From d4869154d2485f5a35951fedcb18ec54fb466318 Mon Sep 17 00:00:00 2001 From: Erik Date: Sun, 5 Jul 2026 19:15:05 +0200 Subject: [PATCH] fix #137 (seam shake): CheckOtherCells queried remaining cells at a stale pre-climb center MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The P2 cellar-lip lesson one loop deeper. CheckOtherCells takes footCenter by value and used it for every cell in the loop — but a mid-loop query can MOVE the sphere: at the Facility Hub cell boundaries the neighbor's ramp floor full-hits, step_sphere_up climbs the foot +0.6mm and returns OK, and the loop continued querying the REMAINING cells (including the under-room, portal-ring-3) at the pre-climb height — 0.4mm inside the double-faced floor slab, grazing its underside (the under-room's ceiling) within the near-miss window. That dispatched a neg-poly step-up with a DOWNWARD normal, whose failure funneled into slide_sphere's opposing branch -> synthetic reversed-movement collision -> Collided -> revert, every frame: the seam shake (and, pre-mechanism-2-fix, the original absorbing wedge's entry). Retail check_other_cells reads the LIVE sphere_path.global_sphere for every cell (each cell's find_collisions receives the transition itself, pc:272717+). Fix: re-read footCenter = sp.GlobalSphere[0].Origin at the top of each loop iteration. All three Issue137CorridorSeamReplayTests repros un-skipped: the snapshot-exact west-boundary crossing (capture tick 4101), the east deep-straddle, and the clean-run lifecycle all GREEN. Full suites: Core 2556 / App 713 / UI 425 / Net 385, 0 failures. Visual gate pending: corridor run + the purple seam flashing re-check (expected to be the render exposing the same per-frame oscillation). Co-Authored-By: Claude Fable 5 --- docs/ISSUES.md | 14 ++++++++++++++ src/AcDream.Core/Physics/TransitionTypes.cs | 15 +++++++++++++++ .../Physics/Issue137CorridorSeamReplayTests.cs | 6 +++--- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 49c7c19a..3e6ed8f2 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -1183,6 +1183,20 @@ walls** in particular. (Symptoms not fully characterized yet: likely walking thr openings that should block / blocking at openings that should pass, and door collision not matching the door's open/closed state.) +**SEAM SHAKE FIXED (same day): the stale `footCenter` in `CheckOtherCells`' +per-cell loop** — the P2 cellar-lip lesson one loop deeper. A mid-loop +other-cell query can MOVE the sphere (the boundary full-hit dispatches +step_sphere_up; the successful climb lifts the foot +0.6 mm and returns +OK), and the remaining cells were then queried with the by-value +pre-climb center — 0.4 mm inside the floor slab, grazing the under-room's +ceiling and firing the chain below. Retail's `check_other_cells` reads the +LIVE `sphere_path.global_sphere` per cell (pc:272717+). Fix: re-read +`footCenter = sp.GlobalSphere[0].Origin` per iteration. All three +`Issue137CorridorSeamReplayTests` repros un-skipped and GREEN; full suites +green. Visual gate pending. (The step 3 "restore clobbers CheckPos" wording +below was the right CLASS but the wrong site — CheckPos was fine; the +stale copy was the loop's captured parameter.) + **GATE 2026-07-06 FAILED — THIRD MECHANISM CHARACTERIZED (the seam shake), deterministic offline repro secured:** with mechanisms 1+2 fixed the dead stop became a SHAKE at cell seams (+ purple floor flashing there — almost diff --git a/src/AcDream.Core/Physics/TransitionTypes.cs b/src/AcDream.Core/Physics/TransitionTypes.cs index cc21a953..20dcdef1 100644 --- a/src/AcDream.Core/Physics/TransitionTypes.cs +++ b/src/AcDream.Core/Physics/TransitionTypes.cs @@ -1804,6 +1804,21 @@ public sealed class Transition { if (cellId == sp.CheckCellId) continue; + // #137 seam shake (2026-07-06): a mid-loop query can MOVE the + // sphere — a Path-5 full hit dispatches step_sphere_up, and a + // successful climb lifts the foot (the 0.6 mm ramp-slab lift at + // the Facility Hub boundaries) yet returns OK, so the loop + // continues. Retail's check_other_cells reads the LIVE + // sphere_path.global_sphere for every cell (each cell's + // find_collisions receives the transition itself, pc:272717+); + // querying the remaining cells with the pre-climb center re-tests + // the boundary ~0.4 mm inside the floor slab and grazes the + // under-room's CEILING (the slab underside) — the neg-poly + // step-up-with-a-downward-normal chain that shook the player at + // every corridor seam. Same lesson as the P2 cellar-lip fix + // (RunCheckOtherCellsAndAdvance's entry refresh), one loop deeper. + footCenter = sp.GlobalSphere[0].Origin; + if ((cellId & 0xFFFFu) < 0x0100u) { var terrainWalkable = engine.SampleTerrainWalkable(footCenter.X, footCenter.Y); diff --git a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs index 42d5d28b..ae39eeba 100644 --- a/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs +++ b/tests/AcDream.Core.Tests/Physics/Issue137CorridorSeamReplayTests.cs @@ -168,7 +168,7 @@ public class Issue137CorridorSeamReplayTests /// opposing-normals branch → Collided → revert. Repeat. /// /// - [Fact(Skip = "#137 seam shake — deterministic RED repro; the post-step-up check-pos restore clobbers the lifted position (P2 stale-snapshot class). Un-skip with the fix.")] + [Fact] public void SeamShake_WestBoundary_SnapshotExact_Advances() { var datDir = FindDatDir(); @@ -255,7 +255,7 @@ public class Issue137CorridorSeamReplayTests /// frame (the "shaking at the seam" report). The deeper straddle start is /// what the original replay frame (84.638 → 85.253) didn't cover. /// - [Fact(Skip = "#137 seam shake — deterministic RED repro; the post-step-up check-pos restore clobbers the lifted position (P2 stale-snapshot class). Un-skip with the fix.")] + [Fact] public void SeamCrossing_FromDeepStraddleStart_Advances() { var datDir = FindDatDir(); @@ -285,7 +285,7 @@ public class Issue137CorridorSeamReplayTests $"reversed-movement normal = the 2026-07-06 seam shake."); } - [Fact(Skip = "#137 seam shake — deterministic RED repro; the post-step-up check-pos restore clobbers the lifted position (P2 stale-snapshot class). Un-skip with the fix.")] + [Fact] public void SeamCrossing_DoesNotPersistSyntheticSlidingNormal_AndRunContinues() { var datDir = FindDatDir();