summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--constants/battle_constants.asm35
-rw-r--r--data/battle/ai/constant_damage_effects.asm10
-rw-r--r--data/battle/ai/encore_moves.asm34
-rw-r--r--data/battle/ai/rain_dance_moves.asm15
-rw-r--r--data/battle/ai/reckless_moves.asm9
-rw-r--r--data/battle/ai/residual_moves.asm16
-rw-r--r--data/battle/ai/risky_effects.asm7
-rw-r--r--data/battle/ai/stall_moves.asm37
-rw-r--r--data/battle/ai/status_only_effects.asm9
-rw-r--r--data/battle/ai/sunny_day_moves.asm12
-rw-r--r--data/battle/ai/useful_moves.asm23
-rw-r--r--engine/battle/ai/scoring.asm3207
-rwxr-xr-xhome/battle_vars.asm2
-rw-r--r--main.asm40
-rw-r--r--wram.asm68
15 files changed, 3472 insertions, 52 deletions
diff --git a/constants/battle_constants.asm b/constants/battle_constants.asm
index 99d86e56..a53a7100 100644
--- a/constants/battle_constants.asm
+++ b/constants/battle_constants.asm
@@ -1,12 +1,30 @@
+; significant level values
MAX_LEVEL EQU 100
MIN_LEVEL EQU 2
EGG_LEVEL EQU 5
+
+; maximum moves known per mon
NUM_MOVES EQU 4
-REST_TURNS EQU 2
-MAX_STAT_LEVEL EQU 13
+; significant stat values
BASE_STAT_LEVEL EQU 7
+MAX_STAT_LEVEL EQU 13
+
+; minimum damage before type effectiveness
+MIN_NEUTRAL_DAMAGE EQU 2
+; turns that sleep lasts
+REST_SLEEP_TURNS EQU 2
+
+; type effectiveness factors, scaled by 10
+SUPER_EFFECTIVE EQU 20
+MORE_EFFECTIVE EQU 15
+EFFECTIVE EQU 10
+NOT_VERY_EFFECTIVE EQU 05
+NO_EFFECT EQU 00
+
+; wPlayerStatLevels and wEnemyStatLevels indexes (see wram.asm)
+; GetStatName arguments (see data/battle/stat_names.asm)
const_def
const ATTACK
const DEFENSE
@@ -18,7 +36,7 @@ BASE_STAT_LEVEL EQU 7
const ABILITY
NUM_LEVEL_STATS EQU const_value
-; move struct
+; move struct members (see data/moves/moves.asm)
const_def
const MOVE_ANIM
const MOVE_EFFECT
@@ -30,14 +48,21 @@ NUM_LEVEL_STATS EQU const_value
const MOVE_LENGTH
; stat constants
-const_value SET 1
+; indexes for:
+; - wPlayerStats and wEnemyStats (see wram.asm)
+; - party_struct and battle_struct members (see macros/wram.asm)
+ const_def 1
const STAT_HP
const STAT_ATK
const STAT_DEF
const STAT_SPD
const STAT_SATK
+NUM_EXP_STATS EQU const_value - 1
const STAT_SDEF
-NUM_STATS EQU const_value
+NUM_STATS EQU const_value - 1
+NUM_BATTLE_STATS EQU NUM_STATS - 1 ; don't count HP
+
+; stat formula constants
STAT_MIN_NORMAL EQU 5
STAT_MIN_HP EQU 10
diff --git a/data/battle/ai/constant_damage_effects.asm b/data/battle/ai/constant_damage_effects.asm
new file mode 100644
index 00000000..cd812d41
--- /dev/null
+++ b/data/battle/ai/constant_damage_effects.asm
@@ -0,0 +1,10 @@
+; AIDamageCalc uses BattleCommand_ConstantDamage
+; to calculate damage for these instead of
+; BattleCommand_DamageCalc and BattleCommand_Stab.
+
+ConstantDamageEffects:
+ db EFFECT_SUPER_FANG
+ db EFFECT_STATIC_DAMAGE
+ db EFFECT_LEVEL_DAMAGE
+ db EFFECT_PSYWAVE
+ db -1 ; end
diff --git a/data/battle/ai/encore_moves.asm b/data/battle/ai/encore_moves.asm
new file mode 100644
index 00000000..03e028bd
--- /dev/null
+++ b/data/battle/ai/encore_moves.asm
@@ -0,0 +1,34 @@
+; AI_SMART encourages these moves with Encore.
+
+EncoreMoves:
+ db SWORDS_DANCE
+ db WHIRLWIND
+ db LEER
+ db ROAR
+ db DISABLE
+ db MIST
+ db LEECH_SEED
+ db GROWTH
+ db POISONPOWDER
+ db STRING_SHOT
+ db MEDITATE
+ db AGILITY
+ db TELEPORT
+ db SCREECH
+ db HAZE
+ db FOCUS_ENERGY
+ db DREAM_EATER
+ db POISON_GAS
+ db SPLASH
+ db SHARPEN
+ db CONVERSION
+ db SUPER_FANG
+ db SUBSTITUTE
+ db TRIPLE_KICK
+ db SPIDER_WEB
+ db MIND_READER
+ db FLAME_WHEEL
+ db AEROBLAST
+ db COTTON_SPORE
+ db POWDER_SNOW
+ db -1 ; end
diff --git a/data/battle/ai/rain_dance_moves.asm b/data/battle/ai/rain_dance_moves.asm
new file mode 100644
index 00000000..c00e0b60
--- /dev/null
+++ b/data/battle/ai/rain_dance_moves.asm
@@ -0,0 +1,15 @@
+; AI_SMART prefers these moves during rain.
+
+RainDanceMoves:
+ db WATER_GUN
+ db HYDRO_PUMP
+ db SURF
+ db BUBBLEBEAM
+ db THUNDER
+ db WATERFALL
+ db CLAMP
+ db BUBBLE
+ db CRABHAMMER
+ db OCTAZOOKA
+ db WHIRLPOOL
+ db -1 ; end
diff --git a/data/battle/ai/reckless_moves.asm b/data/battle/ai/reckless_moves.asm
new file mode 100644
index 00000000..67252979
--- /dev/null
+++ b/data/battle/ai/reckless_moves.asm
@@ -0,0 +1,9 @@
+; AI_AGGRESSIVE does not discourage these moves
+; even if a stronger one is available.
+
+RecklessMoves:
+ db EFFECT_SELFDESTRUCT
+ db EFFECT_RAMPAGE
+ db EFFECT_MULTI_HIT
+ db EFFECT_DOUBLE_HIT
+ db -1 ; end
diff --git a/data/battle/ai/residual_moves.asm b/data/battle/ai/residual_moves.asm
new file mode 100644
index 00000000..c99ac0f5
--- /dev/null
+++ b/data/battle/ai/residual_moves.asm
@@ -0,0 +1,16 @@
+; AI_CAUTIOUS discourages these moves after the first turn.
+
+ResidualMoves:
+ db MIST
+ db LEECH_SEED
+ db POISONPOWDER
+ db STUN_SPORE
+ db THUNDER_WAVE
+ db FOCUS_ENERGY
+ db BIDE
+ db POISON_GAS
+ db TRANSFORM
+ db CONVERSION
+ db SUBSTITUTE
+ db SPIKES
+ db -1 ; end
diff --git a/data/battle/ai/risky_effects.asm b/data/battle/ai/risky_effects.asm
new file mode 100644
index 00000000..529436c4
--- /dev/null
+++ b/data/battle/ai/risky_effects.asm
@@ -0,0 +1,7 @@
+; AI_RISKY will not use these effects at max HP
+; even if they would KO the player.
+
+RiskyEffects:
+ db EFFECT_SELFDESTRUCT
+ db EFFECT_OHKO
+ db -1 ; end
diff --git a/data/battle/ai/stall_moves.asm b/data/battle/ai/stall_moves.asm
new file mode 100644
index 00000000..65838e0f
--- /dev/null
+++ b/data/battle/ai/stall_moves.asm
@@ -0,0 +1,37 @@
+; AI_OPPORTUNIST discourages these moves
+; when the player's HP is low.
+
+StallMoves:
+ db SWORDS_DANCE
+ db TAIL_WHIP
+ db LEER
+ db GROWL
+ db DISABLE
+ db MIST
+ db COUNTER
+ db LEECH_SEED
+ db GROWTH
+ db STRING_SHOT
+ db MEDITATE
+ db AGILITY
+ db RAGE
+ db MIMIC
+ db SCREECH
+ db HARDEN
+ db WITHDRAW
+ db DEFENSE_CURL
+ db BARRIER
+ db LIGHT_SCREEN
+ db HAZE
+ db REFLECT
+ db FOCUS_ENERGY
+ db BIDE
+ db AMNESIA
+ db TRANSFORM
+ db SPLASH
+ db ACID_ARMOR
+ db SHARPEN
+ db CONVERSION
+ db SUBSTITUTE
+ db FLAME_WHEEL
+ db -1 ; end
diff --git a/data/battle/ai/status_only_effects.asm b/data/battle/ai/status_only_effects.asm
new file mode 100644
index 00000000..8748d93b
--- /dev/null
+++ b/data/battle/ai/status_only_effects.asm
@@ -0,0 +1,9 @@
+; AI_BASIC discourages these effects if the player
+; already has a status condition.
+
+StatusOnlyEffects:
+ db EFFECT_SLEEP
+ db EFFECT_TOXIC
+ db EFFECT_POISON
+ db EFFECT_PARALYZE
+ db -1 ; end
diff --git a/data/battle/ai/sunny_day_moves.asm b/data/battle/ai/sunny_day_moves.asm
new file mode 100644
index 00000000..38d6a8ee
--- /dev/null
+++ b/data/battle/ai/sunny_day_moves.asm
@@ -0,0 +1,12 @@
+; AI_SMART prefers these moves during harsh sunlight.
+
+SunnyDayMoves:
+ db FIRE_PUNCH
+ db EMBER
+ db FLAMETHROWER
+ db FIRE_SPIN
+ db FIRE_BLAST
+ db SACRED_FIRE
+ db MORNING_SUN
+ db SYNTHESIS
+ db -1 ; end
diff --git a/data/battle/ai/useful_moves.asm b/data/battle/ai/useful_moves.asm
new file mode 100644
index 00000000..456bda2d
--- /dev/null
+++ b/data/battle/ai/useful_moves.asm
@@ -0,0 +1,23 @@
+; AI_SMART knows these moves are usable all-around.
+
+UsefulMoves:
+ db DOUBLE_EDGE
+ db SING
+ db FLAMETHROWER
+ db HYDRO_PUMP
+ db SURF
+ db ICE_BEAM
+ db BLIZZARD
+ db HYPER_BEAM
+ db SLEEP_POWDER
+ db THUNDERBOLT
+ db THUNDER
+ db EARTHQUAKE
+ db TOXIC
+ db PSYCHIC_M
+ db HYPNOSIS
+ db RECOVER
+ db FIRE_BLAST
+ db SOFTBOILED
+ db SUPER_FANG
+ db -1 ; end
diff --git a/engine/battle/ai/scoring.asm b/engine/battle/ai/scoring.asm
new file mode 100644
index 00000000..41d4841c
--- /dev/null
+++ b/engine/battle/ai/scoring.asm
@@ -0,0 +1,3207 @@
+AIScoring: ; used only for BANK(AIScoring)
+
+AI_Basic:
+; Don't do anything redundant:
+; -Using status-only moves if the player can't be statused
+; -Using moves that fail if they've already been used
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ inc hl
+ ld a, [de]
+ and a
+ ret z
+
+ inc de
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ ld c, a
+
+; Dismiss moves with special effects if they are
+; useless or not a good choice right now.
+; For example, healing moves, weather moves, Dream Eater...
+ push hl
+ push de
+ push bc
+ farcall AI_Redundant
+ pop bc
+ pop de
+ pop hl
+ jr nz, .discourage
+
+; Dismiss status-only moves if the player can't be statused.
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ push hl
+ push de
+ push bc
+ ld hl, StatusOnlyEffects
+ ld de, 1
+ call IsInArray
+
+ pop bc
+ pop de
+ pop hl
+ jr nc, .checkmove
+
+ ld a, [wBattleMonStatus]
+ and a
+ jr nz, .discourage
+
+; Dismiss Safeguard if it's already active.
+ ld a, [wPlayerScreens]
+ bit SCREENS_SAFEGUARD, a
+ jr z, .checkmove
+
+.discourage
+ call AIDiscourageMove
+ jr .checkmove
+
+INCLUDE "data/battle/ai/status_only_effects.asm"
+
+
+AI_Setup:
+; Use stat-modifying moves on turn 1.
+
+; 50% chance to greatly encourage stat-up moves during the first turn of enemy's Pokemon.
+; 50% chance to greatly encourage stat-down moves during the first turn of player's Pokemon.
+; Almost 90% chance to greatly discourage stat-modifying moves otherwise.
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ inc hl
+ ld a, [de]
+ and a
+ ret z
+
+ inc de
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+
+ cp EFFECT_ATTACK_UP
+ jr c, .checkmove
+ cp EFFECT_EVASION_UP + 1
+ jr c, .statup
+
+; cp EFFECT_ATTACK_DOWN - 1
+ jr z, .checkmove
+ cp EFFECT_EVASION_DOWN + 1
+ jr c, .statdown
+
+ cp EFFECT_ATTACK_UP_2
+ jr c, .checkmove
+ cp EFFECT_EVASION_UP_2 + 1
+ jr c, .statup
+
+; cp EFFECT_ATTACK_DOWN_2 - 1
+ jr z, .checkmove
+ cp EFFECT_EVASION_DOWN_2 + 1
+ jr c, .statdown
+
+ jr .checkmove
+
+.statup
+ ld a, [wEnemyTurnsTaken]
+ and a
+ jr nz, .discourage
+
+ jr .encourage
+
+.statdown
+ ld a, [wPlayerTurnsTaken]
+ and a
+ jr nz, .discourage
+
+.encourage
+ call AI_50_50
+ jr c, .checkmove
+
+ dec [hl]
+ dec [hl]
+ jr .checkmove
+
+.discourage
+ call Random
+ cp 12 percent
+ jr c, .checkmove
+ inc [hl]
+ inc [hl]
+ jr .checkmove
+
+
+AI_Types:
+; Dismiss any move that the player is immune to.
+; Encourage super-effective moves.
+; Discourage not very effective moves unless
+; all damaging moves are of the same type.
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ inc hl
+ ld a, [de]
+ and a
+ ret z
+
+ inc de
+ call AIGetEnemyMove
+
+ push hl
+ push bc
+ push de
+ ld a, 1
+ ldh [hBattleTurn], a
+ callfar BattleCheckTypeMatchup
+ pop de
+ pop bc
+ pop hl
+
+ ld a, [wTypeMatchup]
+ and a
+ jr z, .immune
+ cp EFFECTIVE
+ jr z, .checkmove
+ jr c, .noteffective
+
+; effective
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .checkmove
+ dec [hl]
+ jr .checkmove
+
+.noteffective
+; Discourage this move if there are any moves
+; that do damage of a different type.
+ push hl
+ push de
+ push bc
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ ld d, a
+ ld hl, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+ ld c, 0
+.checkmove2
+ dec b
+ jr z, .asm_38685
+
+ ld a, [hli]
+ and a
+ jr z, .asm_38685
+
+ call AIGetEnemyMove
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ cp d
+ jr z, .checkmove2
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr nz, .asm_38684
+ jr .checkmove2
+
+.asm_38684
+ ld c, a
+.asm_38685
+ ld a, c
+ pop bc
+ pop de
+ pop hl
+ and a
+ jr z, .checkmove
+ inc [hl]
+ jr .checkmove
+
+.immune
+ call AIDiscourageMove
+ jr .checkmove
+
+
+AI_Offensive:
+; Greatly discourage non-damaging moves.
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ inc hl
+ ld a, [de]
+ and a
+ ret z
+
+ inc de
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr nz, .checkmove
+
+ inc [hl]
+ inc [hl]
+ jr .checkmove
+
+
+AI_Smart:
+; Context-specific scoring.
+
+ ld hl, wBuffer1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ ld a, [de]
+ inc de
+ and a
+ ret z
+
+ push de
+ push bc
+ push hl
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ ld hl, .table_386f2
+ ld de, 3
+ call IsInArray
+
+ inc hl
+ jr nc, .nextmove
+
+ ld a, [hli]
+ ld e, a
+ ld d, [hl]
+
+ pop hl
+ push hl
+
+ ld bc, .nextmove
+ push bc
+
+ push de
+ ret
+
+.nextmove
+ pop hl
+ pop bc
+ pop de
+ inc hl
+ jr .checkmove
+
+.table_386f2
+ dbw EFFECT_SLEEP, AI_Smart_Sleep
+ dbw EFFECT_LEECH_HIT, AI_Smart_LeechHit
+ dbw EFFECT_SELFDESTRUCT, AI_Smart_Selfdestruct
+ dbw EFFECT_DREAM_EATER, AI_Smart_DreamEater
+ dbw EFFECT_MIRROR_MOVE, AI_Smart_MirrorMove
+ dbw EFFECT_EVASION_UP, AI_Smart_EvasionUp
+ dbw EFFECT_ALWAYS_HIT, AI_Smart_AlwaysHit
+ dbw EFFECT_ACCURACY_DOWN, AI_Smart_AccuracyDown
+ dbw EFFECT_RESET_STATS, AI_Smart_ResetStats
+ dbw EFFECT_BIDE, AI_Smart_Bide
+ dbw EFFECT_FORCE_SWITCH, AI_Smart_ForceSwitch
+ dbw EFFECT_HEAL, AI_Smart_Heal
+ dbw EFFECT_TOXIC, AI_Smart_Toxic
+ dbw EFFECT_LIGHT_SCREEN, AI_Smart_LightScreen
+ dbw EFFECT_OHKO, AI_Smart_Ohko
+ dbw EFFECT_RAZOR_WIND, AI_Smart_RazorWind
+ dbw EFFECT_SUPER_FANG, AI_Smart_SuperFang
+ dbw EFFECT_TRAP_TARGET, AI_Smart_TrapTarget
+ dbw EFFECT_UNUSED_2B, AI_Smart_Unused2B
+ dbw EFFECT_CONFUSE, AI_Smart_Confuse
+ dbw EFFECT_SP_DEF_UP_2, AI_Smart_SpDefenseUp2
+ dbw EFFECT_REFLECT, AI_Smart_Reflect
+ dbw EFFECT_PARALYZE, AI_Smart_Paralyze
+ dbw EFFECT_SPEED_DOWN_HIT, AI_Smart_SpeedDownHit
+ dbw EFFECT_SUBSTITUTE, AI_Smart_Substitute
+ dbw EFFECT_HYPER_BEAM, AI_Smart_HyperBeam
+ dbw EFFECT_RAGE, AI_Smart_Rage
+ dbw EFFECT_MIMIC, AI_Smart_Mimic
+ dbw EFFECT_LEECH_SEED, AI_Smart_LeechSeed
+ dbw EFFECT_DISABLE, AI_Smart_Disable
+ dbw EFFECT_COUNTER, AI_Smart_Counter
+ dbw EFFECT_ENCORE, AI_Smart_Encore
+ dbw EFFECT_PAIN_SPLIT, AI_Smart_PainSplit
+ dbw EFFECT_SNORE, AI_Smart_Snore
+ dbw EFFECT_CONVERSION2, AI_Smart_Conversion2
+ dbw EFFECT_LOCK_ON, AI_Smart_LockOn
+ dbw EFFECT_DEFROST_OPPONENT, AI_Smart_DefrostOpponent
+ dbw EFFECT_SLEEP_TALK, AI_Smart_SleepTalk
+ dbw EFFECT_DESTINY_BOND, AI_Smart_DestinyBond
+ dbw EFFECT_REVERSAL, AI_Smart_Reversal
+ dbw EFFECT_SPITE, AI_Smart_Spite
+ dbw EFFECT_HEAL_BELL, AI_Smart_HealBell
+ dbw EFFECT_PRIORITY_HIT, AI_Smart_PriorityHit
+ dbw EFFECT_THIEF, AI_Smart_Thief
+ dbw EFFECT_MEAN_LOOK, AI_Smart_MeanLook
+ dbw EFFECT_NIGHTMARE, AI_Smart_Nightmare
+ dbw EFFECT_FLAME_WHEEL, AI_Smart_FlameWheel
+ dbw EFFECT_CURSE, AI_Smart_Curse
+ dbw EFFECT_PROTECT, AI_Smart_Protect
+ dbw EFFECT_FORESIGHT, AI_Smart_Foresight
+ dbw EFFECT_PERISH_SONG, AI_Smart_PerishSong
+ dbw EFFECT_SANDSTORM, AI_Smart_Sandstorm
+ dbw EFFECT_ENDURE, AI_Smart_Endure
+ dbw EFFECT_ROLLOUT, AI_Smart_Rollout
+ dbw EFFECT_SWAGGER, AI_Smart_Swagger
+ dbw EFFECT_FURY_CUTTER, AI_Smart_FuryCutter
+ dbw EFFECT_ATTRACT, AI_Smart_Attract
+ dbw EFFECT_SAFEGUARD, AI_Smart_Safeguard
+ dbw EFFECT_MAGNITUDE, AI_Smart_Magnitude
+ dbw EFFECT_BATON_PASS, AI_Smart_BatonPass
+ dbw EFFECT_PURSUIT, AI_Smart_Pursuit
+ dbw EFFECT_RAPID_SPIN, AI_Smart_RapidSpin
+ dbw EFFECT_MORNING_SUN, AI_Smart_MorningSun
+ dbw EFFECT_SYNTHESIS, AI_Smart_Synthesis
+ dbw EFFECT_MOONLIGHT, AI_Smart_Moonlight
+ dbw EFFECT_HIDDEN_POWER, AI_Smart_HiddenPower
+ dbw EFFECT_RAIN_DANCE, AI_Smart_RainDance
+ dbw EFFECT_SUNNY_DAY, AI_Smart_SunnyDay
+ dbw EFFECT_BELLY_DRUM, AI_Smart_BellyDrum
+ dbw EFFECT_PSYCH_UP, AI_Smart_PsychUp
+ dbw EFFECT_MIRROR_COAT, AI_Smart_MirrorCoat
+ dbw EFFECT_SKULL_BASH, AI_Smart_SkullBash
+ dbw EFFECT_TWISTER, AI_Smart_Twister
+ dbw EFFECT_EARTHQUAKE, AI_Smart_Earthquake
+ dbw EFFECT_FUTURE_SIGHT, AI_Smart_FutureSight
+ dbw EFFECT_GUST, AI_Smart_Gust
+ dbw EFFECT_STOMP, AI_Smart_Stomp
+ dbw EFFECT_SOLARBEAM, AI_Smart_Solarbeam
+ dbw EFFECT_THUNDER, AI_Smart_Thunder
+ dbw EFFECT_FLY, AI_Smart_Fly
+ db -1 ; end
+
+AI_Smart_Sleep:
+; Greatly encourage sleep inducing moves if the enemy has either Dream Eater or Nightmare.
+; 50% chance to greatly encourage sleep inducing moves otherwise.
+
+ ld b, EFFECT_DREAM_EATER
+ call AIHasMoveEffect
+ jr c, .asm_387e2
+
+ ld b, EFFECT_NIGHTMARE
+ call AIHasMoveEffect
+ ret nc
+
+.asm_387e2
+ call AI_50_50
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_LeechHit:
+ push hl
+ ld a, 1
+ ldh [hBattleTurn], a
+ callfar BattleCheckTypeMatchup
+ pop hl
+
+; 60% chance to discourage this move if not very effective.
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ jr c, .asm_38807
+
+; Do nothing if effectiveness is neutral.
+ ret z
+
+; Do nothing if enemy's HP is full.
+ call AICheckEnemyMaxHP
+ ret c
+
+; 80% chance to encourage this move otherwise.
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ ret
+
+.asm_38807
+ call Random
+ cp 39 percent + 1
+ ret c
+
+ inc [hl]
+ ret
+
+AI_Smart_LockOn:
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_LOCK_ON, a
+ jr nz, .asm_38874
+
+ push hl
+ call AICheckEnemyQuarterHP
+ jr nc, .asm_38869
+
+ call AICheckEnemyHalfHP
+ jr c, .asm_38826
+
+ call AICompareSpeed
+ jr nc, .asm_38869
+
+.asm_38826
+ ld a, [wPlayerEvaLevel]
+ cp $a
+ jr nc, .asm_3886c
+ cp $8
+ jr nc, .asm_38867
+
+ ld a, [wEnemyAccLevel]
+ cp $5
+ jr c, .asm_3886c
+ cp $7
+ jr c, .asm_38867
+
+ ld hl, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.asm_38841
+ dec c
+ jr z, .asm_38869
+
+ ld a, [hli]
+ and a
+ jr z, .asm_38869
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_ACC]
+ cp 180
+ jr nc, .asm_38841
+
+ ld a, $1
+ ldh [hBattleTurn], a
+
+ push hl
+ push bc
+ farcall BattleCheckTypeMatchup
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ pop bc
+ pop hl
+ jr c, .asm_38841
+
+.asm_38867
+ pop hl
+ ret
+
+.asm_38869
+ pop hl
+ inc [hl]
+ ret
+
+.asm_3886c
+ pop hl
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38874
+ push hl
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+
+.asm_3887d
+ inc hl
+ dec c
+ jr z, .asm_38894
+
+ ld a, [de]
+ and a
+ jr z, .asm_38894
+
+ inc de
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_ACC]
+ cp 180
+ jr nc, .asm_3887d
+
+ dec [hl]
+ dec [hl]
+ jr .asm_3887d
+
+.asm_38894
+ pop hl
+ jp AIDiscourageMove
+
+AI_Smart_Selfdestruct:
+; Selfdestruct, Explosion
+
+; Greatly discourage this move if enemy's HP is above 50%.
+ call AICheckEnemyHalfHP
+ jr c, .asm_388a7
+
+; Do nothing if enemy's HP is below 25%.
+ call AICheckEnemyQuarterHP
+ ret nc
+
+; If enemy's HP is between 25% and 50%,
+; over 90% chance to greatly discourage this move.
+ call Random
+ cp 9 percent - 2
+ ret c
+
+.asm_388a7
+ inc [hl]
+ inc [hl]
+ inc [hl]
+ ret
+
+AI_Smart_DreamEater:
+; 90% chance to greatly encourage this move.
+; The AI_Basic layer will make sure that
+; Dream Eater is only used against sleeping targets.
+ call Random
+ cp 10 percent
+ ret c
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_EvasionUp:
+; Dismiss this move if enemy's evasion can't raise anymore.
+ ld a, [wEnemyEvaLevel]
+ cp $d
+ jp nc, AIDiscourageMove
+
+; If enemy's HP is full...
+ call AICheckEnemyMaxHP
+ jr nc, .asm_388d3
+
+; ...greatly encourage this move if player is badly poisoned.
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_388d0
+
+; ...70% chance to greatly encourage this move if player is not badly poisoned.
+ call Random
+ cp 70 percent
+ jr nc, .asm_388f2
+
+.asm_388d0
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_388d3
+
+; Greatly discourage this move if enemy's HP is below 25%.
+ call AICheckEnemyQuarterHP
+ jr nc, .asm_388f0
+
+; If enemy's HP is above 25% but not full, 4% chance to greatly encourage this move.
+ call Random
+ cp 4 percent
+ jr c, .asm_388d0
+
+; If enemy's HP is between 25% and 50%,...
+ call AICheckEnemyHalfHP
+ jr nc, .asm_388eb
+
+; If enemy's HP is above 50% but not full, 20% chance to greatly encourage this move.
+ call AI_80_20
+ jr c, .asm_388d0
+ jr .asm_388f2
+
+.asm_388eb
+; ...50% chance to greatly discourage this move.
+ call AI_50_50
+ jr c, .asm_388f2
+
+.asm_388f0
+ inc [hl]
+ inc [hl]
+
+; 30% chance to end up here if enemy's HP is full and player is not badly poisoned.
+; 77% chance to end up here if enemy's HP is above 50% but not full.
+; 96% chance to end up here if enemy's HP is between 25% and 50%.
+; 100% chance to end up here if enemy's HP is below 25%.
+; In other words, we only end up here if the move has not been encouraged or dismissed.
+.asm_388f2
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38919
+
+ ld a, [wPlayerSubStatus4]
+ bit SUBSTATUS_LEECH_SEED, a
+ jr nz, .asm_38922
+
+; Discourage this move if enemy's evasion level is higher than player's accuracy level.
+ ld a, [wEnemyEvaLevel]
+ ld b, a
+ ld a, [wPlayerAccLevel]
+ cp b
+ jr c, .asm_38917
+
+; Greatly encourage this move if the player is in the middle of Fury Cutter or Rollout.
+ ld a, [wPlayerFuryCutterCount]
+ and a
+ jr nz, .asm_388d0
+
+ ld a, [wPlayerSubStatus1]
+ bit SUBSTATUS_ROLLOUT, a
+ jr nz, .asm_388d0
+
+.asm_38917
+ inc [hl]
+ ret
+
+; Player is badly poisoned.
+; 70% chance to greatly encourage this move.
+; This would counter any previous discouragement.
+.asm_38919
+ call Random
+ cp 31 percent + 1
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+; Player is seeded.
+; 50% chance to encourage this move.
+; This would partly counter any previous discouragement.
+.asm_38922
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+AI_Smart_AlwaysHit:
+; 80% chance to greatly encourage this move if either...
+
+; ...enemy's accuracy level has been lowered three or more stages
+ ld a, [wEnemyAccLevel]
+ cp $5
+ jr c, .asm_38935
+
+; ...or player's evasion level has been raised three or more stages.
+ ld a, [wPlayerEvaLevel]
+ cp $a
+ ret c
+
+.asm_38935
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_MirrorMove:
+; If the player did not use any move last turn...
+ ld a, [wLastPlayerCounterMove]
+ and a
+ jr nz, .asm_38949
+
+; ...do nothing if enemy is slower than player
+ call AICompareSpeed
+ ret nc
+
+; ...or dismiss this move if enemy is faster than player.
+ jp AIDiscourageMove
+
+; If the player did use a move last turn...
+.asm_38949
+ push hl
+ ld hl, UsefulMoves
+ ld de, 1
+ call IsInArray
+ pop hl
+
+; ...do nothing if he didn't use a useful move.
+ ret nc
+
+; If he did, 50% chance to encourage this move...
+ call AI_50_50
+ ret c
+
+ dec [hl]
+
+; ...and 90% chance to encourage this move again if the enemy is faster.
+ call AICompareSpeed
+ ret nc
+
+ call Random
+ cp 10 percent
+ ret c
+
+ dec [hl]
+ ret
+
+AI_Smart_AccuracyDown:
+; If player's HP is full...
+ call AICheckPlayerMaxHP
+ jr nc, .asm_38981
+
+; ...and enemy's HP is above 50%...
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38981
+
+; ...greatly encourage this move if player is badly poisoned.
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_3897e
+
+; ...70% chance to greatly encourage this move if player is not badly poisoned.
+ call Random
+ cp 70 percent
+ jr nc, .asm_389a0
+
+.asm_3897e
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38981
+
+; Greatly discourage this move if player's HP is below 25%.
+ call AICheckPlayerQuarterHP
+ jr nc, .asm_3899e
+
+; If player's HP is above 25% but not full, 4% chance to greatly encourage this move.
+ call Random
+ cp 4 percent
+ jr c, .asm_3897e
+
+; If player's HP is between 25% and 50%,...
+ call AICheckPlayerHalfHP
+ jr nc, .asm_38999
+
+; If player's HP is above 50% but not full, 20% chance to greatly encourage this move.
+ call AI_80_20
+ jr c, .asm_3897e
+ jr .asm_389a0
+
+; ...50% chance to greatly discourage this move.
+.asm_38999
+ call AI_50_50
+ jr c, .asm_389a0
+
+.asm_3899e
+ inc [hl]
+ inc [hl]
+
+; We only end up here if the move has not been already encouraged.
+.asm_389a0
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_389c7
+
+ ld a, [wPlayerSubStatus4]
+ bit SUBSTATUS_LEECH_SEED, a
+ jr nz, .asm_389d0
+
+; Discourage this move if enemy's evasion level is higher than player's accuracy level.
+ ld a, [wEnemyEvaLevel]
+ ld b, a
+ ld a, [wPlayerAccLevel]
+ cp b
+ jr c, .asm_389c5
+
+; Greatly encourage this move if the player is in the middle of Fury Cutter or Rollout.
+ ld a, [wPlayerFuryCutterCount]
+ and a
+ jr nz, .asm_3897e
+
+ ld a, [wPlayerSubStatus1]
+ bit SUBSTATUS_ROLLOUT, a
+ jr nz, .asm_3897e
+
+.asm_389c5
+ inc [hl]
+ ret
+
+; Player is badly poisoned.
+; 70% chance to greatly encourage this move.
+; This would counter any previous discouragement.
+.asm_389c7
+ call Random
+ cp 31 percent + 1
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+; Player is seeded.
+; 50% chance to encourage this move.
+; This would partly counter any previous discouragement.
+.asm_389d0
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+AI_Smart_ResetStats:
+; 85% chance to encourage this move if any of enemy's stat levels is lower than -2.
+ push hl
+ ld hl, wEnemyAtkLevel
+ ld c, $8
+.asm_389dc
+ dec c
+ jr z, .asm_389e6
+ ld a, [hli]
+ cp $5
+ jr c, .asm_389f3
+ jr .asm_389dc
+
+; 85% chance to encourage this move if any of player's stat levels is higher than +2.
+.asm_389e6
+ ld hl, wPlayerAtkLevel
+ ld c, $8
+.asm_389eb
+ dec c
+ jr z, .asm_389fc
+ ld a, [hli]
+ cp $a
+ jr c, .asm_389eb
+
+.asm_389f3
+ pop hl
+ call Random
+ cp 16 percent
+ ret c
+ dec [hl]
+ ret
+
+; Discourage this move if neither:
+; Any of enemy's stat levels is lower than -2.
+; Any of player's stat levels is higher than +2.
+.asm_389fc
+ pop hl
+ inc [hl]
+ ret
+
+AI_Smart_Bide:
+; 90% chance to discourage this move unless enemy's HP is full.
+
+ call AICheckEnemyMaxHP
+ ret c
+ call Random
+ cp 10 percent
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_ForceSwitch:
+; Whirlwind, Roar.
+
+; Discourage this move if the player has not shown
+; a super-effective move against the enemy.
+; Consider player's type(s) if its moves are unknown.
+
+ push hl
+ callfar CheckPlayerMoveTypeMatchups
+ ld a, [wEnemyAISwitchScore]
+ cp 10 ; neutral
+ pop hl
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Heal:
+AI_Smart_MorningSun:
+AI_Smart_Synthesis:
+AI_Smart_Moonlight:
+; 90% chance to greatly encourage this move if enemy's HP is below 25%.
+; Discourage this move if enemy's HP is higher than 50%.
+; Do nothing otherwise.
+
+ call AICheckEnemyQuarterHP
+ jr nc, .asm_38a26
+ call AICheckEnemyHalfHP
+ ret nc
+ inc [hl]
+ ret
+
+.asm_38a26
+ call Random
+ cp 10 percent
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Toxic:
+AI_Smart_LeechSeed:
+; Discourage this move if player's HP is below 50%.
+
+ call AICheckPlayerHalfHP
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_LightScreen:
+AI_Smart_Reflect:
+; Over 90% chance to discourage this move unless enemy's HP is full.
+
+ call AICheckEnemyMaxHP
+ ret c
+ call Random
+ cp 8 percent
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Ohko:
+; Dismiss this move if player's level is higher than enemy's level.
+; Else, discourage this move is player's HP is below 50%.
+
+ ld a, [wBattleMonLevel]
+ ld b, a
+ ld a, [wEnemyMonLevel]
+ cp b
+ jp c, AIDiscourageMove
+ call AICheckPlayerHalfHP
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_TrapTarget:
+; Bind, Wrap, Fire Spin, Clamp
+
+; 50% chance to discourage this move if the player is already trapped.
+ ld a, [wPlayerWrapCount]
+ and a
+ jr nz, .asm_38a6c
+
+; 50% chance to greatly encourage this move if player is either
+; badly poisoned, in love, identified, stuck in Rollout, or has a Nightmare.
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38a72
+
+ ld a, [wPlayerSubStatus1]
+ and 1 << SUBSTATUS_IN_LOVE | 1 << SUBSTATUS_ROLLOUT | 1 << SUBSTATUS_IDENTIFIED | 1 << SUBSTATUS_NIGHTMARE
+ jr nz, .asm_38a72
+
+; Else, 50% chance to greatly encourage this move if it's the player's Pokemon first turn.
+ ld a, [wPlayerTurnsTaken]
+ and a
+ jr z, .asm_38a72
+
+; 50% chance to discourage this move otherwise.
+.asm_38a6c
+ call AI_50_50
+ ret c
+ inc [hl]
+ ret
+
+.asm_38a72
+ call AICheckEnemyQuarterHP
+ ret nc
+ call AI_50_50
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_RazorWind:
+AI_Smart_Unused2B:
+ ld a, [wEnemySubStatus1]
+ bit SUBSTATUS_PERISH, a
+ jr z, .asm_38a8b
+
+ ld a, [wEnemyPerishCount]
+ cp 3
+ jr c, .asm_38ab4
+
+.asm_38a8b
+ push hl
+ ld hl, wPlayerUsedMoves
+ ld c, 4
+
+.asm_38a91
+ ld a, [hli]
+ and a
+ jr z, .asm_38aa2
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ cp EFFECT_PROTECT
+ jr z, .asm_38ab6
+ dec c
+ jr nz, .asm_38a91
+
+.asm_38aa2
+ pop hl
+ ld a, [wEnemySubStatus3]
+ bit SUBSTATUS_CONFUSED, a
+ jr nz, .asm_38aae
+
+ call AICheckEnemyHalfHP
+ ret c
+
+.asm_38aae
+ call Random
+ cp 79 percent - 1
+ ret c
+
+.asm_38ab4
+ inc [hl]
+ ret
+
+.asm_38ab6
+ pop hl
+ ld a, [hl]
+ add 6
+ ld [hl], a
+ ret
+
+AI_Smart_Confuse:
+; 90% chance to discourage this move if player's HP is between 25% and 50%.
+ call AICheckPlayerHalfHP
+ ret c
+ call Random
+ cp 10 percent
+ jr c, .asm_38ac8
+ inc [hl]
+
+.asm_38ac8
+; Discourage again if player's HP is below 25%.
+ call AICheckPlayerQuarterHP
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_SpDefenseUp2:
+; Discourage this move if enemy's HP is lower than 50%.
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38af1
+
+; Discourage this move if enemy's special defense level is higher than +3.
+ ld a, [wEnemySDefLevel]
+ cp $b
+ jr nc, .asm_38af1
+
+; 80% chance to greatly encourage this move if
+; enemy's Special Defense level is lower than +2, and the player is of a special type.
+ cp $9
+ ret nc
+
+ ld a, [wBattleMonType1]
+ cp SPECIAL
+ jr nc, .asm_38aea
+ ld a, [wBattleMonType2]
+ cp SPECIAL
+ ret c
+
+.asm_38aea
+ call AI_80_20
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38af1
+ inc [hl]
+ ret
+
+AI_Smart_Fly:
+; Fly, Dig
+
+; Greatly encourage this move if the player is
+; flying or underground, and slower than the enemy.
+
+ ld a, [wPlayerSubStatus3]
+ and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
+ ret z
+
+ call AICompareSpeed
+ ret nc
+
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_SuperFang:
+; Discourage this move if player's HP is below 25%.
+
+ call AICheckPlayerQuarterHP
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Paralyze:
+; 50% chance to discourage this move if player's HP is below 25%.
+ call AICheckPlayerQuarterHP
+ jr nc, .asm_38b1b
+
+; 80% chance to greatly encourage this move
+; if enemy is slower than player and its HP is above 25%.
+ call AICompareSpeed
+ ret c
+ call AICheckEnemyQuarterHP
+ ret nc
+ call AI_80_20
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38b1b
+ call AI_50_50
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_SpeedDownHit:
+; Icy Wind
+
+; Almost 90% chance to greatly encourage this move if the following conditions all meet:
+; Enemy's HP is higher than 25%.
+; It's the first turn of player's Pokemon.
+; Player is faster than enemy.
+
+ ld a, [wEnemyMoveStruct + MOVE_ANIM]
+ cp ICY_WIND
+ ret nz
+ call AICheckEnemyQuarterHP
+ ret nc
+ ld a, [wPlayerTurnsTaken]
+ and a
+ ret nz
+ call AICompareSpeed
+ ret c
+ call Random
+ cp 12 percent
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Substitute:
+; Dismiss this move if enemy's HP is below 50%.
+
+ call AICheckEnemyHalfHP
+ ret c
+ jp AIDiscourageMove
+
+AI_Smart_HyperBeam:
+ call AICheckEnemyHalfHP
+ jr c, .asm_38b53
+
+; 50% chance to encourage this move if enemy's HP is below 25%.
+ call AICheckEnemyQuarterHP
+ ret c
+ call AI_50_50
+ ret c
+ dec [hl]
+ ret
+
+.asm_38b53
+; If enemy's HP is above 50%, discourage this move at random
+ call Random
+ cp 35 percent + 1
+ ret c
+ inc [hl]
+ call AI_50_50
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Rage:
+ ld a, [wEnemySubStatus4]
+ bit SUBSTATUS_RAGE, a
+ jr z, .asm_38b7c
+
+; If enemy's Rage is building, 50% chance to encourage this move.
+ call AI_50_50
+ jr c, .asm_38b6d
+
+ dec [hl]
+
+; Encourage this move based on Rage's counter.
+.asm_38b6d
+ ld a, [wEnemyRageCounter]
+ cp $2
+ ret c
+ dec [hl]
+ ld a, [wEnemyRageCounter]
+ cp $3
+ ret c
+ dec [hl]
+ ret
+
+.asm_38b7c
+; If enemy's Rage is not building, discourage this move if enemy's HP is below 50%.
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38b87
+
+; 50% chance to encourage this move otherwise.
+ call AI_80_20
+ ret nc
+ dec [hl]
+ ret
+
+.asm_38b87
+ inc [hl]
+ ret
+
+AI_Smart_Mimic:
+ ld a, [wLastPlayerCounterMove]
+ and a
+ jr z, .asm_38bca
+
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38bd0
+
+ push hl
+ ld a, [wLastPlayerCounterMove]
+ call AIGetEnemyMove
+
+ ld a, $1
+ ldh [hBattleTurn], a
+ callfar BattleCheckTypeMatchup
+
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ pop hl
+ jr c, .asm_38bd0
+ jr z, .asm_38bb5
+
+ call AI_50_50
+ jr c, .asm_38bb5
+
+ dec [hl]
+
+.asm_38bb5
+ ld a, [wLastPlayerCounterMove]
+ push hl
+ ld hl, UsefulMoves
+ ld de, 1
+ call IsInArray
+
+ pop hl
+ ret nc
+ call AI_50_50
+ ret c
+ dec [hl]
+ ret
+
+.asm_38bca
+ call AICompareSpeed
+ jp c, AIDiscourageMove
+
+.asm_38bd0
+ inc [hl]
+ ret
+
+AI_Smart_Counter:
+ push hl
+ ld hl, wPlayerUsedMoves
+ ld c, 4
+ ld b, 0
+
+.asm_38bda
+ ld a, [hli]
+ and a
+ jr z, .asm_38c0e
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .asm_38c0e
+
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ cp SPECIAL
+ jr nc, .asm_38c0e
+
+ inc b
+
+.asm_38c0e
+ dec c
+ jr nz, .asm_38bda
+
+ pop hl
+ ld a, b
+ and a
+ jr z, .asm_38c1a
+
+ cp $3
+ jr nc, .asm_38c11
+
+ ld a, [wLastPlayerCounterMove]
+ and a
+ jr z, .asm_38c19
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .asm_38c19
+
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ cp SPECIAL
+ jr nc, .asm_38c19
+
+.asm_38c11
+ call Random
+ cp 39 percent + 1
+ jr c, .asm_38c19
+
+ dec [hl]
+
+.asm_38c19
+ ret
+
+.asm_38c1a
+ inc [hl]
+ ret
+
+AI_Smart_Encore:
+ call AICompareSpeed
+ jr nc, .asm_38c62
+
+ ld a, [wLastPlayerMove]
+ and a
+ jp z, AIDiscourageMove
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .asm_38c49
+
+ push hl
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ ld hl, wEnemyMonType1
+ predef CheckTypeMatchup
+
+ pop hl
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ jr nc, .asm_38c49
+
+ and a
+ ret nz
+ jr .asm_38c59
+
+.asm_38c49
+ push hl
+ ld a, [wLastPlayerCounterMove]
+ ld hl, EncoreMoves
+ ld de, 1
+ call IsInArray
+ pop hl
+ jr nc, .asm_38c62
+
+.asm_38c59
+ call Random
+ cp 28 percent - 1
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38c62
+ inc [hl]
+ inc [hl]
+ inc [hl]
+ ret
+
+INCLUDE "data/battle/ai/encore_moves.asm"
+
+AI_Smart_PainSplit:
+; Discourage this move if [enemy's current HP * 2 > player's current HP].
+
+ push hl
+ ld hl, wEnemyMonHP
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ sla c
+ rl b
+ ld hl, wBattleMonHP + 1
+ ld a, [hld]
+ cp c
+ ld a, [hl]
+ sbc b
+ pop hl
+ ret nc
+ inc [hl]
+ ret
+
+AI_Smart_Snore:
+AI_Smart_SleepTalk:
+; Greatly encourage this move if enemy is fast asleep.
+; Greatly discourage this move otherwise.
+
+ ld a, [wEnemyMonStatus]
+ and $7
+ cp $1
+ jr z, .asm_38ca8
+
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38ca8
+ inc [hl]
+ inc [hl]
+ inc [hl]
+ ret
+
+AI_Smart_DefrostOpponent:
+; Greatly encourage this move if enemy is frozen.
+; No move has EFFECT_DEFROST_OPPONENT, so this layer is unused.
+
+ ld a, [wEnemyMonStatus]
+ and 1 << FRZ
+ ret z
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Spite:
+ ld a, [wLastPlayerCounterMove]
+ and a
+ jr nz, .asm_38cc8
+
+ call AICompareSpeed
+ jp c, AIDiscourageMove
+
+ call AI_50_50
+ ret c
+ inc [hl]
+ ret
+
+.asm_38cc8
+ push hl
+ ld b, a
+ ld c, 4
+ ld hl, wBattleMonMoves
+ ld de, wBattleMonPP
+
+.asm_38cd2
+ ld a, [hli]
+ cp b
+ jr z, .asm_38cdc
+
+ inc de
+ dec c
+ jr nz, .asm_38cd2
+
+ pop hl
+ ret
+
+.asm_38cdc
+ pop hl
+ ld a, [de]
+ cp $6
+ jr c, .asm_38cee
+ cp $f
+ jr nc, .asm_38cec
+
+ call Random
+ cp 39 percent + 1
+ ret nc
+
+.asm_38cec
+ inc [hl]
+ ret
+
+.asm_38cee
+ call Random
+ cp 39 percent + 1
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+Function_0x38d16:
+ jp AIDiscourageMove
+
+AI_Smart_DestinyBond:
+AI_Smart_Reversal:
+AI_Smart_SkullBash:
+; Discourage this move if enemy's HP is above 25%.
+
+ call AICheckEnemyQuarterHP
+ ret nc
+ inc [hl]
+ ret
+
+AI_Smart_HealBell:
+; Dismiss this move if none of the opponent's Pokemon is statused.
+; Encourage this move if the enemy is statused.
+; 50% chance to greatly encourage this move if the enemy is fast asleep or frozen.
+
+ push hl
+ ld a, [wOTPartyCount]
+ ld b, a
+ ld c, 0
+ ld hl, wOTPartyMon1HP
+ ld de, PARTYMON_STRUCT_LENGTH
+
+.loop
+ push hl
+ ld a, [hli]
+ or [hl]
+ jr z, .next
+
+ ; status
+ dec hl
+ dec hl
+ dec hl
+ ld a, [hl]
+ or c
+ ld c, a
+
+.next
+ pop hl
+ add hl, de
+ dec b
+ jr nz, .loop
+
+ pop hl
+ ld a, c
+ and a
+ jr z, .no_status
+
+ ld a, [wEnemyMonStatus]
+ and a
+ jr z, .ok
+ dec [hl]
+.ok
+ and 1 << FRZ | SLP
+ ret z
+ call AI_50_50
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+.no_status
+ ld a, [wEnemyMonStatus]
+ and a
+ ret nz
+ jp AIDiscourageMove
+
+
+AI_Smart_PriorityHit:
+ call AICompareSpeed
+ ret c
+
+; Dismiss this move if the player is flying or underground.
+ ld a, [wPlayerSubStatus3]
+ and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
+ jp nz, AIDiscourageMove
+
+; Greatly encourage this move if it will KO the player.
+ ld a, $1
+ ldh [hBattleTurn], a
+ push hl
+ callfar EnemyAttackDamage
+ callfar BattleCommand_DamageCalc
+ callfar BattleCommand_Stab
+ pop hl
+ ld a, [wCurDamage + 1]
+ ld c, a
+ ld a, [wCurDamage]
+ ld b, a
+ ld a, [wBattleMonHP + 1]
+ cp c
+ ld a, [wBattleMonHP]
+ sbc b
+ ret nc
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Thief:
+; Don't use Thief unless it's the only move available.
+
+ ld a, [hl]
+ add $1e
+ ld [hl], a
+ ret
+
+AI_Smart_Conversion2:
+ ld a, [wLastPlayerMove]
+ and a
+ jr nz, .asm_38daa
+
+ push hl
+ dec a
+ ld hl, Moves + MOVE_TYPE
+ ld bc, MOVE_LENGTH
+ call AddNTimes
+
+ ld a, BANK(Moves)
+ call GetFarByte
+ ld [wPlayerMoveStruct + MOVE_TYPE], a
+
+ xor a
+ ldh [hBattleTurn], a
+
+ callfar BattleCheckTypeMatchup
+
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ pop hl
+ jr c, .asm_38daa
+ ret z
+
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+.asm_38daa
+ call Random
+ cp 10 percent
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Disable:
+ call AICompareSpeed
+ jr nc, .asm_38dd4
+
+ push hl
+ ld a, [wLastPlayerCounterMove]
+ ld hl, UsefulMoves
+ ld de, 1
+ call IsInArray
+
+ pop hl
+ jr nc, .asm_38dcf
+
+ call Random
+ cp 39 percent + 1
+ ret c
+ dec [hl]
+ ret
+
+.asm_38dcf
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ ret nz
+
+.asm_38dd4
+ call Random
+ cp 8 percent
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_MeanLook:
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38e05
+
+ push hl
+ call AICheckLastPlayerMon
+ pop hl
+ jp z, AIDiscourageMove
+
+; 80% chance to greatly encourage this move if the enemy is badly poisoned (buggy).
+; Should check wPlayerSubStatus5 instead.
+ ld a, [wEnemySubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38e07
+
+; 80% chance to greatly encourage this move if the player is either
+; in love, identified, stuck in Rollout, or has a Nightmare.
+ ld a, [wPlayerSubStatus1]
+ and 1 << SUBSTATUS_IN_LOVE | 1 << SUBSTATUS_ROLLOUT | 1 << SUBSTATUS_IDENTIFIED | 1 << SUBSTATUS_NIGHTMARE
+ jr nz, .asm_38e07
+
+; Otherwise, discourage this move unless the player only has not very effective moves against the enemy.
+ push hl
+ callfar CheckPlayerMoveTypeMatchups
+ ld a, [wEnemyAISwitchScore]
+ cp $b ; not very effective
+ pop hl
+ ret nc
+
+.asm_38e05
+ inc [hl]
+ ret
+
+.asm_38e07
+ call AI_80_20
+ ret c
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+AICheckLastPlayerMon:
+ ld a, [wPartyCount]
+ ld b, a
+ ld c, 0
+ ld hl, wPartyMon1HP
+ ld de, PARTYMON_STRUCT_LENGTH
+
+.loop
+ ld a, [wCurBattleMon]
+ cp c
+ jr z, .asm_38e25
+
+ ld a, [hli]
+ or [hl]
+ ret nz
+ dec hl
+
+.asm_38e25
+ add hl, de
+ inc c
+ dec b
+ jr nz, .loop
+
+ ret
+
+AI_Smart_Nightmare:
+; 50% chance to encourage this move.
+; The AI_Basic layer will make sure that
+; Dream Eater is only used against sleeping targets.
+
+ call AI_50_50
+ ret c
+ dec [hl]
+ ret
+
+AI_Smart_FlameWheel:
+; Use this move if the enemy is frozen.
+
+ ld a, [wEnemyMonStatus]
+ bit FRZ, a
+ ret z
+rept 5
+ dec [hl]
+endr
+ ret
+
+AI_Smart_Curse:
+ ld a, [wEnemyMonType1]
+ cp GHOST
+ jr z, .ghostcurse
+ ld a, [wEnemyMonType2]
+ cp GHOST
+ jr z, .ghostcurse
+
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38e72
+
+ ld a, [wEnemyAtkLevel]
+ cp $b
+ jr nc, .asm_38e72
+ cp $9
+ ret nc
+
+ ld a, [wBattleMonType1]
+ cp GHOST
+ jr z, .asm_38e71
+ cp SPECIAL
+ ret nc
+ ld a, [wBattleMonType2]
+ cp SPECIAL
+ ret nc
+ call AI_80_20
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38e71
+ inc [hl]
+.asm_38e72
+ inc [hl]
+ ret
+
+.ghostcurse
+ call AICheckEnemyQuarterHP
+ jp nc, AIDiscourageMove
+
+ call AICheckEnemyHalfHP
+ jr nc, .asm_38e72
+
+ ld a, [wPlayerSubStatus1]
+ bit SUBSTATUS_CURSE, a
+ jp nz, AIDiscourageMove
+
+ ld a, [wPlayerTurnsTaken]
+ and a
+ ret nz
+
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Protect:
+ ld a, [wEnemyProtectCount]
+ and a
+ jr nz, .asm_38ed4
+
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_LOCK_ON, a
+ jr nz, .asm_38ed5
+
+ ld a, [wPlayerFuryCutterCount]
+ cp 3
+ jr nc, .asm_38ece
+
+ ld a, [wPlayerSubStatus3]
+ bit SUBSTATUS_CHARGED, a
+ jr nz, .asm_38ece
+
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_TOXIC, a
+ jr nz, .asm_38ece
+ ld a, [wPlayerSubStatus4]
+ bit SUBSTATUS_LEECH_SEED, a
+ jr nz, .asm_38ece
+ ld a, [wPlayerSubStatus1]
+ bit SUBSTATUS_CURSE, a
+ jr nz, .asm_38ece
+
+ bit SUBSTATUS_ROLLOUT, a
+ jr z, .asm_38ed5
+
+ ld a, [wPlayerRolloutCount]
+ cp 3
+ jr c, .asm_38ed5
+
+.asm_38ece
+ call AI_80_20
+ ret c
+ dec [hl]
+ ret
+
+.asm_38ed4
+ inc [hl]
+
+.asm_38ed5
+ call Random
+ cp 8 percent
+ ret c
+ inc [hl]
+ inc [hl]
+ ret
+
+AI_Smart_Foresight:
+ ld a, [wEnemyAccLevel]
+ cp $5
+ jr c, .asm_38f02
+ ld a, [wPlayerEvaLevel]
+ cp $a
+ jr nc, .asm_38f02
+
+ ld a, [wBattleMonType1]
+ cp GHOST
+ jr z, .asm_38f02
+ ld a, [wBattleMonType2]
+ cp GHOST
+ jr z, .asm_38f02
+
+ call Random
+ cp 8 percent
+ ret c
+ inc [hl]
+ ret
+
+.asm_38f02
+ call Random
+ cp 39 percent + 1
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_PerishSong:
+ push hl
+ callfar FindAliveEnemyMons
+ pop hl
+ jr c, .no
+
+ ld a, [wPlayerSubStatus5]
+ bit SUBSTATUS_CANT_RUN, a
+ jr nz, .yes
+
+ push hl
+ callfar CheckPlayerMoveTypeMatchups
+ ld a, [wEnemyAISwitchScore]
+ cp 10 ; 1.0
+ pop hl
+ ret c
+
+ call AI_50_50
+ ret c
+
+ inc [hl]
+ ret
+
+.yes
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+.no
+ ld a, [hl]
+ add 5
+ ld [hl], a
+ ret
+
+AI_Smart_Sandstorm:
+; Greatly discourage this move if the player is immune to Sandstorm damage.
+ ld a, [wBattleMonType1]
+ push hl
+ ld hl, .SandstormImmuneTypes
+ ld de, 1
+ call IsInArray
+ pop hl
+ jr c, .asm_38f66
+
+ ld a, [wBattleMonType2]
+ push hl
+ ld hl, .SandstormImmuneTypes
+ ld de, 1
+ call IsInArray
+ pop hl
+ jr c, .asm_38f66
+
+; Discourage this move if player's HP is below 50%.
+ call AICheckPlayerHalfHP
+ jr nc, .asm_38f67
+
+; 50% chance to encourage this move otherwise.
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+.asm_38f66
+ inc [hl]
+
+.asm_38f67
+ inc [hl]
+ ret
+
+.SandstormImmuneTypes:
+ db ROCK
+ db GROUND
+ db STEEL
+ db -1 ; end
+
+AI_Smart_Endure:
+ ld a, [wEnemyProtectCount]
+ and a
+ jr nz, .asm_38f99
+
+ call AICheckEnemyMaxHP
+ jr c, .asm_38f99
+
+ call AICheckEnemyQuarterHP
+ jr c, .asm_38f9a
+
+ ld b, EFFECT_REVERSAL
+ call AIHasMoveEffect
+ jr nc, .asm_38f8c
+
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38f8c
+ ld a, [wEnemySubStatus5]
+ bit SUBSTATUS_LOCK_ON, a
+ ret z
+
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38f99
+ inc [hl]
+
+.asm_38f9a
+ inc [hl]
+ ret
+
+AI_Smart_FuryCutter:
+; Encourage this move based on Fury Cutter's count.
+
+ ld a, [wEnemyFuryCutterCount]
+ and a
+ jr z, .end
+ dec [hl]
+
+ cp 2
+ jr c, .end
+ dec [hl]
+ dec [hl]
+
+ cp 3
+ jr c, .end
+ dec [hl]
+ dec [hl]
+ dec [hl]
+
+.end
+
+ ; fallthrough
+
+AI_Smart_Rollout:
+; Rollout, Fury Cutter
+
+; 80% chance to discourage this move if the enemy is in love, confused, or paralyzed.
+ ld a, [wEnemySubStatus1]
+ bit SUBSTATUS_IN_LOVE, a
+ jr nz, .asm_38fe1
+
+ ld a, [wEnemySubStatus3]
+ bit SUBSTATUS_CONFUSED, a
+ jr nz, .asm_38fe1
+
+ ld a, [wEnemyMonStatus]
+ bit PAR, a
+ jr nz, .asm_38fe1
+
+; 80% chance to discourage this move if the enemy's HP is below 25%,
+; or if accuracy or evasion modifiers favour the player.
+ call AICheckEnemyQuarterHP
+ jr nc, .asm_38fe1
+
+ ld a, [wEnemyAccLevel]
+ cp 7
+ jr c, .asm_38fe1
+ ld a, [wPlayerEvaLevel]
+ cp 8
+ jr nc, .asm_38fe1
+
+; Otherwise, 80% chance to greatly encourage this move.
+ call Random
+ cp 79 percent - 1
+ ret nc
+ dec [hl]
+ dec [hl]
+ ret
+
+.asm_38fe1
+ call AI_80_20
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Swagger:
+AI_Smart_Attract:
+; 80% chance to encourage this move during the first turn of player's Pokemon.
+; 80% chance to discourage this move otherwise.
+
+ ld a, [wPlayerTurnsTaken]
+ and a
+ jr z, .first_turn
+
+ call AI_80_20
+ ret c
+ inc [hl]
+ ret
+
+.first_turn
+ call Random
+ cp 79 percent - 1
+ ret nc
+ dec [hl]
+ ret
+
+AI_Smart_Safeguard:
+; 80% chance to discourage this move if player's HP is below 50%.
+
+ call AICheckPlayerHalfHP
+ ret c
+ call AI_80_20
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Magnitude:
+AI_Smart_Earthquake:
+; Greatly encourage this move if the player is underground and the enemy is faster.
+ ld a, [wLastPlayerCounterMove]
+ cp DIG
+ ret nz
+
+ ld a, [wPlayerSubStatus3]
+ bit SUBSTATUS_UNDERGROUND, a
+ jr z, .could_dig
+
+ call AICompareSpeed
+ ret nc
+ dec [hl]
+ dec [hl]
+ ret
+
+.could_dig
+ ; Try to predict if the player will use Dig this turn.
+
+ ; 50% chance to encourage this move if the enemy is slower than the player.
+ call AICompareSpeed
+ ret c
+
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+AI_Smart_BatonPass:
+; Discourage this move if the player hasn't shown super-effective moves against the enemy.
+; Consider player's type(s) if its moves are unknown.
+
+ push hl
+ callfar CheckPlayerMoveTypeMatchups
+ ld a, [wEnemyAISwitchScore]
+ cp 10 ; neutral
+ pop hl
+ ret c
+ inc [hl]
+ ret
+
+AI_Smart_Pursuit:
+; 50% chance to greatly encourage this move if player's HP is below 25%.
+; 80% chance to discourage this move otherwise.
+
+ call AICheckPlayerQuarterHP
+ jr nc, .asm_3903e
+ call AI_80_20
+ ret c
+ inc [hl]
+ ret
+
+.asm_3903e
+ call AI_50_50
+ ret c
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_RapidSpin:
+; 80% chance to greatly encourage this move if the enemy is
+; trapped (Bind effect), seeded, or scattered with spikes.
+
+ ld a, [wEnemyWrapCount]
+ and a
+ jr nz, .asm_39058
+
+ ld a, [wEnemySubStatus4]
+ bit SUBSTATUS_LEECH_SEED, a
+ jr nz, .asm_39058
+
+ ld a, [wEnemyScreens]
+ bit SCREENS_SPIKES, a
+ ret z
+
+.asm_39058
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_HiddenPower:
+ push hl
+ ld a, 1
+ ldh [hBattleTurn], a
+
+; Calculate Hidden Power's type and base power based on enemy's DVs.
+ callfar HiddenPowerDamage
+ callfar BattleCheckTypeMatchup
+ pop hl
+
+; Discourage Hidden Power if not very effective.
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE
+ jr c, .bad
+
+; Discourage Hidden Power if its base power is lower than 50.
+ ld a, d
+ cp 50
+ jr c, .bad
+
+; Encourage Hidden Power if super-effective.
+ ld a, [wTypeMatchup]
+ cp EFFECTIVE + 1
+ jr nc, .good
+
+; Encourage Hidden Power if its base power is 70.
+ ld a, d
+ cp 70
+ ret c
+
+.good
+ dec [hl]
+ ret
+
+.bad
+ inc [hl]
+ ret
+
+AI_Smart_RainDance:
+; Greatly discourage this move if it would favour the player type-wise.
+; Particularly, if the player is a Water-type.
+ ld a, [wBattleMonType1]
+ cp WATER
+ jr z, AIBadWeatherType
+ cp FIRE
+ jr z, AIGoodWeatherType
+
+ ld a, [wBattleMonType2]
+ cp WATER
+ jr z, AIBadWeatherType
+ cp FIRE
+ jr z, AIGoodWeatherType
+
+ push hl
+ ld hl, RainDanceMoves
+ jr AI_Smart_WeatherMove
+
+INCLUDE "data/battle/ai/rain_dance_moves.asm"
+
+AI_Smart_SunnyDay:
+; Greatly discourage this move if it would favour the player type-wise.
+; Particularly, if the player is a Fire-type.
+ ld a, [wBattleMonType1]
+ cp FIRE
+ jr z, AIBadWeatherType
+ cp WATER
+ jr z, AIGoodWeatherType
+
+ ld a, [wBattleMonType2]
+ cp FIRE
+ jr z, AIBadWeatherType
+ cp WATER
+ jr z, AIGoodWeatherType
+
+ push hl
+ ld hl, SunnyDayMoves
+
+ ; fallthrough
+
+AI_Smart_WeatherMove:
+; Rain Dance, Sunny Day
+
+; Greatly discourage this move if the enemy doesn't have
+; one of the useful Rain Dance or Sunny Day moves.
+ call AIHasMoveInArray
+ pop hl
+ jr nc, AIBadWeatherType
+
+; Greatly discourage this move if player's HP is below 50%.
+ call AICheckPlayerHalfHP
+ jr nc, AIBadWeatherType
+
+; 50% chance to encourage this move otherwise.
+ call AI_50_50
+ ret c
+
+ dec [hl]
+ ret
+
+AIBadWeatherType:
+ inc [hl]
+ inc [hl]
+ inc [hl]
+ ret
+
+AIGoodWeatherType:
+; Rain Dance, Sunny Day
+
+; Greatly encourage this move if it would disfavour the player type-wise and player's HP is above 50%...
+ call AICheckPlayerHalfHP
+ ret nc
+
+; ...as long as one of the following conditions meet:
+; It's the first turn of the player's Pokemon.
+ ld a, [wPlayerTurnsTaken]
+ and a
+ jr z, .good
+
+; Or it's the first turn of the enemy's Pokemon.
+ ld a, [wEnemyTurnsTaken]
+ and a
+ ret nz
+
+.good
+ dec [hl]
+ dec [hl]
+ ret
+
+INCLUDE "data/battle/ai/sunny_day_moves.asm"
+
+AI_Smart_BellyDrum:
+; Dismiss this move if enemy's attack is higher than +2 or if enemy's HP is below 50%.
+; Else, discourage this move if enemy's HP is not full.
+
+ ld a, [wEnemyAtkLevel]
+ cp $a
+ jr nc, .asm_3910e
+
+ call AICheckEnemyMaxHP
+ ret c
+
+ inc [hl]
+
+ call AICheckEnemyHalfHP
+ ret c
+
+.asm_3910e
+ ld a, [hl]
+ add $5
+ ld [hl], a
+ ret
+
+AI_Smart_PsychUp:
+ push hl
+ ld hl, wEnemyAtkLevel
+ ld b, $8
+ ld c, 100
+
+; Calculate the sum of all enemy's stat level modifiers. Add 100 first to prevent underflow.
+; Put the result in c. c will range between 58 and 142.
+.asm_3911b
+ ld a, [hli]
+ sub $7
+ add c
+ ld c, a
+ dec b
+ jr nz, .asm_3911b
+
+; Calculate the sum of all player's stat level modifiers. Add 100 first to prevent underflow.
+; Put the result in d. d will range between 58 and 142.
+ ld hl, wPlayerAtkLevel
+ ld b, $8
+ ld d, 100
+
+.asm_3912a
+ ld a, [hli]
+ sub $7
+ add d
+ ld d, a
+ dec b
+ jr nz, .asm_3912a
+
+; Greatly discourage this move if enemy's stat levels are higher than player's (if c>=d).
+ ld a, c
+ sub d
+ pop hl
+ jr nc, .asm_3914f
+
+; This block will always ret, since the comparisons to wPlayerEvaLevel capture every possible value
+ ld a, [wPlayerAccLevel]
+ cp $6
+ ret c
+
+ ld a, [wPlayerEvaLevel]
+ cp $9
+ ret c
+
+ ld a, [wPlayerEvaLevel]
+ cp $8
+ ret nc
+
+; unused
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ ret
+
+.asm_3914f
+ inc [hl]
+ ret
+
+AI_Smart_MirrorCoat:
+ push hl
+ ld hl, wPlayerUsedMoves
+ ld c, $4
+ ld b, $0
+
+.asm_39159
+ ld a, [hli]
+ and a
+ jr z, .asm_3916e
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .asm_3916e
+
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ cp SPECIAL
+ jr c, .asm_3916e
+
+ inc b
+
+.asm_3916e
+ dec c
+ jr nz, .asm_39159
+
+ pop hl
+ ld a, b
+ and a
+ jr z, .asm_39199
+
+ cp $3
+ jr nc, .asm_39190
+
+ ld a, [wLastPlayerCounterMove]
+ and a
+ jr z, .asm_39198
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .asm_39198
+
+ ld a, [wEnemyMoveStruct + MOVE_TYPE]
+ cp SPECIAL
+ jr c, .asm_39198
+
+.asm_39190
+ call Random
+ cp 100
+ jr c, .asm_39198
+ dec [hl]
+
+.asm_39198
+ ret
+
+.asm_39199
+ inc [hl]
+ ret
+
+AI_Smart_Twister:
+AI_Smart_Gust:
+; Greatly encourage this move if the player is flying and the enemy is faster.
+ ld a, [wLastPlayerCounterMove]
+ cp FLY
+ ret nz
+
+ ld a, [wPlayerSubStatus3]
+ bit SUBSTATUS_FLYING, a
+ jr z, .couldFly
+
+ call AICompareSpeed
+ ret nc
+
+ dec [hl]
+ dec [hl]
+ ret
+
+; Try to predict if the player will use Fly this turn.
+.couldFly
+
+; 50% chance to encourage this move if the enemy is slower than the player.
+ call AICompareSpeed
+ ret c
+ call AI_50_50
+ ret c
+ dec [hl]
+ ret
+
+AI_Smart_FutureSight:
+; Greatly encourage this move if the player is
+; flying or underground, and slower than the enemy.
+
+ call AICompareSpeed
+ ret nc
+
+ ld a, [wPlayerSubStatus3]
+ and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
+ ret z
+
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Stomp:
+; 80% chance to encourage this move if the player has used Minimize.
+
+ ld a, [wPlayerMinimized]
+ and a
+ ret z
+
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ ret
+
+AI_Smart_Solarbeam:
+; 80% chance to encourage this move when it's sunny.
+; 90% chance to discourage this move when it's raining.
+
+ ld a, [wBattleWeather]
+ cp WEATHER_SUN
+ jr z, .asm_391e4
+
+ cp WEATHER_RAIN
+ ret nz
+
+ call Random
+ cp 10 percent
+ ret c
+
+ inc [hl]
+ inc [hl]
+ ret
+
+.asm_391e4
+ call AI_80_20
+ ret c
+
+ dec [hl]
+ dec [hl]
+ ret
+
+AI_Smart_Thunder:
+; 90% chance to discourage this move when it's sunny.
+
+ ld a, [wBattleWeather]
+ cp WEATHER_SUN
+ ret nz
+
+ call Random
+ cp 10 percent
+ ret c
+
+ inc [hl]
+ ret
+
+AICompareSpeed:
+; Return carry if enemy is faster than player.
+
+ push bc
+ ld a, [wEnemyMonSpeed + 1]
+ ld b, a
+ ld a, [wBattleMonSpeed + 1]
+ cp b
+ ld a, [wEnemyMonSpeed]
+ ld b, a
+ ld a, [wBattleMonSpeed]
+ sbc b
+ pop bc
+ ret
+
+AICheckPlayerMaxHP:
+ push hl
+ push de
+ push bc
+ ld de, wBattleMonHP
+ ld hl, wBattleMonMaxHP
+ jr AICheckMaxHP
+
+AICheckEnemyMaxHP:
+ push hl
+ push de
+ push bc
+ ld de, wEnemyMonHP
+ ld hl, wEnemyMonMaxHP
+ ; fallthrough
+
+AICheckMaxHP:
+; Return carry if hp at de matches max hp at hl.
+
+ ld a, [de]
+ inc de
+ cp [hl]
+ jr nz, .asm_3922f
+
+ inc hl
+ ld a, [de]
+ cp [hl]
+ jr nz, .asm_3922f
+
+ pop bc
+ pop de
+ pop hl
+ scf
+ ret
+
+.asm_3922f
+ pop bc
+ pop de
+ pop hl
+ and a
+ ret
+
+AICheckPlayerHalfHP:
+ push hl
+ ld hl, wBattleMonHP
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ sla c
+ rl b
+ inc hl
+ inc hl
+ ld a, [hld]
+ cp c
+ ld a, [hl]
+ sbc b
+ pop hl
+ ret
+
+AICheckEnemyHalfHP:
+ push hl
+ push de
+ push bc
+ ld hl, wEnemyMonHP
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ sla c
+ rl b
+ inc hl
+ inc hl
+ ld a, [hld]
+ cp c
+ ld a, [hl]
+ sbc b
+ pop bc
+ pop de
+ pop hl
+ ret
+
+AICheckEnemyQuarterHP:
+ push hl
+ push de
+ push bc
+ ld hl, wEnemyMonHP
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ sla c
+ rl b
+ sla c
+ rl b
+ inc hl
+ inc hl
+ ld a, [hld]
+ cp c
+ ld a, [hl]
+ sbc b
+ pop bc
+ pop de
+ pop hl
+ ret
+
+AICheckPlayerQuarterHP:
+ push hl
+ ld hl, wBattleMonHP
+ ld b, [hl]
+ inc hl
+ ld c, [hl]
+ sla c
+ rl b
+ sla c
+ rl b
+ inc hl
+ inc hl
+ ld a, [hld]
+ cp c
+ ld a, [hl]
+ sbc b
+ pop hl
+ ret
+
+AIHasMoveEffect:
+; Return carry if the enemy has move b.
+
+ push hl
+ ld hl, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves
+
+.checkmove
+ ld a, [hli]
+ and a
+ jr z, .no
+
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ cp b
+ jr z, .yes
+
+ dec c
+ jr nz, .checkmove
+
+.no
+ pop hl
+ and a
+ ret
+
+.yes
+ pop hl
+ scf
+ ret
+
+AIHasMoveInArray:
+; Return carry if the enemy has a move in array hl.
+
+ push hl
+ push de
+ push bc
+
+.next
+ ld a, [hli]
+ cp $ff
+ jr z, .done
+
+ ld b, a
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+ ld de, wEnemyMonMoves
+
+.check
+ dec c
+ jr z, .next
+
+ ld a, [de]
+ inc de
+ cp b
+ jr nz, .check
+
+ scf
+
+.done
+ pop bc
+ pop de
+ pop hl
+ ret
+
+INCLUDE "data/battle/ai/useful_moves.asm"
+
+AI_Opportunist:
+; Discourage stall moves when the enemy's HP is low.
+
+; Do nothing if enemy's HP is above 50%.
+ call AICheckEnemyHalfHP
+ ret c
+
+; Discourage stall moves if enemy's HP is below 25%.
+ call AICheckEnemyQuarterHP
+ jr nc, .asm_392e8
+
+; 50% chance to discourage stall moves if enemy's HP is between 25% and 50%.
+ call AI_50_50
+ ret c
+
+.asm_392e8
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ inc hl
+ dec c
+ jr z, .asm_3930d
+
+ ld a, [de]
+ inc de
+ and a
+ jr z, .asm_3930d
+
+ push hl
+ push de
+ push bc
+ ld hl, StallMoves
+ ld de, 1
+ call IsInArray
+
+ pop bc
+ pop de
+ pop hl
+ jr nc, .checkmove
+
+ inc [hl]
+ jr .checkmove
+
+.asm_3930d
+ ret
+
+INCLUDE "data/battle/ai/stall_moves.asm"
+
+
+AI_Aggressive:
+; Use whatever does the most damage.
+
+; Discourage all damaging moves but the one that does the most damage.
+; If no damaging move deals damage to the player (immune),
+; no move will be discouraged
+
+; Figure out which attack does the most damage and put it in c.
+ ld hl, wEnemyMonMoves
+ ld bc, 0
+ ld de, 0
+.checkmove
+ inc b
+ ld a, b
+ cp wEnemyMonMovesEnd - wEnemyMonMoves + 1
+ jr z, .gotstrongestmove
+
+ ld a, [hli]
+ and a
+ jr z, .gotstrongestmove
+
+ push hl
+ push de
+ push bc
+ call AIGetEnemyMove
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .nodamage
+ call AIDamageCalc
+ pop bc
+ pop de
+ pop hl
+
+; Update current move if damage is highest so far
+ ld a, [wCurDamage + 1]
+ cp e
+ ld a, [wCurDamage]
+ sbc d
+ jr c, .checkmove
+
+ ld a, [wCurDamage + 1]
+ ld e, a
+ ld a, [wCurDamage]
+ ld d, a
+ ld c, b
+ jr .checkmove
+
+.nodamage
+ pop bc
+ pop de
+ pop hl
+ jr .checkmove
+
+.gotstrongestmove
+; Nothing we can do if no attacks did damage.
+ ld a, c
+ and a
+ jr z, .done
+
+; Discourage moves that do less damage unless they're reckless too.
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, 0
+.checkmove2
+ inc b
+ ld a, b
+ cp wEnemyMonMovesEnd - wEnemyMonMoves + 1
+ jr z, .done
+
+; Ignore this move if it is the highest damaging one.
+ cp c
+ ld a, [de]
+ inc de
+ inc hl
+ jr z, .checkmove2
+
+ call AIGetEnemyMove
+
+; Ignore this move if its power is 0 or 1.
+; Moves such as Seismic Toss, Hidden Power,
+; Counter and Fissure have a base power of 1.
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ cp 2
+ jr c, .checkmove2
+
+; Ignore this move if it is reckless.
+ push hl
+ push de
+ push bc
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ ld hl, RecklessMoves
+ ld de, 1
+ call IsInArray
+ pop bc
+ pop de
+ pop hl
+ jr c, .checkmove2
+
+; If we made it this far, discourage this move.
+ inc [hl]
+ jr .checkmove2
+
+.done
+ ret
+
+INCLUDE "data/battle/ai/reckless_moves.asm"
+
+AIDamageCalc:
+ ld a, 1
+ ldh [hBattleTurn], a
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ ld de, 1
+ ld hl, ConstantDamageEffects
+ call IsInArray
+ jr nc, .asm_393c6
+ callfar BattleCommand_ConstantDamage
+ ret
+
+.asm_393c6
+ callfar EnemyAttackDamage
+ callfar BattleCommand_DamageCalc
+ callfar BattleCommand_Stab
+ ret
+
+INCLUDE "data/battle/ai/constant_damage_effects.asm"
+
+AI_Cautious:
+; 90% chance to discourage moves with residual effects after the first turn.
+
+ ld a, [wEnemyTurnsTaken]
+ and a
+ ret z
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.asm_393eb
+ inc hl
+ dec c
+ ret z
+
+ ld a, [de]
+ inc de
+ and a
+ ret z
+
+ push hl
+ push de
+ push bc
+ ld hl, ResidualMoves
+ ld de, 1
+ call IsInArray
+
+ pop bc
+ pop de
+ pop hl
+ jr nc, .asm_393eb
+
+ call Random
+ cp 90 percent + 1
+ ret nc
+
+ inc [hl]
+ jr .asm_393eb
+
+INCLUDE "data/battle/ai/residual_moves.asm"
+
+
+AI_Status:
+; Dismiss status moves that don't affect the player.
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld b, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ dec b
+ ret z
+
+ inc hl
+ ld a, [de]
+ and a
+ ret z
+
+ inc de
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ cp EFFECT_TOXIC
+ jr z, .poisonimmunity
+ cp EFFECT_POISON
+ jr z, .poisonimmunity
+ cp EFFECT_SLEEP
+ jr z, .typeimmunity
+ cp EFFECT_PARALYZE
+ jr z, .typeimmunity
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .checkmove
+
+ jr .typeimmunity
+
+.poisonimmunity
+ ld a, [wBattleMonType1]
+ cp POISON
+ jr z, .immune
+ ld a, [wBattleMonType2]
+ cp POISON
+ jr z, .immune
+
+.typeimmunity
+ push hl
+ push bc
+ push de
+ ld a, 1
+ ldh [hBattleTurn], a
+ callfar BattleCheckTypeMatchup
+ pop de
+ pop bc
+ pop hl
+
+ ld a, [wTypeMatchup]
+ and a
+ jr nz, .checkmove
+
+.immune
+ call AIDiscourageMove
+ jr .checkmove
+
+
+AI_Risky:
+; Use any move that will KO the target.
+; Risky moves will often be an exception (see below).
+
+ ld hl, wBuffer1 - 1
+ ld de, wEnemyMonMoves
+ ld c, wEnemyMonMovesEnd - wEnemyMonMoves + 1
+.checkmove
+ inc hl
+ dec c
+ ret z
+
+ ld a, [de]
+ inc de
+ and a
+ ret z
+
+ push de
+ push bc
+ push hl
+ call AIGetEnemyMove
+
+ ld a, [wEnemyMoveStruct + MOVE_POWER]
+ and a
+ jr z, .nextmove
+
+; Don't use risky moves at max hp.
+ ld a, [wEnemyMoveStruct + MOVE_EFFECT]
+ ld de, 1
+ ld hl, RiskyEffects
+ call IsInArray
+ jr nc, .checkko
+
+ call AICheckEnemyMaxHP
+ jr c, .nextmove
+
+; Else, 80% chance to exclude them.
+ call Random
+ cp 79 percent - 1
+ jr c, .nextmove
+
+.checkko
+ call AIDamageCalc
+
+ ld a, [wCurDamage + 1]
+ ld e, a
+ ld a, [wCurDamage]
+ ld d, a
+ ld a, [wBattleMonHP + 1]
+ cp e
+ ld a, [wBattleMonHP]
+ sbc d
+ jr nc, .nextmove
+
+ pop hl
+rept 5
+ dec [hl]
+endr
+ push hl
+
+.nextmove
+ pop hl
+ pop bc
+ pop de
+ jr .checkmove
+
+INCLUDE "data/battle/ai/risky_effects.asm"
+
+
+AI_None:
+ ret
+
+AIDiscourageMove:
+ ld a, [hl]
+ add 10
+ ld [hl], a
+ ret
+
+AIGetEnemyMove:
+; Load attributes of move a into ram
+
+ push hl
+ push de
+ push bc
+ dec a
+ ld hl, Moves
+ ld bc, MOVE_LENGTH
+ call AddNTimes
+
+ ld de, wEnemyMoveStruct
+ ld a, BANK(Moves)
+ call FarCopyBytes
+
+ pop bc
+ pop de
+ pop hl
+ ret
+
+AI_80_20:
+ call Random
+ cp 20 percent - 1
+ ret
+
+AI_50_50:
+ call Random
+ cp 50 percent + 1
+ ret
diff --git a/home/battle_vars.asm b/home/battle_vars.asm
index 29acb040..6fc94409 100755
--- a/home/battle_vars.asm
+++ b/home/battle_vars.asm
@@ -107,5 +107,5 @@ BattleVarLocations:
dw wPlayerMoveStructPower, wEnemyMoveStructPower
dw wPlayerMoveStructType, wEnemyMoveStructType
dw wCurPlayerMove, wCurEnemyMove
- dw wLastEnemyCounterMove, wLastPlayerCounterMove
+ dw wLastPlayerCounterMove, wLastEnemyCounterMove
dw wLastPlayerMove, wLastEnemyMove
diff --git a/main.asm b/main.asm
index 91cd7c07..68e1b80b 100644
--- a/main.asm
+++ b/main.asm
@@ -277,7 +277,9 @@ JohtoGrassWildMons:
dr $2ab35, $2c000
SECTION "bankb", ROMX, BANK[$b]
- dr $2c000, $2c352
+ dr $2c000, $2c225
+AI_Redundant:
+ dr $2c225, $2c352
MoveDeletion:
dr $2c352, $2c57a
@@ -300,11 +302,26 @@ SECTION "bankc", ROMX, BANK[$c]
dr $30000, $34000
SECTION "bankd", ROMX
- dr $34000, $34923
+ dr $34000, $34822
+BattleCommand_Stab:
+ dr $34822, $34918
+BattleCheckTypeMatchup::
+ dr $34918, $34923
CheckTypeMatchup::
- dr $34923, $34a91
+ dr $34923, $3499e
+CheckPlayerMoveTypeMatchups::
+ dr $3499e, $34a91
CheckAbleToSwitch::
- dr $34a91, $36313
+ dr $34a91, $34b44
+FindAliveEnemyMons::
+ dr $34b44, $3553d
+
+EnemyAttackDamage::
+ dr $3553d, $35753
+BattleCommand_DamageCalc::
+ dr $35753, $35868
+BattleCommand_ConstantDamage::
+ dr $35868, $36313
RaiseStat:
dr $36313, $364d7
@@ -321,15 +338,8 @@ GetItemHeldEffect:
SECTION "banke", ROMX
INCLUDE "engine/battle/ai/items.asm"
-;INCLUDE "engine/battle/ai/scoring.asm"
- dr $38583, $39217
-
-AICheckEnemyMaxHP::
- dr $39217, $39247
-AICheckEnemyHalfHP::
- dr $39247, $3925e
-AICheckEnemyQuarterHP::
- dr $3925e, $394f3
+INCLUDE "engine/battle/ai/scoring.asm"
+
GetTrainerClassName::
dr $394f3, $39562
TrainerClassAttributes::
@@ -904,7 +914,9 @@ UpdateUnownDex:
CheckMagikarpLength:
dr $fbc3c, $fbdd6
MagikarpHouseSign:
- dr $fbdd6, $fc000
+ dr $fbdd6, $fbdf1
+HiddenPowerDamage:
+ dr $fbdf1, $fc000
SECTION "bank3f", ROMX, BANK[$3f]
nop
diff --git a/wram.asm b/wram.asm
index cf7a49b9..1b0ee4a7 100644
--- a/wram.asm
+++ b/wram.asm
@@ -1667,20 +1667,20 @@ wEnemySubStatus2:: ds 1 ; cb4c
wEnemySubStatus3:: ds 1 ; cb4d
wEnemySubStatus4:: ds 1 ; cb4e
wEnemySubStatus5:: ds 1 ; cb4f
-wcb50:: ds 1 ; cb50
+wPlayerRolloutCount:: db ; cb50
wcb51:: ds 1 ; cb51
wcb52:: ds 1 ; cb52
wcb53:: ds 1 ; cb53
wcb54:: ds 1 ; cb54
wcb55:: ds 1 ; cb55
-wcb56:: ds 1 ; cb56
+wPlayerFuryCutterCount:: db ; cb56
wcb57:: ds 1 ; cb57
wcb58:: ds 1 ; cb58
wEnemyConfuseCount:: db ; cb59
wEnemyToxicCount:: db ; cb5a
wcb5b:: ds 1 ; cb5b
wcb5c:: ds 1 ; cb5c
-wcb5d:: ds 1 ; cb5d
+wEnemyPerishCount:: db ; cb5d
wEnemyFuryCutterCount:: db ; cb5e
wEnemyProtectCount:: db ; cb5f
wPlayerDamageTaken::
@@ -1760,24 +1760,24 @@ wcba6:: ds 1 ; cba6
wcba7:: ds 1 ; cba7
wcba8:: ds 1 ; cba8
wcba9:: ds 1 ; cba9
-wcbaa:: ds 1 ; cbaa
-wcbab:: ds 1 ; cbab
-wcbac:: ds 1 ; cbac
-wcbad:: ds 1 ; cbad
-wcbae:: ds 1 ; cbae
-wcbaf:: ds 1 ; cbaf
-wcbb0:: ds 1 ; cbb0
-wcbb1:: ds 1 ; cbb1
-wcbb2:: ds 1 ; cbb2
-wcbb3:: ds 1 ; cbb3
-wcbb4:: ds 1 ; cbb4
-wcbb5:: ds 1 ; cbb5
-wcbb6:: ds 1 ; cbb6
-wcbb7:: ds 1 ; cbb7
-wcbb8:: ds 1 ; cbb8
-wcbb9:: ds 1 ; cbb9
+wPlayerAtkLevel:: db ; cbaa
+wPlayerDefLevel:: db ; cbab
+wPlayerSpdLevel:: db ; cbac
+wPlayerSAtkLevel:: db ; cbad
+wPlayerSDefLevel:: db ; cbae
+wPlayerAccLevel:: db ; cbaf
+wPlayerEvaLevel:: db ; cbb0
+ ds 1
+wEnemyAtkLevel:: db ; cbb2
+wEnemyDefLevel:: db ; cbb3
+wEnemySpdLevel:: db ; cbb4
+wEnemySAtkLevel:: db ; cbb5
+wEnemySDefLevel:: db ; cbb6
+wEnemyAccLevel:: db ; cbb7
+wEnemyEvaLevel:: db ; cbb8
+ ds 1
wEnemyTurnsTaken:: db ; cbba
-wcbbb:: ds 1 ; cbbb
+wPlayerTurnsTaken:: db ; cbbb
wcbbc:: ds 1 ; cbbc
wcbbd:: ds 1 ; cbbd
wcbbe:: ds 1 ; cbbe
@@ -1803,15 +1803,18 @@ wcbd2:: ds 1 ; cbd2
wcbd3:: ds 1 ; cbd3
wcbd4:: ds 1 ; cbd4
wcbd5:: ds 1 ; cbd5
-wLastEnemyCounterMove:: ds 1 ; cbd6
-wLastPlayerCounterMove:: ds 1 ; cbd7
+
+; exists so you can't counter on switch
+wLastPlayerCounterMove:: db ; cbd6
+wLastEnemyCounterMove:: db ; cbd7
+
wcbd8:: ds 1 ; cbd8
wcbd9:: ds 1 ; cbd9
wcbda:: ds 1 ; cbda
wcbdb:: ds 1 ; cbdb
-wcbdc:: ds 1 ; cbdc
-wcbdd:: ds 1 ; cbdd
-wcbde:: ds 1 ; cbde
+wPlayerMinimized:: db ; cbdc
+wPlayerScreens:: db ; cbdd
+wEnemyScreens:: db ; cbde
wcbdf:: ds 1 ; cbdf
wcbe0:: ds 1 ; cbe0
wcbe1:: ds 1 ; cbe1
@@ -1821,7 +1824,7 @@ wcbe4:: ds 1 ; cbe4
wcbe5:: ds 1 ; cbe5
wcbe6:: ds 1 ; cbe6
wcbe7:: ds 1 ; cbe7
-wcbe8:: ds 1 ; cbe8
+wBattleWeather:: db ; cbe8
wcbe9:: ds 1 ; cbe9
wcbea:: ds 1 ; cbea
wcbeb:: ds 1 ; cbeb
@@ -1829,11 +1832,12 @@ wcbec:: ds 1 ; cbec
wEnemyGoesFirst:: db ; cbed
wcbee:: ds 1 ; cbee
wEnemyIsSwitching:: db ; cbef
-wcbf0:: ds 1 ; cbf0
-wcbf1:: ds 1 ; cbf1
-wcbf2:: ds 1 ; cbf2
-wcbf3:: ds 1 ; cbf3
-wcbf4:: ds 1 ; cbf4
+wPlayerUsedMoves:: ; cbf0
+; add a move that has been used once by the player
+; added in order of use
+ ds NUM_MOVES
+
+wEnemyAISwitchScore:: db ; cbf4
wEnemySwitchMonParam:: db ; cbf5
wEnemySwitchMonIndex:: db ; cbf6
wcbf7:: ds 1 ; cbf7
@@ -1859,7 +1863,7 @@ wEnemyRageCounter:: db ; cc0a
wcc0b:: ds 1 ; cc0b
wcc0c:: ds 1 ; cc0c
wcc0d:: ds 1 ; cc0d
-wcc0e:: ds 1 ; cc0e
+wPlayerWrapCount:: db ; cc0e
wEnemyWrapCount:: db ; cc0f
wcc10:: ds 1 ; cc10
wcc11:: ds 1 ; cc11