Pokémon Crystal - AI calculations ----- NOTE: - Some behaviours are wrongly explained here. TODO ---- LINKS : (1) AI layers : https://github.com/pret/pokecrystal/blob/master/data/trainers/attributes.asm (2) AI constant flags : https://github.com/pret/pokecrystal/blob/4fb008844030283ad34cb0802b088b4dd7c9891c/constants/trainer_data_constants.asm (3) Scoring : https://github.com/pret/pokecrystal/blob/650686476c47d03148dfb93de1388b1a7294e385/engine/battle/ai/scoring.asm WHEN AI IS CALLED : - Just before the battle menu shows up. INITIALISATION : - Each usable move is given a score of 20. - Each unusable move is given a score of 80. An unusable move is defined as follows : - Disabled moves. - Moves with 0 PP left. SCORES MODIFICATION : - Each AI layer will juggle with each move score. - Encouraging a move decreases its score (gets closer to 0). - Discouraging a move increases its score (gets away from 0). - A call to `AIDiscourageMove` will add 10 to a move score. It almost always means the move is discarded. - the term "dismiss" will be used when this function is called. - Otherwise, (en/dis)couraging describes a score variation of 1. - Greatly (en/dis)couraging describes a score variation of 2. IMPACT OF RANDOMNESS : - Many AI layers involve randomness thresholds, which can create variance in the results. - Variance functions are - `AI_50_50` : 50/50 outcome. - `AI_80_20` : 80/20 outcome (the odds of an outcome is context-specific). ADRESSES : - `wBuffer1` up to `wBuffer1 + 3` store enemy move scores. SCORE COMPILATION : - Once all AI layers have been applied, all moves with the minimum score are candidates for the AI choice. - If more than 1 move is candidate, the selection is done at random, each move having the same chance to be picked. EXAMPLE : - Blue's AI is defined as follows : AI_BASIC | AI_SETUP | AI_SMART | AI_AGGRESSIVE | AI_CAUTIOUS | AI_STATUS | AI_RISKY - AI_BASIC will be the first layer, AI_SETUP will be the second, etc. - Let's investigate a setup turn on Pidgeot against a neutral faster player Pokémon : Moveset : QUICK_ATTACK, WHIRLWIND, WING_ATTACK, MIRROR_MOVE (0) Initialisation : scores set to 20/20/20/20 (1) AI_BASIC : - Dismiss all moves in `AI_Redundant` if they are useless. - Dismiss status-only moves if the user is already statused. - Dismiss Safeguard if already active. Since none apply here, scores are unchanged : 20/20/20/20 (2) AI_SETUP : - 50% chance to greatly encourage stat-up/down moves during first enemy turn. Since none apply here, scores are unchanged : 20/20/20/20 (3) AI_SMART : - Context-specific scoring : it could be seen as a combo-search layer. - It will search moves in `AI_Smart_EffectHandlers` and update their scoring. MIRROR_MOVE (EFFECT_MIRROR_MOVE) and WHIRLWIND (EFFECT_FORCE_SWITCH) are in this table. a) MIRROR_MOVE : ┌─ enemy is faster ────────── dismiss - Player did not use a move ┴─ enemy is slower or tied ── nothing - Player used a move ┬─ not in `v` ──────────── nothing └─ in `UsefulMoves` ─┬─50%────────── nothing └─50%─ encourage ─┬─ enemy slower or tied ── nothing └─ enemy is faster ─┬─10%─ nothing └─90%- encourage The player didn't use a move, the enemy is slower, so MIRROR_MOVE score won't be dismissed. b) WHIRLWIND : - Discourage if the player has not shown a super-effective move, or its typing is super-effective. The player didn't use a move, and is neutral typing, so the move is discouraged. Scores are now : 20/21/20/20 (4) AI_AGGRESSIVE : - Discourage all damaging moves but the one that does the most damage, unless such a move : - has 0 or 1 base power (moves like Seismic Toss, Hidden Power, Counter, Fissure, etc.) - is "reckless" (Selfdestruct, Thrash, Double Slap, Double Kick, etc.) - If no damaging move deals damage to the player (immune), no move will be discouraged The most damaging move is WING_ATTACK and the only other damaging move is QUICK_ATTACK, so the latter is discouraged. Scores are now 21/21/20/20 (5) AI_CAUTIOUS : - 90% chance to discourage moves in `ResidualMoves` after the first turn - Such moves are among Mist, Leech Seed, Poison Gas, etc. Since we're still in turn 1, this clause doesn't apply. Scores are unchanged : 21/21/20/20 (6) AI_STATUS : - Dismiss status moves that don't affect the player. - If the player can't be poisoned, put to sleep, or paralyzed. Since none apply here, scores are unchanged : 21/21/20/20 (7) AI_RISKY : - Use any move that will KO the target. - Enemy never uses moves like Selfdestruct or Horn Drill at full health (effect in `RiskyEffects`). - If effect in `RiskyEffects` and enemy is not at full health, 20% chance to reduce score by 5. Since none apply here, scores are unchanged : 21/21/20/20 (8) Now that all layers have been encountered, the AI chooses a move among the lowest scores, at random. In this case, WING_ATTACK and MIRROR_MOVE have 20. Pidgeot will be doing either of those 50% of the time. MANIP BLUE's PIDGEOT : - Since wLastPlayerCounterMove is not reset when using X Items, you can use a move in `UsefulMoves` to get 75% Mirror Move odds. - This can be a life-saver for specific Pokémon like Heracross with Earthquake, since Wing Attack is a 4x effective move.