using AcDream.Core.Physics;
using Xunit;
namespace AcDream.Core.Tests.Physics;
///
/// A6.P7 (2026-05-25) — retail-binary dispatch rule. Retail's
/// CPhysicsObj::FindObjCollisions at
/// docs/research/named-retail/acclient_2013_pseudo_c.txt:276861
/// dispatches BINARILY between "BSP-only" and "cyl + sphere" based on
/// the HAS_PHYSICS_BSP_PS flag (bit 16, hex 0x10000) in
/// PhysicsState. The flag is defined in
/// docs/research/named-retail/acclient.h:2833 and mirrored in
/// ACE at references/ACE/Source/ACE.Entity/Enum/PhysicsState.cs:24
/// as HasPhysicsBSP = 0x00010000.
///
///
/// For non-PvP, non-missile movers (M1.5 scope — walking-vs-static), an
/// entity with HAS_PHYSICS_BSP_PS in its state tests its BSP exclusively
/// — the foot cyl is NEVER tested. The closed cottage door (state
/// 0x10008 = STATIC | REPORT_COLLISIONS | HAS_PHYSICS_BSP)
/// hits this branch.
///
///
///
/// Pre-A6.P7: our dispatcher iterates every ShadowEntry
/// independently and tests both the cyl AND the BSP for a door. The
/// cyl's radial normal contaminates the slide direction at NE/SE
/// approach headings (see
/// docs/research/2026-05-25-a6-door-cyl-retail-dispatch-investigation.md).
///
///
///
/// Post-A6.P7: the dispatcher consults
/// on each cyl/sphere
/// entry and skips it when the entity has BSP, matching retail.
///
///
public class A6P7DispatchRulesTests
{
///
/// Retail bit constant HAS_PHYSICS_BSP_PS = 0x10000
/// (acclient.h:2833) and ACE's HasPhysicsBSP = 0x00010000
/// (PhysicsState.cs:24) must match the value we expose on
/// .
///
[Fact]
public void PhysicsStateFlags_HasPhysicsBsp_Is_Bit_16()
{
Assert.Equal(0x00010000u, (uint)PhysicsStateFlags.HasPhysicsBsp);
}
///
/// The dispatch predicate maps directly from retail's branch at
/// acclient_2013_pseudo_c.txt:276861:
///
/// ((state & 0x10000) == 0 || ebp_1 != 0 || eax_12 != 0)
/// → cyl + sphere path
/// else
/// → BSP-only path
///
/// For M1.5 scope ebp_1 (PvP-target-player) and eax_12
/// (missile_ignore) are treated as false. The predicate reduces to:
/// "BSP-only iff HAS_PHYSICS_BSP_PS is set".
///
[Theory]
[InlineData(0x00010008u, true)] // closed cottage door — STATIC | REPORT | HAS_BSP
[InlineData(0x00010000u, true)] // bare HAS_BSP
[InlineData(0x00110000u, true)] // HAS_BSP | CLOAKED
[InlineData(0x00000008u, false)] // creature — REPORT_COLLISIONS only
[InlineData(0x00000000u, false)] // empty state
[InlineData(0x0000FFFFu, false)] // every bit BELOW 0x10000 set
public void BspOnlyDispatch_RespectsHasPhysicsBspFlag(
uint entityState, bool expected)
{
Assert.Equal(expected, Transition.BspOnlyDispatch(entityState));
}
}