Fix bad odds / defensive switchin double switch cases (#6927)
This commit is contained in:
parent
de463af0df
commit
99073dc9f2
@ -180,6 +180,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
bool32 getsOneShot = FALSE, hasStatusMove = FALSE, hasSuperEffectiveMove = FALSE;
|
||||
u16 typeEffectiveness = UQ_4_12(1.0); //baseline typing damage
|
||||
enum BattleMoveEffects aiMoveEffect;
|
||||
u32 hitsToKoPlayer = 0, hitsToKoAI = 0;
|
||||
|
||||
// Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer
|
||||
if (!(gAiThinkingStruct->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
|
||||
@ -238,6 +239,8 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
}
|
||||
}
|
||||
|
||||
hitsToKoPlayer = GetNoOfHitsToKOBattlerDmg(maxDamageDealt, opposingBattler);
|
||||
|
||||
// Calculate type advantage
|
||||
typeEffectiveness = uq4_12_multiply(typeEffectiveness, (GetTypeModifier(atkType1, defType1)));
|
||||
if (atkType2 != atkType1)
|
||||
@ -266,6 +269,8 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
}
|
||||
}
|
||||
|
||||
hitsToKoAI = GetNoOfHitsToKOBattlerDmg(maxDamageTaken, battler);
|
||||
|
||||
// Check if mon gets one shot
|
||||
if(maxDamageTaken > gBattleMons[battler].hp
|
||||
&& !(gItemsInfo[gBattleMons[battler].item].holdEffect == HOLD_EFFECT_FOCUS_SASH || (!IsMoldBreakerTypeAbility(opposingBattler, gBattleMons[opposingBattler].ability) && B_STURDY >= GEN_5 && aiAbility == ABILITY_STURDY)))
|
||||
@ -273,12 +278,9 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
getsOneShot = TRUE;
|
||||
}
|
||||
|
||||
// Check if current mon can outspeed and KO in spite of bad matchup, and don't switch out if it can
|
||||
if(damageDealt > gBattleMons[opposingBattler].hp)
|
||||
{
|
||||
if (AI_IsFaster(battler, opposingBattler, aiBestMove))
|
||||
return FALSE;
|
||||
}
|
||||
// Check if current mon can 1v1 in spite of bad matchup, and don't switch out if it can
|
||||
if(hitsToKoPlayer < hitsToKoAI || (hitsToKoPlayer == hitsToKoAI && AI_IsFaster(battler, opposingBattler, aiBestMove)))
|
||||
return FALSE;
|
||||
|
||||
// If we don't have any other viable options, don't switch out
|
||||
if (gAiLogicData->mostSuitableMonId[battler] == PARTY_SIZE)
|
||||
@ -2063,14 +2065,6 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
hitsToKOAI = GetSwitchinHitsToKO(GetMaxDamagePlayerCouldDealToSwitchin(battler, opposingBattler, gAiLogicData->switchinCandidate.battleMon), battler);
|
||||
typeMatchup = GetSwitchinTypeMatchup(opposingBattler, gAiLogicData->switchinCandidate.battleMon);
|
||||
|
||||
// Track max hits to KO and set defensive mon
|
||||
if(hitsToKOAI > maxHitsToKO)
|
||||
{
|
||||
maxHitsToKO = hitsToKOAI;
|
||||
if(maxHitsToKO > defensiveMonHitKOThreshold)
|
||||
defensiveMonId = i;
|
||||
}
|
||||
|
||||
// Check through current mon's moves
|
||||
for (j = 0; j < MAX_MON_MOVES; j++)
|
||||
{
|
||||
@ -2100,6 +2094,14 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId,
|
||||
}
|
||||
}
|
||||
|
||||
// Track max hits to KO and set defensive mon
|
||||
if(hitsToKOAI > maxHitsToKO && (canSwitchinWin1v1 || gAiThinkingStruct->aiFlags[battler] & AI_FLAG_STALL))
|
||||
{
|
||||
maxHitsToKO = hitsToKOAI;
|
||||
if(maxHitsToKO > defensiveMonHitKOThreshold)
|
||||
defensiveMonId = i;
|
||||
}
|
||||
|
||||
// Check for mon with resistance and super effective move for best type matchup mon with effective move
|
||||
if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove))
|
||||
{
|
||||
|
||||
@ -296,7 +296,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: Mid-battle switches prioritize
|
||||
|
||||
PARAMETRIZE { expectedIndex = 3; move1 = MOVE_SCRATCH; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = 0; } // When not smart, AI will only switch in a defensive mon if it has a SE move, otherwise will just default to damage
|
||||
PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = 0; }
|
||||
PARAMETRIZE { expectedIndex = 2; move1 = MOVE_SCRATCH; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } // When smart, AI will prioritize SE move, but still switch in good type matchup without SE move
|
||||
PARAMETRIZE { expectedIndex = 2; move1 = MOVE_SCRATCH; move2 = MOVE_WATER_PULSE; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; } // When smart, AI will prioritize SE move, but still switch in good type matchup without SE move
|
||||
PARAMETRIZE { expectedIndex = 1; move1 = MOVE_GIGA_DRAIN; move2 = MOVE_SCRATCH; aiSmartSwitchFlags = AI_FLAG_SMART_MON_CHOICES; }
|
||||
|
||||
GIVEN {
|
||||
@ -1180,3 +1180,62 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will use pivot move to activate Palafin's Z
|
||||
TURN { MOVE(player, MOVE_CELEBRATE); EXPECT_MOVE(opponent, MOVE_FLIP_TURN); EXPECT_SEND_OUT(opponent, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI won't send out defensive mon that can lose 1v1, or switch out a mon that can win 1v1 even with bad type matchup")
|
||||
{
|
||||
PASSES_RANDOMLY(100, 100, RNG_AI_SWITCH_HASBADODDS);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_PANPOUR) {
|
||||
Level(15);
|
||||
Moves(MOVE_WATER_PULSE, MOVE_PLAY_NICE, MOVE_FURY_SWIPES, MOVE_LICK);
|
||||
Item(ITEM_MYSTIC_WATER);
|
||||
Ability(ABILITY_GLUTTONY);
|
||||
Nature(NATURE_MODEST);
|
||||
HPIV(31);
|
||||
AttackIV(31);
|
||||
DefenseIV(31);
|
||||
SpAttackIV(31);
|
||||
SpDefenseIV(31);
|
||||
SpeedIV(31); }
|
||||
OPPONENT(SPECIES_RHYHORN) {
|
||||
Level(14);
|
||||
Moves(MOVE_ROCK_TOMB, MOVE_HORN_ATTACK, MOVE_BULLDOZE, MOVE_ROCK_SMASH);
|
||||
Item(ITEM_RINDO_BERRY);
|
||||
Ability(ABILITY_LIGHTNING_ROD);
|
||||
Nature(NATURE_ADAMANT);
|
||||
HPIV(31);
|
||||
AttackIV(31);
|
||||
DefenseIV(31);
|
||||
SpAttackIV(31);
|
||||
SpDefenseIV(31);
|
||||
SpeedIV(31); }
|
||||
OPPONENT(SPECIES_GLIGAR) {
|
||||
Level(15);
|
||||
Moves(MOVE_WING_ATTACK, MOVE_QUICK_ATTACK, MOVE_BULLDOZE);
|
||||
Item(ITEM_ORAN_BERRY);
|
||||
Ability(ABILITY_SAND_VEIL);
|
||||
Nature(NATURE_ADAMANT);
|
||||
HPIV(31);
|
||||
AttackIV(31);
|
||||
DefenseIV(31);
|
||||
SpAttackIV(31);
|
||||
SpDefenseIV(31);
|
||||
SpeedIV(31); }
|
||||
OPPONENT(SPECIES_WOOPER_PALDEA) {
|
||||
Level(15);
|
||||
Moves(MOVE_MUD_SHOT, MOVE_ACID_SPRAY, MOVE_YAWN, MOVE_SANDSTORM);
|
||||
Item(ITEM_ORAN_BERRY);
|
||||
Ability(ABILITY_WATER_ABSORB);
|
||||
Nature(NATURE_MODEST);
|
||||
HPIV(31);
|
||||
AttackIV(31);
|
||||
DefenseIV(31);
|
||||
SpAttackIV(31);
|
||||
SpDefenseIV(31);
|
||||
SpeedIV(31); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_WATER_PULSE); EXPECT_MOVE(opponent, MOVE_BULLDOZE); EXPECT_SEND_OUT(opponent, 1); }
|
||||
TURN { MOVE(player, MOVE_WATER_PULSE); EXPECT_MOVE(opponent, MOVE_BULLDOZE); }
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user