Free-Field Generation (RE-measured)
A PSZ free field is not a hand-drawn dungeon and it is not the
invented 5×5 sketch the old generator produced. It is a small, gated tree of
reused room tiles whose shape, gates, keys, and enemy tables were
measured out of the original ROM by the
psz-re project. This page is
the normative contract for reproducing one to parity. The reference
observations live in data/re_reference/; the Valley field
(data/field_quests/valley_field.json) is the first built to it.
The room vocabulary
Every stage ships the same room codes; the first letter of the code encodes
the room's door count and shape — this is confirmed by the
game's own name-format table (psz-re FUN_0206D2E4):
sstart ·ggoal ·ndead end — 1 door eachistraight (2 doors, opposite walls) ·lL-corner (2 doors, adjacent walls)tT-junction (3 doors) ·xcross (4 doors)
A field's variant letter is its area role: a/b
are the two explorable areas, e the single-room transition between
them, z the boss arena. So a full field is four sections —
grid a → transition e → grid b → boss z.
The layout is always a tree
The generator MUST satisfy these invariants (measured across four fields, 36 rooms; tested in test_field_layout.gd):
- Room 0 is always the start (shape
s); there is exactly one goal (shapeg), and it is not necessarily last. - The layout is a tree: edges = rooms − 1, no cycles, adjacency symmetric.
- The number of doors on a room equals the door count its shape letter implies.
- Each room stores an absolute grid cell (column A.., row 1..5); the in-game map draws a fixed grid the layout occupies part of.
Rotation is derived, not stored
The game does not store a room's rotation. A port MUST derive it: rotate the
room's door set until it covers the directions the layout needs at that
cell — there is exactly one 90° multiple that fits (psz-re
"Rooms are rotated, and the rotation is derived"). In this engine the
room's authored config portal directions are the door set, and
StageRotation.rotate_dir is a logical label remap (never a
mesh rotation — see Field Stage Lifecycle and issue #218).
Gates and keys
Each outward edge (away from the start) carries a gate value; the way-back edge is always open:
0— open, walk through.4— enemy-defeat gate: locked while the room holds live enemies, opens on clear. The common case.1/2— key gate: needs that many keys.
A field places exactly as many keys as its gates require, on cells
reachable before the gate — so a layout is always solvable without backtracking
to an unreachable room. Valley: a 2-key gate B1 → C1, with both keys
on B2. This balance is a tested invariant.
Enemy population
Spawns are drawn from the measured wave tables, not authored by hand. Each room
code has an allowed list of wave templates with selection weights
(psz-re enemy_room_assignment); each template is a fixed set of enemy
ids (enemy_wave_templates). The start and goal rooms carry no
wave and spawn nothing. The exact per-instance roll (which allowed
template a room draws) is not yet decoded, so the builder rolls one
deterministically against the measured weights — preserving the "mostly ordinary
fights, occasional rare" texture rather than making every instance identical.
psz-re internal enemy names map to this engine's ids: snake→garapython,
vulture→vulkure, lion→helion, lion_rare→blaze_helion,
hyena→grimble, lizard→ghowl, rappy→rappy.
The boss room
The z section is a single arena. Valley's is s01z_na1, and
the assignment table's sole s01z entry is boss_dragon — so
Valley's boss is Reyburn. See
Boss Behavior. Clearing the boss spawns the
return-to-city warp (the existing type: "boss" section handling).
What is deliberately approximated
- The generator algorithm itself is located in the decomp (psz-re
FUN_02082a98; room count =min + rand(max−min)) but not yet ported. Current fields are static fixtures transcribed from observed layouts — parity of output, not of the RNG. (issue #562 Phase 3.) - Enemy spawn positions within a room are not decoded; the builder rings them around room centre.
- Which allowed wave a room rolls is our own weighted pick (see above).