docs(cliffs): read crossingsForChunk whole - it matches the port (#18) - #77
Merged
Conversation
Records the last unread function in the cliff path (0x10160c9cc, 2244 bytes). Every structural element agrees with what is ported, so these are now confirmed rather than assumed: the bare sample lattice (chunkX*32 + i*grid, no grid_offset), the smoothing knots (lo = i & ~3, hi = min(lo + 4, w - 1), t = (i & 3) / (hi - lo), blend s*bilerp + (1-s)*raw with s at settings+0xd0), which register is smoothed (0x1e0) versus read raw (0x1e4), crossesCliff inlined with the cliffiness > 0.5 gate, both edge array shapes and strides, and the tail call to fixImpossibleCells(this, false). Three more causes falsified with denominators. float vs double is not it: replaying the whole rule with Math.fround at every step changes nothing, 0 of 12,480 raw edges per region and identical placement and orientation. The engine's (int) truncation where the port floors is a real textual difference but inert - the two differ only when max(a,b) < elevation_0, where neither sign case can fire. And the smoothing model is right IN KIND rather than merely unfalsified: cliff_smoothing = 0 makes the orientation error much worse (29.8 -> 71.3%, 8.1 -> 64.1%, 11.7 -> 54.5%). Also notes that the float table where a smoothing-weight table would live is just 0.0..31.0, the SIMD lane-index constant. What survives: fixImpossibleCells in detail, and the choice of expression - which no substitution can test, because the corner-field fixtures capture vulcanus_elevation and cliffiness_basic BY NAME. If a different expression compiles into settings+0x1e0, the substitution agrees with the port for the same reason the port is wrong. Settle that by reading 0x1e0, not by substituting more values. Documentation only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013eczw9uoWDfN6Wc6kA7UBY
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documentation only. Records the last unread function in the cliff path, plus three more falsified causes and two closed leads.
crossingsForChunkread whole - and it matches0x10160c9cc, 2244 bytes, decompiled entire. Every structural element agrees with what is ported, so these are now confirmed rather than assumed:(chunkX*32 + i*grid, chunkY*32 + j*grid)over a 9x9 corner block - nogrid_offsetanywhere. fix(cliffs): sample the fields at the game's lattice - Nauvis is now EXACT (#18) #70's finding, seen from the producing side.lo = i & ~3,hi = lo + 4clamped tow - 1(theuVar25 = uVar25 - 1before the loop is where the 7 comes from),t = (i & 3) / (hi - lo), blends * bilerp + (1 - s) * rawwithsatsettings + 0xd0.0x1e0(elevation) into a fresh array;0x1e4(cliffiness) read raw at the same indices.crossesCliffinlined, matching including thecliffinessAvg > 0.5gate.(h+1) x watx + w*y, vertical(w+1) x hatx + y*(w+1), withgenerateCliffsreading L/R from vertical and T/B from horizontal.fixImpossibleCells(this, false).Three more causes falsified, with denominators
floatvsdoubleis not it. The engine works at 32 bits and the port at 64, which fits the signature (one corner flipping near a band boundary). Replaying the whole rule withMath.froundat every step changes nothing: 0 of 12,480 raw edges per region, identical placement and orientation.(int)vsMath.floordifference is real but inert. The engine truncates toward zero where the port floors. They differ only whenmax(a,b) < elevation_0, and there both give "no crossing" - the band lands at or belowelevation_0and both corners are below it, so neither sign case can fire.cliff_smoothing = 0makes the orientation error much worse - 29.8% → 71.3%, 8.1% → 64.1%, 11.7% → 54.5%. That is the control the disassembly reading needed.Also: the float table where a smoothing-weight table would live (
0x102cf9cf0) is just0.0..31.0, the SIMD lane-index constant.Two leads closed from documentation
vulcanus_elevationandcliffiness_basicby name. Closed from the data:planet-map-gen.lua:13-14routescliffiness = "cliffiness_basic"andcliff_elevation = "cliff_elevation_from_elevation", and that is literallyexpression = "elevation". Worth knowing the alternative was live: the defaultcliff_elevationiscliff_elevation_nauvis, a completely different field - the same shape of trap as thecliff_smoothingdefault that cost Vulcanus cliffs: 12.5% of matched cells get the wrong cliff_orientation (residual after the placement-count fixes) #18 two months.C(4,2)*2*2 = 24possible two-crossing codes, so 12 two-crossing codes are illegal. A count-based predicate would leave those in, andgenerateCliffsasserts and aborts on an illegal code.FFF #386 corroborates two things we had only from the binary. Crater cliffs exist because "the collision boxes are always rectangles so hitting invisible corners is annoying" - developers stating outright that cliff collision boxes are plain rectangles, which is independent confirmation for
CLIFF_ORIENTATION_COLLISION_BOXand therotbbAABB derivation. And "a ring of special cliffs where sections of the ring can randomly be removed" is not a lattice structure, which is why their positions are fractional. They also cannot be #18's residual, stated with the count rather than by argument:[0,0]has zero crater-cliffs and[1500,1500]has zero; all 8 are in[-1200,800].Where #18 stands
Fields exact (including at
[0,0]), rule structurally confirmed, precision irrelevant, smoothing confirmed, expression choice confirmed - and 12.5% of shared cells still carry the wrong crossings. What survives isfixImpossibleCellsin detail: it accounts for only 1.8 of the 12.5 points as ported, but "our sweep differs subtly from the game's" is not excluded by that - a different sweep could be both closer and worth more. FFF #219's note that the pass prioritises chunk boundaries agrees with the port's "a boundary edge is not clearable".pnpm run verifygreen: 304 files checked, 1279 tests.🤖 Generated with Claude Code
https://claude.ai/code/session_013eczw9uoWDfN6Wc6kA7UBY