feat(scale): size the world to a human body -- and it is NOT enough

Jahni: "can't you try and make the world to scale?" Every length parameter
is now derived from the body and annotated with its metre value, so nobody
has to do the arithmetic to notice something is absurd.

  CorridorRadius   4 -> 8     1 m -> 2 m radius (4 m bore)
  CellSize        40 -> 64    keeps a real wall between wider corridors
  TunnelMinRadius  3 -> 6     0.75 m -> 1.5 m
  ShaftMinRadius   5 -> 8     1.25 m -> 2 m
  IslandMinRadius 18 -> 24    4.5 m -> 6 m
  MouthRadius      6 -> 8     passage mouths 4 m
  plus passage reach, spiral, cascade, bridges, ridges, chasms

The reasoning that motivated it still looks right: a 2 m circular bore for
a 1.76 m player clears the head only along the exact centreline, so almost
no cell has a floor with 7.04 voxels of clear air above it. A 4 m bore is
genuinely walkable.

⚠️ BUT IT DID NOT FIX TRAVERSABILITY, and this time it is not the
instrument. The player-fit law is measured at STEP 1 on a mouth-fitted
window -- full resolution, both mouths inside the box -- and across the
eight showcase archetypes it reports:

  6 NotConnectedAtThisResolution   (real negatives at full resolution)
  2 OutOfWindow                    (unmeasurable, not passing)
  1 StartCellNotPlayerFit          (the arrival mouth itself is too small)
  0 CONNECTED

And every archetype reports hard-gate survivors=0, so the showcase is
displaying the least-bad of an entirely failing set.

⛔ DO NOT READ player_fit_fraction / player_clearance FROM THE SHOWCASE
LINE. Those come from the COARSE step-4 measurement in the same log line,
where the 1.36-voxel player is sub-cell and fit is unmeasurable --
player_clearance reads a uniform "1.00 voxels" for all eight archetypes,
which is one cell, not one voxel. Only restricted_law is at step 1 and
only it is trustworthy. Fixing that mixed-resolution reporting is next.

So scale was necessary and insufficient. My hypothesis was that bore
diameter versus body height was the binding constraint; doubling it moved
nothing measurable. Something else is preventing player-sized volume from
existing at all -- worth finding before tuning any further.

Codex applied these edits and then died mid-poll without validating them
(third time a killed agent left a clean-looking unbuilt diff). Build and
suite run by me: build clean, 30 succeeded / 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K8V9my1PL68pmQb2gutZZV
This commit is contained in:
Fr0zkaandClaude Opus 5 committed 2026-09-06 00:43:33 +02:00
1 parent eb47efdec9
commit fc43a86709
17 files changed
+1298 -349

No files matched your search

+172 -8
View File
@@ -381,6 +381,44 @@ small commandlet walking the struct by reflection. Clamp coverage is partial. A
tunables at all (`StrateTopWorldZ` / `StrateBottomWorldZ` are runtime Z bounds) and need an explicit
exclusion list. Bools cannot be blended — roll them by probability or inherit from the dominant parent.
#### Human-scale audit and the killed tunnel-only hypothesis (2026-09-05)
The generation defaults are now derived from the body reference rather than chosen as voxel counts:
**1 voxel = 0.25 m**, the player capsule is **1.36 voxels / 0.34 m radius** and **7.04 voxels /
1.76 m tall**, and the default strate is **8 chunks / 256 voxels / 64 m**. The complete generated
`name | voxels | METRES | body/level meaning` table is emitted by `VoxelForge.Composer.Showcase` and
covers each archetype plus the shared passage/disturbance and optional transport fields.
The requested maze test was run first on the same seed/index and a mouth-fitted step-1 ROI. The
radius is the tunnel radius; the bore is twice the radius:
| Corridor radius | Bore | Player-fit fraction | Traversable share | Minimum clearance | Arrival→departure |
|----------------:|-----:|--------------------:|------------------:|------------------:|-------------------|
| 4 vox / 1.00 m | 2.00 m | 0.009007 | 0.078358 | 1 voxel / 0.25 m | NotConnected |
| 6 vox / 1.50 m | 3.00 m | 0.014545 | 0.165932 | 1 voxel / 0.25 m | NotConnected |
| 8 vox / 2.00 m | 4.00 m | 0.012156 | 0.126354 | 1 voxel / 0.25 m | NotConnected |
| 10 vox / 2.50 m | 5.00 m | 0.009814 | 0.105611 | 1 voxel / 0.25 m | NotConnected |
| 12 vox / 3.00 m | 6.00 m | 0.008697 | 0.185039 | 1 voxel / 0.25 m | NotConnected |
The hypothesis is **killed as a single root cause**. There is no sharp or monotonic fit rise, and
the law stays disconnected at every bore. The unchanged one-voxel minimum also shows that the
failure is not explained by the nominal tunnel diameter alone: the generated field, route mouths,
floor/cap interaction, and/or resolution still need separate diagnosis.
The new defaults use separate derivations: rooms are 8-20 m diameters with a 24 m origin hub and
32 m cells; round passages are 3-4 m bores; Maze is a 16 m cell with a 4 m bore; slabs reserve a
22.4 m floor-to-ceiling span; shaft diameters are 4-7 m with 3 m connectors; islands are 12-24 m
diameters on 28 m cells; ordinary passages are 3-4 m bores and reach 8-24 m. `RoomSpacing` keeps
the largest room 6 m radially clear of the next cell, `CorridorRadius` is 8/32 = 0.25 of Maze half-cell,
and `StrateHeightInChunks` grows from 4 to 8 because 17 m tall rooms, 20 m terrain relief,
vertical shafts, and a high cap do not share a comfortable 32 m envelope. No global multiplier was
used. The roughness reach is `1.875 × roughness` voxels: the new default ratios are
**0.625** (minimum tunnel), **0.469** (Maze), **0.469/0.625** (shaft/connector), **0.234** island
radius (**0.484** including blend), **0.625/0.938** slab column for floor/ceiling, and **0.047**
against SurfaceWorld's 80-voxel relief scale.
The architecture sanity check uses [Epic's Unreal level-blockout guidance](https://dev.epicgames.com/documentation/en-us/unreal-engine/designer-01-project-setup-and-level-blockout-in-unreal-engine) (player-sized reference, 2-3 m halls and 3-4 m heights as starting guidance), the [2010 ADA Standards](https://www.ada.gov/law-and-regs/design-standards/2010-stds/) (915 mm clear walking width and larger passing/turning spaces), and [NPS Lehman Cave dimensions](https://www.nps.gov/grba/learn/nature/lehman-caves-dimensions.htm) (real chambers ranging from passages to 20 m-plus vertical volumes). These are sanity anchors, not claims that one universal ratio makes a good cave.
### ✅ Tier 5 status — promotion is built and measured (2026-09-05)
Promotion is now a real corpus input, not a claim about a future approval UI. A surviving editor
@@ -817,9 +855,9 @@ pass, to:
`Saved/ComposerPreview/structure_seed_0_corpus_9dbcea85_step_4_radius_256_fine_step_1_fine_radius_64/`
The fine pass is explicit and bounded: the current composer selects the 42 coarse survivors, samples
step 1 in a radius-64 (128×128 XY) ROI, and refuses before allocation when `MaxCells=2,000,000` would be
exceeded. The default is radius 64 because it stays around the observed 1.8M-cell budget while exposing
The fine pass is explicit and bounded: the historical composer selected the 42 coarse survivors, sampled
step 1 in a radius-64 (128×128 XY) ROI, and refused before allocation when `MaxCells=2,000,000` would be
exceeded. The default is radius 64 because it stays around the observed multi-million-cell budget while exposing
voxel-scale detail; radius 128 is already roughly 7.1–7.5M cells and radius 256 exceeds the 8M coarse
cap. The public settings let another editor/automation caller choose step, radius, centre, margin, and
cap, or the writer can be called for an explicitly selected list. Fine filenames, captions, and each
@@ -859,8 +897,10 @@ the editor automation test VoxelForge.Composer.Showcase; opening it is offline a
generation hook. It contains one alphabetized card for each native archetype, with the exact four PIE
hand-off values, recipe, coarse step-4 filled/contour XZ+XY views, and a separate step-1 filled/contour
ROI centred on that card's coarse LargestComponentPoint. The fine ROI is bounded at radius 64 and
MaxCells=2,000,000; a refusal or blank ROI is written as text rather than represented by an empty
image. All eight cards in the final run rendered both fine views; refusals **0**, blank cards **0**.
MaxCells=4,000,000; a refusal or blank ROI is written as text rather than represented by an empty
image. The earlier bounded four-chunk run rendered all eight fine views; the final production-height
run is recorded below because its larger window produced **7** fine renders, **1** refusal, and **1**
blank diagnostic card.
The Part A table adds three measurements to the original volumetric walkability ratio:
@@ -881,7 +921,9 @@ those survivors the deterministic score is floor_area + 0.25*clamp(clearance/64,
The fixture and PIE hand-off use the project generator seed **0**, bComposerRollStructure=false,
and leave the existing slot layout, passage endpoints, placement, and WorldRadiusVoxels=0 intact.
Selected-card measurements (each card prints its own exact derived-margin Z window; common XY window
The following is the **pre-scale baseline** captured before the 2026-09-05 human-scale defaults
(the post-scale diagnostic table is below). Each card prints its own exact derived-margin Z window;
common XY window
is [-256,256) × [-256,256) voxels, step **4**, HeadroomCells=2, MaxCells=8,000,000):
| Archetype | walkable fraction | floor area fraction | median clearance | largest surface share |
@@ -921,6 +963,126 @@ cave design
(https://store.steampowered.com/news/posts/?appgroupname=Deep+Rock+Galactic&appids=548430&enddate=1729500950&feed=steam_community_announcements),
and Team Cherry map design (https://www.pcgamer.com/how-to-design-a-great-metroidvania-map/).
#### Final post-scale measurement (2026-09-05)
The new defaults are applied in `VoxelStrateTypes.h`; the production definition, season defaults, and
the owner-facing showcase use `StrateHeightInChunks=8` (64 m). The bounded test fixture remains at
four chunks so the broad regression suite stays finite; this is a test-budget distinction, not a
second production default. The final focused run is
`Saved/AutomationReports/WorldScaleShowcaseProductionFinal/index.json`, with 256 roll evaluations,
82 eligible single-region evaluations, 174 lateral-region evaluations skipped while that gate is off,
and a **0/8** complete hard-gate survivor set. It still wrote fresh diagnostic cards: 7 fine renders,
1 refusal, and 1 blank card.
The before/after values below are deliberately labelled as candidate measurements, not paired
experiments: the before rows are the selected pre-scale candidates from the baseline report, while
the after rows are the best measured post-scale candidates from the production-height search. Floor
area is the coarse 128 m × 128 m projected-footprint proxy (16,384 m² maximum); the ratio is the
candidate's reported roughness-to-feature ratio. A zero or unresolved player law is a result, not a
substituted value.
| Archetype | Before: fit / traversable / law | Before: floor m² / median clearance m / roughness ratio | After: fit / traversable / law | After: floor m² / median clearance m / roughness ratio |
|---|---|---|---|---|
| CrystalChamber | 0.011745 / 0.810378 / NotConnectedAtThisResolution | 16,382 / 17 / 1.813 floor, 1.796 ceiling | 0.002699 / 0.017288 / NotConnectedAtThisResolution | 16,384 / 35 / 0.847 |
| FlatPlain | 0.003938 / 0.053571 / NotConnectedAtThisResolution | 16,382 / 18 / 1.840 floor, 2.308 ceiling | 0.000000 / 0.000000 / unresolved | 16,343 / 43 / 1.092 |
| FloatingIslands | 0.000000 / 0.000000 / StartCellNotPlayerFit | 6,556 / 9 / 0.025 | 0.000000 / 0.000000 / StartCellNotPlayerFit | 4,577 / 29 / 0.283 |
| Maze | 0.010523 / 0.136646 / NotConnectedAtThisResolution | 4,759 / 2 / 0.938 | 0.016851 / 0.058757 / NotConnectedAtThisResolution | 6,115 / 3 / 0.423 |
| SurfaceWorld | 0.001027 / 0.029412 / NotConnectedAtThisResolution | 15,359 / 16 / 0.032 | 0.000627 / 0.008415 / NotConnectedAtThisResolution | 16,384 / 42 / 0.038 |
| TunnelNetwork | 0.004439 / 0.145833 / NotConnectedAtThisResolution | 3,414 / 5 / 1.436 | 0.001197 / 0.612245 / NotConnectedAtThisResolution | 6,153 / 9 / 0.383 |
| Underwater | 0.005251 / 0.160000 / NotConnectedAtThisResolution | 3,376 / 3 / 2.212 | 0.000000 / 0.000000 / OutOfWindow | 21 / 17 / 0.683 |
| VerticalShafts | 0.007458 / 0.233577 / NotConnectedAtThisResolution | 1,864 / 3 / 0.731 shaft, 1.302 connector | 0.009883 / 0.083045 / NotConnectedAtThisResolution | 2,718 / 4 / 0.622 |
The interpreted outcome is mixed. Nominal dimensions and median clearances grew where they should,
and TunnelNetwork's best measured candidate's traversable share rose substantially, but the global law
did not become connected and broad rooms can still have very low player-fit fractions. Maze improved
only modestly and remains disconnected. This is consistent with the radius sweep being a killed
single-cause hypothesis: width alone did not cure the route/mouth/resolution failures.
The direct default roughness arithmetic is stable and independent of which rolled candidate won:
| Archetype / feature | Arithmetic | Ratio |
|---|---|---:|
| TunnelNetwork, Underwater tunnel | reach `= 2 × 1.25 × 1.5 = 3.75 vox`; `3.75 / 6` minimum radius | 0.625 |
| Maze corridor | `3.75 / 8` | 0.469 |
| FlatPlain, CrystalChamber floor / ceiling columns | `7.50 / 12` and `11.25 / 12` using mean 12-voxel column radius | 0.625 / 0.938 |
| VerticalShafts shaft / connector | `3.75 / 8` and `3.75 / 6` | 0.469 / 0.625 |
| FloatingIslands | `5.625 / 24`; including 6-voxel SDF blend, `(5.625+6)/24` | 0.234 / 0.484 |
| SurfaceWorld relief | `3.75 / 80` terrain-relief scale | 0.047 |
The default derivations are not a global multiplier:
* Body and target anchors: `1 voxel = 0.25 m`; the capsule is `1.36 vox` radius and `7.04 vox`
tall. A 2.5 m no-duck corridor is 10 voxels; the 3-4 m fight target is 12-16 voxels. An 8-15 m
room is 32-60 voxels across, and a 20 m cathedral anchor is 80 voxels across. Epic's official
Unreal blockout guidance uses a player-sized reference and gives roughly 2-3 m halls and 3-4 m
heights as starting guidance; the [2010 ADA Standards](https://www.ada.gov/law-and-regs/design-standards/2010-stds/)
provide a 915 mm accessible clear-width lower bound, not a combat-space target.
* TunnelNetwork/Underwater: room radii `16..40 vox = 4..10 m`, so diameters are 8-20 m; the
origin radius `48 vox = 12 m` gives a 24 m, three-chunk hub. `RoomSpacing=128 vox = 32 m` leaves
`64-40=24 vox = 6 m` radial margin around the largest room. `TunnelMin/MaxRadius=6..8` gives
3-4 m bores. `RoomHeightRatio=0.85` makes the largest room's vertical diameter
`2×40×0.85×0.25=17 m`; `H=8×32=256 vox=64 m` leaves enough vertical budget for seals,
passages, and a high room. `MaxTunnelLength=360 vox=90 m` exceeds the worst jittered neighbour
distance with margin.
* FlatPlain/CrystalChamber: floor `0.25×256=64 vox=16 m`, ceiling `0.60×256=153.6 vox=38.4 m`,
leaving `22.4 m` before roughness. Columns are `8..16 vox` radii (4-8 m diameters) on 96-voxel
(24 m) cells. The two names intentionally retain the same slab generator and parameter block.
* Maze: `CellSize=64 vox=16 m`; `CorridorRadius=8 vox=2 m`, hence a 4 m bore; the corridor radius
is `8/32=0.25` of the half-cell, leaving a 6 m centre-to-wall radial margin before other geometry.
* SurfaceWorld: `ElevationRange=80 vox=20 m`, base ground `0.25×256=16 m`, warp `48 vox=12 m`,
sky cap `0.95×256=243.2 vox=60.8 m`; terrace/layer/beach/overhang values are separately
2 m / 2 m / 3 m / 4 m reach + 6 m height optional features.
* VerticalShafts: spacing `80 vox=20 m`, shaft radii `8..14 vox` (4-7 m diameters), connector
radius `6 vox` (3 m bore), ledge spacing `32 vox=8 m`, ledge depth `4 vox=1 m`.
* FloatingIslands: spacing `112 vox=28 m`, radii `24..48 vox` (12-24 m diameters); the largest
leaves `56-48=8 vox=2 m` centre-to-edge radial margin. Thickness is independent:
`48×0.60=28.8 vox=7.2 m` below the centre and `48×0.20=9.6 vox=2.4 m` above it.
* Shared passages and disturbances: mouth/mid radii `8/6 vox` (4/3 m bores), reach `32..96 vox`
(8-24 m), spine distance `64..192 vox` (16-48 m), wander/spiral `24 vox=6 m`, cascade ledge
`8 vox=2 m`; chasm spacing/radius `192/24 vox` (48 m / 6 m), bridge spacing/radius `128/8`
(32 m / 2 m), and ridge spacing/height/thickness `128/32/8` (32 m / 8 m / 2 m). Optional
transport fields are also audited: arch radius `6..12` (1.5-3 m), column `4..8` (1-2 m), pit
`8..16` plus depth `32` (2-4 m plus 8 m), chimney `4..8` plus height `32` (1-2 m plus 8 m),
dome `16..32` (4-8 m), pinch length `24` (6 m), overhang depth `8` (2 m), and the inactive
layer/rib depths `0.3/0.4` (7.5/10 cm). The exact generated row-by-row audit includes nominal
periods for every frequency field.
The 64 m height is deliberate rather than accidental: the GDD boss-space anchor is approximately
3-4 chunks (24-32 m), so the extra vertical envelope is needed to combine that room scale with
seals and vertical traversal. The NPS [Lehman Cave dimensions](https://www.nps.gov/grba/learn/nature/lehman-caves-dimensions.htm)
also support heterogeneous natural volumes rather than one fixed room ratio.
#### Equivalence, box safety, and cost after the default move
The full report `Saved/AutomationReports/WorldScaleFullFinal3/index.json` recorded 28 successes,
2 warning-only tests, 0 failures, and 0 not-run tests in 1,704.010 s. The warnings are known scope
findings: lateral regions remain gated at 9/16 cross-region law, and TunnelNetwork op-stack
sampling has only 240/6,000 samples outside its gate. Neither is a box-soundness violation.
All legacy/stack equivalence tests remained bit-identical to their shared reference paths, including
Maze, both slab archetypes, SurfaceWorld, TunnelNetwork stage A+B, VerticalShafts, and FloatingIslands.
`WorldRadiusVoxels` remained 0, lateral regions stayed gated, density sign remained correct, and every
box brute-force audit reported **0 violations**. Current representative box counts are: ParameterRoll
1,149 proved / 1,529,319 lattice voxels; StructureRoll 715 / 951,665; corpus-free arms 185 / 246,235,
260 / 346,060, and 299 / 397,969; TunnelNetwork production op-stack 7/40 proved (7 AllSolid),
Underwater 34/40, Maze 127/256 plus 250/256 novel lattice boxes, FlatPlain 27/60, CrystalChamber
39/60, tuned CrystalChamber 29/60, VerticalShafts 31/60, and FloatingIslands 15/60 AllAir.
Every listed count has zero brute-force violations.
The pristine pre-scale player-fit showcase did not execute the op-stack classification suite, so a
pure old-default tile-count delta does not exist. The nearest instrumented pre-final checkpoint had
the operator-stack 600-tile scan at **521 Mixed / 23 AllSolid / 56 AllAir**; the final world-scale
scan is **518 / 71 / 11**. Uniform proofs therefore did not collapse (79 → 82), although the
AllAir/AllSolid mix moved. The final non-stack scan is **522 / 22 / 56**. This is a real measured
classification result, but it must not be misrepresented as a pristine causal A/B run. The
production-height showcase itself cost about **1,709.7 s** and produced 7 fine renders, one refusal,
and one blank diagnostic card; its artifact is `Saved/VoxelForge/Showcase/index.html`.
The corrected owner-facing artifact is therefore at `Saved/VoxelForge/Showcase/index.html` (fresh
report: `Saved/AutomationReports/WorldScaleShowcaseProductionFinal/index.json`). It contains the new
metre audit and the rejected-but-useful diagnostic cards; the zero hard-gate survivor set is
intentionally visible rather than hidden by a fallback candidate.
### 3.5 Validation in three layers, and how "good" is ever judged
1. **Construct by design** so the law cannot break — build the connections FIRST and generate around
@@ -1092,8 +1254,10 @@ a passage and arrive in a sealed pocket.**
`SuggestLandingPoint(DesiredX, DesiredY, MaxLateralSnap) -> optional FVector`. Every source knows where
its own air is: `FRoomGraphSource` keeps the nearest room's vertical placement at the requested XY,
`MakeSlabVoidSource` answers in the void band, `FIslandBlobSource` finds a blob top, and the lattice/
shaft sources search their placement grid. Sparse sources may move laterally, but only within one
source spacing/cell; if that bounded search has no footing, falling back is the honest answer.
shaft sources search their placement grid. Sparse sources may move laterally, but only within a
bounded local source neighbourhood (one cell for Maze, two shaft spacings at the default
VerticalShafts density, one spacing for islands); if that search has no footing, falling back is the
honest answer.
Passage placement remains deterministic and cheap, and the slanted control-point chain is bounded too.
Then the measurement pass flood fill is the net: does the upper mouth's air component reach the lower