diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d29becb2ea..fc2ac90b1d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1720,7 +1720,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (gBattleMons[battlerAtk].volatiles.dragonCheer || gBattleMons[battlerAtk].volatiles.focusEnergy) ADJUST_SCORE(-10); break; + case EFFECT_NON_VOLATILE_STATUS: + if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY + && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); + if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; case EFFECT_CONFUSE: + if (GetBattlerMoveTargetType(battlerAtk, move) & MOVE_TARGET_FOES_AND_ALLY + && PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); case EFFECT_SWAGGER: case EFFECT_FLATTER: if (!AI_CanConfuse(battlerAtk, battlerDef, aiData->abilities[battlerDef], BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) @@ -1853,7 +1863,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_STICKY_WEB: if (IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) ADJUST_SCORE(-10); - else if (PartnerMoveIsSameNoTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove) && IsHazardOnSide(GetBattlerSide(battlerDef), HAZARDS_STICKY_WEB)) + if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) ADJUST_SCORE(-10); // only one mon needs to set up Sticky Web break; case EFFECT_FORESIGHT: @@ -1881,7 +1891,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { ADJUST_SCORE(-10); //Both enemies are perish songed } - else if (DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) + else if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) { ADJUST_SCORE(-10); } @@ -2547,7 +2557,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { // This only happens if the ally already rolled on double trick room on final turn. // Both Pokemon use Trick Room on the final turn of Trick Room to anticipate both opponents Protecting to stall out. - if (gFieldTimers.trickRoomTimer == gBattleTurnCounter) + if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer == gBattleTurnCounter) ADJUST_SCORE(PERFECT_EFFECT); else ADJUST_SCORE(-10); @@ -2854,6 +2864,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); } break; + case EFFECT_COURT_CHANGE: + case EFFECT_TEATIME: + if (PartnerHasSameMoveEffectWithoutTarget(BATTLE_PARTNER(battlerAtk), move, aiData->partnerMove)) + ADJUST_SCORE(-10); + break; case EFFECT_PLACEHOLDER: return 0; // cannot even select } // move effect checks diff --git a/test/battle/ai/ai_doubles.c b/test/battle/ai/ai_doubles.c index e4ab8610ab..60dce82801 100644 --- a/test/battle/ai/ai_doubles.c +++ b/test/battle/ai/ai_doubles.c @@ -85,6 +85,59 @@ AI_DOUBLE_BATTLE_TEST("AI will not use a status move if partner already chose He } } +TO_DO_BATTLE_TEST("AI understands Instruct") + +TO_DO_BATTLE_TEST("AI understands Quick Guard") +TO_DO_BATTLE_TEST("AI understands Wide Guard") + +AI_DOUBLE_BATTLE_TEST("AI will not use the same nondamaging move as its partner for no reason") +{ + u32 move; + PARAMETRIZE { move = MOVE_AROMATHERAPY; } + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } + PARAMETRIZE { move = MOVE_FOLLOW_ME; } + PARAMETRIZE { move = MOVE_GRASSY_TERRAIN; } + PARAMETRIZE { move = MOVE_GRAVITY; } + PARAMETRIZE { move = MOVE_HAIL; } + PARAMETRIZE { move = MOVE_HEAL_BELL; } + PARAMETRIZE { move = MOVE_LIGHT_SCREEN; } + PARAMETRIZE { move = MOVE_LUCKY_CHANT; } + PARAMETRIZE { move = MOVE_MAGIC_ROOM; } + PARAMETRIZE { move = MOVE_MISTY_TERRAIN; } + PARAMETRIZE { move = MOVE_MUD_SPORT; } + PARAMETRIZE { move = MOVE_PSYCHIC_TERRAIN; } + PARAMETRIZE { move = MOVE_RAIN_DANCE; } + PARAMETRIZE { move = MOVE_REFLECT; } + PARAMETRIZE { move = MOVE_SAFEGUARD; } + PARAMETRIZE { move = MOVE_SANDSTORM; } + PARAMETRIZE { move = MOVE_SNOWSCAPE; } + PARAMETRIZE { move = MOVE_SPOTLIGHT; } + PARAMETRIZE { move = MOVE_STEALTH_ROCK; } + PARAMETRIZE { move = MOVE_SUNNY_DAY; } + PARAMETRIZE { move = MOVE_TAILWIND; } + PARAMETRIZE { move = MOVE_TEETER_DANCE; } + PARAMETRIZE { move = MOVE_TRICK_ROOM; } + PARAMETRIZE { move = MOVE_WATER_SPORT; } + PARAMETRIZE { move = MOVE_COURT_CHANGE; } + PARAMETRIZE { move = MOVE_PERISH_SONG; } + PARAMETRIZE { move = MOVE_STICKY_WEB; } + PARAMETRIZE { move = MOVE_TEATIME; } + PARAMETRIZE { move = MOVE_WONDER_ROOM; } + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_TACKLE); } + } WHEN { + TURN { EXPECT_MOVE(opponentLeft, move); EXPECT_MOVE(opponentRight, MOVE_TACKLE); } + } +} + AI_DOUBLE_BATTLE_TEST("AI will not choose Earthquake if it damages the partner without a positive effect") { ASSUME(GetMoveTarget(MOVE_EARTHQUAKE) == MOVE_TARGET_FOES_AND_ALLY);