using PkmnLib.Dynamic.Models;
using PkmnLib.Dynamic.ScriptHandling;
using PkmnLib.Dynamic.ScriptHandling.Registry;
using PkmnLib.Plugin.Gen7.Scripts.Battle;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Static;
using PkmnLib.Static.Moves;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
///
/// Tests for the move script and its attached .
/// Gen VII Bulbapedia behavior: "Mud Sport now reduces the base power of Electric-type moves by 67%
/// (approximated as a factor of 1352/4096) on both sides in battle." and (Generations VI and VII):
/// "Mud Sport is now active for five turns, even if the user switches out."
///
public class MudSportTests
{
///
/// Creates a fully mocked test setup where the battle has a real as its volatile
/// script set.
///
private static (MudSport script, IExecutingMove move, IBattlePokemon target, IBattle battle, IScriptSet
battleVolatile) CreateTestSetup()
{
var script = new MudSport();
var move = Substitute.For();
var target = Substitute.For();
var battle = Substitute.For();
battle.GetScripts().Returns(_ => new ScriptIterator(Array.Empty>()));
IScriptSet battleVolatile = new ScriptSet(battle);
battle.Volatile.Returns(battleVolatile);
var user = Substitute.For();
move.User.Returns(user);
user.Battle.Returns(battle);
return (script, move, target, battle, battleVolatile);
}
///
/// Creates a mocked executing move whose used move has the given type name.
///
private static IExecutingMove CreateExecutingMoveOfType(string typeName)
{
var executingMove = Substitute.For();
var moveData = Substitute.For();
moveData.MoveType.Returns(new TypeIdentifier(1, typeName));
executingMove.UseMove.Returns(moveData);
return executingMove;
}
///
/// Bulbapedia: Mud Sport reduces the base power of Electric-type moves "on both sides in battle" — using
/// the move puts the on the battle's volatile scripts so it affects the whole
/// field, "even if the user switches out".
///
[Test]
public async Task OnSecondaryEffect_AddsMudSportEffectToBattleVolatile()
{
// Arrange
var (script, move, target, _, battleVolatile) = CreateTestSetup();
// Act
script.OnSecondaryEffect(move, target, 0);
// Assert
await Assert.That(battleVolatile.Contains(ScriptUtils.ResolveName())).IsTrue();
}
///
/// Bulbapedia: "Mud Sport now reduces the base power of Electric-type moves by 67% (approximated as a
/// factor of 1352/4096) on both sides in battle."
///
[Test, Arguments((ushort)100, (ushort)33), Arguments((ushort)4096, (ushort)1352)]
public async Task ChangeBasePower_ElectricMove_PowerReducedBySixtySevenPercent(ushort basePower,
ushort expectedPower)
{
// Arrange
var effect = new MudSportEffect();
var electricMove = CreateExecutingMoveOfType("electric");
var target = Substitute.For();
// Act
effect.ChangeBasePower(electricMove, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo(expectedPower);
}
///
/// Bulbapedia: Mud Sport only "reduces the base power of Electric-type moves" — moves of other types are
/// unaffected.
///
[Test]
public async Task ChangeBasePower_NonElectricMove_PowerUnchanged()
{
// Arrange
var effect = new MudSportEffect();
var fireMove = CreateExecutingMoveOfType("fire");
var target = Substitute.For();
ushort basePower = 100;
// Act
effect.ChangeBasePower(fireMove, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)100);
}
///
/// Bulbapedia: "Mud Sport is now active for five turns" — after four end-of-turn ticks the
/// is still on the battle.
///
[Test]
public async Task OnEndTurn_FourTurns_EffectRemains()
{
// Arrange
var (script, move, target, battle, battleVolatile) = CreateTestSetup();
script.OnSecondaryEffect(move, target, 0);
var effect = battleVolatile.Get()!;
// Act
for (var turn = 0; turn < 4; turn++)
effect.OnEndTurn(battle, battle);
// Assert
await Assert.That(battleVolatile.Contains(ScriptUtils.ResolveName())).IsTrue();
}
///
/// Bulbapedia: "Mud Sport is now active for five turns" — after the fifth end-of-turn tick the
/// removes itself.
///
[Test]
public async Task OnEndTurn_FiveTurns_EffectRemovesItself()
{
// Arrange
var (script, move, target, battle, battleVolatile) = CreateTestSetup();
script.OnSecondaryEffect(move, target, 0);
var effect = battleVolatile.Get()!;
// Act
for (var turn = 0; turn < 5; turn++)
effect.OnEndTurn(battle, battle);
// Assert
await Assert.That(battleVolatile.Contains(ScriptUtils.ResolveName())).IsFalse();
}
}