using PkmnLib.Dynamic.Models; using PkmnLib.Dynamic.Models.Choices; using PkmnLib.Dynamic.ScriptHandling; using PkmnLib.Plugin.Gen7.Scripts.Moves; using PkmnLib.Plugin.Gen7.Scripts.Pokemon; using PkmnLib.Static.Moves; using PkmnLib.Static.Utils; namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves; /// /// Tests for the move script and its volatile. /// Gen VII Bulbapedia behavior: "As long as the user remains in battle, opponents cannot use any move which /// is also known by the user. This includes opponents switched in after the move was used". Generation V /// onwards: "Imprison still works even if no opponent has a move the user knows." /// public class ImprisonTests { /// /// Creates a substitute learned move whose is the given name. /// private static ILearnedMove CreateLearnedMove(string name) { var moveData = Substitute.For(); moveData.Name.Returns(new StringKey(name)); var learnedMove = Substitute.For(); learnedMove.MoveData.Returns(moveData); return learnedMove; } /// /// Creates the Pokémon that used Imprison, knowing the given moves (with an empty move slot, as real /// movesets can have them), and the bound to it. /// private static (ImprisonEffect effect, IBattlePokemon user) CreateImprisonUser(params string[] knownMoves) { var user = Substitute.For(); var moves = knownMoves.Select(ILearnedMove? (m) => CreateLearnedMove(m)).Append(null).ToArray(); user.Moves.Returns(moves); return (new ImprisonEffect(user), user); } /// /// Creates a move choice by the given Pokémon for a move with the given name. /// private static IMoveChoice CreateMoveChoice(IBattlePokemon chooser, string moveName) { var choice = Substitute.For(); choice.User.Returns(chooser); var learnedMove = CreateLearnedMove(moveName); choice.ChosenMove.Returns(learnedMove); return choice; } /// /// Bulbapedia: "As long as the user remains in battle, opponents cannot use any move which is also known /// by the user." This includes opponents switched in after the move was used, so using the move puts the /// on the battle's volatile scripts, where every move choice sees it. /// [Test] public async Task OnSecondaryEffect_Used_AddsImprisonEffectToBattleVolatile() { // Arrange var script = new Imprison(); var move = Substitute.For(); var user = Substitute.For(); move.User.Returns(user); var target = Substitute.For(); var battle = Substitute.For(); battle.GetScripts().Returns(_ => new ScriptIterator(Array.Empty>())); var battleVolatile = new ScriptSet(battle); battle.Volatile.Returns(battleVolatile); target.Battle.Returns(battle); // Act script.OnSecondaryEffect(move, target, 0); // Assert await Assert.That(battleVolatile.Get()).IsNotNull(); } /// /// Bulbapedia: "opponents cannot use any move which is also known by the user." An opponent choosing a /// move the Imprison user knows has its selection prevented. /// [Test] public async Task PreventMoveSelection_OpponentChoosesMoveKnownByUser_SelectionPrevented() { // Arrange var (effect, _) = CreateImprisonUser("tackle", "imprison"); var opponent = Substitute.For(); var choice = CreateMoveChoice(opponent, "tackle"); var prevent = false; // Act effect.PreventMoveSelection(choice, ref prevent); // Assert await Assert.That(prevent).IsTrue(); } /// /// Bulbapedia: only moves "also known by the user" are sealed. An opponent choosing a move the Imprison /// user does not know is free to use it. /// [Test] public async Task PreventMoveSelection_OpponentChoosesMoveNotKnownByUser_SelectionAllowed() { // Arrange var (effect, _) = CreateImprisonUser("tackle", "imprison"); var opponent = Substitute.For(); var choice = CreateMoveChoice(opponent, "ember"); var prevent = false; // Act effect.PreventMoveSelection(choice, ref prevent); // Assert await Assert.That(prevent).IsFalse(); } /// /// Bulbapedia: "opponents cannot use any move which is also known by the user" — the user itself is not /// restricted and can keep using its own moves. /// [Test] public async Task PreventMoveSelection_UsersOwnChoice_SelectionAllowed() { // Arrange var (effect, user) = CreateImprisonUser("tackle", "imprison"); var choice = CreateMoveChoice(user, "tackle"); var prevent = false; // Act effect.PreventMoveSelection(choice, ref prevent); // Assert await Assert.That(prevent).IsFalse(); } }