feat(battle-node): derive Matched.seed + Ready.idxChangeSeed from master seed
InitBattle now emits Stable(master) as the shared effect seed and the master- shuffled deck as selfDeck; Swap emits each recipient's per-side IdxChange seed. BattleSession exposes + logs the master seed per battle for future replay. Updated lifecycle/dispatch/integration tests (deck assertions now permutation- based since selfDeck is shuffled). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,41 @@ public class BattleSessionDispatchTests
|
||||
"Both sides must see the same seed.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_Matched_seed_derives_from_master_via_BattleSeeds_Stable()
|
||||
{
|
||||
var (s, a, _) = NewPvpSession();
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
var routes = s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
|
||||
var body = (MatchedBody)routes[0].Frame.Body;
|
||||
Assert.That(body.SelfInfo.Seed, Is.EqualTo((long)BattleSeeds.Stable(s.MasterSeed)));
|
||||
Assert.That(body.OppoInfo.Seed, Is.EqualTo((long)BattleSeeds.Stable(s.MasterSeed)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_Ready_idxChangeSeed_derives_from_master_and_recipient_viewer()
|
||||
{
|
||||
var (s, a, b) = NewPvpSession();
|
||||
// Both sides must complete the handshake before either can swap; then a swaps, then b's
|
||||
// swap releases Ready to BOTH (mirrors Pvp_Swap_from_both_releases_Ready).
|
||||
foreach (var p in new[] { a, b })
|
||||
{
|
||||
s.ComputeFrames(p, NewEnvelope(NetworkBattleUri.InitNetwork));
|
||||
s.ComputeFrames(p, NewEnvelope(NetworkBattleUri.InitBattle));
|
||||
s.ComputeFrames(p, NewEnvelope(NetworkBattleUri.Loaded));
|
||||
}
|
||||
s.ComputeFrames(a, NewEnvelope(NetworkBattleUri.Swap)); // a swaps first
|
||||
var bRoutes = s.ComputeFrames(b, NewEnvelope(NetworkBattleUri.Swap)); // b releases both Readys
|
||||
|
||||
var readyToA = bRoutes.Single(r => ReferenceEquals(r.Target, a) && r.Frame.Uri == NetworkBattleUri.Ready);
|
||||
var readyToB = bRoutes.Single(r => ReferenceEquals(r.Target, b) && r.Frame.Uri == NetworkBattleUri.Ready);
|
||||
Assert.That(((ReadyBody)readyToA.Frame.Body).IdxChangeSeed,
|
||||
Is.EqualTo(BattleSeeds.IdxChange(s.MasterSeed, a.ViewerId)));
|
||||
Assert.That(((ReadyBody)readyToB.Frame.Body).IdxChangeSeed,
|
||||
Is.EqualTo(BattleSeeds.IdxChange(s.MasterSeed, b.ViewerId)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Pvp_InitBattle_from_B_pushes_Matched_with_A_oppoInfo_to_B_only()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user