procedural-generation
Implements deterministic generation algorithms using seeds for consistent, reproducible results.
Install
mkdir -p .claude/skills/procedural-generation && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12007" && unzip -o skill.zip -d .claude/skills/procedural-generation && rm skill.zipInstalls to .claude/skills/procedural-generation
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Procedural generation patterns — Perlin/Simplex noise, BSP dungeon generation, random walk, loot tables with weighted random, wave function collapse basics, seed-based reproducibility.Key capabilities
- →Generate terrain using Perlin noise
- →Generate dungeons using BSP
- →Generate caves using random walk
- →Generate loot using weighted tables
- →Ensure seed-based reproducibility for generation algorithms
How it works
This skill provides patterns for procedural content generation, such as using Perlin noise for height maps or BSP for dungeons. It emphasizes seed-based reproducibility by using `System.Random` and deriving sub-seeds.
Inputs & outputs
When to use procedural-generation
- →Generate random dungeon layouts
- →Create procedural terrain maps
- →Implement balanced, seeded loot tables
About this skill
Procedural Generation Patterns
Patterns for generating content at runtime: terrain with noise, dungeons with BSP, caves with random walk, loot with weighted tables, and tile layouts with wave function collapse. All patterns support seed-based reproducibility.
Seed-Based Reproducibility
Every generation algorithm should accept a seed. Given the same seed, the output is identical. This enables shareable worlds, bug reproduction, and daily challenge modes.
Critical rule: Use System.Random (not UnityEngine.Random) for deterministic generation. UnityEngine.Random is a global singleton; any other code calling it between your generation steps will change the sequence.
public class SeededRandom
{
private System.Random _rng;
public int Seed { get; }
public SeededRandom(int seed)
{
Seed = seed;
_rng = new System.Random(seed);
}
public int Next(int min, int max) => _rng.Next(min, max);
public float NextFloat() => (float)_rng.NextDouble();
public float Range(float min, float max) => min + (max - min) * NextFloat();
public bool Chance(float probability) => NextFloat() < probability;
/// <summary>Shuffle a list in place using Fisher-Yates.</summary>
public void Shuffle<T>(IList<T> list)
{
for (int i = list.Count - 1; i > 0; i--)
{
int j = _rng.Next(0, i + 1);
(list[i], list[j]) = (list[j], list[i]);
}
}
}
For world generation, derive sub-seeds from the master seed so different systems (terrain, dungeons, loot) do not interfere:
int masterSeed = 12345;
var terrainRng = new SeededRandom(masterSeed);
var dungeonRng = new SeededRandom(masterSeed + 1);
var lootRng = new SeededRandom(masterSeed + 2);
Noise-Based Terrain Generation
Use Perlin noise to generate height maps for terrain, biome maps, moisture maps, and other continuous fields.
Basic Height Map
using UnityEngine;
public static class NoiseGenerator
{
/// <summary>
/// Generate a 2D noise map. Values range from 0 to 1.
/// </summary>
public static float[,] GenerateNoiseMap(
int width, int height, int seed,
float scale, int octaves, float persistence, float lacunarity,
Vector2 offset)
{
var map = new float[width, height];
// Use seed to generate random octave offsets
var rng = new System.Random(seed);
var octaveOffsets = new Vector2[octaves];
for (int i = 0; i < octaves; i++)
{
float ox = rng.Next(-100000, 100000) + offset.x;
float oy = rng.Next(-100000, 100000) + offset.y;
octaveOffsets[i] = new Vector2(ox, oy);
}
if (scale <= 0f) scale = 0.001f;
float maxNoise = float.MinValue;
float minNoise = float.MaxValue;
float halfW = width / 2f;
float halfH = height / 2f;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float amplitude = 1f;
float frequency = 1f;
float noiseHeight = 0f;
for (int o = 0; o < octaves; o++)
{
float sampleX = (x - halfW + octaveOffsets[o].x) / scale * frequency;
float sampleY = (y - halfH + octaveOffsets[o].y) / scale * frequency;
// Mathf.PerlinNoise returns 0-1; remap to -1 to 1
float perlin = Mathf.PerlinNoise(sampleX, sampleY) * 2f - 1f;
noiseHeight += perlin * amplitude;
amplitude *= persistence; // Each octave contributes less
frequency *= lacunarity; // Each octave has finer detail
}
map[x, y] = noiseHeight;
if (noiseHeight > maxNoise) maxNoise = noiseHeight;
if (noiseHeight < minNoise) minNoise = noiseHeight;
}
}
// Normalize to 0-1
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
map[x, y] = Mathf.InverseLerp(minNoise, maxNoise, map[x, y]);
return map;
}
}
Parameter guide:
| Parameter | Effect | Typical Value |
|---|---|---|
| scale | Zoom level (higher = smoother) | 20-100 |
| octaves | Layers of detail | 4-6 |
| persistence | Amplitude decay per octave | 0.4-0.6 |
| lacunarity | Frequency increase per octave | 1.8-2.2 |
Applying Noise to a Tilemap
using UnityEngine;
using UnityEngine.Tilemaps;
public class TerrainGenerator : MonoBehaviour
{
[SerializeField] private Tilemap tilemap;
[SerializeField] private TileBase waterTile;
[SerializeField] private TileBase sandTile;
[SerializeField] private TileBase grassTile;
[SerializeField] private TileBase stoneTile;
[SerializeField] private TileBase snowTile;
[Header("Generation Settings")]
[SerializeField] private int width = 100;
[SerializeField] private int height = 100;
[SerializeField] private int seed = 42;
[SerializeField] private float scale = 30f;
[SerializeField] private int octaves = 4;
[SerializeField] private float persistence = 0.5f;
[SerializeField] private float lacunarity = 2f;
[Header("Height Thresholds")]
[SerializeField] private float waterLevel = 0.3f;
[SerializeField] private float sandLevel = 0.4f;
[SerializeField] private float grassLevel = 0.7f;
[SerializeField] private float stoneLevel = 0.85f;
public void Generate()
{
tilemap.ClearAllTiles();
var noiseMap = NoiseGenerator.GenerateNoiseMap(
width, height, seed, scale, octaves, persistence, lacunarity, Vector2.zero);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
float value = noiseMap[x, y];
TileBase tile = GetTileForHeight(value);
tilemap.SetTile(new Vector3Int(x - width / 2, y - height / 2, 0), tile);
}
}
}
private TileBase GetTileForHeight(float height)
{
if (height < waterLevel) return waterTile;
if (height < sandLevel) return sandTile;
if (height < grassLevel) return grassTile;
if (height < stoneLevel) return stoneTile;
return snowTile;
}
}
BSP Dungeon Generation
Binary Space Partition creates rectangular rooms connected by corridors. It produces clean, grid-aligned dungeons suitable for roguelikes and RPGs.
Algorithm Overview
- Start with a large rectangle (the entire dungeon area).
- Recursively split it in half (horizontally or vertically) until pieces reach minimum size.
- Place a room inside each leaf partition (with random padding).
- Connect sibling rooms with corridors.
Implementation
using System.Collections.Generic;
using UnityEngine;
public class BSPDungeon
{
public class BSPNode
{
public RectInt Area;
public BSPNode Left;
public BSPNode Right;
public RectInt? Room;
public bool IsLeaf => Left == null && Right == null;
}
private int _minPartitionSize;
private int _minRoomSize;
private int _roomPadding;
private SeededRandom _rng;
private List<RectInt> _rooms = new();
private HashSet<Vector2Int> _corridors = new();
public IReadOnlyList<RectInt> Rooms => _rooms;
public IReadOnlyCollection<Vector2Int> Corridors => _corridors;
public BSPDungeon(int minPartitionSize = 10, int minRoomSize = 4, int roomPadding = 2)
{
_minPartitionSize = minPartitionSize;
_minRoomSize = minRoomSize;
_roomPadding = roomPadding;
}
public int[,] Generate(int width, int height, int seed)
{
_rng = new SeededRandom(seed);
_rooms.Clear();
_corridors.Clear();
// 0 = wall, 1 = floor
var grid = new int[width, height];
// Build BSP tree
var root = new BSPNode { Area = new RectInt(0, 0, width, height) };
Split(root);
// Place rooms in leaves
PlaceRooms(root);
// Connect rooms
ConnectRooms(root);
// Write rooms to grid
foreach (var room in _rooms)
{
for (int x = room.x; x < room.x + room.width; x++)
for (int y = room.y; y < room.y + room.height; y++)
grid[x, y] = 1;
}
// Write corridors to grid
foreach (var pos in _corridors)
{
if (pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height)
grid[pos.x, pos.y] = 1;
}
return grid;
}
private void Split(BSPNode node)
{
// Stop if too small to split
if (node.Area.width < _minPartitionSize * 2 &&
node.Area.height < _minPartitionSize * 2)
return;
// Choose split direction
bool splitHorizontal;
if (node.Area.width < _minPartitionSize * 2)
splitHorizontal = true;
else if (node.Area.height < _minPartitionSize * 2)
splitHorizontal = false;
else
splitHorizontal = _rng.Chance(0.5f);
if (splitHorizontal)
{
int splitY = _rng.Next(
node.Area.y + _minPartitionSize,
node.Area.y + node.Area.height - _minPartitionSize);
node.Left = new BSPNode
{
Area = new RectInt(node.Area.x, node.Area.y,
node.Area.width, splitY - node.Area.y)
};
node.Right = new BSPNode
{
Area = new RectInt(node.Area.x, splitY,
node.Area.width, node.Area.y + node.Area.height - splitY)
};
}
else
{
i
---
*Content truncated.*
When not to use it
- →When `System.Random` is not used for deterministic generation
- →When generation logic is not separated from rendering
- →When complex generation is not run in a coroutine or background thread
Limitations
- →Requires `System.Random` for deterministic generation
- →Generation logic should be separated from rendering
- →Complex generation may require coroutines or background threads
How it compares
This skill offers structured patterns for procedural generation with a focus on deterministic reproducibility, which allows for shareable worlds and bug reproduction, unlike ad-hoc random generation.
Compared to similar skills
procedural-generation side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| procedural-generation (this skill) | 0 | 4mo | No flags | Advanced |
| mlir-development | 1 | 6mo | Review | Advanced |
| compiler-development | 1 | 6mo | No flags | Advanced |
| add-cuda-kernel | 1 | 3mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
mlir-development
gmh5225
Expertise in MLIR (Multi-Level Intermediate Representation) and CIR (Clang IR) development for domain-specific compilation and high-level optimizations. Use this skill when building ML compilers, domain-specific languages, or working with multi-level compilation pipelines.
compiler-development
gmh5225
Expertise in compiler development using LLVM infrastructure including frontend design, IR generation, optimization passes, and code generation. Use this skill when building custom programming languages, implementing DSL compilers, or working on compiler internals.
add-cuda-kernel
flashinfer-ai
Step-by-step tutorial for adding new CUDA kernels to FlashInfer
benchmark-kernel
flashinfer-ai
Guide for benchmarking FlashInfer kernels with CUPTI timing
debug-quantized-kernel-accuracy
tensormux
2. **Isolate the quantization step responsible.** The quantization pipeline is: ``` fp32 input → quantize → int8 input int8 GEMM (or other op) with int32 accumulation int32 accumulation → dequantize → fp32/fp16 output ``` Test each boundary: - **Quant-dequant roundtrip**: quantiz
tritonify
IsNoobgrammer
>-