using System.Numerics;
using AcDream.Core.Physics;
using Xunit;
namespace AcDream.Core.Tests.Physics;
///
/// #32 regression — the last-known contact plane must survive a steep
/// mid-transition contact.
///
///
/// CTransition::cliff_slide @0x0050a6d0 takes its slide direction from
/// cross(steep contact normal, last_known_contact_plane.N). It needs
/// the surface the mover was STANDING ON as the second vector. acdream's
/// CollisionInfo.SetContactPlane used to latch the last-known group on
/// every call, so by the time cliff_slide ran, last-known had already
/// been overwritten with the steep face itself — the cross product of a vector
/// with itself, which is zero. Degenerate direction, no slide applied, and the
/// player walked off the cliff.
///
///
///
/// Retail's COLLISIONINFO::set_contact_plane @0x00509d80 is 22 bytes
/// and writes the CONTACT group only. The last-known group has four writers,
/// none of them that function.
///
///
///
/// Measured live at Rithwic on 2026-08-06 with
/// ACDREAM_DUMP_EDGE_SLIDE=1: six branch2/steep-cliffslide
/// events, every one reporting
/// curN=(-0.954,0.000,0.301) lastN=(-0.954,0.000,0.301) angle=0.0000
/// apply=False with outcome degenerate-cross/last-known — the two
/// vectors identical to three decimals. That capture is decision-table row 1
/// of docs/research/2026-08-06-32-local-edge-slide-research.md, and the
/// normals below are taken from it verbatim rather than invented.
///
///
///
/// Sabotage check. Restore the four last-known writes at the tail of
/// SetContactPlane and
///
/// fails on its lastN assertion while
/// keeps passing — the pair
/// separates "the latch is gone" from "nothing writes last-known at all",
/// which a single test could not do.
///
///
public sealed class Issue32LastKnownContactPlaneTests
{
private const uint Cell = 0x0001_0001u;
/// The flat ground the mover is standing on before the rim.
private static readonly Plane Walkable = new(Vector3.UnitZ, 0f);
///
/// The Rithwic cliff face, verbatim from the live capture: a normal whose
/// Z of 0.301 is about 72.5° from horizontal, far below
/// , so it is rejected as walkable and
/// routes to the cliff-slide branch.
///
private static readonly Plane Steep =
new(Vector3.Normalize(new Vector3(-0.954f, 0f, 0.301f)), 0f);
[Fact]
public void MidTransitionSteepContact_LeavesTheWalkableLastKnownPlaneIntact()
{
var ci = new CollisionInfo();
// Start of transition: standing on flat ground. Retail's
// init_contact_plane seeds BOTH groups here, because there is no
// earlier surface to remember.
ci.InitContactPlane(Walkable, Cell);
// Mid-transition: the sweep meets the cliff face. Retail's
// set_contact_plane writes the contact group and nothing else.
ci.SetContactPlane(Steep, Cell);
Assert.True(ci.ContactPlaneValid);
Assert.Equal(Steep.Normal, ci.ContactPlane.Normal);
Assert.True(
ci.LastKnownContactPlaneValid,
"the seeded last-known plane must survive a steep contact — "
+ "cliff_slide has no second vector without it.");
Assert.Equal(Walkable.Normal, ci.LastKnownContactPlane.Normal);
// The consequence that actually mattered in play: a non-degenerate
// slide direction. With the latch in place both vectors were the steep
// face and this cross product was the zero vector.
Vector3 slide = Vector3.Cross(Steep.Normal, ci.LastKnownContactPlane.Normal);
Assert.True(
slide.Length() > 1e-4f,
$"cliff_slide's direction is degenerate: |cross| = {slide.Length():E3}. "
+ $"contactN = {Steep.Normal}, lastN = {ci.LastKnownContactPlane.Normal}.");
}
///
/// CONTROL. The seed path must still write both groups, or the test above
/// would pass simply because nothing ever populates last-known.
///
[Fact]
public void InitContactPlane_SeedsBothGroups()
{
var ci = new CollisionInfo();
Assert.False(ci.LastKnownContactPlaneValid);
ci.InitContactPlane(Walkable, Cell, isWater: true);
Assert.True(ci.ContactPlaneValid);
Assert.Equal(Walkable.Normal, ci.ContactPlane.Normal);
Assert.Equal(Cell, ci.ContactPlaneCellId);
Assert.True(ci.ContactPlaneIsWater);
Assert.True(ci.LastKnownContactPlaneValid);
Assert.Equal(Walkable.Normal, ci.LastKnownContactPlane.Normal);
Assert.Equal(Cell, ci.LastKnownContactPlaneCellId);
Assert.True(ci.LastKnownContactPlaneIsWater);
}
///
/// A second steep contact must not resurrect the defect through the
/// no-op-if-unchanged guard: the guard returns early when the CONTACT
/// group already matches, and an early return must not be the only thing
/// protecting last-known.
///
[Fact]
public void RepeatedSteepContact_StillLeavesLastKnownIntact()
{
var ci = new CollisionInfo();
ci.InitContactPlane(Walkable, Cell);
ci.SetContactPlane(Steep, Cell);
ci.SetContactPlane(Steep, Cell); // hits the no-op guard
ci.SetContactPlane(Steep, Cell);
Assert.Equal(Walkable.Normal, ci.LastKnownContactPlane.Normal);
}
}