Skip to content

feat(oracle): the resource lever moves TILES - confounded, but inert for cliffs (#84) - #128

Merged
wormeyman merged 1 commit into
mainfrom
feat/tile-lever-oracle
Aug 4, 2026
Merged

feat(oracle): the resource lever moves TILES - confounded, but inert for cliffs (#84)#128
wormeyman merged 1 commit into
mainfrom
feat/tile-lever-oracle

Conversation

@wormeyman

Copy link
Copy Markdown
Owner

Every ore result in #84 uses one instrument: switch a resource off through map_gen_settings.autoplace_controls and see which cliffs come back. It has been treated throughout as removing entities and nothing else. It does more, and the game's data files say so.

-- planet-vulcanus-map-gen.lua
vulcanus_calcite_size   = "slider_rescale(control:calcite:size, 2)"
vulcanus_calcite_region = "... vulcanus_calcite_size ..., control:calcite:frequency ..."

-- tiles-vulcanus.lua
volcanic_jagged_ground_range = "5 * min(10, max(vulcanus_calcite_region + 0.2, ...))"

That last one is a tile range, so calcite size = 0 changes which tile the argmax picks - a live route from the lever to Surface::wouldCollide's TILE half, exactly the kind #124 was left looking for after it closed the entity half.

Measured against the game

Three arms over [1500,1500], uniform stride-2 grid, 16384 points:

arm tiles changed blocking gained blocking lost
calcite OFF 841 (5.1%) 0 0
ALL resources OFF 1066 0 0

Every change is ground-to-ground - volcanic-jagged-ground losing the argmax to -folds, -folds-warm, -soil-dark, -soil-light, -folds-flat. Only lava and lava-hot carry tile_collision_masks.lava(), and nothing crosses that boundary, so constCollideWithTile cannot see any of it.

Every ore result in #84 stands. But the instrument was mischaracterised, and anyone reaching for autoplace_controls for a new question needs to know it moves tiles.

Non-vacuity: 1682 of the 16384 sampled tiles are blocking, so there was a boundary to cross; and each arm records the autoplace_controls the SURFACE read back, so "no tile moved" cannot be confused with "the override never applied".

Our port reproduces it, which covers the unsampled tiles

The capture is a 25% sample. Our tile model answers over all 65536 and says 3335 changed, 0 blocking - a rate of 5.09% against the game's 5.13%, on a lever nobody had ever pointed at it. That corroborates the port independently and is what lets its "no blocking flip anywhere" cover the 75% the grid skipped.

Control: tungsten OFF moves zero tiles here - there is no tungsten in this region; it is what fills [0,0], where #126 measured the ore suppressing zero cliffs.

Where this leaves the mechanism - a three-way contradiction

Both halves of Surface::wouldCollide are now closed against the ore:

half closed by
entity #124 - disjoint masks at prototype level, ordering, applyEntities skipping rather than destroying
tile this PR, on the game's own data

And yet #124 also found the ore acting at the destroy stage, where wouldCollide is the only thing that destroys. All three cannot be right. Recorded rather than smoothed over, ranked by corroboration:

  1. entity half closed - three independent routes, one a prototype-level data fact. Strong.
  2. tile half closed - the game's own tiles, non-vacuity arm, corroborating port model. Strong, but a 25% grid.
  3. ore acts at the destroy stage - n = 1. Weakest, and the first place to look.

Note that one cell, 1546,1550.5, is also one of the six #125's cascade does not explain. It has now been anomalous twice.

Harness

sampleTileNames gains an autoplaceControls override, plus a sampleTileNamesFull sibling returning the controls the surface read back (the existing signature is unchanged and now delegates). New fixture is deliberately a uniform grid rather than the positions our port predicts will change, so it does not encode the model it exists to check. PROVENANCE.json entry added; capture takes ~7s.

Verification

pnpm run verify green - 1478 app (up 9) + 13 worker + 3 container tests, 0 warnings, exit 0. Nothing shipping changed.

🤖 Generated with Claude Code

https://claude.ai/code/session_015jeznBmWiZywUc7cBw9xFU

…for cliffs (#84)

Every ore result in #84 uses one instrument: switch a resource off through
`map_gen_settings.autoplace_controls` and see which cliffs come back, treated
throughout as removing entities and nothing else. It does more, and the game's
data files say so:

  vulcanus_calcite_size   = slider_rescale(control:calcite:size, 2)
  vulcanus_calcite_region = ... vulcanus_calcite_size ..., control:calcite:frequency ...
  volcanic_jagged_ground_range = 5 * min(10, max(vulcanus_calcite_region + 0.2, ...))

That last one is a TILE range, so `calcite size = 0` changes which tile the
argmax picks - a live route from the lever to `Surface::wouldCollide`'s tile
half, exactly the kind #124 was left looking for after closing the entity half.

Measured against the GAME, three arms over [1500,1500] on a uniform stride-2
grid of 16384 points:

| arm               | tiles changed | blocking gained | blocking lost |
| ---               | ---           | ---             | ---           |
| calcite OFF       | 841 (5.1%)    | 0               | 0             |
| ALL resources OFF | 1066          | 0               | 0             |

Every change is ground-to-ground - jagged-ground losing the argmax to folds,
folds-warm, soil-dark, soil-light, folds-flat. Nothing crosses the
lava/lava-hot boundary, so `constCollideWithTile` cannot see any of it and
EVERY ORE RESULT IN #84 STANDS. But the instrument was mischaracterised, and
anyone using `autoplace_controls` for a new question needs to know it moves
tiles.

Non-vacuity: 1682 of the 16384 sampled tiles ARE blocking, so there was a
boundary to cross, and each arm records the controls the SURFACE read back.

Our port reproduces it - 3335 of 65536 changed, 0 blocking, a rate of 5.09%
against the game's 5.13%. That corroborates the port on a lever nobody had
pointed at it, and is what lets its "no blocking flip anywhere" cover the 75%
of tiles the grid skipped. Control: tungsten OFF moves zero tiles here, because
there is no tungsten in this region.

WHERE THIS LEAVES THE MECHANISM - a three-way contradiction, recorded rather
than smoothed over. Both halves of `Surface::wouldCollide` are now closed
against the ore (entity by #124, tile here), yet #124 also found the ore acting
at the destroy stage, where `wouldCollide` is the only thing that destroys. All
three cannot be right. Ranked by corroboration, the destroy-stage result is
weakest at n=1 - and its one cell, `1546,1550.5`, is also one of the six #125's
cascade does not explain, so it has been anomalous twice.

Harness: `sampleTileNames` gains an `autoplaceControls` override and a
`sampleTileNamesFull` sibling returning the controls the surface read back.
New fixture + PROVENANCE entry; capture takes ~7s.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jeznBmWiZywUc7cBw9xFU
@wormeyman
wormeyman merged commit 4eb6be9 into main Aug 4, 2026
6 checks passed
@wormeyman
wormeyman deleted the feat/tile-lever-oracle branch August 4, 2026 02:23
wormeyman added a commit that referenced this pull request Aug 4, 2026
… effect remains (#84) (#129)

* test(cliffs): every route from the ore to a cliff is closed - and the effect remains (#84)

#128 closed the tile half and recorded a three-way contradiction. Two more
routes are now closed, and the honest summary is stronger than "unknown": the
search space is EXHAUSTED, not merely unexplored.

| route                             | evidence                                    |
| ---                               | ---                                         |
| the cliff FIELD reads a resource  | `cliff_elevation = cliff_elevation_from_elevation = elevation = vulcanus_elevation`, whose 47-node expression closure holds no resource region; and our port's raw cell set is BIT-IDENTICAL under every lever arm (2277 cells, same codes) |
| `Surface::wouldCollide` does more | disassembled: per-orientation box, degenerate early-out, `constCollideWithTile`, `collideWithEntity`, both with the cliff's own mask at `proto+0x2b0`. No third input |
| its ENTITY half                   | #124 - disjoint masks at prototype level, ordering |
| its TILE half                     | #128 - 841 tiles move, none crosses lava/lava-hot |
| the lever perturbs STRUCTURALLY   | this PR - richness x2 and x0.5 move ZERO cliffs |

The last row was the only route #128 left open. `control:calcite:richness`
appears in `vulcanus_calcite_richness` ALONE - not in
`vulcanus_calcite_probability` (where the ore lands) nor in
`vulcanus_calcite_region` (which drives the volcanic_jagged_ground_range tile) -
so it hands the generator a different CompiledMapGenSettings describing the same
world. Over [1500,1500]: 861 cliffs and 3933 resources in all three arms,
identical cell for cell and orientation for orientation. The surface reads the
changed richness back, so the override applied.

So the lever is not a structural perturbation: the effect tracks ore PRESENCE -
and nothing that can see ore presence can reach a cliff.

This does NOT say the rule is wrong. Box overlap against real resource positions
reproduces the game at precision 1.000 over 31 cells and survives out of sample
(#126). The rule is right; the mechanism is missing, and the port's model of map
generation is incomplete in a way none of these five rows covers.

Recorded so the next person does not re-walk a closed route. Three genuinely
untouched ideas are listed in the notes: chunk-generation ORDER beyond the mask
argument, whatever happens to the queue between `generateCliffs` and
`applyCliffs`, and `CliffCraterPlacer::tryToPlaceCliffAsCrater` - ruled out for
the residual by position but never as a mechanism.

New fixture + PROVENANCE entry; capture takes ~7s.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jeznBmWiZywUc7cBw9xFU

* test(cliffs): close the cliffiness gap in the field argument (#84)

The field-closure row named `cliff_elevation` only. The cliff generator reads
TWO properties, and a closure argument that covers one of them leaves the gate
unexamined - `planet-map-gen.lua` routes `cliffiness = "cliffiness_basic"` for
Vulcanus, and nothing had traced that one.

It is clean: `cliffiness_basic`'s closure is a single node referencing only `x`,
`y` and `cliff_richness`. So the row stands, but now for both properties rather
than for the one that happened to get traced first.

Found while checking whether crater-cliff's appearance under the lever shared a
cause; `crater_cliff` (47-node closure) and both Vulcanus biomes it reads are
clean too.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015jeznBmWiZywUc7cBw9xFU

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
wormeyman added a commit that referenced this pull request Aug 4, 2026
…#136)

#130 proposed a mechanism class new to #84 - entity autoplace ROLLS, so removing
calcite shifts the per-chunk RNG stream - and said "nothing here tests it".
This is that test. No capture: every fact is in fixtures already committed, one
of them since #111.

The hypothesis is not refuted. The evidence for it is.

1. **n is ONE crater, not eight.** The eight `crater-cliff` entities are eight
   segments of a single ring - centre (1646.62, 1679.75), radii 4.95 to 7.00,
   against the prototype's own `crater_radius = 7`. FFF #386 describes exactly
   that. Effective sample size 1; #130's table invites reading it as 8.

2. **The spatial reading would have been vacuous.** All eight sit within 0.33
   tiles of a calcite entity - and their chunk holds 805 calcite over 1024
   tiles, 78.6% coverage. Landing on calcite there is expected.

3. **#130's `geyser OFF` control is VACUOUS.** Zero geysers in the ring's chunk;
   all 19 are in (48,48), (48,49), (53,54). The lever works globally - removes
   all 19, moves cliff-vulcanus 885 -> 889 - and cannot touch that chunk's
   stream by construction.

4. **A lever unrelated to calcite also produces craters**, unread in the #111
   fixture: `LAVA TILES OFF only` gives 7 craters with resources still ON, and
   both levers together give 18 against 8 and 7 alone.

5. **And that row is a data fact.** `crater-cliff` overrides the default cliff
   mask with `{item, object, player, water_tile}`, and on Vulcanus only lava and
   lava-hot carry `water_tile`. No RNG needed.

Calcite's own route stays open, with two more closed by reading rather than
assuming: not entity collision (`resource` mask is `{resource}`, disjoint from
every cliff mask including crater-cliff's - #124's argument extended rather than
carried over), and not lava tiles (#128 measured zero blocking tiles moved).

A third fact from the same file closes a route this session had to consider: the
default `cliff` mask carries `not_colliding_with_itself = true`, so cliffs never
collide with same-prototype cliffs. That matters because `applyCliffs` adds each
cliff to the surface before testing the next, and 57 of 400 adjacent orientation
pairs have overlapping boxes.

No new fixtures, no shipping behaviour change.


Claude-Session: https://claude.ai/code/session_01MmitdaFJxN9Wm8LkQu33kc

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant