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

@ -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,
};

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)
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;

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)
{
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)))

View file

@ -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;