diff --git a/docs/ai_flags.md b/docs/ai_flags.md index bb7b1b7444e5..8ba2e33253d3 100644 --- a/docs/ai_flags.md +++ b/docs/ai_flags.md @@ -42,8 +42,8 @@ This flag is divided into two components to calculate the best available move fo This is different to `AI_FLAG_CHECK_BAD_MOVE` as it calculates how poor a move is and not whether it will fail or not. -## `AI_FLAG_SETUP_FIRST_TURN` -AI will prioritize using setup moves on the first turn. These include stat buffs, field effects, status moves, etc. +## `AI_FLAG_FORCE_SETUP_FIRST_TURN` +AI will prioritize using setup moves on the first turn at the expense of all else. These include stat buffs, field effects, status moves, etc. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. This is just a flat increase without any consideration of whether it makes sense to use the move or not. For better move choice quality for those moves, `AI_FLAG_CHECK_VIABILITY` should be used. diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index 75802bad49ab..ca469cadeb8f 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -25,28 +25,29 @@ #define AI_EFFECTIVENESS_x0 0 // AI Flags. Most run specific functions to update score, new flags are used for internal logic in other scripts -#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) -#define AI_FLAG_TRY_TO_FAINT (1 << 1) -#define AI_FLAG_CHECK_VIABILITY (1 << 2) -#define AI_FLAG_SETUP_FIRST_TURN (1 << 3) -#define AI_FLAG_RISKY (1 << 4) -#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5) -#define AI_FLAG_PREFER_BATON_PASS (1 << 6) -#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner -#define AI_FLAG_HP_AWARE (1 << 8) -#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target +// See docs/ai_flags.md for more details. +#define AI_FLAG_CHECK_BAD_MOVE (1 << 0) // AI will avoid using moves that are likely to fail or be ineffective in the current situation. +#define AI_FLAG_TRY_TO_FAINT (1 << 1) // AI will prioritize KOing the player's mon if able. +#define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation. +#define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. +#define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. +#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. +#define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass. +#define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner. +#define AI_FLAG_HP_AWARE (1 << 8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. +#define AI_FLAG_POWERFUL_STATUS (1 << 9) // AI prefers moves that set up field effects or side statuses, even if the user can faint the target. // New, Trainer Handicap Flags -#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc -#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc +#define AI_FLAG_NEGATE_UNAWARE (1 << 10) // AI is NOT aware of negating effects like wonder room, mold breaker, etc. +#define AI_FLAG_WILL_SUICIDE (1 << 11) // AI will use explosion / self destruct / final gambit / etc. // New, Trainer Strategy Flags -#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves -#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished +#define AI_FLAG_PREFER_STATUS_MOVES (1 << 12) // AI gets a score bonus for status moves. Should be combined with AI_FLAG_CHECK_BAD_MOVE to prevent using only status moves. +#define AI_FLAG_STALL (1 << 13) // AI stalls battle and prefers secondary damage/trapping/etc. TODO not finished. #define AI_FLAG_SMART_SWITCHING (1 << 14) // AI includes a lot more switching checks. Automatically includes AI_FLAG_SMART_MON_CHOICES. #define AI_FLAG_ACE_POKEMON (1 << 15) // AI has an Ace Pokemon. The last Pokemon in the party will not be used until it's the last one remaining. -#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items +#define AI_FLAG_OMNISCIENT (1 << 16) // AI has full knowledge of player moves, abilities, hold items. #define AI_FLAG_SMART_MON_CHOICES (1 << 17) // AI will make smarter decisions when choosing which mon to send out mid-battle and after a KO, which are separate decisions. Automatically included by AI_FLAG_SMART_SWITCHING. -#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage -#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle +#define AI_FLAG_CONSERVATIVE (1 << 18) // AI assumes all moves will low roll damage. +#define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle. #define AI_FLAG_COUNT 20 diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index b622cf273af4..ffaa058a082d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -46,7 +46,7 @@ EWRAM_DATA AiScoreFunc sDynamicAiFunc = NULL; static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); -static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); +static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); @@ -64,7 +64,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = [0] = AI_CheckBadMove, // AI_FLAG_CHECK_BAD_MOVE [1] = AI_TryToFaint, // AI_FLAG_TRY_TO_FAINT [2] = AI_CheckViability, // AI_FLAG_CHECK_VIABILITY - [3] = AI_SetupFirstTurn, // AI_FLAG_SETUP_FIRST_TURN + [3] = AI_ForceSetupFirstTurn, // AI_FLAG_FORCE_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 @@ -4821,7 +4821,7 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score } // Effects that are encouraged on the first turn of battle -static s32 AI_SetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) +static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { u8 i; if (IS_TARGETING_PARTNER(battlerAtk, battlerDef) diff --git a/src/data/trainers.h b/src/data/trainers.h index c1907cfee5e6..ebc85e9cab2d 100644 --- a/src/data/trainers.h +++ b/src/data/trainers.h @@ -4044,7 +4044,7 @@ F_TRAINER_FEMALE | #line 1692 .doubleBattle = FALSE, #line 1693 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -4085,7 +4085,7 @@ F_TRAINER_FEMALE | #line 1708 .doubleBattle = FALSE, #line 1709 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -4164,7 +4164,7 @@ F_TRAINER_FEMALE | #line 1742 .doubleBattle = FALSE, #line 1743 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -11394,7 +11394,7 @@ F_TRAINER_FEMALE | #line 4594 .doubleBattle = FALSE, #line 4595 - .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_BASIC_TRAINER | AI_FLAG_FORCE_SETUP_FIRST_TURN, #line 4596 .mugshotEnabled = TRUE, .mugshotColor = MUGSHOT_COLOR_PURPLE, @@ -23880,7 +23880,7 @@ F_TRAINER_FEMALE | #line 9565 .doubleBattle = FALSE, #line 9566 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25772,7 +25772,7 @@ F_TRAINER_FEMALE | #line 10290 .doubleBattle = FALSE, #line 10291 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25840,7 +25840,7 @@ F_TRAINER_FEMALE | #line 10318 .doubleBattle = FALSE, #line 10319 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 1, .party = (const struct TrainerMon[]) { @@ -25921,7 +25921,7 @@ F_TRAINER_FEMALE | #line 10350 .doubleBattle = FALSE, #line 10351 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -25968,7 +25968,7 @@ F_TRAINER_FEMALE | #line 10368 .doubleBattle = FALSE, #line 10369 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 3, .party = (const struct TrainerMon[]) { @@ -26073,7 +26073,7 @@ F_TRAINER_FEMALE | #line 10408 .doubleBattle = FALSE, #line 10409 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -26167,7 +26167,7 @@ F_TRAINER_FEMALE | #line 10444 .doubleBattle = FALSE, #line 10445 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27472,7 +27472,7 @@ F_TRAINER_FEMALE | #line 10958 .doubleBattle = FALSE, #line 10959 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -27560,7 +27560,7 @@ F_TRAINER_FEMALE | #line 10992 .doubleBattle = FALSE, #line 10993 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { @@ -31937,7 +31937,7 @@ F_TRAINER_FEMALE | #line 12747 .doubleBattle = TRUE, #line 12748 - .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SETUP_FIRST_TURN, + .aiFlags = AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_FORCE_SETUP_FIRST_TURN, .partySize = 2, .party = (const struct TrainerMon[]) { diff --git a/src/data/trainers.party b/src/data/trainers.party index 34a736429ee6..14304518b69b 100644 --- a/src/data/trainers.party +++ b/src/data/trainers.party @@ -1690,7 +1690,7 @@ Gender: Female Music: Cool Items: Hyper Potion Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Zangoose Level: 26 @@ -1706,7 +1706,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Mawile Level: 29 @@ -1740,7 +1740,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Lairon Level: 45 @@ -4592,7 +4592,7 @@ Gender: Male Music: Elite Four Items: Full Restore / Full Restore Double Battle: No -AI: Basic Trainer / Setup First Turn +AI: Basic Trainer / Force Setup First Turn Mugshot: Purple Mightyena @@ -9563,7 +9563,7 @@ Pic: Brendan Gender: Male Music: Male Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Torchic Level: 5 @@ -10288,7 +10288,7 @@ Gender: Male Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Breloom Level: 31 @@ -10316,7 +10316,7 @@ Gender: Male Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Breloom Level: 37 @@ -10348,7 +10348,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Gloom Level: 26 @@ -10366,7 +10366,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Lotad Level: 28 @@ -10406,7 +10406,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Gloom Level: 30 @@ -10442,7 +10442,7 @@ Gender: Female Music: Cool Items: Full Restore Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Gloom Level: 36 @@ -10956,7 +10956,7 @@ Gender: Male Music: Cool Items: Hyper Potion Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Kecleon Level: 33 @@ -10990,7 +10990,7 @@ Pic: May Gender: Female Music: Female Double Battle: No -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Wingull Level: 13 @@ -12745,7 +12745,7 @@ Pic: Old Couple Gender: Male Music: Intense Double Battle: Yes -AI: Check Bad Move / Try To Faint / Setup First Turn +AI: Check Bad Move / Try To Faint / Force Setup First Turn Medicham Level: 49