From 666e59b37f2a3a79554589c8b7667928219a75e1 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Sun, 19 Feb 2023 15:36:16 +0000 Subject: [PATCH] Test Roar The original implementation of forcerandomswitch was biased towards certain party members. --- src/battle_script_commands.c | 33 +++++------------ test/move_effect_roar.c | 70 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 25 deletions(-) create mode 100644 test/move_effect_roar.c diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 21dbf59e48..b4bafd215c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12089,8 +12089,8 @@ static void Cmd_forcerandomswitch(void) s32 lastMonId = 0; // + 1 s32 monsCount; struct Pokemon *party = NULL; - s32 validMons = 0; - s32 minNeeded; + u8 validMons[PARTY_SIZE]; + s32 validMonsCount = 0; bool32 redCardForcedSwitch = FALSE; @@ -12147,7 +12147,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = 6; monsCount = 6; - minNeeded = 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -12166,7 +12165,6 @@ static void Cmd_forcerandomswitch(void) lastMonId = PARTY_SIZE / 2; } monsCount = PARTY_SIZE / 2; - minNeeded = 1; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -12184,7 +12182,6 @@ static void Cmd_forcerandomswitch(void) lastMonId = PARTY_SIZE / 2; } monsCount = PARTY_SIZE / 2; - minNeeded = 1; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -12195,7 +12192,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE; monsCount = PARTY_SIZE; - minNeeded = 2; // since there are two opponents, it has to be a double battle } else { @@ -12210,7 +12206,6 @@ static void Cmd_forcerandomswitch(void) lastMonId = PARTY_SIZE / 2; } monsCount = PARTY_SIZE / 2; - minNeeded = 1; } battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; @@ -12220,7 +12215,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE; monsCount = PARTY_SIZE; - minNeeded = 2; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; battler1PartyId = gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerTarget)]; } @@ -12229,7 +12223,6 @@ static void Cmd_forcerandomswitch(void) firstMonId = 0; lastMonId = PARTY_SIZE; monsCount = PARTY_SIZE; - minNeeded = 1; battler2PartyId = gBattlerPartyIndexes[gBattlerTarget]; // there is only one pokemon out in single battles battler1PartyId = gBattlerPartyIndexes[gBattlerTarget]; } @@ -12238,13 +12231,15 @@ static void Cmd_forcerandomswitch(void) { if (GetMonData(&party[i], MON_DATA_SPECIES) != SPECIES_NONE && !GetMonData(&party[i], MON_DATA_IS_EGG) - && GetMonData(&party[i], MON_DATA_HP) != 0) + && GetMonData(&party[i], MON_DATA_HP) != 0 + && i != battler1PartyId + && i != battler2PartyId) { - validMons++; + validMons[validMonsCount++] = i; } } - if (!redCardForcedSwitch && validMons <= minNeeded) + if (validMonsCount == 0) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -12252,19 +12247,7 @@ static void Cmd_forcerandomswitch(void) { *(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget]; gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; - - do - { - i = Random() % monsCount; - i += firstMonId; - } - while (i == battler2PartyId - || i == battler1PartyId - || GetMonData(&party[i], MON_DATA_SPECIES) == SPECIES_NONE - || GetMonData(&party[i], MON_DATA_IS_EGG) == TRUE - || GetMonData(&party[i], MON_DATA_HP) == 0); - - *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = i; + *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[Random() % validMonsCount]; if (!IsMultiBattle()) SwitchPartyOrder(gBattlerTarget); diff --git a/test/move_effect_roar.c b/test/move_effect_roar.c new file mode 100644 index 0000000000..2d4eadda85 --- /dev/null +++ b/test/move_effect_roar.c @@ -0,0 +1,70 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_ROAR].effect == EFFECT_ROAR); +} + +SINGLE_BATTLE_TEST("Roar switches the target with a random non-fainted replacement") +{ + PASSES_RANDOMLY(1, 2); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BULBASAUR); + OPPONENT(SPECIES_CHARMANDER); + OPPONENT(SPECIES_SQUIRTLE) { HP(0); } + } WHEN { + TURN { MOVE(player, MOVE_ROAR); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, player); + MESSAGE("Foe Bulbasaur was dragged out!"); + } +} + +DOUBLE_BATTLE_TEST("Roar switches the target with a random non-battler, non-fainted replacement") +{ + PASSES_RANDOMLY(1, 2); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_BULBASAUR); + OPPONENT(SPECIES_CHARMANDER); + OPPONENT(SPECIES_SQUIRTLE) { HP(0); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_ROAR, target: opponentRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROAR, playerLeft); + MESSAGE("Foe Bulbasaur was dragged out!"); + } +} + +SINGLE_BATTLE_TEST("Roar fails if no replacements") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ROAR); } + } SCENE { + MESSAGE("Wobbuffet used Roar!"); + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Roar fails if replacements fainted") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { HP(0); } + } WHEN { + TURN { MOVE(player, MOVE_ROAR); } + } SCENE { + MESSAGE("Wobbuffet used Roar!"); + MESSAGE("But it failed!"); + } +}