2017-02-02 05:15:38 +01:00
# include "global.h"
2019-10-10 16:18:48 +02:00
# include "malloc.h"
2017-02-04 03:34:56 +01:00
# include "battle.h"
2019-03-31 19:15:39 +02:00
# include "battle_anim.h"
2020-12-11 06:10:21 +01:00
# include "battle_ai_util.h"
2020-12-20 22:47:20 +01:00
# include "battle_ai_main.h"
2018-11-14 01:01:50 +01:00
# include "battle_factory.h"
2018-02-08 00:00:25 +01:00
# include "battle_setup.h"
2022-07-21 21:32:14 +02:00
# include "battle_z_move.h"
2019-04-04 23:53:06 +02:00
# include "data.h"
2021-07-27 17:49:39 +02:00
# include "event_data.h"
2017-09-05 09:41:48 +02:00
# include "item.h"
2018-11-14 01:01:50 +01:00
# include "pokemon.h"
# include "random.h"
# include "recorded_battle.h"
2018-11-11 16:44:27 +01:00
# include "util.h"
# include "constants/abilities.h"
2018-11-14 01:01:50 +01:00
# include "constants/battle_ai.h"
2017-12-05 18:55:48 +01:00
# include "constants/battle_move_effects.h"
2019-08-27 18:29:34 +02:00
# include "constants/hold_effects.h"
2017-12-11 19:27:51 +01:00
# include "constants/moves.h"
2020-12-20 05:58:23 +01:00
# include "constants/items.h"
2017-02-02 05:15:38 +01:00
2017-09-05 09:41:48 +02:00
# define AI_ACTION_DONE 0x0001
# define AI_ACTION_FLEE 0x0002
# define AI_ACTION_WATCH 0x0004
# define AI_ACTION_DO_NOT_ATTACK 0x0008
2017-02-04 03:34:56 +01:00
# define AI_ACTION_UNK5 0x0010
# define AI_ACTION_UNK6 0x0020
# define AI_ACTION_UNK7 0x0040
# define AI_ACTION_UNK8 0x0080
// AI states
enum
{
AIState_SettingUp ,
AIState_Processing ,
AIState_FinishedProcessing ,
AIState_DoNotProcess
} ;
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Singles ( void ) ;
static u8 ChooseMoveOrAction_Doubles ( void ) ;
2017-09-05 09:41:48 +02:00
static void BattleAI_DoAIProcessing ( void ) ;
2022-01-27 01:45:24 +01:00
static bool32 IsPinchBerryItemEffect ( u16 holdEffect ) ;
2017-09-05 09:41:48 +02:00
// ewram
2020-12-20 22:47:20 +01:00
EWRAM_DATA const u8 * gAIScriptPtr = NULL ; // Still used in contests
2020-12-11 16:05:00 +01:00
EWRAM_DATA u8 sBattler_AI = 0 ;
2017-09-05 09:41:48 +02:00
// const rom data
2020-12-20 05:58:23 +01:00
static s16 AI_CheckBadMove ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_TryToFaint ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
2021-01-05 03:39:59 +01:00
static s16 AI_CheckViability ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
2020-12-20 05:58:23 +01:00
static s16 AI_SetupFirstTurn ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_Risky ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_PreferStrongestMove ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_PreferBatonPass ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_HPAware ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_Roaming ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_Safari ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
static s16 AI_FirstBattle ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
2021-01-13 19:08:43 +01:00
static s16 AI_DoubleBattle ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score ) ;
2020-12-20 05:58:23 +01:00
static s16 ( * const sBattleAiFuncTable [ ] ) ( u8 , u8 , u16 , s16 ) =
2020-12-11 05:37:37 +01:00
{
2020-12-13 23:02:21 +01:00
[ 0 ] = AI_CheckBadMove , // AI_FLAG_CHECK_BAD_MOVE
[ 1 ] = AI_TryToFaint , // AI_FLAG_TRY_TO_FAINT
2021-01-05 03:39:59 +01:00
[ 2 ] = AI_CheckViability , // AI_FLAG_CHECK_VIABILITY
2020-12-13 23:02:21 +01:00
[ 3 ] = AI_SetupFirstTurn , // AI_FLAG_SETUP_FIRST_TURN
[ 4 ] = AI_Risky , // AI_FLAG_RISKY
[ 5 ] = AI_PreferStrongestMove , // AI_FLAG_PREFER_STRONGEST_MOVE
[ 6 ] = AI_PreferBatonPass , // AI_FLAG_PREFER_BATON_PASS
2021-08-12 01:33:10 +02:00
[ 7 ] = AI_DoubleBattle , // AI_FLAG_DOUBLE_BATTLE
2020-12-13 23:02:21 +01:00
[ 8 ] = AI_HPAware , // AI_FLAG_HP_AWARE
2020-12-20 22:47:20 +01:00
[ 9 ] = NULL , // AI_FLAG_NEGATE_UNAWARE
[ 10 ] = NULL , // AI_FLAG_WILL_SUICIDE
[ 11 ] = NULL , // AI_FLAG_HELP_PARTNER
2020-12-11 05:37:37 +01:00
[ 12 ] = NULL , // Unused
[ 13 ] = NULL , // Unused
[ 14 ] = NULL , // Unused
[ 15 ] = NULL , // Unused
[ 16 ] = NULL , // Unused
[ 17 ] = NULL , // Unused
[ 18 ] = NULL , // Unused
[ 19 ] = NULL , // Unused
[ 20 ] = NULL , // Unused
[ 21 ] = NULL , // Unused
[ 22 ] = NULL , // Unused
[ 23 ] = NULL , // Unused
[ 24 ] = NULL , // Unused
[ 25 ] = NULL , // Unused
[ 26 ] = NULL , // Unused
[ 27 ] = NULL , // Unused
2020-12-16 05:57:33 +01:00
[ 28 ] = NULL , // Unused
2020-12-13 23:02:21 +01:00
[ 29 ] = AI_Roaming , // AI_FLAG_ROAMING
[ 30 ] = AI_Safari , // AI_FLAG_SAFARI
[ 31 ] = AI_FirstBattle , // AI_FLAG_FIRST_BATTLE
2020-12-11 05:37:37 +01:00
} ;
2020-12-20 22:47:20 +01:00
// Functions
2018-12-22 20:57:12 +01:00
void BattleAI_SetupItems ( void )
2017-02-02 05:15:38 +01:00
{
s32 i ;
2018-06-17 16:48:58 +02:00
u8 * data = ( u8 * ) BATTLE_HISTORY ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
for ( i = 0 ; i < sizeof ( struct BattleHistory ) ; i + + )
2017-02-02 05:15:38 +01:00
data [ i ] = 0 ;
2018-06-17 16:48:58 +02:00
// Items are allowed to use in ONLY trainer battles.
if ( ( gBattleTypeFlags & BATTLE_TYPE_TRAINER )
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_BATTLE_TOWER
| BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_SECRET_BASE | BATTLE_TYPE_FRONTIER
2021-02-12 19:02:10 +01:00
| BATTLE_TYPE_INGAME_PARTNER | BATTLE_TYPE_RECORDED_LINK )
2018-06-17 16:48:58 +02:00
)
)
2017-02-02 05:15:38 +01:00
{
2019-09-08 18:21:24 +02:00
for ( i = 0 ; i < MAX_TRAINER_ITEMS ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
if ( gTrainers [ gTrainerBattleOpponent_A ] . items [ i ] ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
BATTLE_HISTORY - > trainerItems [ BATTLE_HISTORY - > itemsNo ] = gTrainers [ gTrainerBattleOpponent_A ] . items [ i ] ;
BATTLE_HISTORY - > itemsNo + + ;
2017-02-02 05:15:38 +01:00
}
}
}
2018-12-22 20:57:12 +01:00
}
2021-07-27 17:49:39 +02:00
static u32 GetWildAiFlags ( void )
{
u8 avgLevel = GetMonData ( & gEnemyParty [ 0 ] , MON_DATA_LEVEL ) ;
u32 flags ;
2022-08-24 21:56:24 +02:00
2021-07-27 17:49:39 +02:00
if ( IsDoubleBattle ( ) )
avgLevel = ( GetMonData ( & gEnemyParty [ 0 ] , MON_DATA_LEVEL ) + GetMonData ( & gEnemyParty [ 1 ] , MON_DATA_LEVEL ) ) / 2 ;
2022-08-24 21:56:24 +02:00
2021-07-27 17:53:47 +02:00
flags | = AI_FLAG_CHECK_BAD_MOVE ;
if ( avgLevel > = 20 )
2021-07-27 17:49:39 +02:00
flags | = AI_FLAG_CHECK_VIABILITY ;
2021-07-27 17:53:47 +02:00
if ( avgLevel > = 60 )
2021-07-27 17:49:39 +02:00
flags | = AI_FLAG_PREFER_STRONGEST_MOVE ;
2021-07-27 17:53:47 +02:00
if ( avgLevel > = 80 )
2021-07-27 17:49:39 +02:00
flags | = AI_FLAG_HP_AWARE ;
2022-08-24 03:00:08 +02:00
# if B_VAR_WILD_AI_FLAGS != 0
if ( VarGet ( B_VAR_WILD_AI_FLAGS ) ! = 0 )
2021-07-27 17:49:39 +02:00
flags | = VarGet ( B_VAR_WILD_AI_FLAGS ) ;
2022-08-24 03:00:08 +02:00
# endif
2022-08-24 21:56:24 +02:00
2021-07-27 17:49:39 +02:00
return flags ;
}
2018-12-22 20:57:12 +01:00
void BattleAI_SetupFlags ( void )
{
if ( gBattleTypeFlags & BATTLE_TYPE_RECORDED )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInRecordedBattle ( ) ;
else if ( gBattleTypeFlags & BATTLE_TYPE_SAFARI )
2020-12-13 23:02:21 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_FLAG_SAFARI ;
2018-12-22 20:57:12 +01:00
else if ( gBattleTypeFlags & BATTLE_TYPE_ROAMER )
2020-12-13 23:02:21 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_FLAG_ROAMING ;
2018-12-22 20:57:12 +01:00
else if ( gBattleTypeFlags & BATTLE_TYPE_FIRST_BATTLE )
2020-12-13 23:02:21 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_FLAG_FIRST_BATTLE ;
2018-12-22 20:57:12 +01:00
else if ( gBattleTypeFlags & BATTLE_TYPE_FACTORY )
AI_THINKING_STRUCT - > aiFlags = GetAiScriptsInBattleFactory ( ) ;
else if ( gBattleTypeFlags & ( BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE ) )
2021-01-05 03:39:59 +01:00
AI_THINKING_STRUCT - > aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT ;
2018-12-22 20:57:12 +01:00
else if ( gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS )
AI_THINKING_STRUCT - > aiFlags = gTrainers [ gTrainerBattleOpponent_A ] . aiFlags | gTrainers [ gTrainerBattleOpponent_B ] . aiFlags ;
else
AI_THINKING_STRUCT - > aiFlags = gTrainers [ gTrainerBattleOpponent_A ] . aiFlags ;
2022-08-24 21:56:24 +02:00
2021-07-27 17:49:39 +02:00
// check smart wild AI
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER ) ) & & IsWildMonSmart ( ) )
AI_THINKING_STRUCT - > aiFlags | = GetWildAiFlags ( ) ;
2017-09-04 21:43:13 +02:00
2018-12-22 21:43:21 +01:00
if ( gBattleTypeFlags & ( BATTLE_TYPE_DOUBLE | BATTLE_TYPE_TWO_OPPONENTS ) | | gTrainers [ gTrainerBattleOpponent_A ] . doubleBattle )
2020-12-13 23:02:21 +01:00
AI_THINKING_STRUCT - > aiFlags | = AI_FLAG_DOUBLE_BATTLE ; // Act smart in doubles and don't attack your partner.
2017-02-02 05:15:38 +01:00
}
2022-06-05 17:09:04 +02:00
// sBattler_AI set in ComputeBattleAiScores
2017-09-05 09:41:48 +02:00
void BattleAI_SetupAIData ( u8 defaultScoreMoves )
2017-02-02 05:15:38 +01:00
{
2019-08-27 18:29:34 +02:00
s32 i , move , dmg ;
2017-09-05 09:41:48 +02:00
u8 moveLimitations ;
2017-02-04 03:34:56 +01:00
2018-12-22 20:57:12 +01:00
// Clear AI data but preserve the flags.
u32 flags = AI_THINKING_STRUCT - > aiFlags ;
memset ( AI_THINKING_STRUCT , 0 , sizeof ( struct AI_ThinkingStruct ) ) ;
AI_THINKING_STRUCT - > aiFlags = flags ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Conditional score reset, unlike Ruby.
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
if ( defaultScoreMoves & 1 )
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 100 ;
2017-02-02 05:15:38 +01:00
else
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 0 ;
2018-06-17 16:48:58 +02:00
2017-09-05 09:41:48 +02:00
defaultScoreMoves > > = 1 ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
2022-01-13 17:28:27 +01:00
moveLimitations = AI_DATA - > moveLimitations [ gActiveBattler ] ;
2017-02-04 03:34:56 +01:00
2018-06-17 16:48:58 +02:00
// Ignore moves that aren't possible to use.
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-05 09:41:48 +02:00
if ( gBitTable [ i ] & moveLimitations )
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > score [ i ] = 0 ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
2022-06-05 17:09:04 +02:00
//sBattler_AI = gActiveBattler;
2019-08-27 18:29:34 +02:00
gBattlerTarget = SetRandomTarget ( sBattler_AI ) ;
2022-06-05 17:09:04 +02:00
gBattleStruct - > aiChosenTarget [ sBattler_AI ] = gBattlerTarget ;
2017-02-02 05:15:38 +01:00
}
2017-09-05 09:41:48 +02:00
u8 BattleAI_ChooseMoveOrAction ( void )
2017-02-02 05:15:38 +01:00
{
2020-04-14 13:40:27 +02:00
u32 savedCurrentMove = gCurrentMove ;
2017-02-02 05:15:38 +01:00
u8 ret ;
2017-09-04 21:43:13 +02:00
2017-09-05 09:41:48 +02:00
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) )
2018-06-17 16:48:58 +02:00
ret = ChooseMoveOrAction_Singles ( ) ;
2017-02-02 05:15:38 +01:00
else
2018-06-17 16:48:58 +02:00
ret = ChooseMoveOrAction_Doubles ( ) ;
2022-08-24 21:56:24 +02:00
2021-10-13 16:11:02 +02:00
// Clear protect structures, some flags may be set during AI calcs
// e.g. pranksterElevated from GetMovePriority
2021-12-01 21:30:07 +01:00
memset ( & gProtectStructs , 0 , MAX_BATTLERS_COUNT * sizeof ( struct ProtectStruct ) ) ;
2022-08-24 21:56:24 +02:00
2017-09-05 09:41:48 +02:00
gCurrentMove = savedCurrentMove ;
2017-02-02 05:15:38 +01:00
return ret ;
}
2022-06-05 17:09:04 +02:00
// damages/other info computed in GetAIDataAndCalcDmg
u8 ComputeBattleAiScores ( u8 battler )
2020-12-17 06:56:10 +01:00
{
2022-06-05 17:09:04 +02:00
sBattler_AI = battler ;
BattleAI_SetupAIData ( 0xF ) ;
return BattleAI_ChooseMoveOrAction ( ) ;
}
static void SetBattlerAiData ( u8 battlerId )
{
AI_DATA - > abilities [ battlerId ] = AI_GetAbility ( battlerId ) ;
AI_DATA - > items [ battlerId ] = gBattleMons [ battlerId ] . item ;
AI_DATA - > holdEffects [ battlerId ] = AI_GetHoldEffect ( battlerId ) ;
AI_DATA - > holdEffectParams [ battlerId ] = GetBattlerHoldEffectParam ( battlerId ) ;
AI_DATA - > predictedMoves [ battlerId ] = gLastMoves [ battlerId ] ;
AI_DATA - > hpPercents [ battlerId ] = GetHealthPercentage ( battlerId ) ;
2022-08-24 04:38:35 +02:00
AI_DATA - > moveLimitations [ battlerId ] = CheckMoveLimitations ( battlerId , 0 , MOVE_LIMITATIONS_ALL ) ;
2022-06-05 17:09:04 +02:00
}
2022-01-13 17:28:27 +01:00
void GetAiLogicData ( void )
2020-12-17 06:56:10 +01:00
{
2022-01-13 17:28:27 +01:00
u32 battlerAtk , battlerDef , i , move ;
u8 effectiveness ;
s32 dmg ;
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
memset ( AI_DATA , 0 , sizeof ( struct AiLogicData ) ) ;
2022-08-24 21:56:24 +02:00
2022-07-05 19:19:03 +02:00
if ( ! ( gBattleTypeFlags & ( BATTLE_TYPE_TRAINER | BATTLE_TYPE_FIRST_BATTLE | BATTLE_TYPE_SAFARI | BATTLE_TYPE_ROAMER ) )
& & ! IsWildMonSmart ( ) )
2022-01-13 17:28:27 +01:00
return ;
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
// get/assume all battler data
for ( i = 0 ; i < gBattlersCount ; i + + )
2022-01-13 17:28:27 +01:00
{
2022-06-05 17:09:04 +02:00
if ( IsBattlerAlive ( i ) ) {
SetBattlerAiData ( i ) ;
}
}
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
// simulate AI damage
for ( battlerAtk = 0 ; battlerAtk < gBattlersCount ; battlerAtk + + )
{
if ( ! IsBattlerAlive ( battlerAtk )
| | ! IsBattlerAIControlled ( battlerAtk ) ) {
continue ;
}
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
for ( battlerDef = 0 ; battlerDef < gBattlersCount ; battlerDef + + )
{
if ( battlerAtk = = battlerDef )
continue ;
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
RecordKnownMove ( battlerDef , gLastMoves [ battlerDef ] ) ;
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
2022-01-13 17:28:27 +01:00
{
2022-06-05 17:09:04 +02:00
dmg = 0 ;
effectiveness = AI_EFFECTIVENESS_x0 ;
move = gBattleMons [ battlerAtk ] . moves [ i ] ;
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
if ( move ! = 0
& & move ! = 0xFFFF
//&& gBattleMoves[move].power != 0 /* we want to get effectiveness of status moves */
& & ! ( AI_DATA - > moveLimitations [ battlerAtk ] & gBitTable [ i ] ) ) {
2022-07-17 18:40:43 +02:00
dmg = AI_CalcDamage ( move , battlerAtk , battlerDef , & effectiveness , TRUE ) ;
2022-01-13 17:28:27 +01:00
}
2022-08-24 21:56:24 +02:00
2022-06-05 17:09:04 +02:00
AI_DATA - > simulatedDmg [ battlerAtk ] [ battlerDef ] [ i ] = dmg ;
AI_DATA - > effectiveness [ battlerAtk ] [ battlerDef ] [ i ] = effectiveness ;
2022-01-13 17:28:27 +01:00
}
}
}
2020-12-17 06:56:10 +01:00
}
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Singles ( void )
2017-02-02 05:15:38 +01:00
{
2019-09-08 17:53:48 +02:00
u8 currentMoveArray [ MAX_MON_MOVES ] ;
u8 consideredMoveArray [ MAX_MON_MOVES ] ;
2020-04-14 13:40:27 +02:00
u32 numOfBestMoves ;
2019-09-01 14:23:11 +02:00
s32 i , id ;
2018-12-22 20:57:12 +01:00
u32 flags = AI_THINKING_STRUCT - > aiFlags ;
2017-09-04 21:43:13 +02:00
2022-01-13 17:28:27 +01:00
AI_DATA - > partnerMove = 0 ; // no ally
2018-12-22 20:57:12 +01:00
while ( flags ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-22 20:57:12 +01:00
if ( flags & 1 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
2017-02-02 05:15:38 +01:00
BattleAI_DoAIProcessing ( ) ;
}
2018-12-22 20:57:12 +01:00
flags > > = 1 ;
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiLogicId + + ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
2021-10-19 13:39:07 +02:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + ) {
2020-04-14 13:40:27 +02:00
gBattleStruct - > aiFinalScore [ sBattler_AI ] [ gBattlerTarget ] [ i ] = AI_THINKING_STRUCT - > score [ i ] ;
2021-10-19 13:39:07 +02:00
}
2020-04-14 13:40:27 +02:00
2018-06-17 16:48:58 +02:00
// Check special AI actions.
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_FLEE )
2018-06-17 16:48:58 +02:00
return AI_CHOICE_FLEE ;
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_WATCH )
2018-06-17 16:48:58 +02:00
return AI_CHOICE_WATCH ;
2017-02-04 03:34:56 +01:00
2019-09-01 14:23:11 +02:00
gActiveBattler = sBattler_AI ;
2022-08-24 21:56:24 +02:00
2020-02-08 14:20:02 +01:00
// If can switch.
2020-12-20 05:58:23 +01:00
if ( CountUsablePartyMons ( sBattler_AI ) > 0
2020-02-08 14:20:02 +01:00
& & ! IsAbilityPreventingEscape ( sBattler_AI )
& & ! ( gBattleMons [ gActiveBattler ] . status2 & ( STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION ) )
& & ! ( gStatuses3 [ gActiveBattler ] & STATUS3_ROOTED )
& & ! ( gBattleTypeFlags & ( BATTLE_TYPE_ARENA | BATTLE_TYPE_PALACE ) )
2021-01-05 03:39:59 +01:00
& & AI_THINKING_STRUCT - > aiFlags & ( AI_FLAG_CHECK_VIABILITY | AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_PREFER_BATON_PASS ) )
2019-06-11 10:45:12 +02:00
{
2020-02-08 14:20:02 +01:00
// Consider switching if all moves are worthless to use.
if ( GetTotalBaseStat ( gBattleMons [ sBattler_AI ] . species ) > = 310 // Mon is not weak.
& & gBattleMons [ sBattler_AI ] . hp > = gBattleMons [ sBattler_AI ] . maxHP / 2 )
2019-06-11 10:45:12 +02:00
{
2021-01-05 03:39:59 +01:00
s32 cap = AI_THINKING_STRUCT - > aiFlags & ( AI_FLAG_CHECK_VIABILITY ) ? 95 : 93 ;
2020-02-08 14:20:02 +01:00
for ( i = 0 ; i < MAX_MON_MOVES ; i + + )
{
if ( AI_THINKING_STRUCT - > score [ i ] > cap )
break ;
}
2019-06-11 10:45:12 +02:00
2020-02-08 14:20:02 +01:00
if ( i = = MAX_MON_MOVES & & GetMostSuitableMonToSwitchInto ( ) ! = PARTY_SIZE )
{
AI_THINKING_STRUCT - > switchMon = TRUE ;
return AI_CHOICE_SWITCH ;
}
2019-06-11 10:45:12 +02:00
}
2020-02-08 14:20:02 +01:00
// Consider switching if your mon with truant is bodied by Protect spam.
// Or is using a double turn semi invulnerable move(such as Fly) and is faster.
if ( GetBattlerAbility ( sBattler_AI ) = = ABILITY_TRUANT
& & IsTruantMonVulnerable ( sBattler_AI , gBattlerTarget )
& & gDisableStructs [ sBattler_AI ] . truantCounter
& & gBattleMons [ sBattler_AI ] . hp > = gBattleMons [ sBattler_AI ] . maxHP / 2 )
2019-09-01 14:23:11 +02:00
{
2020-02-08 14:20:02 +01:00
if ( GetMostSuitableMonToSwitchInto ( ) ! = PARTY_SIZE )
{
AI_THINKING_STRUCT - > switchMon = TRUE ;
return AI_CHOICE_SWITCH ;
}
2019-09-01 14:23:11 +02:00
}
}
2022-08-24 21:56:24 +02:00
2017-02-04 03:34:56 +01:00
numOfBestMoves = 1 ;
currentMoveArray [ 0 ] = AI_THINKING_STRUCT - > score [ 0 ] ;
consideredMoveArray [ 0 ] = 0 ;
2018-12-25 18:50:15 +01:00
for ( i = 1 ; i < MAX_MON_MOVES ; i + + )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
if ( gBattleMons [ sBattler_AI ] . moves [ i ] ! = MOVE_NONE )
2017-02-02 05:15:38 +01:00
{
2018-06-17 16:48:58 +02:00
// In ruby, the order of these if statements is reversed.
2017-02-04 03:34:56 +01:00
if ( currentMoveArray [ 0 ] = = AI_THINKING_STRUCT - > score [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
currentMoveArray [ numOfBestMoves ] = AI_THINKING_STRUCT - > score [ i ] ;
consideredMoveArray [ numOfBestMoves + + ] = i ;
2017-02-02 05:15:38 +01:00
}
2017-02-04 03:34:56 +01:00
if ( currentMoveArray [ 0 ] < AI_THINKING_STRUCT - > score [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
numOfBestMoves = 1 ;
currentMoveArray [ 0 ] = AI_THINKING_STRUCT - > score [ i ] ;
consideredMoveArray [ 0 ] = i ;
2017-02-02 05:15:38 +01:00
}
}
}
2017-02-04 03:34:56 +01:00
return consideredMoveArray [ Random ( ) % numOfBestMoves ] ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
static u8 ChooseMoveOrAction_Doubles ( void )
2017-02-02 05:15:38 +01:00
{
2019-10-10 16:18:48 +02:00
s32 i , j ;
2018-12-22 20:57:12 +01:00
u32 flags ;
2019-09-08 17:53:48 +02:00
s16 bestMovePointsForTarget [ MAX_BATTLERS_COUNT ] ;
s8 mostViableTargetsArray [ MAX_BATTLERS_COUNT ] ;
u8 actionOrMoveIndex [ MAX_BATTLERS_COUNT ] ;
u8 mostViableMovesScores [ MAX_MON_MOVES ] ;
u8 mostViableMovesIndices [ MAX_MON_MOVES ] ;
2017-09-08 18:19:20 +02:00
s32 mostViableTargetsNo ;
s32 mostViableMovesNo ;
2017-10-09 13:41:07 +02:00
s16 mostMovePoints ;
2017-09-08 18:19:20 +02:00
2018-12-25 18:50:15 +01:00
for ( i = 0 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-02-02 05:15:38 +01:00
{
2018-02-06 23:09:39 +01:00
if ( i = = sBattler_AI | | gBattleMons [ i ] . hp = = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-05 15:31:01 +01:00
actionOrMoveIndex [ i ] = 0xFF ;
2017-09-08 18:19:20 +02:00
bestMovePointsForTarget [ i ] = - 1 ;
2017-02-02 05:15:38 +01:00
}
else
{
2017-09-08 18:19:20 +02:00
if ( gBattleTypeFlags & BATTLE_TYPE_PALACE )
2020-07-17 02:12:12 +02:00
BattleAI_SetupAIData ( gBattleStruct - > palaceFlags > > 4 ) ;
2017-02-02 05:15:38 +01:00
else
2021-01-13 06:45:02 +01:00
BattleAI_SetupAIData ( 0xF ) ;
2022-08-24 21:56:24 +02:00
2018-02-06 23:09:39 +01:00
gBattlerTarget = i ;
if ( ( i & BIT_SIDE ) ! = ( sBattler_AI & BIT_SIDE ) )
2017-09-05 09:41:48 +02:00
RecordLastUsedMoveByTarget ( ) ;
2017-10-09 13:41:07 +02:00
2022-01-13 17:28:27 +01:00
AI_DATA - > partnerMove = GetAllyChosenMove ( i ) ;
2017-09-08 18:19:20 +02:00
AI_THINKING_STRUCT - > aiLogicId = 0 ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2018-12-22 20:57:12 +01:00
flags = AI_THINKING_STRUCT - > aiFlags ;
while ( flags ! = 0 )
2017-02-02 05:15:38 +01:00
{
2018-12-22 20:57:12 +01:00
if ( flags & 1 )
2017-02-02 05:15:38 +01:00
{
2017-02-04 03:34:56 +01:00
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
2017-02-02 05:15:38 +01:00
BattleAI_DoAIProcessing ( ) ;
}
2018-12-22 20:57:12 +01:00
flags > > = 1 ;
2017-09-08 18:19:20 +02:00
AI_THINKING_STRUCT - > aiLogicId + + ;
AI_THINKING_STRUCT - > movesetIndex = 0 ;
2017-02-02 05:15:38 +01:00
}
2018-06-17 16:48:58 +02:00
2017-09-08 18:19:20 +02:00
if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_FLEE )
2018-06-17 16:48:58 +02:00
{
actionOrMoveIndex [ i ] = AI_CHOICE_FLEE ;
}
2017-09-08 18:19:20 +02:00
else if ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_WATCH )
2018-06-17 16:48:58 +02:00
{
actionOrMoveIndex [ i ] = AI_CHOICE_WATCH ;
}
2017-02-02 05:15:38 +01:00
else
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ 0 ] = AI_THINKING_STRUCT - > score [ 0 ] ;
mostViableMovesIndices [ 0 ] = 0 ;
mostViableMovesNo = 1 ;
2018-12-25 18:50:15 +01:00
for ( j = 1 ; j < MAX_MON_MOVES ; j + + )
2017-02-02 05:15:38 +01:00
{
2018-02-06 23:09:39 +01:00
if ( gBattleMons [ sBattler_AI ] . moves [ j ] ! = 0 )
2017-02-02 05:15:38 +01:00
{
2022-05-07 15:56:32 +02:00
if ( ! CanTargetBattler ( sBattler_AI , i , gBattleMons [ sBattler_AI ] . moves [ j ] ) )
continue ;
2022-08-24 21:56:24 +02:00
2017-09-08 18:19:20 +02:00
if ( mostViableMovesScores [ 0 ] = = AI_THINKING_STRUCT - > score [ j ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ mostViableMovesNo ] = AI_THINKING_STRUCT - > score [ j ] ;
mostViableMovesIndices [ mostViableMovesNo ] = j ;
mostViableMovesNo + + ;
2017-02-02 05:15:38 +01:00
}
2017-09-08 18:19:20 +02:00
if ( mostViableMovesScores [ 0 ] < AI_THINKING_STRUCT - > score [ j ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableMovesScores [ 0 ] = AI_THINKING_STRUCT - > score [ j ] ;
mostViableMovesIndices [ 0 ] = j ;
mostViableMovesNo = 1 ;
2017-02-02 05:15:38 +01:00
}
}
}
2017-09-08 18:19:20 +02:00
actionOrMoveIndex [ i ] = mostViableMovesIndices [ Random ( ) % mostViableMovesNo ] ;
bestMovePointsForTarget [ i ] = mostViableMovesScores [ 0 ] ;
2018-06-17 16:48:58 +02:00
// Don't use a move against ally if it has less than 100 points.
2022-09-03 05:57:43 +02:00
if ( i = = BATTLE_PARTNER ( sBattler_AI ) & & bestMovePointsForTarget [ i ] < 100 )
2017-10-09 13:41:07 +02:00
{
2017-09-08 18:19:20 +02:00
bestMovePointsForTarget [ i ] = - 1 ;
2018-06-17 16:48:58 +02:00
mostViableMovesScores [ 0 ] = mostViableMovesScores [ 0 ] ; // Needed to match.
2017-10-09 13:41:07 +02:00
}
2017-02-02 05:15:38 +01:00
}
2020-04-14 13:40:27 +02:00
2021-10-19 13:39:07 +02:00
for ( j = 0 ; j < MAX_MON_MOVES ; j + + ) {
2020-04-14 13:40:27 +02:00
gBattleStruct - > aiFinalScore [ sBattler_AI ] [ gBattlerTarget ] [ j ] = AI_THINKING_STRUCT - > score [ j ] ;
2021-10-19 13:39:07 +02:00
}
2017-02-02 05:15:38 +01:00
}
}
2017-09-04 21:43:13 +02:00
2017-09-08 18:19:20 +02:00
mostMovePoints = bestMovePointsForTarget [ 0 ] ;
mostViableTargetsArray [ 0 ] = 0 ;
mostViableTargetsNo = 1 ;
2017-10-09 13:41:07 +02:00
2019-09-08 17:53:48 +02:00
for ( i = 1 ; i < MAX_BATTLERS_COUNT ; i + + )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
if ( mostMovePoints = = bestMovePointsForTarget [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostViableTargetsArray [ mostViableTargetsNo ] = i ;
mostViableTargetsNo + + ;
2017-02-02 05:15:38 +01:00
}
2017-09-08 18:19:20 +02:00
if ( mostMovePoints < bestMovePointsForTarget [ i ] )
2017-02-02 05:15:38 +01:00
{
2017-09-08 18:19:20 +02:00
mostMovePoints = bestMovePointsForTarget [ i ] ;
mostViableTargetsArray [ 0 ] = i ;
mostViableTargetsNo = 1 ;
2017-02-02 05:15:38 +01:00
}
}
2017-10-09 13:41:07 +02:00
2020-12-20 22:47:20 +01:00
gBattlerTarget = mostViableTargetsArray [ Random ( ) % mostViableTargetsNo ] ;
2022-06-05 17:09:04 +02:00
gBattleStruct - > aiChosenTarget [ sBattler_AI ] = gBattlerTarget ;
2020-12-20 22:47:20 +01:00
return actionOrMoveIndex [ gBattlerTarget ] ;
2020-07-15 21:30:24 +02:00
}
2020-07-26 13:48:25 +02:00
2020-12-20 22:47:20 +01:00
static void BattleAI_DoAIProcessing ( void )
2020-07-26 13:48:25 +02:00
{
2020-12-20 22:47:20 +01:00
while ( AI_THINKING_STRUCT - > aiState ! = AIState_FinishedProcessing )
2020-07-26 13:48:25 +02:00
{
2020-12-20 22:47:20 +01:00
switch ( AI_THINKING_STRUCT - > aiState )
{
case AIState_DoNotProcess : // Needed to match.
break ;
case AIState_SettingUp :
if ( gBattleMons [ sBattler_AI ] . pp [ AI_THINKING_STRUCT - > movesetIndex ] = = 0 )
{
AI_THINKING_STRUCT - > moveConsidered = 0 ;
}
else
{
AI_THINKING_STRUCT - > moveConsidered = gBattleMons [ sBattler_AI ] . moves [ AI_THINKING_STRUCT - > movesetIndex ] ;
}
AI_THINKING_STRUCT - > aiState + + ;
break ;
case AIState_Processing :
if ( AI_THINKING_STRUCT - > moveConsidered ! = MOVE_NONE
& & AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] > 0 )
{
if ( AI_THINKING_STRUCT - > aiLogicId < ARRAY_COUNT ( sBattleAiFuncTable )
& & sBattleAiFuncTable [ AI_THINKING_STRUCT - > aiLogicId ] ! = NULL )
{
// Call AI function
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] =
2021-01-13 19:08:43 +01:00
sBattleAiFuncTable [ AI_THINKING_STRUCT - > aiLogicId ] ( sBattler_AI ,
2020-12-20 22:47:20 +01:00
gBattlerTarget ,
AI_THINKING_STRUCT - > moveConsidered ,
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] ) ;
}
}
else
{
AI_THINKING_STRUCT - > score [ AI_THINKING_STRUCT - > movesetIndex ] = 0 ;
}
2020-07-26 13:48:25 +02:00
2020-12-20 22:47:20 +01:00
AI_THINKING_STRUCT - > movesetIndex + + ;
if ( AI_THINKING_STRUCT - > movesetIndex < MAX_MON_MOVES & & ! ( AI_THINKING_STRUCT - > aiAction & AI_ACTION_DO_NOT_ATTACK ) )
AI_THINKING_STRUCT - > aiState = AIState_SettingUp ;
else
AI_THINKING_STRUCT - > aiState + + ;
break ;
}
}
2020-07-26 13:48:25 +02:00
}
2020-12-11 05:37:37 +01:00
2020-12-20 22:47:20 +01:00
// AI Score Functions
// AI_FLAG_CHECK_BAD_MOVE - decreases move scores
2020-12-20 05:58:23 +01:00
static s16 AI_CheckBadMove ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-16 05:57:33 +01:00
{
2020-12-13 23:02:21 +01:00
// move data
2020-12-17 06:56:10 +01:00
u8 atkPriority = GetMovePriority ( battlerAtk , move ) ;
2020-12-13 23:02:21 +01:00
u16 moveEffect = gBattleMoves [ move ] . effect ;
2021-10-03 11:51:43 +02:00
s32 moveType ;
2022-04-27 12:23:20 +02:00
u16 moveTarget = AI_GetBattlerMoveTargetType ( battlerAtk , move ) ;
2022-06-05 17:09:04 +02:00
u16 accuracy = AI_GetMoveAccuracy ( battlerAtk , battlerDef , move ) ;
2022-07-03 22:20:05 +02:00
u32 effectiveness = AI_DATA - > effectiveness [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] ;
2020-12-20 05:58:23 +01:00
bool32 isDoubleBattle = IsValidDoubleBattle ( battlerAtk ) ;
u32 i ;
2022-01-13 17:28:27 +01:00
u16 predictedMove = AI_DATA - > predictedMoves [ battlerDef ] ;
2022-08-24 21:56:24 +02:00
2021-10-06 10:53:30 +02:00
SetTypeBeforeUsingMove ( move , battlerAtk ) ;
GET_MOVE_TYPE ( move , moveType ) ;
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
return score ;
2021-08-31 00:48:59 +02:00
2021-10-03 11:51:43 +02:00
GET_MOVE_TYPE ( move , moveType ) ;
2022-08-24 21:56:24 +02:00
2021-01-04 23:30:02 +01:00
// check non-user target
2022-04-27 11:51:10 +02:00
if ( ! ( moveTarget & MOVE_TARGET_USER ) )
2020-12-11 16:05:00 +01:00
{
2020-12-13 23:02:21 +01:00
// handle negative checks on non-user target
// check powder moves
2022-01-13 17:28:27 +01:00
if ( TestMoveFlags ( move , FLAG_POWDER ) & & ! IsAffectedByPowder ( battlerDef , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
{
2021-02-12 19:02:10 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
}
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// check ground immunities
if ( moveType = = TYPE_GROUND
& & ! IsBattlerGrounded ( battlerDef )
2022-01-13 17:28:27 +01:00
& & ( ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_LEVITATE
& & DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) )
| | AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_AIR_BALLOON
2020-12-13 23:02:21 +01:00
| | ( gStatuses3 [ battlerDef ] & ( STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS ) ) )
& & move ! = MOVE_THOUSAND_ARROWS )
2020-12-11 16:05:00 +01:00
{
2021-02-12 19:02:10 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-11 16:05:00 +01:00
}
2022-08-24 21:56:24 +02:00
2021-01-27 16:33:43 +01:00
// check off screen
2022-06-05 17:09:04 +02:00
if ( IsSemiInvulnerable ( battlerDef , move ) & & moveEffect ! = EFFECT_SEMI_INVULNERABLE & & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER )
2021-01-27 16:33:43 +01:00
RETURN_SCORE_MINUS ( 20 ) ; // if target off screen and we go first, don't use move
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// check if negates type
2021-01-27 16:33:43 +01:00
switch ( effectiveness )
2021-01-26 23:41:59 +01:00
{
2021-01-27 16:33:43 +01:00
case AI_EFFECTIVENESS_x0 :
RETURN_SCORE_MINUS ( 20 ) ;
break ;
2022-05-29 03:41:59 +02:00
case AI_EFFECTIVENESS_x0_125 :
2021-01-27 16:33:43 +01:00
case AI_EFFECTIVENESS_x0_25 :
RETURN_SCORE_MINUS ( 10 ) ;
break ;
2021-01-26 23:41:59 +01:00
}
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// target ability checks
2022-01-13 17:28:27 +01:00
if ( ! DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > abilities [ battlerDef ] )
2020-12-13 23:02:21 +01:00
{
2021-11-04 02:49:46 +01:00
case ABILITY_MAGIC_GUARD :
switch ( moveEffect )
{
case EFFECT_POISON :
case EFFECT_WILL_O_WISP :
case EFFECT_TOXIC :
case EFFECT_LEECH_SEED :
score - = 5 ;
break ;
case EFFECT_CURSE :
2021-11-04 02:53:28 +01:00
if ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GHOST ) ) // Don't use Curse if you're a ghost type vs a Magic Guard user, they'll take no damage.
2021-11-04 02:49:46 +01:00
score - = 5 ;
break ;
}
break ;
2020-12-13 23:02:21 +01:00
case ABILITY_VOLT_ABSORB :
case ABILITY_MOTOR_DRIVE :
case ABILITY_LIGHTNING_ROD :
2021-01-04 23:30:02 +01:00
if ( moveType = = TYPE_ELECTRIC )
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_WATER_ABSORB :
case ABILITY_DRY_SKIN :
case ABILITY_STORM_DRAIN :
2021-01-04 23:30:02 +01:00
if ( moveType = = TYPE_WATER )
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_FLASH_FIRE :
2021-01-04 23:30:02 +01:00
if ( moveType = = TYPE_FIRE )
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_WONDER_GUARD :
2022-05-29 03:41:59 +02:00
if ( effectiveness < AI_EFFECTIVENESS_x2 )
2020-12-13 23:02:21 +01:00
return 0 ;
break ;
case ABILITY_SAP_SIPPER :
2021-01-04 23:30:02 +01:00
if ( moveType = = TYPE_GRASS )
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_JUSTIFIED :
2021-01-04 23:30:02 +01:00
if ( moveType = = TYPE_DARK & & ! IS_MOVE_STATUS ( move ) )
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_RATTLED :
if ( ! IS_MOVE_STATUS ( move )
2021-01-04 23:30:02 +01:00
& & ( moveType = = TYPE_DARK | | moveType = = TYPE_GHOST | | moveType = = TYPE_BUG ) )
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_SOUNDPROOF :
if ( TestMoveFlags ( move , FLAG_SOUND ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_BULLETPROOF :
if ( TestMoveFlags ( move , FLAG_BALLISTIC ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_DAZZLING :
case ABILITY_QUEENLY_MAJESTY :
if ( atkPriority > 0 )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_AROMA_VEIL :
if ( IsAromaVeilProtectedMove ( move ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_SWEET_VEIL :
if ( moveEffect = = EFFECT_SLEEP | | moveEffect = = EFFECT_YAWN )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_FLOWER_VEIL :
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GRASS ) & & ( IsNonVolatileStatusMoveEffect ( moveEffect ) | | IsStatLoweringMoveEffect ( moveEffect ) ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_MAGIC_BOUNCE :
2021-01-13 19:08:43 +01:00
if ( TestMoveFlags ( move , FLAG_MAGIC_COAT_AFFECTED ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_CONTRARY :
2021-01-04 23:30:02 +01:00
if ( IsStatLoweringMoveEffect ( moveEffect ) )
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_CLEAR_BODY :
2021-01-04 23:30:02 +01:00
case ABILITY_FULL_METAL_BODY :
2020-12-13 23:02:21 +01:00
case ABILITY_WHITE_SMOKE :
if ( IsStatLoweringMoveEffect ( moveEffect ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_HYPER_CUTTER :
if ( ( moveEffect = = EFFECT_ATTACK_DOWN | | moveEffect = = EFFECT_ATTACK_DOWN_2 )
& & move ! = MOVE_PLAY_NICE & & move ! = MOVE_NOBLE_ROAR & & move ! = MOVE_TEARFUL_LOOK & & move ! = MOVE_VENOM_DRENCH )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_KEEN_EYE :
if ( moveEffect = = EFFECT_ACCURACY_DOWN | | moveEffect = = EFFECT_ACCURACY_DOWN_2 )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_BIG_PECKS :
if ( moveEffect = = EFFECT_DEFENSE_DOWN | | moveEffect = = EFFECT_DEFENSE_DOWN_2 )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_DEFIANT :
case ABILITY_COMPETITIVE :
if ( IsStatLoweringMoveEffect ( moveEffect ) & & ! IsTargetingPartner ( battlerAtk , battlerDef ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 8 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_COMATOSE :
if ( IsNonVolatileStatusMoveEffect ( moveEffect ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_SHIELDS_DOWN :
if ( IsShieldsDownProtected ( battlerAtk ) & & IsNonVolatileStatusMoveEffect ( moveEffect ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_LEAF_GUARD :
2021-11-21 19:40:26 +01:00
if ( AI_WeatherHasEffect ( ) & & ( gBattleWeather & B_WEATHER_SUN )
2022-01-13 17:28:27 +01:00
& & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_UTILITY_UMBRELLA
2020-12-13 23:02:21 +01:00
& & IsNonVolatileStatusMoveEffect ( moveEffect ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
} // def ability checks
2022-08-24 21:56:24 +02:00
2021-01-04 23:30:02 +01:00
// target partner ability checks & not attacking partner
if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > abilities [ BATTLE_PARTNER ( battlerDef ) ] )
2020-12-13 23:02:21 +01:00
{
case ABILITY_LIGHTNING_ROD :
2022-01-13 17:28:27 +01:00
if ( moveType = = TYPE_ELECTRIC & & ! IsMoveRedirectionPrevented ( move , AI_DATA - > abilities [ battlerAtk ] ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_STORM_DRAIN :
2022-01-13 17:28:27 +01:00
if ( moveType = = TYPE_WATER & & ! IsMoveRedirectionPrevented ( move , AI_DATA - > abilities [ battlerAtk ] ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_MAGIC_BOUNCE :
2021-01-13 19:08:43 +01:00
if ( TestMoveFlags ( move , FLAG_MAGIC_COAT_AFFECTED ) & & moveTarget & ( MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_OPPONENTS_FIELD ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_SWEET_VEIL :
if ( moveEffect = = EFFECT_SLEEP | | moveEffect = = EFFECT_YAWN )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_FLOWER_VEIL :
if ( ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GRASS ) ) & & ( IsNonVolatileStatusMoveEffect ( moveEffect ) | | IsStatLoweringMoveEffect ( moveEffect ) ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_AROMA_VEIL :
if ( IsAromaVeilProtectedMove ( move ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
case ABILITY_DAZZLING :
case ABILITY_QUEENLY_MAJESTY :
if ( atkPriority > 0 )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
break ;
}
} // def partner ability checks
} // ignore def ability check
2022-08-24 21:56:24 +02:00
2021-01-04 23:30:02 +01:00
// gen7+ dark type mons immune to priority->elevated moves from prankster
2022-07-24 11:47:21 +02:00
# if B_PRANKSTER_DARK_TYPES >= GEN_7
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_PRANKSTER & & IS_BATTLER_OF_TYPE ( battlerDef , TYPE_DARK ) & & IS_MOVE_STATUS ( move )
2020-12-13 23:02:21 +01:00
& & ! ( moveTarget & ( MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_USER ) ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 10 ) ;
2020-12-13 23:02:21 +01:00
# endif
2022-08-24 21:56:24 +02:00
2021-01-04 23:30:02 +01:00
// terrain & effect checks
2021-07-11 00:41:41 +02:00
if ( AI_IsTerrainAffected ( battlerDef , STATUS_FIELD_ELECTRIC_TERRAIN ) )
2020-12-13 23:02:21 +01:00
{
if ( moveEffect = = EFFECT_SLEEP | | moveEffect = = EFFECT_YAWN )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
}
2022-08-24 21:56:24 +02:00
2021-07-11 00:41:41 +02:00
if ( AI_IsTerrainAffected ( battlerDef , STATUS_FIELD_MISTY_TERRAIN ) )
2020-12-13 23:02:21 +01:00
{
if ( IsNonVolatileStatusMoveEffect ( moveEffect ) | | IsConfusionMoveEffect ( moveEffect ) )
2021-01-04 23:30:02 +01:00
RETURN_SCORE_MINUS ( 20 ) ;
2020-12-13 23:02:21 +01:00
}
2022-08-24 21:56:24 +02:00
2021-07-11 00:41:41 +02:00
if ( AI_IsTerrainAffected ( battlerAtk , STATUS_FIELD_PSYCHIC_TERRAIN ) & & atkPriority > 0 )
2020-12-13 23:02:21 +01:00
{
2021-07-11 00:41:41 +02:00
RETURN_SCORE_MINUS ( 20 ) ;
2021-01-04 23:30:02 +01:00
}
2020-12-13 23:02:21 +01:00
} // end check MOVE_TARGET_USER
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// the following checks apply to any target (including user)
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// throat chop check
if ( gDisableStructs [ battlerAtk ] . throatChopTimer & & TestMoveFlags ( move , FLAG_SOUND ) )
return 0 ; // Can't even select move at all
// heal block check
if ( gStatuses3 [ battlerAtk ] & STATUS3_HEAL_BLOCK & & IsHealBlockPreventingMove ( battlerAtk , move ) )
return 0 ; // Can't even select heal blocked move
// primal weather check
2021-08-31 00:48:59 +02:00
if ( WEATHER_HAS_EFFECT )
{
2021-11-21 19:40:26 +01:00
if ( gBattleWeather & B_WEATHER_PRIMAL_ANY )
2021-08-31 00:48:59 +02:00
{
switch ( move )
{
case MOVE_SUNNY_DAY :
case MOVE_RAIN_DANCE :
case MOVE_HAIL :
case MOVE_SANDSTORM :
RETURN_SCORE_MINUS ( 30 ) ;
}
}
if ( ! IS_MOVE_STATUS ( move ) )
{
2021-11-21 19:40:26 +01:00
if ( gBattleWeather & B_WEATHER_SUN_PRIMAL )
2021-08-31 00:48:59 +02:00
{
if ( moveType = = TYPE_WATER )
RETURN_SCORE_MINUS ( 30 ) ;
}
2021-11-21 19:40:26 +01:00
else if ( gBattleWeather & B_WEATHER_RAIN_PRIMAL )
2021-08-31 00:48:59 +02:00
{
if ( moveType = = TYPE_FIRE )
RETURN_SCORE_MINUS ( 30 ) ;
}
}
}
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
// check move effects
switch ( moveEffect )
{
case EFFECT_HIT :
default :
2021-01-04 23:30:02 +01:00
break ; // check move damage
2020-12-13 23:02:21 +01:00
case EFFECT_SLEEP :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanPutToSleep ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_EXPLOSION :
2021-01-04 23:30:02 +01:00
if ( ! ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_WILL_SUICIDE ) )
score - = 2 ;
2022-08-24 21:56:24 +02:00
2021-01-05 04:23:09 +01:00
if ( effectiveness = = AI_EFFECTIVENESS_x0 )
2020-12-13 23:02:21 +01:00
{
2021-01-04 23:30:02 +01:00
score - = 10 ;
2020-12-13 23:02:21 +01:00
}
2022-01-13 17:28:27 +01:00
else if ( IsAbilityOnField ( ABILITY_DAMP ) & & ! DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
2021-01-04 23:30:02 +01:00
else if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
2020-12-13 23:02:21 +01:00
{
2021-01-04 23:30:02 +01:00
if ( CountUsablePartyMons ( battlerDef ) ! = 0 )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2021-01-04 23:30:02 +01:00
else
score - - ;
2020-12-13 23:02:21 +01:00
}
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_DREAM_EATER :
2022-01-13 17:28:27 +01:00
if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP ) | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_COMATOSE )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2021-01-05 04:23:09 +01:00
else if ( effectiveness = = AI_EFFECTIVENESS_x0 )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
// stat raising effects
2020-12-13 23:02:21 +01:00
case EFFECT_ATTACK_UP :
case EFFECT_ATTACK_UP_2 :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2021-01-04 23:30:02 +01:00
break ;
2021-07-27 18:31:48 +02:00
case EFFECT_STUFF_CHEEKS :
if ( ItemId_GetPocket ( gBattleMons [ battlerAtk ] . item ) ! = POCKET_BERRIES )
return 0 ; // cannot even select
2021-01-04 23:30:02 +01:00
//fallthrough
case EFFECT_DEFENSE_UP :
2021-07-27 18:31:48 +02:00
case EFFECT_DEFENSE_UP_2 :
2021-01-04 23:30:02 +01:00
case EFFECT_DEFENSE_UP_3 :
case EFFECT_DEFENSE_CURL :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_SPECIAL_ATTACK_UP :
case EFFECT_SPECIAL_ATTACK_UP_2 :
case EFFECT_SPECIAL_ATTACK_UP_3 :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
2022-08-24 21:56:24 +02:00
case EFFECT_SPECIAL_DEFENSE_UP :
2021-01-04 23:30:02 +01:00
case EFFECT_SPECIAL_DEFENSE_UP_2 :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_ACCURACY_UP :
case EFFECT_ACCURACY_UP_2 :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ACC ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_EVASION_UP :
case EFFECT_EVASION_UP_2 :
case EFFECT_MINIMIZE :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_EVASION ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_COSMIC_POWER :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_BULK_UP :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_CALM_MIND :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_DRAGON_DANCE :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_COIL :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ACC ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 6 ;
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_ATTACK_ACCURACY_UP : //hone claws
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_CONTRARY )
2020-12-13 23:02:21 +01:00
{
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] > = MAX_STAT_STAGE
& & ( gBattleMons [ battlerAtk ] . statStages [ STAT_ACC ] > = MAX_STAT_STAGE | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) ) )
score - = 10 ;
break ;
}
else
{
score - = 10 ;
}
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_CHARGE :
if ( gStatuses3 [ battlerAtk ] & STATUS3_CHARGED_UP )
score - = 20 ;
else if ( ! HasMoveWithType ( battlerAtk , TYPE_ELECTRIC ) )
score - = 10 ;
2022-07-20 20:44:57 +02:00
# if B_CHARGE_SPDEF_RAISE >= GEN_5
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 5 ;
2022-07-20 20:44:57 +02:00
# endif
2020-12-13 23:02:21 +01:00
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_QUIVER_DANCE :
case EFFECT_GEOMANCY :
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ] > = MAX_STAT_STAGE | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 6 ;
2020-12-13 23:02:21 +01:00
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_SHIFT_GEAR :
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_SHELL_SMASH :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2020-12-13 23:02:21 +01:00
}
2021-01-04 23:30:02 +01:00
else
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 6 ;
2020-12-13 23:02:21 +01:00
}
break ;
case EFFECT_GROWTH :
case EFFECT_ATTACK_SPATK_UP : // work up
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_ROTOTILLER :
2020-12-20 05:58:23 +01:00
if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
if ( ! ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GRASS )
& & AI_IsBattlerGrounded ( battlerAtk )
2022-01-13 17:28:27 +01:00
& & ( BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) ) )
& & ! ( IS_BATTLER_OF_TYPE ( BATTLE_PARTNER ( battlerAtk ) , TYPE_GRASS )
& & AI_IsBattlerGrounded ( BATTLE_PARTNER ( battlerAtk ) )
& & AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] ! = ABILITY_CONTRARY
& & ( BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_ATK )
| | BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_SPATK ) ) ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
}
else if ( ! ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GRASS )
& & AI_IsBattlerGrounded ( battlerAtk )
2022-01-13 17:28:27 +01:00
& & ( BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) ) ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
break ;
case EFFECT_GEAR_UP :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_PLUS | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_MINUS )
2020-12-13 23:02:21 +01:00
{
2021-01-04 23:30:02 +01:00
// same as growth, work up
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 05:58:23 +01:00
else if ( ! isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; // no partner and our stats wont rise, so don't use
}
2020-12-20 05:58:23 +01:00
if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_PLUS | | AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_MINUS )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ( ! BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
& & ( ! BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_SPATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_PLUS & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MINUS )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; // nor our or our partner's ability is plus/minus
}
}
break ;
case EFFECT_ACUPRESSURE :
2021-01-04 23:30:02 +01:00
if ( DoesSubstituteBlockMove ( battlerAtk , battlerDef , move ) | | AreBattlersStatsMaxed ( battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_MAGNETIC_FLUX :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_PLUS | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_MINUS )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2020-12-13 23:02:21 +01:00
}
2021-01-04 23:30:02 +01:00
else if ( ! isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2021-01-04 23:30:02 +01:00
score - = 10 ; // our stats wont rise from this move
2020-12-13 23:02:21 +01:00
}
2021-01-04 23:30:02 +01:00
if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_PLUS | | AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_MINUS )
2021-01-04 23:30:02 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_PLUS & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MINUS )
2021-01-04 23:30:02 +01:00
{
score - = 10 ; // nor our or our partner's ability is plus/minus
}
2020-12-13 23:02:21 +01:00
}
break ;
2021-01-04 23:30:02 +01:00
// stat lowering effects
case EFFECT_ATTACK_DOWN :
case EFFECT_ATTACK_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ATK ) ) //|| !HasMoveWithSplit(battlerDef, SPLIT_PHYSICAL))
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_HYPER_CUTTER )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_DEFENSE_DOWN :
case EFFECT_DEFENSE_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_DEF ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SPEED_DOWN :
case EFFECT_SPEED_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_SPEED_BOOST )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SPECIAL_ATTACK_DOWN :
case EFFECT_SPECIAL_ATTACK_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPATK ) ) //|| !HasMoveWithSplit(battlerDef, SPLIT_SPECIAL))
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SPECIAL_DEFENSE_DOWN :
case EFFECT_SPECIAL_DEFENSE_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPDEF ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_ACCURACY_DOWN :
case EFFECT_ACCURACY_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ACC ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_KEEN_EYE )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_EVASION_DOWN :
case EFFECT_EVASION_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_EVASION ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_TICKLE :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ATK ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_VENOM_DRENCH :
if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_PSN_ANY ) )
{
2020-12-13 23:02:21 +01:00
score - = 10 ;
2021-01-04 23:30:02 +01:00
}
else
{
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPATK ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ATK ) )
2021-01-04 23:30:02 +01:00
score - = 6 ;
}
2020-12-13 23:02:21 +01:00
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_NOBLE_ROAR :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPATK ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ATK ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_CAPTIVATE :
{
u8 atkGender = GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerAtk ] . species , gBattleMons [ battlerAtk ] . personality ) ;
u8 defGender = GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerDef ] . species , gBattleMons [ battlerDef ] . personality ) ;
if ( atkGender = = MON_GENDERLESS | | defGender = = MON_GENDERLESS | | atkGender = = defGender )
score - = 10 ;
}
break ;
// other
2020-12-13 23:02:21 +01:00
case EFFECT_HAZE :
2022-01-13 17:28:27 +01:00
if ( PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; // partner already using haze
}
else
{
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerAtk ] . statStages [ i ] > DEFAULT_STAT_STAGE | | gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . statStages [ i ] > DEFAULT_STAT_STAGE )
2020-12-16 05:57:33 +01:00
score - = 10 ; // Don't want to reset our boosted stats
2020-12-13 23:02:21 +01:00
}
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ i ] < DEFAULT_STAT_STAGE | | gBattleMons [ BATTLE_PARTNER ( battlerDef ) ] . statStages [ i ] < DEFAULT_STAT_STAGE )
2020-12-16 05:57:33 +01:00
score - = 10 ; //Don't want to reset enemy lowered stats
2020-12-13 23:02:21 +01:00
}
}
break ;
2021-01-04 23:30:02 +01:00
//case EFFECT_BIDE:
//case EFFECT_SUPER_FANG:
//case EFFECT_RECHARGE:
case EFFECT_LEVEL_DAMAGE :
case EFFECT_PSYWAVE :
//case EFFECT_COUNTER:
//case EFFECT_FLAIL:
case EFFECT_RETURN :
case EFFECT_PRESENT :
case EFFECT_FRUSTRATION :
case EFFECT_SONICBOOM :
//case EFFECT_MIRROR_COAT:
case EFFECT_SKULL_BASH :
case EFFECT_FOCUS_PUNCH :
case EFFECT_SUPERPOWER :
//case EFFECT_ENDEAVOR:
case EFFECT_LOW_KICK :
// AI_CBM_HighRiskForDamage
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_WONDER_GUARD & & effectiveness < AI_EFFECTIVENESS_x2 )
2022-08-24 21:56:24 +02:00
score - = 10 ;
2021-01-04 23:30:02 +01:00
break ;
case EFFECT_COUNTER :
case EFFECT_MIRROR_COAT :
2022-01-13 17:28:27 +01:00
if ( IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) | | gBattleMons [ battlerDef ] . status2 & ( STATUS2_INFATUATION | STATUS2_CONFUSION ) )
2021-01-04 23:30:02 +01:00
score - - ;
if ( predictedMove = = MOVE_NONE | | GetBattleMoveSplit ( predictedMove ) = = SPLIT_STATUS
2022-01-13 17:28:27 +01:00
| | DoesSubstituteBlockMove ( battlerAtk , BATTLE_PARTNER ( battlerDef ) , predictedMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
2022-08-24 21:56:24 +02:00
2021-01-04 23:30:02 +01:00
case EFFECT_ROAR :
if ( CountUsablePartyMons ( battlerDef ) = = 0 )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_SUCTION_CUPS )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_TOXIC_THREAD :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_SPEED ) )
2021-01-04 23:30:02 +01:00
score - - ; // may still want to just poison
//fallthrough
case EFFECT_POISON :
case EFFECT_TOXIC :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanPoison ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_LIGHT_SCREEN :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_LIGHTSCREEN
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_REFLECT :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_REFLECT
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_AURORA_VEIL :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_AURORA_VEIL
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove )
2021-11-21 19:40:26 +01:00
| | ! ( gBattleWeather & B_WEATHER_HAIL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_OHKO :
2022-08-24 03:00:08 +02:00
# if B_SHEER_COLD_IMMUNITY >= GEN_7
if ( move = = MOVE_SHEER_COLD & & IS_BATTLER_OF_TYPE ( battlerDef , TYPE_ICE ) )
2021-11-26 17:49:49 +01:00
return 0 ;
2022-08-24 03:00:08 +02:00
# endif
2022-01-13 17:28:27 +01:00
if ( ! ShouldTryOHKO ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , move ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_MIST :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_MIST
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_FOCUS_ENERGY :
if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_FOCUS_ENERGY )
score - = 10 ;
break ;
case EFFECT_CONFUSE :
case EFFECT_SWAGGER :
case EFFECT_FLATTER :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanConfuse ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_PARALYZE :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanParalyze ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_SUBSTITUTE :
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_SUBSTITUTE | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_INFILTRATOR )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 25 )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-08-24 03:00:08 +02:00
# if B_SOUND_SUBSTITUTE >= GEN_6
else if ( TestMoveFlagsInMoveset ( battlerDef , FLAG_SOUND ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-08-24 03:00:08 +02:00
# endif
2021-01-04 23:30:02 +01:00
break ;
case EFFECT_LEECH_SEED :
if ( gStatuses3 [ battlerDef ] & STATUS3_LEECHSEED
| | IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GRASS )
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_LIQUID_OOZE )
2021-01-04 23:30:02 +01:00
score - = 3 ;
break ;
case EFFECT_DISABLE :
if ( gDisableStructs [ battlerDef ] . disableTimer = = 0
2022-08-24 03:00:08 +02:00
# if B_MENTAL_HERB >= GEN_5
& & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_MENTAL_HERB
# endif
& & ! PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker should go first
2021-01-04 23:30:02 +01:00
{
if ( gLastMoves [ battlerDef ] = = MOVE_NONE | | gLastMoves [ battlerDef ] = = 0xFFFF )
score - = 10 ; // no anticipated move to disable
}
else if ( predictedMove = = MOVE_NONE )
{
score - = 10 ;
}
}
else
{
score - = 10 ;
}
break ;
case EFFECT_ENCORE :
if ( gDisableStructs [ battlerDef ] . encoreTimer = = 0
2022-08-24 03:00:08 +02:00
# if B_MENTAL_HERB >= GEN_5
& & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_MENTAL_HERB
# endif
& & ! DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker should go first
2021-01-04 23:30:02 +01:00
{
if ( gLastMoves [ battlerDef ] = = MOVE_NONE | | gLastMoves [ battlerDef ] = = 0xFFFF )
score - = 10 ; // no anticipated move to encore
}
else if ( predictedMove = = MOVE_NONE )
{
score - = 10 ;
}
}
else
{
score - = 10 ;
}
break ;
case EFFECT_SNORE :
case EFFECT_SLEEP_TALK :
2022-01-13 17:28:27 +01:00
if ( IsWakeupTurn ( battlerAtk ) | | ( ! ( gBattleMons [ battlerAtk ] . status1 & STATUS1_SLEEP ) | | AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_COMATOSE ) )
2021-01-04 23:30:02 +01:00
score - = 10 ; // if mon will wake up, is not asleep, or is not comatose
break ;
case EFFECT_MEAN_LOOK :
2022-01-13 17:28:27 +01:00
if ( IsBattlerTrapped ( battlerDef , TRUE ) | | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_NIGHTMARE :
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_NIGHTMARE )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP ) | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_COMATOSE )
2021-01-04 23:30:02 +01:00
score - = 8 ;
2022-01-13 17:28:27 +01:00
else if ( DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_CURSE :
if ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GHOST ) )
{
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_CURSED
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 50 )
2021-01-04 23:30:02 +01:00
score - = 6 ;
}
else // regular curse
{
2022-01-13 17:28:27 +01:00
if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_ATK ) | | ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! BattlerStatCanRise ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , STAT_DEF ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
}
break ;
case EFFECT_SPIKES :
if ( gSideTimers [ GetBattlerSide ( battlerDef ) ] . spikesAmount > = 3 )
score - = 10 ;
2022-08-24 21:56:24 +02:00
else if ( PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove )
2021-01-04 23:30:02 +01:00
& & gSideTimers [ GetBattlerSide ( battlerDef ) ] . spikesAmount = = 2 )
score - = 10 ; // only one mon needs to set up the last layer of Spikes
break ;
case EFFECT_STEALTH_ROCK :
if ( gSideTimers [ GetBattlerSide ( battlerDef ) ] . stealthRockAmount > 0
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) ) //Only one mon needs to set up Stealth Rocks
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_TOXIC_SPIKES :
if ( gSideTimers [ GetBattlerSide ( battlerDef ) ] . toxicSpikesAmount > = 2 )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) & & gSideTimers [ GetBattlerSide ( battlerDef ) ] . toxicSpikesAmount = = 1 )
2021-01-04 23:30:02 +01:00
score - = 10 ; // only one mon needs to set up the last layer of Toxic Spikes
break ;
case EFFECT_STICKY_WEB :
if ( gSideTimers [ GetBattlerSide ( battlerDef ) ] . stickyWebAmount )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) & & gSideTimers [ GetBattlerSide ( battlerDef ) ] . stickyWebAmount )
2021-01-04 23:30:02 +01:00
score - = 10 ; // only one mon needs to set up Sticky Web
break ;
case EFFECT_FORESIGHT :
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_FORESIGHT )
score - = 10 ;
else if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] < = 4
| | ! ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GHOST ) )
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 9 ;
break ;
case EFFECT_PERISH_SONG :
if ( isDoubleBattle )
{
if ( CountUsablePartyMons ( battlerAtk ) = = 0
2022-01-13 17:28:27 +01:00
& & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_SOUNDPROOF
& & AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] ! = ABILITY_SOUNDPROOF
2021-01-04 23:30:02 +01:00
& & CountUsablePartyMons ( FOE ( battlerAtk ) ) > = 1 )
{
score - = 10 ; //Don't wipe your team if you're going to lose
}
2022-01-13 17:28:27 +01:00
else if ( ( ! IsBattlerAlive ( FOE ( battlerAtk ) ) | | AI_DATA - > abilities [ FOE ( battlerAtk ) ] = = ABILITY_SOUNDPROOF
2021-01-04 23:30:02 +01:00
| | gStatuses3 [ FOE ( battlerAtk ) ] & STATUS3_PERISH_SONG )
2022-01-13 17:28:27 +01:00
& & ( ! IsBattlerAlive ( BATTLE_PARTNER ( FOE ( battlerAtk ) ) ) | | AI_DATA - > abilities [ BATTLE_PARTNER ( FOE ( battlerAtk ) ) ] = = ABILITY_SOUNDPROOF
2021-01-04 23:30:02 +01:00
| | gStatuses3 [ BATTLE_PARTNER ( FOE ( battlerAtk ) ) ] & STATUS3_PERISH_SONG ) )
{
score - = 10 ; //Both enemies are perish songed
}
2022-01-13 17:28:27 +01:00
else if ( DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
{
score - = 10 ;
}
}
else
{
2022-01-13 17:28:27 +01:00
if ( CountUsablePartyMons ( battlerAtk ) = = 0 & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_SOUNDPROOF
2021-01-04 23:30:02 +01:00
& & CountUsablePartyMons ( battlerDef ) > = 1 )
score - = 10 ;
2022-01-13 17:28:27 +01:00
if ( gStatuses3 [ FOE ( battlerAtk ) ] & STATUS3_PERISH_SONG | | AI_DATA - > abilities [ FOE ( battlerAtk ) ] = = ABILITY_SOUNDPROOF )
2021-01-04 23:30:02 +01:00
score - = 10 ;
}
break ;
case EFFECT_SANDSTORM :
2021-12-04 02:30:45 +01:00
if ( gBattleWeather & ( B_WEATHER_SANDSTORM | B_WEATHER_PRIMAL_ANY )
2022-01-13 17:28:27 +01:00
| | PartnerMoveEffectIsWeather ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_SUNNY_DAY :
2021-12-04 02:30:45 +01:00
if ( gBattleWeather & ( B_WEATHER_SUN | B_WEATHER_PRIMAL_ANY )
2022-01-13 17:28:27 +01:00
| | PartnerMoveEffectIsWeather ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_RAIN_DANCE :
2021-12-04 02:30:45 +01:00
if ( gBattleWeather & ( B_WEATHER_RAIN | B_WEATHER_PRIMAL_ANY )
2022-01-13 17:28:27 +01:00
| | PartnerMoveEffectIsWeather ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_HAIL :
2021-12-04 02:30:45 +01:00
if ( gBattleWeather & ( B_WEATHER_HAIL | B_WEATHER_PRIMAL_ANY )
2022-01-13 17:28:27 +01:00
| | PartnerMoveEffectIsWeather ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 8 ;
break ;
case EFFECT_ATTRACT :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanBeInfatuated ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ,
2021-01-04 23:30:02 +01:00
GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerAtk ] . species , gBattleMons [ battlerAtk ] . personality ) ,
GetGenderFromSpeciesAndPersonality ( gBattleMons [ battlerDef ] . species , gBattleMons [ battlerDef ] . personality ) ) )
score - = 10 ;
break ;
case EFFECT_SAFEGUARD :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_SAFEGUARD
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_MAGNITUDE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_LEVITATE )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_PARTING_SHOT :
if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
score - = 10 ;
break ;
case EFFECT_BATON_PASS :
if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_SUBSTITUTE
| | ( gStatuses3 [ battlerAtk ] & ( STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK ) )
| | AnyStatIsRaised ( battlerAtk ) )
break ;
else
score - = 6 ;
break ;
case EFFECT_HIT_ESCAPE :
break ;
case EFFECT_RAPID_SPIN :
if ( ( gBattleMons [ battlerAtk ] . status2 & STATUS2_WRAPPED ) | | ( gStatuses3 [ battlerAtk ] & STATUS3_LEECHSEED ) )
break ; // check damage/accuracy
//Spin checks
if ( ! ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_HAZARDS_ANY ) )
score - = 6 ;
break ;
case EFFECT_BELLY_DRUM :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 60 )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_FUTURE_SIGHT :
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_FUTUREATTACK
| | gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_FUTUREATTACK )
score - = 12 ;
else
score + = 5 ;
break ;
case EFFECT_TELEPORT :
score - = 10 ;
break ;
case EFFECT_FAKE_OUT :
if ( ! gDisableStructs [ battlerAtk ] . isFirstTurn )
{
score - = 10 ;
}
else if ( move = = MOVE_FAKE_OUT ) // filter out first impression
{
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_CHOICE_BAND | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_GORILLA_TACTICS )
2021-11-08 08:37:28 +01:00
& & ( CountUsablePartyMons ( battlerDef ) > 0 | | ! CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) ) )
2021-01-04 23:30:02 +01:00
{
if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
score - = 10 ; // Don't lock the attacker into Fake Out if they can't switch out afterwards.
}
}
break ;
case EFFECT_STOCKPILE :
if ( gDisableStructs [ battlerAtk ] . stockpileCounter > = 3 )
score - = 10 ;
break ;
case EFFECT_SPIT_UP :
if ( gDisableStructs [ battlerAtk ] . stockpileCounter < = 1 )
score - = 10 ;
break ;
case EFFECT_SWALLOW :
if ( gDisableStructs [ battlerAtk ] . stockpileCounter = = 0 )
{
score - = 10 ;
}
else
{
if ( AtMaxHp ( battlerAtk ) )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > = 80 )
2021-01-04 23:30:02 +01:00
score - = 5 ; // do it if nothing better
}
break ;
case EFFECT_TORMENT :
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_TORMENT
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
{
score - = 10 ;
break ;
}
2022-08-24 03:00:08 +02:00
# if B_MENTAL_HERB >= GEN_5
if ( AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_MENTAL_HERB )
2021-01-04 23:30:02 +01:00
score - = 6 ;
2022-08-24 03:00:08 +02:00
# endif
2021-01-04 23:30:02 +01:00
break ;
case EFFECT_WILL_O_WISP :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanBurn ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_MEMENTO :
2022-01-13 17:28:27 +01:00
if ( CountUsablePartyMons ( battlerAtk ) = = 0 | | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] = = MIN_STAT_STAGE & & gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] = = MIN_STAT_STAGE )
score - = 10 ;
break ;
case EFFECT_FOLLOW_ME :
case EFFECT_HELPING_HAND :
if ( ! isDoubleBattle
2022-01-13 17:28:27 +01:00
| | ! IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) )
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove )
2021-01-04 23:30:02 +01:00
| | ( AI_DATA - > partnerMove ! = MOVE_NONE & & IS_MOVE_STATUS ( AI_DATA - > partnerMove ) )
2022-01-13 17:28:27 +01:00
| | * ( gBattleStruct - > monToSwitchIntoId + BATTLE_PARTNER ( battlerAtk ) ) ! = PARTY_SIZE ) //Partner is switching out.
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_TRICK :
case EFFECT_KNOCK_OFF :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_STICKY_HOLD )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_INGRAIN :
if ( gStatuses3 [ battlerAtk ] & STATUS3_ROOTED )
score - = 10 ;
break ;
case EFFECT_AQUA_RING :
if ( gStatuses3 [ battlerAtk ] & STATUS3_AQUA_RING )
score - = 10 ;
break ;
case EFFECT_RECYCLE :
2021-10-28 23:52:52 +02:00
if ( GetUsedHeldItem ( battlerAtk ) = = 0 | | gBattleMons [ battlerAtk ] . item ! = 0 )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_IMPRISON :
if ( gStatuses3 [ battlerAtk ] & STATUS3_IMPRISONED_OTHERS )
score - = 10 ;
break ;
case EFFECT_REFRESH :
if ( ! ( gBattleMons [ battlerDef ] . status1 & ( STATUS1_PSN_ANY | STATUS1_BURN | STATUS1_PARALYSIS ) ) )
score - = 10 ;
break ;
case EFFECT_PSYCHO_SHIFT :
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PSN_ANY & & ! AI_CanPoison ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN & & ! AI_CanBurn ( battlerAtk , battlerDef ,
2022-01-13 17:28:27 +01:00
AI_DATA - > abilities [ battlerDef ] , BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PARALYSIS & & ! AI_CanParalyze ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_SLEEP & & ! AI_CanPutToSleep ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
else
score - = 10 ; // attacker has no status to transmit
break ;
case EFFECT_MUD_SPORT :
if ( gFieldStatuses & STATUS_FIELD_MUDSPORT
2021-11-24 03:20:32 +01:00
| | gStatuses4 [ battlerAtk ] & STATUS4_MUD_SPORT
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_WATER_SPORT :
if ( gFieldStatuses & STATUS_FIELD_WATERSPORT
2021-11-24 03:20:32 +01:00
| | gStatuses4 [ battlerAtk ] & STATUS4_WATER_SPORT
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_ABSORB :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_LIQUID_OOZE )
2021-01-04 23:30:02 +01:00
score - = 6 ;
break ;
case EFFECT_STRENGTH_SAP :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_CONTRARY )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! ShouldLowerStat ( battlerDef , AI_DATA - > abilities [ battlerDef ] , STAT_ATK ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_COPYCAT :
case EFFECT_MIRROR_MOVE :
return AI_CheckBadMove ( battlerAtk , battlerDef , predictedMove , score ) ;
case EFFECT_FLOWER_SHIELD :
if ( ! IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GRASS )
2022-01-13 17:28:27 +01:00
& & ! ( isDoubleBattle & & IS_BATTLER_OF_TYPE ( BATTLE_PARTNER ( battlerAtk ) , TYPE_GRASS ) ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
case EFFECT_AROMATIC_MIST :
2022-01-13 17:28:27 +01:00
if ( ! isDoubleBattle | | gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . hp = = 0 | | ! BattlerStatCanRise ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] , STAT_SPDEF ) )
2021-01-04 23:30:02 +01:00
score - = 10 ;
break ;
2020-12-13 23:02:21 +01:00
case EFFECT_BIDE :
2020-12-20 05:58:23 +01:00
if ( ! HasDamagingMove ( battlerDef )
2022-01-13 17:28:27 +01:00
| | AI_DATA - > hpPercents [ battlerAtk ] < 30 //Close to death
2020-12-13 23:02:21 +01:00
| | gBattleMons [ battlerDef ] . status1 & ( STATUS1_SLEEP | STATUS1_FREEZE ) ) //No point in biding if can't take damage
score - = 10 ;
break ;
case EFFECT_HIT_SWITCH_TARGET :
2022-01-13 17:28:27 +01:00
if ( DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ; // don't scare away pokemon twice
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerDef ] < 10 & & GetBattlerSecondaryDamage ( battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ; // don't blow away mon that will faint soon
else if ( gStatuses3 [ battlerDef ] & STATUS3_PERISH_SONG )
score - = 10 ;
break ;
case EFFECT_CONVERSION :
//Check first move type
if ( IS_BATTLER_OF_TYPE ( battlerAtk , gBattleMoves [ gBattleMons [ battlerAtk ] . moves [ 0 ] ] . type ) )
score - = 10 ;
break ;
case EFFECT_REST :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanSleep ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score - = 10 ;
//fallthrough
case EFFECT_RESTORE_HP :
case EFFECT_SOFTBOILED :
case EFFECT_ROOST :
if ( AtMaxHp ( battlerAtk ) )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > = 90 )
2020-12-20 05:58:23 +01:00
score - = 9 ; //No point in healing, but should at least do it if nothing better
break ;
2020-12-13 23:02:21 +01:00
case EFFECT_MORNING_SUN :
2020-12-20 05:58:23 +01:00
case EFFECT_SYNTHESIS :
case EFFECT_MOONLIGHT :
2021-11-21 19:40:26 +01:00
if ( AI_WeatherHasEffect ( ) & & ( gBattleWeather & ( B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL ) ) )
2020-12-20 05:58:23 +01:00
score - = 3 ;
else if ( AtMaxHp ( battlerAtk ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > = 90 )
2020-12-13 23:02:21 +01:00
score - = 9 ; //No point in healing, but should at least do it if nothing better
break ;
case EFFECT_PURIFY :
if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_ANY ) )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( battlerDef = = BATTLE_PARTNER ( battlerAtk ) )
2020-12-13 23:02:21 +01:00
break ; //Always heal your ally
2020-12-20 05:58:23 +01:00
else if ( AtMaxHp ( battlerAtk ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > = 90 )
2020-12-13 23:02:21 +01:00
score - = 8 ; //No point in healing, but should at least do it if nothing better
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SUPER_FANG :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < 50 )
2020-12-20 05:58:23 +01:00
score - = 4 ;
break ;
2020-12-13 23:02:21 +01:00
case EFFECT_RECOIL_IF_MISS :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MAGIC_GUARD & & AI_GetMoveAccuracy ( battlerAtk , battlerDef , move ) < 75 )
2020-12-13 23:02:21 +01:00
score - = 6 ;
break ;
case EFFECT_RECOIL_25 :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MAGIC_GUARD & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_ROCK_HEAD )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
u32 recoilDmg = max ( 1 , AI_DATA - > simulatedDmg [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] / 4 ) ;
2020-12-13 23:02:21 +01:00
if ( ! ShouldUseRecoilMove ( battlerAtk , battlerDef , recoilDmg , AI_THINKING_STRUCT - > movesetIndex ) )
score - = 10 ;
break ;
}
break ;
case EFFECT_RECOIL_33 :
case EFFECT_RECOIL_33_STATUS :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MAGIC_GUARD & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_ROCK_HEAD )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
u32 recoilDmg = max ( 1 , AI_DATA - > simulatedDmg [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] / 3 ) ;
2020-12-13 23:02:21 +01:00
if ( ! ShouldUseRecoilMove ( battlerAtk , battlerDef , recoilDmg , AI_THINKING_STRUCT - > movesetIndex ) )
score - = 10 ;
break ;
}
break ;
case EFFECT_RECOIL_50 :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MAGIC_GUARD & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_ROCK_HEAD )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
u32 recoilDmg = max ( 1 , AI_DATA - > simulatedDmg [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] / 2 ) ;
2020-12-13 23:02:21 +01:00
if ( ! ShouldUseRecoilMove ( battlerAtk , battlerDef , recoilDmg , AI_THINKING_STRUCT - > movesetIndex ) )
score - = 10 ;
break ;
}
break ;
case EFFECT_TEETER_DANCE :
if ( ( ( gBattleMons [ battlerDef ] . status2 & STATUS2_CONFUSION )
2022-01-13 17:28:27 +01:00
| | ( ! DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) & & AI_DATA - > abilities [ battlerDef ] = = ABILITY_OWN_TEMPO )
2021-07-11 00:41:41 +02:00
| | ( IsBattlerGrounded ( battlerDef ) & & AI_IsTerrainAffected ( battlerDef , STATUS_FIELD_MISTY_TERRAIN ) )
2020-12-13 23:02:21 +01:00
| | ( DoesSubstituteBlockMove ( battlerAtk , battlerDef , move ) ) )
2022-01-13 17:28:27 +01:00
& & ( ( gBattleMons [ BATTLE_PARTNER ( battlerDef ) ] . status2 & STATUS2_CONFUSION )
| | ( ! DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) & & AI_DATA - > abilities [ BATTLE_PARTNER ( battlerDef ) ] = = ABILITY_OWN_TEMPO )
| | ( IsBattlerGrounded ( BATTLE_PARTNER ( battlerDef ) ) & & AI_IsTerrainAffected ( BATTLE_PARTNER ( battlerDef ) , STATUS_FIELD_MISTY_TERRAIN ) )
| | ( DoesSubstituteBlockMove ( battlerAtk , BATTLE_PARTNER ( battlerDef ) , move ) ) ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
break ;
case EFFECT_TRANSFORM :
if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_TRANSFORMED
| | ( gBattleMons [ battlerDef ] . status2 & ( STATUS2_TRANSFORMED | STATUS2_SUBSTITUTE ) ) ) //Leave out Illusion b/c AI is supposed to be fooled
score - = 10 ;
break ;
case EFFECT_TWO_TURNS_ATTACK :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] ! = HOLD_EFFECT_POWER_HERB & & CanTargetFaintAi ( battlerDef , battlerAtk ) )
2020-12-13 23:02:21 +01:00
score - = 6 ;
break ;
case EFFECT_RECHARGE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_WONDER_GUARD & & effectiveness < AI_EFFECTIVENESS_x2 )
2021-01-04 23:30:02 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_TRUANT
2021-11-08 08:37:28 +01:00
& & ! CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) )
2020-12-13 23:02:21 +01:00
score - = 2 ;
break ;
case EFFECT_SPITE :
case EFFECT_MIMIC :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker should go first
2020-12-13 23:02:21 +01:00
{
if ( gLastMoves [ battlerDef ] = = MOVE_NONE
| | gLastMoves [ battlerDef ] = = 0xFFFF )
score - = 10 ;
}
2020-12-20 05:58:23 +01:00
else if ( predictedMove = = MOVE_NONE )
{
// TODO predicted move separate from gLastMoves
score - = 10 ;
}
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_METRONOME :
break ;
case EFFECT_ENDEAVOR :
case EFFECT_PAIN_SPLIT :
if ( gBattleMons [ battlerAtk ] . hp > ( gBattleMons [ battlerAtk ] . hp + gBattleMons [ battlerDef ] . hp ) / 2 )
score - = 10 ;
break ;
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
case EFFECT_CONVERSION_2 :
//TODO
break ;
case EFFECT_LOCK_ON :
if ( gStatuses3 [ battlerDef ] & STATUS3_ALWAYS_HITS
2022-01-13 17:28:27 +01:00
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_NO_GUARD
| | AI_DATA - > abilities [ battlerDef ] = = ABILITY_NO_GUARD
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_LASER_FOCUS :
if ( gStatuses3 [ battlerAtk ] & STATUS3_LASER_FOCUS )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_SHELL_ARMOR | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_BATTLE_ARMOR )
2020-12-13 23:02:21 +01:00
score - = 8 ;
break ;
case EFFECT_SKETCH :
if ( gLastMoves [ battlerDef ] = = MOVE_NONE )
score - = 10 ;
break ;
case EFFECT_DESTINY_BOND :
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_DESTINY_BOND )
score - = 10 ;
break ;
case EFFECT_FALSE_SWIPE :
// TODO
break ;
case EFFECT_HEAL_BELL :
2022-01-13 17:28:27 +01:00
if ( ! AnyPartyMemberStatused ( battlerAtk , TestMoveFlags ( move , FLAG_SOUND ) ) | | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_HIT_PREVENT_ESCAPE :
break ;
case EFFECT_ENDURE :
2020-12-20 05:58:23 +01:00
if ( gBattleMons [ battlerAtk ] . hp = = 1 | | GetBattlerSecondaryDamage ( battlerAtk ) ) //Don't use Endure if you'll die after using it
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_PROTECT :
{
bool32 decreased = FALSE ;
switch ( move )
{
case MOVE_QUICK_GUARD :
case MOVE_WIDE_GUARD :
case MOVE_CRAFTY_SHIELD :
2020-12-20 05:58:23 +01:00
if ( ! isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
decreased = TRUE ;
}
break ;
case MOVE_MAT_BLOCK :
if ( ! gDisableStructs [ battlerAtk ] . isFirstTurn )
{
score - = 10 ;
decreased = TRUE ;
}
break ;
} // move check
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
if ( decreased )
break ;
2022-01-13 17:28:27 +01:00
if ( IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
break ;
}
2021-01-13 06:45:02 +01:00
if ( move ! = MOVE_QUICK_GUARD
2020-12-13 23:02:21 +01:00
& & move ! = MOVE_WIDE_GUARD
& & move ! = MOVE_CRAFTY_SHIELD ) //These moves have infinite usage
{
2021-01-13 06:45:02 +01:00
if ( GetBattlerSecondaryDamage ( battlerAtk ) > = gBattleMons [ battlerAtk ] . hp
2022-01-13 17:28:27 +01:00
& & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_MOXIE
& & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_BEAST_BOOST )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; //Don't protect if you're going to faint after protecting
}
else if ( gDisableStructs [ battlerAtk ] . protectUses = = 1 & & Random ( ) % 100 < 50 )
{
2020-12-20 05:58:23 +01:00
if ( ! isDoubleBattle )
2020-12-13 23:02:21 +01:00
score - = 6 ;
else
score - = 10 ; //Don't try double protecting in doubles
}
else if ( gDisableStructs [ battlerAtk ] . protectUses > = 2 )
{
score - = 10 ;
}
}
2021-01-04 23:30:02 +01:00
/*if (AI_THINKING_STRUCT->aiFlags == AI_SCRIPT_CHECK_BAD_MOVE //Only basic AI
& & IS_DOUBLE_BATTLE ) //Make the regular AI know how to use Protect minimally in Doubles
{
u8 shouldProtect = ShouldProtect ( battlerAtk , battlerDef , move ) ;
if ( shouldProtect = = USE_PROTECT | | shouldProtect = = PROTECT_FROM_FOES )
IncreaseFoeProtectionViability ( & viability , 0xFF , battlerAtk , battlerDef ) ;
else if ( shouldProtect = = PROTECT_FROM_ALLIES )
IncreaseAllyProtectionViability ( & viability , 0xFF ) ;
} */
2020-12-13 23:02:21 +01:00
}
2022-08-24 21:56:24 +02:00
break ;
2021-01-04 23:30:02 +01:00
case EFFECT_MIRACLE_EYE :
if ( gStatuses3 [ battlerDef ] & STATUS3_MIRACLE_EYED )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2021-01-04 23:30:02 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] < = 4
| | ! ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_DARK ) )
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2021-01-04 23:30:02 +01:00
score - = 9 ;
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_BURN_UP :
if ( ! IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_FIRE ) )
score - = 10 ;
break ;
case EFFECT_DEFOG :
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ]
& ( SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST )
| | gSideTimers [ GetBattlerSide ( battlerDef ) ] . auroraVeilTimer ! = 0
2020-12-20 05:58:23 +01:00
| | gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_HAZARDS_ANY )
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; //Only need one hazards removal
break ;
}
}
2020-12-20 05:58:23 +01:00
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_HAZARDS_ANY )
2020-12-13 23:02:21 +01:00
{
score - = 10 ; //Don't blow away opposing hazards
break ;
}
2020-12-20 05:58:23 +01:00
if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2020-12-17 06:56:10 +01:00
if ( IsHazardMoveEffect ( gBattleMoves [ AI_DATA - > partnerMove ] . effect ) // partner is going to set up hazards
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( BATTLE_PARTNER ( battlerAtk ) , battlerAtk , AI_DATA - > partnerMove ) = = AI_IS_FASTER ) // partner is going to set up before the potential Defog
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
break ; // Don't use Defog if partner is going to set up hazards
}
}
// evasion check
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] = = MIN_STAT_STAGE
2022-01-13 17:28:27 +01:00
| | ( ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_CONTRARY ) & & ! IsTargetingPartner ( battlerAtk , battlerDef ) ) ) // don't want to raise target stats unless its your partner
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
case EFFECT_PSYCH_UP : // haze stats check
{
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerAtk ] . statStages [ i ] > DEFAULT_STAT_STAGE | | gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . statStages [ i ] > DEFAULT_STAT_STAGE )
2020-12-16 05:57:33 +01:00
score - = 10 ; // Don't want to reset our boosted stats
2020-12-13 23:02:21 +01:00
}
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ i ] < DEFAULT_STAT_STAGE | | gBattleMons [ BATTLE_PARTNER ( battlerDef ) ] . statStages [ i ] < DEFAULT_STAT_STAGE )
2020-12-16 05:57:33 +01:00
score - = 10 ; //Don't want to copy enemy lowered stats
2020-12-13 23:02:21 +01:00
}
}
break ;
case EFFECT_SPECTRAL_THIEF :
break ;
2021-11-21 19:40:26 +01:00
case EFFECT_SOLAR_BEAM :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_POWER_HERB
| | ( AI_WeatherHasEffect ( ) & & gBattleWeather & B_WEATHER_SUN & & AI_DATA - > holdEffects [ battlerAtk ] ! = HOLD_EFFECT_UTILITY_UMBRELLA ) )
2020-12-13 23:02:21 +01:00
break ;
if ( CanTargetFaintAi ( battlerDef , battlerAtk ) ) //Attacker can be knocked out
score - = 4 ;
break ;
case EFFECT_SEMI_INVULNERABLE :
2020-12-20 05:58:23 +01:00
if ( predictedMove ! = MOVE_NONE
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER
2020-12-13 23:02:21 +01:00
& & gBattleMoves [ predictedMove ] . effect = = EFFECT_SEMI_INVULNERABLE )
2020-12-20 05:58:23 +01:00
score - = 10 ; // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you
2020-12-13 23:02:21 +01:00
2022-01-13 17:28:27 +01:00
if ( BattlerWillFaintFromWeather ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] )
2020-12-13 23:02:21 +01:00
& & ( move = = MOVE_FLY | | move = = MOVE_BOUNCE ) )
score - = 10 ; // Attacker will faint while in the air
break ;
case EFFECT_HEALING_WISH : //healing wish, lunar dance
2022-01-13 17:28:27 +01:00
if ( CountUsablePartyMons ( battlerAtk ) = = 0 | | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( IsPartyFullyHealedExceptBattler ( battlerAtk ) )
score - = 10 ;
break ;
case EFFECT_FINAL_GAMBIT :
2022-01-13 17:28:27 +01:00
if ( CountUsablePartyMons ( battlerAtk ) = = 0 | | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_NATURE_POWER :
2020-12-16 05:57:33 +01:00
return AI_CheckBadMove ( battlerAtk , battlerDef , GetNaturePowerMove ( ) , score ) ;
2020-12-13 23:02:21 +01:00
case EFFECT_TAUNT :
if ( gDisableStructs [ battlerDef ] . tauntTimer > 0
2022-01-13 17:28:27 +01:00
| | DoesPartnerHaveSameMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - - ;
break ;
case EFFECT_BESTOW :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_NONE
2020-12-13 23:02:21 +01:00
| | ! CanBattlerGetOrLoseItem ( battlerAtk , gBattleMons [ battlerAtk ] . item ) ) // AI knows its own item
score - = 10 ;
break ;
case EFFECT_ROLE_PLAY :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = AI_DATA - > abilities [ battlerDef ]
| | AI_DATA - > abilities [ battlerDef ] = = ABILITY_NONE
| | IsRolePlayBannedAbilityAtk ( AI_DATA - > abilities [ battlerAtk ] )
| | IsRolePlayBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( IsAbilityOfRating ( AI_DATA - > abilities [ battlerAtk ] , 5 ) )
2020-12-20 05:58:23 +01:00
score - = 4 ;
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_WISH :
if ( gWishFutureKnock . wishCounter [ battlerAtk ] ! = 0 )
score - = 10 ;
break ;
case EFFECT_ASSIST :
2020-12-20 05:58:23 +01:00
if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
2020-12-13 23:02:21 +01:00
score - = 10 ; // no teammates to assist from
break ;
case EFFECT_MAGIC_COAT :
2021-01-13 19:08:43 +01:00
if ( ! TestMoveFlagsInMoveset ( battlerDef , FLAG_MAGIC_COAT_AFFECTED ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_BELCH :
2021-10-28 23:52:52 +02:00
if ( ItemId_GetPocket ( GetUsedHeldItem ( battlerAtk ) ) ! = POCKET_BERRIES )
2020-12-13 23:02:21 +01:00
score - = 10 ; // attacker has not consumed a berry
break ;
case EFFECT_YAWN :
if ( gStatuses3 [ battlerDef ] & STATUS3_YAWN )
score - = 10 ;
2022-01-13 17:28:27 +01:00
else if ( ! AI_CanPutToSleep ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SKILL_SWAP :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_NONE | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_NONE
| | IsSkillSwapBannedAbility ( AI_DATA - > abilities [ battlerAtk ] ) | | IsSkillSwapBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_WORRY_SEED :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_INSOMNIA
| | IsWorrySeedBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_GASTRO_ACID :
if ( gStatuses3 [ battlerDef ] & STATUS3_GASTRO_ACID
2022-01-13 17:28:27 +01:00
| | IsGastroAcidBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_ENTRAINMENT :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_NONE
| | IsEntrainmentBannedAbilityAttacker ( AI_DATA - > abilities [ battlerAtk ] )
| | IsEntrainmentTargetOrSimpleBeamBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_CORE_ENFORCER :
break ;
case EFFECT_SIMPLE_BEAM :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_SIMPLE
| | IsEntrainmentTargetOrSimpleBeamBannedAbility ( AI_DATA - > abilities [ battlerDef ] ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SNATCH :
if ( ! TestMoveFlagsInMoveset ( battlerDef , FLAG_SNATCH_AFFECTED )
2022-01-13 17:28:27 +01:00
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_POWER_TRICK :
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . defense > = gBattleMons [ battlerAtk ] . attack & & ! HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
score - = 10 ;
break ;
case EFFECT_POWER_SWAP : // Don't use if attacker's stat stages are higher than opponents
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] > = gBattleMons [ battlerDef ] . statStages [ STAT_ATK ]
& & gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ] > = gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] )
score - = 10 ;
break ;
case EFFECT_GUARD_SWAP : // Don't use if attacker's stat stages are higher than opponents
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ] > = gBattleMons [ battlerDef ] . statStages [ STAT_DEF ]
& & gBattleMons [ battlerAtk ] . statStages [ STAT_SPDEF ] > = gBattleMons [ battlerDef ] . statStages [ STAT_SPDEF ] )
score - = 10 ;
break ;
case EFFECT_SPEED_SWAP :
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else
{
if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM & & ( gBattleMons [ battlerAtk ] . speed < = gBattleMons [ battlerDef ] . speed ) )
score - = 10 ;
else if ( gBattleMons [ battlerAtk ] . speed > = gBattleMons [ battlerDef ] . speed )
score - = 10 ;
}
break ;
case EFFECT_HEART_SWAP :
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else
{
u32 atkPositiveStages = CountPositiveStatStages ( battlerAtk ) ;
u32 atkNegativeStages = CountNegativeStatStages ( battlerAtk ) ;
u32 defPositiveStages = CountPositiveStatStages ( battlerDef ) ;
u32 defNegativeStages = CountNegativeStatStages ( battlerDef ) ;
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
if ( atkPositiveStages > = defPositiveStages & & atkNegativeStages < = defNegativeStages )
score - = 10 ;
break ;
}
break ;
case EFFECT_POWER_SPLIT :
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else
{
u8 atkAttack = gBattleMons [ battlerAtk ] . attack ;
u8 defAttack = gBattleMons [ battlerDef ] . attack ;
u8 atkSpAttack = gBattleMons [ battlerAtk ] . spAttack ;
u8 defSpAttack = gBattleMons [ battlerDef ] . spAttack ;
if ( atkAttack + atkSpAttack > = defAttack + defSpAttack ) // Combined attacker stats are > than combined target stats
score - = 10 ;
break ;
}
break ;
case EFFECT_GUARD_SPLIT :
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else
{
u8 atkDefense = gBattleMons [ battlerAtk ] . defense ;
u8 defDefense = gBattleMons [ battlerDef ] . defense ;
u8 atkSpDefense = gBattleMons [ battlerAtk ] . spDefense ;
u8 defSpDefense = gBattleMons [ battlerDef ] . spDefense ;
if ( atkDefense + atkSpDefense > = defDefense + defSpDefense ) //Combined attacker stats are > than combined target stats
score - = 10 ;
break ;
}
break ;
case EFFECT_ME_FIRST :
2020-12-20 05:58:23 +01:00
if ( predictedMove ! = MOVE_NONE )
2020-12-13 23:02:21 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER )
2020-12-20 05:58:23 +01:00
score - = 10 ; // Target is predicted to go first, Me First will fail
2020-12-13 23:02:21 +01:00
else
2020-12-20 05:58:23 +01:00
return AI_CheckBadMove ( battlerAtk , battlerDef , predictedMove , score ) ;
}
else
{
score - = 10 ; //Target is predicted to switch most likely
2020-12-13 23:02:21 +01:00
}
break ;
case EFFECT_NATURAL_GIFT :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_KLUTZ
2020-12-13 23:02:21 +01:00
| | gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
| | GetPocketByItemId ( gBattleMons [ battlerAtk ] . item ) ! = POCKET_BERRIES )
score - = 10 ;
break ;
case EFFECT_GRASSY_TERRAIN :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveEffectIsTerrain ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) | | gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_ELECTRIC_TERRAIN :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveEffectIsTerrain ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) | | gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_PSYCHIC_TERRAIN :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveEffectIsTerrain ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) | | gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_MISTY_TERRAIN :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveEffectIsTerrain ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) | | gFieldStatuses & STATUS_FIELD_MISTY_TERRAIN )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_PLEDGE :
2022-01-13 17:28:27 +01:00
if ( isDoubleBattle & & gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . hp > 0 )
2020-12-13 23:02:21 +01:00
{
2020-12-17 06:56:10 +01:00
if ( AI_DATA - > partnerMove ! = MOVE_NONE
& & gBattleMoves [ AI_DATA - > partnerMove ] . effect = = EFFECT_PLEDGE
& & move ! = AI_DATA - > partnerMove ) // Different pledge moves
2020-12-13 23:02:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ BATTLE_PARTNER ( battlerAtk ) ] . status1 & ( STATUS1_SLEEP | STATUS1_FREEZE ) )
// && gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 != 1) // Will wake up this turn - how would AI know
2020-12-13 23:02:21 +01:00
score - = 10 ; // Don't use combo move if your partner will cause failure
}
}
break ;
case EFFECT_TRICK_ROOM :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveIs ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove , MOVE_TRICK_ROOM ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else if ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM ) // Trick Room Up
{
if ( GetBattlerSideSpeedAverage ( battlerAtk ) < GetBattlerSideSpeedAverage ( battlerDef ) ) // Attacker side slower than target side
score - = 10 ; // Keep the Trick Room up
}
else
{
2021-01-05 03:39:59 +01:00
if ( GetBattlerSideSpeedAverage ( battlerAtk ) > = GetBattlerSideSpeedAverage ( battlerDef ) ) // Attacker side faster than target side
2020-12-13 23:02:21 +01:00
score - = 10 ; // Keep the Trick Room down
}
break ;
case EFFECT_MAGIC_ROOM :
2022-01-13 17:28:27 +01:00
if ( gFieldStatuses & STATUS_FIELD_MAGIC_ROOM | | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_WONDER_ROOM :
2022-01-13 17:28:27 +01:00
if ( gFieldStatuses & STATUS_FIELD_WONDER_ROOM | | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_GRAVITY :
if ( ( gFieldStatuses & STATUS_FIELD_GRAVITY
& & ! IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_FLYING )
2022-01-13 17:28:27 +01:00
& & AI_DATA - > holdEffects [ battlerAtk ] ! = HOLD_EFFECT_AIR_BALLOON ) // Should revert Gravity in this case
| | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_ION_DELUGE :
if ( gFieldStatuses & STATUS_FIELD_ION_DELUGE
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_FLING :
if ( ! CanFling ( battlerAtk ) )
2020-12-20 05:58:23 +01:00
{
2020-12-13 23:02:21 +01:00
score - = 10 ;
2020-12-20 05:58:23 +01:00
}
2020-12-13 23:02:21 +01:00
else
{
2020-12-20 05:58:23 +01:00
/* TODO Fling
2020-12-13 23:02:21 +01:00
u8 effect = gFlingTable [ gBattleMons [ battlerAtk ] . item ] . effect ;
switch ( effect )
{
case MOVE_EFFECT_BURN :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanBurn ( battlerAtk , battlerDef , BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case MOVE_EFFECT_PARALYSIS :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanParalyze ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case MOVE_EFFECT_POISON :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanPoison ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case MOVE_EFFECT_TOXIC :
2022-01-13 17:28:27 +01:00
if ( ! AI_CanPoison ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case MOVE_EFFECT_FREEZE :
if ( ! CanBeFrozen ( battlerDef , TRUE )
| | MoveBlockedBySubstitute ( move , battlerAtk , battlerDef ) )
score - = 10 ;
break ;
} */
}
break ;
case EFFECT_EMBARGO :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_KLUTZ
2020-12-13 23:02:21 +01:00
| | gFieldStatuses & STATUS_FIELD_MAGIC_ROOM
| | gDisableStructs [ battlerDef ] . embargoTimer ! = 0
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_POWDER :
if ( ! HasMoveWithType ( battlerDef , TYPE_FIRE )
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_TELEKINESIS :
if ( gStatuses3 [ battlerDef ] & ( STATUS3_TELEKINESIS | STATUS3_ROOTED | STATUS3_SMACKED_DOWN )
| | gFieldStatuses & STATUS_FIELD_GRAVITY
2022-01-13 17:28:27 +01:00
| | AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_IRON_BALL
2020-12-13 23:02:21 +01:00
| | IsTelekinesisBannedSpecies ( gBattleMons [ battlerDef ] . species )
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_THROAT_CHOP :
break ;
case EFFECT_HEAL_BLOCK :
if ( gDisableStructs [ battlerDef ] . healBlockTimer ! = 0
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SOAK :
2022-01-13 17:28:27 +01:00
if ( PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove )
2020-12-13 23:02:21 +01:00
| | ( gBattleMons [ battlerDef ] . type1 = = TYPE_WATER
& & gBattleMons [ battlerDef ] . type2 = = TYPE_WATER
& & gBattleMons [ battlerDef ] . type3 = = TYPE_MYSTERY ) )
score - = 10 ; // target is already water-only
break ;
case EFFECT_THIRD_TYPE :
switch ( move )
{
case MOVE_TRICK_OR_TREAT :
2022-01-13 17:28:27 +01:00
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GHOST ) | | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case MOVE_FORESTS_CURSE :
2022-01-13 17:28:27 +01:00
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GRASS ) | | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
}
break ;
case EFFECT_HIT_ENEMY_HEAL_ALLY : // pollen puff
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
2022-05-07 15:56:32 +02:00
if ( gStatuses3 [ battlerDef ] & STATUS3_HEAL_BLOCK )
return 0 ;
2020-12-20 05:58:23 +01:00
if ( AtMaxHp ( battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerDef ] . hp > gBattleMons [ battlerDef ] . maxHP / 2 )
score - = 5 ;
break ;
}
// fallthrough
case EFFECT_HEAL_PULSE : // and floral healing
2021-01-04 23:30:02 +01:00
if ( ! IsTargetingPartner ( battlerAtk , battlerDef ) ) // Don't heal enemies
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
else
{
2020-12-20 05:58:23 +01:00
if ( AtMaxHp ( battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( gBattleMons [ battlerDef ] . hp > gBattleMons [ battlerDef ] . maxHP / 2 )
score - = 5 ;
}
break ;
case EFFECT_ELECTRIFY :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER
2020-12-13 23:02:21 +01:00
//|| GetMoveTypeSpecial(battlerDef, predictedMove) == TYPE_ELECTRIC // Move will already be electric type
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_TOPSY_TURVY :
2021-01-04 23:30:02 +01:00
if ( ! IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
{
u8 targetPositiveStages = CountPositiveStatStages ( battlerDef ) ;
u8 targetNegativeStages = CountNegativeStatStages ( battlerDef ) ;
if ( targetPositiveStages = = 0 //No good stat changes to make bad
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
else if ( targetNegativeStages < targetPositiveStages )
score - = 5 ; //More stages would be made positive than negative
}
break ;
case EFFECT_FAIRY_LOCK :
2022-01-13 17:28:27 +01:00
if ( ( gFieldStatuses & STATUS_FIELD_FAIRY_LOCK ) | | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_DO_NOTHING :
score - = 10 ;
break ;
case EFFECT_INSTRUCT :
{
u16 instructedMove ;
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER )
2020-12-20 05:58:23 +01:00
instructedMove = predictedMove ;
2020-12-13 23:02:21 +01:00
else
instructedMove = gLastMoves [ battlerDef ] ;
if ( instructedMove = = MOVE_NONE
| | IsInstructBannedMove ( instructedMove )
| | MoveRequiresRecharging ( instructedMove )
| | MoveCallsOtherMove ( instructedMove )
2022-07-21 21:13:00 +02:00
| | IsZMove ( instructedMove )
2020-12-13 23:02:21 +01:00
| | ( gLockedMoves [ battlerDef ] ! = 0 & & gLockedMoves [ battlerDef ] ! = 0xFFFF )
| | gBattleMons [ battlerDef ] . status2 & STATUS2_MULTIPLETURNS
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
{
score - = 10 ;
}
2020-12-20 05:58:23 +01:00
else if ( isDoubleBattle )
2020-12-13 23:02:21 +01:00
{
2021-01-04 23:30:02 +01:00
if ( ! IsTargetingPartner ( battlerAtk , battlerDef ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
}
else
{
2022-04-27 12:23:20 +02:00
if ( AI_GetBattlerMoveTargetType ( battlerDef , instructedMove ) & ( MOVE_TARGET_SELECTED
2020-12-13 23:02:21 +01:00
| MOVE_TARGET_DEPENDS
| MOVE_TARGET_RANDOM
| MOVE_TARGET_BOTH
| MOVE_TARGET_FOES_AND_ALLY
| MOVE_TARGET_OPPONENTS_FIELD )
& & instructedMove ! = MOVE_MIND_BLOWN & & instructedMove ! = MOVE_STEEL_BEAM )
score - = 10 ; //Don't force the enemy to attack you again unless it can kill itself with Mind Blown
else if ( instructedMove ! = MOVE_MIND_BLOWN )
score - = 5 ; //Do something better
}
}
break ;
case EFFECT_QUASH :
2020-12-20 05:58:23 +01:00
if ( ! isDoubleBattle
2022-06-05 17:09:04 +02:00
| | AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_AFTER_YOU :
2021-01-04 23:30:02 +01:00
if ( ! IsTargetingPartner ( battlerAtk , battlerDef )
2020-12-20 05:58:23 +01:00
| | ! isDoubleBattle
2022-06-05 17:09:04 +02:00
| | AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameAsAttacker ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_SUCKER_PUNCH :
if ( predictedMove ! = MOVE_NONE )
{
2022-06-05 17:09:04 +02:00
if ( IS_MOVE_STATUS ( predictedMove ) | | AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER ) // Opponent going first
2020-12-13 23:02:21 +01:00
score - = 10 ;
2020-12-20 05:58:23 +01:00
}
2020-12-13 23:02:21 +01:00
break ;
case EFFECT_TAILWIND :
if ( gSideTimers [ GetBattlerSide ( battlerAtk ) ] . tailwindTimer ! = 0
2022-01-13 17:28:27 +01:00
| | PartnerMoveIs ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove , MOVE_TAILWIND )
2020-12-13 23:02:21 +01:00
| | ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM & & gFieldTimers . trickRoomTimer > 1 ) ) // Trick Room active and not ending this turn
score - = 10 ;
break ;
case EFFECT_LUCKY_CHANT :
if ( gSideTimers [ GET_BATTLER_SIDE ( battlerAtk ) ] . luckyChantTimer ! = 0
2022-01-13 17:28:27 +01:00
| | PartnerMoveIsSameNoTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
case EFFECT_MAGNET_RISE :
if ( gFieldStatuses & STATUS_FIELD_GRAVITY
| | gDisableStructs [ battlerAtk ] . magnetRiseTimer ! = 0
2022-01-13 17:28:27 +01:00
| | AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_IRON_BALL
2020-12-13 23:02:21 +01:00
| | gStatuses3 [ battlerAtk ] & ( STATUS3_ROOTED | STATUS3_MAGNET_RISE | STATUS3_SMACKED_DOWN )
| | ! IsBattlerGrounded ( battlerAtk ) )
score - = 10 ;
break ;
case EFFECT_CAMOUFLAGE :
if ( ! CanCamouflage ( battlerAtk ) )
score - = 10 ;
break ;
case EFFECT_LAST_RESORT :
if ( ! CanUseLastResort ( battlerAtk ) )
score - = 10 ;
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SYNCHRONOISE :
//Check holding ring target or is of same type
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_RING_TARGET
2020-12-20 05:58:23 +01:00
| | IS_BATTLER_OF_TYPE ( battlerDef , gBattleMons [ battlerAtk ] . type1 )
| | IS_BATTLER_OF_TYPE ( battlerDef , gBattleMons [ battlerAtk ] . type2 )
| | IS_BATTLER_OF_TYPE ( battlerDef , gBattleMons [ battlerAtk ] . type3 ) )
break ;
else
score - = 10 ;
break ;
case EFFECT_ERUPTION :
if ( effectiveness < = AI_EFFECTIVENESS_x0_5 )
score - - ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < 50 )
2020-12-20 05:58:23 +01:00
score - - ;
break ;
case EFFECT_VITAL_THROW :
2022-01-13 17:28:27 +01:00
if ( WillAIStrikeFirst ( ) & & AI_DATA - > hpPercents [ battlerAtk ] < 40 )
2020-12-20 05:58:23 +01:00
score - - ; // don't want to move last
break ;
case EFFECT_FLAIL :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER // Opponent should go first
2022-01-13 17:28:27 +01:00
| | AI_DATA - > hpPercents [ battlerAtk ] > 50 )
2020-12-20 05:58:23 +01:00
score - = 4 ;
break ;
2020-12-13 23:02:21 +01:00
//TODO
2020-12-20 05:58:23 +01:00
//case EFFECT_PLASMA_FISTS:
//break;
//case EFFECT_SHELL_TRAP:
//break;
//case EFFECT_BEAK_BLAST:
//break;
2022-07-20 21:13:53 +02:00
case EFFECT_SKY_DROP :
2020-12-13 23:02:21 +01:00
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_FLYING ) )
score - = 10 ;
2022-07-20 21:13:53 +02:00
if ( BattlerWillFaintFromWeather ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] )
| | DoesSubstituteBlockMove ( battlerAtk , battlerDef , move )
| | GetBattlerWeight ( battlerDef ) > = 2000 ) //200.0 kg
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
2020-12-20 05:58:23 +01:00
/*case EFFECT_NO_RETREAT:
if ( TrappedByNoRetreat ( battlerAtk ) )
2020-12-13 23:02:21 +01:00
score - = 10 ;
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_EXTREME_EVOBOOST :
if ( MainStatsMaxed ( battlerAtk ) )
score - = 10 ;
break ;
case EFFECT_CLANGOROUS_SOUL :
if ( gBattleMons [ battlerAtk ] . hp < = gBattleMons [ battlerAtk ] . maxHP / 3 )
score - = 10 ;
break ; */
2022-08-24 06:30:49 +02:00
case EFFECT_PLACEHOLDER :
return 0 ; // cannot even select
2020-12-13 23:02:21 +01:00
} // move effect checks
2022-08-24 21:56:24 +02:00
2020-12-20 06:57:08 +01:00
if ( score < 0 )
score = 0 ;
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
return score ;
}
2020-12-20 05:58:23 +01:00
static s16 AI_TryToFaint ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2022-08-24 21:56:24 +02:00
{
2020-12-13 23:02:21 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
2021-01-27 01:11:55 +01:00
return score ;
2022-08-24 21:56:24 +02:00
2021-01-27 01:11:55 +01:00
if ( gBattleMoves [ move ] . power = = 0 )
2020-12-16 05:57:33 +01:00
return score ; // can't make anything faint with no power
2022-08-24 21:56:24 +02:00
2021-11-08 08:37:28 +01:00
if ( CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) & & gBattleMoves [ move ] . effect ! = EFFECT_EXPLOSION )
2020-12-13 23:02:21 +01:00
{
2021-01-27 01:11:55 +01:00
// this move can faint the target
2021-09-28 03:03:27 +02:00
if ( ! WillAIStrikeFirst ( ) | | GetMovePriority ( battlerAtk , move ) > 0 )
2021-01-27 16:33:43 +01:00
score + = 4 ; // we go first or we're using priority move
2020-12-13 23:02:21 +01:00
else
score + = 2 ;
}
else
{
2021-01-27 01:11:55 +01:00
// this move isn't expected to faint the target
if ( TestMoveFlags ( move , FLAG_HIGH_CRIT ) )
score + = 2 ; // crit makes it more likely to make them faint
2022-08-24 21:56:24 +02:00
2021-08-12 01:33:10 +02:00
if ( GetMoveDamageResult ( move ) = = MOVE_POWER_OTHER )
2020-12-16 05:57:33 +01:00
score - - ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > effectiveness [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] )
2020-12-13 23:02:21 +01:00
{
2022-05-29 03:41:59 +02:00
case AI_EFFECTIVENESS_x8 :
score + = 8 ;
break ;
2021-01-27 01:11:55 +01:00
case AI_EFFECTIVENESS_x4 :
2022-05-29 03:41:59 +02:00
score + = 4 ;
2021-01-27 01:11:55 +01:00
break ;
case AI_EFFECTIVENESS_x2 :
2022-05-29 03:41:59 +02:00
if ( AI_RandLessThan ( 176 ) )
score + = 2 ;
2021-01-27 01:11:55 +01:00
else
2022-05-29 03:41:59 +02:00
score + + ;
2021-01-27 01:11:55 +01:00
break ;
2020-12-13 23:02:21 +01:00
}
}
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
//AI_TryToFaint_CheckIfDanger
2021-09-28 03:03:27 +02:00
if ( ! WillAIStrikeFirst ( ) & & CanTargetFaintAi ( battlerDef , battlerAtk ) )
2020-12-13 23:02:21 +01:00
{ // AI_TryToFaint_Danger
2020-12-16 05:57:33 +01:00
if ( GetMoveDamageResult ( move ) ! = MOVE_POWER_BEST )
2020-12-13 23:02:21 +01:00
score - - ;
else
score + + ;
}
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
return score ;
}
2021-01-04 23:30:02 +01:00
// double battle logic
2021-01-13 19:08:43 +01:00
static s16 AI_DoubleBattle ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 22:47:20 +01:00
// move data
u8 moveType = gBattleMoves [ move ] . type ;
u16 effect = gBattleMoves [ move ] . effect ;
2022-04-27 12:23:20 +02:00
u16 moveTarget = AI_GetBattlerMoveTargetType ( battlerAtk , move ) ;
2020-12-20 22:47:20 +01:00
// ally data
2022-01-13 17:28:27 +01:00
u8 battlerAtkPartner = BATTLE_PARTNER ( battlerAtk ) ;
u16 atkPartnerAbility = AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] ;
u16 atkPartnerHoldEffect = AI_DATA - > holdEffects [ BATTLE_PARTNER ( battlerAtk ) ] ;
2020-12-20 22:47:20 +01:00
bool32 partnerProtecting = ( gBattleMoves [ AI_DATA - > partnerMove ] . effect = = EFFECT_PROTECT ) ;
2022-01-13 17:28:27 +01:00
bool32 attackerHasBadAbility = ( GetAbilityRating ( AI_DATA - > abilities [ battlerAtk ] ) < 0 ) ;
2021-01-13 19:08:43 +01:00
bool32 partnerHasBadAbility = ( GetAbilityRating ( atkPartnerAbility ) < 0 ) ;
2022-01-13 17:28:27 +01:00
u16 predictedMove = AI_DATA - > predictedMoves [ battlerDef ] ;
2021-10-06 10:53:30 +02:00
SetTypeBeforeUsingMove ( move , battlerAtk ) ;
GET_MOVE_TYPE ( move , moveType ) ;
2021-01-13 19:08:43 +01:00
// check what effect partner is using
if ( AI_DATA - > partnerMove ! = 0 )
2020-12-20 22:47:20 +01:00
{
switch ( gBattleMoves [ AI_DATA - > partnerMove ] . effect )
{
2021-01-13 19:08:43 +01:00
case EFFECT_HELPING_HAND :
if ( IS_MOVE_STATUS ( move ) )
score + = 5 ;
break ;
2020-12-20 22:47:20 +01:00
case EFFECT_PERISH_SONG :
2021-01-13 19:08:43 +01:00
if ( ! ( gBattleMons [ battlerDef ] . status2 & ( STATUS2_ESCAPE_PREVENTION | STATUS2_WRAPPED ) ) )
{
if ( IsTrappingMoveEffect ( effect ) | | predictedMove = = MOVE_INGRAIN )
score + + ;
}
2020-12-20 22:47:20 +01:00
break ;
case EFFECT_ALWAYS_CRIT :
2021-01-13 19:08:43 +01:00
// Ally decided to use Frost Breath on us. we must have Anger Point as our ability
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_ANGER_POINT )
2020-12-20 22:47:20 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerAtkPartner , move ) = = AI_IS_SLOWER ) // Partner moving first
2021-01-13 19:08:43 +01:00
{
// discourage raising our attack since it's about to be maxed out
if ( IsAttackBoostMoveEffect ( effect ) )
score - = 3 ;
// encourage moves hitting multiple opponents
2021-11-23 04:56:11 +01:00
if ( ! IS_MOVE_STATUS ( move ) & & ( moveTarget & ( MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY ) ) )
2021-01-13 19:08:43 +01:00
score + = 3 ;
}
2020-12-20 22:47:20 +01:00
}
break ;
2021-01-13 19:08:43 +01:00
}
} // check partner move effect
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
// consider our move effect relative to partner state
switch ( effect )
2020-12-20 22:47:20 +01:00
{
2021-01-13 19:08:43 +01:00
case EFFECT_HELPING_HAND :
if ( AI_DATA - > partnerMove ! = 0 & & ! HasDamagingMove ( battlerAtkPartner ) )
score - = 5 ;
2020-12-20 22:47:20 +01:00
break ;
2021-01-13 19:08:43 +01:00
case EFFECT_PERISH_SONG :
if ( AI_DATA - > partnerMove ! = 0 & & HasTrappingMoveEffect ( battlerAtkPartner ) )
score + + ;
2020-12-20 22:47:20 +01:00
break ;
2021-01-13 19:08:43 +01:00
case EFFECT_MAGNET_RISE :
if ( IsBattlerGrounded ( battlerAtk )
& & ( HasMove ( battlerAtkPartner , MOVE_EARTHQUAKE ) | | HasMove ( battlerAtkPartner , MOVE_MAGNITUDE ) )
2021-01-26 23:41:59 +01:00
& & ( AI_GetMoveEffectiveness ( MOVE_EARTHQUAKE , battlerAtk , battlerAtkPartner ) ! = AI_EFFECTIVENESS_x0 ) ) // Doesn't resist ground move
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 2 ) ; // partner has earthquake or magnitude -> good idea to use magnet rise
}
2020-12-20 22:47:20 +01:00
break ;
2021-01-13 19:08:43 +01:00
} // our effect relative to partner
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
// consider global move effects
switch ( effect )
{
2020-12-20 22:47:20 +01:00
case EFFECT_SANDSTORM :
if ( ShouldSetSandstorm ( battlerAtkPartner , atkPartnerAbility , atkPartnerHoldEffect ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ; // our partner benefits from sandstorm
}
2020-12-20 22:47:20 +01:00
break ;
case EFFECT_RAIN_DANCE :
if ( ShouldSetRain ( battlerAtkPartner , atkPartnerAbility , atkPartnerHoldEffect ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ; // our partner benefits from rain
}
2020-12-20 22:47:20 +01:00
break ;
case EFFECT_SUNNY_DAY :
if ( ShouldSetSun ( battlerAtkPartner , atkPartnerAbility , atkPartnerHoldEffect ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ; // our partner benefits from sun
}
2020-12-20 22:47:20 +01:00
break ;
case EFFECT_HAIL :
if ( IsBattlerAlive ( battlerAtkPartner )
& & ShouldSetHail ( battlerAtkPartner , atkPartnerAbility , atkPartnerHoldEffect ) )
{
2021-01-13 19:08:43 +01:00
RETURN_SCORE_PLUS ( 2 ) ; // our partner benefits from hail
2020-12-20 22:47:20 +01:00
}
break ;
2021-01-13 19:08:43 +01:00
} // global move effect check
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
// check specific target
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
{
2021-08-12 01:33:10 +02:00
if ( GetMoveDamageResult ( move ) = = MOVE_POWER_OTHER )
2021-01-13 19:08:43 +01:00
{
// partner ability checks
2022-06-05 14:22:24 +02:00
if ( ! partnerProtecting & & moveTarget ! = MOVE_TARGET_BOTH & & ! DoesBattlerIgnoreAbilityChecks ( AI_DATA - > abilities [ battlerAtk ] , move ) )
2021-01-13 19:08:43 +01:00
{
switch ( atkPartnerAbility )
{
case ABILITY_VOLT_ABSORB :
if ( ! ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_HP_AWARE ) )
{
RETURN_SCORE_MINUS ( 10 ) ;
}
break ; // handled in AI_HPAware
case ABILITY_MOTOR_DRIVE :
if ( moveType = = TYPE_ELECTRIC & & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_SPEED ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_LIGHTNING_ROD :
if ( moveType = = TYPE_ELECTRIC
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_SPECIAL )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_SPATK ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_WATER_ABSORB :
case ABILITY_DRY_SKIN :
if ( ! ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_HP_AWARE ) )
{
RETURN_SCORE_MINUS ( 10 ) ;
}
break ; // handled in AI_HPAware
case ABILITY_STORM_DRAIN :
if ( moveType = = TYPE_WATER
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_SPECIAL )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_SPATK ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_WATER_COMPACTION :
if ( moveType = = TYPE_WATER & & GetMoveDamageResult ( move ) = = MOVE_POWER_WEAK )
{
RETURN_SCORE_PLUS ( 1 ) ; // only mon with this ability is weak to water so only make it okay if we do very little damage
}
RETURN_SCORE_MINUS ( 10 ) ;
break ;
case ABILITY_FLASH_FIRE :
if ( moveType = = TYPE_FIRE
& & HasMoveWithType ( battlerAtkPartner , TYPE_FIRE )
& & ! ( gBattleResources - > flags - > flags [ battlerAtkPartner ] & RESOURCE_FLAG_FLASH_FIRE ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_SAP_SIPPER :
if ( moveType = = TYPE_GRASS
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_PHYSICAL )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_ATK ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_JUSTIFIED :
if ( moveType = = TYPE_DARK
& & ! IS_MOVE_STATUS ( move )
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_PHYSICAL )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_ATK )
2021-11-08 08:37:28 +01:00
& & ! CanIndexMoveFaintTarget ( battlerAtk , battlerAtkPartner , AI_THINKING_STRUCT - > movesetIndex , 1 ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_RATTLED :
if ( ! IS_MOVE_STATUS ( move )
& & ( moveType = = TYPE_DARK | | moveType = = TYPE_GHOST | | moveType = = TYPE_BUG )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_SPEED )
2021-11-08 08:37:28 +01:00
& & ! CanIndexMoveFaintTarget ( battlerAtk , battlerAtkPartner , AI_THINKING_STRUCT - > movesetIndex , 1 ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_CONTRARY :
if ( IsStatLoweringEffect ( effect ) )
{
RETURN_SCORE_PLUS ( 2 ) ;
}
break ;
case ABILITY_DEFIANT :
if ( IsStatLoweringEffect ( effect )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_ATK ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case ABILITY_COMPETITIVE :
if ( IsStatLoweringEffect ( effect )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_SPATK ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
2022-08-24 21:56:24 +02:00
break ;
2021-01-13 19:08:43 +01:00
}
} // ability checks
} // move power check
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
// attacker move effects specifically targeting partner
2020-12-20 22:47:20 +01:00
if ( ! partnerProtecting )
{
2021-01-13 19:08:43 +01:00
switch ( effect )
2020-12-20 22:47:20 +01:00
{
2021-01-13 19:08:43 +01:00
case EFFECT_PURIFY :
if ( gBattleMons [ battlerAtkPartner ] . status1 & STATUS1_ANY )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_SWAGGER :
if ( gBattleMons [ battlerAtkPartner ] . statStages [ STAT_ATK ] < MAX_STAT_STAGE
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_PHYSICAL )
2021-08-12 21:37:53 +02:00
& & ( ! AI_CanBeConfused ( battlerAtkPartner , TRUE )
2021-01-13 19:08:43 +01:00
| | atkPartnerHoldEffect = = HOLD_EFFECT_CURE_CONFUSION
| | atkPartnerHoldEffect = = HOLD_EFFECT_CURE_STATUS ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_FLATTER :
if ( gBattleMons [ battlerAtkPartner ] . statStages [ STAT_SPATK ] < MAX_STAT_STAGE
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_SPECIAL )
2021-08-12 21:37:53 +02:00
& & ( ! AI_CanBeConfused ( battlerAtkPartner , TRUE )
2021-01-13 19:08:43 +01:00
| | atkPartnerHoldEffect = = HOLD_EFFECT_CURE_CONFUSION
| | atkPartnerHoldEffect = = HOLD_EFFECT_CURE_STATUS ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_BEAT_UP :
if ( atkPartnerAbility = = ABILITY_JUSTIFIED
& & moveType = = TYPE_DARK
& & ! IS_MOVE_STATUS ( move )
& & HasMoveWithSplit ( battlerAtkPartner , SPLIT_PHYSICAL )
& & BattlerStatCanRise ( battlerAtkPartner , atkPartnerAbility , STAT_ATK )
2021-11-08 08:37:28 +01:00
& & ! CanIndexMoveFaintTarget ( battlerAtk , battlerAtkPartner , AI_THINKING_STRUCT - > movesetIndex , 0 ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_SKILL_SWAP :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] & & ! attackerHasBadAbility )
2021-01-13 19:08:43 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_TRUANT )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 10 ) ;
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_COMPOUND_EYES
& & HasMoveWithLowAccuracy ( battlerAtkPartner , FOE ( battlerAtkPartner ) , 90 , TRUE , atkPartnerAbility , AI_DATA - > abilities [ FOE ( battlerAtkPartner ) ] , atkPartnerHoldEffect , AI_DATA - > holdEffects [ FOE ( battlerAtkPartner ) ] ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 3 ) ;
}
}
break ;
case EFFECT_ROLE_PLAY :
if ( attackerHasBadAbility & & ! partnerHasBadAbility )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_WORRY_SEED :
case EFFECT_GASTRO_ACID :
case EFFECT_SIMPLE_BEAM :
if ( partnerHasBadAbility )
{
RETURN_SCORE_PLUS ( 2 ) ;
}
break ;
case EFFECT_ENTRAINMENT :
2022-01-13 17:28:27 +01:00
if ( partnerHasBadAbility & & IsAbilityOfRating ( AI_DATA - > abilities [ battlerAtk ] , 0 ) )
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_SOAK :
if ( atkPartnerAbility = = ABILITY_WONDER_GUARD
& & ( gBattleMons [ battlerAtkPartner ] . type1 ! = TYPE_WATER
| | gBattleMons [ battlerAtkPartner ] . type2 ! = TYPE_WATER
| | gBattleMons [ battlerAtkPartner ] . type3 ! = TYPE_WATER ) )
{
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
case EFFECT_INSTRUCT :
{
u16 instructedMove ;
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerAtkPartner , move ) = = AI_IS_FASTER )
2021-01-13 19:08:43 +01:00
instructedMove = AI_DATA - > partnerMove ;
else
instructedMove = gLastMoves [ battlerAtkPartner ] ;
if ( instructedMove ! = MOVE_NONE
& & ! IS_MOVE_STATUS ( instructedMove )
2022-04-27 12:23:20 +02:00
& & ( AI_GetBattlerMoveTargetType ( battlerAtkPartner , instructedMove ) & ( MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY ) ) ) // Use instruct on multi-target moves
2021-01-13 19:08:43 +01:00
{
RETURN_SCORE_PLUS ( 1 ) ;
}
}
break ;
case EFFECT_AFTER_YOU :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtkPartner , FOE ( battlerAtkPartner ) , AI_DATA - > partnerMove ) = = AI_IS_SLOWER // Opponent mon 1 goes before partner
| | AI_WhoStrikesFirst ( battlerAtkPartner , BATTLE_PARTNER ( FOE ( battlerAtkPartner ) ) , AI_DATA - > partnerMove ) = = AI_IS_SLOWER ) // Opponent mon 2 goes before partner
2021-01-13 19:08:43 +01:00
{
if ( gBattleMoves [ AI_DATA - > partnerMove ] . effect = = EFFECT_COUNTER | | gBattleMoves [ AI_DATA - > partnerMove ] . effect = = EFFECT_MIRROR_COAT )
break ; // These moves need to go last
RETURN_SCORE_PLUS ( 1 ) ;
}
break ;
} // attacker move effects
} // check partner protecting
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
score - = 30 ; // otherwise, don't target partner
}
else // checking opponent
{
2022-08-24 21:56:24 +02:00
// these checks mostly handled in AI_CheckBadMove and AI_CheckViability
2021-01-13 19:08:43 +01:00
switch ( effect )
2020-12-20 22:47:20 +01:00
{
2021-01-13 19:08:43 +01:00
case EFFECT_SKILL_SWAP :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_TRUANT )
2021-01-13 19:08:43 +01:00
score + = 5 ;
2022-01-13 17:28:27 +01:00
else if ( IsAbilityOfRating ( AI_DATA - > abilities [ battlerAtk ] , 0 ) | | IsAbilityOfRating ( AI_DATA - > abilities [ battlerDef ] , 10 ) )
2021-01-13 19:08:43 +01:00
score + = 2 ; // we want to transfer our bad ability or take their awesome ability
break ;
case EFFECT_EARTHQUAKE :
case EFFECT_MAGNITUDE :
if ( ! IsBattlerGrounded ( battlerAtkPartner )
2021-09-28 03:03:27 +02:00
| | ( IsBattlerGrounded ( battlerAtkPartner )
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , battlerAtkPartner , move ) = = AI_IS_SLOWER
2021-09-28 03:03:27 +02:00
& & IsUngroundingEffect ( gBattleMoves [ AI_DATA - > partnerMove ] . effect ) ) )
2021-01-13 19:08:43 +01:00
score + = 2 ;
else if ( IS_BATTLER_OF_TYPE ( battlerAtkPartner , TYPE_FIRE )
| | IS_BATTLER_OF_TYPE ( battlerAtkPartner , TYPE_ELECTRIC )
| | IS_BATTLER_OF_TYPE ( battlerAtkPartner , TYPE_POISON )
| | IS_BATTLER_OF_TYPE ( battlerAtkPartner , TYPE_ROCK ) )
score - = 10 ; // partner will be hit by earthquake and is weak to it
else
score - = 3 ;
break ;
2020-12-20 22:47:20 +01:00
}
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
// lightning rod, flash fire against enemy handled in AI_CheckBadMove
}
2022-08-24 21:56:24 +02:00
2021-01-13 19:08:43 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2022-01-27 01:45:24 +01:00
static bool32 IsPinchBerryItemEffect ( u16 holdEffect )
{
switch ( holdEffect )
{
case HOLD_EFFECT_ATTACK_UP :
case HOLD_EFFECT_DEFENSE_UP :
case HOLD_EFFECT_SPEED_UP :
case HOLD_EFFECT_SP_ATTACK_UP :
case HOLD_EFFECT_SP_DEFENSE_UP :
case HOLD_EFFECT_CRITICAL_UP :
case HOLD_EFFECT_RANDOM_STAT_UP :
# ifdef HOLD_EFFECT_CUSTAP_BERRY
case HOLD_EFFECT_CUSTAP_BERRY :
# endif
# ifdef HOLD_EFFECT_MICLE_BERRY
case HOLD_EFFECT_MICLE_BERRY :
# endif
return TRUE ;
}
return FALSE ;
}
2021-01-05 03:39:59 +01:00
// AI_FLAG_CHECK_VIABILITY - a weird mix of increasing and decreasing scores
static s16 AI_CheckViability ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-16 05:57:33 +01:00
{
// move data
u16 moveEffect = gBattleMoves [ move ] . effect ;
2022-07-03 22:20:05 +02:00
u32 effectiveness = AI_DATA - > effectiveness [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] ;
2020-12-16 05:57:33 +01:00
u8 atkPriority = GetMovePriority ( battlerAtk , move ) ;
2022-01-13 17:28:27 +01:00
u16 predictedMove = AI_DATA - > predictedMoves [ battlerDef ] ;
2020-12-20 05:58:23 +01:00
bool32 isDoubleBattle = IsValidDoubleBattle ( battlerAtk ) ;
u32 i ;
2022-08-01 12:39:51 +02:00
// We only check for moves that have a 20% chance or more for their secondary effect to happen because moves with a smaller chance are rather worthless. We don't want the AI to use those.
bool32 sereneGraceBoost = ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_SERENE_GRACE & & ( gBattleMoves [ move ] . secondaryEffectChance > = 20 & & gBattleMoves [ move ] . secondaryEffectChance < 100 ) ) ;
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
// Targeting partner, check benefits of doing that instead
2021-01-04 23:30:02 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
return score ;
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
// check always hits
2020-12-16 05:57:33 +01:00
if ( ! IS_MOVE_STATUS ( move ) & & gBattleMoves [ move ] . accuracy = = 0 )
{
2021-01-05 03:39:59 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] > = 10 | | gBattleMons [ battlerAtk ] . statStages [ STAT_ACC ] < = 2 )
2020-12-16 05:57:33 +01:00
score + + ;
2021-01-05 03:39:59 +01:00
if ( AI_RandLessThan ( 100 ) & & ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] > = 8 | | gBattleMons [ battlerAtk ] . statStages [ STAT_ACC ] < = 4 ) )
2020-12-16 05:57:33 +01:00
score + + ;
}
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
// check high crit
if ( TestMoveFlags ( move , FLAG_HIGH_CRIT ) & & effectiveness > = AI_EFFECTIVENESS_x2 & & AI_RandLessThan ( 128 ) )
score + + ;
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
// check already dead
2022-01-13 17:28:27 +01:00
if ( ! IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] )
2021-01-05 03:39:59 +01:00
& & CanTargetFaintAi ( battlerAtk , battlerDef )
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER ) // Opponent should go first
2021-01-05 03:39:59 +01:00
{
2021-09-28 03:03:27 +02:00
if ( atkPriority > 0 )
2021-01-05 03:39:59 +01:00
score + + ;
else
score - - ;
}
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
// check damage
if ( gBattleMoves [ move ] . power ! = 0 & & GetMoveDamageResult ( move ) = = MOVE_POWER_WEAK )
score - - ;
2020-12-20 05:58:23 +01:00
2020-12-16 05:57:33 +01:00
// check status move preference
2021-01-26 23:41:59 +01:00
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_PREFER_STATUS_MOVES & & IS_MOVE_STATUS ( move ) & & effectiveness ! = AI_EFFECTIVENESS_x0 )
2020-12-16 05:57:33 +01:00
score + + ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
// check thawing moves
2021-06-10 13:48:18 +02:00
if ( ( gBattleMons [ battlerAtk ] . status1 & STATUS1_FREEZE ) & & TestMoveFlags ( move , FLAG_THAW_USER ) )
2020-12-20 05:58:23 +01:00
score + = ( gBattleTypeFlags & BATTLE_TYPE_DOUBLE ) ? 20 : 10 ;
2022-08-24 21:56:24 +02:00
2021-02-14 17:37:04 +01:00
// check burn
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN )
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > abilities [ battlerAtk ] )
2021-02-14 17:37:04 +01:00
{
case ABILITY_GUTS :
break ;
case ABILITY_NATURAL_CURE :
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_SMART_SWITCHING
& & HasOnlyMovesWithSplit ( battlerAtk , SPLIT_PHYSICAL , TRUE ) )
score = 90 ; // Force switch if all your attacking moves are physical and you have Natural Cure.
break ;
default :
if ( IS_MOVE_PHYSICAL ( move ) & & gBattleMoves [ move ] . effect ! = EFFECT_FACADE )
score - = 2 ;
break ;
}
}
2022-08-24 21:56:24 +02:00
2021-11-04 02:49:46 +01:00
// attacker ability checks
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > abilities [ battlerAtk ] )
2020-12-20 05:58:23 +01:00
{
case ABILITY_MOXIE :
case ABILITY_BEAST_BOOST :
2021-11-08 17:37:41 +01:00
case ABILITY_CHILLING_NEIGH :
case ABILITY_GRIM_NEIGH :
case ABILITY_AS_ONE_ICE_RIDER :
case ABILITY_AS_ONE_SHADOW_RIDER :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker should go first
2020-12-20 05:58:23 +01:00
{
2021-11-08 08:37:28 +01:00
if ( CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) )
2020-12-20 05:58:23 +01:00
score + = 8 ; // prioritize killing target for stat boost
}
break ;
2022-08-24 21:56:24 +02:00
} // ability checks
2020-12-20 05:58:23 +01:00
// move effect checks
2020-12-16 05:57:33 +01:00
switch ( moveEffect )
{
case EFFECT_HIT :
break ;
case EFFECT_SLEEP :
case EFFECT_YAWN :
2021-01-05 03:39:59 +01:00
if ( AI_RandLessThan ( 128 ) )
IncreaseSleepScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_ABSORB :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_BIG_ROOT )
2020-12-20 05:58:23 +01:00
score + + ;
2021-01-05 04:23:09 +01:00
if ( effectiveness < = AI_EFFECTIVENESS_x0_5 & & AI_RandLessThan ( 50 ) )
2021-01-05 03:39:59 +01:00
score - = 3 ;
2020-12-16 05:57:33 +01:00
break ;
case EFFECT_EXPLOSION :
case EFFECT_MEMENTO :
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_WILL_SUICIDE & & gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] < 7 )
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < 50 & & AI_RandLessThan ( 128 ) )
2020-12-16 05:57:33 +01:00
score + + ;
}
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_MIRROR_MOVE :
2021-01-05 03:39:59 +01:00
if ( predictedMove ! = MOVE_NONE )
return AI_CheckViability ( battlerAtk , battlerDef , gLastMoves [ battlerDef ] , score ) ;
break ;
// stat raising effects
2022-07-26 15:53:39 +02:00
case EFFECT_ATTACK_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_ATTACK_UP_2 :
2021-01-05 03:39:59 +01:00
if ( MovesWithSplitUnusable ( battlerAtk , battlerDef , SPLIT_PHYSICAL ) )
{
score - = 8 ;
break ;
}
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] < 9 )
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 90 & & AI_RandLessThan ( 128 ) )
2021-01-05 03:39:59 +01:00
{
score + = 2 ;
break ;
}
}
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
if ( ! AI_RandLessThan ( 100 ) )
{
score - - ;
}
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_DEFENSE_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_DEFENSE_UP_2 :
2020-12-20 06:51:25 +01:00
case EFFECT_DEFENSE_UP_3 :
2021-01-05 03:39:59 +01:00
if ( ! HasMoveWithSplit ( battlerDef , SPLIT_PHYSICAL ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 90 & & AI_RandLessThan ( 128 ) )
2021-01-05 03:39:59 +01:00
score + = 2 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > 70 & & AI_RandLessThan ( 200 ) )
2021-01-05 03:39:59 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 40 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPEED_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_SPEED_UP_2 :
2021-09-28 03:03:27 +02:00
if ( ! WillAIStrikeFirst ( ) )
2021-01-05 03:39:59 +01:00
{
if ( ! AI_RandLessThan ( 70 ) )
score + = 3 ;
}
else
{
score - = 3 ;
}
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPECIAL_ATTACK_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_SPECIAL_ATTACK_UP_2 :
2020-12-20 06:51:25 +01:00
case EFFECT_SPECIAL_ATTACK_UP_3 :
2021-01-05 03:39:59 +01:00
if ( MovesWithSplitUnusable ( battlerAtk , battlerDef , SPLIT_SPECIAL ) )
{
score - = 8 ;
break ;
}
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ] < 9 )
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 90 & & AI_RandLessThan ( 128 ) )
2021-01-05 03:39:59 +01:00
{
score + = 2 ;
break ;
}
}
2022-08-24 21:56:24 +02:00
2021-01-05 03:39:59 +01:00
if ( ! AI_RandLessThan ( 100 ) )
{
score - - ;
}
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPECIAL_DEFENSE_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_SPECIAL_DEFENSE_UP_2 :
2021-01-05 03:39:59 +01:00
if ( ! HasMoveWithSplit ( battlerDef , SPLIT_SPECIAL ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 90 & & AI_RandLessThan ( 128 ) )
2021-01-05 03:39:59 +01:00
score + = 2 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > 70 & & AI_RandLessThan ( 200 ) )
2021-01-05 03:39:59 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 40 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_ACCURACY_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_ACCURACY_UP_2 :
2021-01-05 03:39:59 +01:00
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ACC ] > = 9 & & ! AI_RandLessThan ( 50 ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-08-24 21:56:24 +02:00
else
2021-01-05 03:39:59 +01:00
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_EVASION_UP :
2020-12-16 05:57:33 +01:00
case EFFECT_EVASION_UP_2 :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 90 & & ! AI_RandLessThan ( 100 ) )
2021-01-05 03:39:59 +01:00
score + = 3 ;
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_EVASION ] > 9 & & AI_RandLessThan ( 128 ) )
score - - ;
2022-01-13 17:28:27 +01:00
if ( ( gBattleMons [ battlerDef ] . status1 & STATUS1_PSN_ANY ) & & AI_DATA - > hpPercents [ battlerAtk ] > = 50 & & ! AI_RandLessThan ( 80 ) )
2021-01-05 03:39:59 +01:00
score + = 3 ;
if ( gStatuses3 [ battlerDef ] & STATUS3_LEECHSEED & & ! AI_RandLessThan ( 70 ) )
score + = 3 ;
if ( gStatuses3 [ battlerAtk ] & STATUS3_ROOTED & & AI_RandLessThan ( 128 ) )
score + = 2 ;
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_CURSED & & ! AI_RandLessThan ( 70 ) )
score + = 3 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < 70 | | gBattleMons [ battlerAtk ] . statStages [ STAT_EVASION ] = = DEFAULT_STAT_STAGE )
2021-01-05 03:39:59 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 40 | | AI_DATA - > hpPercents [ battlerDef ] < 40 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
else if ( ! AI_RandLessThan ( 70 ) )
score - = 2 ;
break ;
// stat lowering effects
2022-07-26 15:53:39 +02:00
case EFFECT_ATTACK_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_ATTACK_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerAttack ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
if ( gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] < DEFAULT_STAT_STAGE )
score - - ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 90 )
2021-01-05 03:39:59 +01:00
score - - ;
if ( gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] > 3 & & ! AI_RandLessThan ( 50 ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerDef ] < 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_DEFENSE_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_DEFENSE_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerDefense ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > hpPercents [ battlerAtk ] < 70 & & ! AI_RandLessThan ( 50 ) ) | | ( gBattleMons [ battlerDef ] . statStages [ STAT_DEF ] < = 3 & & ! AI_RandLessThan ( 50 ) ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < = 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPEED_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_SPEED_DOWN_2 :
2021-09-28 03:03:27 +02:00
if ( WillAIStrikeFirst ( ) )
2021-01-05 03:39:59 +01:00
score - = 3 ;
else if ( ! AI_RandLessThan ( 70 ) )
score + = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPECIAL_ATTACK_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_SPECIAL_ATTACK_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerSpAtk ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
if ( gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] < DEFAULT_STAT_STAGE )
score - - ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < = 90 )
2021-01-05 03:39:59 +01:00
score - - ;
if ( gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] > 3 & & ! AI_RandLessThan ( 50 ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerDef ] < 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_SPECIAL_DEFENSE_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_SPECIAL_DEFENSE_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerSpDef ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > hpPercents [ battlerAtk ] < 70 & & ! AI_RandLessThan ( 50 ) )
2021-01-05 03:39:59 +01:00
| | ( gBattleMons [ battlerDef ] . statStages [ STAT_SPDEF ] < = 3 & & ! AI_RandLessThan ( 50 ) ) )
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < = 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_ACCURACY_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_ACCURACY_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ShouldLowerAccuracy ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > hpPercents [ battlerAtk ] < 70 | | AI_DATA - > hpPercents [ battlerDef ] < 70 ) & & AI_RandLessThan ( 100 ) )
2021-01-05 03:39:59 +01:00
score - - ;
if ( gBattleMons [ battlerDef ] . statStages [ STAT_ACC ] < = 4 & & ! AI_RandLessThan ( 80 ) )
score - = 2 ;
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_PSN_ANY & & ! AI_RandLessThan ( 70 ) )
score + = 2 ;
if ( gStatuses3 [ battlerDef ] & STATUS3_LEECHSEED & & ! AI_RandLessThan ( 70 ) )
score + = 2 ;
if ( gStatuses3 [ battlerDef ] & STATUS3_ROOTED & & AI_RandLessThan ( 128 ) )
score + + ;
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_CURSED & & ! AI_RandLessThan ( 70 ) )
score + = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 70 | | gBattleMons [ battlerDef ] . statStages [ STAT_ACC ] < DEFAULT_STAT_STAGE )
2021-01-05 03:39:59 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 40 | | AI_DATA - > hpPercents [ battlerDef ] < 40 | | ! AI_RandLessThan ( 70 ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
2022-07-26 15:53:39 +02:00
case EFFECT_EVASION_DOWN :
2021-01-05 03:39:59 +01:00
case EFFECT_EVASION_DOWN_2 :
2022-01-13 17:28:27 +01:00
if ( ! ShouldLowerEvasion ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > hpPercents [ battlerAtk ] < 70 | | gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] < = 3 ) & & ! AI_RandLessThan ( 50 ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < = 70 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ACC ] < DEFAULT_STAT_STAGE )
score + + ;
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] < 7 | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_NO_GUARD )
2021-01-05 03:39:59 +01:00
score - = 2 ;
break ;
case EFFECT_BIDE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < 90 )
2021-01-05 03:39:59 +01:00
score - = 2 ;
2020-12-17 06:56:10 +01:00
break ;
2021-01-05 03:39:59 +01:00
case EFFECT_DREAM_EATER :
if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP ) )
break ;
score + + ; // if target is asleep, dream eater is a pretty good move even without draining
// fallthrough
2020-12-17 06:56:10 +01:00
case EFFECT_ACUPRESSURE :
2020-12-16 05:57:33 +01:00
break ;
2020-12-17 06:56:10 +01:00
case EFFECT_ATTACK_ACCURACY_UP : // hone claws
2020-12-20 05:58:23 +01:00
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ACC , & score ) ;
2020-12-17 06:56:10 +01:00
break ;
case EFFECT_GROWTH :
case EFFECT_ATTACK_SPATK_UP : // work up
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < = 40 | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
break ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
if ( HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
else if ( HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPATK , & score ) ;
break ;
case EFFECT_HAZE :
2022-01-13 17:28:27 +01:00
if ( AnyStatIsRaised ( BATTLE_PARTNER ( battlerAtk ) )
| | PartnerHasSameMoveEffectWithoutTarget ( BATTLE_PARTNER ( battlerAtk ) , move , AI_DATA - > partnerMove ) )
2021-01-05 03:39:59 +01:00
score - = 3 ;
2020-12-20 05:58:23 +01:00
break ;
// fallthrough
case EFFECT_ROAR :
case EFFECT_CLEAR_SMOG :
if ( isDoubleBattle )
2022-01-13 17:28:27 +01:00
score + = min ( CountPositiveStatStages ( battlerDef ) + CountPositiveStatStages ( BATTLE_PARTNER ( battlerDef ) ) , 7 ) ;
2020-12-20 05:58:23 +01:00
else
score + = min ( CountPositiveStatStages ( battlerDef ) , 4 ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MULTI_HIT :
case EFFECT_DOUBLE_HIT :
case EFFECT_TRIPLE_KICK :
2022-01-13 17:28:27 +01:00
if ( AI_MoveMakesContact ( AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > holdEffects [ battlerAtk ] , move )
& & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_MAGIC_GUARD
& & AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_ROCKY_HELMET )
2021-11-08 17:55:06 +01:00
score - = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_CONVERSION :
if ( ! IS_BATTLER_OF_TYPE ( battlerAtk , gBattleMoves [ gBattleMons [ battlerAtk ] . moves [ 0 ] ] . type ) )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FLINCH_HIT :
2022-01-13 17:28:27 +01:00
score + = ShouldTryToFlinch ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , move ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SWALLOW :
if ( gDisableStructs [ battlerAtk ] . stockpileCounter = = 0 )
{
break ;
}
else
{
u32 healPercent = 0 ;
switch ( gDisableStructs [ battlerAtk ] . stockpileCounter )
{
case 1 :
healPercent = 25 ;
break ;
case 2 :
healPercent = 50 ;
break ;
case 3 :
healPercent = 100 ;
break ;
default :
break ;
}
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
if ( ShouldRecover ( battlerAtk , battlerDef , move , healPercent ) )
score + = 2 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_RESTORE_HP :
case EFFECT_SOFTBOILED :
case EFFECT_ROOST :
case EFFECT_MORNING_SUN :
case EFFECT_SYNTHESIS :
case EFFECT_MOONLIGHT :
if ( ShouldRecover ( battlerAtk , battlerDef , move , 50 ) )
score + = 3 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_BIG_ROOT )
2020-12-20 05:58:23 +01:00
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TOXIC :
case EFFECT_POISON :
IncreasePoisonScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_LIGHT_SCREEN :
2020-12-16 05:57:33 +01:00
case EFFECT_REFLECT :
2020-12-20 05:58:23 +01:00
case EFFECT_AURORA_VEIL :
2021-02-14 17:11:29 +01:00
if ( ShouldSetScreen ( battlerAtk , battlerDef , moveEffect ) )
2020-12-20 05:58:23 +01:00
{
score + = 5 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_LIGHT_CLAY )
2020-12-20 05:58:23 +01:00
score + = 2 ;
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_SCREENER )
score + = 2 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_REST :
2022-01-13 17:28:27 +01:00
if ( ! ( AI_CanSleep ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) ) )
2020-12-20 05:58:23 +01:00
{
break ;
}
else if ( ShouldRecover ( battlerAtk , battlerDef , move , 100 ) )
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_CURE_SLP
| | AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_CURE_STATUS
2020-12-20 05:58:23 +01:00
| | HasMoveEffect ( EFFECT_SLEEP_TALK , battlerAtk )
| | HasMoveEffect ( EFFECT_SNORE , battlerAtk )
2022-01-13 17:28:27 +01:00
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_SHED_SKIN
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_EARLY_BIRD
| | ( gBattleWeather & B_WEATHER_RAIN & & gWishFutureKnock . weatherDuration ! = 1 & & AI_DATA - > abilities [ battlerAtk ] = = ABILITY_HYDRATION & & AI_DATA - > holdEffects [ battlerAtk ] ! = HOLD_EFFECT_UTILITY_UMBRELLA ) )
2020-12-20 05:58:23 +01:00
{
score + = 2 ;
}
else
{
score + + ;
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_OHKO :
if ( gStatuses3 [ battlerAtk ] & STATUS3_ALWAYS_HITS )
score + = 5 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TRAP :
2022-07-26 15:53:39 +02:00
if ( HasMoveEffect ( battlerDef , EFFECT_RAPID_SPIN ) )
break ;
//fallthrough
2020-12-20 05:58:23 +01:00
case EFFECT_MEAN_LOOK :
2022-07-26 15:53:39 +02:00
if ( IsBattlerTrapped ( battlerDef , TRUE ) )
2020-12-20 05:58:23 +01:00
break ; // in this case its a bad attacking move
else if ( ShouldTrap ( battlerAtk , battlerDef , move ) )
score + = 5 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MIST :
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_SCREENER )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FOCUS_ENERGY :
case EFFECT_LASER_FOCUS :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_SUPER_LUCK
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_SNIPER
| | AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_SCOPE_LENS
2020-12-20 05:58:23 +01:00
| | TestMoveFlagsInMoveset ( battlerAtk , FLAG_HIGH_CRIT ) )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_CONFUSE_HIT :
2022-08-01 12:39:51 +02:00
if ( sereneGraceBoost )
2020-12-20 05:58:23 +01:00
score + + ;
//fallthrough
case EFFECT_CONFUSE :
IncreaseConfusionScore ( battlerAtk , battlerDef , move , & score ) ;
break ;
case EFFECT_PARALYZE :
IncreaseParalyzeScore ( battlerAtk , battlerDef , move , & score ) ;
break ;
2021-10-18 15:05:19 +02:00
case EFFECT_GRAV_APPLE :
if ( gFieldStatuses & STATUS_FIELD_GRAVITY )
score + = 2 ;
// fall through
2020-12-20 05:58:23 +01:00
case EFFECT_ATTACK_DOWN_HIT :
case EFFECT_DEFENSE_DOWN_HIT :
case EFFECT_SPECIAL_ATTACK_DOWN_HIT :
case EFFECT_SPECIAL_DEFENSE_DOWN_HIT :
case EFFECT_ACCURACY_DOWN_HIT :
case EFFECT_EVASION_DOWN_HIT :
2022-08-01 12:39:51 +02:00
if ( sereneGraceBoost & & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SPEED_DOWN_HIT :
2021-09-28 03:03:27 +02:00
if ( WillAIStrikeFirst ( ) )
2021-01-05 03:39:59 +01:00
score - = 2 ;
else if ( ! AI_RandLessThan ( 70 ) )
score + + ;
2022-01-13 17:28:27 +01:00
if ( ShouldLowerSpeed ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2021-01-05 04:23:09 +01:00
{
2022-08-01 12:39:51 +02:00
if ( sereneGraceBoost & & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_CONTRARY )
score + = 5 ;
2021-01-05 04:23:09 +01:00
else
score + = 2 ;
}
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SUBSTITUTE :
if ( gStatuses3 [ battlerDef ] & STATUS3_PERISH_SONG )
score + = 3 ;
if ( gBattleMons [ battlerDef ] . status1 & ( STATUS1_BURN | STATUS1_PSN_ANY ) )
score + + ;
if ( HasMoveEffect ( battlerDef , EFFECT_SLEEP )
| | HasMoveEffect ( battlerDef , EFFECT_TOXIC )
| | HasMoveEffect ( battlerDef , EFFECT_POISON )
| | HasMoveEffect ( battlerDef , EFFECT_PARALYZE )
| | HasMoveEffect ( battlerDef , EFFECT_WILL_O_WISP )
| | HasMoveEffect ( battlerDef , EFFECT_CONFUSE )
| | HasMoveEffect ( battlerDef , EFFECT_LEECH_SEED ) )
score + = 2 ;
2022-01-13 17:28:27 +01:00
if ( ! gBattleMons [ battlerDef ] . status2 & ( STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION & & AI_DATA - > hpPercents [ battlerAtk ] > 70 ) )
2020-12-20 05:58:23 +01:00
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MIMIC :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER )
2020-12-20 05:58:23 +01:00
{
if ( gLastMoves [ battlerDef ] ! = MOVE_NONE & & gLastMoves [ battlerDef ] ! = 0xFFFF )
2021-01-05 03:39:59 +01:00
return AI_CheckViability ( battlerAtk , battlerDef , gLastMoves [ battlerDef ] , score ) ;
2020-12-20 05:58:23 +01:00
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_LEECH_SEED :
if ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GRASS )
| | gStatuses3 [ battlerDef ] & STATUS3_LEECHSEED
| | HasMoveEffect ( battlerDef , EFFECT_RAPID_SPIN )
2022-01-13 17:28:27 +01:00
| | AI_DATA - > abilities [ battlerDef ] = = ABILITY_LIQUID_OOZE
| | AI_DATA - > abilities [ battlerDef ] = = ABILITY_MAGIC_GUARD )
2020-12-20 05:58:23 +01:00
break ;
score + = 3 ;
if ( ! HasDamagingMove ( battlerDef ) | | IsBattlerTrapped ( battlerDef , FALSE ) )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_DO_NOTHING :
//todo - check z splash, z celebrate, z happy hour (lol)
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TELEPORT :
if ( ! ( gBattleTypeFlags & BATTLE_TYPE_TRAINER ) | | GetBattlerSide ( battlerAtk ) ! = B_SIDE_PLAYER )
break ;
//fallthrough
case EFFECT_HIT_ESCAPE :
case EFFECT_PARTING_SHOT :
if ( ! IsDoubleBattle ( ) )
{
2022-01-13 17:28:27 +01:00
switch ( ShouldPivot ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] , move , AI_THINKING_STRUCT - > movesetIndex ) )
2020-12-20 05:58:23 +01:00
{
case 0 : // no
score - = 10 ; // technically should go in CheckBadMove, but this is easier/less computationally demanding
break ;
case 1 : // maybe
break ;
case 2 : // yes
score + = 7 ;
break ;
}
}
else //Double Battle
{
if ( CountUsablePartyMons ( battlerAtk ) = = 0 )
break ; // Can't switch
//if (switchAbility == ABILITY_INTIMIDATE && PartyHasMoveSplit(battlerDef, SPLIT_PHYSICAL))
//score += 7;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_BATON_PASS :
if ( ShouldSwitch ( ) & & ( gBattleMons [ battlerAtk ] . status2 & STATUS2_SUBSTITUTE
| | ( gStatuses3 [ battlerAtk ] & ( STATUS3_ROOTED | STATUS3_AQUA_RING | STATUS3_MAGNET_RISE | STATUS3_POWER_TRICK ) )
| | AnyStatIsRaised ( battlerAtk ) ) )
score + = 5 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_DISABLE :
if ( gDisableStructs [ battlerDef ] . disableTimer = = 0
2022-08-24 03:00:08 +02:00
# if B_MENTAL_HERB >= GEN_5
& & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_MENTAL_HERB // mental herb
# endif
)
2020-12-20 05:58:23 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // AI goes first
2020-12-20 05:58:23 +01:00
{
if ( gLastMoves [ battlerDef ] ! = MOVE_NONE
& & gLastMoves [ battlerDef ] ! = 0xFFFF )
{
/* TODO predicted moves
if ( gLastMoves [ battlerDef ] = = predictedMove )
score + = 3 ;
else */ if ( CanMoveFaintBattler ( gLastMoves [ battlerDef ] , battlerDef , battlerAtk , 1 ) )
2022-07-26 15:53:39 +02:00
score + = 2 ; //Disable move that can kill attacker
2020-12-20 05:58:23 +01:00
}
}
else if ( predictedMove ! = MOVE_NONE & & IS_MOVE_STATUS ( predictedMove ) )
{
score + + ; // Disable annoying status moves
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ENCORE :
if ( gDisableStructs [ battlerDef ] . encoreTimer = = 0
2022-08-24 03:00:08 +02:00
# if B_MENTAL_HERB >= GEN_5
& & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_MENTAL_HERB // mental herb
# endif
)
2020-12-20 05:58:23 +01:00
{
if ( IsEncoreEncouragedEffect ( gBattleMoves [ gLastMoves [ battlerDef ] ] . effect ) )
score + = 3 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PAIN_SPLIT :
{
u16 newHp = ( gBattleMons [ battlerAtk ] . hp + gBattleMons [ battlerDef ] . hp ) / 2 ;
u16 healthBenchmark = ( gBattleMons [ battlerAtk ] . hp * 12 ) / 10 ;
2022-01-13 17:28:27 +01:00
if ( newHp > healthBenchmark & & ShouldAbsorb ( battlerAtk , battlerDef , move , AI_DATA - > simulatedDmg [ battlerAtk ] [ battlerDef ] [ AI_THINKING_STRUCT - > movesetIndex ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
}
2022-08-24 21:56:24 +02:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SLEEP_TALK :
case EFFECT_SNORE :
if ( ! IsWakeupTurn ( battlerAtk ) & & gBattleMons [ battlerAtk ] . status1 & STATUS1_SLEEP )
score + = 10 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_LOCK_ON :
if ( HasMoveEffect ( battlerAtk , EFFECT_OHKO ) )
score + = 3 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_COMPOUND_EYES & & HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 80 , TRUE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2022-01-13 17:28:27 +01:00
else if ( HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 85 , TRUE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2022-01-13 17:28:27 +01:00
else if ( HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 90 , TRUE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SPEED_UP_HIT :
2022-08-01 12:39:51 +02:00
if ( sereneGraceBoost & & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_CONTRARY & & ! WillAIStrikeFirst ( ) )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_DESTINY_BOND :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER & & CanTargetFaintAi ( battlerDef , battlerAtk ) )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SPITE :
//TODO - predicted move
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_WISH :
case EFFECT_HEAL_BELL :
if ( ShouldUseWishAromatherapy ( battlerAtk , battlerDef , move ) )
score + = 7 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_THIEF :
{
bool32 canSteal = FALSE ;
2022-08-24 21:56:24 +02:00
2022-08-24 03:00:08 +02:00
# if B_TRAINERS_KNOCK_OFF_ITEMS == TRUE
2020-12-20 05:58:23 +01:00
canSteal = TRUE ;
# endif
if ( gBattleTypeFlags & BATTLE_TYPE_FRONTIER | | GetBattlerSide ( battlerAtk ) = = B_SIDE_PLAYER )
canSteal = TRUE ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( canSteal & & AI_DATA - > items [ battlerAtk ] = = ITEM_NONE
& & AI_DATA - > items [ battlerDef ] ! = ITEM_NONE
& & CanBattlerGetOrLoseItem ( battlerDef , AI_DATA - > items [ battlerDef ] )
& & CanBattlerGetOrLoseItem ( battlerAtk , AI_DATA - > items [ battlerDef ] )
2020-12-20 05:58:23 +01:00
& & ! HasMoveEffect ( battlerAtk , EFFECT_ACROBATICS )
2022-01-13 17:28:27 +01:00
& & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_STICKY_HOLD )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > holdEffects [ battlerDef ] )
2020-12-20 05:58:23 +01:00
{
case HOLD_EFFECT_NONE :
break ;
case HOLD_EFFECT_CHOICE_BAND :
case HOLD_EFFECT_CHOICE_SCARF :
case HOLD_EFFECT_CHOICE_SPECS :
score + = 2 ;
break ;
case HOLD_EFFECT_TOXIC_ORB :
2022-01-13 17:28:27 +01:00
if ( ShouldPoisonSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_FLAME_ORB :
2022-01-13 17:28:27 +01:00
if ( ShouldBurnSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_BLACK_SLUDGE :
if ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_POISON ) )
score + = 2 ;
break ;
case HOLD_EFFECT_IRON_BALL :
if ( HasMoveEffect ( battlerAtk , EFFECT_FLING ) )
score + = 2 ;
break ;
case HOLD_EFFECT_LAGGING_TAIL :
case HOLD_EFFECT_STICKY_BARB :
break ;
default :
score + + ;
break ;
}
}
break ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_NIGHTMARE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] ! = ABILITY_MAGIC_GUARD
2020-12-20 05:58:23 +01:00
& & ! ( gBattleMons [ battlerDef ] . status2 & STATUS2_NIGHTMARE )
2022-01-13 17:28:27 +01:00
& & ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_COMATOSE | | gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP ) )
2020-12-20 05:58:23 +01:00
{
score + = 5 ;
if ( IsBattlerTrapped ( battlerDef , TRUE ) )
score + = 3 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_CURSE :
if ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_GHOST ) )
{
if ( IsBattlerTrapped ( battlerDef , TRUE ) )
score + = 3 ;
else
score + + ;
break ;
}
else
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_MAGIC_GUARD )
2020-12-20 05:58:23 +01:00
break ;
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] < 8 )
score + = ( 8 - gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] ) ;
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_SPEED ] < 3 )
break ;
else if ( gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ] < 8 )
score + = ( 8 - gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ] ) ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PROTECT :
if ( predictedMove = = 0xFFFF )
predictedMove = MOVE_NONE ;
switch ( move )
{
case MOVE_QUICK_GUARD :
if ( predictedMove ! = MOVE_NONE & & gBattleMoves [ predictedMove ] . priority > 0 )
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
break ;
case MOVE_WIDE_GUARD :
2022-04-27 12:23:20 +02:00
if ( predictedMove ! = MOVE_NONE & & AI_GetBattlerMoveTargetType ( battlerDef , predictedMove ) & ( MOVE_TARGET_FOES_AND_ALLY | MOVE_TARGET_BOTH ) )
2020-12-20 05:58:23 +01:00
{
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
}
2022-06-05 17:09:04 +02:00
else if ( isDoubleBattle & & AI_GetBattlerMoveTargetType ( BATTLE_PARTNER ( battlerAtk ) , AI_DATA - > partnerMove ) & MOVE_TARGET_FOES_AND_ALLY )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_TELEPATHY )
2020-12-20 05:58:23 +01:00
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
}
break ;
case MOVE_CRAFTY_SHIELD :
2022-04-27 12:23:20 +02:00
if ( predictedMove ! = MOVE_NONE & & IS_MOVE_STATUS ( predictedMove ) & & ! ( AI_GetBattlerMoveTargetType ( battlerDef , predictedMove ) & MOVE_TARGET_USER ) )
2020-12-20 05:58:23 +01:00
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
break ;
case MOVE_MAT_BLOCK :
if ( gDisableStructs [ battlerAtk ] . isFirstTurn & & predictedMove ! = MOVE_NONE
2022-04-27 12:23:20 +02:00
& & ! IS_MOVE_STATUS ( predictedMove ) & & ! ( AI_GetBattlerMoveTargetType ( battlerDef , predictedMove ) & MOVE_TARGET_USER ) )
2020-12-20 05:58:23 +01:00
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
break ;
case MOVE_KINGS_SHIELD :
# if (defined SPECIES_AEGISLASH && defined SPECIES_AEGISLASH_BLADE)
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_STANCE_CHANGE //Special logic for Aegislash
& & gBattleMons [ battlerAtk ] . species = = SPECIES_AEGISLASH_BLADE
& & ! IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
{
score + = 3 ;
break ;
}
# endif
//fallthrough
default : // protect
ProtectChecks ( battlerAtk , battlerDef , move , predictedMove , & score ) ;
break ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ENDURE :
if ( CanTargetFaintAi ( battlerDef , battlerAtk ) )
{
if ( gBattleMons [ battlerAtk ] . hp > gBattleMons [ battlerAtk ] . maxHP / 4 // Pinch berry couldn't have activated yet
2022-01-13 17:28:27 +01:00
& & IsPinchBerryItemEffect ( AI_DATA - > holdEffects [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
{
score + = 3 ;
}
else if ( gBattleMons [ battlerAtk ] . hp > 1 ) // Only spam endure for Flail/Reversal if you're not at Min Health
{
if ( HasMoveEffect ( battlerAtk , EFFECT_FLAIL ) | | HasMoveEffect ( battlerAtk , EFFECT_ENDEAVOR ) )
score + = 3 ;
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SPIKES :
case EFFECT_STEALTH_ROCK :
case EFFECT_STICKY_WEB :
case EFFECT_TOXIC_SPIKES :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_MAGIC_BOUNCE | | CountUsablePartyMons ( battlerDef ) = = 0 )
2020-12-20 05:58:23 +01:00
break ;
if ( gDisableStructs [ battlerAtk ] . isFirstTurn )
2022-08-24 21:56:24 +02:00
score + = 2 ;
//TODO - track entire opponent party data to determine hazard effectiveness
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FORESIGHT :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_SCRAPPY )
2020-12-20 05:58:23 +01:00
break ;
else if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] > DEFAULT_STAT_STAGE
| | ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_GHOST )
& & ( HasMoveWithType ( battlerAtk , TYPE_NORMAL )
| | HasMoveWithType ( battlerAtk , TYPE_FIGHTING ) ) ) )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MIRACLE_EYE :
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] > DEFAULT_STAT_STAGE
| | ( IS_BATTLER_OF_TYPE ( battlerDef , TYPE_DARK ) & & ( HasMoveWithType ( battlerAtk , TYPE_PSYCHIC ) ) ) )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PERISH_SONG :
if ( IsBattlerTrapped ( battlerDef , TRUE ) )
score + = 3 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SANDSTORM :
2022-01-13 17:28:27 +01:00
if ( ShouldSetSandstorm ( battlerAtk , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
{
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_SMOOTH_ROCK )
2020-12-20 05:58:23 +01:00
score + + ;
2020-12-20 22:47:20 +01:00
if ( HasMoveEffect ( battlerDef , EFFECT_MORNING_SUN )
| | HasMoveEffect ( battlerDef , EFFECT_SYNTHESIS )
| | HasMoveEffect ( battlerDef , EFFECT_MOONLIGHT ) )
2022-08-24 21:56:24 +02:00
score + = 2 ;
2020-12-20 05:58:23 +01:00
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_HAIL :
2022-01-13 17:28:27 +01:00
if ( ShouldSetHail ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > holdEffects [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
if ( ( HasMoveEffect ( battlerAtk , EFFECT_AURORA_VEIL ) | | HasMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , EFFECT_AURORA_VEIL ) )
2020-12-20 05:58:23 +01:00
& & ShouldSetScreen ( battlerAtk , battlerDef , EFFECT_AURORA_VEIL ) )
score + = 3 ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_ICY_ROCK )
2020-12-20 05:58:23 +01:00
score + + ;
if ( HasMoveEffect ( battlerDef , EFFECT_MORNING_SUN )
| | HasMoveEffect ( battlerDef , EFFECT_SYNTHESIS )
| | HasMoveEffect ( battlerDef , EFFECT_MOONLIGHT ) )
score + = 2 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_RAIN_DANCE :
2022-01-13 17:28:27 +01:00
if ( ShouldSetRain ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > holdEffects [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
{
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_DAMP_ROCK )
2020-12-20 05:58:23 +01:00
score + + ;
if ( HasMoveEffect ( battlerDef , EFFECT_MORNING_SUN )
| | HasMoveEffect ( battlerDef , EFFECT_SYNTHESIS )
| | HasMoveEffect ( battlerDef , EFFECT_MOONLIGHT ) )
score + = 2 ;
2022-01-13 17:28:27 +01:00
if ( HasMoveWithType ( battlerDef , TYPE_FIRE ) | | HasMoveWithType ( BATTLE_PARTNER ( battlerDef ) , TYPE_FIRE ) )
2020-12-20 05:58:23 +01:00
score + + ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SUNNY_DAY :
2022-01-13 17:28:27 +01:00
if ( ShouldSetSun ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > holdEffects [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
{
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_HEAT_ROCK )
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
if ( HasMoveWithType ( battlerDef , TYPE_WATER ) | | HasMoveWithType ( BATTLE_PARTNER ( battlerDef ) , TYPE_WATER ) )
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
if ( HasMoveEffect ( battlerDef , EFFECT_THUNDER ) | | HasMoveEffect ( BATTLE_PARTNER ( battlerDef ) , EFFECT_THUNDER ) )
2020-12-20 05:58:23 +01:00
score + + ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ATTACK_UP_HIT :
2022-08-01 12:39:51 +02:00
if ( sereneGraceBoost )
2020-12-20 05:58:23 +01:00
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FELL_STINGER :
if ( gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] < MAX_STAT_STAGE
2022-01-13 17:28:27 +01:00
& & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_CONTRARY
2021-11-08 08:37:28 +01:00
& & CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) )
2020-12-20 05:58:23 +01:00
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker goes first
2020-12-20 05:58:23 +01:00
score + = 9 ;
else
score + = 3 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_BELLY_DRUM :
2022-01-13 17:28:27 +01:00
if ( ! CanTargetFaintAi ( battlerDef , battlerAtk ) & & HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
score + = ( MAX_STAT_STAGE - gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PSYCH_UP :
case EFFECT_SPECTRAL_THIEF :
// Want to copy positive stat changes
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
2022-08-24 21:56:24 +02:00
{
2020-12-20 05:58:23 +01:00
if ( gBattleMons [ battlerDef ] . statStages [ i ] > gBattleMons [ battlerAtk ] . statStages [ i ] )
{
switch ( i )
{
case STAT_ATK :
if ( HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
score + + ;
break ;
case STAT_SPATK :
if ( HasMoveWithSplit ( battlerAtk , SPLIT_SPECIAL ) )
score + + ;
break ;
case STAT_ACC :
case STAT_EVASION :
case STAT_SPEED :
score + + ;
break ;
case STAT_DEF :
case STAT_SPDEF :
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_STALL )
score + + ;
break ;
}
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SEMI_INVULNERABLE :
score + + ;
if ( predictedMove ! = MOVE_NONE & & ! isDoubleBattle )
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker goes first
2020-12-20 05:58:23 +01:00
{
if ( gBattleMoves [ predictedMove ] . effect = = EFFECT_EXPLOSION
| | gBattleMoves [ predictedMove ] . effect = = EFFECT_PROTECT )
score + = 3 ;
}
else if ( gBattleMoves [ predictedMove ] . effect = = EFFECT_SEMI_INVULNERABLE & & ! ( gStatuses3 [ battlerDef ] & STATUS3_SEMI_INVULNERABLE ) )
{
score + = 3 ;
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_DEFENSE_CURL :
if ( HasMoveEffect ( battlerAtk , EFFECT_ROLLOUT ) & & ! ( gBattleMons [ battlerAtk ] . status2 & STATUS2_DEFENSE_CURL ) )
score + + ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_DEF , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FAKE_OUT :
if ( move = = MOVE_FAKE_OUT // filter out first impression
& & ShouldFakeOut ( battlerAtk , battlerDef , move ) )
score + = 8 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_STOCKPILE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
break ;
if ( HasMoveEffect ( battlerAtk , EFFECT_SWALLOW )
| | HasMoveEffect ( battlerAtk , EFFECT_SPIT_UP ) )
score + = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_DEF , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPDEF , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SPIT_UP :
if ( gDisableStructs [ battlerAtk ] . stockpileCounter > = 2 )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ROLLOUT :
if ( gBattleMons [ battlerAtk ] . status2 & STATUS2_DEFENSE_CURL )
score + = 8 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SWAGGER :
if ( HasMoveEffect ( battlerAtk , EFFECT_FOUL_PLAY )
| | HasMoveEffect ( battlerAtk , EFFECT_PSYCH_UP )
| | HasMoveEffect ( battlerAtk , EFFECT_SPECTRAL_THIEF ) )
score + + ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
score + = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
IncreaseConfusionScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FLATTER :
if ( HasMoveEffect ( battlerAtk , EFFECT_PSYCH_UP )
| | HasMoveEffect ( battlerAtk , EFFECT_SPECTRAL_THIEF ) )
score + = 2 ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
score + = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
IncreaseConfusionScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FURY_CUTTER :
2022-01-13 17:28:27 +01:00
if ( ! isDoubleBattle & & AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_METRONOME )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ATTRACT :
2022-01-13 17:28:27 +01:00
if ( ! isDoubleBattle & & BattlerWillFaintFromSecondaryDamage ( battlerDef , AI_DATA - > abilities [ battlerDef ] )
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER ) // Target goes first
2020-12-20 05:58:23 +01:00
break ; // Don't use if the attract won't have a change to activate
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_ANY
| | ( gBattleMons [ battlerDef ] . status2 & STATUS2_CONFUSION )
| | IsBattlerTrapped ( battlerDef , TRUE ) )
score + = 2 ;
else
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SAFEGUARD :
2021-07-11 00:41:41 +02:00
if ( ! AI_IsTerrainAffected ( battlerAtk , STATUS_FIELD_MISTY_TERRAIN ) | | ! IsBattlerGrounded ( battlerAtk ) )
2020-12-20 05:58:23 +01:00
score + + ;
//if (CountUsablePartyMons(battlerDef) != 0)
//score += 8;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PURSUIT :
/*TODO
if ( IsPredictedToSwitch ( battlerDef , battlerAtk ) )
score + = 3 ;
else if ( IsPredictedToUsePursuitableMove ( battlerDef , battlerAtk ) & & ! MoveWouldHitFirst ( move , battlerAtk , battlerDef ) ) //Pursuit against fast U-Turn
score + = 3 ; */
break ;
case EFFECT_RAPID_SPIN :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPEED , & score ) ; // Gen 8 increases speed
//fallthrough
case EFFECT_DEFOG :
if ( gSideStatuses [ GetBattlerSide ( battlerAtk ) ] & SIDE_STATUS_HAZARDS_ANY & & CountUsablePartyMons ( battlerAtk ) ! = 0 )
{
score + = 3 ;
break ;
}
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
switch ( move )
{
case MOVE_DEFOG :
2021-05-23 20:22:07 +02:00
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & ( SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST ) )
2020-12-20 05:58:23 +01:00
{
score + = 3 ;
}
else if ( ! ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_SPIKES ) ) //Don't blow away hazards if you set them up
{
if ( isDoubleBattle )
{
if ( IsHazardMoveEffect ( gBattleMoves [ AI_DATA - > partnerMove ] . effect ) // Partner is going to set up hazards
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , BATTLE_PARTNER ( battlerAtk ) , move ) = = AI_IS_SLOWER ) // Partner going first
2020-12-20 05:58:23 +01:00
break ; // Don't use Defog if partner is going to set up hazards
}
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
// check defog lowering evasion
2022-01-13 17:28:27 +01:00
if ( ShouldLowerEvasion ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
{
if ( gBattleMons [ battlerDef ] . statStages [ STAT_EVASION ] > 7
2022-01-13 17:28:27 +01:00
| | HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 90 , TRUE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ; // encourage lowering evasion if they are evasive or we have a move with low accuracy
else
score + + ;
}
}
break ;
case MOVE_RAPID_SPIN :
if ( gStatuses3 [ battlerAtk ] & STATUS3_LEECHSEED | | gBattleMons [ battlerAtk ] . status2 & STATUS2_WRAPPED )
score + = 3 ;
break ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TORMENT :
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_WILL_O_WISP :
IncreaseBurnScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_FOLLOW_ME :
if ( isDoubleBattle
& & move ! = MOVE_SPOTLIGHT
2022-01-13 17:28:27 +01:00
& & ! IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] )
& & ( move ! = MOVE_RAGE_POWDER | | IsAffectedByPowder ( battlerDef , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerDef ] ) ) // Rage Powder doesn't affect powder immunities
& & IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
u16 predictedMoveOnPartner = gLastMoves [ BATTLE_PARTNER ( battlerAtk ) ] ;
2020-12-20 05:58:23 +01:00
if ( predictedMoveOnPartner ! = MOVE_NONE & & ! IS_MOVE_STATUS ( predictedMoveOnPartner ) )
score + = 3 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_NATURE_POWER :
2021-01-05 03:39:59 +01:00
return AI_CheckViability ( battlerAtk , battlerDef , GetNaturePowerMove ( ) , score ) ;
2020-12-20 05:58:23 +01:00
case EFFECT_CHARGE :
if ( HasDamagingMoveOfType ( battlerAtk , TYPE_ELECTRIC ) )
score + = 2 ;
2022-07-20 20:44:57 +02:00
# if B_CHARGE_SPDEF_RAISE >= GEN_5
2020-12-20 05:58:23 +01:00
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPDEF , & score ) ;
2022-07-20 20:44:57 +02:00
# endif
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TAUNT :
if ( IS_MOVE_STATUS ( predictedMove ) )
score + = 3 ;
else if ( HasMoveWithSplit ( battlerDef , SPLIT_STATUS ) )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TRICK :
case EFFECT_BESTOW :
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > holdEffects [ battlerAtk ] )
2020-12-20 05:58:23 +01:00
{
case HOLD_EFFECT_CHOICE_SCARF :
score + = 2 ; // assume its beneficial
break ;
case HOLD_EFFECT_CHOICE_BAND :
if ( ! HasMoveWithSplit ( battlerDef , SPLIT_PHYSICAL ) )
score + = 2 ;
break ;
case HOLD_EFFECT_CHOICE_SPECS :
if ( ! HasMoveWithSplit ( battlerDef , SPLIT_SPECIAL ) )
score + = 2 ;
break ;
case HOLD_EFFECT_TOXIC_ORB :
2022-01-13 17:28:27 +01:00
if ( ! ShouldPoisonSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_FLAME_ORB :
2022-01-13 17:28:27 +01:00
if ( ! ShouldBurnSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) & & AI_CanBeBurned ( battlerAtk , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_BLACK_SLUDGE :
2022-01-13 17:28:27 +01:00
if ( ! IS_BATTLER_OF_TYPE ( battlerDef , TYPE_POISON ) & & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_MAGIC_GUARD )
2020-12-20 05:58:23 +01:00
score + = 3 ;
break ;
case HOLD_EFFECT_IRON_BALL :
if ( ! HasMoveEffect ( battlerDef , EFFECT_FLING ) | | ! IsBattlerGrounded ( battlerDef ) )
score + = 2 ;
break ;
case HOLD_EFFECT_LAGGING_TAIL :
case HOLD_EFFECT_STICKY_BARB :
score + = 3 ;
break ;
case HOLD_EFFECT_UTILITY_UMBRELLA :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_SOLAR_POWER & & AI_DATA - > abilities [ battlerAtk ] ! = ABILITY_DRY_SKIN & & AI_WeatherHasEffect ( ) )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > abilities [ battlerDef ] )
2020-12-20 05:58:23 +01:00
{
case ABILITY_SWIFT_SWIM :
2021-11-21 19:40:26 +01:00
if ( gBattleWeather & B_WEATHER_RAIN )
2020-12-20 05:58:23 +01:00
score + = 3 ; // Slow 'em down
break ;
case ABILITY_CHLOROPHYLL :
case ABILITY_FLOWER_GIFT :
2021-11-21 19:40:26 +01:00
if ( gBattleWeather & B_WEATHER_SUN )
2020-12-20 05:58:23 +01:00
score + = 3 ; // Slow 'em down
break ;
}
}
break ;
case HOLD_EFFECT_EJECT_BUTTON :
//if (!IsRaidBattle() && IsDynamaxed(battlerDef) && gNewBS->dynamaxData.timer[battlerDef] > 1 &&
if ( HasDamagingMove ( battlerAtk )
2022-01-13 17:28:27 +01:00
| | ( isDoubleBattle & & IsBattlerAlive ( BATTLE_PARTNER ( battlerAtk ) ) & & HasDamagingMove ( BATTLE_PARTNER ( battlerAtk ) ) ) )
2020-12-20 05:58:23 +01:00
score + = 2 ; // Force 'em out next turn
break ;
default :
2022-01-13 17:28:27 +01:00
if ( move ! = MOVE_BESTOW & & AI_DATA - > items [ battlerAtk ] = = ITEM_NONE )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > holdEffects [ battlerDef ] )
2020-12-20 05:58:23 +01:00
{
case HOLD_EFFECT_CHOICE_BAND :
break ;
case HOLD_EFFECT_TOXIC_ORB :
2022-01-13 17:28:27 +01:00
if ( ShouldPoisonSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_FLAME_ORB :
2022-01-13 17:28:27 +01:00
if ( ShouldBurnSelf ( battlerAtk , AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case HOLD_EFFECT_BLACK_SLUDGE :
2022-01-13 17:28:27 +01:00
if ( IS_BATTLER_OF_TYPE ( battlerAtk , TYPE_POISON ) | | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_MAGIC_GUARD )
2020-12-20 05:58:23 +01:00
score + = 3 ;
break ;
case HOLD_EFFECT_IRON_BALL :
if ( HasMoveEffect ( battlerAtk , EFFECT_FLING ) )
score + = 2 ;
break ;
case HOLD_EFFECT_LAGGING_TAIL :
case HOLD_EFFECT_STICKY_BARB :
break ;
default :
score + + ; //other hold effects generally universally good
break ;
}
}
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_ROLE_PLAY :
2022-01-13 17:28:27 +01:00
if ( ! IsRolePlayBannedAbilityAtk ( AI_DATA - > abilities [ battlerAtk ] )
& & ! IsRolePlayBannedAbility ( AI_DATA - > abilities [ battlerDef ] )
& & ! IsAbilityOfRating ( AI_DATA - > abilities [ battlerAtk ] , 5 )
& & IsAbilityOfRating ( AI_DATA - > abilities [ battlerDef ] , 5 ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_INGRAIN :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_BIG_ROOT )
2020-12-20 05:58:23 +01:00
score + = 3 ;
else
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SUPERPOWER :
case EFFECT_OVERHEAT :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_CONTRARY )
2020-12-20 05:58:23 +01:00
score + = 10 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MAGIC_COAT :
2022-04-27 12:23:20 +02:00
if ( IS_MOVE_STATUS ( predictedMove ) & & AI_GetBattlerMoveTargetType ( battlerDef , predictedMove ) & ( MOVE_TARGET_SELECTED | MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_BOTH ) )
2020-12-20 05:58:23 +01:00
score + = 3 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_RECYCLE :
2021-10-28 23:52:52 +02:00
if ( GetUsedHeldItem ( battlerAtk ) ! = ITEM_NONE )
2020-12-20 05:58:23 +01:00
score + + ;
2021-10-28 23:52:52 +02:00
if ( IsRecycleEncouragedItem ( GetUsedHeldItem ( battlerAtk ) ) )
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_RIPEN )
2021-11-08 17:37:41 +01:00
{
u16 item = GetUsedHeldItem ( battlerAtk ) ;
2021-11-09 03:27:40 +01:00
u16 toHeal = ( ItemId_GetHoldEffectParam ( item ) = = 10 ) ? 10 : gBattleMons [ battlerAtk ] . maxHP / ItemId_GetHoldEffectParam ( item ) ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( IsStatBoostingBerry ( item ) & & AI_DATA - > hpPercents [ battlerAtk ] > 60 )
2021-11-08 17:37:41 +01:00
score + + ;
2022-08-24 21:56:24 +02:00
else if ( ShouldRestoreHpBerry ( battlerAtk , item ) & & ! CanAIFaintTarget ( battlerAtk , battlerDef , 0 )
2021-11-09 03:27:40 +01:00
& & ( ( GetWhoStrikesFirst ( battlerAtk , battlerDef , TRUE ) = = 0 & & CanTargetFaintAiWithMod ( battlerDef , battlerAtk , 0 , 0 ) )
2021-11-09 03:33:00 +01:00
| | ! CanTargetFaintAiWithMod ( battlerDef , battlerAtk , toHeal , 0 ) ) )
2021-11-09 03:27:40 +01:00
score + + ; // Recycle healing berry if we can't otherwise faint the target and the target wont kill us after we activate the berry
2021-11-08 17:37:41 +01:00
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_BRICK_BREAK :
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_REFLECT )
score + + ;
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_LIGHTSCREEN )
score + + ;
if ( gSideStatuses [ GetBattlerSide ( battlerDef ) ] & SIDE_STATUS_AURORA_VEIL )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_KNOCK_OFF :
2022-01-13 17:28:27 +01:00
if ( CanKnockOffItem ( battlerDef , AI_DATA - > items [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
switch ( AI_DATA - > holdEffects [ battlerDef ] )
2020-12-20 05:58:23 +01:00
{
case HOLD_EFFECT_IRON_BALL :
if ( HasMoveEffect ( battlerDef , EFFECT_FLING ) )
score + = 4 ;
break ;
case HOLD_EFFECT_LAGGING_TAIL :
case HOLD_EFFECT_STICKY_BARB :
break ;
default :
score + = 3 ;
break ;
}
}
break ;
case EFFECT_SKILL_SWAP :
2022-01-13 17:28:27 +01:00
if ( GetAbilityRating ( AI_DATA - > abilities [ battlerDef ] ) > GetAbilityRating ( AI_DATA - > abilities [ battlerAtk ] ) )
2020-12-20 05:58:23 +01:00
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_WORRY_SEED :
case EFFECT_GASTRO_ACID :
case EFFECT_SIMPLE_BEAM :
2022-01-13 17:28:27 +01:00
if ( IsAbilityOfRating ( AI_DATA - > abilities [ battlerDef ] , 5 ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case EFFECT_ENTRAINMENT :
2022-01-13 17:28:27 +01:00
if ( IsAbilityOfRating ( AI_DATA - > abilities [ battlerDef ] , 5 ) | | GetAbilityRating ( AI_DATA - > abilities [ battlerAtk ] ) < = 0 )
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] ! = AI_DATA - > abilities [ battlerAtk ] & & ! ( gStatuses3 [ battlerDef ] & STATUS3_GASTRO_ACID ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
2022-08-24 21:56:24 +02:00
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_IMPRISON :
if ( predictedMove ! = MOVE_NONE & & HasMove ( battlerAtk , predictedMove ) )
score + = 3 ;
else if ( gDisableStructs [ battlerAtk ] . isFirstTurn = = 0 )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_REFRESH :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_ANY )
score + = 2 ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_PSYCHO_SHIFT :
if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PSN_ANY )
IncreasePoisonScore ( battlerAtk , battlerDef , move , & score ) ;
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_BURN )
IncreaseBurnScore ( battlerAtk , battlerDef , move , & score ) ;
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_PARALYSIS )
IncreaseParalyzeScore ( battlerAtk , battlerDef , move , & score ) ;
else if ( gBattleMons [ battlerAtk ] . status1 & STATUS1_SLEEP )
IncreaseSleepScore ( battlerAtk , battlerDef , move , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_GRUDGE :
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_SNATCH :
if ( predictedMove ! = MOVE_NONE & & TestMoveFlags ( predictedMove , FLAG_SNATCH_AFFECTED ) )
score + = 3 ; // Steal move
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_MUD_SPORT :
if ( ! HasMoveWithType ( battlerAtk , TYPE_ELECTRIC ) & & HasMoveWithType ( battlerDef , TYPE_ELECTRIC ) )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_WATER_SPORT :
if ( ! HasMoveWithType ( battlerAtk , TYPE_FIRE ) & & ( HasMoveWithType ( battlerDef , TYPE_FIRE ) ) )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_TICKLE :
if ( gBattleMons [ battlerDef ] . statStages [ STAT_DEF ] > 4 & & HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL )
2022-01-13 17:28:27 +01:00
& & AI_DATA - > abilities [ battlerDef ] ! = ABILITY_CONTRARY & & ShouldLowerDefense ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
{
score + = 2 ;
}
2022-01-13 17:28:27 +01:00
else if ( ShouldLowerAttack ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
{
score + = 2 ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_COSMIC_POWER :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_DEF , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPDEF , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_BULK_UP :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_DEF , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_CALM_MIND :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPATK , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPDEF , & score ) ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_GEOMANCY :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_POWER_HERB )
2020-12-20 05:58:23 +01:00
score + = 3 ;
//fallthrough
case EFFECT_QUIVER_DANCE :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPEED , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPATK , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPDEF , & score ) ;
break ;
case EFFECT_SHELL_SMASH :
2022-07-26 15:53:39 +02:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_RESTORE_STATS )
score + = 1 ;
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPEED , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPATK , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
break ;
case EFFECT_DRAGON_DANCE :
case EFFECT_SHIFT_GEAR :
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPEED , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_ATK , & score ) ;
break ;
case EFFECT_GUARD_SWAP :
if ( gBattleMons [ battlerDef ] . statStages [ STAT_DEF ] > gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ]
& & gBattleMons [ battlerDef ] . statStages [ STAT_SPDEF ] > = gBattleMons [ battlerAtk ] . statStages [ STAT_SPDEF ] )
score + + ;
else if ( gBattleMons [ battlerDef ] . statStages [ STAT_SPDEF ] > gBattleMons [ battlerAtk ] . statStages [ STAT_SPDEF ]
& & gBattleMons [ battlerDef ] . statStages [ STAT_DEF ] > = gBattleMons [ battlerAtk ] . statStages [ STAT_DEF ] )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_POWER_SWAP :
if ( gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] > gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ]
& & gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] > = gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ] )
score + + ;
else if ( gBattleMons [ battlerDef ] . statStages [ STAT_SPATK ] > gBattleMons [ battlerAtk ] . statStages [ STAT_SPATK ]
& & gBattleMons [ battlerDef ] . statStages [ STAT_ATK ] > = gBattleMons [ battlerAtk ] . statStages [ STAT_ATK ] )
score + + ;
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_POWER_TRICK :
if ( ! ( gStatuses3 [ battlerAtk ] & STATUS3_POWER_TRICK ) )
{
if ( gBattleMons [ battlerAtk ] . defense > gBattleMons [ battlerAtk ] . attack & & HasMoveWithSplit ( battlerAtk , SPLIT_PHYSICAL ) )
score + = 2 ;
break ;
}
2020-12-16 05:57:33 +01:00
break ;
2020-12-20 05:58:23 +01:00
case EFFECT_HEART_SWAP :
{
bool32 hasHigherStat = FALSE ;
//Only use if all target stats are >= attacker stats to prevent infinite loop
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
if ( gBattleMons [ battlerDef ] . statStages [ i ] < gBattleMons [ battlerAtk ] . statStages [ i ] )
break ;
if ( gBattleMons [ battlerDef ] . statStages [ i ] > gBattleMons [ battlerAtk ] . statStages [ i ] )
hasHigherStat = TRUE ;
}
if ( hasHigherStat & & i = = NUM_BATTLE_STATS )
score + + ;
}
break ;
case EFFECT_SPEED_SWAP :
// TODO this is cheating a bit...
if ( gBattleMons [ battlerDef ] . speed > gBattleMons [ battlerAtk ] . speed )
score + = 3 ;
break ;
case EFFECT_GUARD_SPLIT :
{
// TODO also kind of cheating...
u16 newDefense = ( gBattleMons [ battlerAtk ] . defense + gBattleMons [ battlerDef ] . defense ) / 2 ;
u16 newSpDef = ( gBattleMons [ battlerAtk ] . spDefense + gBattleMons [ battlerDef ] . spDefense ) / 2 ;
if ( ( newDefense > gBattleMons [ battlerAtk ] . defense & & newSpDef > = gBattleMons [ battlerAtk ] . spDefense )
| | ( newSpDef > gBattleMons [ battlerAtk ] . spDefense & & newDefense > = gBattleMons [ battlerAtk ] . defense ) )
score + + ;
}
break ;
case EFFECT_POWER_SPLIT :
{
u16 newAttack = ( gBattleMons [ battlerAtk ] . attack + gBattleMons [ battlerDef ] . attack ) / 2 ;
u16 newSpAtk = ( gBattleMons [ battlerAtk ] . spAttack + gBattleMons [ battlerDef ] . spAttack ) / 2 ;
if ( ( newAttack > gBattleMons [ battlerAtk ] . attack & & newSpAtk > = gBattleMons [ battlerAtk ] . spAttack )
| | ( newSpAtk > gBattleMons [ battlerAtk ] . spAttack & & newAttack > = gBattleMons [ battlerAtk ] . attack ) )
score + + ;
}
break ;
case EFFECT_BUG_BITE : // And pluck
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_SUBSTITUTE | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_STICKY_HOLD )
2020-12-20 05:58:23 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( ItemId_GetPocket ( AI_DATA - > items [ battlerDef ] ) = = POCKET_BERRIES )
2020-12-20 05:58:23 +01:00
score + = 3 ;
break ;
case EFFECT_INCINERATE :
2022-01-13 17:28:27 +01:00
if ( gBattleMons [ battlerDef ] . status2 & STATUS2_SUBSTITUTE | | AI_DATA - > abilities [ battlerDef ] = = ABILITY_STICKY_HOLD )
2020-12-20 05:58:23 +01:00
break ;
2022-01-13 17:28:27 +01:00
else if ( ItemId_GetPocket ( AI_DATA - > items [ battlerDef ] ) = = POCKET_BERRIES | | AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_GEMS )
2020-12-20 05:58:23 +01:00
score + = 3 ;
break ;
case EFFECT_SMACK_DOWN :
if ( ! IsBattlerGrounded ( battlerDef ) )
score + = 3 ;
break ;
2021-11-03 05:23:33 +01:00
case EFFECT_RELIC_SONG :
2020-12-20 05:58:23 +01:00
# if (defined SPECIES_MELOETTA && defined SPECIES_MELOETTA_PIROUETTE)
2021-11-21 18:31:25 +01:00
if ( ! ( gBattleMons [ battlerAtk ] . status2 & STATUS2_TRANSFORMED ) ) // Don't try to change form if it's transformed.
{
2022-07-26 23:00:53 +02:00
if ( gBattleMons [ battlerAtk ] . species = = SPECIES_MELOETTA & & gBattleMons [ battlerDef ] . defense < gBattleMons [ battlerDef ] . spDefense )
score + = 3 ; // Change to Pirouette if can do more damage
else if ( gBattleMons [ battlerAtk ] . species = = SPECIES_MELOETTA_PIROUETTE & & gBattleMons [ battlerDef ] . spDefense < gBattleMons [ battlerDef ] . defense )
2021-11-21 18:31:25 +01:00
score + = 3 ; // Change to Aria if can do more damage
}
2020-12-20 05:58:23 +01:00
# endif
break ;
case EFFECT_ELECTRIC_TERRAIN :
case EFFECT_MISTY_TERRAIN :
if ( gStatuses3 [ battlerAtk ] & STATUS3_YAWN & & IsBattlerGrounded ( battlerAtk ) )
score + = 10 ;
//fallthrough
2022-08-24 21:56:24 +02:00
case EFFECT_GRASSY_TERRAIN :
2020-12-20 05:58:23 +01:00
case EFFECT_PSYCHIC_TERRAIN :
score + = 2 ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_TERRAIN_EXTENDER )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case EFFECT_PLEDGE :
if ( isDoubleBattle )
{
2022-01-13 17:28:27 +01:00
if ( HasMoveEffect ( BATTLE_PARTNER ( battlerAtk ) , EFFECT_PLEDGE ) )
2020-12-20 05:58:23 +01:00
score + = 3 ; // Partner might use pledge move
}
break ;
case EFFECT_TRICK_ROOM :
if ( ! ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM ) & & GetBattlerSideSpeedAverage ( battlerAtk ) < GetBattlerSideSpeedAverage ( battlerDef ) )
score + = 3 ;
else if ( ( gFieldStatuses & STATUS_FIELD_TRICK_ROOM ) & & GetBattlerSideSpeedAverage ( battlerAtk ) > = GetBattlerSideSpeedAverage ( battlerDef ) )
score + = 3 ;
break ;
case EFFECT_MAGIC_ROOM :
score + + ;
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_NONE & & AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_NONE )
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
if ( isDoubleBattle & & AI_DATA - > holdEffects [ BATTLE_PARTNER ( battlerAtk ) ] = = HOLD_EFFECT_NONE & & AI_DATA - > holdEffects [ BATTLE_PARTNER ( battlerDef ) ] ! = HOLD_EFFECT_NONE )
2020-12-20 05:58:23 +01:00
score + + ;
break ;
case EFFECT_WONDER_ROOM :
if ( ( HasMoveWithSplit ( battlerDef , SPLIT_PHYSICAL ) & & gBattleMons [ battlerAtk ] . defense < gBattleMons [ battlerAtk ] . spDefense )
| | ( HasMoveWithSplit ( battlerDef , SPLIT_SPECIAL ) & & gBattleMons [ battlerAtk ] . spDefense < gBattleMons [ battlerAtk ] . defense ) )
score + = 2 ;
break ;
case EFFECT_GRAVITY :
if ( ! ( gFieldStatuses & STATUS_FIELD_GRAVITY ) )
{
if ( HasSleepMoveWithLowAccuracy ( battlerAtk , battlerDef ) ) // Has Gravity for a move like Hypnosis
IncreaseSleepScore ( battlerAtk , battlerDef , move , & score ) ;
2022-01-13 17:28:27 +01:00
else if ( HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 90 , FALSE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
else
score + + ;
}
break ;
case EFFECT_ION_DELUGE :
2022-01-13 17:28:27 +01:00
if ( ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_VOLT_ABSORB
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_MOTOR_DRIVE
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_LIGHTNING_ROD )
2020-12-20 05:58:23 +01:00
& & gBattleMoves [ predictedMove ] . type = = TYPE_NORMAL )
score + = 2 ;
break ;
case EFFECT_FLING :
/* TODO
2022-01-13 17:28:27 +01:00
switch ( gFlingTable [ AI_DATA - > items [ battlerAtk ] ] . effect )
2020-12-20 05:58:23 +01:00
{
case MOVE_EFFECT_BURN :
IncreaseBurnScore ( battlerAtk , battlerDef , move , & score ) ;
break ;
case MOVE_EFFECT_FLINCH :
2022-01-13 17:28:27 +01:00
score + = ShouldTryToFlinch ( battlerAtk , battlerDef , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , move ) ;
2020-12-20 05:58:23 +01:00
break ;
case MOVE_EFFECT_PARALYSIS :
IncreaseParalyzeScore ( battlerAtk , battlerDef , move , & score ) ;
break ;
case MOVE_EFFECT_POISON :
case MOVE_EFFECT_TOXIC :
IncreasePoisonScore ( battlerAtk , battlerDef , move , & score ) ;
break ;
case MOVE_EFFECT_FREEZE :
if ( AI_CanFreeze ( battlerAtk , battlerDef ) )
score + = 3 ;
break ;
} */
break ;
case EFFECT_FEINT :
if ( gBattleMoves [ predictedMove ] . effect = = EFFECT_PROTECT )
score + = 3 ;
break ;
case EFFECT_EMBARGO :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerDef ] ! = HOLD_EFFECT_NONE )
2020-12-20 05:58:23 +01:00
score + + ;
break ;
case EFFECT_POWDER :
if ( predictedMove ! = MOVE_NONE & & ! IS_MOVE_STATUS ( predictedMove ) & & gBattleMoves [ predictedMove ] . type = = TYPE_FIRE )
score + = 3 ;
break ;
case EFFECT_TELEKINESIS :
2022-01-13 17:28:27 +01:00
if ( HasMoveWithLowAccuracy ( battlerAtk , battlerDef , 90 , FALSE , AI_DATA - > abilities [ battlerAtk ] , AI_DATA - > abilities [ battlerDef ] , AI_DATA - > holdEffects [ battlerAtk ] , AI_DATA - > holdEffects [ battlerDef ] )
2020-12-20 05:58:23 +01:00
| | ! IsBattlerGrounded ( battlerDef ) )
score + + ;
break ;
case EFFECT_THROAT_CHOP :
2022-06-05 17:09:04 +02:00
if ( predictedMove ! = MOVE_NONE & & TestMoveFlags ( predictedMove , FLAG_SOUND ) & & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER )
2020-12-20 05:58:23 +01:00
score + = 3 ; // Ai goes first and predicts the target will use a sound move
else if ( TestMoveFlagsInMoveset ( battlerDef , FLAG_SOUND ) )
score + = 3 ;
break ;
case EFFECT_HEAL_BLOCK :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER & & predictedMove ! = MOVE_NONE & & IsHealingMoveEffect ( gBattleMoves [ predictedMove ] . effect ) )
2020-12-20 05:58:23 +01:00
score + = 3 ; // Try to cancel healing move
2022-01-13 17:28:27 +01:00
else if ( HasHealingEffect ( battlerDef ) | | AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_LEFTOVERS
| | ( AI_DATA - > holdEffects [ battlerDef ] = = HOLD_EFFECT_BLACK_SLUDGE & & IS_BATTLER_OF_TYPE ( battlerDef , TYPE_POISON ) ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case EFFECT_SOAK :
if ( HasMoveWithType ( battlerAtk , TYPE_ELECTRIC ) | | HasMoveWithType ( battlerAtk , TYPE_GRASS ) | | HasMoveEffect ( battlerAtk , EFFECT_FREEZE_DRY ) )
score + = 2 ; // Get some super effective moves
break ;
case EFFECT_THIRD_TYPE :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > abilities [ battlerDef ] = = ABILITY_WONDER_GUARD )
2020-12-20 05:58:23 +01:00
score + = 2 ; // Give target more weaknesses
break ;
case EFFECT_ELECTRIFY :
if ( predictedMove ! = MOVE_NONE & & gBattleMoves [ predictedMove ] . type = = TYPE_NORMAL
2022-01-13 17:28:27 +01:00
& & ( AI_DATA - > abilities [ battlerAtk ] = = ABILITY_VOLT_ABSORB
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_MOTOR_DRIVE
| | AI_DATA - > abilities [ battlerAtk ] = = ABILITY_LIGHTNING_ROD ) )
2020-12-20 05:58:23 +01:00
{
score + = 3 ;
}
break ;
case EFFECT_TOPSY_TURVY :
if ( CountPositiveStatStages ( battlerDef ) > CountNegativeStatStages ( battlerDef ) )
score + + ;
break ;
case EFFECT_FAIRY_LOCK :
if ( ! IsBattlerTrapped ( battlerDef , TRUE ) )
{
if ( ShouldTrap ( battlerAtk , battlerDef , move ) )
score + = 8 ;
}
break ;
case EFFECT_QUASH :
if ( isDoubleBattle
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( BATTLE_PARTNER ( battlerAtk ) , battlerDef , AI_DATA - > partnerMove ) = = AI_IS_SLOWER ) // Attacker partner wouldn't go before target
2020-12-20 05:58:23 +01:00
score + + ;
break ;
case EFFECT_TAILWIND :
if ( GetBattlerSideSpeedAverage ( battlerAtk ) < GetBattlerSideSpeedAverage ( battlerDef ) )
score + = 2 ;
break ;
case EFFECT_LUCKY_CHANT :
if ( ! isDoubleBattle )
{
score + + ;
}
else
{
if ( CountUsablePartyMons ( battlerDef ) > 0 )
score + = 8 ;
}
break ;
case EFFECT_MAGNET_RISE :
if ( IsBattlerGrounded ( battlerAtk ) & & HasDamagingMoveOfType ( battlerDef , TYPE_ELECTRIC )
& & ! ( AI_GetTypeEffectiveness ( MOVE_EARTHQUAKE , battlerDef , battlerAtk ) = = AI_EFFECTIVENESS_x0 ) ) // Doesn't resist ground move
{
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Attacker goes first
2021-09-28 03:03:27 +02:00
{
2020-12-20 05:58:23 +01:00
if ( gBattleMoves [ predictedMove ] . type = = TYPE_GROUND )
score + = 3 ; // Cause the enemy's move to fail
break ;
}
else // Opponent Goes First
{
if ( HasDamagingMoveOfType ( battlerDef , TYPE_GROUND ) )
score + = 2 ;
break ;
}
}
break ;
case EFFECT_CAMOUFLAGE :
2022-06-05 17:09:04 +02:00
if ( predictedMove ! = MOVE_NONE & & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER // Attacker goes first
2020-12-20 05:58:23 +01:00
& & ! IS_MOVE_STATUS ( move ) & & AI_GetTypeEffectiveness ( predictedMove , battlerDef , battlerAtk ) ! = AI_EFFECTIVENESS_x0 )
score + + ;
break ;
case EFFECT_FLAME_BURST :
if ( isDoubleBattle )
{
2022-01-13 17:28:27 +01:00
if ( IsBattlerAlive ( BATTLE_PARTNER ( battlerDef ) )
& & AI_DATA - > hpPercents [ BATTLE_PARTNER ( battlerDef ) ] < 12
& & AI_DATA - > abilities [ BATTLE_PARTNER ( battlerDef ) ] ! = ABILITY_MAGIC_GUARD
& & ! IS_BATTLER_OF_TYPE ( BATTLE_PARTNER ( battlerDef ) , TYPE_FIRE ) )
2020-12-20 05:58:23 +01:00
score + + ;
}
break ;
case EFFECT_TOXIC_THREAD :
IncreasePoisonScore ( battlerAtk , battlerDef , move , & score ) ;
IncreaseStatUpScore ( battlerAtk , battlerDef , STAT_SPEED , & score ) ;
break ;
case EFFECT_TWO_TURNS_ATTACK :
case EFFECT_SKULL_BASH :
2021-11-21 19:40:26 +01:00
case EFFECT_SOLAR_BEAM :
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > holdEffects [ battlerAtk ] = = HOLD_EFFECT_POWER_HERB )
2020-12-20 05:58:23 +01:00
score + = 2 ;
break ;
case EFFECT_COUNTER :
2022-01-13 17:28:27 +01:00
if ( ! IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) & & predictedMove ! = MOVE_NONE )
2020-12-20 05:58:23 +01:00
{
if ( gDisableStructs [ battlerDef ] . tauntTimer ! = 0 )
score + + ; // target must use damaging move
if ( GetMoveDamageResult ( predictedMove ) > = MOVE_POWER_GOOD & & GetBattleMoveSplit ( predictedMove ) = = SPLIT_PHYSICAL )
score + = 3 ;
}
break ;
case EFFECT_MIRROR_COAT :
2022-01-13 17:28:27 +01:00
if ( ! IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) & & predictedMove ! = MOVE_NONE )
2020-12-20 05:58:23 +01:00
{
if ( gDisableStructs [ battlerDef ] . tauntTimer ! = 0 )
score + + ; // target must use damaging move
if ( GetMoveDamageResult ( predictedMove ) > = MOVE_POWER_GOOD & & GetBattleMoveSplit ( predictedMove ) = = SPLIT_SPECIAL )
score + = 3 ;
}
break ;
case EFFECT_FLAIL :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_FASTER ) // Ai goes first
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < 20 )
2020-12-20 05:58:23 +01:00
score + + ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 8 )
2020-12-20 05:58:23 +01:00
score + = 2 ;
}
break ;
case EFFECT_SHORE_UP :
2021-11-21 19:40:26 +01:00
if ( AI_WeatherHasEffect ( ) & & ( gBattleWeather & B_WEATHER_SANDSTORM )
2020-12-20 05:58:23 +01:00
& & ShouldRecover ( battlerAtk , battlerDef , move , 67 ) )
score + = 3 ;
else if ( ShouldRecover ( battlerAtk , battlerDef , move , 50 ) )
score + = 2 ;
break ;
case EFFECT_FACADE :
if ( gBattleMons [ battlerAtk ] . status1 & ( STATUS1_POISON | STATUS1_BURN | STATUS1_PARALYSIS | STATUS1_TOXIC_POISON ) )
score + + ;
break ;
case EFFECT_FOCUS_PUNCH :
if ( ! isDoubleBattle & & effectiveness > AI_EFFECTIVENESS_x0_5 )
{
2022-01-13 17:28:27 +01:00
if ( IsBattlerIncapacitated ( battlerDef , AI_DATA - > abilities [ battlerDef ] ) )
2020-12-20 05:58:23 +01:00
score + = 2 ;
else if ( gBattleMons [ battlerDef ] . status2 & ( STATUS2_INFATUATION | STATUS2_CONFUSION ) )
score + + ;
}
break ;
case EFFECT_SMELLINGSALT :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_PARALYSIS )
score + = 2 ;
break ;
case EFFECT_WAKE_UP_SLAP :
if ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP )
score + = 2 ;
break ;
case EFFECT_REVENGE :
if ( ! ( gBattleMons [ battlerDef ] . status1 & STATUS1_SLEEP )
& & ! ( gBattleMons [ battlerDef ] . status2 & ( STATUS2_INFATUATION | STATUS2_CONFUSION ) ) )
score + = 2 ;
break ;
case EFFECT_ENDEAVOR :
2022-06-05 17:09:04 +02:00
if ( AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER ) // Opponent faster
2020-12-20 05:58:23 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] < 40 )
2020-12-20 05:58:23 +01:00
score + + ;
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 50 )
2020-12-20 05:58:23 +01:00
{
score + + ;
}
break ;
//case EFFECT_EXTREME_EVOBOOST: // TODO
//break;
//case EFFECT_CLANGOROUS_SOUL: // TODO
//break;
//case EFFECT_NO_RETREAT: // TODO
//break;
//case EFFECT_SKY_DROP
//break;
} // move effect checks
2022-08-24 21:56:24 +02:00
2020-12-20 05:58:23 +01:00
return score ;
2020-12-16 05:57:33 +01:00
}
2020-12-20 06:07:21 +01:00
// Effects that are encouraged on the first turn of battle
2020-12-20 05:58:23 +01:00
static s16 AI_SetupFirstTurn ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 06:07:21 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef )
| | gBattleResults . battleTurnCounter ! = 0 )
return score ;
2022-08-24 21:56:24 +02:00
if ( AI_THINKING_STRUCT - > aiFlags & AI_FLAG_SMART_SWITCHING
2022-06-05 17:09:04 +02:00
& & AI_WhoStrikesFirst ( battlerAtk , battlerDef , move ) = = AI_IS_SLOWER
2021-02-14 17:20:42 +01:00
& & CanTargetFaintAi ( battlerDef , battlerAtk )
& & GetMovePriority ( battlerAtk , move ) = = 0 )
{
RETURN_SCORE_MINUS ( 20 ) ; // No point in setting up if you will faint. Should just switch if possible..
}
2022-08-24 21:56:24 +02:00
2021-02-14 17:20:42 +01:00
// check effects to prioritize first turn
2020-12-20 06:12:31 +01:00
switch ( gBattleMoves [ move ] . effect )
2020-12-20 06:07:21 +01:00
{
case EFFECT_ATTACK_UP :
case EFFECT_DEFENSE_UP :
case EFFECT_SPEED_UP :
case EFFECT_SPECIAL_ATTACK_UP :
case EFFECT_SPECIAL_DEFENSE_UP :
case EFFECT_ACCURACY_UP :
case EFFECT_EVASION_UP :
case EFFECT_ATTACK_DOWN :
case EFFECT_DEFENSE_DOWN :
case EFFECT_SPEED_DOWN :
case EFFECT_SPECIAL_ATTACK_DOWN :
case EFFECT_SPECIAL_DEFENSE_DOWN :
case EFFECT_ACCURACY_DOWN :
case EFFECT_EVASION_DOWN :
case EFFECT_CONVERSION :
case EFFECT_LIGHT_SCREEN :
case EFFECT_FOCUS_ENERGY :
case EFFECT_CONFUSE :
case EFFECT_ATTACK_UP_2 :
case EFFECT_DEFENSE_UP_2 :
2020-12-20 06:51:25 +01:00
case EFFECT_DEFENSE_UP_3 :
2020-12-20 06:07:21 +01:00
case EFFECT_SPEED_UP_2 :
case EFFECT_SPECIAL_ATTACK_UP_2 :
2020-12-20 06:51:25 +01:00
case EFFECT_SPECIAL_ATTACK_UP_3 :
2020-12-20 06:07:21 +01:00
case EFFECT_SPECIAL_DEFENSE_UP_2 :
case EFFECT_ACCURACY_UP_2 :
case EFFECT_EVASION_UP_2 :
case EFFECT_ATTACK_DOWN_2 :
case EFFECT_DEFENSE_DOWN_2 :
case EFFECT_SPEED_DOWN_2 :
case EFFECT_SPECIAL_ATTACK_DOWN_2 :
case EFFECT_SPECIAL_DEFENSE_DOWN_2 :
case EFFECT_ACCURACY_DOWN_2 :
case EFFECT_EVASION_DOWN_2 :
case EFFECT_REFLECT :
case EFFECT_POISON :
case EFFECT_PARALYZE :
case EFFECT_SUBSTITUTE :
case EFFECT_LEECH_SEED :
case EFFECT_MINIMIZE :
case EFFECT_CURSE :
case EFFECT_SWAGGER :
case EFFECT_CAMOUFLAGE :
case EFFECT_YAWN :
case EFFECT_DEFENSE_CURL :
case EFFECT_TORMENT :
case EFFECT_FLATTER :
case EFFECT_WILL_O_WISP :
case EFFECT_INGRAIN :
case EFFECT_IMPRISON :
case EFFECT_TEETER_DANCE :
case EFFECT_TICKLE :
case EFFECT_COSMIC_POWER :
case EFFECT_BULK_UP :
case EFFECT_CALM_MIND :
case EFFECT_ACUPRESSURE :
case EFFECT_AUTOTOMIZE :
case EFFECT_SHIFT_GEAR :
case EFFECT_SHELL_SMASH :
case EFFECT_GROWTH :
case EFFECT_QUIVER_DANCE :
case EFFECT_ATTACK_SPATK_UP :
case EFFECT_ATTACK_ACCURACY_UP :
case EFFECT_PSYCHIC_TERRAIN :
case EFFECT_GRASSY_TERRAIN :
case EFFECT_ELECTRIC_TERRAIN :
case EFFECT_MISTY_TERRAIN :
case EFFECT_STEALTH_ROCK :
case EFFECT_TOXIC_SPIKES :
case EFFECT_TRICK_ROOM :
case EFFECT_WONDER_ROOM :
case EFFECT_MAGIC_ROOM :
case EFFECT_TAILWIND :
case EFFECT_DRAGON_DANCE :
case EFFECT_STICKY_WEB :
case EFFECT_RAIN_DANCE :
case EFFECT_SUNNY_DAY :
case EFFECT_SANDSTORM :
case EFFECT_HAIL :
case EFFECT_GEOMANCY :
score + = 2 ;
break ;
default :
break ;
}
2022-08-24 21:56:24 +02:00
2020-12-20 06:07:21 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 06:51:25 +01:00
// Adds score bonus to 'riskier' move effects and high crit moves
2020-12-20 05:58:23 +01:00
static s16 AI_Risky ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 06:12:31 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
return score ;
2022-08-24 21:56:24 +02:00
2020-12-20 06:12:31 +01:00
if ( TestMoveFlags ( move , FLAG_HIGH_CRIT ) )
score + = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 06:12:31 +01:00
switch ( gBattleMoves [ move ] . effect )
{
case EFFECT_SLEEP :
case EFFECT_EXPLOSION :
case EFFECT_MIRROR_MOVE :
case EFFECT_OHKO :
case EFFECT_CONFUSE :
case EFFECT_METRONOME :
case EFFECT_PSYWAVE :
case EFFECT_COUNTER :
case EFFECT_DESTINY_BOND :
case EFFECT_SWAGGER :
case EFFECT_ATTRACT :
case EFFECT_PRESENT :
case EFFECT_ALL_STATS_UP_HIT :
case EFFECT_BELLY_DRUM :
case EFFECT_MIRROR_COAT :
case EFFECT_FOCUS_PUNCH :
case EFFECT_REVENGE :
case EFFECT_TEETER_DANCE :
if ( Random ( ) & 1 )
score + = 2 ;
break ;
default :
break ;
}
2022-08-24 21:56:24 +02:00
2020-12-20 06:12:31 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 06:51:25 +01:00
// Adds score bonus to best powered move
2020-12-20 05:58:23 +01:00
static s16 AI_PreferStrongestMove ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 06:51:25 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
return score ;
2022-08-24 21:56:24 +02:00
2020-12-20 06:51:25 +01:00
if ( GetMoveDamageResult ( move ) = = MOVE_POWER_BEST )
score + = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 06:51:25 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 06:51:25 +01:00
// Prefers moves that are good for baton pass
2020-12-20 05:58:23 +01:00
static s16 AI_PreferBatonPass ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 06:51:25 +01:00
u32 i ;
2022-08-24 21:56:24 +02:00
2020-12-20 06:51:25 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef )
| | CountUsablePartyMons ( battlerAtk ) = = 0
2021-08-12 01:33:10 +02:00
| | GetMoveDamageResult ( move ) ! = MOVE_POWER_OTHER
2020-12-20 06:51:25 +01:00
| | ! HasMoveEffect ( battlerAtk , EFFECT_BATON_PASS )
| | IsBattlerTrapped ( battlerAtk , TRUE ) )
return score ;
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
if ( IsStatRaisingEffect ( gBattleMoves [ move ] . effect ) )
2020-12-20 06:51:25 +01:00
{
if ( gBattleResults . battleTurnCounter = = 0 )
score + = 5 ;
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] < 60 )
2020-12-20 06:51:25 +01:00
score - = 10 ;
else
2022-08-24 21:56:24 +02:00
score + + ;
2020-12-20 22:47:20 +01:00
}
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
// other specific checks
switch ( gBattleMoves [ move ] . effect )
{
2020-12-20 06:51:25 +01:00
case EFFECT_INGRAIN :
if ( ! ( gStatuses3 [ battlerAtk ] & STATUS3_ROOTED ) )
score + = 2 ;
break ;
case EFFECT_AQUA_RING :
if ( ! ( gStatuses3 [ battlerAtk ] & STATUS3_AQUA_RING ) )
score + = 2 ;
break ;
case EFFECT_PROTECT :
if ( gLastMoves [ battlerAtk ] = = MOVE_PROTECT | | gLastMoves [ battlerAtk ] = = MOVE_DETECT )
score - = 2 ;
else
score + = 2 ;
break ;
case EFFECT_BATON_PASS :
for ( i = STAT_ATK ; i < NUM_BATTLE_STATS ; i + + )
{
IncreaseStatUpScore ( battlerAtk , battlerDef , i , & score ) ;
}
if ( gStatuses3 [ battlerAtk ] & ( STATUS3_ROOTED | STATUS3_AQUA_RING ) )
score + = 2 ;
if ( gStatuses3 [ battlerAtk ] & STATUS3_LEECHSEED )
2022-08-24 21:56:24 +02:00
score - = 3 ;
2020-12-20 06:51:25 +01:00
break ;
default :
break ;
}
2022-08-24 21:56:24 +02:00
2020-12-20 06:51:25 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 05:58:23 +01:00
static s16 AI_HPAware ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
2020-12-20 22:47:20 +01:00
u16 effect = gBattleMoves [ move ] . effect ;
u8 moveType = gBattleMoves [ move ] . type ;
2021-10-06 10:53:30 +02:00
SetTypeBeforeUsingMove ( move , battlerAtk ) ;
GET_MOVE_TYPE ( move , moveType ) ;
2020-12-20 22:47:20 +01:00
if ( IsTargetingPartner ( battlerAtk , battlerDef ) )
{
if ( ( effect = = EFFECT_HEAL_PULSE | | effect = = EFFECT_HIT_ENEMY_HEAL_ALLY )
2022-01-13 17:28:27 +01:00
| | ( moveType = = TYPE_ELECTRIC & & AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_VOLT_ABSORB )
| | ( moveType = = TYPE_WATER & & ( AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_DRY_SKIN | | AI_DATA - > abilities [ BATTLE_PARTNER ( battlerAtk ) ] = = ABILITY_WATER_ABSORB ) ) )
2020-12-20 22:47:20 +01:00
{
2022-05-07 15:56:32 +02:00
if ( gStatuses3 [ battlerDef ] & STATUS3_HEAL_BLOCK )
return 0 ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( CanTargetFaintAi ( FOE ( battlerAtk ) , BATTLE_PARTNER ( battlerAtk ) )
| | ( CanTargetFaintAi ( BATTLE_PARTNER ( FOE ( battlerAtk ) ) , BATTLE_PARTNER ( battlerAtk ) ) ) )
2020-12-20 22:47:20 +01:00
score - - ;
2022-08-24 21:56:24 +02:00
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < = 50 )
2020-12-20 22:47:20 +01:00
score + + ;
}
}
else
{
// Consider AI HP
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerAtk ] > 70 )
2020-12-20 22:47:20 +01:00
{
// high hp
switch ( effect )
{
case EFFECT_EXPLOSION :
case EFFECT_RESTORE_HP :
case EFFECT_REST :
case EFFECT_DESTINY_BOND :
case EFFECT_FLAIL :
case EFFECT_ENDURE :
case EFFECT_MORNING_SUN :
case EFFECT_SYNTHESIS :
case EFFECT_MOONLIGHT :
case EFFECT_SHORE_UP :
case EFFECT_SOFTBOILED :
case EFFECT_ROOST :
case EFFECT_MEMENTO :
case EFFECT_GRUDGE :
case EFFECT_OVERHEAT :
score - = 2 ;
break ;
default :
break ;
}
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerAtk ] > 30 )
2020-12-20 22:47:20 +01:00
{
// med hp
if ( IsStatRaisingEffect ( effect ) | | IsStatLoweringEffect ( effect ) )
score - = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
switch ( effect )
{
case EFFECT_EXPLOSION :
case EFFECT_BIDE :
case EFFECT_CONVERSION :
case EFFECT_LIGHT_SCREEN :
case EFFECT_MIST :
case EFFECT_FOCUS_ENERGY :
case EFFECT_CONVERSION_2 :
case EFFECT_SAFEGUARD :
case EFFECT_BELLY_DRUM :
score - = 2 ;
break ;
default :
break ;
}
}
else
{
// low hp
if ( IsStatRaisingEffect ( effect ) | | IsStatLoweringEffect ( effect ) )
score - = 2 ;
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
// check other discouraged low hp effects
switch ( effect )
{
case EFFECT_BIDE :
case EFFECT_CONVERSION :
case EFFECT_REFLECT :
case EFFECT_LIGHT_SCREEN :
case EFFECT_AURORA_VEIL :
case EFFECT_MIST :
case EFFECT_FOCUS_ENERGY :
case EFFECT_RAGE :
case EFFECT_CONVERSION_2 :
case EFFECT_LOCK_ON :
case EFFECT_SAFEGUARD :
case EFFECT_BELLY_DRUM :
case EFFECT_PSYCH_UP :
case EFFECT_MIRROR_COAT :
2021-11-21 19:40:26 +01:00
case EFFECT_SOLAR_BEAM :
2020-12-20 22:47:20 +01:00
case EFFECT_TWO_TURNS_ATTACK :
case EFFECT_ERUPTION :
case EFFECT_TICKLE :
case EFFECT_SUNNY_DAY :
case EFFECT_SANDSTORM :
case EFFECT_HAIL :
case EFFECT_RAIN_DANCE :
score - = 2 ;
break ;
default :
break ;
}
}
}
2022-08-24 21:56:24 +02:00
2020-12-20 22:47:20 +01:00
// consider target HP
2021-11-08 08:37:28 +01:00
if ( CanIndexMoveFaintTarget ( battlerAtk , battlerDef , AI_THINKING_STRUCT - > movesetIndex , 0 ) )
2020-12-20 22:47:20 +01:00
{
score + = 2 ;
}
else
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] > 70 )
2020-12-20 22:47:20 +01:00
{
// high HP
; // nothing yet
}
2022-01-13 17:28:27 +01:00
else if ( AI_DATA - > hpPercents [ battlerDef ] > 30 )
2020-12-20 22:47:20 +01:00
{
// med HP - check discouraged effects
switch ( effect )
{
case EFFECT_ATTACK_UP :
case EFFECT_DEFENSE_UP :
case EFFECT_SPEED_UP :
case EFFECT_SPECIAL_ATTACK_UP :
case EFFECT_SPECIAL_DEFENSE_UP :
case EFFECT_ACCURACY_UP :
case EFFECT_EVASION_UP :
case EFFECT_ATTACK_DOWN :
case EFFECT_DEFENSE_DOWN :
case EFFECT_SPEED_DOWN :
case EFFECT_SPECIAL_ATTACK_DOWN :
case EFFECT_SPECIAL_DEFENSE_DOWN :
case EFFECT_ACCURACY_DOWN :
case EFFECT_EVASION_DOWN :
case EFFECT_MIST :
case EFFECT_FOCUS_ENERGY :
case EFFECT_ATTACK_UP_2 :
case EFFECT_DEFENSE_UP_2 :
case EFFECT_SPEED_UP_2 :
case EFFECT_SPECIAL_ATTACK_UP_2 :
case EFFECT_SPECIAL_DEFENSE_UP_2 :
case EFFECT_ACCURACY_UP_2 :
case EFFECT_EVASION_UP_2 :
case EFFECT_ATTACK_DOWN_2 :
case EFFECT_DEFENSE_DOWN_2 :
case EFFECT_SPEED_DOWN_2 :
case EFFECT_SPECIAL_ATTACK_DOWN_2 :
case EFFECT_SPECIAL_DEFENSE_DOWN_2 :
case EFFECT_ACCURACY_DOWN_2 :
case EFFECT_EVASION_DOWN_2 :
case EFFECT_POISON :
case EFFECT_PAIN_SPLIT :
case EFFECT_PERISH_SONG :
case EFFECT_SAFEGUARD :
case EFFECT_TICKLE :
case EFFECT_COSMIC_POWER :
case EFFECT_BULK_UP :
case EFFECT_CALM_MIND :
case EFFECT_DRAGON_DANCE :
2021-01-14 00:42:10 +01:00
case EFFECT_DEFENSE_UP_3 :
case EFFECT_SPECIAL_ATTACK_UP_3 :
2020-12-20 22:47:20 +01:00
score - = 2 ;
break ;
default :
break ;
}
}
else
{
// low HP
if ( IS_MOVE_STATUS ( move ) )
score - = 2 ; // don't use status moves if target is at low health
}
}
2022-08-24 21:56:24 +02:00
2020-12-20 06:57:08 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
static void AI_Flee ( void )
{
AI_THINKING_STRUCT - > aiAction | = ( AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK ) ;
}
static void AI_Watch ( void )
{
AI_THINKING_STRUCT - > aiAction | = ( AI_ACTION_DONE | AI_ACTION_WATCH | AI_ACTION_DO_NOT_ATTACK ) ;
}
2020-12-20 06:51:25 +01:00
// Roaming pokemon logic
2020-12-20 05:58:23 +01:00
static s16 AI_Roaming ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
if ( IsBattlerTrapped ( battlerAtk , FALSE ) )
2020-12-16 05:57:33 +01:00
return score ;
2022-08-24 21:56:24 +02:00
2020-12-13 23:02:21 +01:00
AI_Flee ( ) ;
2020-12-16 05:57:33 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 06:51:25 +01:00
// Safari pokemon logic
2020-12-20 05:58:23 +01:00
static s16 AI_Safari ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-13 23:02:21 +01:00
{
u8 safariFleeRate = gBattleStruct - > safariEscapeFactor * 5 ; // Safari flee rate, from 0-20.
if ( ( Random ( ) % 100 ) < safariFleeRate )
AI_Flee ( ) ;
else
AI_Watch ( ) ;
2020-12-16 05:57:33 +01:00
return score ;
2020-12-13 23:02:21 +01:00
}
2020-12-20 06:51:25 +01:00
// First battle logic
2020-12-20 05:58:23 +01:00
static s16 AI_FirstBattle ( u8 battlerAtk , u8 battlerDef , u16 move , s16 score )
2020-12-11 06:10:21 +01:00
{
2022-01-13 17:28:27 +01:00
if ( AI_DATA - > hpPercents [ battlerDef ] < = 20 )
2020-12-13 23:02:21 +01:00
AI_Flee ( ) ;
2020-12-11 06:10:21 +01:00
2020-12-16 05:57:33 +01:00
return score ;
2020-12-11 05:37:37 +01:00
}