All Devlog Posts
Combat Feel vs Procedural Fairness cover

There is a version of procedural dungeon design where fairness is the primary constraint: every room must be winnable, enemy composition must be proportional to player resources, and the generator must never create a situation where the player faces something impossible given their current state. This version of design is popular because it is quantifiable. You can measure threat values, calculate resource gaps, run simulations.

We do not think it produces the best combat experience. This post explains why, and describes the approach we use instead.

The Problem with Pure Fairness

Pure procedural fairness produces encounters that are always possible but never surprising. When every room's difficulty is calibrated to the player's current resources, the player never faces a room that exceeds their prepared capacity. They also never face a room that demands creative problem-solving beyond their current kit. The encounter is solved by applying the tools the game has already told the player are sufficient. The result is technically balanced and experientially flat.

Roguelites that lean toward pure fairness tend to become optimization problems. The player learns which resource configurations are sufficient for which encounter types and then runs to acquire those configurations. There is skill in that, but it is the skill of efficient resource routing rather than the skill of problem-solving under adversity. These are both legitimate game design goals; they produce different player experiences.

We are designing Ruinveil for the second kind of skill: the ability to adapt and solve problems under unexpected conditions. That means we need some encounters to genuinely exceed the player's prepared capacity, at least momentarily. An encounter that is "unfair" in the strict resource-balance sense can be the most interesting encounter in a run if the player has options for dealing with it creatively.

Earned Difficulty Versus Arbitrary Difficulty

The critical distinction is not between fair and unfair encounters. It is between encounters that feel earned and encounters that feel arbitrary.

An encounter feels earned when the player can reconstruct a logic for why it is difficult: the room's spatial constraints created a disadvantage, the enemy composition was particularly well-suited to limiting the player's movement options, the player made resource decisions earlier in the run that left them underpowered for this specific challenge. The difficulty is explainable after the fact, even if it was not foreseeable in advance.

An encounter feels arbitrary when the player can find no logic: the room is simply harder than it should be at this depth, the enemy composition does not cohere, the difficulty spike appears with no contextual setup. The player does not feel challenged; they feel cheated.

The interesting design question is: how do you produce the first kind without producing the second? Especially in a procedural system where you cannot author the narrative context around each encounter.

The Heuristics We Use

We do not have a complete answer to this. We have heuristics that we believe are directionally correct and that have improved over iterations of the grammar.

Difficulty must have a spatial explanation. A room that is harder than the depth-average difficulty must have a spatial reason encoded in the grammar: a constrained entry (narrow corridor approach), a spatial hazard (multiple hazard tiles reducing safe floor area), or an environmental disadvantage (limited sightlines, elevated enemy positions). The difficulty differential is not in the enemy stats alone; it is in the room's conditions. This gives the player a spatial explanation for why the encounter was hard without requiring explicit narration.

Resource logic must be coherent. The grammar's rest-distribution rules exist partly for game balance and partly to ensure that difficult rooms appear in contexts where the player has had recent access to resources. A difficult room after a resource room is a test. The same difficult room after three combat rooms with no resource access is punishing without context. The sequence matters.

Enemy composition must communicate threat before the fight starts. When a player enters a room, the enemy composition should be readable: the player should be able to identify the primary threats and form an initial approach before combat fully engages. This requires that the ecology system not produce compositions where the most dangerous element is obscured or ambiguous. An anchor blocking the entrance is readable; a high-damage harasser concealed in a dark corner is not.

The hardest rooms must be the most memorable. We track which room encounters players describe in detail after playtests. Rooms that were described as "brutal but fair" in our September playtest were consistently rooms that had an unusual spatial feature combined with a coherent enemy ecology. The difficulty was not just in the numbers; it was in the spatial and relational complexity of the encounter. Those rooms are the ones we want the generator to produce.

Where Our Current System Falls Short

We are not yet satisfied with how the heuristics perform at dungeon depth two and beyond. The spatial explanation heuristic works well in smaller rooms where the constraints are tight. In larger rooms, the same constraint can be present but not dominant: a narrow entry corridor does not produce the same difficulty effect in a large chamber that it does in a small one, because the player has room to recover once they are past the entry point.

The grammar does not currently model room size as a modifier of difficulty contribution from spatial constraints. A spatial hazard in a small room and the same hazard in a large room have different implications for the encounter. We calculate threat values per room as if spatial scale were constant, which it is not. This is a known calibration gap.

The other area where we fall short is in communicating difficulty level before the player enters a room. Players currently have no advance signal about a room's difficulty beyond what they can infer from the dungeon map's visual complexity. We have resisted adding explicit difficulty indicators because they reduce the discovery element. But our playtests suggest that players who encounter a very hard room without any preparation context are more likely to attribute the loss to arbitrariness rather than to the room's inherent challenge. We are still thinking about how to handle this without undermining the uncertainty that makes discovery meaningful.

The Design Position We Hold

We believe that procedural fairness, in the strict resource-balance sense, is not the goal. The goal is procedural integrity: encounters that have an internal logic the player can read and engage with. That logic can include moments of genuine adversity that exceed the player's prepared capacity. What it cannot include is moments that lack any readable explanation.

That is an aspiration, not a fully achieved state. We know our generator produces rooms that fall below this standard in ways we are still discovering. The heuristics improve with each iteration of the grammar, but they are heuristics, not guarantees. We expect this to be ongoing design work for as long as we are developing Ruinveil.