From 4e01ce6993767c6cd3ead555cb167daa2321afcf Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Tue, 11 Mar 2025 21:23:02 +0100 Subject: [PATCH] Moved some AI stuff out of the battlestruct (#6405) Co-authored-by: Hedara --- include/battle.h | 11 ++++++++--- src/battle_ai_main.c | 8 ++++---- src/battle_ai_switch_items.c | 6 +++--- src/battle_ai_util.c | 2 +- src/battle_controller_opponent.c | 4 ++-- src/battle_controller_player.c | 8 ++++---- src/battle_controller_player_partner.c | 4 ++-- src/battle_debug.c | 2 +- src/battle_main.c | 3 ++- src/battle_util2.c | 2 ++ test/test_runner_battle.c | 8 ++++---- 11 files changed, 33 insertions(+), 25 deletions(-) diff --git a/include/battle.h b/include/battle.h index 8342677484..226f9acfef 100644 --- a/include/battle.h +++ b/include/battle.h @@ -765,9 +765,6 @@ struct BattleStruct u16 tracedAbility[MAX_BATTLERS_COUNT]; u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk and Anger Shell. struct Illusion illusion[MAX_BATTLERS_COUNT]; - s32 aiFinalScore[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // AI, target, moves to make debugging easier - u8 aiMoveOrAction[MAX_BATTLERS_COUNT]; - u8 aiChosenTarget[MAX_BATTLERS_COUNT]; u8 soulheartBattlerId; u8 friskedBattler; // Frisk needs to identify 2 battlers in double battles. u8 sameMoveTurns[MAX_BATTLERS_COUNT]; // For Metronome, number of times the same moves has been SUCCESFULLY used. @@ -840,6 +837,13 @@ struct BattleStruct u16 savedMove; // backup current move for mid-turn switching, e.g. Red Card }; +struct AiBattleData +{ + s32 finalScore[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT][MAX_MON_MOVES]; // AI, target, moves to make debugging easier + u8 moveOrAction[MAX_BATTLERS_COUNT]; + u8 chosenTarget[MAX_BATTLERS_COUNT]; +}; + // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, // and 1 flag per battler to indicate whether the battler is awake and at <= 50% HP (which affects move choice). // The assert below is to ensure palaceFlags is large enough to store these flags without overlap. @@ -1155,6 +1159,7 @@ extern u8 gSentPokesToOpponent[2]; extern struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT]; extern struct BattleScripting gBattleScripting; extern struct BattleStruct *gBattleStruct; +extern struct AiBattleData *gAiBattleData; extern u8 *gLinkBattleSendBuffer; extern u8 *gLinkBattleRecvBuffer; extern struct BattleResources *gBattleResources; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b95601f37d..133d62aeb7 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -268,7 +268,7 @@ void BattleAI_SetupAIData(u8 defaultScoreMoves, u32 battler) } gBattlerTarget = SetRandomTarget(battler); - gBattleStruct->aiChosenTarget[battler] = gBattlerTarget; + gAiBattleData->chosenTarget[battler] = gBattlerTarget; } u32 BattleAI_ChooseMoveOrAction(u32 battler) @@ -514,7 +514,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi) for (i = 0; i < MAX_MON_MOVES; i++) { - gBattleStruct->aiFinalScore[battlerAi][gBattlerTarget][i] = AI_THINKING_STRUCT->score[i]; + gAiBattleData->finalScore[battlerAi][gBattlerTarget][i] = AI_THINKING_STRUCT->score[i]; } // Check special AI actions. @@ -641,7 +641,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi) for (j = 0; j < MAX_MON_MOVES; j++) { - gBattleStruct->aiFinalScore[battlerAi][gBattlerTarget][j] = AI_THINKING_STRUCT->score[j]; + gAiBattleData->finalScore[battlerAi][gBattlerTarget][j] = AI_THINKING_STRUCT->score[j]; } } } @@ -666,7 +666,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi) } gBattlerTarget = mostViableTargetsArray[Random() % mostViableTargetsNo]; - gBattleStruct->aiChosenTarget[battlerAi] = gBattlerTarget; + gAiBattleData->chosenTarget[battlerAi] = gBattlerTarget; return actionOrMoveIndex[gBattlerTarget]; } diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 466f6c5cdf..23419ab7e0 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -2201,13 +2201,13 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, enum SwitchType switchType) static bool32 AiExpectsToFaintPlayer(u32 battler) { - u8 target = gBattleStruct->aiChosenTarget[battler]; + u8 target = gAiBattleData->chosenTarget[battler]; - if (gBattleStruct->aiMoveOrAction[battler] > 3) + if (gAiBattleData->moveOrAction[battler] > 3) return FALSE; // AI not planning to use move if (GetBattlerSide(target) != GetBattlerSide(battler) - && CanIndexMoveFaintTarget(battler, target, gBattleStruct->aiMoveOrAction[battler], AI_ATTACKING) + && CanIndexMoveFaintTarget(battler, target, gAiBattleData->moveOrAction[battler], AI_ATTACKING) && AI_IsFaster(battler, target, GetAIChosenMove(battler))) { // We expect to faint the target and move first -> dont use an item diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 952f638d36..24bb482b4a 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -61,7 +61,7 @@ bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move) u32 GetAIChosenMove(u32 battlerId) { - return (gBattleMons[battlerId].moves[gBattleStruct->aiMoveOrAction[battlerId]]); + return (gBattleMons[battlerId].moves[gAiBattleData->moveOrAction[battlerId]]); } bool32 AI_RandLessThan(u32 val) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 38fb304ac1..0a52d88064 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -544,8 +544,8 @@ static void OpponentHandleChooseMove(u32 battler) } else { - chosenMoveId = gBattleStruct->aiMoveOrAction[battler]; - gBattlerTarget = gBattleStruct->aiChosenTarget[battler]; + chosenMoveId = gAiBattleData->moveOrAction[battler]; + gBattlerTarget = gAiBattleData->chosenTarget[battler]; switch (chosenMoveId) { case AI_CHOICE_WATCH: diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index b84b87d0ed..8ee7f036d4 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2042,13 +2042,13 @@ static void PlayerHandleChooseAction(u32 battler) u32 moveTarget = GetBattlerMoveTargetType(B_POSITION_PLAYER_RIGHT, move); if (moveTarget == MOVE_TARGET_SELECTED) { - if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_LEFT) + if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_LEFT) StringAppend(gStringVar1, COMPOUND_STRING(" -{UP_ARROW}")); - else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_RIGHT) + else if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_OPPONENT_RIGHT) StringAppend(gStringVar1, COMPOUND_STRING(" {UP_ARROW}-")); - else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_LEFT) + else if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_LEFT) StringAppend(gStringVar1, COMPOUND_STRING(" {DOWN_ARROW}-")); - else if (gBattleStruct->aiChosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_RIGHT) + else if (gAiBattleData->chosenTarget[B_POSITION_PLAYER_RIGHT] == B_POSITION_PLAYER_RIGHT) StringAppend(gStringVar1, COMPOUND_STRING(" {DOWN_ARROW}-")); } else if (moveTarget == MOVE_TARGET_BOTH) diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 39c1d25526..93c23629f6 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -349,8 +349,8 @@ static void PlayerPartnerHandleChooseMove(u32 battler) u8 chosenMoveId; struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); - chosenMoveId = gBattleStruct->aiMoveOrAction[battler]; - gBattlerTarget = gBattleStruct->aiChosenTarget[battler]; + chosenMoveId = gAiBattleData->moveOrAction[battler]; + gBattlerTarget = gAiBattleData->chosenTarget[battler]; u32 moveTarget = GetBattlerMoveTargetType(battler, moveInfo->moves[chosenMoveId]); if (moveTarget & MOVE_TARGET_USER) diff --git a/src/battle_debug.c b/src/battle_debug.c index 61635cc815..f0dd06c53f 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -941,7 +941,7 @@ static void PutMovesPointsText(struct BattleDebugMenu *data) continue; battlerDef = gSprites[data->spriteIds.aiIconSpriteIds[j]].data[0]; ConvertIntToDecimalStringN(text, - gBattleStruct->aiFinalScore[data->aiBattlerId][battlerDef][i], + gAiBattleData->finalScore[data->aiBattlerId][battlerDef][i], STR_CONV_MODE_RIGHT_ALIGN, 3); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 83 + count * 54, i * 15, 0, NULL); diff --git a/src/battle_main.c b/src/battle_main.c index d7b90bd76d..88bd8e9c07 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -207,6 +207,7 @@ EWRAM_DATA u8 gSentPokesToOpponent[2] = {0}; EWRAM_DATA struct BattleEnigmaBerry gEnigmaBerries[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA struct BattleScripting gBattleScripting = {0}; EWRAM_DATA struct BattleStruct *gBattleStruct = NULL; +EWRAM_DATA struct AiBattleData *gAiBattleData = NULL; EWRAM_DATA u8 *gLinkBattleSendBuffer = NULL; EWRAM_DATA u8 *gLinkBattleRecvBuffer = NULL; EWRAM_DATA struct BattleResources *gBattleResources = NULL; @@ -4200,7 +4201,7 @@ static void HandleTurnActionSelectionState(void) SetupAISwitchingData(battler, switchType); // Do scoring - gBattleStruct->aiMoveOrAction[battler] = BattleAI_ChooseMoveOrAction(battler); + gAiBattleData->moveOrAction[battler] = BattleAI_ChooseMoveOrAction(battler); AI_DATA->aiCalcInProgress = FALSE; } // fallthrough diff --git a/src/battle_util2.c b/src/battle_util2.c index 6d7c82cbe5..3fd6549a19 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -18,6 +18,7 @@ void AllocateBattleResources(void) InitTrainerHillBattleStruct(); gBattleStruct = AllocZeroed(sizeof(*gBattleStruct)); + gAiBattleData = AllocZeroed(sizeof(*gAiBattleData)); #if B_FLAG_SKY_BATTLE gBattleStruct->isSkyBattle = FlagGet(B_FLAG_SKY_BATTLE); @@ -55,6 +56,7 @@ void FreeBattleResources(void) if (gBattleResources != NULL) { FREE_AND_SET_NULL(gBattleStruct); + FREE_AND_SET_NULL(gAiBattleData); FREE_AND_SET_NULL(gBattleResources->secretBase); FREE_AND_SET_NULL(gBattleResources->battleScriptsStack); diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 40e8b31f41..41ea06b67d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -771,7 +771,7 @@ static u32 CountAiExpectMoves(struct ExpectedAIAction *expectedAction, u32 battl if ((1u << i) & expectedAction->moveSlots) { if (printLog) - PrintAiMoveLog(battlerId, i, gBattleMons[battlerId].moves[i], gBattleStruct->aiFinalScore[battlerId][expectedAction->target][i]); + PrintAiMoveLog(battlerId, i, gBattleMons[battlerId].moves[i], gAiBattleData->finalScore[battlerId][expectedAction->target][i]); countExpected++; } } @@ -830,7 +830,7 @@ void TestRunner_Battle_CheckChosenMove(u32 battlerId, u32 moveId, u32 target) if (!expectedAction->notMove && !movePasses) { u32 moveSlot = GetMoveSlot(gBattleMons[battlerId].moves, moveId); - PrintAiMoveLog(battlerId, moveSlot, moveId, gBattleStruct->aiFinalScore[battlerId][expectedAction->target][moveSlot]); + PrintAiMoveLog(battlerId, moveSlot, moveId, gAiBattleData->finalScore[battlerId][expectedAction->target][moveSlot]); if (countExpected > 1) Test_ExitWithResult(TEST_RESULT_FAIL, SourceLine(0), ":L%s:%d: Unmatched EXPECT_MOVES %S, got %S", filename, expectedAction->sourceLine, GetMoveName(expectedMoveId), GetMoveName(moveId)); else @@ -904,7 +904,7 @@ static const char *const sCmpToStringTable[] = static void CheckIfMaxScoreEqualExpectMove(u32 battlerId, s32 target, struct ExpectedAIAction *aiAction, const char *filename) { u32 i; - s32 *scores = gBattleStruct->aiFinalScore[battlerId][target]; + s32 *scores = gAiBattleData->finalScore[battlerId][target]; s32 bestScore = 0, bestScoreId = 0; u16 *moves = gBattleMons[battlerId].moves; for (i = 0; i < MAX_MON_MOVES; i++) @@ -1006,7 +1006,7 @@ void TestRunner_Battle_CheckAiMoveScores(u32 battlerId) { u32 moveId1 = gBattleMons[battlerId].moves[scoreCtx->moveSlot1]; s32 target = scoreCtx->target; - s32 *scores = gBattleStruct->aiFinalScore[battlerId][target]; + s32 *scores = gAiBattleData->finalScore[battlerId][target]; if (scoreCtx->toValue) {