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: "Gyro Ball inflicts more damage the slower the user is compared to the
/// target", with base power = min(150, 25 × target Speed / user Speed + 1).
///
public class GyroBallTests
{
private static (GyroBall script, IExecutingMove move, IPokemon target) CreateTestSetup(uint userSpeed,
uint targetSpeed)
{
var script = new GyroBall();
var move = Substitute.For();
var user = Substitute.For();
user.BoostedStats.Returns(new StatisticSet(100, 100, 100, 100, 100, userSpeed));
move.User.Returns(user);
var target = Substitute.For();
target.BoostedStats.Returns(new StatisticSet(100, 100, 100, 100, 100, targetSpeed));
return (script, move, target);
}
///
/// Bulbapedia: "BasePower = min(150, 25 × CurrentSpeed(target) / CurrentSpeed(user) + 1)". Various
/// speed combinations, including the integer truncation of the division.
///
[Test, Arguments(100u, 100u, (ushort)26), Arguments(100u, 50u, (ushort)13), Arguments(100u, 1u, (ushort)1),
Arguments(50u, 200u, (ushort)101)]
// 25 * 100 / 100 + 1
// 25 * 50 / 100 = 12 (truncated) + 1
// 25 * 1 / 100 = 0 (truncated) + 1
// 25 * 200 / 50 + 1
public async Task ChangeBasePower_SpeedComparison_FollowsFormula(uint userSpeed, uint targetSpeed,
ushort expectedPower)
{
// Arrange
var (script, move, target) = CreateTestSetup(userSpeed, targetSpeed);
ushort basePower = 5;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo(expectedPower);
}
///
/// Bulbapedia: "The move reaches its maximum base power of 150" — a formula result just above the cap
/// is clamped to 150.
///
[Test]
public async Task ChangeBasePower_FormulaExceedsCap_BasePowerCappedAt150()
{
// Arrange - 25 * 60 / 10 + 1 = 151
var (script, move, target) = CreateTestSetup(10, 60);
ushort basePower = 5;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)150);
}
///
/// Bulbapedia: the base power is capped at 150 for any speed ratio. The implementation truncates the
/// formula result to a byte before applying the cap, so results above 255 wrap around and produce a
/// wrong power (25 × 100 / 4 + 1 = 626 wraps to 114).
///
[Test]
public async Task ChangeBasePower_FormulaFarExceedsByteRange_BasePowerCappedAt150()
{
// Arrange - 25 * 100 / 4 + 1 = 626
var (script, move, target) = CreateTestSetup(4, 100);
ushort basePower = 5;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)150);
}
///
/// Bulbapedia (Generation VI onwards): "If the user of Gyro Ball has a Speed stat that rounds down to
/// 0, the move's power is set to 1."
///
[Test]
public async Task ChangeBasePower_UserSpeedIsZero_BasePowerIsOne()
{
// Arrange
var (script, move, target) = CreateTestSetup(0, 100);
ushort basePower = 5;
// Act
script.ChangeBasePower(move, target, 0, ref basePower);
// Assert
await Assert.That(basePower).IsEqualTo((ushort)1);
}
}