Switch chance config support (#6187)
This commit is contained in:
parent
174bc2f29f
commit
579fa6410d
@ -1,6 +1,39 @@
|
||||
#ifndef GUARD_BATTLE_AI_SWITCH_ITEMS_H
|
||||
#define GUARD_BATTLE_AI_SWITCH_ITEMS_H
|
||||
|
||||
enum ShouldSwitchScenario
|
||||
{
|
||||
SHOULD_SWITCH_WONDER_GUARD,
|
||||
SHOULD_SWITCH_ABSORBS_MOVE,
|
||||
SHOULD_SWITCH_TRAPPER,
|
||||
SHOULD_SWITCH_FREE_TURN,
|
||||
SHOULD_SWITCH_TRUANT,
|
||||
SHOULD_SWITCH_ALL_MOVES_BAD,
|
||||
SHOULD_SWITCH_PERISH_SONG,
|
||||
SHOULD_SWITCH_YAWN,
|
||||
SHOULD_SWITCH_BADLY_POISONED,
|
||||
SHOULD_SWITCH_BADLY_POISONED_STATS_RAISED,
|
||||
SHOULD_SWITCH_CURSED,
|
||||
SHOULD_SWITCH_CURSED_STATS_RAISED,
|
||||
SHOULD_SWITCH_NIGHTMARE,
|
||||
SHOULD_SWITCH_NIGHTMARE_STATS_RAISED,
|
||||
SHOULD_SWITCH_SEEDED,
|
||||
SHOULD_SWITCH_SEEDED_STATS_RAISED,
|
||||
SHOULD_SWITCH_INFATUATION,
|
||||
SHOULD_SWITCH_HASBADODDS,
|
||||
SHOULD_SWITCH_NATURAL_CURE_STRONG,
|
||||
SHOULD_SWITCH_NATURAL_CURE_STRONG_STATS_RAISED,
|
||||
SHOULD_SWITCH_NATURAL_CURE_WEAK,
|
||||
SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED,
|
||||
SHOULD_SWITCH_REGENERATOR,
|
||||
SHOULD_SWITCH_REGENERATOR_STATS_RAISED,
|
||||
SHOULD_SWITCH_ENCORE_STATUS,
|
||||
SHOULD_SWITCH_ENCORE_DAMAGE,
|
||||
SHOULD_SWITCH_CHOICE_LOCKED,
|
||||
SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO,
|
||||
SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS,
|
||||
};
|
||||
|
||||
enum SwitchType
|
||||
{
|
||||
SWITCH_AFTER_KO,
|
||||
|
||||
49
include/config/ai.h
Normal file
49
include/config/ai.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef GUARD_CONFIG_AI_H
|
||||
#define GUARD_CONFIG_AI_H
|
||||
|
||||
// For the details on what specific factors the switching functions are considering, go read the corresponding function inside ShouldSwitch in src/battle_ai_switch_items.c
|
||||
// These configuration options control how likely the AI is to switch if it determines that a switch meets all of its criteria
|
||||
// Think of them almost like success rates; if the AI has determined that it needs to switch out to hit Wonder Guard, how often do you want it to actually take that course of action? Etc.
|
||||
|
||||
// AI switch chances; if you want more complex behaviour, modify GetSwitchChance
|
||||
#define SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_TRUANT_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE 100
|
||||
|
||||
// AI smart switching chances; if you want more complex behaviour, modify GetSwitchChance
|
||||
#define SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_TRAPPER_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_FREE_TURN_PERCENTAGE 100
|
||||
#define STAY_IN_ABSORBING_PERCENTAGE 66 // Chance to stay in if outgoing mon has super effective move against player, will prevent switching out for an absorber with this likelihood
|
||||
#define SHOULD_SWITCH_HASBADODDS_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_CHOICE_LOCKED_PERCENTAGE 100 // Only if locked into status move
|
||||
#define SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS_PERCENTAGE 100
|
||||
|
||||
// AI smart switching chances for bad statuses
|
||||
#define SHOULD_SWITCH_PERISH_SONG_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_YAWN_PERCENTAGE 100
|
||||
#define SHOULD_SWITCH_BADLY_POISONED_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_BADLY_POISONED_STATS_RAISED_PERCENTAGE 20
|
||||
#define SHOULD_SWITCH_CURSED_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_CURSED_STATS_RAISED_PERCENTAGE 20
|
||||
#define SHOULD_SWITCH_NIGHTMARE_PERCENTAGE 33
|
||||
#define SHOULD_SWITCH_NIGHTMARE_STATS_RAISED_PERCENTAGE 15
|
||||
#define SHOULD_SWITCH_SEEDED_PERCENTAGE 25
|
||||
#define SHOULD_SWITCH_SEEDED_STATS_RAISED_PERCENTAGE 10
|
||||
#define SHOULD_SWITCH_INFATUATION_PERCENTAGE 100
|
||||
|
||||
// AI smart switching chances for beneficial abilities
|
||||
#define SHOULD_SWITCH_NATURAL_CURE_STRONG_PERCENTAGE 66
|
||||
#define SHOULD_SWITCH_NATURAL_CURE_STRONG_STATS_RAISED_PERCENTAGE 10
|
||||
#define SHOULD_SWITCH_NATURAL_CURE_WEAK_PERCENTAGE 25
|
||||
#define SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED_PERCENTAGE 10
|
||||
#define SHOULD_SWITCH_REGENERATOR_PERCENTAGE 50
|
||||
#define SHOULD_SWITCH_REGENERATOR_STATS_RAISED_PERCENTAGE 20
|
||||
|
||||
// AI prediction chances
|
||||
#define PREDICT_SWITCH_CHANCE 50
|
||||
|
||||
#endif // GUARD_CONFIG_AI_H
|
||||
@ -10,6 +10,7 @@
|
||||
#include "config/overworld.h"
|
||||
#include "config/dexnav.h"
|
||||
#include "config/summary_screen.h"
|
||||
#include "config/ai.h"
|
||||
|
||||
// Invalid Versions show as "----------" in Gen 4 and Gen 5's summary screen.
|
||||
// In Gens 6 and 7, invalid versions instead show "a distant land" in the summary screen.
|
||||
|
||||
@ -171,12 +171,22 @@ enum RandomTag
|
||||
RNG_AI_SWITCH_CURSED,
|
||||
RNG_AI_SWITCH_NIGHTMARE,
|
||||
RNG_AI_SWITCH_SEEDED,
|
||||
RNG_AI_SWITCH_YAWN,
|
||||
RNG_AI_SWITCH_PERISH_SONG,
|
||||
RNG_AI_SWITCH_INFATUATION,
|
||||
RNG_AI_SWITCH_ABSORBING,
|
||||
RNG_AI_SWITCH_ABSORBING_STAY_IN,
|
||||
RNG_AI_SWITCH_NATURAL_CURE,
|
||||
RNG_AI_SWITCH_REGENERATOR,
|
||||
RNG_AI_SWITCH_ENCORE,
|
||||
RNG_AI_SWITCH_CHOICE_LOCKED,
|
||||
RNG_AI_SWITCH_STATS_LOWERED,
|
||||
RNG_AI_SWITCH_SE_DEFENSIVE,
|
||||
RNG_AI_SWITCH_TRUANT,
|
||||
RNG_AI_SWITCH_WONDER_GUARD,
|
||||
RNG_AI_SWITCH_TRAPPER,
|
||||
RNG_AI_SWITCH_FREE_TURN,
|
||||
RNG_AI_SWITCH_ALL_MOVES_BAD,
|
||||
RNG_SHELL_SIDE_ARM,
|
||||
RNG_RANDOM_TARGET,
|
||||
RNG_AI_PREDICT_ABILITY,
|
||||
|
||||
@ -37,6 +37,74 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon)
|
||||
AI_DATA->switchinCandidate.hypotheticalStatus = FALSE;
|
||||
}
|
||||
|
||||
u32 GetSwitchChance(enum ShouldSwitchScenario shouldSwitchScenario)
|
||||
{
|
||||
// Modify these cases if you want unique behaviour based on other data (trainer class, difficulty, etc.)
|
||||
switch(shouldSwitchScenario)
|
||||
{
|
||||
case SHOULD_SWITCH_WONDER_GUARD:
|
||||
return SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ABSORBS_MOVE:
|
||||
return SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE;
|
||||
case SHOULD_SWITCH_TRAPPER:
|
||||
return SHOULD_SWITCH_TRAPPER_PERCENTAGE;
|
||||
case SHOULD_SWITCH_FREE_TURN:
|
||||
return SHOULD_SWITCH_FREE_TURN_PERCENTAGE;
|
||||
case SHOULD_SWITCH_TRUANT:
|
||||
return SHOULD_SWITCH_TRUANT_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ALL_MOVES_BAD:
|
||||
return SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE;
|
||||
case SHOULD_SWITCH_PERISH_SONG:
|
||||
return SHOULD_SWITCH_PERISH_SONG_PERCENTAGE;
|
||||
case SHOULD_SWITCH_YAWN:
|
||||
return SHOULD_SWITCH_YAWN_PERCENTAGE;
|
||||
case SHOULD_SWITCH_BADLY_POISONED:
|
||||
return SHOULD_SWITCH_BADLY_POISONED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_BADLY_POISONED_STATS_RAISED:
|
||||
return SHOULD_SWITCH_BADLY_POISONED_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_CURSED:
|
||||
return SHOULD_SWITCH_CURSED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_CURSED_STATS_RAISED:
|
||||
return SHOULD_SWITCH_CURSED_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NIGHTMARE:
|
||||
return SHOULD_SWITCH_NIGHTMARE_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NIGHTMARE_STATS_RAISED:
|
||||
return SHOULD_SWITCH_NIGHTMARE_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_SEEDED:
|
||||
return SHOULD_SWITCH_SEEDED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_SEEDED_STATS_RAISED:
|
||||
return SHOULD_SWITCH_SEEDED_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_INFATUATION:
|
||||
return SHOULD_SWITCH_INFATUATION_PERCENTAGE;
|
||||
case SHOULD_SWITCH_HASBADODDS:
|
||||
return SHOULD_SWITCH_HASBADODDS_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NATURAL_CURE_STRONG:
|
||||
return SHOULD_SWITCH_NATURAL_CURE_STRONG_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NATURAL_CURE_STRONG_STATS_RAISED:
|
||||
return SHOULD_SWITCH_NATURAL_CURE_STRONG_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NATURAL_CURE_WEAK:
|
||||
return SHOULD_SWITCH_NATURAL_CURE_WEAK_PERCENTAGE;
|
||||
case SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED:
|
||||
return SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_REGENERATOR:
|
||||
return SHOULD_SWITCH_REGENERATOR_PERCENTAGE;
|
||||
case SHOULD_SWITCH_REGENERATOR_STATS_RAISED:
|
||||
return SHOULD_SWITCH_REGENERATOR_STATS_RAISED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ENCORE_STATUS:
|
||||
return SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ENCORE_DAMAGE:
|
||||
return SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE;
|
||||
case SHOULD_SWITCH_CHOICE_LOCKED:
|
||||
return SHOULD_SWITCH_CHOICE_LOCKED_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO:
|
||||
return SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO_PERCENTAGE;
|
||||
case SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS:
|
||||
return SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS_PERCENTAGE;
|
||||
default:
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
u32 GetThinkingBattler(u32 battler)
|
||||
{
|
||||
if (AI_DATA->aiSwitchPredictionInProgress)
|
||||
@ -198,7 +266,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4)))
|
||||
{
|
||||
// 50% chance to stay in regardless
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
@ -218,7 +286,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// 50% chance to stay in regardless
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, (100 - GetSwitchChance(SHOULD_SWITCH_HASBADODDS))) && !AI_DATA->aiSwitchPredictionInProgress)
|
||||
return FALSE;
|
||||
|
||||
// Switch mon out
|
||||
@ -237,7 +305,8 @@ static bool32 ShouldSwitchIfTruant(u32 battler)
|
||||
&& gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
|
||||
{
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
if (RandomPercentage(RNG_AI_SWITCH_TRUANT, GetSwitchChance(SHOULD_SWITCH_TRUANT)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@ -271,7 +340,9 @@ static bool32 ShouldSwitchIfAllMovesBad(u32 battler)
|
||||
}
|
||||
}
|
||||
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
if (RandomPercentage(RNG_AI_SWITCH_ALL_MOVES_BAD, GetSwitchChance(SHOULD_SWITCH_ALL_MOVES_BAD)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 FindMonThatHitsWonderGuard(u32 battler)
|
||||
@ -320,7 +391,7 @@ static bool32 FindMonThatHitsWonderGuard(u32 battler)
|
||||
if (move != MOVE_NONE)
|
||||
{
|
||||
// Found a mon
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0))
|
||||
if (AI_GetMoveEffectiveness(move, battler, opposingBattler) >= UQ_4_12(2.0) && RandomPercentage(RNG_AI_SWITCH_WONDER_GUARD, GetSwitchChance(SHOULD_SWITCH_WONDER_GUARD)))
|
||||
return SetSwitchinAndSwitch(battler, i);
|
||||
}
|
||||
}
|
||||
@ -351,7 +422,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
if (gBattleStruct->prevTurnSpecies[battler] != gBattleMons[battler].species) // AI mon has changed, player's behaviour no longer reliable; note to override this if using AI_FLAG_PREDICT_MOVE
|
||||
return FALSE;
|
||||
|
||||
if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING, 66) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING_STAY_IN, STAY_IN_ABSORBING_PERCENTAGE) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
return FALSE;
|
||||
|
||||
if (IsDoubleBattle())
|
||||
@ -436,7 +507,7 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler)
|
||||
for (j = 0; j < numAbsorbingAbilities; j++)
|
||||
{
|
||||
// Found a mon
|
||||
if (absorbingTypeAbilities[j] == monAbility)
|
||||
if (absorbingTypeAbilities[j] == monAbility && RandomPercentage(RNG_AI_SWITCH_ABSORBING, GetSwitchChance(SHOULD_SWITCH_ABSORBS_MOVE)))
|
||||
return SetSwitchinAndSwitch(battler, i);
|
||||
}
|
||||
}
|
||||
@ -452,7 +523,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler)
|
||||
if (IsDoubleBattle() || !(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING))
|
||||
return FALSE;
|
||||
|
||||
if (isOpposingBattlerChargingOrInvulnerable && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
|
||||
if (isOpposingBattlerChargingOrInvulnerable && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
return FALSE;
|
||||
@ -489,7 +560,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler)
|
||||
if (CanAbilityTrapOpponent(monAbility, opposingBattler) || (CanAbilityTrapOpponent(AI_GetBattlerAbility(opposingBattler), opposingBattler) && monAbility == ABILITY_TRACE))
|
||||
{
|
||||
// If mon in slot i is the most suitable switchin candidate, then it's a trapper than wins 1v1
|
||||
if (i == AI_DATA->mostSuitableMonId[battler])
|
||||
if (i == AI_DATA->mostSuitableMonId[battler] && RandomPercentage(RNG_AI_SWITCH_FREE_TURN, GetSwitchChance(SHOULD_SWITCH_FREE_TURN)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
}
|
||||
@ -508,15 +579,17 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
//Perish Song
|
||||
if (gStatuses3[battler] & STATUS3_PERISH_SONG
|
||||
&& gDisableStructs[battler].perishSongTimer == 0
|
||||
&& monAbility != ABILITY_SOUNDPROOF)
|
||||
switchMon = TRUE;
|
||||
&& monAbility != ABILITY_SOUNDPROOF
|
||||
&& RandomPercentage(RNG_AI_SWITCH_PERISH_SONG, GetSwitchChance(SHOULD_SWITCH_PERISH_SONG)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)
|
||||
{
|
||||
//Yawn
|
||||
if (gStatuses3[battler] & STATUS3_YAWN
|
||||
&& CanBeSlept(battler, monAbility, BLOCKED_BY_SLEEP_CLAUSE)
|
||||
&& gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3)
|
||||
&& gBattleMons[battler].hp > gBattleMons[battler].maxHP / 3
|
||||
&& RandomPercentage(RNG_AI_SWITCH_YAWN, GetSwitchChance(SHOULD_SWITCH_YAWN)))
|
||||
{
|
||||
switchMon = TRUE;
|
||||
|
||||
@ -546,6 +619,9 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
&& !(gBattleMons[battler].status2 & STATUS2_FORESIGHT)
|
||||
&& !(gStatuses3[battler] & STATUS3_MIRACLE_EYED))
|
||||
switchMon = FALSE;
|
||||
|
||||
if (switchMon)
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
|
||||
// Secondary Damage
|
||||
@ -556,35 +632,33 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler)
|
||||
if (((gBattleMons[battler].status1 & STATUS1_TOXIC_COUNTER) >= STATUS1_TOXIC_TURN(2))
|
||||
&& gBattleMons[battler].hp >= (gBattleMons[battler].maxHP / 3)
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_BADLY_POISONED, 20) : RandomPercentage(RNG_AI_SWITCH_BADLY_POISONED, 50)))
|
||||
switchMon = TRUE;
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_BADLY_POISONED, GetSwitchChance(SHOULD_SWITCH_BADLY_POISONED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_BADLY_POISONED, GetSwitchChance(SHOULD_SWITCH_BADLY_POISONED))))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
//Cursed
|
||||
if (gBattleMons[battler].status2 & STATUS2_CURSED
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_CURSED, 20) : RandomPercentage(RNG_AI_SWITCH_CURSED, 50)))
|
||||
switchMon = TRUE;
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_CURSED, GetSwitchChance(SHOULD_SWITCH_CURSED))))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
//Nightmare
|
||||
if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, 15) : RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, 33)))
|
||||
switchMon = TRUE;
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_NIGHTMARE, GetSwitchChance(SHOULD_SWITCH_NIGHTMARE))))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
//Leech Seed
|
||||
if (gStatuses3[battler] & STATUS3_LEECHSEED
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_SEEDED, 10) : RandomPercentage(RNG_AI_SWITCH_SEEDED, 25)))
|
||||
switchMon = TRUE;
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_SEEDED, GetSwitchChance(SHOULD_SWITCH_SEEDED))))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
|
||||
// Infatuation
|
||||
if (gBattleMons[battler].status2 & STATUS2_INFATUATION
|
||||
&& !AiExpectsToFaintPlayer(battler))
|
||||
switchMon = TRUE;
|
||||
&& !AiExpectsToFaintPlayer(battler)
|
||||
&& RandomPercentage(RNG_AI_SWITCH_INFATUATION, GetSwitchChance(SHOULD_SWITCH_INFATUATION)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
|
||||
if (switchMon)
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
else
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static bool32 ShouldSwitchIfAbilityBenefit(u32 battler)
|
||||
@ -602,13 +676,13 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler)
|
||||
//Attempt to cure bad ailment
|
||||
if (gBattleMons[battler].status1 & (STATUS1_SLEEP | STATUS1_FREEZE | STATUS1_TOXIC_POISON)
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, 10) : RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, 66)))
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, GetSwitchChance(SHOULD_SWITCH_NATURAL_CURE_STRONG_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, GetSwitchChance(SHOULD_SWITCH_NATURAL_CURE_STRONG))))
|
||||
break;
|
||||
//Attempt to cure lesser ailment
|
||||
if ((gBattleMons[battler].status1 & STATUS1_ANY)
|
||||
&& (gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 2)
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, 10) : RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, 25)))
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, GetSwitchChance(SHOULD_SWITCH_NATURAL_CURE_WEAK_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_NATURAL_CURE, GetSwitchChance(SHOULD_SWITCH_NATURAL_CURE_WEAK))))
|
||||
break;
|
||||
|
||||
return FALSE;
|
||||
@ -619,7 +693,7 @@ static bool32 ShouldSwitchIfAbilityBenefit(u32 battler)
|
||||
return FALSE;
|
||||
if ((gBattleMons[battler].hp <= ((gBattleMons[battler].maxHP * 2) / 3))
|
||||
&& AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_REGENERATOR, 20) : RandomPercentage(RNG_AI_SWITCH_REGENERATOR, 50)))
|
||||
&& (hasStatRaised ? RandomPercentage(RNG_AI_SWITCH_REGENERATOR, GetSwitchChance(SHOULD_SWITCH_REGENERATOR_STATS_RAISED)) : RandomPercentage(RNG_AI_SWITCH_REGENERATOR, GetSwitchChance(SHOULD_SWITCH_REGENERATOR))))
|
||||
break;
|
||||
|
||||
return FALSE;
|
||||
@ -858,7 +932,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// Switch out if status move
|
||||
if (GetMoveCategory(encoredMove) == DAMAGE_CATEGORY_STATUS)
|
||||
if (GetMoveCategory(encoredMove) == DAMAGE_CATEGORY_STATUS && RandomPercentage(RNG_AI_SWITCH_ENCORE, GetSwitchChance(SHOULD_SWITCH_ENCORE_STATUS)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
// Stay in if effective move
|
||||
@ -866,7 +940,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler)
|
||||
return FALSE;
|
||||
|
||||
// Switch out 50% of the time otherwise
|
||||
else if ((RandomPercentage(RNG_AI_SWITCH_ENCORE, 50) || AI_DATA->aiSwitchPredictionInProgress) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
|
||||
else if ((RandomPercentage(RNG_AI_SWITCH_ENCORE, GetSwitchChance(SHOULD_SWITCH_ENCORE_DAMAGE)) || AI_DATA->aiSwitchPredictionInProgress) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE)
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
|
||||
return FALSE;
|
||||
@ -878,7 +952,7 @@ static bool32 ShouldSwitchIfBadChoiceLock(u32 battler)
|
||||
|
||||
if (HOLD_EFFECT_CHOICE(holdEffect) && gBattleMons[battler].ability != ABILITY_KLUTZ)
|
||||
{
|
||||
if (GetMoveCategory(AI_DATA->lastUsedMove[battler]) == DAMAGE_CATEGORY_STATUS)
|
||||
if (GetMoveCategory(AI_DATA->lastUsedMove[battler]) == DAMAGE_CATEGORY_STATUS && RandomPercentage(RNG_AI_SWITCH_CHOICE_LOCKED, GetSwitchChance(SHOULD_SWITCH_CHOICE_LOCKED)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
|
||||
@ -904,11 +978,11 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler)
|
||||
// 50% chance if attack at -2 and have a good candidate mon
|
||||
else if (attackingStage == DEFAULT_STAT_STAGE - 2)
|
||||
{
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
// If at -3 or worse, switch out regardless
|
||||
else if (attackingStage < DEFAULT_STAT_STAGE - 2)
|
||||
else if ((attackingStage < DEFAULT_STAT_STAGE - 2) && RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
|
||||
@ -921,11 +995,11 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler)
|
||||
// 50% chance if attack at -2 and have a good candidate mon
|
||||
else if (spAttackingStage == DEFAULT_STAT_STAGE - 2)
|
||||
{
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO)) || AI_DATA->aiSwitchPredictionInProgress))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
// If at -3 or worse, switch out regardless
|
||||
else if (spAttackingStage < DEFAULT_STAT_STAGE - 2)
|
||||
else if ((spAttackingStage < DEFAULT_STAT_STAGE - 2) && RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, GetSwitchChance(SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS)))
|
||||
return SetSwitchinAndSwitch(battler, PARTY_SIZE);
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
@ -4160,7 +4160,7 @@ void SetupAISwitchingData(u32 battler, enum SwitchType switchType)
|
||||
gBattleStruct->prevTurnSpecies[opposingBattler] = gBattleMons[opposingBattler].species;
|
||||
|
||||
// Determine whether AI will use predictions this turn
|
||||
AI_DATA->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, 50);
|
||||
AI_DATA->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, PREDICT_SWITCH_CHANCE);
|
||||
}
|
||||
|
||||
// AI's data
|
||||
|
||||
@ -24,6 +24,8 @@ AI_SINGLE_BATTLE_TEST("Choiced Pokémon switch out after using a status move onc
|
||||
PARAMETRIZE { ability = ABILITY_KLUTZ; heldItem = choiceItems[j]; }
|
||||
}
|
||||
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_CHOICE_LOCKED_PERCENTAGE, 100, RNG_AI_SWITCH_CHOICE_LOCKED);
|
||||
|
||||
GIVEN {
|
||||
ASSUME(GetMoveCategory(MOVE_YAWN) == DAMAGE_CATEGORY_STATUS);
|
||||
ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN);
|
||||
|
||||
@ -27,18 +27,6 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in Pursuit sc
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in Wonder Guard scenario")
|
||||
{
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES);
|
||||
PLAYER(SPECIES_SHEDINJA) { Moves(MOVE_PURSUIT, MOVE_CRUNCH); }
|
||||
OPPONENT(SPECIES_GENGAR) { Moves(MOVE_PSYCHIC); }
|
||||
OPPONENT(SPECIES_SWELLOW) { Moves(MOVE_PECK); }
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_PURSUIT); EXPECT_SWITCH(opponent, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI will use hit escape moves on predicted switches")
|
||||
{
|
||||
PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH);
|
||||
@ -137,7 +125,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH | AI_FLAG_PREDICT_INCOMING_MON: AI
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in predicted-incoming-mon scenario")
|
||||
{
|
||||
PASSES_RANDOMLY(5, 10, RNG_AI_SWITCH_HASBADODDS);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_HASBADODDS_PERCENTAGE, 100, RNG_AI_SWITCH_HASBADODDS);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES);
|
||||
PLAYER(SPECIES_TYRANITAR) { Moves(MOVE_CRUNCH, MOVE_SPORE); }
|
||||
|
||||
@ -24,6 +24,7 @@ AI_SINGLE_BATTLE_TEST("AI gets baited by Protect Switch tactics") // This behavi
|
||||
// General switching behaviour
|
||||
AI_SINGLE_BATTLE_TEST("AI switches if Perish Song is about to kill")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_PERISH_SONG_PERCENTAGE, 100, RNG_AI_SWITCH_PERISH_SONG);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
@ -46,6 +47,7 @@ AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spot
|
||||
PARAMETRIZE {flags = AI_FLAG_SMART_SWITCHING; }
|
||||
PARAMETRIZE {flags = 0; }
|
||||
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | flags);
|
||||
PLAYER(SPECIES_RATTATA);
|
||||
@ -67,8 +69,22 @@ AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spot
|
||||
}
|
||||
}
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI will switch out if it has no move that affects the player")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ALL_MOVES_BAD_PERCENTAGE, 100, RNG_AI_SWITCH_ALL_MOVES_BAD);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_RATTATA);
|
||||
OPPONENT(SPECIES_GENGAR) { Moves(MOVE_SHADOW_BALL); }
|
||||
OPPONENT(SPECIES_RATTATA) { Moves(MOVE_TACKLE); }
|
||||
} WHEN {
|
||||
TURN { EXPECT_SWITCH(opponent, 1); }
|
||||
}
|
||||
}
|
||||
|
||||
AI_DOUBLE_BATTLE_TEST("AI will not try to switch for the same pokemon for 2 spots in a double battle (Wonder Guard)")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE, 100, RNG_AI_SWITCH_WONDER_GUARD);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING);
|
||||
PLAYER(SPECIES_SHEDINJA);
|
||||
@ -430,7 +446,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch in trapping mon m
|
||||
u32 aiSmartSwitchingFlag = 0;
|
||||
PARAMETRIZE { aiSmartSwitchingFlag = 0; }
|
||||
PARAMETRIZE { aiSmartSwitchingFlag = AI_FLAG_SMART_SWITCHING; }
|
||||
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_TRAPPER_PERCENTAGE, 100, RNG_AI_SWITCH_TRAPPER);
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_GOLURK].types[0] == TYPE_GROUND);
|
||||
ASSUME(gSpeciesInfo[SPECIES_GOLURK].types[1] == TYPE_GHOST);
|
||||
@ -488,6 +504,7 @@ AI_SINGLE_BATTLE_TEST("AI won't use trapping behaviour if player only has 1 mon
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI will trap player using Trace if player has a trapper")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_TRAPPER_PERCENTAGE, 100, RNG_AI_SWITCH_TRAPPER);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING);
|
||||
PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_ROCK_TOMB); }
|
||||
@ -501,7 +518,7 @@ AI_SINGLE_BATTLE_TEST("AI will trap player using Trace if player has a trapper")
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if mon would be OKHO'd and they have a good switchin 50% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(50, 100, RNG_AI_SWITCH_HASBADODDS);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_HASBADODDS_PERCENTAGE, 100, RNG_AI_SWITCH_HASBADODDS);
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_RHYDON].types[0] == TYPE_GROUND);
|
||||
ASSUME(gSpeciesInfo[SPECIES_PELIPPER].types[0] == TYPE_WATER);
|
||||
@ -520,6 +537,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if mon would
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if it can't deal damage to a mon with Wonder Guard")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE, 100, RNG_AI_SWITCH_WONDER_GUARD);
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[0] == TYPE_BUG);
|
||||
ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[1] == TYPE_GHOST);
|
||||
@ -539,6 +557,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if it can't deal damage to
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it can't deal damage to a mon with Wonder Guard")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_WONDER_GUARD_PERCENTAGE, 100, RNG_AI_SWITCH_WONDER_GUARD);
|
||||
GIVEN {
|
||||
ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[0] == TYPE_BUG);
|
||||
ASSUME(gSpeciesInfo[SPECIES_SHEDINJA].types[1] == TYPE_GHOST);
|
||||
@ -560,7 +579,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
{
|
||||
u32 species = SPECIES_NONE, odds = 0;
|
||||
PARAMETRIZE { species = SPECIES_ZIGZAGOON, odds = 0; }
|
||||
PARAMETRIZE { species = SPECIES_HARIYAMA, odds = 50; }
|
||||
PARAMETRIZE { species = SPECIES_HARIYAMA, odds = SHOULD_SWITCH_BADLY_POISONED_PERCENTAGE; }
|
||||
PASSES_RANDOMLY(odds, 100, RNG_AI_SWITCH_BADLY_POISONED);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_TOXIC) == EFFECT_TOXIC);
|
||||
@ -577,7 +596,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has been Curse'd 50% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(50, 100, RNG_AI_SWITCH_CURSED);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_CURSED_PERCENTAGE, 100, RNG_AI_SWITCH_CURSED);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_CURSE) == EFFECT_CURSE);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -593,7 +612,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has been Nightmare'd 33% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(33, 100, RNG_AI_SWITCH_NIGHTMARE);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_NIGHTMARE_PERCENTAGE, 100, RNG_AI_SWITCH_NIGHTMARE);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_NIGHTMARE) == EFFECT_NIGHTMARE);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -608,7 +627,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has been Leech Seed'd 25% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(25, 100, RNG_AI_SWITCH_SEEDED);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_SEEDED_PERCENTAGE, 100, RNG_AI_SWITCH_SEEDED);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_LEECH_SEED) == EFFECT_LEECH_SEED);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -623,6 +642,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has been infatuated")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_INFATUATION_PERCENTAGE, 100, RNG_AI_SWITCH_INFATUATION);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ATTRACT) == EFFECT_ATTRACT);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -640,6 +660,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
u32 hp;
|
||||
PARAMETRIZE { hp = 30; }
|
||||
PARAMETRIZE { hp = 10; }
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_YAWN_PERCENTAGE, 100, RNG_AI_SWITCH_YAWN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -660,6 +681,7 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
u32 hp;
|
||||
PARAMETRIZE { hp = 30; }
|
||||
PARAMETRIZE { hp = 10; }
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_YAWN_PERCENTAGE, 100, RNG_AI_SWITCH_YAWN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_YAWN) == EFFECT_YAWN);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -680,6 +702,7 @@ AI_DOUBLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has bee
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is semi-invulnerable and it has an absorber")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_DIVE) == TYPE_WATER);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -694,7 +717,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an absorber but current mon has SE move 33% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(33, 100, RNG_AI_SWITCH_ABSORBING);
|
||||
PASSES_RANDOMLY(33, 100, RNG_AI_SWITCH_ABSORBING_STAY_IN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_WATER_GUN) == TYPE_WATER);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -709,7 +732,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has an
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is charging and it has an absorber")
|
||||
{
|
||||
PASSES_RANDOMLY(100, 100, RNG_AI_SWITCH_ABSORBING);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ABSORBS_MOVE_PERCENTAGE, 100, RNG_AI_SWITCH_ABSORBING);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_SOLAR_BEAM) == TYPE_GRASS);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -724,6 +747,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is charging and it has a good switchin immunity (type)")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_DIG) == TYPE_GROUND);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -738,6 +762,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's m
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if player's mon is charging and it has a good switchin immunity (ability)")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_FREE_TURN_PERCENTAGE, 100, RNG_AI_SWITCH_FREE_TURN);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveType(MOVE_DIG) == TYPE_GROUND);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -799,7 +824,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if opponent u
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if badly statused with >= 50% HP remaining and has Natural Cure and a good switchin 66% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(66, 100, RNG_AI_SWITCH_NATURAL_CURE);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_NATURAL_CURE_STRONG_PERCENTAGE, 100, RNG_AI_SWITCH_NATURAL_CURE);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_ODDISH) { Moves(MOVE_TOXIC, MOVE_TACKLE); }
|
||||
@ -813,7 +838,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if badly statused with >= 5
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if it has <= 66% HP remaining and has Regenerator and a good switchin 50% of the time")
|
||||
{
|
||||
PASSES_RANDOMLY(50, 100, RNG_AI_SWITCH_REGENERATOR);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_REGENERATOR_PERCENTAGE, 100, RNG_AI_SWITCH_REGENERATOR);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
|
||||
PLAYER(SPECIES_ZIGZAGOON) { Moves(MOVE_TACKLE); }
|
||||
@ -826,6 +851,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if it has <= 66% HP remaini
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if it has been Encore'd into a status move")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ENCORE_STATUS_PERCENTAGE, 100, RNG_AI_SWITCH_ENCORE);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -855,7 +881,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will stay in if Encore'd into
|
||||
AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if Encore'd into neutral move with good switchin 50% of the time")
|
||||
{
|
||||
KNOWN_FAILING; // AI still switches even if ShouldSwitch is set to immediately return FALSE, something external seems to be triggering this
|
||||
PASSES_RANDOMLY(50, 100, RNG_AI_SWITCH_ENCORE);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ENCORE_DAMAGE_PERCENTAGE, 100, RNG_AI_SWITCH_ENCORE);
|
||||
GIVEN {
|
||||
ASSUME(GetMoveEffect(MOVE_ENCORE) == EFFECT_ENCORE);
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_SWITCHING);
|
||||
@ -870,6 +896,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if Encore'd i
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and opponent has Protect")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_TRUANT_PERCENTAGE, 100, RNG_AI_SWITCH_TRUANT);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_ARON) { Moves(MOVE_TACKLE, MOVE_PROTECT); }
|
||||
@ -883,6 +910,7 @@ AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and oppon
|
||||
|
||||
AI_SINGLE_BATTLE_TEST("Switch AI: AI will switch out if mon has Truant and opponent has invulnerability move and is faster")
|
||||
{
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_TRUANT_PERCENTAGE, 100, RNG_AI_SWITCH_TRUANT);
|
||||
GIVEN {
|
||||
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_OMNISCIENT);
|
||||
PLAYER(SPECIES_SWELLOW) { Speed(5); Moves(MOVE_FLY); }
|
||||
@ -898,7 +926,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if main attac
|
||||
{
|
||||
u32 aiSpecies = SPECIES_NONE, aiMove = MOVE_NONE, move = MOVE_NONE;
|
||||
|
||||
PASSES_RANDOMLY(50, 100, RNG_AI_SWITCH_STATS_LOWERED);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ATTACKING_STAT_MINUS_TWO_PERCENTAGE, 100, RNG_AI_SWITCH_STATS_LOWERED);
|
||||
PARAMETRIZE {move = MOVE_CHARM; aiSpecies = SPECIES_FLAREON; aiMove = MOVE_FIRE_FANG; };
|
||||
PARAMETRIZE {move = MOVE_EERIE_IMPULSE; aiSpecies = SPECIES_ESPEON; aiMove = MOVE_CONFUSION; };
|
||||
|
||||
@ -919,7 +947,7 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI will switch out if main attac
|
||||
{
|
||||
u32 aiSpecies = SPECIES_NONE, aiMove = MOVE_NONE, move = MOVE_NONE, move2 = MOVE_NONE;
|
||||
|
||||
PASSES_RANDOMLY(100, 100, RNG_AI_SWITCH_STATS_LOWERED);
|
||||
PASSES_RANDOMLY(SHOULD_SWITCH_ATTACKING_STAT_MINUS_THREE_PLUS_PERCENTAGE, 100, RNG_AI_SWITCH_STATS_LOWERED);
|
||||
PARAMETRIZE {move = MOVE_GROWL; move2 = MOVE_CHARM; aiSpecies = SPECIES_FLAREON; aiMove = MOVE_FIRE_FANG; };
|
||||
PARAMETRIZE {move = MOVE_CONFIDE; move2 = MOVE_EERIE_IMPULSE; aiSpecies = SPECIES_ESPEON; aiMove = MOVE_STORED_POWER; };
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user