using PkmnLib.Dynamic.Models;
using PkmnLib.Plugin.Gen7.Scripts.Moves;
using PkmnLib.Static;
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
///
/// Tests for the move script.
/// Gen VII Bulbapedia behavior: "Flail inflicts damage and has no additional effect. Its power is based on
/// the user's current HP as a percentage of its maximum HP, which is higher the lower the user's HP is."
/// The power tiers (all generations except IV) are: 20 power at HP ≥ 68.8%, 40 at 35.4% ≤ HP < 68.8%,
/// 80 at 20.8% ≤ HP < 35.4%, 100 at 10.4% ≤ HP < 20.8%, 150 at 4.2% ≤ HP < 10.4%, and
/// 200 at HP < 4.2%. These percentages correspond to the tiers of floor(48 × current HP / max HP).
///
public class FlailTests
{
///
/// Creates a fully mocked test setup for Flail tests with the user at the given current and maximum HP.
///
private static (Flail script, IExecutingMove move, IBattlePokemon target) CreateTestSetup(uint currentHp,
uint maxHp)
{
var script = new Flail();
var move = Substitute.For();
var target = Substitute.For();
var user = Substitute.For();
user.CurrentHealth.Returns(currentHp);
user.BoostedStats.Returns(new StatisticSet(maxHp, 0, 0, 0, 0, 0));
move.User.Returns(user);
return (script, move, target);
}
///
/// Bulbapedia: Flail's power is 20 when the user's HP is at least 68.8% of its maximum.
/// A user at full health uses the weakest power tier.
///
[Test]
public async Task ChangeBasePower_UserAtFullHealth_PowerIs20()
{
// Arrange
var (script, move, target) = CreateTestSetup(100, 100);
ushort basePower = 20;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)20);
}
///
/// Bulbapedia: Flail's power is 200 when the user's HP is below 4.2% of its maximum.
/// A user at 1 HP uses the strongest power tier.
///
[Test]
public async Task ChangeBasePower_UserAtOneHp_PowerIs200()
{
// Arrange
var (script, move, target) = CreateTestSetup(1, 100);
ushort basePower = 20;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)200);
}
///
/// Bulbapedia: "Its power is based on the user's current HP as a percentage of its maximum HP, which is
/// higher the lower the user's HP is". These rows cover the extremes of the table: full health
/// (HP ≥ 68.8% → 20 power) and nearly fainted (HP < 4.2% → 200 power).
///
[Test, Arguments(100u, 100u, 20), Arguments(4u, 100u, 200), Arguments(1u, 100u, 200)]
// 48/48 -> 20
// floor(1.92) = 1 -> 200
// floor(0.48) = 0 -> 200
public async Task ChangeBasePower_HpAtExtremes_MatchesFlailPowerTable(uint currentHp, uint maxHp, int expectedPower)
{
// Arrange
var (script, move, target) = CreateTestSetup(currentHp, maxHp);
ushort basePower = 20;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)expectedPower);
}
///
/// Bulbapedia: "Its power is based on the user's current HP as a percentage of its maximum HP, which is
/// higher the lower the user's HP is", following the tiers 20 (HP ≥ 68.8%), 40 (35.4% ≤ HP < 68.8%),
/// 80 (20.8% ≤ HP < 35.4%), 100 (10.4% ≤ HP < 20.8%), 150 (4.2% ≤ HP < 10.4%) and 200 (HP < 4.2%).
/// The rows cover both boundary values of every tier, verifying the integer arithmetic of
/// floor(48 × current HP / max HP).
///
[Test, Arguments(69u, 100u, 20), Arguments(68u, 100u, 40), Arguments(36u, 100u, 40), Arguments(35u, 100u, 80),
Arguments(21u, 100u, 80), Arguments(20u, 100u, 100), Arguments(11u, 100u, 100), Arguments(10u, 100u, 150),
Arguments(5u, 100u, 150), Arguments(150u, 300u, 40), Arguments(24u, 48u, 40), Arguments(7u, 48u, 100)]
public async Task ChangeBasePower_HpFractionOfMax_MatchesFlailPowerTable(uint currentHp, uint maxHp,
int expectedPower)
{
// Arrange
var (script, move, target) = CreateTestSetup(currentHp, maxHp);
ushort basePower = 20;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)expectedPower);
}
}