This commit is contained in:
205
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/AssistTests.cs
Normal file
205
Plugins/PkmnLib.Plugin.Gen7.Tests/Scripts/Moves/AssistTests.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
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="Assist"/> move script.
|
||||
/// Gen VII Bulbapedia behavior: "The Assist user executes a move that is randomly selected from all the
|
||||
/// eligible moves known by other Pokémon in the same party. If the same move is known by multiple Pokémon,
|
||||
/// each of them counts [...]. Assist can call a move that currently has no PP or is known by a fainted
|
||||
/// Pokémon. [...] If the other Pokémon in the user's party do not know any eligible moves, Assist fails."
|
||||
/// </summary>
|
||||
public class AssistTests
|
||||
{
|
||||
private static IPokemon CreatePokemonWithMoves(params string[] moveNames)
|
||||
{
|
||||
var pokemon = Substitute.For<IPokemon>();
|
||||
var moves = moveNames.Select(name =>
|
||||
{
|
||||
var learned = Substitute.For<ILearnedMove>();
|
||||
var data = Substitute.For<IMoveData>();
|
||||
data.Name.Returns(new StringKey(name));
|
||||
learned.MoveData.Returns(data);
|
||||
return (ILearnedMove?)learned;
|
||||
}).ToArray();
|
||||
pokemon.Moves.Returns(moves);
|
||||
return pokemon;
|
||||
}
|
||||
|
||||
private static (Assist script, IMoveChoice choice, IPokemon user, IBattleRandom random) CreateTestSetup(
|
||||
params IPokemon?[] otherPartyMembers)
|
||||
{
|
||||
var script = new Assist();
|
||||
var user = CreatePokemonWithMoves("tackle");
|
||||
|
||||
var members = new List<IPokemon?> { user };
|
||||
members.AddRange(otherPartyMembers);
|
||||
|
||||
var party = Substitute.For<IPokemonParty>();
|
||||
party.GetEnumerator().Returns(_ => members.GetEnumerator());
|
||||
var battleParty = Substitute.For<IBattleParty>();
|
||||
battleParty.Party.Returns(party);
|
||||
|
||||
var random = Substitute.For<IBattleRandom>();
|
||||
var battle = Substitute.For<IBattle>();
|
||||
battle.Parties.Returns(new[] { battleParty });
|
||||
battle.Random.Returns(random);
|
||||
var battleData = Substitute.For<IPokemonBattleData>();
|
||||
battleData.Battle.Returns(battle);
|
||||
user.BattleData.Returns(battleData);
|
||||
|
||||
var choice = Substitute.For<IMoveChoice>();
|
||||
choice.User.Returns(user);
|
||||
|
||||
return (script, choice, user, random);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "The Assist user executes a move that is randomly selected from all the eligible moves known
|
||||
/// by other Pokémon in the same party."
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_AllyKnowsEligibleMove_SelectsThatMove()
|
||||
{
|
||||
// Arrange
|
||||
var (script, choice, _, random) = CreateTestSetup(CreatePokemonWithMoves("growl"));
|
||||
random.GetInt(Arg.Any<int>()).Returns(0);
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("growl"));
|
||||
choice.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the other Pokémon in the user's party do not know any eligible moves, Assist fails."
|
||||
/// The user's own moves are not eligible: with no other party members, the move fails even though the
|
||||
/// user itself knows a copyable move.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_NoOtherPartyMembers_Fails()
|
||||
{
|
||||
// Arrange
|
||||
var (script, choice, _, _) = CreateTestSetup();
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
choice.Received(1).Fail();
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("assist"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia lists moves that Assist cannot call (e.g. Protect, Counter, moves with a semi-invulnerable
|
||||
/// turn). An ally that only knows ineligible moves provides no options, so Assist fails.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_AllyOnlyKnowsIneligibleMoves_Fails()
|
||||
{
|
||||
// Arrange
|
||||
var (script, choice, _, _) = CreateTestSetup(CreatePokemonWithMoves("protect", "counter", "dig"));
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
choice.Received(1).Fail();
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("assist"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "If the same move is known by multiple Pokémon, each of them counts and therefore the move
|
||||
/// is more likely to be called." Two allies knowing Tackle plus one knowing Growl yields three entries in
|
||||
/// the random selection pool.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void ChangeMove_SameMoveKnownByMultipleAllies_EachCounts()
|
||||
{
|
||||
// Arrange
|
||||
var (script, choice, _, random) = CreateTestSetup(CreatePokemonWithMoves("pound"),
|
||||
CreatePokemonWithMoves("pound"), CreatePokemonWithMoves("growl"));
|
||||
random.GetInt(Arg.Any<int>()).Returns(0);
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert - the selection pool contains three moves (pound twice, growl once)
|
||||
random.Received(1).GetInt(3);
|
||||
choice.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Assist can call a move that [...] is known by a fainted Pokémon."
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_AllyIsFainted_MoveStillEligible()
|
||||
{
|
||||
// Arrange
|
||||
var faintedAlly = CreatePokemonWithMoves("growl");
|
||||
faintedAlly.IsUsable.Returns(false);
|
||||
var (script, choice, _, random) = CreateTestSetup(faintedAlly);
|
||||
random.GetInt(Arg.Any<int>()).Returns(0);
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("growl"));
|
||||
choice.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Assist can call a move that currently has no PP".
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_AllyMoveHasNoPp_MoveStillEligible()
|
||||
{
|
||||
// Arrange
|
||||
var ally = CreatePokemonWithMoves("growl");
|
||||
ally.Moves[0]!.CurrentPp.Returns((byte)0);
|
||||
var (script, choice, _, random) = CreateTestSetup(ally);
|
||||
random.GetInt(Arg.Any<int>()).Returns(0);
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("growl"));
|
||||
choice.DidNotReceive().Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Technical test: outside of battle (no battle data) the script returns without failing the choice.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMove_NoBattleData_DoesNothing()
|
||||
{
|
||||
// Arrange
|
||||
var script = new Assist();
|
||||
var user = Substitute.For<IPokemon>();
|
||||
user.BattleData.Returns((IPokemonBattleData?)null);
|
||||
var choice = Substitute.For<IMoveChoice>();
|
||||
choice.User.Returns(user);
|
||||
StringKey moveName = "assist";
|
||||
|
||||
// Act
|
||||
script.ChangeMove(choice, ref moveName);
|
||||
|
||||
// Assert
|
||||
choice.DidNotReceive().Fail();
|
||||
await Assert.That(moveName).IsEqualTo(new StringKey("assist"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user