/ GUNRPG.Tests / DistanceSynchronizationTests.cs
DistanceSynchronizationTests.cs
1 using GUNRPG.Core; 2 using GUNRPG.Core.Combat; 3 using GUNRPG.Core.Intents; 4 using GUNRPG.Core.Operators; 5 using Xunit; 6 7 namespace GUNRPG.Tests; 8 9 /// <summary> 10 /// Tests to ensure distance between operators is synchronized at round boundaries. 11 /// </summary> 12 public class DistanceSynchronizationTests 13 { 14 [Fact] 15 public void Distance_IsSynchronizedAtEndOfRound() 16 { 17 // Arrange - Create two operators at same distance 18 var player = new Operator("Player") 19 { 20 EquippedWeapon = WeaponFactory.CreateM15Mod0(), 21 DistanceToOpponent = 15f 22 }; 23 player.CurrentAmmo = player.EquippedWeapon!.MagazineSize; 24 25 var enemy = new Operator("Enemy") 26 { 27 EquippedWeapon = WeaponFactory.CreateM15Mod0(), 28 DistanceToOpponent = 15f 29 }; 30 enemy.CurrentAmmo = enemy.EquippedWeapon!.MagazineSize; 31 32 var combat = new CombatSystemV2(player, enemy, seed: 42); 33 34 // Act - Player moves forward, enemy stands still 35 var playerIntents = new SimultaneousIntents(player.Id) 36 { 37 Movement = MovementAction.SprintToward, 38 Primary = PrimaryAction.Fire 39 }; 40 41 var enemyIntents = new SimultaneousIntents(enemy.Id) 42 { 43 Movement = MovementAction.Stand, 44 Primary = PrimaryAction.Fire 45 }; 46 47 combat.SubmitIntents(player, playerIntents); 48 combat.SubmitIntents(enemy, enemyIntents); 49 50 // Execute until round completes 51 while (combat.Phase == CombatPhase.Executing) 52 { 53 combat.ExecuteUntilReactionWindow(); 54 } 55 56 // Assert - Both operators should have the same distance after round completes 57 Assert.Equal(player.DistanceToOpponent, enemy.DistanceToOpponent); 58 } 59 60 [Fact] 61 public void Distance_IsSynchronizedWhenCombatEnds() 62 { 63 // Arrange - Create operators where one will die 64 var player = new Operator("Player") 65 { 66 EquippedWeapon = WeaponFactory.CreateSokol545(), 67 DistanceToOpponent = 10f, 68 Health = 100f 69 }; 70 player.CurrentAmmo = player.EquippedWeapon!.MagazineSize; 71 72 var enemy = new Operator("Enemy") 73 { 74 EquippedWeapon = WeaponFactory.CreateSokol545(), 75 DistanceToOpponent = 10f, 76 Health = 1f // Very low health, likely to die 77 }; 78 enemy.CurrentAmmo = enemy.EquippedWeapon!.MagazineSize; 79 80 var combat = new CombatSystemV2(player, enemy, seed: 42); 81 82 // Act - Both fire 83 var playerIntents = new SimultaneousIntents(player.Id) 84 { 85 Primary = PrimaryAction.Fire 86 }; 87 88 var enemyIntents = new SimultaneousIntents(enemy.Id) 89 { 90 Primary = PrimaryAction.Fire 91 }; 92 93 combat.SubmitIntents(player, playerIntents); 94 combat.SubmitIntents(enemy, enemyIntents); 95 96 // Execute until round completes 97 while (combat.Phase == CombatPhase.Executing) 98 { 99 combat.ExecuteUntilReactionWindow(); 100 } 101 102 // Assert - Even if combat ended, distances should be synchronized 103 Assert.Equal(player.DistanceToOpponent, enemy.DistanceToOpponent); 104 } 105 106 [Fact] 107 public void Distance_RemainsConsistentAcrossMultipleRounds() 108 { 109 // Arrange 110 var player = new Operator("Player") 111 { 112 EquippedWeapon = WeaponFactory.CreateM15Mod0(), 113 DistanceToOpponent = 20f 114 }; 115 player.CurrentAmmo = player.EquippedWeapon!.MagazineSize; 116 117 var enemy = new Operator("Enemy") 118 { 119 EquippedWeapon = WeaponFactory.CreateM15Mod0(), 120 DistanceToOpponent = 20f 121 }; 122 enemy.CurrentAmmo = enemy.EquippedWeapon!.MagazineSize; 123 124 var combat = new CombatSystemV2(player, enemy, seed: 42); 125 126 // Act - Execute multiple rounds with various movement 127 for (int i = 0; i < 5; i++) 128 { 129 var playerIntents = new SimultaneousIntents(player.Id) 130 { 131 Movement = i % 2 == 0 ? MovementAction.WalkToward : MovementAction.WalkAway, 132 Primary = PrimaryAction.Fire 133 }; 134 135 var enemyIntents = new SimultaneousIntents(enemy.Id) 136 { 137 Movement = i % 2 == 0 ? MovementAction.WalkAway : MovementAction.Stand, 138 Primary = PrimaryAction.Fire 139 }; 140 141 combat.SubmitIntents(player, playerIntents); 142 combat.SubmitIntents(enemy, enemyIntents); 143 144 // Execute until round completes 145 while (combat.Phase == CombatPhase.Executing) 146 { 147 combat.ExecuteUntilReactionWindow(); 148 } 149 150 // Assert - After each round, distances should match 151 Assert.Equal(player.DistanceToOpponent, enemy.DistanceToOpponent); 152 153 // Break if combat ended 154 if (combat.Phase == CombatPhase.Ended) 155 break; 156 } 157 } 158 }