An alphabet of 17 tiles
Before a dungeon can be generated, it has to be spelled. The whole world is built from just seventeen square tiles and one rule about how their edges may touch. Get the alphabet right and the walls take care of themselves.
One cell, sixteen ways to wear a wall
The dungeon lives on a square grid. Every cell is either solid rock — we call it
void — or an open floor. That sounds like two tiles, but a floor cell
also needs to know which of its four edges carry a wall. With four edges
that can each independently be wall-or-open, a floor has 2⁴ = 16 variants.
Add the void tile and we get 17 tiles in total.
We encode the four walls as a 4-bit marching-squares mask — bit 0 = North, 1 = East, 2 = South, 3 = West. A set bit means “this edge borders the void, so draw a wall here.” Click the edges below to toggle walls and watch the mask change.
Sockets: edges that have to agree
Here is the trick that makes everything else work. Each edge of a tile exposes a little symbol — a socket — describing what it offers a neighbour:
- F (floor) — open floor continues across this edge; you can walk through.
- W (wall) — this floor cell has a wall facing out across this edge.
- E (empty) — void faces this edge.
Two tiles may sit next to each other only if their touching sockets are compatible:
F ↔ F two floors share an open, walkable seam
W ↔ E a wall always backs onto void
E ↔ E void meets void
(anything else is forbidden)
Drag the two tiles’ walls below and watch the shared seam light up green when it’s legal and red when it isn’t.
Why the walls are never wrong
Look at what the socket rule forces. A floor edge facing void must show W,
because the only thing compatible with the void’s E is a wall — F↔E
is illegal. And two adjacent floors must leave that seam open, because F is only
compatible with F. So:
Paint some floor below (click and drag). The walls are derived automatically from the
marching-squares mask of every floor cell — that’s the same deriveMasks()
the real generator runs.
Weights: tuning the texture
All 17 tiles are legal, but they aren’t equally likely. Each tile gets a weight —
a relative frequency the solver biases toward. Three knobs shape them:
voidWeight (how much rock), openWeight (how much open floor), and
wallFactor — a per-wall multiplier below 1 that makes heavily-walled
tiles progressively rarer, so rooms come out open rather than cramped and boxy.
Drag the knobs and watch the relative weight of each of the 16 floor tiles (grouped by how many walls they carry). This is exactly the table fed to the Wave Function Collapse solver in the next chapter.
That’s the entire alphabet: 17 tiles, one compatibility rule, a handful of weights. Next we hand this to a solver that fills a whole grid with tiles such that every seam is legal — Wave Function Collapse.