#include "global.h" #include "test_battle.h" SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses") { u32 move; PARAMETRIZE { move = MOVE_DYNAMIC_PUNCH; } PARAMETRIZE { move = MOVE_THUNDER; } PARAMETRIZE { move = MOVE_HYDRO_PUMP; } PARAMETRIZE { move = MOVE_RAZOR_LEAF; } PARAMETRIZE { move = MOVE_SCRATCH; } ASSUME(0 < gBattleMoves[move].accuracy && gBattleMoves[move].accuracy <= 100); PASSES_RANDOMLY(gBattleMoves[move].accuracy, 100, RNG_ACCURACY); GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, move); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, move, player); } } SINGLE_BATTLE_TEST("Secondary Effect Chance controls the proportion of secondary effects") { u32 move; PARAMETRIZE { move = MOVE_THUNDER_SHOCK; } PARAMETRIZE { move = MOVE_DISCHARGE; } PARAMETRIZE { move = MOVE_NUZZLE; } ASSUME(gBattleMoves[move].effect == EFFECT_PARALYZE_HIT); ASSUME(0 < gBattleMoves[move].secondaryEffectChance && gBattleMoves[move].secondaryEffectChance <= 100); PASSES_RANDOMLY(gBattleMoves[move].secondaryEffectChance, 100, RNG_SECONDARY_EFFECT); GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, move); } } SCENE { STATUS_ICON(opponent, paralysis: TRUE); } } SINGLE_BATTLE_TEST("Turn order is determined by priority") { GIVEN { ASSUME(gBattleMoves[MOVE_QUICK_ATTACK].priority > gBattleMoves[MOVE_TACKLE].priority); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_TACKLE); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); } } SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties") { GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(2); } OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } } WHEN { TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_QUICK_ATTACK); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, opponent); } } SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie") { KNOWN_FAILING; // The algorithm is significantly biased. PASSES_RANDOMLY(1, 2); GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(1); } OPPONENT(SPECIES_WOBBUFFET) { Speed(1); } } WHEN { TURN { MOVE(player, MOVE_QUICK_ATTACK); MOVE(opponent, MOVE_QUICK_ATTACK); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, player); ANIMATION(ANIM_TYPE_MOVE, MOVE_QUICK_ATTACK, opponent); } } SINGLE_BATTLE_TEST("Critical hits occur at a 1/24 rate") { ASSUME(B_CRIT_CHANCE >= GEN_7); PASSES_RANDOMLY(1, 24, RNG_CRITICAL_HIT); GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_SCRATCH); } } SCENE { MESSAGE("A critical hit!"); } } SINGLE_BATTLE_TEST("Slash's critical hits occur at a 1/8 rate") { ASSUME(B_CRIT_CHANCE >= GEN_7); ASSUME(gBattleMoves[MOVE_SLASH].highCritRatio); PASSES_RANDOMLY(1, 8, RNG_CRITICAL_HIT); GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_SLASH); } } SCENE { MESSAGE("A critical hit!"); } } SINGLE_BATTLE_TEST("Critical hits deal 50% more damage", s16 damage) { bool32 criticalHit; PARAMETRIZE { criticalHit = FALSE; } PARAMETRIZE { criticalHit = TRUE; } GIVEN { ASSUME(B_CRIT_MULTIPLIER >= GEN_6); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_SCRATCH, criticalHit: criticalHit); } } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); } } SINGLE_BATTLE_TEST("Critical hits do not ignore positive stat stages", s16 damage) { u32 move; PARAMETRIZE { move = MOVE_CELEBRATE; } PARAMETRIZE { move = MOVE_HOWL; } PARAMETRIZE { move = MOVE_TAIL_WHIP; } GIVEN { ASSUME(gBattleMoves[MOVE_SCRATCH].split == SPLIT_PHYSICAL); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, move); } TURN { MOVE(player, MOVE_SCRATCH, criticalHit: TRUE); } } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } THEN { if (i > 0) EXPECT_LT(results[0].damage, results[i].damage); } } SINGLE_BATTLE_TEST("Critical hits ignore negative stat stages", s16 damage) { u32 move; PARAMETRIZE { move = MOVE_CELEBRATE; } PARAMETRIZE { move = MOVE_HARDEN; } PARAMETRIZE { move = MOVE_GROWL; } GIVEN { ASSUME(gBattleMoves[MOVE_SCRATCH].split == SPLIT_PHYSICAL); PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(opponent, move); } TURN { MOVE(player, MOVE_SCRATCH, criticalHit: TRUE); } } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } THEN { if (i > 0) EXPECT_EQ(results[0].damage, results[i].damage); } }