You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(cliffs): rotbb collision boxes are ROTATED, not their bounding box (#84) (#88)
The lava perimeter that cost 13 real Vulcanus cliffs their placement was never
the lava mask. It was the collision box's shape.
rotbb(x, y, size, intersect) (entity-util.lua:9) returns
{{cx-x_dist, cy-y_dist}, {cx+x_dist, cy+y_dist}, 1/8} - a rectangle PLUS an
orientation of 1/8, i.e. 45 degrees. Sixteen of the twenty cliff orientations are
built with it; only the four straight ones are axis-aligned. The port kept only
the bounding box, which overruns the rotated rectangle at all four corners, so it
rejected cliffs on lava the game never looks at.
CLIFF_ORIENTATION_COLLISION_BOX remains the correct BROAD phase - wouldCollide
derives its tile rect from a fixed-point floor over an inclusive rectangle, which
cliffCollisionTileBox reproduces. cliffBoxCoversTile adds the narrow phase
(separating-axis over the two world axes and the rectangle's own two).
| | AABB (before) | oriented (after) |
| ------------------- | ------------- | ---------------- |
| recall | 0.9675 | 0.9758 |
| precision | 0.9743 | 0.9727 |
| [0,0] recall | 0.9788 | 1.0000 |
| level-sweep recall | 0.951 @ lvl20 | ~1.000 everywhere |
Clears 13 of 13 false rejections while keeping 182 of the 185 rejections that
remove genuine false positives - the correct shape, not a loosening that trades
precision for recall.
How it was found, because the route matters more than the fix. The standing
explanation - in this spec's own comments and in the notes - was that the tile
resolver was "off by about one tile SOMEWHERE". A new dense capture
(oracle-vulcanus-lava-boundary, radius-4 neighbourhoods around the 35 accusing
tiles) found ZERO lava mismatches over 994 positions and 35/35 at the accusing
tiles themselves. The mask was innocent. It was worth capturing because the
existing 381-position survey structurally could not answer the question: its
sensitivity was measured by planting scale factors on lava's probability, and
1.02 and 1.2 both still pass.
Two corrections this forces:
- PR #86's "gap 0.067 -> 0.018" is wrong; it is 0.024. That was measured with the
over-aggressive AABB rejection, which deleted cells the game keeps and so
flattered exactly the ratio it reported. A too-strong correction hides the
thing it is correcting. The residual below elevation 120 is real, still open,
and now pure over-placement with no recall cost.
- "All 13 sit at Chebyshev depth 1 in our lava" was a true measurement that
pointed at the wrong suspect. The box's four corners ARE its perimeter, so a
corner-shaped box error produces the same signature a one-tile-fat mask would.
A statistic can only rule a suspect out if it would come out DIFFERENTLY for
each candidate.
Checked and cleared on the way: the inclusive-floor fringe is real engine
behaviour (disassembly), and chunk ordering is not it (2 of 13 cross a chunk
boundary against 50 of 185 in the control - less than baseline). 6 of the 13 also
carry a wrong orientation (~23x enrichment over the 2.0% base rate), always a
smaller -to-none variant of ours; those belong to the standing orientation
residual, which is unchanged.
Guards: cliffOrientedBox.spec.ts pins the geometry, and the levels sweep asserts
per-level recall > 0.99. Both verified non-vacuous by planting AABB behaviour -
they fail with "expected 0 to be greater than 20" and "expected 0.9514 to be
greater than 0.99".
Claude-Session: https://claude.ai/code/session_01WRKSNgkidxc6daeHGJHqpt
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments