From b6b6e91959504233d742c7d1b89d7b23f23b7e08 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 7 May 2025 16:50:12 +0200 Subject: [PATCH] A lot of tests (#6734) Co-authored-by: Hedara --- include/config/test.h | 2 + include/constants/flags.h | 2 +- include/constants/generational_changes.h | 1 + include/generational_changes.h | 1 + src/battle_util.c | 4 +- test/battle/ability/anticipation.c | 361 ++++++++++++++++++++++- test/battle/ability/drought.c | 82 ++++- test/battle/ability/liquid_ooze.c | 26 +- test/battle/ability/sand_force.c | 63 +++- test/battle/ability/sand_rush.c | 51 +++- test/battle/ability/sand_veil.c | 16 +- test/battle/ability/slush_rush.c | 65 +++- test/battle/ability/solar_power.c | 71 ++++- test/battle/weather/hail.c | 14 + test/battle/weather/sandstorm.c | 17 ++ 15 files changed, 738 insertions(+), 38 deletions(-) diff --git a/include/config/test.h b/include/config/test.h index a8e2f4ab11..4363a5f82a 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1136,5 +1136,7 @@ // Flags #undef B_FLAG_SLEEP_CLAUSE #define B_FLAG_SLEEP_CLAUSE TESTING_FLAG_SLEEP_CLAUSE +#undef B_FLAG_INVERSE_BATTLE +#define B_FLAG_INVERSE_BATTLE TESTING_FLAG_INVERSE_BATTLE #endif // GUARD_CONFIG_TEST_H diff --git a/include/constants/flags.h b/include/constants/flags.h index aec9ebbd92..47e96c528f 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1663,7 +1663,7 @@ #if TESTING #define TESTING_FLAGS_START 0x5000 #define TESTING_FLAG_SLEEP_CLAUSE (TESTING_FLAGS_START + 0x0) -#define TESTING_FLAG_UNUSED_1 (TESTING_FLAGS_START + 0x1) +#define TESTING_FLAG_INVERSE_BATTLE (TESTING_FLAGS_START + 0x1) #define TESTING_FLAG_UNUSED_2 (TESTING_FLAGS_START + 0x2) #define TESTING_FLAG_UNUSED_3 (TESTING_FLAGS_START + 0x3) #define TESTING_FLAG_UNUSED_4 (TESTING_FLAGS_START + 0x4) diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 5e93679643..e2f40ea328 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -12,6 +12,7 @@ enum GenConfigTag GEN_CONFIG_GALE_WINGS, GEN_CONFIG_HEAL_BELL_SOUNDPROOF, GEN_CONFIG_TELEPORT_BEHAVIOR, + GEN_CONFIG_ABILITY_WEATHER, GEN_CONFIG_MOODY_STATS, GEN_CONFIG_COUNT }; diff --git a/include/generational_changes.h b/include/generational_changes.h index 4f555b9368..bbd12445e4 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -15,6 +15,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_GALE_WINGS] = B_GALE_WINGS, [GEN_CONFIG_HEAL_BELL_SOUNDPROOF] = B_HEAL_BELL_SOUNDPROOF, [GEN_CONFIG_TELEPORT_BEHAVIOR] = B_TELEPORT_BEHAVIOR, + [GEN_CONFIG_ABILITY_WEATHER] = B_ABILITY_WEATHER, [GEN_CONFIG_MOODY_STATS] = B_MOODY_ACC_EVASION, }; diff --git a/src/battle_util.c b/src/battle_util.c index b03718f4b9..afa9b5b94a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4050,7 +4050,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbilit { return FALSE; } - else if (B_ABILITY_WEATHER < GEN_6 && viaAbility) + else if (GetGenConfig(GEN_CONFIG_ABILITY_WEATHER) < GEN_6 && viaAbility) { gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; return TRUE; @@ -4900,7 +4900,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { move = gBattleMons[i].moves[j]; moveType = GetBattleMoveType(move); - if (CalcTypeEffectivenessMultiplier(move, moveType, i, battler, ABILITY_ANTICIPATION, FALSE) >= UQ_4_12(2.0)) + if (CalcTypeEffectivenessMultiplier(move, moveType, i, battler, ABILITY_ANTICIPATION, FALSE) >= UQ_4_12(2.0) || GetMoveEffect(move) == EFFECT_OHKO) { effect++; break; diff --git a/test/battle/ability/anticipation.c b/test/battle/ability/anticipation.c index a15ff153d9..7a45537296 100644 --- a/test/battle/ability/anticipation.c +++ b/test/battle/ability/anticipation.c @@ -1,24 +1,353 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effective move"); -TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move"); -TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a Self-Destruct or Explosion (Gen4)"); -TO_DO_BATTLE_TEST("Anticipation treats Self-Destruct and Explosion like all other Normal types (Gen5+)"); +SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a super-effective move") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CLOSE_COMBAT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} +SINGLE_BATTLE_TEST("Anticipation causes notifies if an opponent has a One-hit KO move") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_FISSURE) == EFFECT_OHKO); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_FISSURE, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats Self-Destruct and Explosion like all other Normal types (Gen5+)") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_EXPLOSION) == EFFECT_EXPLOSION); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_EXPLOSION, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation doesn't consider Normalize into their effectiveness (Gen5+)") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); Moves(MOVE_CLOSE_COMBAT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation doesn't consider Scrappy into their effectiveness (Gen5+)") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(GetMoveType(MOVE_CLOSE_COMBAT) == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_KANGASKHAN) { Ability(ABILITY_SCRAPPY); Moves(MOVE_CLOSE_COMBAT, MOVE_TRICK_OR_TREAT, MOVE_SKILL_SWAP, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_TRICK_OR_TREAT); MOVE(player, MOVE_SKILL_SWAP); } + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TRICK_OR_TREAT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)") +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_SKARMORY); + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_EARTHQUAKE, MOVE_GRAVITY, MOVE_SCRATCH, MOVE_POUND); } + } WHEN { + TURN { MOVE(opponent, MOVE_GRAVITY); MOVE(player, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_GRAVITY, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)") +{ + u32 move, species, typeAtk, typeDef; + PARAMETRIZE { move = MOVE_COUNTER; species = SPECIES_RATICATE; typeAtk = TYPE_FIGHTING; typeDef = TYPE_NORMAL; } + PARAMETRIZE { move = MOVE_METAL_BURST; species = SPECIES_ROGGENROLA; typeAtk = TYPE_STEEL; typeDef = TYPE_ROCK; } + PARAMETRIZE { move = MOVE_MIRROR_COAT; species = SPECIES_NIDORINO; typeAtk = TYPE_PSYCHIC; typeDef = TYPE_POISON; } + GIVEN { + ASSUME(GetMoveType(move) == typeAtk); + ASSUME(gSpeciesInfo[species].types[0] == typeDef); + ASSUME(gSpeciesInfo[species].types[1] == typeDef); + PLAYER(species); + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(move, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation considers Synchronoise as an ordinary Psychic-type move") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_SYNCHRONOISE) == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_NIDORINO].types[0] == TYPE_POISON); + ASSUME(gSpeciesInfo[SPECIES_NIDORINO].types[1] == TYPE_POISON); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] != TYPE_POISON); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] != TYPE_POISON); + PLAYER(SPECIES_NIDORINO); + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_SYNCHRONOISE, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation considers Freeze-Dry as an ordinary Ice-type move") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(GetMoveType(MOVE_FREEZE_DRY) == TYPE_ICE); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[0] == TYPE_WATER); + ASSUME(gSpeciesInfo[SPECIES_SQUIRTLE].types[1] == TYPE_WATER); + PLAYER(SPECIES_SQUIRTLE); + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_FREEZE_DRY, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation considers Flying Press as an ordinary Fighting-type move") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(GetMoveType(MOVE_FLYING_PRESS) == TYPE_FIGHTING); + ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_TANGELA].types[1] == TYPE_GRASS); + PLAYER(SPECIES_TANGELA); + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_FLYING_PRESS, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation considers Aura Wheel as an ordinary Electric-type move") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_AURA_WHEEL) == TYPE_ELECTRIC); + ASSUME(gSpeciesInfo[SPECIES_PONYTA_GALAR].types[0] == TYPE_PSYCHIC); + ASSUME(gSpeciesInfo[SPECIES_PONYTA_GALAR].types[1] == TYPE_PSYCHIC); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_PONYTA_GALAR) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); Moves(MOVE_AURA_WHEEL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { SWITCH(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Judgment") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_JUDGMENT) == EFFECT_CHANGE_TYPE_ON_ITEM); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_ARCEUS) { Item(ITEM_FIST_PLATE); Moves(MOVE_JUDGMENT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Weather Ball") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_WEATHER_BALL) == EFFECT_WEATHER_BALL); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL); + PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); Speed(2); } + OPPONENT(SPECIES_NINETALES) { Ability(ABILITY_DROUGHT); Moves(MOVE_WEATHER_BALL, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); Speed(4); } + } WHEN { + TURN { MOVE(opponent, MOVE_SKILL_SWAP); MOVE(player, MOVE_SKILL_SWAP); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_DROUGHT); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, player); + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Natural Gift") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_NATURAL_GIFT) == EFFECT_NATURAL_GIFT); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LEPPA_BERRY); Moves(MOVE_NATURAL_GIFT, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Techno Blast") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_TECHNO_BLAST) == EFFECT_CHANGE_TYPE_ON_ITEM); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL); + PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_GENESECT) { Item(ITEM_BURN_DRIVE); Moves(MOVE_TECHNO_BLAST, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Revelation Dance") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_REVELATION_DANCE) == EFFECT_REVELATION_DANCE); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL); + ASSUME(gSpeciesInfo[SPECIES_ORICORIO_BAILE].types[0] == TYPE_FIRE); + PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_ORICORIO_BAILE) { Moves(MOVE_REVELATION_DANCE, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal), Multi-Attack") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_MULTI_ATTACK) == EFFECT_CHANGE_TYPE_ON_ITEM); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_SILVALLY) { Item(ITEM_FIGHTING_MEMORY); Moves(MOVE_MULTI_ATTACK, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation does not consider Strong Winds on type matchups") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_RAYQUAZA_MEGA].types[0] == TYPE_DRAGON); + ASSUME(gSpeciesInfo[SPECIES_RAYQUAZA_MEGA].types[1] == TYPE_FLYING); + PLAYER(SPECIES_RAYQUAZA) { Moves(MOVE_DRAGON_ASCENT, MOVE_CELEBRATE); } + OPPONENT(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Moves(MOVE_ROCK_SLIDE, MOVE_SKILL_SWAP, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ABILITY_POPUP(player, ABILITY_DELTA_STREAM); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent); + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation does not consider ate-abilities") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_SCRATCH) == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_WORMADAM_PLANT].types[0] == TYPE_BUG); + ASSUME(gSpeciesInfo[SPECIES_WORMADAM_PLANT].types[1] == TYPE_GRASS); + PLAYER(SPECIES_WORMADAM_PLANT) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_AURORUS) { Ability(ABILITY_REFRIGERATE); Moves(MOVE_GROWL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + NOT ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +SINGLE_BATTLE_TEST("Anticipation treats Hidden Power as its dynamic type (Gen6+)") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[0] == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_EEVEE].types[1] == TYPE_NORMAL); + PLAYER(SPECIES_EEVEE) { Ability(ABILITY_ANTICIPATION); Item(ITEM_CHOPLE_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_HIDDEN_POWER, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); HPIV(30); AttackIV(2); DefenseIV(31); SpAttackIV(30); SpDefenseIV(30); SpeedIV(30); } + } WHEN { + TURN { MOVE(opponent, MOVE_HIDDEN_POWER); } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); // Check that the item is triggered + ANIMATION(ANIM_TYPE_MOVE, MOVE_HIDDEN_POWER, opponent); + HP_BAR(opponent); + MESSAGE("It's super effective!"); + } +} + +SINGLE_BATTLE_TEST("Anticipation considers Inverse Battle types") +{ + GIVEN { + FLAG_SET(B_FLAG_INVERSE_BATTLE); + ASSUME(GetMoveType(MOVE_SCRATCH) == TYPE_NORMAL); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[0] == TYPE_GRASS); + ASSUME(gSpeciesInfo[SPECIES_FERROTHORN].types[1] == TYPE_STEEL); + PLAYER(SPECIES_FERROTHORN) { Ability(ABILITY_ANTICIPATION); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_GROWL, MOVE_SCRATCH, MOVE_POUND, MOVE_CELEBRATE); } + } WHEN { + TURN { } + } SCENE { + ABILITY_POPUP(player, ABILITY_ANTICIPATION); + } +} + +TO_DO_BATTLE_TEST("Anticipation causes notifies if an opponent has a Self-Destruct or Explosion (Gen4)"); TO_DO_BATTLE_TEST("Anticipation considers Scrappy and Normalize into their effectiveness (Gen4)"); -TO_DO_BATTLE_TEST("Anticipation doesn't consider Scrappy and Normalize into their effectiveness (Gen5+)"); TO_DO_BATTLE_TEST("Anticipation considers Gravity into their effectiveness (Gen4)"); -TO_DO_BATTLE_TEST("Anticipation doesn't consider Gravity into their effectiveness (Gen5+)"); TO_DO_BATTLE_TEST("Anticipation doesn't trigger from Counter, Metal Burst or Mirror Coat (Gen4)"); -TO_DO_BATTLE_TEST("Anticipation counts Counter, Metal Burst or Mirror Coat as attacking moves of their types (Gen5+)"); -TO_DO_BATTLE_TEST("Anticipation considers Synchronoise as an ordinary Psychic-type move"); -TO_DO_BATTLE_TEST("Anticipation considers Freeze-Dry as an ordinary Ice-type move"); -TO_DO_BATTLE_TEST("Anticipation considers Flying Press as an ordinary Fighting-type move"); -TO_DO_BATTLE_TEST("Anticipation considers Aura Wheel as an ordinary Electric-type move"); -TO_DO_BATTLE_TEST("Anticipation considers Inverse Battle types"); //Check with Normal-type moves -TO_DO_BATTLE_TEST("Anticipation treats dynamic move types as their base type (Normal)"); // Judgment, Weather Ball, Natural Gift, Techno Blast, Revelation Dance, Multi Attack TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as Normal Type (Gen4-5)"); -TO_DO_BATTLE_TEST("Anticipation treats Hidden Power as its dynamic type (Gen6+)"); -TO_DO_BATTLE_TEST("Anticipation does not consider Strong Winds on type matchups"); -TO_DO_BATTLE_TEST("Anticipation does not consider ate-abilities"); diff --git a/test/battle/ability/drought.c b/test/battle/ability/drought.c index bbe4dbe853..c28b0895b8 100644 --- a/test/battle/ability/drought.c +++ b/test/battle/ability/drought.c @@ -1,5 +1,83 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)"); -TO_DO_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)"); +SINGLE_BATTLE_TEST("Drought sets up sun for 5 turns (Gen6+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_DROUGHT); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight faded."); + } +} + +SINGLE_BATTLE_TEST("Drought sets up sun for 8 turns with Heat Rock (Gen6+)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_6); + PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); Item(ITEM_HEAT_ROCK); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_DROUGHT); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight faded."); + } +} + +SINGLE_BATTLE_TEST("Drought sets up permanent sun (Gen3-5)") +{ + GIVEN { + WITH_CONFIG(GEN_CONFIG_ABILITY_WEATHER, GEN_3); + PLAYER(SPECIES_NINETALES) { Moves(MOVE_CELEBRATE); Ability(ABILITY_DROUGHT); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_CELEBRATE); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ABILITY_POPUP(player, ABILITY_DROUGHT); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + MESSAGE("The sunlight is strong."); + NOT MESSAGE("The sunlight faded."); + } +} diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index fb20522937..bb2fc81afa 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -138,5 +138,27 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder" } } -TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4"); -TO_DO_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+"); +SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+") +{ + s16 damage; + GIVEN { + ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_SLEEP); + ASSUME(GetMoveEffect(MOVE_DREAM_EATER) == EFFECT_DREAM_EATER); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TENTACRUEL) { Ability(ABILITY_LIQUID_OOZE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCRATCH); MOVE(player, MOVE_SPORE); } + TURN { MOVE(player, MOVE_DREAM_EATER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPORE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DREAM_EATER, player); + HP_BAR(opponent); + HP_BAR(player, captureDamage: &damage); + } THEN { + EXPECT_LT(damage, 0); + } +} + +TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4") diff --git a/test/battle/ability/sand_force.c b/test/battle/ability/sand_force.c index e17722a885..959d437980 100644 --- a/test/battle/ability/sand_force.c +++ b/test/battle/ability/sand_force.c @@ -1,6 +1,63 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Sand Force prevents damage from sandstorm"); -TO_DO_BATTLE_TEST("Sand Force increases the power of Rock-, Ground- and Steel-type moves by 30% in sandstorm"); -TO_DO_BATTLE_TEST("Sand Force increases move power if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Sand Force prevents damage from sandstorm") +{ + u32 type1 = gSpeciesInfo[SPECIES_SHELLOS].types[0]; + u32 type2 = gSpeciesInfo[SPECIES_SHELLOS].types[1]; + GIVEN { + ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); + ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); + ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL); + PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SANDSTORM); } + } SCENE { + NOT HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Sand Force increases the power of Rock-, Ground- and Steel-type moves by 30% in sandstorm", s16 damage) +{ + u32 moveOpponent, movePlayer; + PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_ROCK_THROW; } + PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_ROCK_THROW; } + PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_EARTHQUAKE; } + PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_EARTHQUAKE; } + PARAMETRIZE { moveOpponent = MOVE_CELEBRATE; movePlayer = MOVE_IRON_HEAD; } + PARAMETRIZE { moveOpponent = MOVE_SANDSTORM; movePlayer = MOVE_IRON_HEAD; } + GIVEN { + ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK); + ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND); + ASSUME(GetMoveType(MOVE_IRON_HEAD) == TYPE_STEEL); + PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, moveOpponent); MOVE(player, movePlayer); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.3), results[3].damage); + EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.3), results[5].damage); + } +} + +SINGLE_BATTLE_TEST("Sand Force don't increase move power if Cloud Nine/Air Lock is on the field", s16 damage) +{ + u32 move; + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_SANDSTORM; } + GIVEN { + ASSUME(GetMoveType(MOVE_ROCK_THROW) == TYPE_ROCK); + PLAYER(SPECIES_SHELLOS) { Ability(ABILITY_SAND_FORCE); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_ROCK_THROW); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/battle/ability/sand_rush.c b/test/battle/ability/sand_rush.c index fa7695c129..08dd22ef57 100644 --- a/test/battle/ability/sand_rush.c +++ b/test/battle/ability/sand_rush.c @@ -1,6 +1,51 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Sand Rush prevents damage from sandstorm"); -TO_DO_BATTLE_TEST("Sand Rush doubles speed from sandstorm"); -TO_DO_BATTLE_TEST("Sand Rush doesn't double speed if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Sand Rush prevents damage from sandstorm") +{ + u32 type1 = gSpeciesInfo[SPECIES_STOUTLAND].types[0]; + u32 type2 = gSpeciesInfo[SPECIES_STOUTLAND].types[1]; + GIVEN { + ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); + ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); + ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL); + PLAYER(SPECIES_STOUTLAND) { Ability(ABILITY_SAND_RUSH); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SANDSTORM); } + } SCENE { + NOT HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Sand Rush doubles speed from sandstorm") +{ + GIVEN { + PLAYER(SPECIES_SANDSLASH) { Ability(ABILITY_SAND_RUSH); Speed(100); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(199); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SANDSTORM); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} + +SINGLE_BATTLE_TEST("Sand Rush doesn't double speed if Cloud Nine/Air Lock is on the field") +{ + GIVEN { + PLAYER(SPECIES_SANDSLASH) { Ability(ABILITY_SAND_RUSH); Speed(100); } + OPPONENT(SPECIES_GOLDUCK) { Speed(199); Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SANDSTORM); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SANDSTORM, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + } +} diff --git a/test/battle/ability/sand_veil.c b/test/battle/ability/sand_veil.c index 7622d18763..e2bfdd02f8 100644 --- a/test/battle/ability/sand_veil.c +++ b/test/battle/ability/sand_veil.c @@ -29,5 +29,17 @@ SINGLE_BATTLE_TEST("Sand Veil increases evasion during sandstorm") } } -TO_DO_BATTLE_TEST("Sand Veil doesn't prevent Sandstorm damage if Cloud Nine/Air Lock is on the field"); -TO_DO_BATTLE_TEST("Sand Veil doesn't increase evasion if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Sand Veil doesn't increase evasion if Cloud Nine/Air Lock is on the field") +{ + PASSES_RANDOMLY(5, 5, RNG_ACCURACY); + GIVEN { + ASSUME(GetMoveAccuracy(MOVE_POUND) == 100); + PLAYER(SPECIES_SANDSHREW) { Ability(ABILITY_SAND_VEIL); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SANDSTORM); } + TURN { MOVE(opponent, MOVE_POUND); } + } SCENE { + HP_BAR(player); + } +} diff --git a/test/battle/ability/slush_rush.c b/test/battle/ability/slush_rush.c index 8ae62454bb..d7508c2cb4 100644 --- a/test/battle/ability/slush_rush.c +++ b/test/battle/ability/slush_rush.c @@ -1,6 +1,65 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Slush Rush doubles speed from hail"); -TO_DO_BATTLE_TEST("Slush Rush doubles speed from snow"); -TO_DO_BATTLE_TEST("Slush Rush doesn't double speed if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Slush Rush doubles speed from hail") +{ + GIVEN { + PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(199); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_HAIL); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} + +SINGLE_BATTLE_TEST("Slush Rush doubles speed from snow") +{ + GIVEN { + PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(199); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNOWSCAPE); } + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + } +} + +SINGLE_BATTLE_TEST("Slush Rush doesn't double speed if Cloud Nine/Air Lock is on the field") +{ + GIVEN { + PLAYER(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); Speed(100); } + OPPONENT(SPECIES_GOLDUCK) { Speed(199); Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_SNOWSCAPE); } + TURN { MOVE(opponent, MOVE_CELEBRATE); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SNOWSCAPE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + } +} + +SINGLE_BATTLE_TEST("Slush Rush doesn't prevent non-Ice types from taking damage in Hail") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ICE); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ICE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CETITAN) { Ability(ABILITY_SLUSH_RUSH); } + } WHEN { + TURN { MOVE(player, MOVE_HAIL); MOVE(opponent, MOVE_SKILL_SWAP); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, player); + HP_BAR(player); + } +} diff --git a/test/battle/ability/solar_power.c b/test/battle/ability/solar_power.c index f14ea11ee1..1fdccad5be 100644 --- a/test/battle/ability/solar_power.c +++ b/test/battle/ability/solar_power.c @@ -1,7 +1,70 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Solar Power increases a Sp. Attack by x1.5 in Sun"); -TO_DO_BATTLE_TEST("Solar Power doesn't increases a Sp. Attack if Cloud Nine/Air Lock is on the field"); -TO_DO_BATTLE_TEST("Solar Power causes the Pokémon to lose 1/8 max HP in Sun"); -TO_DO_BATTLE_TEST("Solar Power doesn't cause the Pokémon to lose 1/8 max HP if Cloud Nine/Air Lock is on the field"); +SINGLE_BATTLE_TEST("Solar Power increases a Sp. Attack by x1.5 in Sun", s16 damage) +{ + u32 move; + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_SUNNY_DAY; } + GIVEN { + ASSUME(GetMovePower(MOVE_HYPER_VOICE) > 0); + ASSUME(GetMoveCategory(MOVE_HYPER_VOICE) == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_HYPER_VOICE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + if (move == MOVE_SUNNY_DAY) + HP_BAR(player); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Solar Power doesn't increases a Sp. Attack if Cloud Nine/Air Lock is on the field", s16 damage) +{ + u32 move; + PARAMETRIZE { move = MOVE_CELEBRATE; } + PARAMETRIZE { move = MOVE_SUNNY_DAY; } + GIVEN { + ASSUME(GetMovePower(MOVE_HYPER_VOICE) > 0); + ASSUME(GetMoveCategory(MOVE_HYPER_VOICE) == DAMAGE_CATEGORY_SPECIAL); + PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_HYPER_VOICE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Solar Power causes the Pokémon to lose 1/8 max HP in Sun") +{ + GIVEN { + PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); MaxHP(80); HP(80); } + OPPONENT(SPECIES_WOBBUFFET); + } SCENE { + TURN { MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + HP_BAR(player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP - player->maxHP/8); + } +} + +SINGLE_BATTLE_TEST("Solar Power doesn't cause the Pokémon to lose 1/8 max HP if Cloud Nine/Air Lock is on the field") +{ + GIVEN { + PLAYER(SPECIES_CHARIZARD) { Ability(ABILITY_SOLAR_POWER); MaxHP(80); HP(80); } + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUNNY_DAY); } + } SCENE { + NOT HP_BAR(player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP); + } +} diff --git a/test/battle/weather/hail.c b/test/battle/weather/hail.c index 6c7f7bcdec..100692de20 100644 --- a/test/battle/weather/hail.c +++ b/test/battle/weather/hail.c @@ -82,3 +82,17 @@ SINGLE_BATTLE_TEST("Hail damage rounds properly when maxHP < 16") HP_BAR(player, damage: 1); } } + +SINGLE_BATTLE_TEST("Hail doesn't do damage when weather is negated") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[0] != TYPE_ICE); + ASSUME(gSpeciesInfo[SPECIES_WOBBUFFET].types[1] != TYPE_ICE); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(player, MOVE_HAIL); } + } SCENE { + NOT HP_BAR(player); + } +} diff --git a/test/battle/weather/sandstorm.c b/test/battle/weather/sandstorm.c index dcac3f71c3..2ff0697597 100644 --- a/test/battle/weather/sandstorm.c +++ b/test/battle/weather/sandstorm.c @@ -94,3 +94,20 @@ SINGLE_BATTLE_TEST("Sandstorm damage rounds properly when maxHP < 16") HP_BAR(player, damage: 1); } } + +SINGLE_BATTLE_TEST("Sandstorm doesn't do damage when weather is negated") +{ + u32 type1 = gSpeciesInfo[SPECIES_STOUTLAND].types[0]; + u32 type2 = gSpeciesInfo[SPECIES_STOUTLAND].types[1]; + GIVEN { + ASSUME(type1 != TYPE_ROCK && type2 != TYPE_ROCK); + ASSUME(type1 != TYPE_GROUND && type2 != TYPE_GROUND); + ASSUME(type1 != TYPE_STEEL && type2 != TYPE_STEEL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOLDUCK) { Ability(ABILITY_CLOUD_NINE); } + } WHEN { + TURN { MOVE(player, MOVE_SANDSTORM); } + } SCENE { + NOT HP_BAR(player); + } +}