You do not pick a path through a fog. The map is generated whole the moment the act starts, under rules the game ships with — so the question "which path do I take" has two halves: what the generator guarantees before you see it, and what each node type actually pays.
Node budget math
Both games draw maps on a grid: the Exordium and everything after use a 15-row map, 7 nodes wide, at map density 6. The final act collapses to a fixed linear column instead — more on that below.
Room counts are not rolled freely; they are percentages of one number:
availableRoomCount, the nodes that have edges once the second-to-last row is
excluded (room_type_counts.source). Every act uses the same chances
(per_act_chances):
| Room type | Chance | Count formula |
|---|---|---|
| Shop | 0.05 | round(availableRoomCount * shopRoomChance) |
| Rest | 0.12 | same shape |
| Treasure | 0.0 | — |
| Event (?) | 0.22 | same shape |
| Elite | 0.08 | × 1.6 at Ascension 1+, × 2.5 under Elite Swarm |
| Monster | remainder | whatever the other counts leave |
That treasure row is not a typo. treasureRoomChance is 0.0 in all acts;
normal-run chests come only from ? rooms converting into treasure and one
fixed assignment on row 8 (treasure_room_note). The map never budgets a
treasure room — you find them inside question marks.
Why row 0 differs
Row 0 ignores the parent/sibling placement rules entirely: "nodes at y == 0
accept any room regardless of parent/sibling rules" and are force-assigned as
monster rooms first anyway (distribution_rules.row0_exception). That is why
every run opens with the same texture — a wide fan of fights — no matter how
the rest of the map branches.
The elite-weight ramp
Elite rooms cost the same everywhere, but which elite you meet is weighted. Act 1 rolls its three elites evenly — Gremlin Nob, Lagavulin and 3 Sentries all sit at weight 1.0. The Beyond breaks even: Giant Head, Nemesis and Reptomancer each carry weight 2.0 — still uniform among themselves.
The real asymmetry hides in the strong fight pools, not the elite pools.
In the Exordium, hard openers are discounted: Gremlin Gang and Lots of Slimes
sit at weight 1.0 while Blue Slaver,
Large Slime, 3 Louse and
2 Fungi Beasts carry 2.0, and the mid-tier pairs (Exordium Thugs, Exordium
Wildlife) take
1.5 (acts.Exordium.strong). The City runs weights up to 6.0 on its heaviest
fights (acts.TheCity.strong). So an elite path in act 1 is a coin flip
between three known fights — check what each demands before you commit:
the monster index lists them all.
? rooms decay into fights
A ? room is not a coin flip — it is a pot that boils. On entry the game rolls with these base chances:
| Result | Base |
|---|---|
| Event | remainder (0.55 at reset) |
| Monster | 0.10 |
| Shop | 0.03 |
| Treasure | 0.02 |
After each roll, the type you hit resets to base and everything else grows
by its own base amount (ramp_after_miss): miss a monster and MONSTER goes
0.10 → 0.20 → 0.30…, miss a shop and SHOP climbs 0.03 at a time. Two catches
the extraction records: the elite chance resets to 0.0 at every act
transition even though its initial constant reads 0.1 (reset note), and a
shop result is forced to 0 while you stand in a shop row. Hold Tiny Chest and
every fourth ? forces treasure instead.
StS2 keeps the same boiling-pot design with different numbers. Its
unknownMapPointOdds start at Monster 0.1, Treasure 0.02, Shop 0.03, Event
0.85 — and Elite is set to −1.0: negative odds are never rolled and never
grow, so co-op-era Spire 2 maps have no elite surprises hiding in unknowns.
Odds reset between acts. See the StS2 atlas for where
unknowns sit on those maps.
Shop/rest placement rules
Rest sites are the second-largest budget at 0.12, shops the smallest at 0.05
— both computed against availableRoomCount and rounded
(room_type_counts.formulas). Because the formulas round, small acts can
shift a count by one; because the chances are identical across acts
(initializeLevelSpecificChances() is identical for Exordium, TheCity, TheBeyond and TheEnding), a longer path to the boss means proportionally
more camps and shops, never different rates. Planning around "act 3 has fewer
camps" is planning around nothing — it has the same rate, only fewer eligible
nodes if your route skips side branches.
Key and act-4 exceptions
Two overrides break the pattern. Act 4 replaces generation outright: a fixed
linear column at x=3 — Rest, Shop, Elite, Boss, victory — with hardcoded
edges and a still-seeded but layout-deterministic mapRng
(act4_map.layout). And when the emerald key is available and unclaimed, the
game picks one elite node uniformly at random and buffs it: Strength +(actNum+1)
on every monster, or +25% max HP, or Metallicize (actNum×2+2), or Regenerate
(1+actNum×2), chosen by a 4-way roll (emerald_key_elite.buff_roll).
Per-act independence
Each act's map comes off its own seed offset — seed+1, seed+200, seed+600, seed+1200 for acts 1–4 — so knowing act 1's layout tells you nothing about act 2's, and neither game lets you precompute the climb from the seed screen alone. What the seed does decide is a bigger story: see how the acts themselves are built.