Made AI_CheckBadMove take the primal weathers into account

Credits to Syreldar.
Also took the chance and removed trailing spaces from the file.
This commit is contained in:
LOuroboros 2021-08-30 19:48:59 -03:00
parent 216d8f0608
commit c0c6821f62

View file

@ -249,7 +249,7 @@ static u8 ChooseMoveOrAction_Singles(void)
RecordLastUsedMoveByTarget(); RecordLastUsedMoveByTarget();
GetAiLogicData(sBattler_AI, gBattlerTarget); GetAiLogicData(sBattler_AI, gBattlerTarget);
while (flags != 0) while (flags != 0)
{ {
if (flags & 1) if (flags & 1)
@ -364,10 +364,10 @@ static u8 ChooseMoveOrAction_Doubles(void)
BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4); BattleAI_SetupAIData(gBattleStruct->palaceFlags >> 4);
else else
BattleAI_SetupAIData(0xF); BattleAI_SetupAIData(0xF);
gBattlerTarget = i; gBattlerTarget = i;
GetAiLogicData(sBattler_AI, gBattlerTarget); GetAiLogicData(sBattler_AI, gBattlerTarget);
if ((i & BIT_SIDE) != (sBattler_AI & BIT_SIDE)) if ((i & BIT_SIDE) != (sBattler_AI & BIT_SIDE))
RecordLastUsedMoveByTarget(); RecordLastUsedMoveByTarget();
@ -510,19 +510,21 @@ static void BattleAI_DoAIProcessing(void)
static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
// move data // move data
s32 moveType;
u8 atkPriority = GetMovePriority(battlerAtk, move); u8 atkPriority = GetMovePriority(battlerAtk, move);
u16 moveEffect = gBattleMoves[move].effect; u16 moveEffect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type;
u8 moveTarget = gBattleMoves[move].target; u8 moveTarget = gBattleMoves[move].target;
u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move); u16 accuracy = AI_GetMoveAccuracy(battlerAtk, battlerDef, AI_DATA->atkAbility, AI_DATA->defAbility, AI_DATA->atkHoldEffect, AI_DATA->defHoldEffect, move);
u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef); u8 effectiveness = AI_GetMoveEffectiveness(move, battlerAtk, battlerDef);
bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk); bool32 isDoubleBattle = IsValidDoubleBattle(battlerAtk);
u32 i; u32 i;
u16 predictedMove = gLastMoves[battlerDef]; // TODO better move prediction u16 predictedMove = gLastMoves[battlerDef]; // TODO better move prediction
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
GET_MOVE_TYPE(move, move);
// check non-user target // check non-user target
if (!(gBattleMoves[move].target & MOVE_TARGET_USER)) if (!(gBattleMoves[move].target & MOVE_TARGET_USER))
{ {
@ -532,7 +534,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
RETURN_SCORE_MINUS(20); RETURN_SCORE_MINUS(20);
} }
// check ground immunities // check ground immunities
if (moveType == TYPE_GROUND if (moveType == TYPE_GROUND
&& !IsBattlerGrounded(battlerDef) && !IsBattlerGrounded(battlerDef)
@ -544,11 +546,11 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
RETURN_SCORE_MINUS(20); RETURN_SCORE_MINUS(20);
} }
// check off screen // check off screen
if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) != 1) if (IsSemiInvulnerable(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) != 1)
RETURN_SCORE_MINUS(20); // if target off screen and we go first, don't use move RETURN_SCORE_MINUS(20); // if target off screen and we go first, don't use move
// check if negates type // check if negates type
switch (effectiveness) switch (effectiveness)
{ {
@ -559,7 +561,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
RETURN_SCORE_MINUS(10); RETURN_SCORE_MINUS(10);
break; break;
} }
// target ability checks // target ability checks
if (!DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move)) if (!DoesBattlerIgnoreAbilityChecks(AI_DATA->atkAbility, move))
{ {
@ -674,7 +676,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
RETURN_SCORE_MINUS(10); RETURN_SCORE_MINUS(10);
break; break;
} // def ability checks } // def ability checks
// target partner ability checks & not attacking partner // target partner ability checks & not attacking partner
if (isDoubleBattle) if (isDoubleBattle)
{ {
@ -712,35 +714,35 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
} // def partner ability checks } // def partner ability checks
} // ignore def ability check } // ignore def ability check
// gen7+ dark type mons immune to priority->elevated moves from prankster // gen7+ dark type mons immune to priority->elevated moves from prankster
#if B_PRANKSTER >= GEN_7 #if B_PRANKSTER >= GEN_7
if (AI_DATA->atkAbility == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && IS_MOVE_STATUS(move) if (AI_DATA->atkAbility == ABILITY_PRANKSTER && IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) && IS_MOVE_STATUS(move)
&& !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER))) && !(moveTarget & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER)))
RETURN_SCORE_MINUS(10); RETURN_SCORE_MINUS(10);
#endif #endif
// terrain & effect checks // terrain & effect checks
if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN)) if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_ELECTRIC_TERRAIN))
{ {
if (moveEffect == EFFECT_SLEEP || moveEffect == EFFECT_YAWN) if (moveEffect == EFFECT_SLEEP || moveEffect == EFFECT_YAWN)
RETURN_SCORE_MINUS(20); RETURN_SCORE_MINUS(20);
} }
if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN)) if (AI_IsTerrainAffected(battlerDef, STATUS_FIELD_MISTY_TERRAIN))
{ {
if (IsNonVolatileStatusMoveEffect(moveEffect) || IsConfusionMoveEffect(moveEffect)) if (IsNonVolatileStatusMoveEffect(moveEffect) || IsConfusionMoveEffect(moveEffect))
RETURN_SCORE_MINUS(20); RETURN_SCORE_MINUS(20);
} }
if (AI_IsTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0) if (AI_IsTerrainAffected(battlerAtk, STATUS_FIELD_PSYCHIC_TERRAIN) && atkPriority > 0)
{ {
RETURN_SCORE_MINUS(20); RETURN_SCORE_MINUS(20);
} }
} // end check MOVE_TARGET_USER } // end check MOVE_TARGET_USER
// the following checks apply to any target (including user) // the following checks apply to any target (including user)
// throat chop check // throat chop check
if (gDisableStructs[battlerAtk].throatChopTimer && TestMoveFlags(move, FLAG_SOUND)) if (gDisableStructs[battlerAtk].throatChopTimer && TestMoveFlags(move, FLAG_SOUND))
return 0; // Can't even select move at all return 0; // Can't even select move at all
@ -748,8 +750,35 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(battlerAtk, move)) if (gStatuses3[battlerAtk] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(battlerAtk, move))
return 0; // Can't even select heal blocked move return 0; // Can't even select heal blocked move
// primal weather check // primal weather check
//TODO if (WEATHER_HAS_EFFECT)
{
if (gBattleWeather & WEATHER_PRIMAL_ANY)
{
switch (move)
{
case MOVE_SUNNY_DAY:
case MOVE_RAIN_DANCE:
case MOVE_HAIL:
case MOVE_SANDSTORM:
RETURN_SCORE_MINUS(30);
}
}
if (!IS_MOVE_STATUS(move))
{
if (gBattleWeather & WEATHER_SUN_PRIMAL)
{
if (moveType == TYPE_WATER)
RETURN_SCORE_MINUS(30);
}
else if (gBattleWeather & WEATHER_RAIN_PRIMAL)
{
if (moveType == TYPE_FIRE)
RETURN_SCORE_MINUS(30);
}
}
}
// check move effects // check move effects
switch (moveEffect) switch (moveEffect)
{ {
@ -763,7 +792,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_EXPLOSION: case EFFECT_EXPLOSION:
if (!(AI_THINKING_STRUCT->aiFlags & AI_FLAG_WILL_SUICIDE)) if (!(AI_THINKING_STRUCT->aiFlags & AI_FLAG_WILL_SUICIDE))
score -= 2; score -= 2;
if (effectiveness == AI_EFFECTIVENESS_x0) if (effectiveness == AI_EFFECTIVENESS_x0)
{ {
score -= 10; score -= 10;
@ -813,7 +842,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPATK) || !HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL)) if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPATK) || !HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL))
score -= 10; score -= 10;
break; break;
case EFFECT_SPECIAL_DEFENSE_UP: case EFFECT_SPECIAL_DEFENSE_UP:
case EFFECT_SPECIAL_DEFENSE_UP_2: case EFFECT_SPECIAL_DEFENSE_UP_2:
if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPDEF)) if (!BattlerStatCanRise(battlerAtk, AI_DATA->atkAbility, STAT_SPDEF))
score -= 10; score -= 10;
@ -1121,7 +1150,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_LOW_KICK: case EFFECT_LOW_KICK:
// AI_CBM_HighRiskForDamage // AI_CBM_HighRiskForDamage
if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) if (AI_DATA->defAbility == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2)
score -= 10; score -= 10;
break; break;
case EFFECT_COUNTER: case EFFECT_COUNTER:
case EFFECT_MIRROR_COAT: case EFFECT_MIRROR_COAT:
@ -1131,7 +1160,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| DoesSubstituteBlockMove(battlerAtk, AI_DATA->battlerDefPartner, predictedMove)) || DoesSubstituteBlockMove(battlerAtk, AI_DATA->battlerDefPartner, predictedMove))
score -= 10; score -= 10;
break; break;
case EFFECT_ROAR: case EFFECT_ROAR:
if (CountUsablePartyMons(battlerDef) == 0) if (CountUsablePartyMons(battlerDef) == 0)
score -= 10; score -= 10;
@ -1279,7 +1308,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SPIKES: case EFFECT_SPIKES:
if (gSideTimers[GetBattlerSide(battlerDef)].spikesAmount >= 3) if (gSideTimers[GetBattlerSide(battlerDef)].spikesAmount >= 3)
score -= 10; score -= 10;
else if (PartnerMoveIsSameNoTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove) else if (PartnerMoveIsSameNoTarget(AI_DATA->battlerAtkPartner, move, AI_DATA->partnerMove)
&& gSideTimers[GetBattlerSide(battlerDef)].spikesAmount == 2) && gSideTimers[GetBattlerSide(battlerDef)].spikesAmount == 2)
score -= 10; // only one mon needs to set up the last layer of Spikes score -= 10; // only one mon needs to set up the last layer of Spikes
break; break;
@ -1457,7 +1486,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 10; score -= 10;
break; break;
} }
if (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect == HOLD_EFFECT_CURE_ATTRACT) if (B_MENTAL_HERB >= GEN_5 && AI_DATA->defHoldEffect == HOLD_EFFECT_CURE_ATTRACT)
score -= 6; score -= 6;
break; break;
@ -1687,7 +1716,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gBattleMons[battlerAtk].hp > (gBattleMons[battlerAtk].hp + gBattleMons[battlerDef].hp) / 2) if (gBattleMons[battlerAtk].hp > (gBattleMons[battlerAtk].hp + gBattleMons[battlerDef].hp) / 2)
score -= 10; score -= 10;
break; break;
case EFFECT_CONVERSION_2: case EFFECT_CONVERSION_2:
//TODO //TODO
break; break;
@ -1747,7 +1776,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
break; break;
} // move check } // move check
if (decreased) if (decreased)
break; break;
if (IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility)) if (IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility))
@ -1789,7 +1818,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
IncreaseAllyProtectionViability(&viability, 0xFF); IncreaseAllyProtectionViability(&viability, 0xFF);
}*/ }*/
} }
break; break;
case EFFECT_MIRACLE_EYE: case EFFECT_MIRACLE_EYE:
if (gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED) if (gStatuses3[battlerDef] & STATUS3_MIRACLE_EYED)
score -= 10; score -= 10;
@ -1837,7 +1866,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| ((AI_DATA->defAbility == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner || ((AI_DATA->defAbility == ABILITY_CONTRARY) && !IsTargetingPartner(battlerAtk, battlerDef))) // don't want to raise target stats unless its your partner
score -= 10; score -= 10;
break; break;
case EFFECT_PSYCH_UP: // haze stats check case EFFECT_PSYCH_UP: // haze stats check
{ {
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
@ -2001,7 +2030,7 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
u32 atkNegativeStages = CountNegativeStatStages(battlerAtk); u32 atkNegativeStages = CountNegativeStatStages(battlerAtk);
u32 defPositiveStages = CountPositiveStatStages(battlerDef); u32 defPositiveStages = CountPositiveStatStages(battlerDef);
u32 defNegativeStages = CountNegativeStatStages(battlerDef); u32 defNegativeStages = CountNegativeStatStages(battlerDef);
if (atkPositiveStages >= defPositiveStages && atkNegativeStages <= defNegativeStages) if (atkPositiveStages >= defPositiveStages && atkNegativeStages <= defNegativeStages)
score -= 10; score -= 10;
break; break;
@ -2399,21 +2428,21 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 10; score -= 10;
break;*/ break;*/
} // move effect checks } // move effect checks
if (score < 0) if (score < 0)
score = 0; score = 0;
return score; return score;
} }
static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
if (gBattleMoves[move].power == 0) if (gBattleMoves[move].power == 0)
return score; // can't make anything faint with no power return score; // can't make anything faint with no power
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION) if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0) && gBattleMoves[move].effect != EFFECT_EXPLOSION)
{ {
// this move can faint the target // this move can faint the target
@ -2427,24 +2456,43 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// this move isn't expected to faint the target // this move isn't expected to faint the target
if (TestMoveFlags(move, FLAG_HIGH_CRIT)) if (TestMoveFlags(move, FLAG_HIGH_CRIT))
score += 2; // crit makes it more likely to make them faint score += 2; // crit makes it more likely to make them faint
if (GetMoveDamageResult(move) == MOVE_POWER_OTHER) if (GetMoveDamageResult(move) == MOVE_POWER_OTHER)
score--; score--;
switch (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef)) switch (AI_GetMoveEffectiveness(move, battlerAtk, battlerDef))
{ {
case AI_EFFECTIVENESS_x4: case AI_EFFECTIVENESS_x4:
score += 4; if (WEATHER_HAS_EFFECT
&& gBattleWeather & WEATHER_STRONG_WINDS
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING))
{
if (AI_RandLessThan(176)) //Consider it supereffective instead of hypereffective.
score += 2;
else
score++;
}
else
score += 4;
break; break;
case AI_EFFECTIVENESS_x2: case AI_EFFECTIVENESS_x2:
if (AI_RandLessThan(176)) if (WEATHER_HAS_EFFECT
score += 2; && gBattleWeather & WEATHER_STRONG_WINDS
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING))
{
break; // Don't increase score, consider it neutral.
}
else else
score++; {
if (AI_RandLessThan(176))
score += 2;
else
score++;
}
break; break;
} }
} }
//AI_TryToFaint_CheckIfDanger //AI_TryToFaint_CheckIfDanger
if (!IsAiFaster(AI_CHECK_FASTER) && CanTargetFaintAi(battlerDef, battlerAtk)) if (!IsAiFaster(AI_CHECK_FASTER) && CanTargetFaintAi(battlerDef, battlerAtk))
{ // AI_TryToFaint_Danger { // AI_TryToFaint_Danger
@ -2453,7 +2501,7 @@ static s16 AI_TryToFaint(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
else else
score++; score++;
} }
return score; return score;
} }
@ -2472,7 +2520,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
bool32 attackerHasBadAbility = (GetAbilityRating(AI_DATA->atkAbility) < 0); bool32 attackerHasBadAbility = (GetAbilityRating(AI_DATA->atkAbility) < 0);
bool32 partnerHasBadAbility = (GetAbilityRating(atkPartnerAbility) < 0); bool32 partnerHasBadAbility = (GetAbilityRating(atkPartnerAbility) < 0);
u16 predictedMove = gLastMoves[battlerDef]; //for now u16 predictedMove = gLastMoves[battlerDef]; //for now
// check what effect partner is using // check what effect partner is using
if (AI_DATA->partnerMove != 0) if (AI_DATA->partnerMove != 0)
{ {
@ -2506,8 +2554,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} }
} // check partner move effect } // check partner move effect
// consider our move effect relative to partner state // consider our move effect relative to partner state
switch (effect) switch (effect)
{ {
@ -2528,8 +2576,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
break; break;
} // our effect relative to partner } // our effect relative to partner
// consider global move effects // consider global move effects
switch (effect) switch (effect)
{ {
@ -2559,8 +2607,8 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
break; break;
} // global move effect check } // global move effect check
// check specific target // check specific target
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
{ {
@ -2667,11 +2715,11 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
RETURN_SCORE_PLUS(1); RETURN_SCORE_PLUS(1);
} }
break; break;
} }
} // ability checks } // ability checks
} // move power check } // move power check
// attacker move effects specifically targeting partner // attacker move effects specifically targeting partner
if (!partnerProtecting) if (!partnerProtecting)
{ {
@ -2784,12 +2832,12 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} // attacker move effects } // attacker move effects
} // check partner protecting } // check partner protecting
score -= 30; // otherwise, don't target partner score -= 30; // otherwise, don't target partner
} }
else // checking opponent else // checking opponent
{ {
// these checks mostly handled in AI_CheckBadMove and AI_CheckViability // these checks mostly handled in AI_CheckBadMove and AI_CheckViability
switch (effect) switch (effect)
{ {
case EFFECT_SKILL_SWAP: case EFFECT_SKILL_SWAP:
@ -2812,10 +2860,10 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 3; score -= 3;
break; break;
} }
// lightning rod, flash fire against enemy handled in AI_CheckBadMove // lightning rod, flash fire against enemy handled in AI_CheckBadMove
} }
return score; return score;
} }
@ -2831,11 +2879,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
u32 i; u32 i;
u8 atkHpPercent = GetHealthPercentage(battlerAtk); u8 atkHpPercent = GetHealthPercentage(battlerAtk);
u8 defHpPercent = GetHealthPercentage(battlerDef); u8 defHpPercent = GetHealthPercentage(battlerDef);
// Targeting partner, check benefits of doing that instead // Targeting partner, check benefits of doing that instead
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
// check always hits // check always hits
if (!IS_MOVE_STATUS(move) && gBattleMoves[move].accuracy == 0) if (!IS_MOVE_STATUS(move) && gBattleMoves[move].accuracy == 0)
{ {
@ -2844,22 +2892,22 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (AI_RandLessThan(100) && (gBattleMons[battlerDef].statStages[STAT_EVASION] >= 8 || gBattleMons[battlerAtk].statStages[STAT_ACC] <= 4)) if (AI_RandLessThan(100) && (gBattleMons[battlerDef].statStages[STAT_EVASION] >= 8 || gBattleMons[battlerAtk].statStages[STAT_ACC] <= 4))
score++; score++;
} }
// check high crit // check high crit
if (TestMoveFlags(move, FLAG_HIGH_CRIT) && effectiveness >= AI_EFFECTIVENESS_x2 && AI_RandLessThan(128)) if (TestMoveFlags(move, FLAG_HIGH_CRIT) && effectiveness >= AI_EFFECTIVENESS_x2 && AI_RandLessThan(128))
score++; score++;
// check already dead // check already dead
if (!IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility) if (!IsBattlerIncapacitated(battlerDef, AI_DATA->defAbility)
&& CanTargetFaintAi(battlerAtk, battlerDef) && CanTargetFaintAi(battlerAtk, battlerDef)
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent should go first && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1) // opponent should go first
{ {
if (atkPriority > 0) if (atkPriority > 0)
score++; score++;
else else
score--; score--;
} }
// check damage // check damage
if (gBattleMoves[move].power != 0 && GetMoveDamageResult(move) == MOVE_POWER_WEAK) if (gBattleMoves[move].power != 0 && GetMoveDamageResult(move) == MOVE_POWER_WEAK)
score--; score--;
@ -2867,11 +2915,11 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// check status move preference // check status move preference
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_PREFER_STATUS_MOVES && IS_MOVE_STATUS(move) && effectiveness != AI_EFFECTIVENESS_x0) if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_PREFER_STATUS_MOVES && IS_MOVE_STATUS(move) && effectiveness != AI_EFFECTIVENESS_x0)
score++; score++;
// check thawing moves // check thawing moves
if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && TestMoveFlags(move, FLAG_THAW_USER)) if ((gBattleMons[battlerAtk].status1 & STATUS1_FREEZE) && TestMoveFlags(move, FLAG_THAW_USER))
score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10; score += (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) ? 20 : 10;
// check burn // check burn
if (gBattleMons[battlerAtk].status1 & STATUS1_BURN) if (gBattleMons[battlerAtk].status1 & STATUS1_BURN)
{ {
@ -2890,7 +2938,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} }
} }
// ability checks // ability checks
switch (AI_DATA->atkAbility) switch (AI_DATA->atkAbility)
{ {
@ -2917,12 +2965,12 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} }
break; break;
} // ability checks } // ability checks
// move effect checks // move effect checks
switch (moveEffect) switch (moveEffect)
{ {
case EFFECT_HIT: case EFFECT_HIT:
break; break;
case EFFECT_SLEEP: case EFFECT_SLEEP:
@ -2964,7 +3012,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} }
} }
if (!AI_RandLessThan(100)) if (!AI_RandLessThan(100))
{ {
score--; score--;
@ -3010,7 +3058,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
break; break;
} }
} }
if (!AI_RandLessThan(100)) if (!AI_RandLessThan(100))
{ {
score--; score--;
@ -3033,7 +3081,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 2; score -= 2;
else if (atkHpPercent <= 70) else if (atkHpPercent <= 70)
score -= 2; score -= 2;
else else
score++; score++;
break; break;
case EFFECT_EVASION_UP: case EFFECT_EVASION_UP:
@ -3163,7 +3211,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_ATTACK_SPATK_UP: // work up case EFFECT_ATTACK_SPATK_UP: // work up
if (GetHealthPercentage(battlerAtk) <= 40 || AI_DATA->atkAbility == ABILITY_CONTRARY) if (GetHealthPercentage(battlerAtk) <= 40 || AI_DATA->atkAbility == ABILITY_CONTRARY)
break; break;
if (HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL)) if (HasMoveWithSplit(battlerAtk, SPLIT_PHYSICAL))
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score);
else if (HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL)) else if (HasMoveWithSplit(battlerAtk, SPLIT_SPECIAL))
@ -3215,7 +3263,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default: default:
break; break;
} }
if (ShouldRecover(battlerAtk, battlerDef, move, healPercent)) if (ShouldRecover(battlerAtk, battlerDef, move, healPercent))
score += 2; score += 2;
} }
@ -3443,7 +3491,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (newHp > healthBenchmark && ShouldAbsorb(battlerAtk, battlerDef, move, AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex])) if (newHp > healthBenchmark && ShouldAbsorb(battlerAtk, battlerDef, move, AI_THINKING_STRUCT->simulatedDmg[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]))
score += 2; score += 2;
} }
break; break;
case EFFECT_SLEEP_TALK: case EFFECT_SLEEP_TALK:
case EFFECT_SNORE: case EFFECT_SNORE:
if (!IsWakeupTurn(battlerAtk) && gBattleMons[battlerAtk].status1 & STATUS1_SLEEP) if (!IsWakeupTurn(battlerAtk) && gBattleMons[battlerAtk].status1 & STATUS1_SLEEP)
@ -3478,13 +3526,13 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_THIEF: case EFFECT_THIEF:
{ {
bool32 canSteal = FALSE; bool32 canSteal = FALSE;
#if defined B_TRAINERS_KNOCK_OFF_ITEMS && B_TRAINERS_KNOCK_OFF_ITEMS == TRUE #if defined B_TRAINERS_KNOCK_OFF_ITEMS && B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
canSteal = TRUE; canSteal = TRUE;
#endif #endif
if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER || GetBattlerSide(battlerAtk) == B_SIDE_PLAYER)
canSteal = TRUE; canSteal = TRUE;
if (canSteal && AI_DATA->atkItem == ITEM_NONE if (canSteal && AI_DATA->atkItem == ITEM_NONE
&& AI_DATA->defItem != ITEM_NONE && AI_DATA->defItem != ITEM_NONE
&& CanBattlerGetOrLoseItem(battlerDef, AI_DATA->defItem) && CanBattlerGetOrLoseItem(battlerDef, AI_DATA->defItem)
@ -3628,8 +3676,8 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (AI_DATA->defAbility == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0) if (AI_DATA->defAbility == ABILITY_MAGIC_BOUNCE || CountUsablePartyMons(battlerDef) == 0)
break; break;
if (gDisableStructs[battlerAtk].isFirstTurn) if (gDisableStructs[battlerAtk].isFirstTurn)
score += 2; score += 2;
//TODO - track entire opponent party data to determine hazard effectiveness //TODO - track entire opponent party data to determine hazard effectiveness
break; break;
case EFFECT_FORESIGHT: case EFFECT_FORESIGHT:
if (AI_DATA->atkAbility == ABILITY_SCRAPPY) if (AI_DATA->atkAbility == ABILITY_SCRAPPY)
@ -3658,7 +3706,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (HasMoveEffect(battlerDef, EFFECT_MORNING_SUN) if (HasMoveEffect(battlerDef, EFFECT_MORNING_SUN)
|| HasMoveEffect(battlerDef, EFFECT_SYNTHESIS) || HasMoveEffect(battlerDef, EFFECT_SYNTHESIS)
|| HasMoveEffect(battlerDef, EFFECT_MOONLIGHT)) || HasMoveEffect(battlerDef, EFFECT_MOONLIGHT))
score += 2; score += 2;
} }
break; break;
case EFFECT_HAIL: case EFFECT_HAIL:
@ -3667,7 +3715,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if ((HasMoveEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_AURORA_VEIL)) if ((HasMoveEffect(battlerAtk, EFFECT_AURORA_VEIL) || HasMoveEffect(AI_DATA->battlerAtkPartner, EFFECT_AURORA_VEIL))
&& ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL)) && ShouldSetScreen(battlerAtk, battlerDef, EFFECT_AURORA_VEIL))
score += 3; score += 3;
score++; score++;
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_ICY_ROCK) if (AI_DATA->atkHoldEffect == HOLD_EFFECT_ICY_ROCK)
score++; score++;
@ -3726,7 +3774,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SPECTRAL_THIEF: case EFFECT_SPECTRAL_THIEF:
// Want to copy positive stat changes // Want to copy positive stat changes
for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++) for (i = STAT_ATK; i < NUM_BATTLE_STATS; i++)
{ {
if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i]) if (gBattleMons[battlerDef].statStages[i] > gBattleMons[battlerAtk].statStages[i])
{ {
switch (i) switch (i)
@ -3785,7 +3833,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (HasMoveEffect(battlerAtk, EFFECT_SWALLOW) if (HasMoveEffect(battlerAtk, EFFECT_SWALLOW)
|| HasMoveEffect(battlerAtk, EFFECT_SPIT_UP)) || HasMoveEffect(battlerAtk, EFFECT_SPIT_UP))
score += 2; score += 2;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_DEF, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_DEF, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score);
break; break;
@ -3802,20 +3850,20 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
|| HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP) || HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) || HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
score++; score++;
if (AI_DATA->defAbility == ABILITY_CONTRARY) if (AI_DATA->defAbility == ABILITY_CONTRARY)
score += 2; score += 2;
IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); IncreaseConfusionScore(battlerAtk, battlerDef, move, &score);
break; break;
case EFFECT_FLATTER: case EFFECT_FLATTER:
if (HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP) if (HasMoveEffect(battlerAtk, EFFECT_PSYCH_UP)
|| HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF)) || HasMoveEffect(battlerAtk, EFFECT_SPECTRAL_THIEF))
score += 2; score += 2;
if (AI_DATA->defAbility == ABILITY_CONTRARY) if (AI_DATA->defAbility == ABILITY_CONTRARY)
score += 2; score += 2;
IncreaseConfusionScore(battlerAtk, battlerDef, move, &score); IncreaseConfusionScore(battlerAtk, battlerDef, move, &score);
break; break;
case EFFECT_FURY_CUTTER: case EFFECT_FURY_CUTTER:
@ -3856,7 +3904,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score += 3; score += 3;
break; break;
} }
switch (move) switch (move)
{ {
case MOVE_DEFOG: case MOVE_DEFOG:
@ -3872,7 +3920,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
&& GetWhoStrikesFirst(battlerAtk, AI_DATA->battlerAtkPartner, TRUE) == 1) // Partner going first && GetWhoStrikesFirst(battlerAtk, AI_DATA->battlerAtkPartner, TRUE) == 1) // Partner going first
break; // Don't use Defog if partner is going to set up hazards break; // Don't use Defog if partner is going to set up hazards
} }
// check defog lowering evasion // check defog lowering evasion
if (ShouldLowerEvasion(battlerAtk, battlerDef, AI_DATA->defAbility)) if (ShouldLowerEvasion(battlerAtk, battlerDef, AI_DATA->defAbility))
{ {
@ -3912,7 +3960,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_CHARGE: case EFFECT_CHARGE:
if (HasDamagingMoveOfType(battlerAtk, TYPE_ELECTRIC)) if (HasDamagingMoveOfType(battlerAtk, TYPE_ELECTRIC))
score += 2; score += 2;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPDEF, &score);
break; break;
case EFFECT_TAUNT: case EFFECT_TAUNT:
@ -4081,7 +4129,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
if (AI_DATA->defAbility != AI_DATA->atkAbility && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID)) if (AI_DATA->defAbility != AI_DATA->atkAbility && !(gStatuses3[battlerDef] & STATUS3_GASTRO_ACID))
score += 2; score += 2;
} }
break; break;
case EFFECT_IMPRISON: case EFFECT_IMPRISON:
if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove)) if (predictedMove != MOVE_NONE && HasMove(battlerAtk, predictedMove))
@ -4152,7 +4200,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
case EFFECT_SHELL_SMASH: case EFFECT_SHELL_SMASH:
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_POWER_HERB) if (AI_DATA->atkHoldEffect == HOLD_EFFECT_POWER_HERB)
score += 3; score += 3;
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPEED, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPEED, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPATK, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_SPATK, &score);
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score); IncreaseStatUpScore(battlerAtk, battlerDef, STAT_ATK, &score);
@ -4256,7 +4304,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk)) if (gStatuses3[battlerAtk] & STATUS3_YAWN && IsBattlerGrounded(battlerAtk))
score += 10; score += 10;
//fallthrough //fallthrough
case EFFECT_GRASSY_TERRAIN: case EFFECT_GRASSY_TERRAIN:
case EFFECT_PSYCHIC_TERRAIN: case EFFECT_PSYCHIC_TERRAIN:
score += 2; score += 2;
if (AI_DATA->atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) if (AI_DATA->atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER)
@ -4529,7 +4577,7 @@ static s16 AI_CheckViability(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
//case EFFECT_SKY_DROP //case EFFECT_SKY_DROP
//break; //break;
} // move effect checks } // move effect checks
return score; return score;
} }
@ -4539,15 +4587,15 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (IsTargetingPartner(battlerAtk, battlerDef) if (IsTargetingPartner(battlerAtk, battlerDef)
|| gBattleResults.battleTurnCounter != 0) || gBattleResults.battleTurnCounter != 0)
return score; return score;
if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING if (AI_THINKING_STRUCT->aiFlags & AI_FLAG_SMART_SWITCHING
&& GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1 && GetWhoStrikesFirst(battlerAtk, battlerDef, TRUE) == 1
&& CanTargetFaintAi(battlerDef, battlerAtk) && CanTargetFaintAi(battlerDef, battlerAtk)
&& GetMovePriority(battlerAtk, move) == 0) && GetMovePriority(battlerAtk, move) == 0)
{ {
RETURN_SCORE_MINUS(20); // No point in setting up if you will faint. Should just switch if possible.. RETURN_SCORE_MINUS(20); // No point in setting up if you will faint. Should just switch if possible..
} }
// check effects to prioritize first turn // check effects to prioritize first turn
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
{ {
@ -4636,7 +4684,7 @@ static s16 AI_SetupFirstTurn(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default: default:
break; break;
} }
return score; return score;
} }
@ -4645,10 +4693,10 @@ static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
if (TestMoveFlags(move, FLAG_HIGH_CRIT)) if (TestMoveFlags(move, FLAG_HIGH_CRIT))
score += 2; score += 2;
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
{ {
case EFFECT_SLEEP: case EFFECT_SLEEP:
@ -4675,7 +4723,7 @@ static s16 AI_Risky(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
default: default:
break; break;
} }
return score; return score;
} }
@ -4684,10 +4732,10 @@ static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 sc
{ {
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
return score; return score;
if (GetMoveDamageResult(move) == MOVE_POWER_BEST) if (GetMoveDamageResult(move) == MOVE_POWER_BEST)
score += 2; score += 2;
return score; return score;
} }
@ -4695,14 +4743,14 @@ static s16 AI_PreferStrongestMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 sc
static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
u32 i; u32 i;
if (IsTargetingPartner(battlerAtk, battlerDef) if (IsTargetingPartner(battlerAtk, battlerDef)
|| CountUsablePartyMons(battlerAtk) == 0 || CountUsablePartyMons(battlerAtk) == 0
|| GetMoveDamageResult(move) != MOVE_POWER_OTHER || GetMoveDamageResult(move) != MOVE_POWER_OTHER
|| !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS) || !HasMoveEffect(battlerAtk, EFFECT_BATON_PASS)
|| IsBattlerTrapped(battlerAtk, TRUE)) || IsBattlerTrapped(battlerAtk, TRUE))
return score; return score;
if (IsStatRaisingEffect(gBattleMoves[move].effect)) if (IsStatRaisingEffect(gBattleMoves[move].effect))
{ {
if (gBattleResults.battleTurnCounter == 0) if (gBattleResults.battleTurnCounter == 0)
@ -4710,9 +4758,9 @@ static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
else if (GetHealthPercentage(battlerAtk) < 60) else if (GetHealthPercentage(battlerAtk) < 60)
score -= 10; score -= 10;
else else
score++; score++;
} }
// other specific checks // other specific checks
switch (gBattleMoves[move].effect) switch (gBattleMoves[move].effect)
{ {
@ -4738,12 +4786,12 @@ static s16 AI_PreferBatonPass(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING)) if (gStatuses3[battlerAtk] & (STATUS3_ROOTED | STATUS3_AQUA_RING))
score += 2; score += 2;
if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED) if (gStatuses3[battlerAtk] & STATUS3_LEECHSEED)
score -= 3; score -= 3;
break; break;
default: default:
break; break;
} }
return score; return score;
} }
@ -4751,7 +4799,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
u16 effect = gBattleMoves[move].effect; u16 effect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type; u8 moveType = gBattleMoves[move].type;
if (IsTargetingPartner(battlerAtk, battlerDef)) if (IsTargetingPartner(battlerAtk, battlerDef))
{ {
if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY) if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY)
@ -4761,7 +4809,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
if (CanTargetFaintAi(FOE(battlerAtk), AI_DATA->battlerAtkPartner) if (CanTargetFaintAi(FOE(battlerAtk), AI_DATA->battlerAtkPartner)
|| (CanTargetFaintAi(BATTLE_PARTNER(FOE(battlerAtk)), AI_DATA->battlerAtkPartner))) || (CanTargetFaintAi(BATTLE_PARTNER(FOE(battlerAtk)), AI_DATA->battlerAtkPartner)))
score--; score--;
if (GetHealthPercentage(battlerDef) <= 50) if (GetHealthPercentage(battlerDef) <= 50)
score++; score++;
} }
@ -4800,7 +4848,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// med hp // med hp
if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect)) if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect))
score -= 2; score -= 2;
switch (effect) switch (effect)
{ {
case EFFECT_EXPLOSION: case EFFECT_EXPLOSION:
@ -4823,7 +4871,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
// low hp // low hp
if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect)) if (IsStatRaisingEffect(effect) || IsStatLoweringEffect(effect))
score -= 2; score -= 2;
// check other discouraged low hp effects // check other discouraged low hp effects
switch (effect) switch (effect)
{ {
@ -4856,7 +4904,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
} }
} }
} }
// consider target HP // consider target HP
if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0)) if (CanAttackerFaintTarget(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex, 0))
{ {
@ -4928,7 +4976,7 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
score -= 2; // don't use status moves if target is at low health score -= 2; // don't use status moves if target is at low health
} }
} }
return score; return score;
} }
@ -4947,7 +4995,7 @@ static s16 AI_Roaming(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{ {
if (IsBattlerTrapped(battlerAtk, FALSE)) if (IsBattlerTrapped(battlerAtk, FALSE))
return score; return score;
AI_Flee(); AI_Flee();
return score; return score;
} }