Skip to content

Commit b540470

Browse files
wormeymanclaude
andcommitted
test(cliffs): the direction is ORE -> CLIFF, and it is worth 31 cells (#84)
#94 ruled out lava, every other tile, the cliffiness gate and entity collision, then handed the mechanism over open: the cliff/ore correlation fits two stories demanding opposite fixes, and the note closed "settle the direction, not add a rejection." Settled with a lever rather than an argument. `autoplace_controls` is settable on the surface exactly like `cliff_settings`, so the resources can be switched off (`size = 0`) and the same regions regenerated - #82's collapse trick pointed one subsystem over. | arm | cliff-vulcanus | resources | | --- | --- | --- | | `[1500,1500]` resources ON | 885 | 3,933 | | `[1500,1500]` calcite OFF | 912 | 19 | | `[1500,1500]` geyser OFF | 889 | 3,914 | | `[1500,1500]` ALL OFF | 916 | 0 | | `[0,0]` collapsed, ON | 335 | 945 | | `[0,0]` collapsed, ALL OFF | **345** | 0 | **Both arms, not one.** Ore off puts a cliff in all ten blob cells, 0/10 -> 10/10. The converse arm is what makes it a direction: the collapsed settings force 335 cliffs through the region against the default's 283, straight through the tungsten field, and the ore does not move - the same 945 entities. Three properties, each constraining the mechanism: it is ONE-WAY (removing a resource only ever adds cliffs, in all four paired arms), ADDITIVE (27 calcite + 4 geyser = exactly the 31 of all-off, disjoint), and LOCAL with a geometry that is a BOX OVERLAP against the resource ENTITY's rectangle - measurable only because the geyser's collision half-extent is 1.398 against the ores' 0.098, which is why every point-at-tile-centre geometry scored 20-27 of 31. Scored as box overlap: 21 of 31 explained, ZERO false alarms in 885, and all six connected components of the suppressed set contain a directly-overlapped cell (adjacency is not a free pass - only 8 of 885 kept cliffs touch one). Worth 31 of the 42 cells the port over-places at `[1500,1500]`: every one of the 31 is a cell the port places and none is a cliff the game kept, so the rule is pure precision. Still not a collision, now doubly established. The mask argument stands and the fixture carries the layers rather than a claim about them. The disassembly says it more strongly: `computeInternal` (0x101622860) calls `generateCliffs` at +44 and `generateEntities` at +148; `apply` (0x101623b48) calls `applyCliffs` at +124 and `applyEntities` at +164 - the cliffs are computed AND placed before any resource exists, which also refutes #94's "maybe ore avoids cliffs" guess. Harness: `sampleCliffEntitiesFull` gains `autoplaceControls`, `alsoResources` and `protoNames`, dumping cliffs, resources, prototype collision geometry and the controls the SURFACE read back from ONE generated surface - so an override that failed to apply cannot be mistaken for a term that does not matter, and "the ore moved" and "the cliffs moved" are never compared across two worlds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LT6oy76sLRqoC1QzLocQ1h
1 parent 340b70d commit b540470

6 files changed

Lines changed: 71717 additions & 38 deletions

File tree

docs/noise/vulcanus-cliffs-NOTES.md

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@
3131
> game does not put cliffs on ore (3 of its 1,569 cliffs across the three oracle
3232
> regions do) and the port does. Read the LAST section,
3333
> **`## The blob is ore`**; it supersedes the "field-independent suppression of
34-
> unknown cause" framing below. Two corrections ride with it:
34+
> unknown cause" framing below. Its "mechanism is still open / settle the
35+
> direction first" close is itself superseded by the LAST section,
36+
> **`## The direction is ORE -> CLIFF`**: the resources suppress the cliffs, the
37+
> rule is a box overlap against the resource ENTITY's rectangle, and it is worth
38+
> 31 of the 42 surplus cells at `[1500,1500]`. Two corrections ride with it:
3539
>
3640
> - **`37 / 1531 = 2.4%` is the NO-lava-rejection arm**, not what ships. With the
3741
> rejection `renderVulcanusCliffs` actually applies it is **33 wrong of 1,525
@@ -1442,3 +1446,91 @@ port: the corner lattice is the bare `chunkOrigin + (i, j) * grid_size`, the
14421446
elevation register is smoothed with knots at in-chunk indices `{0, 4, 7}`
14431447
(`hi = min(lo + 4, 7)`) and **cliffiness is read unsmoothed**, and
14441448
`getModifiedElevationInterval` is `cliff_elevation_interval / frequency`.
1449+
1450+
## The direction is ORE -> CLIFF (2026-08-02, #84 item 1)
1451+
1452+
The section above ends "the next step is to settle the direction, not to add a
1453+
rejection." It is settled, and the answer is **the resources suppress the
1454+
cliffs**. It was settled by a lever rather than by an argument:
1455+
`map_gen_settings.autoplace_controls` is settable on the surface exactly like
1456+
`cliff_settings`, so the resources can be switched OFF (`size = 0`) and the same
1457+
regions regenerated. That is #82's collapse trick pointed one subsystem over.
1458+
Captured as `oracle-vulcanus-cliff-ore-direction.seed123456.json`, pinned in
1459+
`test/cliffOreDirection.spec.ts`.
1460+
1461+
| arm | cliff-vulcanus | resources |
1462+
| --- | --- | --- |
1463+
| `[1500,1500]`, resources ON | 885 | 3,933 |
1464+
| `[1500,1500]`, calcite OFF | 912 | 19 |
1465+
| `[1500,1500]`, geyser OFF | 889 | 3,914 |
1466+
| `[1500,1500]`, ALL OFF | 916 | 0 |
1467+
| `[0,0]` collapsed, resources ON | 335 | 945 |
1468+
| `[0,0]` collapsed, ALL OFF | **345** | 0 |
1469+
1470+
**Both arms of the question, not just one.** Turning the ore off puts a cliff in
1471+
**all ten** blob cells, `0/10 -> 10/10`. And the converse arm is what makes it a
1472+
direction rather than a correlation: the collapsed settings force 335 cliffs
1473+
through that region against the default's 283, straight through the tungsten
1474+
field, and the ore does not move - the same 945 entities. Cliffs do not push ore
1475+
around; ore removes cliffs.
1476+
1477+
Three properties fall out, and each constrains the mechanism:
1478+
1479+
- **One-way.** Removing a resource only ever ADDS cliffs. Nothing the game placed
1480+
with the resources on disappears when they are removed, in any of the four
1481+
paired arms. A perturbed field would move cells both ways; a rejection cannot.
1482+
- **Additive.** calcite alone accounts for 27 cells, the geyser alone for 4, and
1483+
all resources together for exactly those same 31, with no overlap. So each
1484+
resource acts independently and locally.
1485+
- **Local, with a geometry that is a BOX OVERLAP.** Not "is a resource tile
1486+
inside the 4x4 cell" - the test is the cliff's own collision rectangle against
1487+
the **resource entity's** rectangle. That distinction is measurable only
1488+
because `sulfuric-acid-geyser`'s collision half-extent is **1.398** against the
1489+
ores' **0.098**: a test treating every resource as a point at its tile centre
1490+
explains the calcite cells and cannot explain the geyser ones, which is exactly
1491+
the residual that made every candidate geometry score 20-27 of 31.
1492+
1493+
Scored as a box overlap it explains **21 of the 31** suppressed cells and raises
1494+
**zero** false alarms across the 885 the game kept. The other 10 are not
1495+
scattered: the suppressed set has six 4-connected components and **every one of
1496+
them contains at least one directly-overlapped cell**, so they are the remainder
1497+
of runs whose interior was rejected. Adjacency is not a free pass - only 8 of the
1498+
885 kept cliffs touch a suppressed cell at all.
1499+
1500+
### What it is worth, and what is still open
1501+
1502+
Every one of the 31 is a cell the port currently places, and none is a cliff the
1503+
game kept. So the rule is **pure precision**: it can only remove surplus, and it
1504+
removes 31 of the 42 cells the port over-places at `[1500,1500]`.
1505+
1506+
**The mechanism is still not a collision, and now that is doubly established.**
1507+
The mask argument stands - the fixture now carries the layers rather than a claim
1508+
about them, and `resource` is disjoint from the cliff mask. The disassembly says
1509+
the same thing from the other end, and more strongly:
1510+
`EntityMapGenerationTask::computeInternal` (`0x101622860`) calls `generateCliffs`
1511+
at `+44` and `generateEntities` at `+148`; `apply` (`0x101623b48`) calls
1512+
`applyCliffs` at `+124`, `applyDecoratives` at `+152` and `applyEntities` at
1513+
`+164`. **The cliffs are both computed and placed before any resource exists**,
1514+
so no collision test in the cliff path can see one, and the "ordering effect -
1515+
maybe ore avoids cliffs" half of the previous section's guess is refuted by the
1516+
converse arm above.
1517+
1518+
That leaves a rejection that reads the resource *placement* without the resource
1519+
*entity*: something the cliff pass evaluates that knows where the patches will
1520+
be. `Surface::wouldCollide` (`0x10160c088`) is `constCollideWithTile` +
1521+
`collideWithEntity` and nothing else, so it is not there either - and
1522+
`collideWithEntity` (`0x100a5b108`) was read rather than assumed this time: it
1523+
walks the entities in the box and tests them through the inlined
1524+
`CollisionMask::collides` (`CollisionMask.hpp:36`, at `+676`/`+680`), so it is
1525+
purely a layer test with no special case for resources. Note also that
1526+
`crater-cliff` is suppressed by calcite the same way (0 with calcite on, 8 with
1527+
it off), and craters are placed on a completely different path
1528+
(`CliffCraterPlacer::tryToPlaceCliffAsCrater`, `0x10160bcac`, called from
1529+
`applyEntities`) - so whatever this is, it is common to both cliff kinds rather
1530+
than specific to the cliff generator.
1531+
1532+
**Do not port this as a collision test against our own resource positions
1533+
without checking that arm separately.** The 31/0 score above uses the GAME's
1534+
resource entities as the input, which isolates the rule from the accuracy of the
1535+
resource port; driving it from `renderVulcanusResources` is a second question and
1536+
has not been measured.

0 commit comments

Comments
 (0)