npx skills add ...
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill procedural-gen
Generate game content procedurally — seeded deterministic RNG, value/Perlin/ Simplex noise for terrain and heightmaps, grid dungeon generation (rooms + corridors, BSP, random walk), and weighted loot/drop tables. Engine-neutral algorithms. Use when the user mentions procedural generation, perlin/simplex noise, random seed, dungeon generator, heightmap/terrain, or loot tables.
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill procedural-gen
Generate levels, terrain, and loot from compact rules and a seed. The throughline
of good procgen is determinism: a single seed reproduces the same world, so
bugs are repeatable and players can share seeds. This skill owns the core
algorithms — noise, seeded RNG, dungeon layout, weighted tables; genres like
roguelike and survival-crafting consume it.
When not to use: for the engine's tile API to paint the result, use
godot-tilemap or unity-tilemap-2d. For routing AI through the generated map,
use game-ai. For carefully hand-paced levels, use level-design — procgen and
authored design are complementary, not interchangeable.
int[][] or a dict; a separate pass draws it.Engine equivalents: Godot var rng = RandomNumberGenerator.new(); rng.seed = s;
Unity var rng = new System.Random(seed) (or UnityEngine.Random.InitState).
Store the seed in the save file so a world can be regenerated.
Use a real noise library (FastNoiseLite, opensimplex,
Unity.Mathematics.noise, or Mathf.PerlinNoise) — do not implement gradient
noise yourself. Seed elevation and moisture with different seeds so a
biome lookup over both fields isn't perfectly correlated. Full biome lookup and
island shaping are in references/noise.md.
Weights need not sum to 100 — they are relative. To prevent bad streaks, use a
"pity"/bag system (see references/dungeon-generation.md notes on distributions).
The complete generator (BSP partitioning, L-corridors, reachability check, and
random-walk caves) is in references/dungeon-generation.md.
0..1; divide by the summed amplitude (and beware library output ranges — some
return -1..1, some 0..1).references/noise.md — octaves/lacunarity/gain, redistribution, island
shaping, two-axis biome lookup, blue-noise object scatter.references/dungeon-generation.md — BSP, rooms+corridors, random-walk caves,
cellular-automata smoothing, connectivity validation, distribution/pity tables.godot-tilemap, unity-tilemap-2d — paint the generated grid into the engine.game-ai — pathfinding over the generated graph.level-design — pacing and hand-authored structure that procgen complements.roguelike, survival-crafting — genres that compose this skill.# Sum several octaves: each higher octave has higher frequency, lower amplitude.
def fbm(noise, x, y, octaves=5, lacunarity=2.0, gain=0.5):
total, amp, freq, norm = 0.0, 1.0, 1.0, 0.0
for _ in range(octaves):
total += amp * noise(x * freq, y * freq) # noise() returns ~0..1
norm += amp # track total amplitude
amp *= gain # each octave contributes less
freq *= lacunarity # ...at a higher frequency
return total / norm # normalize back into 0..1
# Redistribute to carve flat valleys / sharpen peaks: higher exp -> more lowland.
elevation = pow(fbm(noise, nx, ny), 2.2)# Roll proportional to weight: common drops far more often than legendary.
def weighted_pick(rng, table): # table: list of (item, weight)
total = sum(w for _, w in table)
roll = rng.uniform(0, total) # a point on the cumulative line
upto = 0.0
for item, w in table:
upto += w
if roll < upto: # first bucket the roll falls into
return item
return table[-1][0] # float-safety fallback
loot = weighted_pick(rng, [("common", 70), ("rare", 25), ("legendary", 5)])# 1. Place non-overlapping rooms; 2. connect them; 3. carve into the grid.
rooms = []
for _ in range(attempts):
r = Rect(rng.randint(1, W-w-1), rng.randint(1, H-h-1), w, h)
if not any(r.intersects(o.expand(1)) for o in rooms): # keep a 1-tile gap
rooms.append(r)
for a, b in zip(rooms, rooms[1:]): # connect each room to the next
carve_l_corridor(grid, a.center, b.center, rng) # horizontal then vertical