This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using PkmnLib.Dynamic.Libraries;
|
||||
using PkmnLib.Dynamic.Models;
|
||||
using PkmnLib.Dynamic.ScriptHandling;
|
||||
using PkmnLib.Plugin.Gen7.Scripts.Moves;
|
||||
using PkmnLib.Static;
|
||||
using PkmnLib.Static.Libraries;
|
||||
@@ -7,25 +8,43 @@ using PkmnLib.Static.Utils;
|
||||
|
||||
namespace PkmnLib.Plugin.Gen7.Tests.Scripts.Moves;
|
||||
|
||||
/// <summary>
|
||||
/// Tests for the <see cref="HiddenPower"/> move script.
|
||||
/// Gen VII Bulbapedia behavior: "Hidden Power can be any type, other than Normal and Fairy, based on its user's
|
||||
/// IVs." and "From Generation VI onward, its power is fixed at 60."
|
||||
/// </summary>
|
||||
public class HiddenPowerTests
|
||||
{
|
||||
public record TestCaseData(IndividualValueStatisticSet Ivs, StringKey ExpectedType, ushort ExpectedPower)
|
||||
public record TestCaseData(IndividualValueStatisticSet Ivs, StringKey ExpectedType)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string ToString() =>
|
||||
$"Hidden Power type is {ExpectedType}, base power is {ExpectedPower} " +
|
||||
$"Hidden Power type is {ExpectedType} " +
|
||||
$"with IVs: HP {Ivs.Hp}, Atk {Ivs.Attack}, Def {Ivs.Defense}, SpA {Ivs.SpecialAttack}, SpD {Ivs.SpecialDefense}, Spe {Ivs.Speed}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rows of the Bulbapedia type-determination formula: the type index is
|
||||
/// (a + 2b + 4c + 8d + 16e + 32f) × 15 / 63 rounded down, where a–f are the least significant bits of the
|
||||
/// HP, Attack, Defense, Speed, Special Attack, and Special Defense IVs, and index 0 is Fighting through
|
||||
/// index 15 being Dark.
|
||||
/// </summary>
|
||||
public static IEnumerable<Func<TestCaseData>> HiddenPowerTestData()
|
||||
{
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(31, 31, 31, 31, 31, 31), "dark", 70);
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(25, 2, 12, 5, 8, 17), "bug", 31);
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(29, 19, 18, 22, 15, 28), "fire", 64);
|
||||
// All-even IVs: formula value 0 -> the lowest possible type, Fighting.
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(0, 0, 0, 0, 0, 0), "fighting");
|
||||
// Only the Speed IV is odd: formula value 8 -> 8 * 15 / 63 = 1, Flying.
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(0, 0, 0, 0, 0, 1), "flying");
|
||||
// All-odd IVs: formula value 63 -> the highest possible type, Dark.
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(31, 31, 31, 31, 31, 31), "dark");
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(25, 2, 12, 5, 8, 17), "bug");
|
||||
yield return () => new TestCaseData(new IndividualValueStatisticSet(29, 19, 18, 22, 15, 28), "fire");
|
||||
}
|
||||
|
||||
[Test, MethodDataSource(nameof(HiddenPowerTestData))]
|
||||
public async Task HiddenPower_ChangesType(TestCaseData test)
|
||||
/// <summary>
|
||||
/// Creates a type library holding all 18 Gen VII types, registered in the National Pokédex type order.
|
||||
/// </summary>
|
||||
private static TypeLibrary CreateTypeLibrary()
|
||||
{
|
||||
var typeLibrary = new TypeLibrary();
|
||||
typeLibrary.RegisterType("normal");
|
||||
@@ -46,7 +65,14 @@ public class HiddenPowerTests
|
||||
typeLibrary.RegisterType("dragon");
|
||||
typeLibrary.RegisterType("dark");
|
||||
typeLibrary.RegisterType("fairy");
|
||||
return typeLibrary;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mocked executing move whose user has the given IVs and a library containing all 18 types.
|
||||
/// </summary>
|
||||
private static (IExecutingMove executingMove, IPokemon target) CreateTestSetup(IndividualValueStatisticSet ivs)
|
||||
{
|
||||
var executingMove = Substitute.For<IExecutingMove>();
|
||||
var user = Substitute.For<IPokemon>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
@@ -54,10 +80,22 @@ public class HiddenPowerTests
|
||||
var staticLibrary = Substitute.For<IStaticLibrary>();
|
||||
|
||||
executingMove.User.Returns(user);
|
||||
user.IndividualValues.Returns(test.Ivs);
|
||||
user.IndividualValues.Returns(ivs);
|
||||
user.Library.Returns(dynamicLibrary);
|
||||
staticLibrary.Types.Returns(typeLibrary);
|
||||
staticLibrary.Types.Returns(CreateTypeLibrary());
|
||||
dynamicLibrary.StaticLibrary.Returns(staticLibrary);
|
||||
return (executingMove, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Hidden Power can be any type, other than Normal and Fairy, based on its user's IVs."
|
||||
/// The type index is (a + 2b + 4c + 8d + 16e + 32f) × 15 / 63 rounded down, where a–f are the least
|
||||
/// significant bits of the HP, Attack, Defense, Speed, Special Attack, and Special Defense IVs.
|
||||
/// </summary>
|
||||
[Test, MethodDataSource(nameof(HiddenPowerTestData))]
|
||||
public async Task HiddenPower_ChangesType(TestCaseData test)
|
||||
{
|
||||
var (executingMove, target) = CreateTestSetup(test.Ivs);
|
||||
|
||||
TypeIdentifier? moveType = new TypeIdentifier(1, "normal");
|
||||
|
||||
@@ -67,24 +105,42 @@ public class HiddenPowerTests
|
||||
await Assert.That(moveType!.Value.Name).IsEqualTo(test.ExpectedType);
|
||||
}
|
||||
|
||||
[Test, MethodDataSource(nameof(HiddenPowerTestData))]
|
||||
public async Task HiddenPower_ChangesBasePower(TestCaseData test)
|
||||
/// <summary>
|
||||
/// Bulbapedia: "Hidden Power can be any type, other than Normal and Fairy, based on its user's IVs."
|
||||
/// The type only depends on the least significant bit of each of the six IVs, so checking all 64 parity
|
||||
/// combinations exhaustively proves the move can never be Normal or Fairy.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public async Task ChangeMoveType_AllIvParityCombinations_TypeIsNeverNormalOrFairy()
|
||||
{
|
||||
var executingMove = Substitute.For<IExecutingMove>();
|
||||
var user = Substitute.For<IPokemon>();
|
||||
var target = Substitute.For<IPokemon>();
|
||||
var dynamicLibrary = Substitute.For<IDynamicLibrary>();
|
||||
var staticLibrary = Substitute.For<IStaticLibrary>();
|
||||
for (byte combination = 0; combination < 64; combination++)
|
||||
{
|
||||
// Arrange - each bit of the combination becomes the least significant bit of one IV.
|
||||
var ivs = new IndividualValueStatisticSet((byte)(combination & 0x01), (byte)((combination >> 1) & 0x01),
|
||||
(byte)((combination >> 2) & 0x01), (byte)((combination >> 4) & 0x01), (byte)((combination >> 5) & 0x01),
|
||||
(byte)((combination >> 3) & 0x01));
|
||||
var (executingMove, target) = CreateTestSetup(ivs);
|
||||
TypeIdentifier? moveType = new TypeIdentifier(1, "normal");
|
||||
|
||||
executingMove.User.Returns(user);
|
||||
user.IndividualValues.Returns(test.Ivs);
|
||||
user.Library.Returns(dynamicLibrary);
|
||||
dynamicLibrary.StaticLibrary.Returns(staticLibrary);
|
||||
// Act
|
||||
var hiddenPower = new HiddenPower();
|
||||
hiddenPower.ChangeMoveType(executingMove, target, 0, ref moveType);
|
||||
|
||||
// Assert
|
||||
await Assert.That(moveType!.Value.Name).IsNotEqualTo(new StringKey("normal"));
|
||||
await Assert.That(moveType!.Value.Name).IsNotEqualTo(new StringKey("fairy"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bulbapedia: "From Generation VI onward, its power is fixed at 60." The pre-Gen-VI variable power formula
|
||||
/// no longer applies, so the script must leave the base power of 60 from the move data untouched, regardless
|
||||
/// of the user's IVs.
|
||||
/// </summary>
|
||||
[Test, MethodDataSource(nameof(HiddenPowerTestData))]
|
||||
public async Task ChangeBasePower_AnyIvs_PowerRemainsFixedAtSixty(TestCaseData test)
|
||||
{
|
||||
var hiddenPower = new HiddenPower();
|
||||
ushort power = 0;
|
||||
hiddenPower.ChangeBasePower(executingMove, target, 0, ref power);
|
||||
|
||||
await Assert.That(power).IsEqualTo(test.ExpectedPower);
|
||||
await Assert.That(hiddenPower).IsNotAssignableTo<IScriptChangeBasePower>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user