What it does
Each generator is an object you create once; generation runs straight away, and from then on the level is plain data you
read every frame. Through game.levelgen the seed defaults to the game's own, so a level replays; pass a number or a
string to choose one. The same seed and options always give the same level.
A maze is a grid of cells with a wall on every edge, carved by one of ten algorithms that each give a different
character: the recursive backtracker's long winding corridors, Prim's and Kruskal's bushy branches, Wilson's and
Aldous-Broder's uniform texture, recursive division's roomy halls, and more. braid opens a share of the dead ends into
loops so there is more than one route, rooms carves open spaces, and exits punches openings in the border. The maze
answers canMove, path, distanceField, directionTo, directionToExit and deadEnds, and exports either thick
tiles or thin wall segments for line drawing.
A dungeon places rectangular rooms, joins them into one connected network with extra corridors for loops, and detects the doors. It tags its rooms: the start in the top-left, the boss room furthest from it, junctions where three or more corridors meet, and treasure rooms at the dead ends. A cave fills the grid at random, smooths it by a majority rule into natural caverns, keeps only the largest one, and finds the two floor cells furthest apart for an entrance and an exit.
Features
- Ten maze algorithms —
backtracker,prim,kruskal,wilson,aldous-broder,hunt-and-kill,eller,recursive-division,binary-treeandsidewinder. - Braiding, rooms and exits — loops for multiple routes, open rooms carved in, and border openings by count or by side.
- Maze queries — movement tests, shortest paths, distance fields for many chasers, a hint arrow to the nearest exit and every dead end.
- Dungeons with tagged rooms — start, boss, treasure, junction and normal, with room lookup by tag or by cell.
- Doors — detected where one-tile corridors meet rooms, with their own tile value if you want one.
- Cellular caves — tunable fill, smoothing passes and wall threshold, the largest cavern kept.
- Entrance and exit —
farthestPairfor two far-apart cave cells. - Tile grids —
tiles()with your own wall and floor values, for tilemaps, collision, fog and movement. - Seeded — numbers or strings, so a daily level or a shared code always builds the same map.
Good for
- Roguelikes and dungeon crawlers, with a fresh dungeon each run and a boss room to reach.
- Maze games, with braided loops so there is more than one way round, and a hint arrow to the exit.
- Mining and cave exploration games with organic caverns and an entrance and exit far apart.
- Daily challenges where everyone plays the level from the day's seed.
- First-person or 3D mazes, standing a box on every wall tile.
Make it yours
Mazes take a size, an algorithm, a seed, a braid fraction from 0 to 1, rooms by count or by size range, and exits by count or by side and position. Dungeons take a size, a seed, room attempts, minimum and maximum room sizes, the margin between rooms, extra connections and corridor width. Caves take a size, a seed, the fill probability, the number of smoothing passes, the wall threshold and whether to keep only the largest cavern.
Two very different levels: a sealed perfect maze from the backtracker for a puzzle with one solution; and a loopy 60 by 40 dungeon with three extra connections, the player dropped in the start room and the exit in the boss room.
A quick look
A maze, a dungeon and a cave, each with the queries a game uses:
const maze = game.levelgen.maze({ cols: 20, rows: 15, algorithm: 'prim', braid: 0.3, rooms: 2, exits: 2 });
const grid = maze.tiles(); // 0 floor / 1 wall, 41×31
const dir = maze.directionToExit(c, r); // 0 N · 1 E · 2 S · 3 W · -1 none
const dungeon = game.levelgen.dungeon({ cols: 60, rows: 40, seed: 'level-1', extraConnections: 3 });
const start = dungeon.roomsByTag('start')[0]!, boss = dungeon.roomsByTag('boss')[0]!;
const route = dungeon.path({ col: start.cx, row: start.cy }, { col: boss.cx, row: boss.cy });
const cave = game.levelgen.cave({ cols: 80, rows: 50, fillProb: 0.46, iterations: 4 });
const [entrance, exit] = cave.farthestPair();
Works with
tiles-2d— draws and collides with the tile grid.fogandvisibility-2d— fog of war and line of sight over the walls.grid-move— moves things through the cells.maths— the source of its seed hashing, bundled with it; part of every core bundle.nav— for weighted or diagonal routes beyond the generators' own paths.
Good to know
- Generation runs on the CPU when the object is made: a 200 by 200 cave or a Wilson maze past 60 by 60 takes a moment, so build it on scene entry or behind the loading screen.
- A maze's tile grid is twice its cell size plus one: a 20 by 15 maze is a 41 by 31 map.
- Paths are four-way breadth-first searches; for weighted or diagonal movement use a flow field or your own A*.
- Doors are detected only with one-tile corridors.
- It draws nothing; pair it with
tiles-2d.






