diff --git a/SVSim.BattleNode/Sessions/Dispatch/Handlers/JudgeHandler.cs b/SVSim.BattleNode/Sessions/Dispatch/Handlers/JudgeHandler.cs index 4ba8146..0e2b973 100644 --- a/SVSim.BattleNode/Sessions/Dispatch/Handlers/JudgeHandler.cs +++ b/SVSim.BattleNode/Sessions/Dispatch/Handlers/JudgeHandler.cs @@ -1,4 +1,5 @@ using SVSim.BattleNode.Protocol; +using SVSim.BattleNode.Protocol.Bodies; namespace SVSim.BattleNode.Sessions.Dispatch.Handlers; @@ -6,9 +7,18 @@ internal sealed class JudgeHandler : IFrameHandler { public IReadOnlyList Handle(FrameDispatchContext ctx) { - // Only a scripted-bot Judge is forwarded. A real player's Judge has no routing rule (drops). + // Scripted-bot Judge (test stub): forward verbatim (carries the {spin} shape already). if (ctx.IsScriptedBot(ctx.From)) return new[] { new DispatchRoute(ctx.Other, ctx.Env, false) }; + + // PvP: active player's Judge{battleCode} -> opponent {spin} (RNG catch-up; spin=0 for the + // deterministic-turn slice). Receiving Judge starts the opponent's own turn. + if (ctx.Type == BattleType.Pvp && ctx.BothAfterReady()) + { + var frame = ctx.Env with { Body = new JudgeBody(Spin: 0) }; + return new[] { new DispatchRoute(ctx.Other, frame, false) }; + } + return Array.Empty(); } } diff --git a/SVSim.UnitTests/BattleNode/Sessions/BattleSessionDispatchTests.cs b/SVSim.UnitTests/BattleNode/Sessions/BattleSessionDispatchTests.cs index ed3be3a..68c8c2f 100644 --- a/SVSim.UnitTests/BattleNode/Sessions/BattleSessionDispatchTests.cs +++ b/SVSim.UnitTests/BattleNode/Sessions/BattleSessionDispatchTests.cs @@ -399,6 +399,22 @@ public class BattleSessionDispatchTests Assert.That(body.Spin, Is.EqualTo(0)); } + [Test] + public void Pvp_Judge_from_A_emits_spin0_to_B() + { + var (s, a, b) = NewPvpSession(); + DriveToAfterReady(s, a); + DriveToAfterReady(s, b); + + var routes = s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.Judge)); + + Assert.That(routes.Count, Is.EqualTo(1)); + Assert.That(routes[0].Target, Is.SameAs(b)); + Assert.That(routes[0].Frame.Uri, Is.EqualTo(NetworkBattleUri.Judge)); + var body = (SVSim.BattleNode.Protocol.Bodies.JudgeBody)routes[0].Frame.Body; + Assert.That(body.Spin, Is.EqualTo(0)); + } + [Test] public void Pvp_PlayActions_synthesizes_knownList_from_sender_deck() {