Respect beneficial status in healing moves and add tests (#8478)
This commit is contained in:
parent
aa172aad6c
commit
04b26b752e
@ -2079,7 +2079,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_REFRESH:
|
||||
if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE))
|
||||
if (!(gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)
|
||||
|| !ShouldCureStatus(battlerAtk, battlerAtk, aiData))
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_PSYCHO_SHIFT:
|
||||
@ -2904,12 +2905,17 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
case EFFECT_JUNGLE_HEALING:
|
||||
if (AI_BattlerAtMaxHp(battlerAtk)
|
||||
&& AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk))
|
||||
&& !(gBattleMons[battlerAtk].status1 & STATUS1_ANY)
|
||||
&& !(gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY))
|
||||
{
|
||||
bool32 canCureSelf = (gBattleMons[battlerAtk].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, battlerAtk, aiData);
|
||||
bool32 canCurePartner = (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, BATTLE_PARTNER(battlerAtk), aiData);
|
||||
|
||||
if (AI_BattlerAtMaxHp(battlerAtk)
|
||||
&& AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk))
|
||||
&& !canCureSelf
|
||||
&& !canCurePartner)
|
||||
ADJUST_SCORE(-10);
|
||||
break;
|
||||
}
|
||||
case EFFECT_TAKE_HEART:
|
||||
if ((!(gBattleMons[battlerAtk].status1 & STATUS1_ANY)
|
||||
|| PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_JUNGLE_HEALING)
|
||||
@ -5100,7 +5106,8 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
break;
|
||||
case EFFECT_REFRESH:
|
||||
if (gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)
|
||||
if ((gBattleMons[battlerAtk].status1 & STATUS1_CAN_MOVE)
|
||||
&& ShouldCureStatus(battlerAtk, battlerAtk, aiData))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
break;
|
||||
case EFFECT_TAKE_HEART:
|
||||
@ -5558,12 +5565,17 @@ static s32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move, stru
|
||||
//case EFFECT_SKY_DROP
|
||||
//break;
|
||||
case EFFECT_JUNGLE_HEALING:
|
||||
{
|
||||
bool32 canCureSelf = (gBattleMons[battlerAtk].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, battlerAtk, aiData);
|
||||
bool32 canCurePartner = (gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY) && ShouldCureStatus(battlerAtk, BATTLE_PARTNER(battlerAtk), aiData);
|
||||
|
||||
if (ShouldRecover(battlerAtk, battlerDef, move, 25)
|
||||
|| ShouldRecover(BATTLE_PARTNER(battlerAtk), battlerDef, move, 25)
|
||||
|| gBattleMons[battlerAtk].status1 & STATUS1_ANY
|
||||
|| gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY)
|
||||
|| canCureSelf
|
||||
|| canCurePartner)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
break;
|
||||
}
|
||||
case EFFECT_RAPID_SPIN:
|
||||
if ((AreAnyHazardsOnSide(GetBattlerSide(battlerAtk)) && CountUsablePartyMons(battlerAtk) != 0)
|
||||
|| (gBattleMons[battlerAtk].volatiles.leechSeed || gBattleMons[battlerAtk].volatiles.wrapped))
|
||||
|
||||
@ -3839,6 +3839,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
{
|
||||
struct Pokemon *party;
|
||||
u32 i, battlerOnField1, battlerOnField2;
|
||||
bool32 hasStatusToCure = FALSE;
|
||||
|
||||
party = GetBattlerParty(battlerId);
|
||||
|
||||
@ -3850,8 +3851,9 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| gAiLogicData->abilities[BATTLE_PARTNER(battlerId)] != ABILITY_SOUNDPROOF
|
||||
|| !checkSoundproof)
|
||||
&& GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE)
|
||||
return TRUE;
|
||||
&& GetMonData(&party[battlerOnField2], MON_DATA_STATUS) != STATUS1_NONE
|
||||
&& ShouldCureStatus(battlerId, BATTLE_PARTNER(battlerId), gAiLogicData))
|
||||
hasStatusToCure = TRUE;
|
||||
}
|
||||
else // In singles there's only one battlerId by side.
|
||||
{
|
||||
@ -3863,8 +3865,9 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
if ((GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) == GEN_5
|
||||
|| GetConfig(CONFIG_HEAL_BELL_SOUNDPROOF) >= GEN_8
|
||||
|| gAiLogicData->abilities[battlerId] != ABILITY_SOUNDPROOF || !checkSoundproof)
|
||||
&& GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE)
|
||||
return TRUE;
|
||||
&& GetMonData(&party[battlerOnField1], MON_DATA_STATUS) != STATUS1_NONE
|
||||
&& ShouldCureStatus(battlerId, battlerId, gAiLogicData))
|
||||
hasStatusToCure = TRUE;
|
||||
|
||||
// Check inactive party mons' status
|
||||
for (i = 0; i < PARTY_SIZE; i++)
|
||||
@ -3879,7 +3882,7 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return hasStatusToCure;
|
||||
}
|
||||
|
||||
bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex)
|
||||
|
||||
@ -232,6 +232,29 @@ AI_DOUBLE_BATTLE_TEST("AI chooses moves that cure self or partner")
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Refresh only when curing status is worthwhile")
|
||||
{
|
||||
u32 status1;
|
||||
enum Ability ability;
|
||||
u32 expectedMove;
|
||||
|
||||
PARAMETRIZE { status1 = STATUS1_BURN; ability = ABILITY_GUTS; expectedMove = MOVE_ROCK_SLIDE; }
|
||||
PARAMETRIZE { status1 = STATUS1_BURN; ability = ABILITY_PRESSURE; expectedMove = MOVE_REFRESH; }
|
||||
PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; ability = ABILITY_POISON_HEAL; expectedMove = MOVE_ROCK_SLIDE; }
|
||||
PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; ability = ABILITY_SCRAPPY; expectedMove = MOVE_REFRESH; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_REFRESH) == EFFECT_REFRESH);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_REGIROCK) { Moves(MOVE_ROCK_SLIDE, MOVE_REFRESH); Status1(status1); Ability(ability); }
|
||||
OPPONENT(SPECIES_EXPLOUD) { Moves(MOVE_CELEBRATE); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, expectedMove); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members")
|
||||
{
|
||||
u32 status, config;
|
||||
|
||||
@ -139,6 +139,32 @@ AI_DOUBLE_BATTLE_TEST("AI won't use the same nondamaging move as its partner for
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("Heal Bell and Jungle Healing skip curing a partner that benefits from burn")
|
||||
{
|
||||
u32 move;
|
||||
|
||||
PARAMETRIZE { move = MOVE_HEAL_BELL; }
|
||||
PARAMETRIZE { move = MOVE_JUNGLE_HEALING; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_HEAL_BELL) == EFFECT_HEAL_BELL);
|
||||
ASSUME(GetMoveEffect(MOVE_JUNGLE_HEALING) == EFFECT_JUNGLE_HEALING);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_MEMENTO); Speed(1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_MEMENTO); Speed(1); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Moves(move, MOVE_SCRATCH); Speed(20); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_GUTS); Moves(MOVE_TACKLE); Status1(STATUS1_BURN); MaxHP(200); HP(200); Speed(10); }
|
||||
} WHEN {
|
||||
TURN {
|
||||
NOT_EXPECT_MOVE(opponentLeft, move);
|
||||
EXPECT_MOVE(opponentLeft, MOVE_SCRATCH, target: playerLeft);
|
||||
EXPECT_MOVE(opponentRight, MOVE_TACKLE, target: playerLeft);
|
||||
MOVE(playerLeft, MOVE_MEMENTO);
|
||||
MOVE(playerRight, MOVE_MEMENTO);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user