using PkmnLib.Dynamic.Models; using PkmnLib.Static; using PkmnLib.Static.Species; using PkmnLib.Tests.Integration; namespace PkmnLib.Tests.Dynamic; /// /// Tests for the temporary move overlay (), used by effects /// such as Mimic. The permanently learned moves must never be mutated by a temporary move, and the overlay /// must be discarded by the engine itself when the Pokemon leaves the battlefield. /// public class PokemonTemporaryMoveTests { private static (IBattle battle, IBattlePokemon battlePokemon, IPokemon pokemon) CreateBattlePokemon() { var library = LibraryHelpers.LoadLibrary(); if (!library.StaticLibrary.Species.TryGet("bulbasaur", out var species)) throw new InvalidOperationException("Failed to load bulbasaur species."); IPokemon CreateBulbasaur() => new PokemonImpl(library, species, species.GetDefaultForm(), new AbilityIndex { Index = 0, IsHidden = false, }, 50, 0, Gender.Male, 0, "hardy"); var pokemon = CreateBulbasaur(); pokemon.LearnMove("tackle", MoveLearnMethod.LevelUp, 0); var party = new PokemonPartyImpl(1); party.SwapInto(pokemon, 0); var opponentParty = new PokemonPartyImpl(1); opponentParty.SwapInto(CreateBulbasaur(), 0); var parties = new[] { new BattlePartyImpl(party, [new ResponsibleIndex(0, 0)]), new BattlePartyImpl(opponentParty, [new ResponsibleIndex(1, 0)]), }; var battle = new BattleImpl(library, parties, false, 2, 1, false, "grass", 0); return (battle, battle.Parties[0].GetBattlePokemon(pokemon)!, pokemon); } [Test] public async Task LearnTemporaryMove_ReplacesMoveInMovesButNotInBaseMoves() { var (_, battlePokemon, pokemon) = CreateBattlePokemon(); battlePokemon.LearnTemporaryMove("swords_dance", MoveLearnMethod.Mimic, 0); await Assert.That(battlePokemon.Moves[0]!.MoveData.Name.ToString()).IsEqualTo("swords_dance"); await Assert.That(battlePokemon.Moves[0]!.LearnMethod).IsEqualTo(MoveLearnMethod.Mimic); await Assert.That(battlePokemon.BaseMoves[0]!.MoveData.Name.ToString()).IsEqualTo("tackle"); await Assert.That(pokemon.Moves[0]!.MoveData.Name.ToString()).IsEqualTo("tackle"); } [Test] public async Task OnSwitchedOut_RestoresOriginalMoveWithItsPP() { var (_, battlePokemon, _) = CreateBattlePokemon(); battlePokemon.OnSwitchedIn(0); // Use the original move once, so we can verify its PP survives the temporary replacement untouched. var originalMove = battlePokemon.Moves[0]!; originalMove.TryUse(); var expectedPp = originalMove.CurrentPp; battlePokemon.LearnTemporaryMove("swords_dance", MoveLearnMethod.Mimic, 0); battlePokemon.OnSwitchedOut(); await Assert.That(ReferenceEquals(battlePokemon.Moves[0], originalMove)).IsTrue(); await Assert.That(battlePokemon.Moves[0]!.CurrentPp).IsEqualTo(expectedPp); } [Test] public async Task BattleEnd_LeavesOriginalMovesUntouched() { var (battle, battlePokemon, pokemon) = CreateBattlePokemon(); battlePokemon.LearnTemporaryMove("swords_dance", MoveLearnMethod.Mimic, 0); battle.Dispose(); await Assert.That(pokemon.Moves[0]!.MoveData.Name.ToString()).IsEqualTo("tackle"); } [Test] public async Task Serialize_WithActiveTemporaryMove_WritesOriginalMove() { var (_, battlePokemon, _) = CreateBattlePokemon(); battlePokemon.LearnTemporaryMove("swords_dance", MoveLearnMethod.Mimic, 0); var serialized = battlePokemon.Serialize(); await Assert.That(serialized.Moves[0]!.MoveName.ToString()).IsEqualTo("tackle"); } }