From 0f21415130231b75a7e792c321a4f495681d6082 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:15:12 -0400 Subject: [PATCH] Minor AI flag fixes / cleanup (#4924) * AI flag fixes / cleanup * Review feedback --- include/constants/battle_ai.h | 2 +- src/battle_ai_main.c | 8 ++++++-- src/battle_ai_switch_items.c | 12 ++++++++++-- src/battle_ai_util.c | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index bddd03724b..79f8f04d6c 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -32,7 +32,7 @@ #define AI_FLAG_RISKY (1 << 4) #define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5) #define AI_FLAG_PREFER_BATON_PASS (1 << 6) -#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // removed, split between AI_FLAG_CHECK_BAD_MOVE & AI_FLAG_CHECK_GOOD_MOVE +#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner #define AI_FLAG_HP_AWARE (1 << 8) #define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target // New, Trainer Handicap Flags diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 43fdcb5ce9..a21e13b8fc 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -3272,6 +3272,10 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); } break; + case EFFECT_FINAL_GAMBIT: + if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_WILL_SUICIDE) + ADJUST_SCORE(DECENT_EFFECT); + break; case EFFECT_MIRROR_MOVE: if (predictedMove != MOVE_NONE) return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); @@ -4995,11 +4999,11 @@ static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 scor ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_BATON_PASS: - // TODO: Increase Score based on current stats. if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING)) ADJUST_SCORE(DECENT_EFFECT); if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) ADJUST_SCORE(-3); + ADJUST_SCORE(CountPositiveStatStages(battlerAtk) - CountNegativeStatStages(battlerAtk)); break; default: break; @@ -5074,6 +5078,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_BIDE: case EFFECT_CONVERSION: case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: case EFFECT_MIST: case EFFECT_FOCUS_ENERGY: case EFFECT_CONVERSION_2: @@ -5099,7 +5104,6 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CONVERSION: case EFFECT_REFLECT: case EFFECT_LIGHT_SCREEN: - case EFFECT_AURORA_VEIL: case EFFECT_MIST: case EFFECT_FOCUS_ENERGY: case EFFECT_RAGE: diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 6471c25ce6..1d4ce806a7 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1305,7 +1305,10 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) { aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j); - dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); + if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_CONSERVATIVE) + dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_LOWEST); + else + dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); if (bestDmg < dmg) { bestDmg = dmg; @@ -1864,7 +1867,12 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, // Only do damage calc if switching after KO, don't need it otherwise and saves ~0.02s per turn if (isSwitchAfterKO && aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) - damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); + { + if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_CONSERVATIVE) + damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_LOWEST); + else + damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); + } // Check for Baton Pass; hitsToKO requirements mean mon can boost and BP without dying whether it's slower or not if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed))) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index fe73ab3bce..1d23d4c965 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -844,6 +844,8 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s { case EFFECT_MAX_HP_50_RECOIL: case EFFECT_MIND_BLOWN: + case EFFECT_EXPLOSION: + case EFFECT_FINAL_GAMBIT: return TRUE; case EFFECT_RECOIL_IF_MISS: if (AI_IsDamagedByRecoil(battlerAtk))