test(physics): harden TS-4 production chronology

This commit is contained in:
Erik 2026-07-31 14:08:51 +02:00
parent 75b6f6b6c9
commit d3c0d9ec0e
5 changed files with 807 additions and 101 deletions

View file

@ -6,13 +6,10 @@ using Xunit.Abstractions;
namespace AcDream.Core.Tests.Physics;
/// <summary>
/// Campaign P Slice 2B's production-shaped steep-roof control. It carries
/// contact state between 30 Hz resolves exactly as the live PhysicsBody path
/// does, so the nested edge/StepDown dispatcher can turn a vertical landing
/// into retail's downhill response instead of the old under-modeled fixed
/// point. The paired graph/flat direction matrix in
/// <see cref="RetailEdgeResponseOrderingTests"/> covers vertical, inward,
/// tangential, uphill, downhill, wall, roof, and ledge histories.
/// Historical resolver-only steep-roof control retained for the original
/// half-second wedge signature. The authoritative production chronology and
/// graph/flat direction matrix live in
/// <see cref="Ts4ProductionQuantumConformanceTests"/>.
/// </summary>
public class Ts4SteepRoofWedgeCaptureTests
{
@ -21,7 +18,7 @@ public class Ts4SteepRoofWedgeCaptureTests
private const uint CellId = 0xA9B40001u;
private const int TicksPerSecond = 30; // #32 L.5 retail physics tick rate
private const int MaxTicks = 6 * TicksPerSecond;
private const int MaxTicks = 3 * TicksPerSecond;
private const int WedgeTickThreshold = 15; // 0.5 s of zero motion == wedged
private const float WedgeEpsilon = 0.001f; // 1 mm
@ -74,12 +71,12 @@ public class Ts4SteepRoofWedgeCaptureTests
/// <summary>
/// Falls a player-flagged mover from directly above the slope and carries
/// each frame's contact state into the next frame, matching the production
/// PhysicsBody path. The exact edge/step-down chain must move the body
/// downhill and onto the reference floor without a half-second wedge.
/// resolver contact bits between frames. Within the original three-second
/// capture window it must keep making downhill progress and never enter
/// the reported half-second fixed point.
/// </summary>
[Fact]
public void FallOntoSteepSlope_PureVertical_NeverWedgesAndReachesFloor()
public void FallOntoSteepSlope_PureVertical_NeverWedgesWithinThreeSeconds()
{
var engine = MakeSlopeEngine();
float r = BSPStepUpFixtures.SphereRadius;
@ -97,8 +94,8 @@ public class Ts4SteepRoofWedgeCaptureTests
float fallVelocityZ = 0f;
uint cell = CellId;
Vector3 start = pos;
int frozenStreak = 0;
bool reachedFloor = false;
for (int tick = 0; tick < MaxTicks; tick++)
{
@ -148,15 +145,10 @@ public class Ts4SteepRoofWedgeCaptureTests
Assert.True(frozenStreak <= WedgeTickThreshold,
$"Body froze for {frozenStreak} ticks at {pos}.");
if (pos.X < 0f && pos.Z <= r + 0.05f)
{
reachedFloor = true;
break;
}
}
Assert.True(reachedFloor,
$"The production-shaped vertical trace did not reach the floor within " +
$"{MaxTicks} ticks; final=({pos.X:F3},{pos.Y:F3},{pos.Z:F3}).");
Assert.True(pos.X < start.X - 0.10f,
$"The resolver-only trace made no downhill progress within " +
$"{MaxTicks} ticks; start={start}, final={pos}.");
}
}