Fixes AI repeated use of weather set up moves (#6963)

This commit is contained in:
Alex 2025-05-22 22:50:13 +02:00 committed by GitHub
parent 2e3ae0d167
commit f9400332fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 84 additions and 39 deletions

View File

@ -22,6 +22,14 @@ enum AIPivot
SHOULD_PIVOT,
};
enum WeatherState
{
WEATHER_INACTIVE,
WEATHER_ACTIVE,
WEATHER_ACTIVE_BUT_BLOCKED,
WEATHER_INACTIVE_AND_BLOCKED,
};
bool32 AI_IsFaster(u32 battlerAi, u32 battlerDef, u32 move);
bool32 AI_IsSlower(u32 battlerAi, u32 battlerDef, u32 move);
bool32 AI_RandLessThan(u32 val);
@ -58,6 +66,7 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId);
u32 AI_DecideHoldEffectForTurn(u32 battlerId);
bool32 DoesBattlerIgnoreAbilityChecks(u32 battlerAtk, u32 atkAbility, u32 move);
u32 AI_GetWeather(void);
enum WeatherState IsWeatherActive(u32 flags);
bool32 CanAIFaintTarget(u32 battlerAtk, u32 battlerDef, u32 numHits);
bool32 CanIndexMoveFaintTarget(u32 battlerAtk, u32 battlerDef, u32 index, u32 numHits);
bool32 HasDamagingMove(u32 battlerId);

View File

@ -5407,19 +5407,19 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SUNNY_DAY:
if (!(AI_GetWeather() & (B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY)))
if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE)
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_RAIN_DANCE:
if (!(AI_GetWeather() & (B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY)))
if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE)
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_HAIL:
if (!(AI_GetWeather() & (B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY)))
if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE)
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
break;
case EFFECT_SNOWSCAPE:
if (!(AI_GetWeather() & (B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY)))
if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) == WEATHER_INACTIVE)
ADJUST_SCORE(POWERFUL_STATUS_MOVE);
}

View File

@ -1418,6 +1418,26 @@ u32 AI_GetWeather(void)
return gBattleWeather;
}
enum WeatherState IsWeatherActive(u32 flags)
{
enum WeatherState state = WEATHER_INACTIVE;
if (gBattleWeather & flags)
state = WEATHER_ACTIVE;
else
state = WEATHER_INACTIVE;
if (!AI_WeatherHasEffect())
{
if (state == WEATHER_ACTIVE)
state = WEATHER_ACTIVE_BUT_BLOCKED;
else
state = WEATHER_INACTIVE_AND_BLOCKED;
}
return state;
}
bool32 IsAromaVeilProtectedEffect(u32 moveEffect)
{
switch (moveEffect)
@ -1619,19 +1639,18 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil
bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect)
{
u32 weather = AI_GetWeather();
if (weather & B_WEATHER_SANDSTORM)
if (IsWeatherActive(B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE)
return FALSE;
if (ability == ABILITY_SAND_VEIL
|| ability == ABILITY_SAND_RUSH
|| ability == ABILITY_SAND_FORCE
|| ability == ABILITY_OVERCOAT
|| ability == ABILITY_MAGIC_GUARD
|| holdEffect == HOLD_EFFECT_SAFETY_GOGGLES
|| IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)
|| HasMoveEffect(battler, EFFECT_SHORE_UP)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
|| ability == ABILITY_SAND_RUSH
|| ability == ABILITY_SAND_FORCE
|| ability == ABILITY_OVERCOAT
|| ability == ABILITY_MAGIC_GUARD
|| holdEffect == HOLD_EFFECT_SAFETY_GOGGLES
|| IS_BATTLER_ANY_TYPE(battler, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL)
|| HasMoveEffect(battler, EFFECT_SHORE_UP)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
{
return TRUE;
}
@ -1640,21 +1659,20 @@ bool32 ShouldSetSandstorm(u32 battler, u32 ability, u32 holdEffect)
bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect)
{
u32 weather = AI_GetWeather();
if (weather & (B_WEATHER_HAIL | B_WEATHER_SNOW))
if (IsWeatherActive(B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE)
return FALSE;
if (ability == ABILITY_SNOW_CLOAK
|| ability == ABILITY_ICE_BODY
|| ability == ABILITY_FORECAST
|| ability == ABILITY_SLUSH_RUSH
|| ability == ABILITY_MAGIC_GUARD
|| ability == ABILITY_OVERCOAT
|| holdEffect == HOLD_EFFECT_SAFETY_GOGGLES
|| IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|| HasMoveEffect(battler, EFFECT_BLIZZARD)
|| HasMoveEffect(battler, EFFECT_AURORA_VEIL)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
|| ability == ABILITY_ICE_BODY
|| ability == ABILITY_FORECAST
|| ability == ABILITY_SLUSH_RUSH
|| ability == ABILITY_MAGIC_GUARD
|| ability == ABILITY_OVERCOAT
|| holdEffect == HOLD_EFFECT_SAFETY_GOGGLES
|| IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|| HasMoveEffect(battler, EFFECT_BLIZZARD)
|| HasMoveEffect(battler, EFFECT_AURORA_VEIL)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
{
return TRUE;
}
@ -1663,8 +1681,7 @@ bool32 ShouldSetHail(u32 battler, u32 ability, u32 holdEffect)
bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, u32 holdEffect)
{
u32 weather = AI_GetWeather();
if (weather & B_WEATHER_RAIN)
if (IsWeatherActive(B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE)
return FALSE;
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
@ -1684,8 +1701,7 @@ bool32 ShouldSetRain(u32 battlerAtk, u32 atkAbility, u32 holdEffect)
bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect)
{
u32 weather = AI_GetWeather();
if (weather & B_WEATHER_SUN)
if (IsWeatherActive(B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE)
return FALSE;
if (holdEffect != HOLD_EFFECT_UTILITY_UMBRELLA
@ -1710,18 +1726,17 @@ bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect)
bool32 ShouldSetSnow(u32 battler, u32 ability, u32 holdEffect)
{
u32 weather = AI_GetWeather();
if (weather & (B_WEATHER_SNOW | B_WEATHER_HAIL))
if (IsWeatherActive(B_WEATHER_SNOW | B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY) != WEATHER_INACTIVE)
return FALSE;
if (ability == ABILITY_SNOW_CLOAK
|| ability == ABILITY_ICE_BODY
|| ability == ABILITY_FORECAST
|| ability == ABILITY_SLUSH_RUSH
|| IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|| HasMoveEffect(battler, EFFECT_BLIZZARD)
|| HasMoveEffect(battler, EFFECT_AURORA_VEIL)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
|| ability == ABILITY_ICE_BODY
|| ability == ABILITY_FORECAST
|| ability == ABILITY_SLUSH_RUSH
|| IS_BATTLER_OF_TYPE(battler, TYPE_ICE)
|| HasMoveEffect(battler, EFFECT_BLIZZARD)
|| HasMoveEffect(battler, EFFECT_AURORA_VEIL)
|| HasMoveEffect(battler, EFFECT_WEATHER_BALL))
{
return TRUE;
}

View File

@ -914,3 +914,24 @@ SINGLE_BATTLE_TEST("AI correctly records used moves")
EXPECT_EQ(BATTLE_HISTORY->usedMoves[B_POSITION_OPPONENT_LEFT][3], MOVE_EARTHQUAKE);
}
}
AI_SINGLE_BATTLE_TEST("AI will not set up Weather if it wont have any affect")
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CLOUD_NINE; }
PARAMETRIZE { ability = ABILITY_DAMP; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY);
PLAYER(SPECIES_GOLDUCK) { Ability(ability); Moves(MOVE_SCRATCH); }
OPPONENT(SPECIES_KABUTOPS) { Ability(ABILITY_SWIFT_SWIM); Moves(MOVE_RAIN_DANCE, MOVE_POUND); }
} WHEN {
if (ability == ABILITY_CLOUD_NINE)
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_POUND); }
else
TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_RAIN_DANCE); }
}
}