using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.Models.Choices;
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Plugin.Gen7.Scripts.MoveVolatile;
using PkmnLib.Static.Moves;
using PkmnLib.Static.Utils;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
///
/// Tests for the move script.
/// Bulbapedia: "When two allies attempt to use Fire Pledge and either Water Pledge or Grass Pledge on the
/// same turn, the ally moving first will not itself use a move, but instead the ally moving second will use
/// a combined attack with a power of 150 and an additional effect immediately after it".
///
public class FirePledgeTests
{
///
/// Creates a move choice for a Pokémon on the given side, using a move with the given name.
/// The choice gets a real as its volatile set, so combination markers can be
/// added to and read from it.
///
private static IMoveChoice CreateQueuedChoice(string moveName, byte sideIndex)
{
var choice = Substitute.For();
choice.GetScripts().Returns(_ => new ScriptIterator(new List>()));
var pokemon = Substitute.For();
pokemon.SideIndex.Returns(sideIndex);
choice.User.Returns(pokemon);
var moveData = Substitute.For();
moveData.Name.Returns(new StringKey(moveName));
var learnedMove = Substitute.For();
learnedMove.MoveData.Returns(moveData);
choice.ChosenMove.Returns(learnedMove);
var choiceVolatile = new ScriptSet(choice);
choice.Volatile.Returns(choiceVolatile);
return choice;
}
///
/// Creates a fully mocked test setup for Fire Pledge tests. The user is on side 0.
///
private static (FirePledge script, IExecutingMove move, IMoveChoice ownChoice) CreateTestSetup(
BattleChoiceQueue? queue)
{
var script = new FirePledge();
var move = Substitute.For();
var battle = Substitute.For();
battle.ChoiceQueue.Returns(queue);
move.Battle.Returns(battle);
var user = Substitute.For();
user.SideIndex.Returns((byte)0);
move.User.Returns(user);
var ownChoice = CreateQueuedChoice("fire_pledge", 0);
move.MoveChoice.Returns(ownChoice);
return (script, move, ownChoice);
}
///
/// Bulbapedia: "the ally moving first will not itself use a move".
/// An ally on the same side still has Water Pledge queued, so this Fire Pledge is stopped.
///
[Test]
public async Task StopBeforeMove_AllyWaterPledgeQueued_StopsMove()
{
// Arrange
var allyChoice = CreateQueuedChoice("water_pledge", 0);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsTrue();
}
///
/// Bulbapedia: "If Fire Pledge and Water Pledge are used in the same turn, the ally moving second will
/// use Water Pledge with a power of 150, and create a rainbow on the user's side of the field for four
/// turns."
/// The queued ally choice is marked with the volatile that implements
/// the combined move.
///
[Test]
public async Task StopBeforeMove_AllyWaterPledgeQueued_MarksAllyChoiceAsCombinedFireWaterPledge()
{
// Arrange
var allyChoice = CreateQueuedChoice("water_pledge", 0);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(allyChoice.Volatile.Contains()).IsTrue();
}
///
/// Bulbapedia: "the ally moving first will not itself use a move".
/// An ally on the same side still has Grass Pledge queued, so this Fire Pledge is stopped.
///
[Test]
public async Task StopBeforeMove_AllyGrassPledgeQueued_StopsMove()
{
// Arrange
var allyChoice = CreateQueuedChoice("grass_pledge", 0);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsTrue();
}
///
/// Bulbapedia: "If Fire Pledge and Grass Pledge are used in the same turn, the ally moving second will
/// use Fire Pledge with a power of 150, and create a sea of fire on the target's side of the field for
/// four turns."
/// The queued ally choice is marked with the volatile that implements
/// the combined move.
///
[Test]
public async Task StopBeforeMove_AllyGrassPledgeQueued_MarksAllyChoiceAsCombinedFireGrassPledge()
{
// Arrange
var allyChoice = CreateQueuedChoice("grass_pledge", 0);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(allyChoice.Volatile.Contains()).IsTrue();
}
///
/// Bulbapedia: the combination only happens when allies use "Fire Pledge and either Water Pledge or
/// Grass Pledge on the same turn".
/// No Pledge move is queued by an ally, so Fire Pledge executes normally.
///
[Test]
public async Task StopBeforeMove_NoPledgeMoveQueued_DoesNotStop()
{
// Arrange
var allyChoice = CreateQueuedChoice("tackle", 0);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
}
///
/// Bulbapedia: "When two allies attempt to use Fire Pledge and either Water Pledge or Grass Pledge on
/// the same turn" — a Pledge move queued by an opponent does not combine.
///
[Test]
public async Task StopBeforeMove_OpponentWaterPledgeQueued_DoesNotStop()
{
// Arrange
var opponentChoice = CreateQueuedChoice("water_pledge", 1);
var (script, move, _) = CreateTestSetup(new BattleChoiceQueue([opponentChoice]));
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
await Assert.That(opponentChoice.Volatile.Contains()).IsFalse();
}
///
/// Bulbapedia: "the ally moving second will use Fire Pledge with a power of 150".
/// When this Fire Pledge choice is itself the combined move of Grass Pledge and Fire Pledge (marked
/// with ), it must execute instead of deferring again.
///
[Test]
public async Task StopBeforeMove_ChoiceIsCombinedFireGrassPledge_DoesNotStop()
{
// Arrange
var allyChoice = CreateQueuedChoice("grass_pledge", 0);
var (script, move, ownChoice) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
ownChoice.Volatile.Add(new FireGrassPledgeMove());
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
await Assert.That(allyChoice.Volatile.Contains()).IsFalse();
}
///
/// Bulbapedia: "the ally moving second will use Water Pledge with a power of 150".
/// When this choice is the combined move of Fire Pledge and Water Pledge (marked with
/// ), it must execute instead of deferring again.
///
[Test]
public async Task StopBeforeMove_ChoiceIsCombinedFireWaterPledge_DoesNotStop()
{
// Arrange
var allyChoice = CreateQueuedChoice("water_pledge", 0);
var (script, move, ownChoice) = CreateTestSetup(new BattleChoiceQueue([allyChoice]));
ownChoice.Volatile.Add(new FireWaterPledgeMove());
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
await Assert.That(allyChoice.Volatile.Contains()).IsFalse();
}
///
/// Technical test: when the battle has no active choice queue, the move executes normally without
/// throwing.
///
[Test]
public async Task StopBeforeMove_NullChoiceQueue_DoesNotStop()
{
// Arrange
var (script, move, _) = CreateTestSetup(null);
var stop = false;
// Act
script.StopBeforeMove(move, ref stop);
// Assert
await Assert.That(stop).IsFalse();
}
}