From d53c616e068c73713ffc1932947a4e4d60f8aedf Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 24 Apr 2025 20:13:03 +0200 Subject: [PATCH] Adds a whole bunch of new tests (#6685) --- test/battle/ability/analytic.c | 20 +++- test/battle/move_effect/aqua_ring.c | 30 +++++- test/battle/move_effect/attract.c | 106 +++++++++++++++++++- test/battle/move_effect/bestow.c | 134 ++++++++++++++++++++++++-- test/battle/move_effect/captivate.c | 113 +++++++++++++++++++++- test/battle/move_effect/entrainment.c | 48 ++++++++- 6 files changed, 430 insertions(+), 21 deletions(-) diff --git a/test/battle/ability/analytic.c b/test/battle/ability/analytic.c index 44c42ae2d5..526e0983f4 100644 --- a/test/battle/ability/analytic.c +++ b/test/battle/ability/analytic.c @@ -1,7 +1,25 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the last one that uses its move"); +SINGLE_BATTLE_TEST("Analytic increases the power of moves by 30% if it's the last one that uses its move", s16 damage) +{ + u32 speed; + + PARAMETRIZE { speed = 3; } + PARAMETRIZE { speed = 1; } + + GIVEN { + PLAYER(SPECIES_MAGNEMITE) { Ability(ABILITY_ANALYTIC); Speed(speed); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(2); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); + } +} + TO_DO_BATTLE_TEST("Analytic takes into account modifications to speeed an priority (Gen 5-8)"); //Eg. Paralysis, Power Weight, Stall TO_DO_BATTLE_TEST("Analytic does not take into account modifications to speeed an priority (Gen 8)"); //Eg. Paralysis, Power Weight, Stall TO_DO_BATTLE_TEST("Analytic takes into account the turn order of what fainted Pokémon would've moved"); diff --git a/test/battle/move_effect/aqua_ring.c b/test/battle/move_effect/aqua_ring.c index 158c839d79..d137a35276 100644 --- a/test/battle/move_effect/aqua_ring.c +++ b/test/battle/move_effect/aqua_ring.c @@ -1,6 +1,32 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Aqua Ring recovers 1/16th HP at end of turn"); -TO_DO_BATTLE_TEST("Aqua Ring can be used under Heal Block but will not heal the user"); +SINGLE_BATTLE_TEST("Aqua Ring recovers 1/16th HP at end of turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(128); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_AQUA_RING); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AQUA_RING, player); + } THEN { + EXPECT(player->hp == 58); + } +} + +SINGLE_BATTLE_TEST("Aqua Ring can be used under Heal Block but will not heal the user") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(50); MaxHP(128); Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_HEAL_BLOCK); MOVE(player, MOVE_AQUA_RING); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AQUA_RING, player); + } THEN { + EXPECT(player->hp == 50); + } +} + TO_DO_BATTLE_TEST("Baton Pass passes Aqua Ring's effect"); diff --git a/test/battle/move_effect/attract.c b/test/battle/move_effect/attract.c index 748a88a950..be30483358 100644 --- a/test/battle/move_effect/attract.c +++ b/test/battle/move_effect/attract.c @@ -1,7 +1,105 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Attract causes the target to become infatuated with the user if they have opposite genders"); -TO_DO_BATTLE_TEST("Attract ignores type immunity"); -TO_DO_BATTLE_TEST("Attract bypasses Substitute"); -TO_DO_BATTLE_TEST("Attract fails if the target is already infatuated"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_ATTRACT) == EFFECT_ATTRACT); + ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE); + ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE); +} + +SINGLE_BATTLE_TEST("Attract causes the target to become infatuated with the user if they have opposite genders") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_NIDOKING); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); + MESSAGE("The opposing Nidoking fell in love!"); + } THEN { + EXPECT(opponent->status2 & STATUS2_INFATUATION); + } +} + +SINGLE_BATTLE_TEST("Attract ignores type immunity") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_ATTRACT) == TYPE_NORMAL); + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_MISDREAVUS) { Gender(MON_MALE); } + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); + MESSAGE("The opposing Misdreavus fell in love!"); + } THEN { + EXPECT(opponent->status2 & STATUS2_INFATUATION); + } +} + +SINGLE_BATTLE_TEST("Attract bypasses Substitute") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN) { Speed(90); } + OPPONENT(SPECIES_NIDOKING) { Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); } + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); + MESSAGE("The opposing Nidoking fell in love!"); + } THEN { + EXPECT(opponent->status2 & STATUS2_INFATUATION); + } +} + +SINGLE_BATTLE_TEST("Attract fails if the target is already infatuated") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_NIDOKING); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ATTRACT, player); + MESSAGE("The opposing Nidoking fell in love!"); + MESSAGE("Nidoqueen used Attract!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT(opponent->status2 & STATUS2_INFATUATION); + } +} + +SINGLE_BATTLE_TEST("Attract fails when used on a Pokémon of the same gender") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_NIDOQUEEN); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + MESSAGE("Nidoqueen used Attract!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + } +} + +SINGLE_BATTLE_TEST("Attract fails when used on a genderless Pokémon") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_STARMIE].genderRatio == MON_GENDERLESS); + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_STARMIE); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + MESSAGE("Nidoqueen used Attract!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + } +} diff --git a/test/battle/move_effect/bestow.c b/test/battle/move_effect/bestow.c index 1161cdf8ae..24abdb3bea 100644 --- a/test/battle/move_effect/bestow.c +++ b/test/battle/move_effect/bestow.c @@ -1,10 +1,130 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Bestow transfers its held item to the target"); -TO_DO_BATTLE_TEST("Bestow fails if the user has no held item"); -TO_DO_BATTLE_TEST("Bestow fails if the target already has a held item"); -TO_DO_BATTLE_TEST("Bestow fails if the target is behind a Substitute"); -TO_DO_BATTLE_TEST("Bestow fails if the user is holding Mail"); -TO_DO_BATTLE_TEST("Bestow fails if the user's held item changes its form"); -TO_DO_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal"); +SINGLE_BATTLE_TEST("Bestow transfers its held item to the target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(opponent->item == ITEM_SITRUS_BERRY); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the user has no held item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_NONE); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the target already has a held item") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); } + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LUM_BERRY); } + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_LUM_BERRY); + } +} + +#include "mail.h" +SINGLE_BATTLE_TEST("Bestow fails if the user is holding Mail") +{ + KNOWN_FAILING; + + GIVEN { + ASSUME(ItemIsMail(ITEM_ORANGE_MAIL)); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_ORANGE_MAIL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_ORANGE_MAIL); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the user's held item is a Mega Stone") +{ + GIVEN { + PLAYER(SPECIES_BLAZIKEN) { Item(ITEM_BLAZIKENITE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_BLAZIKENITE); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the user's held item is a Z-Crystal") +{ + GIVEN { + ASSUME(ItemId_GetHoldEffect(ITEM_FIGHTINIUM_Z) == HOLD_EFFECT_Z_CRYSTAL); + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_FIGHTINIUM_Z); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_FIGHTINIUM_Z); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the target is behind a Substitute") +{ + KNOWN_FAILING; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SITRUS_BERRY); Speed(50); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(100); } + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_SITRUS_BERRY); + EXPECT(opponent->item == ITEM_NONE); + } +} + +SINGLE_BATTLE_TEST("Bestow fails if the user's held item changes its form") +{ + KNOWN_FAILING; + + GIVEN { + PLAYER(SPECIES_GIRATINA_ORIGIN) { Item(ITEM_GRISEOUS_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BESTOW); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->item == ITEM_GRISEOUS_ORB); + EXPECT(opponent->item == ITEM_NONE); + } +} + diff --git a/test/battle/move_effect/captivate.c b/test/battle/move_effect/captivate.c index 0da58983c7..224e6bef07 100644 --- a/test/battle/move_effect/captivate.c +++ b/test/battle/move_effect/captivate.c @@ -1,7 +1,112 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Captivate decreases the target's Sp. Attack if they're opposite gender from the user"); -TO_DO_BATTLE_TEST("Captivate fails if the target and user share gender"); -TO_DO_BATTLE_TEST("Captivate fails if the target is genderless"); -TO_DO_BATTLE_TEST("Captivate fails if the user is genderless"); +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_CAPTIVATE) == EFFECT_CAPTIVATE); + ASSUME(gSpeciesInfo[SPECIES_NIDOKING].genderRatio == MON_MALE); + ASSUME(gSpeciesInfo[SPECIES_NIDOQUEEN].genderRatio == MON_FEMALE); + ASSUME(gSpeciesInfo[SPECIES_STARMIE].genderRatio == MON_GENDERLESS); +} + +SINGLE_BATTLE_TEST("Captivate decreases the target's Sp. Attack if they're opposite gender from the user") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_NIDOKING); + } WHEN { + TURN { MOVE(player, MOVE_CAPTIVATE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CAPTIVATE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Nidoking's Sp. Atk harshly fell!"); + } THEN { + EXPECT(opponent->statStages[STAT_SPATK] == 4); + } +} + +SINGLE_BATTLE_TEST("Captivate fails if the target and user share gender") +{ + GIVEN { + PLAYER(SPECIES_NIDOKING); + OPPONENT(SPECIES_NIDOKING); + } WHEN { + TURN { MOVE(player, MOVE_CAPTIVATE); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(opponent->statStages[STAT_SPATK] == 6); + } +} + +SINGLE_BATTLE_TEST("Captivate fails if the target is genderless") +{ + GIVEN { + PLAYER(SPECIES_NIDOQUEEN); + OPPONENT(SPECIES_STARMIE); + } WHEN { + TURN { MOVE(player, MOVE_CAPTIVATE); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(opponent->statStages[STAT_SPATK] == 6); + } +} + +SINGLE_BATTLE_TEST("Captivate fails if the user is genderless") +{ + GIVEN { + PLAYER(SPECIES_STARMIE); + OPPONENT(SPECIES_NIDOQUEEN); + } WHEN { + TURN { MOVE(player, MOVE_CAPTIVATE); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(opponent->statStages[STAT_SPATK] == 6); + } +} + +SINGLE_BATTLE_TEST("Captivate fails if both the user and the opponent are genderless") +{ + GIVEN { + PLAYER(SPECIES_STARMIE); + OPPONENT(SPECIES_STARMIE); + } WHEN { + TURN { MOVE(player, MOVE_CAPTIVATE); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(opponent->statStages[STAT_SPATK] == 6); + } +} + +SINGLE_BATTLE_TEST("Attract fails when used by a genderless Pokémon") +{ + GIVEN { + PLAYER(SPECIES_STARMIE); + OPPONENT(SPECIES_NIDOQUEEN); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + MESSAGE("Starmie used Attract!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + } +} + +SINGLE_BATTLE_TEST("Attract fails if both the user and the target are genderless") +{ + GIVEN { + PLAYER(SPECIES_STARMIE); + OPPONENT(SPECIES_STARMIE); + } WHEN { + TURN { MOVE(player, MOVE_ATTRACT); } + } SCENE { + MESSAGE("Starmie used Attract!"); + MESSAGE("But it failed!"); + } THEN { + EXPECT(!(opponent->status2 & STATUS2_INFATUATION)); + } +} diff --git a/test/battle/move_effect/entrainment.c b/test/battle/move_effect/entrainment.c index cccae86759..fd47937f04 100644 --- a/test/battle/move_effect/entrainment.c +++ b/test/battle/move_effect/entrainment.c @@ -14,6 +14,48 @@ AI_DOUBLE_BATTLE_TEST("AI prefers Entrainment'ing good abilities onto partner wi } } -TO_DO_BATTLE_TEST("Entrainment changes the target's Ability to match the user's"); -TO_DO_BATTLE_TEST("Entrainment fails if the user's ability has cantBeCopied flag"); -TO_DO_BATTLE_TEST("Entrainment fails if the targets's ability has cantBeOverwritten flag"); +SINGLE_BATTLE_TEST("Entrainment changes the target's Ability to match the user's") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); } + } WHEN { + TURN { MOVE(player, MOVE_ENTRAINMENT); } + } THEN { + EXPECT(opponent->ability == ABILITY_TELEPATHY); + } +} + +SINGLE_BATTLE_TEST("Entrainment fails if the user's ability has cantBeCopied flag") +{ + GIVEN { + ASSUME(gAbilitiesInfo[ABILITY_MULTITYPE].cantBeCopied); + PLAYER(SPECIES_ARCEUS) { Ability(ABILITY_MULTITYPE); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_SHADOW_TAG); } + } WHEN { + TURN { MOVE(player, MOVE_ENTRAINMENT); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->ability == ABILITY_MULTITYPE); + EXPECT(opponent->ability == ABILITY_SHADOW_TAG); + } +} + +SINGLE_BATTLE_TEST("Entrainment fails if the target's ability has cantBeOverwritten flag") +{ + GIVEN { + ASSUME(gAbilitiesInfo[ABILITY_MULTITYPE].cantBeOverwritten); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_TELEPATHY); } + OPPONENT(SPECIES_ARCEUS) { Ability(ABILITY_MULTITYPE); } + } WHEN { + TURN { MOVE(player, MOVE_ENTRAINMENT); } + } SCENE { + MESSAGE("But it failed!"); + } THEN { + EXPECT(player->ability == ABILITY_TELEPATHY); + EXPECT(opponent->ability == ABILITY_MULTITYPE); + } +} + +TO_DO_BATTLE_TEST("Entrainment fails on Dynamaxed Pokémon");