feat(composer): the parameter roll -- infrastructure real, corpus starved
Tier 4a. The first piece of the composer that INVENTS rather than fixes. The design, from COMPOSER-NOTES §3.3: do NOT roll 73 parameters independently. The coherent region of a 73-dimensional space is a vanishingly thin sheet and uniform sampling never lands on it -- and independent rolling destroys the CORRELATIONS (room spacing <-> room radius <-> tunnel length) that make a vector coherent. So blend known-good vectors through the existing FStrateGenerationParams::Lerp instead: constraint satisfaction is free, because a convex combination preserves every relation holding in both parents. Min <= Max stays true because it was never broken. Built: FVoxelStrateCorpus (loads authored vectors, computes per-field spread), VF_RollStrateParams (2-3 weighted parents, convex blend, jitter by +-15% of each field's MEASURED corpus range -- not by the clamps, which are "don't type nonsense" limits, not "this makes a good world" limits), and VoxelForge.Composer.ParameterRoll. Determinism asserted by rolling twice and comparing every field. Exclusion list found by reflection, not assumption: StrateTopWorldZ and StrateBottomWorldZ (manager-owned runtime bounds) plus 34 terrain-op transport fields (TerraceStepHeight..PinchLength) that are copied in from room operators rather than being strate tunables. Bools inherit from the dominant parent; ints/enums use Lerp's existing snap. ⚠️ THE RESULT IS VACUOUS AND SAYS SO. 64/64 candidates "survived" -- but the corpus loaded ONE vector (DA_Strate3), so all 64 are bit-identical. 100% survival of a single point is not evidence of anything. The box- verdict check is vacuous too: 2,560 boxes, 0 proved, 0 voxels brute-forced, so §6.2 is NOT closed. The test emits a warning saying exactly this rather than reporting a clean pass, and no workaround was added to hide it. Four strate assets exist (DA_Strate1..4); the loader found one. Fixing the corpus is the next task -- with one parent there is nothing to blend, and every number above is a placeholder. Also owed: clamp metadata is editor-only, so the safety net needs a cook-time baked table before this ships. Nothing calls the composer from any runtime path (§3.1: offline, once per season, on a build box). Build clean, 23 tests / 0 failed (1 carries the deliberate vacuity warning), verified in VoxelM.log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VJiTcTSDNkKBtnNdiBtdaU
This commit is contained in:
1 parent
8e346a3054
commit
358bd415a9
5 files changed
+1649
-2
No files matched your search
+48
-2
@@ -196,6 +196,49 @@ 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.
|
||||
|
||||
### ✅ Tier 4a status — parameter roll built (2026-09-04)
|
||||
|
||||
`Public/VoxelStrateComposer.h` + `Private/VoxelStrateComposer.cpp` now implement the corpus and
|
||||
the deterministic roll. `Private/Tests/VoxelForgeComposerParameterRollTest.cpp` is the offline
|
||||
measurement harness. The roll uses `FStrateGenerationParams::Lerp`, chooses 2–3 weighted parents
|
||||
inside one archetype group, applies jitter of **±15% of each field's measured corpus range
|
||||
(`max-min`)**, then applies reflected `ClampMin`/`ClampMax` metadata. It does not use clamps as
|
||||
distribution ranges, does not touch generation, and leaves `WorldRadiusVoxels` at its default 0.
|
||||
|
||||
The loader walks the settings asset's fixed-strate and pool references, de-duplicates by asset path,
|
||||
and accepts only `TunnelNetwork` / `Underwater`: those are the only archetypes whose authored vector
|
||||
is `GenerationParams`. The current `DA_Settings` asset contains **one unique resolved reference**,
|
||||
`DA_Strate3`, and it is `TunnelNetwork`; the other authored archetype assets are not in that
|
||||
settings corpus. Consequently every measured field has zero spread, all 64 rolls repeat the same
|
||||
known-good vector (parent weights still roll deterministically), and this run did not exercise
|
||||
non-zero jitter. That is a corpus-size finding, not a rate optimization.
|
||||
|
||||
The reflection/use audit found **36 excluded fields**: the 34 terrain-op transport fields
|
||||
`TerraceStepHeight`, `TerraceHardness`, `TerraceNoiseDisplacement`, `LayerLineSpacing`,
|
||||
`LayerLineDepth`, `OverhangStrength`, `OverhangDepth`, `OverhangFrequency`, `RibbingSpacing`,
|
||||
`RibbingDepth`, `CliffStrength`, `ScallopStrength`, `ScallopFrequency`, `ArchDensity`,
|
||||
`ArchMinRadius`, `ArchMaxRadius`, `ColumnDensity`, `ColumnMinRadius`, `ColumnMaxRadius`,
|
||||
`PitDensity`, `PitMinRadius`, `PitMaxRadius`, `PitDepth`, `ChimneyDensity`, `ChimneyMinRadius`,
|
||||
`ChimneyMaxRadius`, `ChimneyHeight`, `DomeDensity`, `DomeMinRadius`, `DomeMaxRadius`,
|
||||
`DomeHeightRatio`, `PinchDensity`, `PinchStrength`, `PinchLength` — populated per room by
|
||||
`UVoxelTerrainOpDefinition` — plus the manager-owned runtime bounds `StrateTopWorldZ` and
|
||||
`StrateBottomWorldZ`. The test prints the complete field-by-field table, including excluded fields,
|
||||
reflection status, and clamp metadata.
|
||||
|
||||
The bool policy is explicit: `bTunnelsFlowTowardOrigin` is inherited from the dominant parent.
|
||||
`OriginRoomMaxConnections` and `RoughnessNoiseType` retain `Lerp`'s existing SNAP behavior and
|
||||
are not jittered. In this editor build clamp metadata was available while the table was built; it
|
||||
is **not promised in a cooked runtime**, so the commandlet/cook-time bake remains owed.
|
||||
|
||||
The first 64-candidate run (step 4, radius 256, max 8,000,000 cells, fixture seed 1337) produced
|
||||
64/64 non-vacuous candidates, 64/64 largest-component share ≥ 0.50, and 64/64 exact unsnapped
|
||||
arrival→departure law passes. Every row was `air=0.520272`, `largest share=0.999996`,
|
||||
`walkable=0.057995`, `feature scale=20.000000`, `Connected`; total runtime was **542.220 s**.
|
||||
The §6.2 check saw **2,560 Mixed, 0 AllSolid, 0 AllAir, 0 brute-force voxels, 0 violations**:
|
||||
this is explicitly **vacuous**, not evidence that rolled bounds are sound, because the current cave
|
||||
box path emitted no uniform verdict. The test leaves §6.2 open and reports that fact rather than
|
||||
turning it into a workaround.
|
||||
|
||||
### 3.4 The measurement pass — one grid, one flood fill, three jobs
|
||||
|
||||
Sample a candidate strate into a coarse voxel grid, flood-fill the air **once**, derive everything from
|
||||
@@ -533,8 +576,11 @@ an open semantic decision; the Part 0 analysis above concludes that FloorBias is
|
||||
roughness and should stay late in the stack.
|
||||
|
||||
### Tier 4 — the composer proper
|
||||
Structure roll (§3.2) · parameter roll (§3.3) · reject-and-resample driven by Tier 2 (§3.5) · the
|
||||
**offline season pipeline** with Jahni's review and veto (§3.1).
|
||||
- ✅ **Parameter roll (§3.3, Tier 4a)** — corpus spread + deterministic blend/jitter implementation
|
||||
and the 64-candidate measurement pass are built; the first run exposed a one-vector settings corpus
|
||||
and a vacuous cave box-verdict scan, both recorded above.
|
||||
- ⬜ Structure roll (§3.2) · reject-and-resample driven by Tier 2 (§3.5) · the **offline season
|
||||
pipeline** with Jahni's review and veto (§3.1).
|
||||
|
||||
### Tier 5 — the long game
|
||||
**Promotion** (good strates rejoin the corpus) · theme and tag draws for materials, creatures and audio ·
|
||||
|
||||
Reference in new issue
Block a user