acdream/tests/AcDream.App.Tests/Rendering/Walk/WalkTraceConformanceTests.cs
Erik c1a029edf9 feat(render) Campaign FW1: NINE of ten fixtures conformant - the degrade arm
The moving-fixture divergence was the building degrade ladder:
GfxObjDegradeInfo::get_degrade @0x0051e4b0 (Ghidra-verified - BN's
FPU-flag pseudo-C misread BOTH arm selection and one formula) slides
each level's threshold from ideal toward MAX as the multiplier
approaches 1, and the live client runs the positive arm at ~0.99, so
level 0's portal-bearing BSP survives to ~max_dist (48 for the Holtburg
cottages), not ideal (24). The recon note's "deg_mul = -0.99" was a
sign misread; the negative arm's threshold slides toward MIN and
contradicts the fixtures from both directions. With the two-arm port,
holtburg-walkout, holtburg-transitions, and holtburg-walkabout pass
every pairable frame - the walkout-F2 microscope's prediction
(103,100 | 100x3 | 124 through the cottage exit views) landed exactly.

Also this round, falsified and reverted: a BN-driven swap of the
portal walker's negative/in-plane arms (Ghidra shows side 1 = negative
EMITS, side 2 = in-plane does not - the original port was correct; the
swap broke four fixtures). The walker docs and unit tests now pin the
Ghidra-verified truth table.

Parked with findings: foundry-entry F67 (right flood set, one
plane-side classification at the +/-eps boundary orders 11d before
116/118) and doorway-still (retail shows zero floods at a pose one
meter from walkout-F2's flooding pose; multi-portal clip boundary).

Suites: Walk 124/3 skips; hermetic 6,687/0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 11:34:45 +02:00

232 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AcDream.App.Tests.Rendering;
using AcDream.App.Rendering.Walk;
using DatReaderWriter;
using DatReaderWriter.Options;
namespace AcDream.App.Tests.Rendering.Walk;
/// <summary>
/// FW1's conformance gate, first slice: replay pose-stamped oracle
/// fixtures through the ported walk and require the identical event
/// sequence. The projection-light interior fixtures gate first
/// (docs/research/2026-08-30-fw-walk-oracle/README.md, posed round);
/// the outdoor/landscape fixtures join as the landscape world build
/// lands.
/// </summary>
[Trait("Lane", "InstalledDat")]
public sealed class WalkTraceConformanceTests
{
private sealed class Recorder : IWalkEventSink
{
public readonly List<WalkEvent> Events = new();
public void Emit(in WalkEvent walkEvent) => Events.Add(walkEvent);
}
private static DatCollection OpenDats()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null)
{
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory; see docs/release-gate.md.");
}
return new DatCollection(datDir!, DatAccessType.Read);
}
[Fact]
public void Street_outdoor_first_frame_diff()
{
// The first landscape-involving conformance case: diff-first (the
// assert prints both signatures on mismatch for adjudication).
IReadOnlyList<WalkOracleFrame> frames =
WalkOracleTrace.Load("posed/holtburg-street-outdoor");
Assert.NotEmpty(frames);
using DatCollection dats = OpenDats();
WalkOracleFrame frame = frames[1]; // frame 2: pose settled (marker timing)
Assert.NotNull(frame.Pose);
WalkLandscapeDatBuilder.BuiltWorld world =
WalkLandscapeDatBuilder.Build(dats, frame.Pose!.CellId, frame.Pose.Origin);
var ctx = new WalkTraceReplayContext(frame.Pose, world.Cells)
{
Buildings = world.Buildings,
};
var walk = new RetailFrameWalk();
var recorder = new Recorder();
walk.WalkFrame(frame.Pose.CellId, null, world.Landscape, ctx, recorder);
string expected = WalkTraceReplayContext.Signature(frame);
string actual = WalkTraceReplayContext.Signature(recorder.Events);
Assert.True(
expected == actual,
$"walk diverged from retail\nEXPECTED: {expected}\nACTUAL: {actual}");
}
[Fact(Skip = "FW1 residue (2026-08-30 v3): at the doorway pose the replay "
+ "floods 001e(103,100×4)/0026(124)/002f — the EXACT set retail shows at "
+ "walkout F2 one meter away — but retail shows ZERO floods here (F2F6, "
+ "static pose). Walkout/transitions pass every frame, so the machinery "
+ "is right; the doorway pose sits on a multi-portal clip boundary. "
+ "Adjudicate the exit-view extents vs the portal projections.")]
public void Doorway_still_first_frame_diff()
{
// Interior flood adjudication: DI + DC(ov=2, n=3) + the landscape
// through two exit views — tests the flood depth in isolation from
// the building look-in machinery.
IReadOnlyList<WalkOracleFrame> frames =
WalkOracleTrace.Load("posed/holtburg-doorway-still");
Assert.NotEmpty(frames);
using DatCollection dats = OpenDats();
WalkOracleFrame frame = frames[1];
Assert.NotNull(frame.Pose);
WalkLandscapeDatBuilder.BuiltWorld world =
WalkLandscapeDatBuilder.Build(dats, frame.Pose!.CellId, frame.Pose.Origin);
var ctx = new WalkTraceReplayContext(frame.Pose, world.Cells)
{
Buildings = world.Buildings,
};
WalkCell camera = Assert.Contains(frame.Pose.CellId, world.Cells);
var walk = new RetailFrameWalk();
var recorder = new Recorder();
walk.WalkFrame(frame.Pose.CellId, camera, world.Landscape, ctx, recorder);
string expected = WalkTraceReplayContext.Signature(frame);
string actual = WalkTraceReplayContext.Signature(recorder.Events);
Assert.True(
expected == actual,
$"walk diverged from retail\nEXPECTED: {expected}\nACTUAL: {actual}");
}
[Theory]
[InlineData("posed/terrace-center")]
[InlineData("posed/terrace-edge")]
[InlineData("posed/cathedral-arrival")]
public void Still_fixture_first_frame_reproduces_exactly(string fixture)
{
IReadOnlyList<WalkOracleFrame> frames = WalkOracleTrace.Load(fixture);
Assert.NotEmpty(frames);
using DatCollection dats = OpenDats();
WalkOracleFrame frame = frames[1];
Assert.NotNull(frame.Pose);
WalkLandscapeDatBuilder.BuiltWorld world =
WalkLandscapeDatBuilder.Build(dats, frame.Pose!.CellId, frame.Pose.Origin);
var ctx = new WalkTraceReplayContext(frame.Pose, world.Cells)
{
Buildings = world.Buildings,
};
WalkCell? camera = (frame.Pose.CellId & 0xFFFFu) >= 0x100
? Assert.Contains(frame.Pose.CellId, world.Cells)
: null;
var walk = new RetailFrameWalk();
var recorder = new Recorder();
walk.WalkFrame(frame.Pose.CellId, camera, world.Landscape, ctx, recorder);
string expected = WalkTraceReplayContext.Signature(frame);
string actual = WalkTraceReplayContext.Signature(recorder.Events);
Assert.True(
expected == actual,
$"walk diverged from retail ({fixture})\nEXPECTED: {expected}\nACTUAL: {actual}");
}
[Theory(Skip = "FW1 residue (2026-08-30 v3): F67 floods the right SET through "
+ "building a9b40036 but orders 11d,11b before 116/118 — retail (F67+F68, "
+ "identical camera) orders 116,118,11d. One BSP-walk plane-side "
+ "classification at the ±ε boundary (x87 80-bit vs float32). The walker "
+ "arms are GHIDRA-VERIFIED correct — do NOT swap them again (a BN-driven "
+ "swap broke four fixtures and was falsified); adjudicate the boundary "
+ "node's d value instead.")]
[InlineData("posed/foundry-entry")]
public void Moving_fixture_parked_residue(string fixture)
=> MovingFixtureReplay(fixture);
[Theory]
[InlineData("posed/holtburg-walkout")]
[InlineData("posed/holtburg-transitions")]
[InlineData("posed/holtburg-walkabout")]
public void Moving_fixture_reproduces_every_pairable_frame(string fixture)
=> MovingFixtureReplay(fixture);
private void MovingFixtureReplay(string fixture)
{
// Marker timing: the pose stamped at frame N+1 is the camera state
// frame N drew with (fixture README) — pair events(N) with
// pose(N+1). One walk + one landscape carry state across frames,
// reproducing retail's cross-frame caches (the stale cell-order
// quirk included).
IReadOnlyList<WalkOracleFrame> frames = WalkOracleTrace.Load(fixture);
Assert.True(frames.Count >= 3);
using DatCollection dats = OpenDats();
WalkOraclePose anchor = frames[1].Pose!;
WalkLandscapeDatBuilder.BuiltWorld world =
WalkLandscapeDatBuilder.Build(dats, anchor.CellId, anchor.Origin);
var walk = new RetailFrameWalk();
for (int n = 1; n < frames.Count - 1; n++)
{
WalkOracleFrame frame = frames[n];
string expected = WalkTraceReplayContext.Signature(frame);
// The marker dumps the PREVIOUS frame's camera, so frame N's
// true camera state lies between pose(N) and pose(N+1) — a
// capture artifact, not a port ambiguity. A frame passes when
// the replay matches under either adjacent pose.
string? firstActual = null;
bool matched = false;
foreach (WalkOraclePose pose in new[] { frames[n + 1].Pose!, frame.Pose! })
{
Assert.NotNull(pose);
WalkLandscapeDatBuilder.SetViewer(world.Landscape, pose.CellId, pose.Origin);
var ctx = new WalkTraceReplayContext(pose, world.Cells)
{
Buildings = world.Buildings,
};
WalkCell? camera = null;
if ((pose.CellId & 0xFFFFu) >= 0x100)
{
Assert.True(
world.Cells.TryGetValue(pose.CellId, out camera),
$"frame {frame.Number}: interior camera cell {pose.CellId:x8} not loaded");
}
var recorder = new Recorder();
walk.WalkFrame(pose.CellId, camera, world.Landscape, ctx, recorder);
string actual = WalkTraceReplayContext.Signature(recorder.Events);
firstActual ??= actual;
if (actual == expected)
{
matched = true;
break;
}
}
Assert.True(
matched,
$"frame {frame.Number} diverged under both adjacent poses ({fixture})\n"
+ $"EXPECTED: {expected}\nACTUAL: {firstActual}");
}
}
[Fact]
public void Foundry_deep_reproduces_every_complete_frame_exactly()
{
IReadOnlyList<WalkOracleFrame> frames = WalkOracleTrace.Load("posed/foundry-deep");
Assert.NotEmpty(frames);
using DatCollection dats = OpenDats();
Dictionary<uint, WalkCell> cells =
WalkWorldDatAdapter.BuildInteriorCells(dats, 0xA9B40000u);
var landscape = new WalkLandscape { MidWidth = 1, Blocks = new WalkLandBlock?[1] };
foreach (WalkOracleFrame frame in frames)
{
Assert.NotNull(frame.Pose);
WalkCell camera = Assert.Contains(frame.Pose!.CellId, cells);
var ctx = new WalkTraceReplayContext(frame.Pose, cells);
var walk = new RetailFrameWalk();
var recorder = new Recorder();
walk.WalkFrame(frame.Pose.CellId, camera, landscape, ctx, recorder);
Assert.Equal(
WalkTraceReplayContext.Signature(frame),
WalkTraceReplayContext.Signature(recorder.Events));
}
}
}