Fix how AI categorizes Weak moves and give priority to always hits moves when needed (#3109)

* ai weak move fix and always hits move prioritarizing
This commit is contained in:
DizzyEggg 2023-07-16 08:24:59 +02:00 committed by GitHub
parent 58ede15263
commit 3c5c68ac58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 2 deletions

View File

@ -85,6 +85,7 @@ bool32 ShouldLowerEvasion(u8 battlerAtk, u8 battlerDef, u16 defAbility);
bool32 IsAffectedByPowder(u8 battler, u16 ability, u16 holdEffect);
bool32 MovesWithSplitUnusable(u32 attacker, u32 target, u32 split);
s32 AI_CalcDamage(u16 move, u8 battlerAtk, u8 battlerDef, u8 *effectiveness, bool32 considerZPower);
u32 GetNoOfHitsToKO(u32 dmg, s32 hp);
u8 GetMoveDamageResult(u16 move);
u32 GetCurrDamageHpPercent(u8 battlerAtk, u8 battlerDef);
u16 AI_GetTypeEffectiveness(u16 move, u8 battlerAtk, u8 battlerDef);

View File

@ -3102,6 +3102,19 @@ static bool32 IsPinchBerryItemEffect(u16 holdEffect)
return FALSE;
}
static u32 GetAIMostDamagingMoveId(u8 battlerAtk, u8 battlerDef)
{
u32 i, id = 0;
u32 mostDmg = 0;
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (AI_DATA->simulatedDmg[battlerAtk][battlerDef][i] > mostDmg)
id = i, mostDmg = AI_DATA->simulatedDmg[battlerAtk][battlerDef][i];
}
return id;
}
// AI_FLAG_CHECK_VIABILITY - a weird mix of increasing and decreasing scores
static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
@ -3122,6 +3135,14 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// check always hits
if (!IS_MOVE_STATUS(move) && gBattleMoves[move].accuracy == 0)
{
// If 2 moves can KO the target in the same number of turns, but one of them always hits and there is a risk the other move could miss, prioritize the always hits move.
if (gBattleMons[battlerDef].statStages[STAT_EVASION] > 6 || gBattleMons[battlerAtk].statStages[STAT_ACC] < 6)
{
u32 mostDmgMoveId = GetAIMostDamagingMoveId(battlerAtk, battlerDef);
u32 *dmgs = AI_DATA->simulatedDmg[battlerAtk][battlerDef];
if (GetNoOfHitsToKO(dmgs[mostDmgMoveId], gBattleMons[battlerDef].hp) == GetNoOfHitsToKO(dmgs[AI_THINKING_STRUCT->movesetIndex], gBattleMons[battlerDef].hp))
score++;
}
if (gBattleMons[battlerDef].statStages[STAT_EVASION] >= 10 || gBattleMons[battlerAtk].statStages[STAT_ACC] <= 2)
score++;
if (AI_RandLessThan(100) && (gBattleMons[battlerDef].statStages[STAT_EVASION] >= 8 || gBattleMons[battlerAtk].statStages[STAT_ACC] <= 4))

View File

@ -953,6 +953,11 @@ static u32 WhichMoveBetter(u32 move1, u32 move2)
return 2;
}
u32 GetNoOfHitsToKO(u32 dmg, s32 hp)
{
return hp / (dmg + 1) + 1;
}
u8 GetMoveDamageResult(u16 move)
{
s32 i, checkedMove, bestId, currId, hp;
@ -1018,9 +1023,8 @@ u8 GetMoveDamageResult(u16 move)
currId = AI_THINKING_STRUCT->movesetIndex;
if (currId == bestId)
AI_THINKING_STRUCT->funcResult = MOVE_POWER_BEST;
// Compare percentage difference.
else if ((moveDmgs[currId] >= hp || moveDmgs[bestId] < hp) // If current move can faint as well, or if neither can
&& (moveDmgs[bestId] * 100 / hp) - (moveDmgs[currId] * 100 / hp) <= 30
&& GetNoOfHitsToKO(moveDmgs[currId], hp) - GetNoOfHitsToKO(moveDmgs[bestId], hp) <= 2 // Consider a move weak if it needs to be used at least 2 times more to faint the target, compared to the best move.
&& WhichMoveBetter(gBattleMons[sBattler_AI].moves[bestId], gBattleMons[sBattler_AI].moves[currId]) != 0)
AI_THINKING_STRUCT->funcResult = MOVE_POWER_GOOD;
else