Skip to content

Commit

Permalink
replace some AI_GetMoveEffectiveness with AI_DATA->efefctiveness in s…
Browse files Browse the repository at this point in the history
…witch logic
  • Loading branch information
ghoulslash committed Feb 5, 2025
1 parent a642759 commit 3dc0541
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 34 deletions.
3 changes: 2 additions & 1 deletion include/battle_ai_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ uq4_12_t AI_GetMoveEffectiveness(u32 move, u32 battlerAtk, u32 battlerDef);
u16 *GetMovesArray(u32 battler);
bool32 IsConfusionMoveEffect(u32 moveEffect);
bool32 HasMove(u32 battlerId, u32 move);
u32 GetIndexInMoveArray(u32 battler, u32 move);
bool32 HasOnlyMovesWithCategory(u32 battlerId, u32 category, bool32 onlyOffensive);
bool32 HasMoveWithCategory(u32 battler, u32 category);
bool32 HasMoveWithType(u32 battler, u32 type);
Expand Down Expand Up @@ -208,7 +209,7 @@ void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
void IncreaseConfusionScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);
void IncreaseFrostbiteScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score);

s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, bool32 isPartyMonAttacker, enum DamageRollType rollType);
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, bool32 isPartyMonAttacker, enum DamageRollType rollType);
u32 AI_WhoStrikesFirstPartyMon(u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, u32 moveConsidered);
s32 AI_TryToClearStats(u32 battlerAtk, u32 battlerDef, bool32 isDoubleBattle);
bool32 AI_ShouldCopyStatChanges(u32 battlerAtk, u32 battlerDef);
Expand Down
3 changes: 0 additions & 3 deletions src/battle_ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -997,9 +997,6 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
// target partner ability checks & not attacking partner
if (isDoubleBattle)
{
if (CanPartnerAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[BATTLE_PARTNER(battlerDef)]))
RETURN_SCORE_MINUS(20);

switch (aiData->abilities[BATTLE_PARTNER(battlerDef)])
{
case ABILITY_LIGHTNING_ROD:
Expand Down
50 changes: 24 additions & 26 deletions src/battle_ai_switch_items.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
if (!IsBattleMoveStatus(aiMove))
{
// Check if mon has a super effective move
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
if (AI_DATA->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
hasSuperEffectiveMove = TRUE;

// Get maximum damage mon can deal
Expand Down Expand Up @@ -255,9 +255,8 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = gBattleMons[battler].moves[moveIndex];
if ((AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0)
|| AI_GetMoveEffectiveness(aiMove, battler, opposingPartner) > UQ_4_12(0.0))
&& aiMove != MOVE_NONE)
if (aiMove != MOVE_NONE && (AI_DATA->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0)
|| AI_DATA->effectiveness[battler][opposingPartner][moveIndex] > UQ_4_12(0.0)))
return FALSE;
}
}
Expand All @@ -266,7 +265,7 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
{
aiMove = gBattleMons[battler].moves[moveIndex];
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) > UQ_4_12(0.0) && aiMove != MOVE_NONE)
if (aiMove != MOVE_NONE && AI_DATA->effectiveness[battler][opposingBattler][moveIndex] > UQ_4_12(0.0))
return FALSE;
}
}
Expand All @@ -292,12 +291,8 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler)
// Check if Pokémon has a super effective move.
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = gBattleMons[battler].moves[i];
if (move != MOVE_NONE)
{
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
return FALSE;
}
if (gBattleMons[battler].moves[i] != MOVE_NONE && AI_DATA->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
return FALSE;
}

// Get party information.
Expand Down Expand Up @@ -528,7 +523,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|| monAbility == ABILITY_EARLY_BIRD)
|| holdEffect == (HOLD_EFFECT_CURE_SLP | HOLD_EFFECT_CURE_STATUS)
|| HasMove(battler, MOVE_SLEEP_TALK)
|| (HasMoveEffect(battler, MOVE_SNORE) && AI_GetMoveEffectiveness(MOVE_SNORE, battler, opposingBattler) >= UQ_4_12(2.0))
|| (HasMove(battler, MOVE_SNORE) && AI_DATA->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, MOVE_SNORE)] >= UQ_4_12(2.0))
|| (IsBattlerGrounded(battler)
&& (HasMove(battler, MOVE_MISTY_TERRAIN) || HasMove(battler, MOVE_ELECTRIC_TERRAIN)))
)
Expand Down Expand Up @@ -631,7 +626,6 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler)
static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
{
s32 i;
u16 move;

u32 opposingPosition = BATTLE_OPPOSITE(GetBattlerPosition(battler));
u32 opposingBattler = GetBattlerAtPosition(opposingPosition);
Expand All @@ -640,11 +634,10 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = gBattleMons[battler].moves[i];
if (move == MOVE_NONE)
if (gBattleMons[battler].moves[i] == MOVE_NONE)
continue;

if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
if (AI_DATA->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
{
if (noRng)
return TRUE;
Expand All @@ -662,11 +655,10 @@ static bool32 HasSuperEffectiveMoveAgainstOpponents(u32 battler, bool32 noRng)
{
for (i = 0; i < MAX_MON_MOVES; i++)
{
move = gBattleMons[battler].moves[i];
if (move == MOVE_NONE)
if (gBattleMons[battler].moves[i] == MOVE_NONE)
continue;

if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
if (AI_DATA->effectiveness[battler][opposingBattler][i] >= UQ_4_12(2.0))
{
if (noRng)
return TRUE;
Expand Down Expand Up @@ -859,7 +851,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
return SetSwitchinAndSwitch(battler, PARTY_SIZE);

// Stay in if effective move
else if (AI_GetMoveEffectiveness(encoredMove, battler, opposingBattler) >= UQ_4_12(2.0))
else if (AI_DATA->effectiveness[battler][opposingBattler][GetIndexInMoveArray(battler, encoredMove)] >= UQ_4_12(2.0))
return FALSE;

// Switch out 50% of the time otherwise
Expand Down Expand Up @@ -1235,7 +1227,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
int dmg, bestDmg = 0;
int bestMonId = PARTY_SIZE;
u32 rollType = GetDmgRollType(battler);

uq4_12_t effectiveness;
u32 aiMove;

// If we couldn't find the best mon in terms of typing, find the one that deals most damage.
Expand All @@ -1250,7 +1242,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
{
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j);
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, rollType);
dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, &effectiveness, TRUE, rollType);
if (bestDmg < dmg)
{
bestDmg = dmg;
Expand Down Expand Up @@ -1699,13 +1691,14 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle
int i = 0;
u32 playerMove;
s32 damageTaken = 0, maxDamageTaken = 0;
uq4_12_t effectiveness;

for (i = 0; i < MAX_MON_MOVES; i++)
{
playerMove = gBattleMons[opposingBattler].moves[i];
if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && gMovesInfo[playerMove].effect != EFFECT_FOCUS_PUNCH)
{
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, FALSE, DMG_ROLL_HIGHEST);
damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, &effectiveness, FALSE, DMG_ROLL_HIGHEST);
if (damageTaken > maxDamageTaken)
maxDamageTaken = damageTaken;
}
Expand Down Expand Up @@ -1787,6 +1780,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
u32 aiMove, hitsToKOAI, maxHitsToKO = 0;
u16 bestResist = UQ_4_12(1.0), bestResistEffective = UQ_4_12(1.0), typeMatchup;
bool32 isFreeSwitch = IsFreeSwitch(isSwitchAfterKO, battlerIn1, opposingBattler), isSwitchinFirst, canSwitchinWin1v1;
uq4_12_t effectiveness = UQ_4_12(1.0);

// Iterate through mons
for (i = firstId; i < lastId; i++)
Expand Down Expand Up @@ -1836,9 +1830,13 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
{
if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_CONSERVATIVE)
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_LOWEST);
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, &effectiveness, TRUE, DMG_ROLL_LOWEST);
else
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT);
damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, &effectiveness, TRUE, DMG_ROLL_DEFAULT);
}
else
{
effectiveness = AI_GetMoveEffectiveness(aiMove, battler, opposingBattler);
}

// Offensive switchin decisions are based on which whether switchin moves first and whether it can win a 1v1
Expand Down Expand Up @@ -1867,7 +1865,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
{
if (typeMatchup < bestResistEffective)
{
if (AI_GetMoveEffectiveness(aiMove, battler, opposingBattler) >= UQ_4_12(2.0))
if (effectiveness >= UQ_4_12(2.0))
{
if (canSwitchinWin1v1)
{
Expand Down
17 changes: 13 additions & 4 deletions src/battle_ai_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,6 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u
simDamage.minimum = 0;
}

// convert multiper to AI_EFFECTIVENESS_xX
*typeEffectiveness = effectivenessMultiplier;

// Undo temporary settings
Expand Down Expand Up @@ -1949,6 +1948,17 @@ u16 *GetMovesArray(u32 battler)
return gBattleResources->battleHistory->usedMoves[battler];
}

u32 GetIndexInMoveArray(u32 battler, u32 move)
{
u16 *moves = GetMovesArray(battler);
u32 i;
for (i = 0; i < MAX_MON_MOVES; i++) {
if (moves[i] == move)
return i;
}
return MAX_MON_MOVES;
}

bool32 HasOnlyMovesWithCategory(u32 battlerId, u32 category, bool32 onlyOffensive)
{
u32 i;
Expand Down Expand Up @@ -3537,10 +3547,9 @@ void FreeRestoreBattleMons(struct BattlePokemon *savedBattleMons)
}

// party logic
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, bool32 isPartyMonAttacker, enum DamageRollType rollType)
s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct BattlePokemon switchinCandidate, uq4_12_t *effectiveness, bool32 isPartyMonAttacker, enum DamageRollType rollType)
{
struct SimulatedDamage dmg;
uq4_12_t effectiveness;
struct BattlePokemon *savedBattleMons = AllocSaveBattleMons();

if (isPartyMonAttacker)
Expand All @@ -3558,7 +3567,7 @@ s32 AI_CalcPartyMonDamage(u32 move, u32 battlerAtk, u32 battlerDef, struct Battl
AI_THINKING_STRUCT->saved[battlerAtk].saved = FALSE;
}

dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, FALSE, AI_GetWeather(), rollType);
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, effectiveness, FALSE, AI_GetWeather(), rollType);
// restores original gBattleMon struct
FreeRestoreBattleMons(savedBattleMons);

Expand Down

0 comments on commit 3dc0541

Please sign in to comment.