283 lines
12 KiB
C
283 lines
12 KiB
C
#include "global.h"
|
|
#include "test/battle.h"
|
|
|
|
// From https://bulbapedia.bulbagarden.net/wiki/Damage#Example
|
|
|
|
SINGLE_BATTLE_TEST("Damage calculation matches Gen5+")
|
|
{
|
|
s16 dmg;
|
|
s16 expectedDamage;
|
|
PARAMETRIZE { expectedDamage = 196; }
|
|
PARAMETRIZE { expectedDamage = 192; }
|
|
PARAMETRIZE { expectedDamage = 192; }
|
|
PARAMETRIZE { expectedDamage = 192; }
|
|
PARAMETRIZE { expectedDamage = 184; }
|
|
PARAMETRIZE { expectedDamage = 184; }
|
|
PARAMETRIZE { expectedDamage = 184; }
|
|
PARAMETRIZE { expectedDamage = 180; }
|
|
PARAMETRIZE { expectedDamage = 180; }
|
|
PARAMETRIZE { expectedDamage = 180; }
|
|
PARAMETRIZE { expectedDamage = 172; }
|
|
PARAMETRIZE { expectedDamage = 172; }
|
|
PARAMETRIZE { expectedDamage = 172; }
|
|
PARAMETRIZE { expectedDamage = 168; }
|
|
PARAMETRIZE { expectedDamage = 168; }
|
|
PARAMETRIZE { expectedDamage = 168; }
|
|
GIVEN {
|
|
ASSUME(GetMoveCategory(MOVE_ICE_FANG) == DAMAGE_CATEGORY_PHYSICAL);
|
|
PLAYER(SPECIES_GLACEON) { Level(75); Attack(123); }
|
|
OPPONENT(SPECIES_GARCHOMP) { Defense(163); }
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(player, MOVE_ICE_FANG, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
|
|
}
|
|
}
|
|
SCENE {
|
|
MESSAGE("Glaceon used Ice Fang!");
|
|
HP_BAR(opponent, captureDamage: &dmg);
|
|
}
|
|
THEN {
|
|
EXPECT_EQ(expectedDamage, dmg);
|
|
}
|
|
}
|
|
|
|
SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Muscle Band, crit)")
|
|
{
|
|
s16 dmg;
|
|
s16 expectedDamage;
|
|
PARAMETRIZE { expectedDamage = 324; }
|
|
PARAMETRIZE { expectedDamage = 316; }
|
|
PARAMETRIZE { expectedDamage = 312; }
|
|
PARAMETRIZE { expectedDamage = 312; }
|
|
PARAMETRIZE { expectedDamage = 304; }
|
|
PARAMETRIZE { expectedDamage = 304; }
|
|
PARAMETRIZE { expectedDamage = 300; }
|
|
PARAMETRIZE { expectedDamage = 300; }
|
|
PARAMETRIZE { expectedDamage = 292; }
|
|
PARAMETRIZE { expectedDamage = 292; }
|
|
PARAMETRIZE { expectedDamage = 288; }
|
|
PARAMETRIZE { expectedDamage = 288; }
|
|
PARAMETRIZE { expectedDamage = 280; }
|
|
PARAMETRIZE { expectedDamage = 276; }
|
|
PARAMETRIZE { expectedDamage = 276; }
|
|
PARAMETRIZE { expectedDamage = 268; }
|
|
GIVEN {
|
|
ASSUME(GetMoveCategory(MOVE_ICE_FANG) == DAMAGE_CATEGORY_PHYSICAL);
|
|
PLAYER(SPECIES_GLACEON) { Level(75); Attack(123); Item(ITEM_MUSCLE_BAND); }
|
|
OPPONENT(SPECIES_GARCHOMP) { Defense(163); }
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(player, MOVE_ICE_FANG, WITH_RNG(RNG_DAMAGE_MODIFIER, i), criticalHit: TRUE);
|
|
}
|
|
}
|
|
SCENE {
|
|
MESSAGE("Glaceon used Ice Fang!");
|
|
HP_BAR(opponent, captureDamage: &dmg);
|
|
}
|
|
THEN {
|
|
EXPECT_EQ(expectedDamage, dmg);
|
|
}
|
|
}
|
|
|
|
SINGLE_BATTLE_TEST("Damage calculation matches Gen5+ (Marshadow vs Mawile)")
|
|
{
|
|
s16 dmg;
|
|
s16 expectedDamage;
|
|
PARAMETRIZE { expectedDamage = 145; }
|
|
PARAMETRIZE { expectedDamage = 144; }
|
|
PARAMETRIZE { expectedDamage = 142; }
|
|
PARAMETRIZE { expectedDamage = 141; }
|
|
PARAMETRIZE { expectedDamage = 139; }
|
|
PARAMETRIZE { expectedDamage = 138; }
|
|
PARAMETRIZE { expectedDamage = 136; }
|
|
PARAMETRIZE { expectedDamage = 135; }
|
|
PARAMETRIZE { expectedDamage = 133; }
|
|
PARAMETRIZE { expectedDamage = 132; }
|
|
PARAMETRIZE { expectedDamage = 130; }
|
|
PARAMETRIZE { expectedDamage = 129; }
|
|
PARAMETRIZE { expectedDamage = 127; }
|
|
PARAMETRIZE { expectedDamage = 126; }
|
|
PARAMETRIZE { expectedDamage = 124; }
|
|
PARAMETRIZE { expectedDamage = 123; }
|
|
GIVEN {
|
|
ASSUME(GetMoveCategory(MOVE_SPECTRAL_THIEF) == DAMAGE_CATEGORY_PHYSICAL);
|
|
PLAYER(SPECIES_MARSHADOW) { Level(100); Attack(286); }
|
|
OPPONENT(SPECIES_MAWILE) { Level(100); Defense(226); HP(241); }
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(player, MOVE_SPECTRAL_THIEF, WITH_RNG(RNG_DAMAGE_MODIFIER, i), criticalHit: FALSE);
|
|
}
|
|
}
|
|
SCENE{
|
|
MESSAGE("Marshadow used Spectral Thief!");
|
|
HP_BAR(opponent, captureDamage: &dmg);
|
|
}
|
|
THEN{
|
|
EXPECT_EQ(expectedDamage, dmg);
|
|
}
|
|
}
|
|
|
|
DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if the first target faints from first hit of the spread move")
|
|
{
|
|
s16 damage[6];
|
|
GIVEN {
|
|
PLAYER(SPECIES_REGIROCK);
|
|
PLAYER(SPECIES_REGIROCK);
|
|
OPPONENT(SPECIES_WOBBUFFET) { HP(200); }
|
|
OPPONENT(SPECIES_WOBBUFFET);
|
|
} WHEN {
|
|
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); }
|
|
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); MOVE(playerRight, MOVE_ROCK_SLIDE); }
|
|
TURN { MOVE(playerLeft, MOVE_ROCK_SLIDE); }
|
|
} SCENE {
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
|
|
HP_BAR(opponentLeft, captureDamage: &damage[0]);
|
|
HP_BAR(opponentRight, captureDamage: &damage[1]);
|
|
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
|
|
HP_BAR(opponentLeft, captureDamage: &damage[2]);
|
|
HP_BAR(opponentRight, captureDamage: &damage[3]);
|
|
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerRight);
|
|
HP_BAR(opponentRight, captureDamage: &damage[4]);
|
|
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft);
|
|
HP_BAR(opponentRight, captureDamage: &damage[5]);
|
|
} THEN {
|
|
EXPECT_EQ(damage[0], damage[1]);
|
|
EXPECT_EQ(damage[1], damage[3]);
|
|
EXPECT_MUL_EQ(damage[5], UQ_4_12(0.75), damage[3]);
|
|
EXPECT_EQ(damage[4], damage[5]);
|
|
}
|
|
}
|
|
|
|
SINGLE_BATTLE_TEST("Punching Glove vs Muscle Band Damage calculation")
|
|
{
|
|
s16 dmgPlayer, dmgOpponent;
|
|
s16 expectedDamagePlayer, expectedDamageOpponent;
|
|
PARAMETRIZE { expectedDamagePlayer = 204, expectedDamageOpponent = 201; }
|
|
PARAMETRIZE { expectedDamagePlayer = 201, expectedDamageOpponent = 198; }
|
|
PARAMETRIZE { expectedDamagePlayer = 199, expectedDamageOpponent = 196; }
|
|
PARAMETRIZE { expectedDamagePlayer = 196, expectedDamageOpponent = 193; }
|
|
PARAMETRIZE { expectedDamagePlayer = 195, expectedDamageOpponent = 192; }
|
|
PARAMETRIZE { expectedDamagePlayer = 193, expectedDamageOpponent = 190; }
|
|
PARAMETRIZE { expectedDamagePlayer = 190, expectedDamageOpponent = 187; }
|
|
PARAMETRIZE { expectedDamagePlayer = 189, expectedDamageOpponent = 186; }
|
|
PARAMETRIZE { expectedDamagePlayer = 187, expectedDamageOpponent = 184; }
|
|
PARAMETRIZE { expectedDamagePlayer = 184, expectedDamageOpponent = 181; }
|
|
PARAMETRIZE { expectedDamagePlayer = 183, expectedDamageOpponent = 180; }
|
|
PARAMETRIZE { expectedDamagePlayer = 181, expectedDamageOpponent = 178; }
|
|
PARAMETRIZE { expectedDamagePlayer = 178, expectedDamageOpponent = 175; }
|
|
PARAMETRIZE { expectedDamagePlayer = 177, expectedDamageOpponent = 174; }
|
|
PARAMETRIZE { expectedDamagePlayer = 174, expectedDamageOpponent = 172; }
|
|
PARAMETRIZE { expectedDamagePlayer = 172, expectedDamageOpponent = 169; }
|
|
GIVEN {
|
|
PLAYER(SPECIES_MAKUHITA) { Item(ITEM_PUNCHING_GLOVE); }
|
|
OPPONENT(SPECIES_MAKUHITA) { Item(ITEM_MUSCLE_BAND); }
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
|
|
MOVE(opponent, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
|
|
}
|
|
}
|
|
SCENE {
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player);
|
|
HP_BAR(opponent, captureDamage: &dmgPlayer);
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, opponent);
|
|
HP_BAR(player, captureDamage: &dmgOpponent);
|
|
}
|
|
THEN {
|
|
EXPECT_EQ(expectedDamagePlayer, dmgPlayer);
|
|
EXPECT_EQ(expectedDamageOpponent, dmgOpponent);
|
|
}
|
|
}
|
|
|
|
SINGLE_BATTLE_TEST("Gem boosted Damage calculation")
|
|
{
|
|
s16 dmg;
|
|
s16 expectedDamage;
|
|
PARAMETRIZE { expectedDamage = 240; }
|
|
PARAMETRIZE { expectedDamage = 237; }
|
|
PARAMETRIZE { expectedDamage = 234; }
|
|
PARAMETRIZE { expectedDamage = 232; }
|
|
PARAMETRIZE { expectedDamage = 229; }
|
|
PARAMETRIZE { expectedDamage = 228; }
|
|
PARAMETRIZE { expectedDamage = 225; }
|
|
PARAMETRIZE { expectedDamage = 222; }
|
|
PARAMETRIZE { expectedDamage = 220; }
|
|
PARAMETRIZE { expectedDamage = 217; }
|
|
PARAMETRIZE { expectedDamage = 216; }
|
|
PARAMETRIZE { expectedDamage = 213; }
|
|
PARAMETRIZE { expectedDamage = 210; }
|
|
PARAMETRIZE { expectedDamage = 208; }
|
|
PARAMETRIZE { expectedDamage = 205; }
|
|
PARAMETRIZE { expectedDamage = 204; }
|
|
GIVEN {
|
|
PLAYER(SPECIES_MAKUHITA) { Item(ITEM_FIGHTING_GEM); }
|
|
OPPONENT(SPECIES_MAKUHITA);
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i));
|
|
}
|
|
}
|
|
SCENE {
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player);
|
|
HP_BAR(opponent, captureDamage: &dmg);
|
|
}
|
|
THEN {
|
|
EXPECT_EQ(expectedDamage, dmg);
|
|
}
|
|
}
|
|
|
|
#define NUM_DAMAGE_SPREADS (DMG_ROLL_PERCENT_HI - DMG_ROLL_PERCENT_LO) + 1
|
|
|
|
static const s16 sThunderShockTransistorSpread[] = { 54, 55, 56, 57, 57, 58, 59, 60, 60, 60, 61, 62, 63, 63, 64, 65 };
|
|
static const s16 sThunderShockRegularSpread[] = { 42, 42, 43, 43, 44, 45, 45, 45, 46, 46, 47, 48, 48, 48, 49, 50 };
|
|
static const s16 sWildChargeTransistorSpread[] = { 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145 };
|
|
static const s16 sWildChargeRegularSpread[] = { 94, 96, 96, 98, 99, 100, 101, 102, 103, 105, 105, 107, 108, 109, 110, 111 };
|
|
|
|
DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage)
|
|
{
|
|
s16 expectedDamageTransistorSpec = 0, expectedDamageRegularPhys = 0, expectedDamageRegularSpec = 0, expectedDamageTransistorPhys = 0;
|
|
s16 damagePlayerLeft, damagePlayerRight, damageOpponentLeft, damageOpponentRight;
|
|
for (u32 spread = 0; spread < 16; ++spread) {
|
|
PARAMETRIZE { expectedDamageTransistorSpec = sThunderShockTransistorSpread[spread],
|
|
expectedDamageRegularSpec = sThunderShockRegularSpread[spread],
|
|
expectedDamageTransistorPhys = sWildChargeTransistorSpread[spread],
|
|
expectedDamageRegularPhys = sWildChargeRegularSpread[spread];
|
|
}
|
|
}
|
|
GIVEN {
|
|
ASSUME(GetMoveType(MOVE_WILD_CHARGE) == TYPE_ELECTRIC);
|
|
ASSUME(GetMoveType(MOVE_THUNDER_SHOCK) == TYPE_ELECTRIC);
|
|
ASSUME(GetMoveCategory(MOVE_WILD_CHARGE) == DAMAGE_CATEGORY_PHYSICAL);
|
|
ASSUME(GetMoveCategory(MOVE_THUNDER_SHOCK) == DAMAGE_CATEGORY_SPECIAL);
|
|
ASSUME(NUM_DAMAGE_SPREADS == 16);
|
|
|
|
PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); }
|
|
PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); }
|
|
OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); }
|
|
OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); }
|
|
} WHEN {
|
|
TURN {
|
|
MOVE(playerLeft, MOVE_THUNDER_SHOCK, target: opponentLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
|
|
MOVE(playerRight, MOVE_THUNDER_SHOCK, target: opponentRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
|
|
MOVE(opponentLeft, MOVE_WILD_CHARGE, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
|
|
MOVE(opponentRight, MOVE_WILD_CHARGE, target: playerRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i));
|
|
}
|
|
} SCENE {
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerLeft);
|
|
HP_BAR(opponentLeft, captureDamage: &damageOpponentLeft);
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerRight);
|
|
HP_BAR(opponentRight, captureDamage: &damageOpponentRight);
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentLeft);
|
|
HP_BAR(playerLeft, captureDamage: &damagePlayerLeft);
|
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentRight);
|
|
HP_BAR(playerRight, captureDamage: &damagePlayerRight);
|
|
} THEN {
|
|
EXPECT_EQ(damageOpponentLeft, expectedDamageRegularSpec);
|
|
EXPECT_EQ(damageOpponentRight, expectedDamageTransistorSpec);
|
|
EXPECT_EQ(damagePlayerLeft, expectedDamageRegularPhys);
|
|
EXPECT_EQ(damagePlayerRight, expectedDamageTransistorPhys);
|
|
}
|
|
}
|