AI uses Tailwind. (#7515)
This commit is contained in:
parent
c6ee7feaa3
commit
7fb5d98bf6
@ -125,7 +125,6 @@ bool32 BattlerWillFaintFromWeather(u32 battler, u32 ability);
|
||||
bool32 BattlerWillFaintFromSecondaryDamage(u32 battler, u32 ability);
|
||||
bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move);
|
||||
bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex);
|
||||
u32 GetBattlerSideSpeedAverage(u32 battler);
|
||||
bool32 ShouldAbsorb(u32 battlerAtk, u32 battlerDef, u32 move, s32 damage);
|
||||
bool32 ShouldRecover(u32 battlerAtk, u32 battlerDef, u32 move, u32 healPercent);
|
||||
bool32 ShouldSetScreen(u32 battlerAtk, u32 battlerDef, enum BattleMoveEffects moveEffect);
|
||||
|
||||
@ -429,13 +429,13 @@ static enum FieldEffectOutcome BenefitsFromPsychicTerrain(u32 battler)
|
||||
static enum FieldEffectOutcome BenefitsFromTrickRoom(u32 battler)
|
||||
{
|
||||
// If we're in singles, we literally only care about speed.
|
||||
if (!IsDoubleBattle())
|
||||
if (IsBattle1v1())
|
||||
{
|
||||
if (GetBattlerSideSpeedAverage(battler) < GetBattlerSideSpeedAverage(FOE(battler)))
|
||||
if (gAiLogicData->speedStats[battler] < gAiLogicData->speedStats[FOE(battler)])
|
||||
return FIELD_EFFECT_POSITIVE;
|
||||
// If we tie, we shouldn't change trick room state.
|
||||
else if (GetBattlerSideSpeedAverage(battler) == GetBattlerSideSpeedAverage(FOE(battler)))
|
||||
return FIELD_EFFECT_NEUTRAL;
|
||||
else if (gAiLogicData->speedStats[battler] == gAiLogicData->speedStats[FOE(battler)])
|
||||
return FIELD_EFFECT_NEUTRAL;
|
||||
else
|
||||
return FIELD_EFFECT_NEGATIVE;
|
||||
}
|
||||
|
||||
@ -5092,6 +5092,9 @@ case EFFECT_GUARD_SPLIT:
|
||||
{
|
||||
if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && ShouldSetFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
// Set it for next pokemon in singles.
|
||||
else if (!(gFieldStatuses & STATUS_FIELD_TRICK_ROOM) && !hasPartner && (CountUsablePartyMons(battlerAtk) != 0))
|
||||
ADJUST_SCORE(DECENT_EFFECT);
|
||||
// Don't unset it on last turn.
|
||||
else if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter && ShouldClearFieldStatus(battlerAtk, STATUS_FIELD_TRICK_ROOM))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
@ -5200,9 +5203,44 @@ case EFFECT_GUARD_SPLIT:
|
||||
ADJUST_SCORE(DECENT_EFFECT); // Attacker partner wouldn't go before target
|
||||
break;
|
||||
case EFFECT_TAILWIND:
|
||||
if (GetBattlerSideSpeedAverage(battlerAtk) < GetBattlerSideSpeedAverage(battlerDef))
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
{
|
||||
if (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer != gBattleTurnCounter)
|
||||
break;
|
||||
|
||||
if (HasBattlerSideMoveWithEffect(battlerAtk, EFFECT_ELECTRO_BALL))
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
|
||||
if (isBattle1v1)
|
||||
{
|
||||
IncreaseStatUpScore(battlerAtk, battlerDef, STAT_CHANGE_SPEED);
|
||||
|
||||
if (CountUsablePartyMons(battlerAtk) != 0)
|
||||
ADJUST_SCORE(WEAK_EFFECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 tailwindScore = 0;
|
||||
u32 speed = aiData->speedStats[battlerAtk];
|
||||
u32 partnerSpeed = aiData->speedStats[BATTLE_PARTNER(battlerAtk)];
|
||||
u32 foe1Speed = aiData->speedStats[FOE(battlerAtk)];
|
||||
u32 foe2Speed = aiData->speedStats[BATTLE_PARTNER(FOE(battlerAtk))];
|
||||
|
||||
if (speed <= foe1Speed && (speed * 2) > foe1Speed)
|
||||
tailwindScore += 1;
|
||||
if (speed <= foe2Speed && (speed * 2) > foe2Speed)
|
||||
tailwindScore += 1;
|
||||
if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed)
|
||||
tailwindScore += 1;
|
||||
if (partnerSpeed <= foe1Speed && (speed * 2) > foe1Speed)
|
||||
tailwindScore += 1;
|
||||
|
||||
if (tailwindScore > 0)
|
||||
tailwindScore += 1;
|
||||
|
||||
ADJUST_SCORE(tailwindScore);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EFFECT_LUCKY_CHANT:
|
||||
if (isBattle1v1 && CountUsablePartyMons(battlerDef) > 0)
|
||||
ADJUST_SCORE(GOOD_EFFECT);
|
||||
|
||||
@ -3687,27 +3687,6 @@ bool32 AnyPartyMemberStatused(u32 battlerId, bool32 checkSoundproof)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
u32 GetBattlerSideSpeedAverage(u32 battler)
|
||||
{
|
||||
u32 speed1 = 0;
|
||||
u32 speed2 = 0;
|
||||
u32 numBattlersAlive = 0;
|
||||
|
||||
if (IsBattlerAlive(battler))
|
||||
{
|
||||
speed1 = gAiLogicData->speedStats[battler];
|
||||
numBattlersAlive++;
|
||||
}
|
||||
|
||||
if (HasPartner(battler))
|
||||
{
|
||||
speed2 = gAiLogicData->speedStats[BATTLE_PARTNER(battler)];
|
||||
numBattlersAlive++;
|
||||
}
|
||||
|
||||
return (speed1 + speed2) / numBattlersAlive;
|
||||
}
|
||||
|
||||
bool32 ShouldUseRecoilMove(u32 battlerAtk, u32 battlerDef, u32 recoilDmg, u32 moveIndex)
|
||||
{
|
||||
if (recoilDmg >= gBattleMons[battlerAtk].hp //Recoil kills attacker
|
||||
|
||||
@ -340,6 +340,24 @@ AI_SINGLE_BATTLE_TEST("AI uses Skill Swap against Poison Heal")
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Trick Room (singles)")
|
||||
{
|
||||
u32 speed;
|
||||
PARAMETRIZE { speed = 10; }
|
||||
PARAMETRIZE { speed = 20; }
|
||||
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(11); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(speed); Moves(MOVE_TACKLE, MOVE_TRICK_ROOM); }
|
||||
} WHEN {
|
||||
if (speed == 10)
|
||||
TURN { EXPECT_MOVE(opponent, MOVE_TRICK_ROOM); }
|
||||
else
|
||||
TURN { NOT_EXPECT_MOVE(opponent, MOVE_TRICK_ROOM); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI uses Quick Guard against Quick Attack when opponent would take poison damage")
|
||||
{
|
||||
PASSES_RANDOMLY(PREDICT_MOVE_CHANCE, 100, RNG_AI_PREDICT_MOVE);
|
||||
|
||||
@ -594,6 +594,34 @@ AI_DOUBLE_BATTLE_TEST("AI uses Trick Room intelligently")
|
||||
TURN { NOT_EXPECT_MOVE(opponentRight, MOVE_TRICK_ROOM); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Tailwind")
|
||||
{
|
||||
u32 speed1, speed2, speed3, speed4;
|
||||
|
||||
PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 20; speed4 = 20; }
|
||||
PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 5; speed4 = 5; }
|
||||
PARAMETRIZE { speed1 = 20; speed2 = 20; speed3 = 15; speed4 = 15; }
|
||||
PARAMETRIZE { speed1 = 1; speed2 = 1; speed3 = 5; speed4 = 5; }
|
||||
PARAMETRIZE { speed1 = 1; speed2 = 20; speed3 = 15; speed4 = 15; }
|
||||
PARAMETRIZE { speed1 = 1; speed2 = 20; speed3 = 20; speed4 = 15; }
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_AFTER_YOU) == EFFECT_AFTER_YOU);
|
||||
ASSUME(GetMoveEffect(MOVE_TRICK_ROOM) == EFFECT_TRICK_ROOM);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_DOUBLE_BATTLE);
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(speed1); }
|
||||
PLAYER(SPECIES_WOBBUFFET) { Speed(speed2); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(speed3); Moves(MOVE_TAILWIND, MOVE_HEADBUTT); }
|
||||
OPPONENT(SPECIES_WOBBUFFET) { Speed(speed4); Moves(MOVE_TAILWIND, MOVE_HEADBUTT); }
|
||||
} WHEN {
|
||||
if (speed3 > 10)
|
||||
TURN { EXPECT_MOVE(opponentLeft, MOVE_TAILWIND); }
|
||||
else
|
||||
TURN { NOT_EXPECT_MOVE(opponentLeft, MOVE_TAILWIND); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI uses Guard Split to improve its stats")
|
||||
{
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user