From 5ce276c802bdd496eb7f20012765fad6e8cb42bf Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 12 Jun 2024 22:21:43 +0100 Subject: [PATCH] fixup! Fix speed ties --- include/battle.h | 2 +- src/battle_main.c | 47 +++++++++++++++++++++++++------------- test/battle/move.c | 56 +++++++++++++++++++++++++++++++++------------- 3 files changed, 73 insertions(+), 32 deletions(-) diff --git a/include/battle.h b/include/battle.h index 81475691dc9e..26abcc44079e 100644 --- a/include/battle.h +++ b/include/battle.h @@ -780,7 +780,7 @@ struct BattleStruct u8 quickClawRandom[MAX_BATTLERS_COUNT]; u8 quickDrawRandom[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; - u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values, determines all speed tie-breaks. + u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, diff --git a/src/battle_main.c b/src/battle_main.c index 7cf5722c6786..5ff2cb461025 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5164,29 +5164,44 @@ s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenM ); } -u32 GetBattlerOrder(u32 battler) +// 24 == MAX_BATTLERS_COUNT!. +// These are the possible orders if all the battlers speed tie. An order +// is chosen at the start of the turn. +static const u8 sBattlerOrders[24][4] = { - u32 i; - u32 div = MAX_BATTLERS_COUNT; - u32 n = gBattleStruct->speedTieBreaks; - for (i = 0; i < battler; i++) - { - n /= div; - div--; - } - if (div > 0) - return n % div; - else - return n; -} + { 0, 1, 2, 3 }, + { 0, 1, 3, 2 }, + { 0, 2, 1, 3 }, + { 0, 2, 3, 1 }, + { 0, 3, 1, 2 }, + { 0, 3, 2, 1 }, + { 1, 0, 2, 3 }, + { 1, 0, 3, 2 }, + { 1, 2, 0, 3 }, + { 1, 2, 3, 0 }, + { 1, 3, 0, 2 }, + { 1, 3, 2, 0 }, + { 2, 0, 1, 3 }, + { 2, 0, 3, 1 }, + { 2, 1, 0, 3 }, + { 2, 1, 3, 0 }, + { 2, 3, 0, 1 }, + { 2, 3, 1, 0 }, + { 3, 0, 1, 2 }, + { 3, 0, 2, 1 }, + { 3, 1, 0, 2 }, + { 3, 1, 2, 0 }, + { 3, 2, 0, 1 }, + { 3, 2, 1, 0 }, +}; s32 GetWhichBattlerFaster(u32 battler1, u32 battler2, bool32 ignoreChosenMoves) { s32 strikesFirst = GetWhichBattlerFasterOrTies(battler1, battler2, ignoreChosenMoves); if (strikesFirst == 0) { - s32 order1 = GetBattlerOrder(battler1); - s32 order2 = GetBattlerOrder(battler2); + s32 order1 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler1]; + s32 order2 = sBattlerOrders[gBattleStruct->speedTieBreaks][battler2]; if (order1 < order2) strikesFirst = 1; else diff --git a/test/battle/move.c b/test/battle/move.c index c76d6eb10f6b..228a09a7c665 100644 --- a/test/battle/move.c +++ b/test/battle/move.c @@ -66,7 +66,7 @@ SINGLE_BATTLE_TEST("Turn order is determined by Speed if priority ties") } } -SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie") +SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [singles]") { PASSES_RANDOMLY(1, 2, RNG_SPEED_TIE); GIVEN { @@ -80,15 +80,44 @@ SINGLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie" } } -DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie") +DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie [doubles]") { - struct BattlePokemon *fastest = NULL; - PARAMETRIZE { fastest = playerLeft; } - PARAMETRIZE { fastest = playerRight; } - PARAMETRIZE { fastest = opponentLeft; } - PARAMETRIZE { fastest = opponentRight; } + struct BattlePokemon *order[4] = { NULL, NULL, NULL, NULL }; + u32 a, b, c, d; - PASSES_RANDOMLY(1, 4, RNG_SPEED_TIE); + // TODO: Test all of these in a single PASSES_RANDOMLY pass rather + // than 24 PARAMETRIZEd passes. + PARAMETRIZE { a = 0; b = 1; c = 2; d = 3; } + PARAMETRIZE { a = 0; b = 1; c = 3; d = 2; } + PARAMETRIZE { a = 0; b = 2; c = 1; d = 3; } + PARAMETRIZE { a = 0; b = 2; c = 3; d = 1; } + PARAMETRIZE { a = 0; b = 3; c = 1; d = 2; } + PARAMETRIZE { a = 0; b = 3; c = 2; d = 1; } + PARAMETRIZE { a = 1; b = 0; c = 2; d = 3; } + PARAMETRIZE { a = 1; b = 0; c = 3; d = 2; } + PARAMETRIZE { a = 1; b = 2; c = 0; d = 3; } + PARAMETRIZE { a = 1; b = 2; c = 3; d = 0; } + PARAMETRIZE { a = 1; b = 3; c = 0; d = 2; } + PARAMETRIZE { a = 1; b = 3; c = 2; d = 0; } + PARAMETRIZE { a = 2; b = 0; c = 1; d = 3; } + PARAMETRIZE { a = 2; b = 0; c = 3; d = 1; } + PARAMETRIZE { a = 2; b = 1; c = 0; d = 3; } + PARAMETRIZE { a = 2; b = 1; c = 3; d = 0; } + PARAMETRIZE { a = 2; b = 3; c = 0; d = 1; } + PARAMETRIZE { a = 2; b = 3; c = 1; d = 0; } + PARAMETRIZE { a = 3; b = 0; c = 1; d = 2; } + PARAMETRIZE { a = 3; b = 0; c = 2; d = 1; } + PARAMETRIZE { a = 3; b = 1; c = 0; d = 2; } + PARAMETRIZE { a = 3; b = 1; c = 2; d = 0; } + PARAMETRIZE { a = 3; b = 2; c = 0; d = 1; } + PARAMETRIZE { a = 3; b = 2; c = 1; d = 0; } + + order[a] = playerLeft; + order[b] = playerRight; + order[c] = opponentLeft; + order[d] = opponentRight; + + PASSES_RANDOMLY(1, 24, RNG_SPEED_TIE); GIVEN { PLAYER(SPECIES_WOBBUFFET) { Speed(1); } @@ -98,13 +127,10 @@ DOUBLE_BATTLE_TEST("Turn order is determined randomly if priority and Speed tie" } WHEN { TURN { MOVE(playerLeft, MOVE_SPLASH); MOVE(playerRight, MOVE_SPLASH); MOVE(opponentLeft, MOVE_SPLASH); MOVE(opponentRight, MOVE_SPLASH); } } SCENE { - NONE_OF { - if (fastest != playerLeft) ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, playerLeft); - if (fastest != playerRight) ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, playerRight); - if (fastest != opponentLeft) ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponentLeft); - if (fastest != opponentRight) ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, opponentRight); - } - ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, fastest); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[0]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[1]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[2]); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPLASH, order[3]); } }