Throw out unnecessary functions

This commit is contained in:
Pawkkie 2025-05-08 14:49:49 -04:00
parent 83b7732fae
commit b48d0c387d
5 changed files with 51 additions and 143 deletions

View File

@ -333,7 +333,7 @@ struct AiLogicData
u8 ejectPackSwitch:1; // Tracks whether current switch out was from Eject Pack
u8 predictingSwitch:1; // Determines whether AI will use switch predictions this turn or not
u8 predictingMove:1; // Determines whether AI will use move predictions this turn or not
u8 aiSwitchPredictionInProgress:1; // Tracks whether the AI is in the middle of running prediction calculations
u8 aiPredictionInProgress:1; // Tracks whether the AI is in the middle of running prediction calculations
u8 padding:2;
u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out
u8 aiCalcInProgress:1;

View File

@ -240,5 +240,6 @@ bool32 IsBattlerItemEnabled(u32 battler);
bool32 IsBattlerPredictedToSwitch(u32 battler);
bool32 HasLowAccuracyMove(u32 battlerAtk, u32 battlerDef);
bool32 HasBattlerSideAbility(u32 battlerDef, u32 ability, struct AiLogicData *aiData);
u32 GetThinkingBattler(u32 battler);
#endif //GUARD_BATTLE_AI_UTIL_H

View File

@ -32,11 +32,10 @@
#define AI_ACTION_WATCH (1 << 2)
#define AI_ACTION_DO_NOT_ATTACK (1 << 3)
static u32 ChooseMoveOrAction_Singles(u32 battlerAi);
static u32 ChooseMoveOrAction_Doubles(u32 battlerAi);
static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u32 battlerAi, u32 battlerDef);
static inline void BattleAI_DoAIProcessing_PredictMove(struct AI_ThinkingStruct *aiThink, u32 battler, u32 opposingBattler);
static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAi, u32 battlerDef);
static u32 ChooseMoveOrAction_Singles(u32 battler);
static u32 ChooseMoveOrAction_Doubles(u32 battler);
static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u32 battler, u32 battlerDef);
static inline void BattleAI_DoAIProcessing_PredictedSwitchin(struct AI_ThinkingStruct *aiThink, struct AiLogicData *aiData, u32 battlerAtk, u32 battlerDef);
static bool32 IsPinchBerryItemEffect(enum ItemHoldEffect holdEffect);
// ewram
@ -308,16 +307,15 @@ bool32 BattlerChoseNonMoveAction(void)
void SetupAIPredictionData(u32 battler, enum SwitchType switchType)
{
s32 opposingBattler = GetOppositeBattler(battler);
AI_DATA->aiPredictionInProgress = TRUE;
AI_DATA->battlerDoingPrediction = battler;
// Switch prediction
if ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH))
{
AI_DATA->aiSwitchPredictionInProgress = TRUE;
AI_DATA->battlerDoingPrediction = battler;
AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, switchType);
if (ShouldSwitch(opposingBattler))
AI_DATA->shouldSwitch |= (1u << opposingBattler);
AI_DATA->aiSwitchPredictionInProgress = FALSE;
gBattleStruct->prevTurnSpecies[opposingBattler] = gBattleMons[opposingBattler].species;
// Determine whether AI will use predictions this turn
@ -327,13 +325,14 @@ void SetupAIPredictionData(u32 battler, enum SwitchType switchType)
// Move prediction
if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_MOVES)
{
AI_DATA->predictedMove[opposingBattler] = gBattleMons[opposingBattler].moves[BattleAI_PredictMove(battler, opposingBattler)];
AI_DATA->predictedMove[opposingBattler] = gBattleMons[opposingBattler].moves[BattleAI_ChooseMoveIndex(opposingBattler)];
DebugPrintf("Predicted move: %d", AI_DATA->predictedMove[opposingBattler]);
ModifySwitchAfterMoveScoring(opposingBattler);
// Determine whether AI will use predictions this turn
AI_DATA->predictingMove = RandomPercentage(RNG_AI_PREDICT_MOVE, PREDICT_MOVE_CHANCE);
}
AI_DATA->aiPredictionInProgress = FALSE;
}
void ComputeBattlerDecisions(u32 battler)
@ -640,77 +639,23 @@ static u32 PpStallReduction(u32 move, u32 battlerAtk)
return returnValue;
}
u32 BattleAI_PredictMove(u32 battler, u32 opposingBattler)
static u32 ChooseMoveOrAction_Singles(u32 battler)
{
u8 currentMoveArray[MAX_MON_MOVES];
u8 consideredMoveArray[MAX_MON_MOVES];
u32 numOfBestMoves;
s32 i;
u32 flags = AI_THINKING_STRUCT->aiFlags[battler];
u64 flags = AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)];
AI_DATA->partnerMove = 0; // no ally
while (flags != 0)
{
if (flags & 1)
{
BattleAI_DoAIProcessing_PredictMove(AI_THINKING_STRUCT, battler, opposingBattler);
}
flags >>= 1;
AI_THINKING_STRUCT->aiLogicId++;
}
for (i = 0; i < MAX_MON_MOVES; i++)
{
gAiBattleData->finalScore[opposingBattler][battler][i] = AI_THINKING_STRUCT->score[i];
DebugPrintf("Final score: %d", gAiBattleData->finalScore[opposingBattler][battler][i]);
}
numOfBestMoves = 1;
currentMoveArray[0] = AI_THINKING_STRUCT->score[0];
consideredMoveArray[0] = 0;
for (i = 1; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[opposingBattler].moves[i] != MOVE_NONE)
{
// In ruby, the order of these if statements is reversed.
if (currentMoveArray[0] == AI_THINKING_STRUCT->score[i])
{
currentMoveArray[numOfBestMoves] = AI_THINKING_STRUCT->score[i];
consideredMoveArray[numOfBestMoves++] = i;
}
if (currentMoveArray[0] < AI_THINKING_STRUCT->score[i])
{
numOfBestMoves = 1;
currentMoveArray[0] = AI_THINKING_STRUCT->score[i];
consideredMoveArray[0] = i;
}
}
}
DebugPrintf("Number of best moves: %d", numOfBestMoves);
DebugPrintf("Random best move: %d", consideredMoveArray[Random() % numOfBestMoves]);
DebugPrintf("Random best move: %d", consideredMoveArray[Random() % numOfBestMoves]);
DebugPrintf("Random best move: %d", consideredMoveArray[Random() % numOfBestMoves]);
return consideredMoveArray[Random() % numOfBestMoves];
}
static u32 ChooseMoveOrAction_Singles(u32 battlerAi)
{
u8 currentMoveArray[MAX_MON_MOVES];
u8 consideredMoveArray[MAX_MON_MOVES];
u32 numOfBestMoves;
s32 i;
u64 flags = AI_THINKING_STRUCT->aiFlags[battlerAi];
AI_DATA->partnerMove = 0; // no ally
while (flags != 0)
{
if (flags & 1)
{
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battlerAi] & AI_FLAG_PREDICT_INCOMING_MON))
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battlerAi, gBattlerTarget);
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_INCOMING_MON))
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battler, gBattlerTarget);
else
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battler, gBattlerTarget);
}
flags >>= (u64)1;
AI_THINKING_STRUCT->aiLogicId++;
@ -718,7 +663,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi)
for (i = 0; i < MAX_MON_MOVES; i++)
{
gAiBattleData->finalScore[battlerAi][gBattlerTarget][i] = AI_THINKING_STRUCT->score[i];
gAiBattleData->finalScore[battler][gBattlerTarget][i] = AI_THINKING_STRUCT->score[i];
}
numOfBestMoves = 1;
@ -727,7 +672,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi)
for (i = 1; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[battlerAi].moves[i] != MOVE_NONE)
if (gBattleMons[battler].moves[i] != MOVE_NONE)
{
// In ruby, the order of these if statements is reversed.
if (currentMoveArray[0] == AI_THINKING_STRUCT->score[i])
@ -746,7 +691,7 @@ static u32 ChooseMoveOrAction_Singles(u32 battlerAi)
return consideredMoveArray[Random() % numOfBestMoves];
}
static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
static u32 ChooseMoveOrAction_Doubles(u32 battler)
{
s32 i, j;
u64 flags;
@ -761,7 +706,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (i == battlerAi || gBattleMons[i].hp == 0)
if (i == battler || gBattleMons[i].hp == 0)
{
actionOrMoveIndex[i] = 0xFF;
bestMovePointsForTarget[i] = -1;
@ -769,25 +714,25 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
else
{
if (gBattleTypeFlags & BATTLE_TYPE_PALACE)
BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4, battlerAi);
BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4, battler);
else
BattleAI_SetupAIData(0xF, battlerAi);
BattleAI_SetupAIData(0xF, battler);
gBattlerTarget = i;
AI_DATA->partnerMove = GetAllyChosenMove(battlerAi);
AI_DATA->partnerMove = GetAllyChosenMove(battler);
AI_THINKING_STRUCT->aiLogicId = 0;
AI_THINKING_STRUCT->movesetIndex = 0;
flags = AI_THINKING_STRUCT->aiFlags[battlerAi];
flags = AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)];
while (flags != 0)
{
if (flags & 1)
{
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battlerAi] & AI_FLAG_PREDICT_INCOMING_MON))
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battlerAi, gBattlerTarget);
if (IsBattlerPredictedToSwitch(gBattlerTarget) && (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_INCOMING_MON))
BattleAI_DoAIProcessing_PredictedSwitchin(AI_THINKING_STRUCT, AI_DATA, battler, gBattlerTarget);
else
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battlerAi, gBattlerTarget);
BattleAI_DoAIProcessing(AI_THINKING_STRUCT, battler, gBattlerTarget);
}
flags >>= (u64)1;
AI_THINKING_STRUCT->aiLogicId++;
@ -798,9 +743,9 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
mostViableMovesNo = 1;
for (j = 1; j < MAX_MON_MOVES; j++)
{
if (gBattleMons[battlerAi].moves[j] != 0)
if (gBattleMons[battler].moves[j] != 0)
{
if (!CanTargetBattler(battlerAi, i, gBattleMons[battlerAi].moves[j]))
if (!CanTargetBattler(battler, i, gBattleMons[battler].moves[j]))
continue;
if (mostViableMovesScores[0] == AI_THINKING_STRUCT->score[j])
@ -821,14 +766,14 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
bestMovePointsForTarget[i] = mostViableMovesScores[0];
// Don't use a move against ally if it has less than 100 points.
if (i == BATTLE_PARTNER(battlerAi) && bestMovePointsForTarget[i] < AI_SCORE_DEFAULT)
if (i == BATTLE_PARTNER(battler) && bestMovePointsForTarget[i] < AI_SCORE_DEFAULT)
{
bestMovePointsForTarget[i] = -1;
}
for (j = 0; j < MAX_MON_MOVES; j++)
{
gAiBattleData->finalScore[battlerAi][gBattlerTarget][j] = AI_THINKING_STRUCT->score[j];
gAiBattleData->finalScore[battler][gBattlerTarget][j] = AI_THINKING_STRUCT->score[j];
}
}
}
@ -853,7 +798,7 @@ static u32 ChooseMoveOrAction_Doubles(u32 battlerAi)
}
gBattlerTarget = mostViableTargetsArray[Random() % mostViableTargetsNo];
gAiBattleData->chosenTarget[battlerAi] = gBattlerTarget;
gAiBattleData->chosenTarget[battler] = gBattlerTarget;
return actionOrMoveIndex[gBattlerTarget];
}
@ -868,64 +813,26 @@ static inline bool32 ShouldConsiderMoveForBattler(u32 battlerAi, u32 battlerDef,
return TRUE;
}
static inline void BattleAI_DoAIProcessing_PredictMove(struct AI_ThinkingStruct *aiThink, u32 battler, u32 opposingBattler)
static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u32 battler, u32 battlerDef)
{
do
{
if (gBattleMons[opposingBattler].pp[aiThink->movesetIndex] == 0)
if (gBattleMons[battler].pp[aiThink->movesetIndex] == 0)
aiThink->moveConsidered = MOVE_NONE;
else
aiThink->moveConsidered = gBattleMons[opposingBattler].moves[aiThink->movesetIndex];
DebugPrintf("Move considered: %d", aiThink->moveConsidered);
aiThink->moveConsidered = gBattleMons[battler].moves[aiThink->movesetIndex];
// There is no point in calculating scores for all 3 battlers(2 opponents + 1 ally) with certain moves.
if (aiThink->moveConsidered != MOVE_NONE
&& aiThink->score[aiThink->movesetIndex] > 0
&& ShouldConsiderMoveForBattler(opposingBattler, battler, aiThink->moveConsidered))
&& ShouldConsiderMoveForBattler(battler, battlerDef, aiThink->moveConsidered))
{
if (aiThink->aiLogicId < ARRAY_COUNT(sBattleAiFuncTable)
&& sBattleAiFuncTable[aiThink->aiLogicId] != NULL)
{
// Call AI function
aiThink->score[aiThink->movesetIndex] =
sBattleAiFuncTable[aiThink->aiLogicId](opposingBattler,
battler,
aiThink->moveConsidered,
aiThink->score[aiThink->movesetIndex]);
DebugPrintf("Current score: %d", aiThink->score[aiThink->movesetIndex]);
}
}
else
{
aiThink->score[aiThink->movesetIndex] = 0;
}
aiThink->movesetIndex++;
} while (aiThink->movesetIndex < MAX_MON_MOVES);
aiThink->movesetIndex = 0;
}
static inline void BattleAI_DoAIProcessing(struct AI_ThinkingStruct *aiThink, u32 battlerAi, u32 battlerDef)
{
do
{
if (gBattleMons[battlerAi].pp[aiThink->movesetIndex] == 0)
aiThink->moveConsidered = MOVE_NONE;
else
aiThink->moveConsidered = gBattleMons[battlerAi].moves[aiThink->movesetIndex];
// There is no point in calculating scores for all 3 battlers(2 opponents + 1 ally) with certain moves.
if (aiThink->moveConsidered != MOVE_NONE
&& aiThink->score[aiThink->movesetIndex] > 0
&& ShouldConsiderMoveForBattler(battlerAi, battlerDef, aiThink->moveConsidered))
{
if (aiThink->aiLogicId < ARRAY_COUNT(sBattleAiFuncTable)
&& sBattleAiFuncTable[aiThink->aiLogicId] != NULL)
{
// Call AI function
aiThink->score[aiThink->movesetIndex] =
sBattleAiFuncTable[aiThink->aiLogicId](battlerAi,
sBattleAiFuncTable[aiThink->aiLogicId](battler,
battlerDef,
aiThink->moveConsidered,
aiThink->score[aiThink->movesetIndex]);

View File

@ -108,13 +108,6 @@ u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario)
}
}
u32 GetThinkingBattler(u32 battler)
{
if (AI_DATA->aiSwitchPredictionInProgress)
return AI_DATA->battlerDoingPrediction;
return battler;
}
static bool32 IsAceMon(u32 battler, u32 monPartyId)
{
if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_ACE_POKEMON
@ -295,7 +288,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4)))
{
// 50% chance to stay in regardless
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiSwitchPredictionInProgress)
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiPredictionInProgress)
return FALSE;
// Switch mon out
@ -315,7 +308,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
return FALSE;
// 50% chance to stay in regardless
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiSwitchPredictionInProgress)
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiPredictionInProgress)
return FALSE;
// Switch mon out
@ -465,7 +458,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
return FALSE;
if (gBattleStruct->prevTurnSpecies[battler] != gBattleMons[battler].species && !(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_MOVES)) // AI mon has changed, player's behaviour no longer reliable; note to override this if using AI_FLAG_PREDICT_MOVE
return FALSE;
if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING_STAY_IN, STAY_IN_ABSORBING_PERCENTAGE) || AI_DATA->aiSwitchPredictionInProgress))
if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING_STAY_IN, STAY_IN_ABSORBING_PERCENTAGE) || AI_DATA->aiPredictionInProgress))
return FALSE;
if (AreStatsRaised(battler))
return FALSE;
@ -898,7 +891,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc
if (move == 0)
continue;
if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress))
if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= UQ_4_12(2.0) && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiPredictionInProgress))
return SetSwitchinAndSwitch(battler, i);
}
}
@ -990,7 +983,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
return FALSE;
// Switch out 50% of the time otherwise
else if ((RandomPercentage(RNG_AI_SWITCH_ENCORE, GetSwitchChance(SHOULD_SWITCH_ENCORE_DAMAGE)) || AI_DATA->aiSwitchPredictionInProgress) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
else if ((RandomPercentage(RNG_AI_SWITCH_ENCORE, GetSwitchChance(SHOULD_SWITCH_ENCORE_DAMAGE)) || AI_DATA->aiPredictionInProgress) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
return FALSE;
@ -1036,7 +1029,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler)
// 50% chance if attack at -2 and have a good candidate mon
else if (attackingStage == DEFAULT_STAT_STAGE - 2)
{
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiSwitchPredictionInProgress))
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiPredictionInProgress))
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
}
// If at -3 or worse, switch out regardless
@ -1053,7 +1046,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler)
// 50% chance if attack at -2 and have a good candidate mon
else if (spAttackingStage == DEFAULT_STAT_STAGE - 2)
{
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiSwitchPredictionInProgress))
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiPredictionInProgress))
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
}
// If at -3 or worse, switch out regardless

View File

@ -4517,3 +4517,10 @@ bool32 HasBattlerSideAbility(u32 battler, u32 ability, struct AiLogicData *aiDat
return TRUE;
return FALSE;
}
u32 GetThinkingBattler(u32 battler)
{
if (AI_DATA->aiPredictionInProgress)
return AI_DATA->battlerDoingPrediction;
return battler;
}