using PkmnLib.Dynamic.Models; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Static; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script. /// Gen VII Bulbapedia behavior: "Guard Split averages the user's Defense and Special Defense stats with /// those of the target Pokémon." and "Both the user's and the target's stat changes are ignored when /// calculating the average." (the calculation therefore uses the flat, unboosted stats). /// public class GuardSplitTests { private static (GuardSplit script, IExecutingMove move, IBattlePokemon user, IBattlePokemon target) CreateTestSetup( uint userDefense, uint userSpecialDefense, uint targetDefense, uint targetSpecialDefense) { var script = new GuardSplit(); var move = Substitute.For(); var user = Substitute.For(); user.FlatStats.Returns(new StatisticSet(100, 100, userDefense, 100, userSpecialDefense, 100)); move.User.Returns(user); var target = Substitute.For(); target.FlatStats.Returns(new StatisticSet(100, 100, targetDefense, 100, targetSpecialDefense, 100)); return (script, move, user, target); } /// /// Bulbapedia: "Guard Split averages the user's Defense and Special Defense stats with those of the /// target Pokémon." — both Pokémon end up with the averaged Defense value. /// [Test] public async Task OnSecondaryEffect_DifferentDefenseStats_BothGetAveragedDefense() { // Arrange var (script, move, user, target) = CreateTestSetup(40, 100, 60, 100); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(user.FlatStats.GetStatistic(Statistic.Defense)).IsEqualTo(50u); await Assert.That(target.FlatStats.GetStatistic(Statistic.Defense)).IsEqualTo(50u); } /// /// Bulbapedia: the averaging also covers "Special Defense" — both Pokémon end up with the averaged /// Special Defense value. /// [Test] public async Task OnSecondaryEffect_DifferentSpecialDefenseStats_BothGetAveragedSpecialDefense() { // Arrange var (script, move, user, target) = CreateTestSetup(100, 80, 100, 120); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(user.FlatStats.GetStatistic(Statistic.SpecialDefense)).IsEqualTo(100u); await Assert.That(target.FlatStats.GetStatistic(Statistic.SpecialDefense)).IsEqualTo(100u); } /// /// The average of an odd sum is truncated by integer division, matching the games' integer stat /// arithmetic. /// [Test, Arguments(35u, 40u, 37u), Arguments(1u, 2u, 1u), Arguments(99u, 100u, 99u)] public async Task OnSecondaryEffect_OddDefenseSum_AverageIsTruncated(uint userDefense, uint targetDefense, uint expectedAverage) { // Arrange var (script, move, user, target) = CreateTestSetup(userDefense, 100, targetDefense, 100); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(user.FlatStats.GetStatistic(Statistic.Defense)).IsEqualTo(expectedAverage); await Assert.That(target.FlatStats.GetStatistic(Statistic.Defense)).IsEqualTo(expectedAverage); } /// /// Bulbapedia: only Defense and Special Defense are averaged — the other stats are left untouched. /// [Test] public async Task OnSecondaryEffect_Always_OtherStatsUnchanged() { // Arrange var (script, move, user, target) = CreateTestSetup(40, 80, 60, 120); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(user.FlatStats.GetStatistic(Statistic.Attack)).IsEqualTo(100u); await Assert.That(user.FlatStats.GetStatistic(Statistic.SpecialAttack)).IsEqualTo(100u); await Assert.That(user.FlatStats.GetStatistic(Statistic.Speed)).IsEqualTo(100u); await Assert.That(user.FlatStats.GetStatistic(Statistic.Hp)).IsEqualTo(100u); } /// /// The changed flat stats must be propagated to the effective in-battle stats — both Pokémon get /// their boosted stats recalculated. /// [Test] public async Task OnSecondaryEffect_Always_RecalculatesBoostedStatsOnBothPokemon() { // Arrange var (script, move, user, target) = CreateTestSetup(40, 80, 60, 120); // Act script.OnSecondaryEffect(move, target, 0); // Assert user.Received(1).RecalculateBoostedStats(); target.Received(1).RecalculateBoostedStats(); await Assert.That(user.ReceivedCalls().Any(c => c.GetMethodInfo().Name == "RecalculateBoostedStats")).IsTrue(); } }