Use 9th roll instead of average in AI calcs (#4679)

* Use 9th roll instead of average in AI calcs

* damage_roll

* duke suggestion
This commit is contained in:
Alex 2024-06-02 15:36:12 +02:00 committed by GitHub
parent 240b69d032
commit 4eda5f61af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 13 additions and 12 deletions

View file

@ -6,11 +6,12 @@
// Roll boundaries used by AI when scoring. Doesn't affect actual damage dealt. // 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 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 enum
{ {
DMG_ROLL_LOWEST, DMG_ROLL_LOWEST,
DMG_ROLL_AVERAGE, DMG_ROLL_DEFAULT,
DMG_ROLL_HIGHEST, DMG_ROLL_HIGHEST,
}; };

View file

@ -464,7 +464,7 @@ static void SetBattlerAiMovesData(struct AiLogicData *aiData, u32 battlerAtk, u3
else if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE) else if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CONSERVATIVE)
dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_LOWEST); dmg = AI_CalcDamage(move, battlerAtk, battlerDef, &effectiveness, TRUE, weather, DMG_ROLL_LOWEST);
else 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->moveAccuracy[battlerAtk][battlerDef][i] = Ai_SetMoveAccuracy(aiData, battlerAtk, battlerDef, move);
} }
aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg; aiData->simulatedDmg[battlerAtk][battlerDef][i] = dmg;

View file

@ -1279,7 +1279,7 @@ static u32 GetBestMonDmg(struct Pokemon *party, int firstId, int lastId, u8 inva
if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0) if (aiMove != MOVE_NONE && gMovesInfo[aiMove].power != 0)
{ {
aiMove = GetMonData(&party[i], MON_DATA_MOVE1 + j); 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) if (bestDmg < dmg)
{ {
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 // 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) 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 // 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))) if (aiMove == MOVE_BATON_PASS && ((hitsToKOAI > hitsToKOAIThreshold + 1 && AI_DATA->switchinCandidate.battleMon.speed < playerMonSpeed) || (hitsToKOAI > hitsToKOAIThreshold && AI_DATA->switchinCandidate.battleMon.speed > playerMonSpeed)))

View file

@ -391,9 +391,9 @@ static inline s32 HighestRollDmg(s32 dmg)
return 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; dmg /= 100;
return dmg; return dmg;
} }
@ -566,8 +566,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
aiData->abilities[battlerAtk], aiData->abilities[battlerDef]); aiData->abilities[battlerAtk], aiData->abilities[battlerDef]);
u32 critChance = GetCritHitChance(critChanceIndex); u32 critChance = GetCritHitChance(critChanceIndex);
// With critChance getting closer to 1, dmg gets closer to critDmg. // With critChance getting closer to 1, dmg gets closer to critDmg.
if (dmgRoll == DMG_ROLL_AVERAGE) if (dmgRoll == DMG_ROLL_DEFAULT)
dmg = AverageDmg((critDmg + normalDmg * (critChance - 1)) / (critChance)); dmg = DmgRoll((critDmg + normalDmg * (critChance - 1)) / (critChance));
else if (dmgRoll == DMG_ROLL_HIGHEST) else if (dmgRoll == DMG_ROLL_HIGHEST)
dmg = HighestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance)); dmg = HighestRollDmg((critDmg + normalDmg * (critChance - 1)) / (critChance));
else else
@ -575,8 +575,8 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
} }
else else
{ {
if (dmgRoll == DMG_ROLL_AVERAGE) if (dmgRoll == DMG_ROLL_DEFAULT)
dmg = AverageDmg(normalDmg); dmg = DmgRoll(normalDmg);
else if (dmgRoll == DMG_ROLL_HIGHEST) else if (dmgRoll == DMG_ROLL_HIGHEST)
dmg = HighestRollDmg(normalDmg); dmg = HighestRollDmg(normalDmg);
else 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)) else if (!IS_MOVE_STATUS(chosenMove) && IS_MOVE_STATUS(gBattleStruct->zmove.chosenZMove))
return FALSE; 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 FALSE; // don't waste damaging z move if can otherwise faint target
return TRUE; return TRUE;