acdream/tests/AcDream.Core.Tests/Physics/WeenieErrorCodeTableTests.cs
Erik 8664959152 feat(R3-W1): retail state completion — action FIFOs, MovementParameters, MotionNode, WeenieError renumber (closes J2, J16-codes)
InterpretedMotionState + the unified RawMotionState (LegacyRawMotionState
folded away) gain retail's action FIFO + ApplyMotion/RemoveMotion, ported
verbatim from the raw named decomp (0x0051e790/0x0051eb60 region, pc
293252-293703) including two genuine retail quirks pinned by tests and
independently re-verified against the raw text before commit:
- RawMotionState::ApplyMotion's RunForward (0x44000007) dead branch — a
  cycle-class apply of literal RunForward writes NOTHING (retail encodes
  run as WalkForward + HoldKey_Run on the raw state; same family as the
  D6 apply_run_to_command early-return).
- InterpretedMotionState::RemoveMotion's exact-match-only TurnRight/
  SideStepRight handling (left variants fall through to the style/
  forward branches).

MovementParameters verbatim (A4 pin): 18 named flags per the absolute
mask table, ctor = 0x1EE0F expansion + distance_to_object 0.6 /
fail_distance FLT_MAX / speed 1 / walk_run_threshhold 15 / hold_key
Invalid — with the two ACE-divergence traps ported RETAIL-side
(can_charge FALSE where ACE defaults true; threshold 15.0 not 1.0).
MotionNode {ContextId, Motion, JumpErrorCode} (acclient.h:53293) — the
pending_motions node W2 consumes.

WeenieError renumbered to retail's numeric semantics (A10 table):
NotGrounded=0x24, GeneralMovementFailure 0x24→0x47, new 0x3f/0x40/0x41
combat-stance rejects + 0x42 chat-emote + 0x45 action-depth; the
airborne jump/action returns corrected 0x48→0x24 per the A10 sweep
(incl. jump_is_allowed's null-physics-obj 0x24-not-8 divergence from
ACE). Codes are local-only — wire untouched.

Outbound packer proof: RawMotionStatePacker unmodified; all 6
golden-byte RawMotionStatePackTests pass unmodified. TS-24 register row
updated (capability landed; outbound wiring still open).

Implemented by a dedicated agent against the W0-pinned spec; quirks,
scope, and suite independently verified. Full suite green: 3,531
(374+425+713+2015+4 pre-existing skips).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 22:12:33 +02:00

81 lines
3 KiB
C#

using AcDream.Core.Physics;
using Xunit;
namespace AcDream.Core.Tests.Physics;
/// <summary>
/// R3-W1 — pins <see cref="WeenieError"/>'s numeric values against the
/// definitive retail table in
/// docs/research/2026-07-02-r3-motioninterp/W0-pins.md §A10 (an exhaustive
/// sweep of every <c>return &lt;code&gt;</c> site across raw 304908-306277 +
/// 300150-300540: 19 return sites + 1 store site, all attributed). These
/// codes are local-only (never on the wire), so the renumber from the
/// pre-R3 shuffled names is a safe rename — this test is the single
/// source of truth that a future edit can't silently un-pin.
/// </summary>
public sealed class WeenieErrorCodeTableTests
{
[Fact]
public void None_Is0x00()
=> Assert.Equal(0x00u, (uint)WeenieError.None);
[Fact]
public void NoPhysicsObject_Is0x08()
=> Assert.Equal(0x08u, (uint)WeenieError.NoPhysicsObject);
[Fact]
public void NotGrounded_Is0x24()
=> Assert.Equal(0x24u, (uint)WeenieError.NotGrounded);
[Fact]
public void CrouchInCombatStance_Is0x3f()
=> Assert.Equal(0x3fu, (uint)WeenieError.CrouchInCombatStance);
[Fact]
public void SitInCombatStance_Is0x40()
=> Assert.Equal(0x40u, (uint)WeenieError.SitInCombatStance);
[Fact]
public void SleepInCombatStance_Is0x41()
=> Assert.Equal(0x41u, (uint)WeenieError.SleepInCombatStance);
[Fact]
public void ChatEmoteOutsideNonCombat_Is0x42()
=> Assert.Equal(0x42u, (uint)WeenieError.ChatEmoteOutsideNonCombat);
[Fact]
public void ActionDepthExceeded_Is0x45()
=> Assert.Equal(0x45u, (uint)WeenieError.ActionDepthExceeded);
[Fact]
public void GeneralMovementFailure_Is0x47()
=> Assert.Equal(0x47u, (uint)WeenieError.GeneralMovementFailure);
[Fact]
public void YouCantJumpFromThisPosition_Is0x48()
=> Assert.Equal(0x48u, (uint)WeenieError.YouCantJumpFromThisPosition);
[Fact]
public void CantJumpLoadedDown_Is0x49()
=> Assert.Equal(0x49u, (uint)WeenieError.CantJumpLoadedDown);
/// <summary>
/// Every code in the A10 table in one pass — guards against a
/// future partial edit desyncing an individual test above from the
/// enum declaration.
/// </summary>
[Theory]
[InlineData(WeenieError.None, 0x00u)]
[InlineData(WeenieError.NoPhysicsObject, 0x08u)]
[InlineData(WeenieError.NotGrounded, 0x24u)]
[InlineData(WeenieError.CrouchInCombatStance, 0x3fu)]
[InlineData(WeenieError.SitInCombatStance, 0x40u)]
[InlineData(WeenieError.SleepInCombatStance, 0x41u)]
[InlineData(WeenieError.ChatEmoteOutsideNonCombat, 0x42u)]
[InlineData(WeenieError.ActionDepthExceeded, 0x45u)]
[InlineData(WeenieError.GeneralMovementFailure, 0x47u)]
[InlineData(WeenieError.YouCantJumpFromThisPosition, 0x48u)]
[InlineData(WeenieError.CantJumpLoadedDown, 0x49u)]
public void A10Table_EveryCode_MatchesRetailNumericValue(WeenieError code, uint expected)
=> Assert.Equal(expected, (uint)code);
}