diff --git a/include/random.h b/include/random.h index d15aa28bfb..37649cedf5 100644 --- a/include/random.h +++ b/include/random.h @@ -188,6 +188,7 @@ enum RandomTag RNG_QUICK_CLAW, RNG_TRACE, RNG_FICKLE_BEAM, + RNG_AI_ABILITY, }; #define RandomWeighted(tag, ...) \ diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index f8275d417a..27215563b9 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1084,6 +1084,8 @@ bool32 AI_IsAbilityOnSide(u32 battlerId, u32 ability) // does NOT include ability suppression checks s32 AI_DecideKnownAbilityForTurn(u32 battlerId) { + u32 validAbilities[NUM_ABILITY_SLOTS]; + u8 i, numValidAbilities = 0; u32 knownAbility = GetBattlerAbility(battlerId); // We've had ability overwritten by e.g. Worry Seed. It is not part of AI_PARTY in case of switching @@ -1105,18 +1107,15 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId) if (knownAbility == ABILITY_SHADOW_TAG || knownAbility == ABILITY_MAGNET_PULL || knownAbility == ABILITY_ARENA_TRAP) return knownAbility; - // Else, guess the ability - if (gSpeciesInfo[gBattleMons[battlerId].species].abilities[0] != ABILITY_NONE) + for (i = 0; i < NUM_ABILITY_SLOTS; i++) { - u32 abilityGuess = ABILITY_NONE; - while (abilityGuess == ABILITY_NONE) - { - abilityGuess = gSpeciesInfo[gBattleMons[battlerId].species].abilities[Random() % NUM_ABILITY_SLOTS]; - } - - return abilityGuess; + if (gSpeciesInfo[gBattleMons[battlerId].species].abilities[i] != ABILITY_NONE) + validAbilities[numValidAbilities++] = gSpeciesInfo[gBattleMons[battlerId].species].abilities[i]; } + if (numValidAbilities > 0) + return validAbilities[RandomUniform(RNG_AI_ABILITY, 0, numValidAbilities - 1)]; + return ABILITY_NONE; // Unknown. } diff --git a/test/battle/ai.c b/test/battle/ai.c index 819eb2edaa..59acdf966c 100644 --- a/test/battle/ai.c +++ b/test/battle/ai.c @@ -819,8 +819,9 @@ AI_SINGLE_BATTLE_TEST("AI will not choose Burn Up if the user lost the Fire typi } } -AI_SINGLE_BATTLE_TEST("AI will choose Surf over Thunderbolt and Ice Beam if the opposing mon has Volt Absorb") +AI_SINGLE_BATTLE_TEST("AI will only choose Surf 1/3 times if the opposing mon has Volt Absorb") { + PASSES_RANDOMLY(1, 3, RNG_AI_ABILITY); GIVEN { ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); @@ -828,6 +829,27 @@ AI_SINGLE_BATTLE_TEST("AI will choose Surf over Thunderbolt and Ice Beam if the OPPONENT(SPECIES_LANTURN) { Moves(MOVE_THUNDERBOLT, MOVE_ICE_BEAM, MOVE_SURF); } } WHEN { TURN { EXPECT_MOVE(opponent, MOVE_SURF); } + TURN { EXPECT_MOVE(opponent, MOVE_SURF); } + } SCENE { + MESSAGE("Foe Lanturn used Surf!"); + MESSAGE("Foe Lanturn used Surf!"); + } +} + +AI_SINGLE_BATTLE_TEST("AI will choose Thunderbolt then Surf 2/3 times if the opposing mon has Volt Absorb") +{ + PASSES_RANDOMLY(2, 3, RNG_AI_ABILITY); + GIVEN { + ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); }; + OPPONENT(SPECIES_LANTURN) { Moves(MOVE_THUNDERBOLT, MOVE_ICE_BEAM, MOVE_SURF); } + } WHEN { + TURN { EXPECT_MOVE(opponent, MOVE_THUNDERBOLT); } + TURN { EXPECT_MOVE(opponent, MOVE_SURF); } + } SCENE { + MESSAGE("Foe Lanturn used Thunderbolt!"); + MESSAGE("Foe Lanturn used Surf!"); } }