Pure randomness produces garbage. Every roguelike you've loved uses constrained, biased, shaped randomness — and understanding the difference explains why Spelunky feels designed and your first procedural dungeon felt like noise.

Open a blank grid and fill each cell with a coin flip — 50% wall, 50% floor. What you get is static. Unnavigable. Deeply unfun. Yet somehow, Spelunky generates a complete platformer level in milliseconds. Dead Cells produces hand-crafted-feeling rooms thousands of players never see twice. Minecraft conjures mountain ranges that look like they were sculpted. None of them flip coins. They all use different flavours of the same insight: randomness needs constraints, and constraints need to be layered in the right order. Here's what that actually looks like.

1. Why pure random looks wrong

Human brains are pattern-detectors. We read intent into layouts. A cluster of six walls in a row reads as a deliberate obstacle. An open void reads as a designed clearing. When randomness produces these patterns by accident — and it will, constantly — the brain interprets them as authored choices that don't make sense.

There's also a structural problem. Pure random placement doesn't guarantee connectivity. Flip enough cells to wall and you'll wall off sections of your map. Players get stuck. Flip too few and you get open fields with no interesting decisions. The honest truth is that a flat uniform distribution — every cell equally likely to be anything — optimises for nothing a player actually wants.

The fix isn't less randomness. It's randomness applied at the right scale, with the right constraints sitting on top.

2. Noise instead of dice: Perlin and friends

Ken Perlin invented his noise function in 1983 for the film Tron's CGI. The idea is simple: instead of each point on a grid picking its value independently, nearby points are correlated. A Perlin noise field at position (x, y) interpolates smoothly between random gradient vectors placed at grid corners. The result is a surface that rises and falls gradually — exactly what terrain does.

"Perlin noise is a type of gradient noise developed by Ken Perlin in 1983 ... it has a smooth appearance because it is constructed from pseudo-random gradient vectors, which are interpolated."

— Wikipedia, "Perlin noise" (CC BY-SA 4.0)

Minecraft's overworld uses octave Perlin noise: multiple noise layers at different scales summed together. A coarse layer sets the broad continental shape. A medium layer adds hills and valleys. A fine layer adds surface roughness. Tune the amplitude of each octave and you can get anything from rolling plains to jagged mountains — all from one seed number. The terrain isn't random per-block; it's a smooth function that happens to look organic because the gradients were chosen randomly.

Simplex noise (also Perlin, 2001) does the same thing with fewer artefacts in higher dimensions. Most modern engines reach for one of these two instead of raw value noise, which produces a blocky look at the octave boundaries.

3. Structure first: BSP trees and guaranteed rooms

Noise works for terrain. Dungeons need rooms and corridors, and those have hard structural requirements — a room must be traversable, corridors must connect things, critical doors must be reachable. The most common structural tool for this is binary space partitioning (BSP).

BSP splits your map recursively: take the full rectangle, pick a random vertical or horizontal cut somewhere in the middle third (not the edge — that's a constraint), repeat on each half until rectangles are small enough to become rooms, then connect parent rectangles with corridors. The randomness determines where cuts happen and how rooms are shaped. The recursion structure guarantees every room is connected to the tree, which means every room is reachable. No isolated pockets. No dead voids.

This is the core technique behind classic roguelikes going back to 1980s Rogue itself. The randomness produces variety; the tree structure provides the guarantee. It's a clean separation of concerns that holds up at any scale.

4. Weighted tables: rigging the deck on purpose

Once you have a map, you need to fill it. Item drops, enemy placement, trap density — these all use random draws, and flat uniform distributions are almost always wrong here too.

The Binding of Isaac uses a weighted pool system: each item has a base weight, and pools are filtered by room type, floor depth, and run state. A starting floor draw pulls from a pool where weak-but-synergy-enabling items are overrepresented. A late-floor boss draw skews toward high-power actives. The player experiences this as "the game knows what I need" — but it's just weighted probability. The deck is rigged to curve.

Designing weights is iterative. If 30% of your loot pool is one item type, that item shows up roughly every third chest — which quickly feels like the game only has one trick. You can verify the actual frequencies before shipping by simulating a few thousand draws. Our percentage calculator is handy for sanity-checking whether the weights you wrote actually produce the distribution you intended — "item A at weight 5 in a pool of total weight 40" is 12.5%, which may or may not match what you pictured.

5. The critical path: Spelunky's guarantee

Spelunky (2008, Derek Yu) is one of the best-studied examples of procedural generation that feels authored. Each level is divided into a 4×4 grid of room-sized chunks. Before any randomness fires, the generator walks a random path from the top row to the exit room — guaranteeing a navigable route through the level. Only then does it fill non-path rooms with random templates, traps, and enemies.

The player never consciously notices the critical path. They notice that the level is always beatable, always has a visible route, always rewards exploration without punishing curiosity too hard. The designed feeling comes from the guarantee, not the variety. Randomness generates the texture; the path constraint generates the playability.

This layered approach — structure first, then weights, then noise — is the actual algorithm behind every roguelike that doesn't feel like noise. Strip any one layer and the output degrades fast. Strip the structural guarantee and you get dead ends. Strip the weights and the curve flattens. Strip the noise and rooms look copy-pasted.

6. Pacing and density: not just where but when

Procedural difficulty scaling is a second-order problem. It's not enough to generate a beatable level — the level needs to be appropriately hard for where it sits in the run. Most games solve this with floor-indexed parameters: enemy HP scales by a multiplier, spawn counts ramp up a step function at defined depth thresholds, and elite variant weights increase.

The math here is the same as any XP curve or damage calculation — it's just applied to generation parameters instead of character stats. If you're designing a scaling function and want to visualize how fast it ramps, our XP curve calculator will plot any polynomial or exponential formula against depth. The damage calculator is useful for checking that your enemy stat ramp doesn't outpace the player's expected gear curve — the two have to stay in conversation with each other or the procedural content feels broken regardless of how clean the generation math is.

The one-line version

Procedural generation that feels designed isn't about better randomness — it's about using randomness at the right level of abstraction while constraints handle everything that can't be left to chance. Pick your structure first. Bias your weights deliberately. Guarantee your critical paths. Let noise handle the texture. If any of those layers is missing, the player will feel it, even if they can't say why.

If you want to get a feel for what raw flat distributions actually produce versus weighted ones, our dice roller lets you run arbitrary pools side by side — roll 1d20 vs a weighted draw a few dozen times and the clustering difference becomes obvious fast.

← All articles