Procedural dungeon
Building each dungeon level at random from rules, such as rooms placed on the map and joined by corridors.
On this page
A procedural dungeon is generated rather than drawn, so every game has new levels. Rogue 5.4 cuts the screen into a 3 × 3 grid of boxes and joins neighbors1,2. NetHack 3.6.7 drops rooms into free rectangles and joins them from left to right3, and keeps one level built in Rogue’s grid style4.
- Room gridRogue (1980). Nine boxes in a 3 × 3 grid, up to 3 of them bare junctions, joined only between neighbors.1,2NetHack (1987). One level in Rogue's 3 × 3 style, each cell an intersection 1 time in 5.4
- Free rectanglesNetHack (1987). Up to 40 rooms in free rectangles, joined from left to right, plus extra corridors that can dead-end.3
Games
| Game | Year | How | Note |
|---|---|---|---|
| Rogue | 1980 | Room grid | nine boxes in a 3 × 3 grid, up to 3 of them bare junctions, joined only between neighbors |
| NetHack | 1987 | Room grid | one level in Rogue's 3 × 3 style, each cell an intersection 1 time in 5 |
| NetHack | 1987 | Free rectangles | up to 40 rooms in free rectangles, joined from left to right, plus extra corridors that can dead-end |
Every claim about this mechanic, by game (4)
References
- ^ abRogue 5.4 lays out each level as nine boxes in a 3 by 3 grid over the 80 by 24 screen. It first marks 0 to 3 boxes, picked at random and possibly the same twice, as gone: a gone box gets a point for corridors to meet but no room. Each other box gets a room; it is dark when a roll of 0 to 9 is below the depth less 1, and a dark room is a maze at a chance of 1 in 15.CodeRogue 5.4.4 source
How we know
22#define MAXROOMS 9rogue.h line 22 at cf9bd26 · upstream ↗ 31#define NUMCOLS 80rogue.h lines 30–31 at cf9bd26 · upstream ↗ 41 bsze.x = NUMCOLS / 3;rooms.c lines 41–42 at cf9bd26 · upstream ↗ 57 rooms[rnd_room()].r_flags |= ISGONE;rooms.c lines 55–57 at cf9bd26 · upstream ↗ Place a gone room.
rooms.c#L61-L82 · upstream ↗ 86 if (rnd(10) < level - 1)rooms.c lines 86–91 at cf9bd26 · upstream ↗ if not gone pick door pos
passages.c#L169-L183 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abRogue 5.4 joins the boxes with corridors only between grid neighbors: from a random box it grows a tree, each step joining a random neighbor not yet joined, until all nine are connected, and then makes 0 to 4 tries at an extra corridor between a random box and a neighbor it isn't joined to.CodeRogue 5.4.4 source
How we know
38 { { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0 },passages.c lines 33–43 at cf9bd26 · upstream ↗ 69 if (r1->conn[i] && !rdes[i].ingraph && rnd(++j) == 0)passages.c lines 55–95 at cf9bd26 · upstream ↗ 101 for (roomcount = rnd(5); roomcount > 0; roomcount--)passages.c lines 97–115 at cf9bd26 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
- ^ abAn ordinary NetHack 3.6.7 level places rooms, one of which may be a vault, in free rectangles until none is left, a room fails to fit, or it has 40. It sorts them by left edge, and joins each to the next, stopping early at a chance of 1 in 50 per join. It then joins each room to the one two along when they aren't yet connected, then any pair still unconnected. With 3 or more rooms it makes 4 to (room count + 3) attempts at another corridor; an attempt gives up before digging when the square outside its door is already open, and stops short, leaving a dead end, at a chance of 1 in 35 per step.CodeNetHack 3.6.7 sourcerevised
How we know
229 while (nroom < MAXNROFROOMS && rnd_rect()) {src/mklev.c lines 227–239 at ed600d9 · upstream ↗ 330#define MAXNROFROOMS 40 /* max number of rooms per level */include/global.h line 330 at ed600d9 · upstream ↗ 62 if (x->lx < y->lx)src/mklev.c lines 62–64 at ed600d9 · upstream ↗ 704 sort_rooms();src/mklev.c lines 700–704 at ed600d9 · upstream ↗ 341 for (i = rn2(nroom) + 4; i; i--) {src/mklev.c lines 319–348 at ed600d9 · upstream ↗ 294 if (nxcor && levl[xx + dx][yy + dy].typ)src/mklev.c lines 294–295 at ed600d9 · upstream ↗ 2248 if (cct++ > 500 || (nxcor && !rn2(35)))src/sp_lev.c line 2248 at ed600d9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Revised after a check by a second AI model, 2026-10-21.
- ^ abNetHack 3.6.7's main dungeon, the Dungeons of Doom, holds one level built in Rogue's style. Its code's comment says “Rogue levels are structured 3 by 3, with each section containing a room or an intersection”, and each of the nine cells is an intersection at a chance of 1 in 5, so long as at least one room is made.CodeNetHack 3.6.7 source
How we know
20LEVEL: "rogue" "R" @ (15, 4)dat/dungeon.def lines 17–21 at ed600d9 · upstream ↗ Rogue levels are structured 3 by 3, with each section containing
src/extralev.c#L209-L213 · upstream ↗ 233 if (!rn2(5) && (nroom || (x < 2 && y < 2))) {src/extralev.c lines 228–243 at ed600d9 · upstream ↗ 700 makeroguerooms();src/mklev.c lines 698–701 at ed600d9 · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-21.
Checked by a second AI model, 2026-10-21.
Sources
Code
- Toy, Michael, Ken Arnold, and Glenn Wichman. 2016. “Rogue 5.4.4 source code.” Commit cf9bd26. Davidslv/rogue @ cf9bd26 · licence, all uses
- NetHack DevTeam. 2023. “NetHack 3.6.7 source code.” Commit ed600d9. NetHack/NetHack @ ed600d9 · licence, all uses