From 4eda5f61af48f41769cd035a9c7a27c5ef71b8d7 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 2 Jun 2024 15:36:12 +0200 Subject: [PATCH] Use 9th roll instead of average in AI calcs (#4679) * Use 9th roll instead of average in AI calcs * damage_roll * duke suggestion --- include/battle_ai_util.h | 5 +++-- src/battle_ai_main.c | 2 +- src/battle_ai_switch_items.c | 4 ++-- src/battle_ai_util.c | 14 +++++++------- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 36ce1cdda50e..ffb5d3ca77f6 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -4,13 +4,14 @@ #define FOE(battler) ((BATTLE_OPPOSITE(battler)) & BIT_SIDE) // Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt. -#define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI +#define MAX_ROLL_PERCENTAGE DMG_ROLL_PERCENT_HI #define MIN_ROLL_PERCENTAGE DMG_ROLL_PERCENT_LO +#define DMG_ROLL_PERCENTAGE ((MAX_ROLL_PERCENTAGE + MIN_ROLL_PERCENTAGE + 1) / 2) // Controls the damage roll the AI sees for the default roll. By default the 9th roll is seen enum { DMG_ROLL_LOWEST, - DMG_ROLL_AVERAGE, + DMG_ROLL_DEFAULT, DMG_ROLL_HIGHEST, }; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 484efbbbd636..10ad41d1fcc0 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -464,7 +464,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3 else if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_LOWEST); else - dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_AVERAGE); + dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_DEFAULT); aiData->moveAccuracy[battlerAtk][battlerDef][i] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move); } aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 19bf2adbc672..77552ccae980 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1279,7 +1279,7 @@ 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_AVERAGE); + dmg = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); if (bestDmg < dmg) { bestDmg = dmg; @@ -1840,7 +1840,7 @@ 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_AVERAGE); + 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 f76599a52f39..7efee7ae05f5 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -391,9 +391,9 @@ static inline s32 HighestRollDmg(s32 dmg) return dmg; } -static inline s32 AverageDmg(s32 dmg) +static inline s32 DmgRoll(s32 dmg) { - dmg = (dmg * (MIN_ROLL_PERCENTAGE + MAX_ROLL_PERCENTAGE)) / 2; + dmg *= DMG_ROLL_PERCENTAGE; dmg /= 100; return dmg; } @@ -566,8 +566,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); u32 critChance = GetCritHitChance(critChanceIndex); // With critChance getting closer to 1, dmg gets closer to critDmg. - if (dmgRoll == DMG_ROLL_AVERAGE) - dmg = AverageDmg((critDmg + normalDmg * (critChance - 1)) / (critChance)); + if (dmgRoll == DMG_ROLL_DEFAULT) + dmg = DmgRoll((critDmg + normalDmg * (critChance - 1)) / (critChance)); else if (dmgRoll == DMG_ROLL_HIGHEST) dmg = HighestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance)); else @@ -575,8 +575,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes } else { - if (dmgRoll == DMG_ROLL_AVERAGE) - dmg = AverageDmg(normalDmg); + if (dmgRoll == DMG_ROLL_DEFAULT) + dmg = DmgRoll(normalDmg); else if (dmgRoll == DMG_ROLL_HIGHEST) dmg = HighestRollDmg(normalDmg); else @@ -3763,7 +3763,7 @@ bool32 ShouldUseZMove(u32 battlerAtk, u32 battlerDef, u32 chosenMove) else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove)) return FALSE; - if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE, DMG_ROLL_AVERAGE) >= gBattleMons[battlerDef].hp) + if (!IS_MOVE_STATUS(chosenMove) && AI_CalcDamageSaveBattlers(chosenMove, battlerAtk, battlerDef, &effectiveness, FALSE, DMG_ROLL_DEFAULT) >= gBattleMons[battlerDef].hp) return FALSE; // don't waste damaging z move if can otherwise faint target return TRUE;