Improve AI's Skill Swap handling in double battles (#5360)
* Improve AI contrary * Update src/battle_ai_util.c Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Fix additionalEffects loop * moves[i] to aiMove * Update src/battle_ai_util.c Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com>
This commit is contained in:
parent
b478881fc6
commit
047289a639
4 changed files with 80 additions and 4 deletions
|
@ -114,6 +114,7 @@ bool32 HasMoveEffectANDArg(u32 battlerId, u32 effect, u32 argument);
|
|||
bool32 HasMoveWithAdditionalEffect(u32 battlerId, u32 moveEffect);
|
||||
bool32 HasMoveWithCriticalHitChance(u32 battlerId);
|
||||
bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception);
|
||||
bool32 HasMoveThatLowersOwnStats(u32 battlerId);
|
||||
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect);
|
||||
bool32 HasAnyKnownMove(u32 battlerId);
|
||||
bool32 IsAromaVeilProtectedMove(u32 move);
|
||||
|
@ -138,6 +139,7 @@ bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move);
|
|||
bool32 HasThawingMove(u32 battler);
|
||||
bool32 IsStatRaisingEffect(u32 effect);
|
||||
bool32 IsStatLoweringEffect(u32 effect);
|
||||
bool32 IsSelfStatLoweringEffect(u32 effect);
|
||||
bool32 IsAttackBoostMoveEffect(u32 effect);
|
||||
bool32 IsUngroundingEffect(u32 effect);
|
||||
bool32 IsSemiInvulnerable(u32 battlerDef, u32 move);
|
||||
|
|
|
@ -3049,15 +3049,26 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
|
|||
case EFFECT_SKILL_SWAP:
|
||||
if (aiData->abilities[battlerAtk] != aiData->abilities[BATTLE_PARTNER(battlerAtk)] && !attackerHasBadAbility)
|
||||
{
|
||||
// Partner abilities
|
||||
if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_TRUANT)
|
||||
{
|
||||
RETURN_SCORE_PLUS(10);
|
||||
ADJUST_SCORE(10);
|
||||
}
|
||||
else if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES
|
||||
&& HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)]))
|
||||
else if (aiData->abilities[BATTLE_PARTNER(battlerAtk)] == ABILITY_INTIMIDATE)
|
||||
{
|
||||
RETURN_SCORE_PLUS(3);
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
}
|
||||
// Active mon abilities
|
||||
if (aiData->abilities[battlerAtk] == ABILITY_COMPOUND_EYES
|
||||
&& HasMoveWithLowAccuracy(battlerAtkPartner, FOE(battlerAtkPartner), 90, TRUE, atkPartnerAbility, aiData->abilities[FOE(battlerAtkPartner)], atkPartnerHoldEffect, aiData->holdEffects[FOE(battlerAtkPartner)]))
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
else if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY && HasMoveThatLowersOwnStats(battlerAtkPartner))
|
||||
{
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
}
|
||||
return score;
|
||||
}
|
||||
break;
|
||||
case EFFECT_ROLE_PLAY:
|
||||
|
|
|
@ -2089,6 +2089,26 @@ bool32 HasAnyKnownMove(u32 battlerId)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveThatLowersOwnStats(u32 battlerId)
|
||||
{
|
||||
s32 i, j;
|
||||
u32 aiMove;
|
||||
u16 *moves = GetMovesArray(battlerId);
|
||||
for (i = 0; i < MAX_MON_MOVES; i++)
|
||||
{
|
||||
aiMove = moves[i];
|
||||
if (aiMove != MOVE_NONE && aiMove != MOVE_UNAVAILABLE)
|
||||
{
|
||||
for (j = 0; j < gMovesInfo[aiMove].numAdditionalEffects; j++)
|
||||
{
|
||||
if (IsSelfStatLoweringEffect(gMovesInfo[aiMove].additionalEffects[j].moveEffect) && gMovesInfo[aiMove].additionalEffects[j].self)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect)
|
||||
{
|
||||
s32 i;
|
||||
|
@ -2294,6 +2314,34 @@ bool32 IsStatLoweringEffect(u32 effect)
|
|||
}
|
||||
}
|
||||
|
||||
bool32 IsSelfStatLoweringEffect(u32 effect)
|
||||
{
|
||||
// Self stat lowering moves like Overheart, Superpower etc.
|
||||
switch (effect)
|
||||
{
|
||||
case MOVE_EFFECT_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_SPD_MINUS_1:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_1:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_1:
|
||||
case MOVE_EFFECT_EVS_MINUS_1:
|
||||
case MOVE_EFFECT_ACC_MINUS_1:
|
||||
case MOVE_EFFECT_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_SPD_MINUS_2:
|
||||
case MOVE_EFFECT_SP_ATK_MINUS_2:
|
||||
case MOVE_EFFECT_SP_DEF_MINUS_2:
|
||||
case MOVE_EFFECT_EVS_MINUS_2:
|
||||
case MOVE_EFFECT_ACC_MINUS_2:
|
||||
case MOVE_EFFECT_V_CREATE:
|
||||
case MOVE_EFFECT_ATK_DEF_DOWN:
|
||||
case MOVE_EFFECT_DEF_SPDEF_DOWN:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
bool32 HasDamagingMove(u32 battlerId)
|
||||
{
|
||||
u32 i;
|
||||
|
|
|
@ -239,3 +239,18 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves that cure inactive party members")
|
|||
TURN { EXPECT_MOVE(opponent, MOVE_HEAL_BELL); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI prioritizes Skill Swapping Contrary to allied mons that would benefit from it")
|
||||
{
|
||||
GIVEN {
|
||||
ASSUME(gMovesInfo[MOVE_SKILL_SWAP].effect == EFFECT_SKILL_SWAP);
|
||||
ASSUME(gMovesInfo[MOVE_OVERHEAT].additionalEffects[0].moveEffect == MOVE_EFFECT_SP_ATK_MINUS_2);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(3); }
|
||||
OPPONENT(SPECIES_SPINDA) { Ability(ABILITY_CONTRARY); Speed(5); Moves(MOVE_SKILL_SWAP, MOVE_ENCORE, MOVE_FAKE_TEARS, MOVE_SWAGGER); }
|
||||
OPPONENT(SPECIES_ARCANINE) { Ability(ABILITY_INTIMIDATE); Speed(4); Moves (MOVE_OVERHEAT); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_SKILL_SWAP, target:opponentRight); EXPECT_MOVE(opponentRight, MOVE_OVERHEAT); }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue