Back in 2015 I tackled automata generated caverns for a 7DRL, and in 2018 I wrote up the meander algorithm for rivers. Both made it into compass and both got a little sharper along the way, so I wanted to revisit them with the actual implementations in hand.

Caverns

The cavern generator is Conway’s Game of Life pointed at a terrain problem. It’s almost embarrassing how little code it takes.

  1. Clone the map and randomly seed roughly 55% of it as floor.
  2. Run a single Game of Life pass over the Moore neighborhood (the 8 surrounding cells). An empty cell is born as floor with 5 or more floor neighbors, and an existing floor cell survives with 4 or more.
  3. clipOrphaned keeps only the largest connected blob so you don’t get a dozen disconnected pockets.
  4. Build walls around everything walkable and force the map border to wall so the cave is sealed.

One pass is enough. The birth and survival thresholds are doing the smoothing that I used to iterate several times to get, and the result is the lumpy organic cave you’d expect.

A cave generated from a single Game of Life pass

Meander

The meander is still my favorite because it’s two old ideas glued together: Bresenham’s line and a recursive backtracker maze.

  1. Draw a straight Bresenham line between a start and end terminal. This is the pathing vector.
  2. Chop that line into chunks (9 tiles is the default strength). The bigger the chunk, the more the river winds, and the more often generation fails.
  3. Inside each chunk, carve a recursive-backtracker maze, then pathfind from the chunk’s entry to its exit. Because the maze is random, the route through it wanders.
  4. Stitch the per-chunk routes together into one winding line, mark it as water, and give the adjacent tiles a 30% chance of becoming a sandy bank.

It retries up to five times before giving up, since a maze occasionally fails to offer a clean path. Stack the same two-scale simplex noise over the top that the rivers use and you get a meandering waterway through textured ground.

A river meandering through chunked maze segments

What strikes me revisiting these is how durable the underlying ideas were. The 2015 cellular automata and the 2018 maze-chunked river are doing the same jobs they always did. They just live in a shared library now with proper noise, terminal-point helpers, and orphan cleanup behind them, so I get to compose them instead of rewriting them every time I want a cave with a stream in it.