acdream/tests/AcDream.App.Tests/Rendering/Walk/WalkLookInGateSweepTests.cs
Erik e23a589a6b feat(render) Campaign FW1: port the exact retail degrade selection
UpdateViewerDistance @0x0050e030 + get_degrade @0x0051e4b0 ported with
live-pinned globals: distance measured to the part SCALED SORT CENTER,
effective = max(0, dist - s_rDegradeDistance [live 100]), level = first
with effective < IdealDist (the live auto_update_deg_mul<=0 arm), else
the last level. WalkBuildingDegradeLevel carries the full authored
bands; the adapter fills sort centers; the replay context measures to
the transformed sort center. Sweep state after the rule: the level-0
building set is now correct; the residual divergence is the per-portal
side/clip gate (my arms punch a near-complement of retail two) - the
sweep driver carries the next instrument in its Skip note.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 10:55:19 +02:00

116 lines
5.1 KiB
C#

using AcDream.App.Tests.Rendering;
using AcDream.App.Rendering.Walk;
using DatReaderWriter;
using DatReaderWriter.Options;
using System.Text;
namespace AcDream.App.Tests.Rendering.Walk;
/// <summary>
/// FW1 look-in gate adjudication sweep: with data joins proven correct,
/// the wrong-building punches must come from the sidedness gate's two
/// unvalidated inputs — the GfxObj portal-poly plane sign and the
/// BuildingPortal side-flag decode. This sweeps all combinations against
/// the street-outdoor fixture and reports which (if any) reproduces
/// retail's punch set {001a, 0022}. Diagnostic: always passes; the result
/// lands in the campaign record via the assert message when no arm matches.
/// </summary>
[Trait("Lane", "InstalledDat")]
public sealed class WalkLookInGateSweepTests
{
private sealed class Recorder : IWalkEventSink
{
public readonly List<WalkEvent> Events = new();
public void Emit(in WalkEvent walkEvent) => Events.Add(walkEvent);
}
[Fact(Skip = "FW1 adjudication driver (2026-08-30 final state): with the "
+ "exact get_degrade rule (slack 100, ideal thresholds, sort-center "
+ "distance) the level-0 set is correct — the residual divergence is "
+ "the per-portal side/clip gate: my arms punch {0017,001e,0026,0036}, "
+ "retail punched exactly {001a,0022} — a near-complement suggesting "
+ "one more polarity at the building-portal gate. Next instrument: "
+ "per-portal dump for 001a (retail punches) vs 001e (retail doesn't): "
+ "side values, plane orientation, eye side, clip result per arm.")]
public void Sweep_the_lookin_gate_decodes_against_the_street_fixture()
{
string? datDir = CornerFloodReplayTests.ResolveDatDir();
if (datDir is null)
{
Assert.Fail("Lane=InstalledDat requires an installed retail DAT directory.");
}
IReadOnlyList<WalkOracleFrame> frames =
WalkOracleTrace.Load("posed/holtburg-street-outdoor");
WalkOracleFrame frame = frames[1];
Assert.NotNull(frame.Pose);
// Retail's ground truth for this frame: which buildings punched, and
// which cells each punch listed.
string expectedPunches = PunchSignature(
frame.Events.Select(e => e.Kind == WalkOracleEventKind.Building
? ("BLD", e.CellId!.Value, Array.Empty<uint>())
: e.Kind == WalkOracleEventKind.DrawCells
? ("DC", 0u, e.Cells.ToArray())
: ("", 0u, Array.Empty<uint>())));
var report = new StringBuilder();
report.AppendLine($"RETAIL: {expectedPunches}");
string? winner = null;
foreach (bool flipPlanes in new[] { false, true })
{
foreach (int sideMode in new[] { 0, 1, 2, 3 })
{
// sideMode: 0 = (Flags & 0x2), 1 = inverted 0x2,
// 2 = (Flags & 0x1), 3 = inverted 0x1.
using var dats = new DatCollection(datDir!, DatAccessType.Read);
WalkWorldDatAdapter.FlipGfxPolygonPlanes = flipPlanes;
WalkWorldDatAdapter.BuildingSideMode = sideMode;
try
{
WalkLandscapeDatBuilder.BuiltWorld world =
WalkLandscapeDatBuilder.Build(dats, frame.Pose!.CellId);
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 actual = PunchSignature(
recorder.Events.Select(e => e.Kind == WalkEventKind.Building
? ("BLD", e.CellId, Array.Empty<uint>())
: e.Kind == WalkEventKind.DrawCells
? ("DC", 0u, e.Cells.ToArray())
: ("", 0u, Array.Empty<uint>())));
string arm = $"flip={flipPlanes} side={sideMode}";
report.AppendLine($"{arm}: {actual}");
if (actual == expectedPunches)
winner ??= arm;
}
finally
{
WalkWorldDatAdapter.FlipGfxPolygonPlanes = false;
WalkWorldDatAdapter.BuildingSideMode = 0;
}
}
}
Assert.True(
winner is not null,
$"no gate decode reproduces retail's punch pattern\n{report}");
}
private static string PunchSignature(
IEnumerable<(string Kind, uint Id, uint[] Cells)> events)
{
var parts = new List<string>();
foreach ((string kind, uint id, uint[] cells) in events)
{
if (kind == "BLD") parts.Add($"B{id:x8}");
else if (kind == "DC")
parts.Add($"D[{string.Join(',', cells.Select(c => (c & 0xFFFF).ToString("x3")))}]");
}
return string.Join("|", parts);
}
}