Fix abusable two-turn-move switch behaviour (#7770)

This commit is contained in:
Pawkkie 2025-09-22 13:47:23 -04:00 committed by GitHub
parent 780867611e
commit 1ca5b23f19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 8 additions and 7 deletions

View File

@ -15,7 +15,7 @@
#define SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE 100
#define SHOULD_SWITCH_ABSORBS_HIDDEN_POWER_PERCENTAGE 50
#define SHOULD_SWITCH_TRAPPER_PERCENTAGE 100
#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 100
#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 50
#define STAY_IN_ABSORBING_PERCENTAGE 66 // Chance to stay in if outgoing mon has super effective move against player, will prevent switching out for an absorber with this likelihood
#define SHOULD_SWITCH_HASBADODDS_PERCENTAGE 50
#define SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE 100

View File

@ -621,6 +621,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler)
if (IsDoubleBattle() || !(gAiThinkingStruct->aiFlags[battler] & AI_FLAG_SMART_SWITCHING))
return FALSE;
// In a world with a unified ShouldSwitch function, also want to check whether we already win 1v1 and if we do don't switch; not worth doubling the HasBadOdds computation for now
if (isOpposingBattlerChargingOrInvulnerable && gAiLogicData->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN)))
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
@ -658,7 +659,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler)
if (CanAbilityTrapOpponent(monAbility, opposingBattler) || (CanAbilityTrapOpponent(gAiLogicData->abilities[opposingBattler], opposingBattler) && monAbility == ABILITY_TRACE))
{
// If mon in slot i is the most suitable switchin candidate, then it's a trapper than wins 1v1
if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN)))
if (i == gAiLogicData->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_TRAPPER, GetSwitchChance(SHOULD_SWITCH_TRAPPER)))
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
}
}

View File

@ -748,15 +748,15 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
}
}
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is semi-invulnerable and it has an absorber")
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is semi-invulnerable and it has a good switchin")
{
PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN);
GIVEN {
ASSUME(GetMoveType(MOVE_DIVE) == TYPE_WATER);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
PLAYER(SPECIES_LUVDISC) { Moves(MOVE_DIVE); }
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);
PLAYER(SPECIES_LUVDISC) { Level(1); Moves(MOVE_DIVE); }
OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_MANTINE) { Moves(MOVE_SCRATCH); Ability(ABILITY_WATER_ABSORB); }
OPPONENT(SPECIES_PIKACHU) { Moves(MOVE_THUNDERBOLT); }
} WHEN {
TURN { MOVE(player, MOVE_DIVE) ; EXPECT_MOVE(opponent, MOVE_SCRATCH); }
TURN { SKIP_TURN(player); EXPECT_SWITCH(opponent, 1); }
@ -810,7 +810,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is charging and it has a good switchin immunity (ability)")
{
PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN);
PASSES_RANDOMLY(SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE, 100, RNG_AI_SWITCH_ABSORBING);
GIVEN {
ASSUME(GetMoveType(MOVE_DIG) == TYPE_GROUND);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);