210 lines
7.8 KiB
C#
210 lines
7.8 KiB
C#
using PkmnLib.Dynamic.Models;
|
|
using PkmnLib.Dynamic.Models.Choices;
|
|
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
|
using PkmnLib.Static.Moves;
|
|
using PkmnLib.Static.Utils;
|
|
|
|
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
|
|
|
/// <summary>
|
|
/// Tests for the <see cref="LastResort"/> move script.
|
|
/// Gen VII Bulbapedia behavior: "Last Resort will fail unless the Pokémon has used all of its other moves
|
|
/// at least once while on the field. Using a move before switching out and back in does not count towards
|
|
/// being able to use Last Resort. Last Resort will fail if it is the only move the user knows".
|
|
/// </summary>
|
|
public class LastResortTests
|
|
{
|
|
/// <summary>
|
|
/// Creates a mocked <see cref="ILearnedMove"/> with the given move name.
|
|
/// </summary>
|
|
private static ILearnedMove CreateLearnedMove(string name)
|
|
{
|
|
var moveData = Substitute.For<IMoveData>();
|
|
moveData.Name.Returns(new StringKey(name));
|
|
moveData.SecondaryEffect.Returns((ISecondaryEffect?)null);
|
|
var learnedMove = Substitute.For<ILearnedMove>();
|
|
learnedMove.MoveData.Returns(moveData);
|
|
return learnedMove;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a mocked user in battle that knows the given moves.
|
|
/// </summary>
|
|
private static IBattlePokemon CreateUser(params ILearnedMove?[] moves)
|
|
{
|
|
var user = Substitute.For<IBattlePokemon>();
|
|
user.Moves.Returns(moves);
|
|
var battle = Substitute.For<IBattle>();
|
|
user.Battle.Returns(battle);
|
|
return user;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the battle's previous turn choices, one inner array per turn (oldest first).
|
|
/// </summary>
|
|
private static void SetPreviousTurns(IBattlePokemon user, params ITurnChoice[][] turns)
|
|
{
|
|
user.Battle.PreviousTurnChoices.Returns(turns.Select(IReadOnlyList<ITurnChoice> (t) => t).ToList());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs <see cref="LastResort.PreventMoveSelection"/> for the user selecting the given Last Resort
|
|
/// move and returns whether the selection was prevented.
|
|
/// </summary>
|
|
private static bool RunPreventMoveSelection(IBattlePokemon user, ILearnedMove lastResort)
|
|
{
|
|
var script = new LastResort();
|
|
var choice = new MoveChoice(user, lastResort, 0, 0);
|
|
var prevent = false;
|
|
script.PreventMoveSelection(choice, ref prevent);
|
|
return prevent;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Last Resort will fail unless the Pokémon has used all of its other moves at least once
|
|
/// while on the field." — with every other move used, selecting Last Resort is allowed.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_AllOtherMovesUsedOnField_SelectionAllowed()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var growl = CreateLearnedMove("growl");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, growl, lastResort);
|
|
SetPreviousTurns(user, [new MoveChoice(user, tackle, 0, 0)], [new MoveChoice(user, growl, 0, 0)]);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Last Resort will fail unless the Pokémon has used all of its other moves at least once
|
|
/// while on the field." — with one of the other moves never used, the selection is prevented.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_NotAllOtherMovesUsed_SelectionPrevented()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var growl = CreateLearnedMove("growl");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, growl, lastResort);
|
|
SetPreviousTurns(user, [new MoveChoice(user, tackle, 0, 0)]);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: Last Resort fails "unless the Pokémon has used all of its other moves at least once" —
|
|
/// with no moves used at all (e.g. the first turn), the selection is prevented.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_NoMovesUsedYet_SelectionPrevented()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, lastResort);
|
|
SetPreviousTurns(user);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Last Resort will fail if it is the only move the user knows".
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_LastResortOnlyKnownMove_SelectionPrevented()
|
|
{
|
|
// Arrange
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(lastResort, null, null, null);
|
|
SetPreviousTurns(user);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "Using a move before switching out and back in does not count towards being able to use
|
|
/// Last Resort." — a move used only before the user was switched back in does not enable Last Resort.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_MoveOnlyUsedBeforeSwitchingOut_SelectionPrevented()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, lastResort);
|
|
var ally = Substitute.For<IBattlePokemon>();
|
|
SetPreviousTurns(user, [new MoveChoice(user, tackle, 0, 0)], [new SwitchChoice(user, ally)],
|
|
[new SwitchChoice(ally, user)]);
|
|
// The user re-entered the field during turn 3, after all three recorded turns' choices were made.
|
|
user.SwitchInTurn.Returns(3u);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsTrue();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: "A move will still count as used for Last Resort even if it would have no effect, so for
|
|
/// example, using Snore when the user is awake or a move missing due to accuracy or evasion." — a failed
|
|
/// move choice still counts as used.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_OtherMoveFailed_SelectionAllowed()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, lastResort);
|
|
var failedTackle = new MoveChoice(user, tackle, 0, 0);
|
|
failedTackle.Fail();
|
|
SetPreviousTurns(user, [failedTackle]);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsFalse();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Bulbapedia: the requirement is that "the Pokémon has used all of its other moves" — a move used by a
|
|
/// different Pokémon does not count for the user.
|
|
/// </summary>
|
|
[Test]
|
|
public async Task PreventMoveSelection_MoveUsedByAnotherPokemon_SelectionPrevented()
|
|
{
|
|
// Arrange
|
|
var tackle = CreateLearnedMove("tackle");
|
|
var lastResort = CreateLearnedMove("last_resort");
|
|
var user = CreateUser(tackle, lastResort);
|
|
var other = Substitute.For<IBattlePokemon>();
|
|
SetPreviousTurns(user, [new MoveChoice(other, tackle, 0, 0)]);
|
|
|
|
// Act
|
|
var prevent = RunPreventMoveSelection(user, lastResort);
|
|
|
|
// Assert
|
|
await Assert.That(prevent).IsTrue();
|
|
}
|
|
} |