AI Tests + accompanying bugfixes for Skill Swap, Worry Seed, weather setting in double battles, and Discharging into an ally's lightningrod (#7297)
This commit is contained in:
parent
4e558af76e
commit
424c127b8b
@ -39,9 +39,10 @@ enum AIScore
|
||||
DECENT_EFFECT = 2,
|
||||
GOOD_EFFECT = 3,
|
||||
BEST_EFFECT = 4,
|
||||
PERFECT_EFFECT = 10,
|
||||
BAD_EFFECT = -1,
|
||||
AWFUL_EFFECT = -3,
|
||||
WORST_EFFECT = -5
|
||||
WORST_EFFECT = -10
|
||||
};
|
||||
|
||||
// AI_TryToFaint
|
||||
|
||||
@ -5279,7 +5279,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData
|
||||
case ABILITY_POWER_SPOT:
|
||||
case ABILITY_VICTORY_STAR:
|
||||
if (IsDoubleBattle() && IsBattlerAlive(BATTLE_PARTNER(battler)) && aiData->abilities[BATTLE_PARTNER(battler)] != ability)
|
||||
return GOOD_EFFECT;
|
||||
return BEST_EFFECT;
|
||||
break;
|
||||
case ABILITY_GUTS:
|
||||
if (HasMoveWithCategory(battler, DAMAGE_CATEGORY_PHYSICAL) && gBattleMons[battler].status1 & (STATUS1_CAN_MOVE))
|
||||
@ -5295,7 +5295,7 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData
|
||||
case ABILITY_VITAL_SPIRIT:
|
||||
if (HasMoveWithEffect(battler, EFFECT_REST))
|
||||
return WORST_EFFECT;
|
||||
return NO_INCREASE;
|
||||
break;
|
||||
case ABILITY_INTIMIDATE:
|
||||
{
|
||||
u32 abilityDef = aiData->abilities[FOE(battler)];
|
||||
@ -5335,6 +5335,8 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData
|
||||
return WEAK_EFFECT;
|
||||
if (gBattleMons[battler].status1 & (STATUS1_TOXIC_POISON))
|
||||
return BEST_EFFECT;
|
||||
if (gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
return NO_INCREASE;
|
||||
break;
|
||||
// Also used to Simple Beam SIMPLE_BEAM.
|
||||
case ABILITY_SIMPLE:
|
||||
@ -5354,11 +5356,13 @@ s32 BattlerBenefitsFromAbilityScore(u32 battler, u32 ability, struct AiLogicData
|
||||
return NO_INCREASE;
|
||||
}
|
||||
return GOOD_EFFECT;
|
||||
case ABILITY_NONE:
|
||||
return NO_INCREASE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NO_INCREASE;
|
||||
return WEAK_EFFECT;
|
||||
}
|
||||
|
||||
u32 GetThinkingBattler(u32 battler)
|
||||
|
||||
@ -281,12 +281,22 @@ AI_SINGLE_BATTLE_TEST("AI uses Wide Guard against Earthquake when opponent would
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Worry Seed against Rest")
|
||||
{
|
||||
u32 move;
|
||||
u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT;
|
||||
|
||||
PARAMETRIZE { move = MOVE_REST; }
|
||||
PARAMETRIZE { move = MOVE_EXTREME_SPEED; }
|
||||
PARAMETRIZE { move = MOVE_REST; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; }
|
||||
PARAMETRIZE { move = MOVE_EXTREME_SPEED; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; }
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_ZUBAT) { Moves(MOVE_REST, MOVE_SLEEP_TALK, MOVE_AIR_CUTTER); }
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_PREDICT_MOVE);
|
||||
OPPONENT(SPECIES_BUDEW) { Moves(MOVE_WORRY_SEED, MOVE_SLUDGE_BOMB); }
|
||||
AI_FLAGS(aiFlags);
|
||||
PLAYER(SPECIES_ZIGZAGOON) { Moves(move, MOVE_SLEEP_TALK, MOVE_HEADBUTT); }
|
||||
OPPONENT(SPECIES_ZIGZAGOON) { Moves(MOVE_WORRY_SEED, MOVE_HEADBUTT); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_AIR_CUTTER); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); }
|
||||
if (move == MOVE_REST)
|
||||
TURN { MOVE(player, MOVE_HEADBUTT); EXPECT_MOVE(opponent, MOVE_WORRY_SEED); }
|
||||
else
|
||||
TURN { MOVE(player, MOVE_HEADBUTT); NOT_EXPECT_MOVE(opponent, MOVE_WORRY_SEED); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,4 +319,23 @@ AI_SINGLE_BATTLE_TEST("AI uses Simple Beam against Contrary Leaf Storm")
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Skill Swap against Poison Heal")
|
||||
{
|
||||
u8 status;
|
||||
u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT;
|
||||
PARAMETRIZE { status = STATUS1_POISON; }
|
||||
PARAMETRIZE { status = STATUS1_POISON; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; }
|
||||
PARAMETRIZE { status = STATUS1_TOXIC_POISON; }
|
||||
PARAMETRIZE { status = STATUS1_TOXIC_POISON; aiFlags |= AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION; }
|
||||
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_SHROOMISH) { Ability(ABILITY_POISON_HEAL); Status1(status); }
|
||||
AI_FLAGS(aiFlags);
|
||||
OPPONENT(SPECIES_SPINDA) { Moves(MOVE_SKILL_SWAP, MOVE_HEADBUTT); }
|
||||
} WHEN {
|
||||
if (status == STATUS1_TOXIC_POISON)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
else
|
||||
TURN { NOT_EXPECT_MOVE(opponent, MOVE_SKILL_SWAP); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -348,7 +348,7 @@ AI_DOUBLE_BATTLE_TEST("AI sees corresponding absorbing abilities on partners")
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI knows if redirection abilities provide immunity to allies")
|
||||
AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 4)")
|
||||
{
|
||||
KNOWN_FAILING;
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
@ -356,26 +356,44 @@ AI_DOUBLE_BATTLE_TEST("AI knows if redirection abilities provide immunity to all
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
|
||||
u32 ability, move, species, config;
|
||||
u32 ability, move, species;
|
||||
|
||||
PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; config = GEN_4; }
|
||||
PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; config = GEN_5; }
|
||||
PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; config = GEN_4; }
|
||||
PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; config = GEN_5; }
|
||||
PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; }
|
||||
PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, config);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
PLAYER(SPECIES_ZIGZAGOON);
|
||||
OPPONENT(SPECIES_SLAKING) { Moves(move, MOVE_SCRATCH); }
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_4);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_HEADBUTT); }
|
||||
OPPONENT(species) { HP(1); Ability(ability); Moves(MOVE_ROUND); }
|
||||
} WHEN {
|
||||
if (config == GEN_5)
|
||||
TURN { EXPECT_MOVE(opponentLeft, move); }
|
||||
else
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_SCRATCH); }
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_HEADBUTT); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI treats an ally's redirection ability appropriately (gen 5+)")
|
||||
{
|
||||
ASSUME(GetMoveTarget(MOVE_DISCHARGE) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_DISCHARGE) == TYPE_ELECTRIC);
|
||||
ASSUME(GetMoveTarget(MOVE_SURF) == MOVE_TARGET_FOES_AND_ALLY);
|
||||
ASSUME(GetMoveType(MOVE_SURF) == TYPE_WATER);
|
||||
|
||||
u32 ability, move, species;
|
||||
|
||||
PARAMETRIZE { species = SPECIES_SEAKING; ability = ABILITY_LIGHTNING_ROD; move = MOVE_DISCHARGE; }
|
||||
PARAMETRIZE { species = SPECIES_SHELLOS; ability = ABILITY_STORM_DRAIN; move = MOVE_SURF; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_HP_AWARE);
|
||||
WITH_CONFIG(B_REDIRECT_ABILITY_IMMUNITY, GEN_5);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_HEADBUTT); }
|
||||
OPPONENT(species) { HP(1); Ability(ability); Moves(MOVE_ROUND); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, move); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,6 +428,41 @@ AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons tha
|
||||
}
|
||||
}
|
||||
|
||||
// Sandstorm is omitted on purpose.
|
||||
// Tornadus is currently not willing to set up Sandstorm for its ally, but the actual purpose of this test is to demonstrate that Tornadus or Whimsicott will perform standard VGC openers.
|
||||
// Rain Dance, Sunny Day, and Snowscape are the actually important ones; setting up a good Sandstorm test + functionality is less important and will be done in later PRs.
|
||||
AI_DOUBLE_BATTLE_TEST("AI will set up weather for its ally")
|
||||
{
|
||||
u32 goodWeather, badWeather, weatherTrigger;
|
||||
u64 aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT;
|
||||
|
||||
PARAMETRIZE { goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; }
|
||||
PARAMETRIZE { goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; }
|
||||
PARAMETRIZE { goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; }
|
||||
PARAMETRIZE { goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; }
|
||||
// PARAMETRIZE { goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; }
|
||||
PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION;
|
||||
goodWeather = MOVE_SUNNY_DAY; badWeather = MOVE_RAIN_DANCE; weatherTrigger = MOVE_SOLAR_BEAM; }
|
||||
PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION;
|
||||
goodWeather = MOVE_RAIN_DANCE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_THUNDER; }
|
||||
PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION;
|
||||
goodWeather = MOVE_HAIL; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; }
|
||||
PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION;
|
||||
goodWeather = MOVE_SNOWSCAPE; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_BLIZZARD; }
|
||||
// PARAMETRIZE { aiFlags |= AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PP_STALL_PREVENTION;
|
||||
// goodWeather = MOVE_SANDSTORM; badWeather = MOVE_SUNNY_DAY; weatherTrigger = MOVE_SHORE_UP; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(aiFlags);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_TORNADUS) { Ability(ABILITY_PRANKSTER); Moves(goodWeather, badWeather, MOVE_RETURN, MOVE_TAUNT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(weatherTrigger, MOVE_EARTH_POWER); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, goodWeather); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room")
|
||||
{
|
||||
u32 move;
|
||||
@ -433,6 +486,7 @@ AI_DOUBLE_BATTLE_TEST("AI uses After You to set up Trick Room")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats")
|
||||
{
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user