-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Fix AI's Switch In Battle
voloved edited this page Feb 1, 2023
·
4 revisions
by devolov
You may notice that battle_ai_switch_items.c
has this comment:
/* Possible bug: this comparison gives the type that takes the most damage, when
a "good" AI would want to select the type that takes the least damage. Unknown if this
is a legitimate mistake or if it's an intentional, if weird, design choice */
Let's get rid of that possible bug.
- Check for worst type Pokémon. So prioritize Charmander over Bulbasaur if the opponent has a Squirtle out.
- See if it has a super effective move
- If not, then remove it from the options.
- repeat 1-3.
- If none have a super effective move, then use the one with the most damaging attack.
There are a few issues I see with this. The largest is Check for worst type Pokémon
. Obviously, we'd like to prioritize sending out the best typing.
The change below makes it so we check if Pokemon that have super effective typing have a super-effective move first.
@@ -688,9 +691,12 @@ u8 GetMostSuitableMonToSwitchInto(void)
invalidMons = 0;
while (invalidMons != 0x3F) // All mons are invalid.
{
+#ifdef BUGFIX
+ bestDmg = 255;
+#else
bestDmg = TYPE_MUL_NO_EFFECT;
+#endif
bestMonId = PARTY_SIZE;
// Find the mon whose type is the most suitable offensively.
for (i = firstId; i < lastId; i++)
{
@@ -711,9 +717,10 @@ u8 GetMostSuitableMonToSwitchInto(void)
/* Possible bug: this comparison gives the type that takes the most damage, when
a "good" AI would want to select the type that takes the least damage. Unknown if this
is a legitimate mistake or if it's an intentional, if weird, design choice */
+#ifdef BUGFIX
+ if (bestDmg > typeDmg)
+#else
if (bestDmg < typeDmg)
+#endif
{
bestDmg = typeDmg;
bestMonId = i;
This is not as crucial, but we'd still like to prioritize a super effective typing regardless of strongest move. If we have a Squirtle out and faint the AI's Pokemon, it'd make sense for them to send out a Bulbasaur with no super-strong moves than a Charmander or Porygon with a stronger move.
// this file's functions
@@ -641,8 +642,10 @@ u8 GetMostSuitableMonToSwitchInto(void)
struct Pokemon *party;
s32 i, j;
u8 invalidMons;
u16 move;
+ bool8 checkedAllMonForSEMoves = FALSE; // We have checked all Pokemon in the party for if they have a super effective move
if (*(gBattleStruct->monToSwitchIntoId + gActiveBattler) != PARTY_SIZE)
return *(gBattleStruct->monToSwitchIntoId + gActiveBattler);
if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
@@ -733,12 +740,17 @@ u8 GetMostSuitableMonToSwitchInto(void)
if (move != MOVE_NONE && TypeCalc(move, gActiveBattler, opposingBattler) & MOVE_RESULT_SUPER_EFFECTIVE)
break;
}
- if (i != MAX_MON_MOVES)
+ if (i != MAX_MON_MOVES || (checkedAllMonForSEMoves && bestDmg <= TYPE_MUL_NOT_EFFECTIVE))
return bestMonId; // Has both the typing and at least one super effective move.
invalidMons |= gBitTable[bestMonId]; // Sorry buddy, we want something better.
+ if (invalidMons == 0x3F && !checkedAllMonForSEMoves) // If we already checked all for a super effective move, then use the one with the best typing
+ {
+ invalidMons = 0;
+ checkedAllMonForSEMoves = TRUE;
+ }
}
else
{
invalidMons = 0x3F; // No viable mon to switch.
-1. Check for worst type pokemon.
+1. Check for best type pokemon.
2. See if it has a super effective move
3. If not, then remove it from the options.
4. repeat 1-3.
+5. if none have a super effective move, then flag that no pokemon have a super effective move and find the best type pokemon again.
+6 If it's typing is super effective or better, then send it out.
-5. If none have a super effective move, then use the one with the most damaging attack.
+7. If none have a super effective type, then use the one with the most damaging attack.