Files
PkmnLib.NET/Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/ImprisonTests.cs

142 lines
5.3 KiB
C#

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;
/// <summary>
/// Tests for the <see cref="Imprison"/> move script and its <see cref="ImprisonEffect"/> 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."
/// </summary>
public class ImprisonTests
{
/// <summary>
/// Creates a substitute learned move whose <see cref="IMoveData.Name"/> is the given name.
/// </summary>
private static ILearnedMove CreateLearnedMove(string name)
{
var moveData = Substitute.For<IMoveData>();
moveData.Name.Returns(new StringKey(name));
var learnedMove = Substitute.For<ILearnedMove>();
learnedMove.MoveData.Returns(moveData);
return learnedMove;
}
/// <summary>
/// Creates the Pokémon that used Imprison, knowing the given moves (with an empty move slot, as real
/// movesets can have them), and the <see cref="ImprisonEffect"/> bound to it.
/// </summary>
private static (ImprisonEffect effect, IBattlePokemon user) CreateImprisonUser(params string[] knownMoves)
{
var user = Substitute.For<IBattlePokemon>();
var moves = knownMoves.Select(ILearnedMove? (m) => CreateLearnedMove(m)).Append(null).ToArray();
user.Moves.Returns(moves);
return (new ImprisonEffect(user), user);
}
/// <summary>
/// Creates a move choice by the given Pokémon for a move with the given name.
/// </summary>
private static IMoveChoice CreateMoveChoice(IBattlePokemon chooser, string moveName)
{
var choice = Substitute.For<IMoveChoice>();
choice.User.Returns(chooser);
var learnedMove = CreateLearnedMove(moveName);
choice.ChosenMove.Returns(learnedMove);
return choice;
}
/// <summary>
/// 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
/// <see cref="ImprisonEffect"/> on the battle's volatile scripts, where every move choice sees it.
/// </summary>
[Test]
public async Task OnSecondaryEffect_Used_AddsImprisonEffectToBattleVolatile()
{
// Arrange
var script = new Imprison();
var move = Substitute.For<IExecutingMove>();
var user = Substitute.For<IBattlePokemon>();
move.User.Returns(user);
var target = Substitute.For<IBattlePokemon>();
var battle = Substitute.For<IBattle>();
battle.GetScripts().Returns(_ => new ScriptIterator(Array.Empty<IEnumerable<ScriptContainer>>()));
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<ImprisonEffect>()).IsNotNull();
}
/// <summary>
/// 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.
/// </summary>
[Test]
public async Task PreventMoveSelection_OpponentChoosesMoveKnownByUser_SelectionPrevented()
{
// Arrange
var (effect, _) = CreateImprisonUser("tackle", "imprison");
var opponent = Substitute.For<IBattlePokemon>();
var choice = CreateMoveChoice(opponent, "tackle");
var prevent = false;
// Act
effect.PreventMoveSelection(choice, ref prevent);
// Assert
await Assert.That(prevent).IsTrue();
}
/// <summary>
/// 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.
/// </summary>
[Test]
public async Task PreventMoveSelection_OpponentChoosesMoveNotKnownByUser_SelectionAllowed()
{
// Arrange
var (effect, _) = CreateImprisonUser("tackle", "imprison");
var opponent = Substitute.For<IBattlePokemon>();
var choice = CreateMoveChoice(opponent, "ember");
var prevent = false;
// Act
effect.PreventMoveSelection(choice, ref prevent);
// Assert
await Assert.That(prevent).IsFalse();
}
/// <summary>
/// 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.
/// </summary>
[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();
}
}