Skip to content

test(cliffs): invert the elevation by level set - #18 is ONE TERM of vulcanus_elev - #82

Merged
wormeyman merged 1 commit into
mainfrom
cliffs-level-set-basalt-lakes-18
Aug 2, 2026
Merged

test(cliffs): invert the elevation by level set - #18 is ONE TERM of vulcanus_elev#82
wormeyman merged 1 commit into
mainfrom
cliffs-level-set-basalt-lakes-18

Conversation

@wormeyman

Copy link
Copy Markdown
Owner

The collapsed rule from #81 is also an instrument. A cell carries a cliff exactly when its corner elevations straddle cliff_elevation_0, so sweeping that threshold measures the elevation field the generator reads - the one thing an expression sample cannot do, since calculate_tile_properties answers for its own channel and whether the two agree was the open question.

19 levels, cliff_elevation_0 20..200 step 10, region [0,0], rule collapsed:

cliff_elevation_0 game ours ours/game
20 658 979 1.49
40 603 816 1.35
70 335 463 1.38
110 142 200 1.41
120 122 126 1.03
150 117 117 1.00
200 97 97 1.00

A clean edge at 120. At or above it every level is 1.00-1.04 and the same cells (both/game > 0.9, not merely the same count); below it every level is 1.20-1.49. Worst high 1.04 vs best low 1.20 - a threshold, not a drift, which is why the spec asserts the gap rather than two bounds separately.

Why 120 is not arbitrary

vulcanus_elev =
  vulcanus_elevation_offset
    + lerp(lerp(120 * vulcanus_basalt_lakes_multisample,
                20 + vulcanus_mountains_func * vulcanus_mountains_elevation_multiplier,
                vulcanus_mountains_biome),
           vulcanus_ashlands_func,
           vulcanus_ashlands_biome)

vulcanus_basalt_lakes is a min(1, ...), so the basalt-lakes branch saturates at exactly 120. Everything above 120 comes from the mountains and ashlands branches - which contain no multisample - and the port reproduces those exactly. Everything below is governed by vulcanus_basalt_lakes_multisample: the only multisample in the chain, and the only term with no Nauvis counterpart.

So the residual is that one term, and the port is exact everywhere else in the field. That is a far smaller target than "the Vulcanus elevation".

The mechanism to suspect

multisample's own docs: it evaluates "in a separate noise program with a larger grid" whose "sub-grids are copied to the main program". The cliff generator walks the 4-tile corner lattice; calculate_tile_properties does not - and that is the channel vulcanus-multisample-NOTES.md measured multisample(e,dx,dy) == e(x+dx,y+dy) through, and the channel every elevation fixture was captured through. A min() of four samples is an erosion operator, so a coarser effective grid smooths the field exactly the way a 40% over-placement implies.

What this does NOT say

Neither the multisample port nor the corner-fields fixture is refuted - both are correct in their channel. What has never been tested is whether the primitive behaves the same when the calling program's grid is 4 tiles rather than 1. The tile renderer, which consumes vulcanus_elevation through that same 1-tile channel, is not implicated by any of this.

Does not fix #18. pnpm run verify: 309 files clean, 1302 passed / 3 skipped, preview 12 passed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GRx1CU29RKLsRuUAErEDRB

The collapsed rule is also an instrument. A cell carries a cliff exactly when
its corner elevations straddle cliff_elevation_0, so sweeping that threshold
measures the elevation field the GENERATOR reads - the one thing an expression
sample cannot do, since calculate_tile_properties answers for its own channel
and whether the two agree was the open question.

19 levels, cliff_elevation_0 20..200 step 10, region [0,0], rule collapsed:

  e0= 20  game 658  ours 979  1.49
  e0= 40  game 603  ours 816  1.35
  e0= 70  game 335  ours 463  1.38
  e0=110  game 142  ours 200  1.41
  e0=120  game 122  ours 126  1.03
  e0=150  game 117  ours 117  1.00
  e0=200  game  97  ours  97  1.00

A clean edge at 120. At or above it every level is 1.00-1.04 AND the same
cells (both/game > 0.9), not merely the same count; below it every level is
1.20-1.49. Worst high 1.04 vs best low 1.20, so this is a threshold, not a
drift - which is why the spec asserts the GAP rather than two bounds.

The edge is not arbitrary. vulcanus_elev is

  vulcanus_elevation_offset
    + lerp(lerp(120 * vulcanus_basalt_lakes_multisample,
                20 + vulcanus_mountains_func * ..._multiplier,
                vulcanus_mountains_biome),
           vulcanus_ashlands_func, vulcanus_ashlands_biome)

and vulcanus_basalt_lakes is a min(1, ...), so the basalt-lakes branch
SATURATES AT EXACTLY 120. Everything above 120 comes from the mountains and
ashlands branches - no multisample anywhere in them - and the port reproduces
those exactly. Everything below is governed by
vulcanus_basalt_lakes_multisample: the only multisample in the chain, and the
only term with no Nauvis counterpart.

So the residual is that one term, and the port is exact everywhere else in the
field. That is a much smaller target than "the Vulcanus elevation".

The mechanism to suspect is the one the primitive's own docs describe: it
evaluates "in a separate noise program with a larger grid" whose "sub-grids
are copied to the main program". The cliff generator walks the 4-tile corner
lattice; calculate_tile_properties does not - and that is the channel
vulcanus-multisample-NOTES measured multisample(e,dx,dy) == e(x+dx,y+dy)
through, and the channel every elevation fixture was captured through. A min()
of four samples is an erosion operator, so a coarser effective grid smooths
the field exactly the way a 40% over-placement implies.

What this does NOT say: neither the multisample port nor the corner-fields
fixture is refuted. Both are correct IN THEIR CHANNEL. What has never been
tested is whether the primitive behaves the same when the calling program's
grid is 4 tiles rather than 1 - and the tile renderer, which consumes
vulcanus_elevation through that same 1-tile channel, is not implicated.

DOES NOT FIX #18.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GRx1CU29RKLsRuUAErEDRB
@wormeyman
wormeyman merged commit b07b544 into main Aug 2, 2026
2 checks passed
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.

Vulcanus cliffs: 12.5% of matched cells get the wrong cliff_orientation (residual after the placement-count fixes)

1 participant