All Devlog Posts
Room Composition Rules cover

The previous post covered the generation pipeline at a high level: how we build a spatial graph, place structural landmarks, fill the critical path, and branch the non-critical rooms. This post goes one level deeper into the grammar itself: the specific categories of rules we use and the reasoning behind each category.

If you are building a procedural system and wondering what "encode design intent as constraints" actually looks like in practice, this is meant to be the concrete version of that answer.

Room Roles: The Vocabulary of the Grammar

Before any rules can fire, the grammar needs a vocabulary. In our system, rooms are not generic spaces. They are assigned roles, and roles carry implicit contracts about what they contain and how they connect. The current role taxonomy has eight categories:

Entry: the run's starting position. Always single-entrance/multi-exit. Low enemy density. Gives the player a moment to orient before committing.

Combat: the primary encounter space. Variable enemy density and composition based on dungeon depth. Most rooms are some flavor of combat.

Transition: the connecting tissue between zones of the dungeon. Corridors, stairs, narrow passages. No enemies; traversal only. Serves as pacing breath between encounters.

Resource: contains a guaranteed pickup (healing item, equipment, consumable). Placed by the grammar according to rest-distribution rules to ensure the player is not starved across an entire zone.

Shrine: a special resource room with a higher-value offering. Placed sparsely. The grammar enforces that shrines are off the critical path and require the player to choose to detour toward them.

Vault: a locked room requiring a key found elsewhere in the dungeon. High-value reward. Optional by design; the grammar treats vault placement as an enrichment pass, not a structural requirement.

Boss approach: the corridor or room sequence immediately before a boss chamber. Subject to the most restrictive rules in the grammar. No resources, reduced exit count, elevation changes to reinforce the sense of descent.

Boss: the boss chamber. Always single-entrance. High spatial footprint. The grammar reserves a specific region of the dungeon's spatial extent for boss placement and builds toward it.

Ordering Rules: What Can Follow What

The most important category of rules governs sequence. In Ruinveil's grammar, rooms have permitted predecessors and successors based on their roles and the dungeon's current progression state.

Some of these rules are hard constraints: a boss approach room can only follow a combat room that is at least two rooms from the last resource room. No exceptions. A shrine can never connect directly to a boss approach. A vault requires that its corresponding key room be reachable from the same entry branch, within a maximum traversal distance.

Some rules are soft constraints: preferences that the generator will satisfy if possible but can violate if no valid placement exists under all hard constraints. For example, we prefer that two consecutive combat rooms have different encounter densities. If the search space has no valid placement satisfying that preference at a given step, the generator places the best available option and logs the constraint relaxation. We review those logs periodically to identify situations where the grammar is producing unwanted sequences under backpressure.

Spatial Distribution Rules

Beyond sequence, the grammar constrains spatial distribution: where in the dungeon's physical grid certain room types can appear. We measure distribution along two axes: depth (distance from entry, measured in traversal steps) and quadrant (the dungeon's spatial canvas divided into a 2x2 quadrant grid).

Resource rooms are distributed by a rest interval rule: the maximum number of consecutive combat rooms before a resource or shrine must appear. The current value is four. That means at any point on the critical path, there is always a resource within four rooms of the player's position. This prevents resource deserts on long paths while avoiding the opposite problem of resource rooms being so dense that the player never feels pressured.

Vault rooms are quadrant-exclusive: no more than one vault per quadrant. The purpose is navigational clarity. If the player finds one vault in the southwest quadrant and decides to search for others, they know to look in the other three quadrants. The dungeon gives the player information through its structure rather than through explicit UI markers.

The boss room depth rule is one we arrived at after playtesting revealed a problem with our early generation: occasionally the generator would place the boss relatively early in the depth sequence, producing a dungeon that felt short and anticlimactic. The current rule sets a minimum depth for boss placement at 70% of the dungeon's maximum depth. The boss will always be in the deeper portion of the dungeon, never in the first third.

Content Composition Rules

The grammar's third category governs not just what rooms appear and where, but what they contain. This is where the level grammar hands off to the enemy ecology system, but the handoff is not a clean break. The grammar specifies a content specification for each room based on its role and depth, and the ecology system assembles from that specification.

A combat room at depth 1 has a content specification of: low total threat value, no elite-tier enemies, maximum three enemy instances. A combat room at depth 4 has: high total threat value, one elite permitted, up to six instances. The grammar calculates these specifications as a function of depth, dungeon length, and the current run's difficulty factor.

The most complex content rule governs boss encounters. The grammar does not specify the boss encounter directly; it specifies a threat budget, an encounter space footprint, and a set of environmental hazard slots. The ecology system assembles the boss within those constraints, drawing from a pool of boss archetypes that have been parameterized to fit the allocated threat budget. Different runs will encounter different boss configurations even for the same boss archetype because the trait composition system applies to boss AI just as it does to standard enemies.

The Edge Cases That Have Cost Us the Most Time

Two categories of edge cases have required the most iteration to handle well.

The first is backtracking under compound constraint pressure. When the generator is building the critical path and hits a point where the next room must satisfy several high-priority constraints simultaneously, the search space can narrow to zero valid placements. The generator backtracks to the last unconstrained choice point and tries again. In most cases this resolves in one or two backtrack steps. In rare cases with hostile seed values, we have observed backtrack chains that span twenty or more steps before resolving. Those cases produce valid dungeons but with unusual structural patterns that feel off to experienced players. We are working on early detection of constraint pressure during generation to reroute before a deep backtrack becomes necessary.

The second is symmetry artifacts. Because the grammar uses quadrant-based distribution rules, dungeons occasionally exhibit near-symmetrical layouts where the player can roughly predict where rooms will be based on what they have already seen in the opposite quadrant. This breaks the sense of discovery. Our current mitigation is a post-generation symmetry check that measures structural similarity between quadrant pairs and rejects layouts that exceed a similarity threshold. The threshold is calibrated against playtest feedback, but getting it right is more art than science.

Writing Rules Versus Playing Them

The honest difficulty of this approach is the gap between writing a rule and understanding how it will feel to play. Priya and I will write a rule that looks obviously correct from a design principles standpoint, implement it, run five hundred generated dungeons, and discover that it produces a spatial consequence we did not anticipate when thinking about it abstractly. The rule about minimum boss depth seemed obviously right and did not cause problems. The rule about vault quadrant exclusivity seemed obviously right and turned out to produce confusing navigational implications we had to think carefully about before we understood them.

The grammar gets better with each iteration, but we have accepted that it will never be fully specified from first principles. Some rules will always need to emerge from observation of generated output rather than from design reasoning. That is the nature of the system, not a flaw in the approach.