Skip to content

Add Fulgora scrap's placement roll to the engine (#363) - #370

Merged
wormeyman merged 1 commit into
mainfrom
fulgora-scrap-placement
Aug 31, 2026
Merged

Add Fulgora scrap's placement roll to the engine (#363)#370
wormeyman merged 1 commit into
mainfrom
fulgora-scrap-placement

Conversation

@wormeyman

Copy link
Copy Markdown
Collaborator

PR 1 of 2 for #363. The engine can now decide where Fulgora scrap is PLACED,
not only where it could land. Nothing calls it yet - the render arm, the ABI
fields and the dispatcher gate are PR 2.

#363's premise was wrong, and that is what this PR is for

The issue says both halves of Fulgora's "all" composite already exist in Rust.
They do not. VIEW_SCRAP_FOOTPRINT paints every tile where probability > 0,
and its own doc comment at render.rs:72 says that is deliberate: a rolled
overlay would measure the salt rather than the model. The TypeScript composite
at elevationRenderRequest.ts:681 paints makeFulgoraScrapPlacement, which is
a real PlacementSet roll. So a byte-identical port needs placement code the
engine did not have.

What lands

placement::roll::salt::FULGORA_SCRAP 0x003ba58c, the same value as PLACEMENT_SALT.fulgoraScrap in src/noise/placement/placementRoll.ts
resources::fulgora_catalog ported from src/noise/resources/fulgoraResourceCatalog.ts: the map colour, the collision box and FulgoraScrapPlacement
render.rs reads SCRAP_MAP_COLOR from that module instead of keeping its own [229, 229, 229]

The salt module's doc claimed only the two Vulcanus salts were present, which
had already expired. The table is now all nine the TypeScript has, and says so.

Two copies of a map colour with nothing comparing them is the shape #364 removed
for the Vulcanus cliff tiles, so the second copy goes rather than gaining a
sibling.

Measured

128x128 window at the origin, seed 123456, neutral sliders, by
places_a_strict_nonempty_subset_of_the_footprint: 708 of 16,384 tiles are in
the footprint and 177 are placed
, so the roll accepts 25.0% of it.
Substituting one view for the other would move 531 pixels in that window.

engine.wasm: the code section is BYTE-IDENTICAL

The module stays 321,381 bytes, and 51 bytes change. Walking the section table
puts all 51 in the data section and none in the code section. They are
panic-location line numbers, which moved because render.rs and roll.rs each
gained lines above existing code.

section size differing bytes
code 303,925 0
data 15,658 51
every other section - 0

Building the main render.rs against the new fmw-noise isolates it further:
3 bytes, all from roll.rs's own line shift. The new placement module
contributes nothing, because nothing reaches it yet and dead-code elimination
removes it. It starts costing bytes in PR 2, when the render arm calls it.

Anti-vacuity

places_a_strict_nonempty_subset_of_the_footprint is added to
verify-rust.sh's poison set and was watched going red, not assumed to: the
perturbation inverts every accept and placements go from 177 to 16,207 of
16,384, tripping the test's upper bound.

Its sibling the_collision_box_cannot_reject_anything is deliberately left OUT.
Both of its arms run through the same poisoned resolve_chunk, so the effect
cancels and it stays green - the relational shape poison.rs records for the
capture-grid snap test. Listing it would fail the gate for being correct.

That second test also earns its place: the collision box is 0.1953125 tiles and
cannot reject anything, which looks like an oversight unless something asserts
it. The TypeScript passes the same inert box and
test/fulgoraScrapDensity.spec.ts makes the same assertion on that side.

Gates

gate result
scripts/verify-rust.sh VERIFY_RC=0
pnpm run verify VERIFY_RC=0, 9m41s, 162 test files, 1,589 passed, 3 skipped

Both exit codes were written into their logs and read back from there, not taken
from a wrapper's exit code.

What PR 2 does

The scrap params over the ABI, a Fulgora composite arm in render_fulgora, the
supported match at render.rs:236, the dispatcher gate at
elevationRenderRequest.ts:646, and a spec asserting the engine's composite is
byte-identical to the TypeScript's. Fulgora's "resources" and "all" are the
same pixels today, since the planet has no cliffs and no rocks, so one arm
serves both codes.

PR 1 of 2. The engine can now decide where scrap is PLACED, not only where it
could land. Nothing calls it yet - the render arm, the ABI fields and the
dispatcher gate are PR 2.

## #363's premise was wrong, and that is what this PR is for

The issue says both halves of Fulgora's `"all"` composite already exist in
Rust. They do not. `VIEW_SCRAP_FOOTPRINT` paints every tile where
`probability > 0`, and its own doc comment at `render.rs:72` says that is
deliberate: a rolled overlay would measure the salt rather than the model. The
TypeScript composite at `elevationRenderRequest.ts:681` paints
`makeFulgoraScrapPlacement`, which is a real `PlacementSet` roll. So a
byte-identical port needs placement code the engine did not have.

## What lands

| | |
| --- | --- |
| `placement::roll::salt::FULGORA_SCRAP` | `0x003ba58c`, the same value as `PLACEMENT_SALT.fulgoraScrap` in `src/noise/placement/placementRoll.ts` |
| `resources::fulgora_catalog` | ported from `src/noise/resources/fulgoraResourceCatalog.ts`: the map colour, the collision box and `FulgoraScrapPlacement` |
| `render.rs` | reads `SCRAP_MAP_COLOR` from that module instead of keeping its own `[229, 229, 229]` |

The salt module's doc claimed only the two Vulcanus salts were present, which
had already expired. The table is now all nine the TypeScript has, and says so.

Two copies of a map colour with nothing comparing them is the shape #364
removed for the Vulcanus cliff tiles, so the second copy goes rather than
gaining a sibling.

## Measured

128x128 window at the origin, seed 123456, neutral sliders, by
`places_a_strict_nonempty_subset_of_the_footprint`: **708 of 16,384 tiles are
in the footprint and 177 are placed**, so the roll accepts 25.0% of it.
Substituting one view for the other would move 531 pixels in that window.

## engine.wasm: the code section is BYTE-IDENTICAL

The module stays 321,381 bytes, and 51 bytes change. Walking the section table
puts **all 51 in the data section and none in the code section** - they are
panic-location line numbers, which moved because `render.rs` and `roll.rs` each
gained lines above existing code.

Building the HEAD `render.rs` against the new `fmw-noise` isolates it further:
3 bytes, all from `roll.rs`'s own line shift. The new placement module
contributes nothing, because nothing reaches it yet and dead-code elimination
removes it. It starts costing bytes in PR 2, when the render arm calls it.

## Anti-vacuity

`places_a_strict_nonempty_subset_of_the_footprint` is added to
`verify-rust.sh`'s poison set and was **watched going red**, not assumed to:
the perturbation inverts every accept and placements go from 177 to 16,207 of
16,384, tripping the test's upper bound.

Its sibling `the_collision_box_cannot_reject_anything` is deliberately left
OUT. Both of its arms run through the same poisoned `resolve_chunk`, so the
effect cancels and it stays green - the relational shape `poison.rs` records
for the capture-grid snap test. Listing it would fail the gate for being
correct.

That second test also earns its place: the collision box is 0.1953125 tiles and
cannot reject anything, which looks like an oversight unless something asserts
it. The TypeScript passes the same inert box and
`test/fulgoraScrapDensity.spec.ts` makes the same assertion on that side.

## Gate

`scripts/verify-rust.sh`, `VERIFY_RC=0`, read out of
`/home/eric/gate-logs/363a-rust.log` rather than from a wrapper's exit code.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@wormeyman
wormeyman merged commit df71e26 into main Aug 31, 2026
9 checks passed
@wormeyman
wormeyman deleted the fulgora-scrap-placement branch August 31, 2026 19:12
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