mirror of
https://github.com/thornAvery/jep-hack.git
synced 2025-11-14 00:56:40 +13:00
This adds Rock Climb functionality to Strong Arm and Dive functionality to Water Sport, as discussed in the server. HMs have been added, but we need 16bit Items to add Wind Ride, and I haven't finished their functionality.
The Rock Climb tile is a bit terrible, it's not easy to notice. Maybe change so that it works well with yellow or another colour?
This does not build due to issues with effect_commands.asm, but since Zeta is meant to be working on the mapping and Water Sport anyway, it seems to be up his alley.
I ported over much of the underwater assets Rangi was using as they looked very pretty. I imagine it'll be fun to utilise going forward. May as well, right?
I shall now lay down in a dark room.
Review: c21561ea71 (diff-5508f3b794fc68821ba35e94b6a293b2aaaa16c02a1b34fac70d03fd2f74c4b2R113)
3331 lines
54 KiB
NASM
3331 lines
54 KiB
NASM
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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, NUM_MOVES + 1
|
|
ld c, 0
|
|
.checkmove2
|
|
dec b
|
|
jr z, .movesdone
|
|
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .movesdone
|
|
|
|
call AIGetEnemyMove
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
cp d
|
|
jr z, .checkmove2
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr nz, .damaging
|
|
jr .checkmove2
|
|
|
|
.damaging
|
|
ld c, a
|
|
.movesdone
|
|
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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, wEnemyAIMoveScores
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, AI_Smart_EffectHandlers
|
|
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
|
|
|
|
AI_Smart_EffectHandlers:
|
|
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
|
|
dbw EFFECT_SURF, AI_Smart_Surf
|
|
dbw EFFECT_WHIRLPOOL, AI_Smart_Whirlpool
|
|
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, .encourage
|
|
|
|
ld b, EFFECT_NIGHTMARE
|
|
call AIHasMoveEffect
|
|
ret nc
|
|
|
|
.encourage
|
|
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, .discourage
|
|
|
|
; 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
|
|
|
|
.discourage
|
|
call Random
|
|
cp 39 percent + 1
|
|
ret c
|
|
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_LockOn:
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_LOCK_ON, a
|
|
jr nz, .player_locked_on
|
|
|
|
push hl
|
|
call AICheckEnemyQuarterHP
|
|
jr nc, .discourage
|
|
|
|
call AICheckEnemyHalfHP
|
|
jr c, .skip_speed_check
|
|
|
|
call AICompareSpeed
|
|
jr nc, .discourage
|
|
|
|
.skip_speed_check
|
|
ld a, [wPlayerEvaLevel]
|
|
cp BASE_STAT_LEVEL + 3
|
|
jr nc, .maybe_encourage
|
|
cp BASE_STAT_LEVEL + 1
|
|
jr nc, .do_nothing
|
|
|
|
ld a, [wEnemyAccLevel]
|
|
cp BASE_STAT_LEVEL - 2
|
|
jr c, .maybe_encourage
|
|
cp BASE_STAT_LEVEL
|
|
jr c, .do_nothing
|
|
|
|
ld hl, wEnemyMonMoves
|
|
ld c, NUM_MOVES + 1
|
|
.checkmove
|
|
dec c
|
|
jr z, .discourage
|
|
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .discourage
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_ACC]
|
|
cp 71 percent - 1
|
|
jr nc, .checkmove
|
|
|
|
ld a, 1
|
|
ldh [hBattleTurn], a
|
|
|
|
push hl
|
|
push bc
|
|
farcall BattleCheckTypeMatchup
|
|
ld a, [wTypeMatchup]
|
|
cp EFFECTIVE
|
|
pop bc
|
|
pop hl
|
|
jr c, .checkmove
|
|
|
|
.do_nothing
|
|
pop hl
|
|
ret
|
|
|
|
.discourage
|
|
pop hl
|
|
inc [hl]
|
|
ret
|
|
|
|
.maybe_encourage
|
|
pop hl
|
|
call AI_50_50
|
|
ret c
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.player_locked_on
|
|
push hl
|
|
ld hl, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld c, NUM_MOVES + 1
|
|
|
|
.checkmove2
|
|
inc hl
|
|
dec c
|
|
jr z, .dismiss
|
|
|
|
ld a, [de]
|
|
and a
|
|
jr z, .dismiss
|
|
|
|
inc de
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_ACC]
|
|
cp 71 percent - 1
|
|
jr nc, .checkmove2
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
jr .checkmove2
|
|
|
|
.dismiss
|
|
pop hl
|
|
jp AIDiscourageMove
|
|
|
|
AI_Smart_Selfdestruct:
|
|
; Selfdestruct, Explosion
|
|
|
|
; Unless this is the enemy's last Pokemon...
|
|
push hl
|
|
farcall FindAliveEnemyMons
|
|
pop hl
|
|
jr nc, .notlastmon
|
|
|
|
; ...greatly discourage this move unless this is the player's last Pokemon too.
|
|
push hl
|
|
call AICheckLastPlayerMon
|
|
pop hl
|
|
jr nz, .discourage
|
|
|
|
.notlastmon
|
|
; Greatly discourage this move if enemy's HP is above 50%.
|
|
call AICheckEnemyHalfHP
|
|
jr c, .discourage
|
|
|
|
; 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 8 percent
|
|
ret c
|
|
|
|
.discourage
|
|
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 MAX_STAT_LEVEL
|
|
jp nc, AIDiscourageMove
|
|
|
|
; If enemy's HP is full...
|
|
call AICheckEnemyMaxHP
|
|
jr nc, .hp_mismatch_1
|
|
|
|
; ...greatly encourage this move if player is badly poisoned.
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .greatly_encourage
|
|
|
|
; ...70% chance to greatly encourage this move if player is not badly poisoned.
|
|
call Random
|
|
cp 70 percent
|
|
jr nc, .not_encouraged
|
|
|
|
.greatly_encourage
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.hp_mismatch_1
|
|
|
|
; Greatly discourage this move if enemy's HP is below 25%.
|
|
call AICheckEnemyQuarterHP
|
|
jr nc, .hp_mismatch_2
|
|
|
|
; If enemy's HP is above 25% but not full, 4% chance to greatly encourage this move.
|
|
call Random
|
|
cp 4 percent
|
|
jr c, .greatly_encourage
|
|
|
|
; If enemy's HP is between 25% and 50%,...
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .hp_mismatch_3
|
|
|
|
; If enemy's HP is above 50% but not full, 20% chance to greatly encourage this move.
|
|
call AI_80_20
|
|
jr c, .greatly_encourage
|
|
jr .not_encouraged
|
|
|
|
.hp_mismatch_3
|
|
; ...50% chance to greatly discourage this move.
|
|
call AI_50_50
|
|
jr c, .not_encouraged
|
|
|
|
.hp_mismatch_2
|
|
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.
|
|
.not_encouraged
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .maybe_greatly_encourage
|
|
|
|
ld a, [wPlayerSubStatus4]
|
|
bit SUBSTATUS_LEECH_SEED, a
|
|
jr nz, .maybe_encourage
|
|
|
|
; 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, .discourage
|
|
|
|
; Greatly encourage this move if the player is in the middle of Fury Cutter or Rollout.
|
|
ld a, [wPlayerFuryCutterCount]
|
|
and a
|
|
jr nz, .greatly_encourage
|
|
|
|
ld a, [wPlayerSubStatus1]
|
|
bit SUBSTATUS_ROLLOUT, a
|
|
jr nz, .greatly_encourage
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
; Player is badly poisoned.
|
|
; 70% chance to greatly encourage this move.
|
|
; This would counter any previous discouragement.
|
|
.maybe_greatly_encourage
|
|
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.
|
|
.maybe_encourage
|
|
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 BASE_STAT_LEVEL - 2
|
|
jr c, .encourage
|
|
|
|
; ...or player's evasion level has been raised three or more stages.
|
|
ld a, [wPlayerEvaLevel]
|
|
cp BASE_STAT_LEVEL + 3
|
|
ret c
|
|
|
|
.encourage
|
|
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, .usedmove
|
|
|
|
; ...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...
|
|
.usedmove
|
|
push hl
|
|
ld hl, UsefulMoves
|
|
call AI_CheckMoveInList
|
|
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, .hp_mismatch_1
|
|
|
|
; ...and enemy's HP is above 50%...
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .hp_mismatch_1
|
|
|
|
; ...greatly encourage this move if player is badly poisoned.
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .greatly_encourage
|
|
|
|
; ...70% chance to greatly encourage this move if player is not badly poisoned.
|
|
call Random
|
|
cp 70 percent
|
|
jr nc, .not_encouraged
|
|
|
|
.greatly_encourage
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.hp_mismatch_1
|
|
|
|
; Greatly discourage this move if player's HP is below 25%.
|
|
call AICheckPlayerQuarterHP
|
|
jr nc, .hp_mismatch_2
|
|
|
|
; If player's HP is above 25% but not full, 4% chance to greatly encourage this move.
|
|
call Random
|
|
cp 4 percent
|
|
jr c, .greatly_encourage
|
|
|
|
; If player's HP is between 25% and 50%,...
|
|
call AICheckPlayerHalfHP
|
|
jr nc, .hp_mismatch_3
|
|
|
|
; If player's HP is above 50% but not full, 20% chance to greatly encourage this move.
|
|
call AI_80_20
|
|
jr c, .greatly_encourage
|
|
jr .not_encouraged
|
|
|
|
; ...50% chance to greatly discourage this move.
|
|
.hp_mismatch_3
|
|
call AI_50_50
|
|
jr c, .not_encouraged
|
|
|
|
.hp_mismatch_2
|
|
inc [hl]
|
|
inc [hl]
|
|
|
|
; We only end up here if the move has not been already encouraged.
|
|
.not_encouraged
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .maybe_greatly_encourage
|
|
|
|
ld a, [wPlayerSubStatus4]
|
|
bit SUBSTATUS_LEECH_SEED, a
|
|
jr nz, .encourage
|
|
|
|
; 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, .discourage
|
|
|
|
; Greatly encourage this move if the player is in the middle of Fury Cutter or Rollout.
|
|
ld a, [wPlayerFuryCutterCount]
|
|
and a
|
|
jr nz, .greatly_encourage
|
|
|
|
ld a, [wPlayerSubStatus1]
|
|
bit SUBSTATUS_ROLLOUT, a
|
|
jr nz, .greatly_encourage
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
; Player is badly poisoned.
|
|
; 70% chance to greatly encourage this move.
|
|
; This would counter any previous discouragement.
|
|
.maybe_greatly_encourage
|
|
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.
|
|
.encourage
|
|
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, NUM_LEVEL_STATS
|
|
.enemystatsloop
|
|
dec c
|
|
jr z, .enemystatsdone
|
|
ld a, [hli]
|
|
cp BASE_STAT_LEVEL - 2
|
|
jr c, .encourage
|
|
jr .enemystatsloop
|
|
|
|
; 85% chance to encourage this move if any of player's stat levels is higher than +2.
|
|
.enemystatsdone
|
|
ld hl, wPlayerAtkLevel
|
|
ld c, NUM_LEVEL_STATS
|
|
.playerstatsloop
|
|
dec c
|
|
jr z, .discourage
|
|
ld a, [hli]
|
|
cp BASE_STAT_LEVEL + 3
|
|
jr c, .playerstatsloop
|
|
|
|
.encourage
|
|
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.
|
|
.discourage
|
|
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 BASE_AI_SWITCH_SCORE
|
|
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, .encourage
|
|
call AICheckEnemyHalfHP
|
|
ret nc
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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, .discourage
|
|
|
|
; 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, .encourage
|
|
|
|
ld a, [wPlayerSubStatus1]
|
|
and 1 << SUBSTATUS_IN_LOVE | 1 << SUBSTATUS_ROLLOUT | 1 << SUBSTATUS_IDENTIFIED | 1 << SUBSTATUS_NIGHTMARE
|
|
jr nz, .encourage
|
|
|
|
; Else, 50% chance to greatly encourage this move if it's the player's Pokemon first turn.
|
|
ld a, [wPlayerTurnsTaken]
|
|
and a
|
|
jr z, .encourage
|
|
|
|
; 50% chance to discourage this move otherwise.
|
|
.discourage
|
|
call AI_50_50
|
|
ret c
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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, .no_perish_count
|
|
|
|
ld a, [wEnemyPerishCount]
|
|
cp 3
|
|
jr c, .discourage
|
|
|
|
.no_perish_count
|
|
push hl
|
|
ld hl, wPlayerUsedMoves
|
|
ld c, NUM_MOVES
|
|
|
|
.checkmove
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .movesdone
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_EFFECT]
|
|
cp EFFECT_PROTECT
|
|
jr z, .dismiss
|
|
dec c
|
|
jr nz, .checkmove
|
|
|
|
.movesdone
|
|
pop hl
|
|
ld a, [wEnemySubStatus3]
|
|
bit SUBSTATUS_CONFUSED, a
|
|
jr nz, .maybe_discourage
|
|
|
|
call AICheckEnemyHalfHP
|
|
ret c
|
|
|
|
.maybe_discourage
|
|
call Random
|
|
cp 79 percent - 1
|
|
ret c
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
.dismiss
|
|
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, .skipdiscourage
|
|
inc [hl]
|
|
|
|
.skipdiscourage
|
|
; 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, .discourage
|
|
|
|
; Discourage this move if enemy's special defense level is higher than +3.
|
|
ld a, [wEnemySDefLevel]
|
|
cp BASE_STAT_LEVEL + 4
|
|
jr nc, .discourage
|
|
|
|
; 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 BASE_STAT_LEVEL + 2
|
|
ret nc
|
|
|
|
ld a, [wBattleMonType1]
|
|
cp SPECIAL
|
|
jr nc, .encourage
|
|
ld a, [wBattleMonType2]
|
|
cp SPECIAL
|
|
ret c
|
|
|
|
.encourage
|
|
call AI_80_20
|
|
ret c
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Fly:
|
|
; Fly, Dig, Dive, Bounce
|
|
|
|
; 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
|
|
jr nz, .player_hidden
|
|
ld a, [wPlayerSubStatus4]
|
|
and 1 << SUBSTATUS_UNDERWATER
|
|
ret z
|
|
|
|
.player_hidden
|
|
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, .discourage
|
|
|
|
; 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
|
|
|
|
.discourage
|
|
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]
|
|
push hl
|
|
call GetMoveIDFromIndex
|
|
ld a, h
|
|
if HIGH(ICY_WIND)
|
|
cp HIGH(ICY_WIND)
|
|
else
|
|
and a
|
|
endc
|
|
ld a, l
|
|
pop hl
|
|
ret nz
|
|
cp LOW(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, .discourage
|
|
|
|
; 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
|
|
|
|
.discourage
|
|
; If enemy's HP is above 50%, discourage this move at random
|
|
call Random
|
|
cp 16 percent
|
|
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, .notbuilding
|
|
|
|
; If enemy's Rage is building, 50% chance to encourage this move.
|
|
call AI_50_50
|
|
jr c, .skipencourage
|
|
|
|
dec [hl]
|
|
|
|
; Encourage this move based on Rage's counter.
|
|
.skipencourage
|
|
ld a, [wEnemyRageCounter]
|
|
cp 2
|
|
ret c
|
|
dec [hl]
|
|
ld a, [wEnemyRageCounter]
|
|
cp 3
|
|
ret c
|
|
dec [hl]
|
|
ret
|
|
|
|
.notbuilding
|
|
; If enemy's Rage is not building, discourage this move if enemy's HP is below 50%.
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .discourage
|
|
|
|
; 20% chance to encourage this move otherwise.
|
|
call AI_80_20
|
|
ret nc
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Mimic:
|
|
; Discourage this move if the player did not use any move last turn.
|
|
ld a, [wLastPlayerCounterMove]
|
|
and a
|
|
jr z, .dismiss
|
|
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .discourage
|
|
|
|
push hl
|
|
ld a, [wLastPlayerCounterMove]
|
|
call AIGetEnemyMove
|
|
|
|
ld a, 1
|
|
ldh [hBattleTurn], a
|
|
callfar BattleCheckTypeMatchup
|
|
|
|
ld a, [wTypeMatchup]
|
|
cp EFFECTIVE
|
|
pop hl
|
|
jr c, .discourage
|
|
jr z, .skip_encourage
|
|
|
|
call AI_50_50
|
|
jr c, .skip_encourage
|
|
|
|
dec [hl]
|
|
|
|
.skip_encourage
|
|
ld a, [wLastPlayerCounterMove]
|
|
push hl
|
|
ld hl, UsefulMoves
|
|
call AI_CheckMoveInList
|
|
|
|
pop hl
|
|
ret nc
|
|
call AI_50_50
|
|
ret c
|
|
dec [hl]
|
|
ret
|
|
|
|
.dismiss
|
|
; Dismiss this move if the enemy is faster than the player.
|
|
call AICompareSpeed
|
|
jp c, AIDiscourageMove
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Counter:
|
|
push hl
|
|
ld hl, wPlayerUsedMoves
|
|
ld c, NUM_MOVES
|
|
ld b, 0
|
|
|
|
.playermoveloop
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .skipmove
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr z, .skipmove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
cp SPECIAL
|
|
jr nc, .skipmove
|
|
|
|
inc b
|
|
|
|
.skipmove
|
|
dec c
|
|
jr nz, .playermoveloop
|
|
|
|
pop hl
|
|
ld a, b
|
|
and a
|
|
jr z, .discourage
|
|
|
|
cp 3
|
|
jr nc, .encourage
|
|
|
|
ld a, [wLastPlayerCounterMove]
|
|
and a
|
|
jr z, .done
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr z, .done
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
cp SPECIAL
|
|
jr nc, .done
|
|
|
|
.encourage
|
|
call Random
|
|
cp 39 percent + 1
|
|
jr c, .done
|
|
|
|
dec [hl]
|
|
|
|
.done
|
|
ret
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Encore:
|
|
call AICompareSpeed
|
|
jr nc, .discourage
|
|
|
|
ld a, [wLastPlayerMove]
|
|
and a
|
|
jp z, AIDiscourageMove
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr z, .weakmove
|
|
|
|
push hl
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
ld hl, wEnemyMonType1
|
|
predef CheckTypeMatchup
|
|
|
|
pop hl
|
|
ld a, [wTypeMatchup]
|
|
cp EFFECTIVE
|
|
jr nc, .weakmove
|
|
|
|
and a
|
|
ret nz
|
|
jr .encourage
|
|
|
|
.weakmove
|
|
push hl
|
|
ld a, [wLastPlayerCounterMove]
|
|
ld hl, EncoreMoves
|
|
call AI_CheckMoveInList
|
|
pop hl
|
|
jr nc, .discourage
|
|
|
|
.encourage
|
|
call Random
|
|
cp 28 percent - 1
|
|
ret c
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
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 SLP_MASK
|
|
cp 1
|
|
jr z, .discourage
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
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, .usedmove
|
|
|
|
call AICompareSpeed
|
|
jp c, AIDiscourageMove
|
|
|
|
call AI_50_50
|
|
ret c
|
|
inc [hl]
|
|
ret
|
|
|
|
.usedmove
|
|
push hl
|
|
ld b, a
|
|
ld c, NUM_MOVES
|
|
ld hl, wBattleMonMoves
|
|
ld de, wBattleMonPP
|
|
|
|
.moveloop
|
|
ld a, [hli]
|
|
cp b
|
|
jr z, .foundmove
|
|
|
|
inc de
|
|
dec c
|
|
jr nz, .moveloop
|
|
|
|
pop hl
|
|
ret
|
|
|
|
.foundmove
|
|
pop hl
|
|
ld a, [de]
|
|
cp 6
|
|
jr c, .encourage
|
|
cp 15
|
|
jr nc, .discourage
|
|
|
|
call Random
|
|
cp 39 percent + 1
|
|
ret nc
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
call Random
|
|
cp 39 percent + 1
|
|
ret c
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.dismiss ; unreferenced
|
|
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_MASK
|
|
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, underwater, or underground.
|
|
ld a, [wPlayerSubStatus3]
|
|
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
|
|
jp nz, AIDiscourageMove
|
|
ld a, [wPlayerSubStatus4]
|
|
and 1 << SUBSTATUS_UNDERWATER
|
|
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_Surf:
|
|
AI_Smart_Whirlpool:
|
|
; Greatly encourage this move if the player is underwater and the enemy is faster.
|
|
ld a, [wLastPlayerCounterMove]
|
|
cp DIVE
|
|
ret nz
|
|
ld a, [wPlayerSubStatus4]
|
|
bit SUBSTATUS_UNDERWATER, a
|
|
jr z, .could_dive
|
|
call AICompareSpeed
|
|
ret nc
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
.could_dive
|
|
; Try to predict if the player will use Dive 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_Thief:
|
|
; Don't use Thief unless it's the only move available.
|
|
|
|
ld a, [hl]
|
|
add $1e
|
|
ld [hl], a
|
|
ret
|
|
|
|
AI_Smart_Conversion2:
|
|
; BUG: "Smart" AI discourages Conversion2 after the first turn (see docs/bugs_and_glitches.md)
|
|
ld a, [wLastPlayerMove]
|
|
and a
|
|
jr nz, .discourage
|
|
|
|
push hl
|
|
ld l, a
|
|
ld a, MOVE_TYPE
|
|
call GetMoveAttribute
|
|
ld [wPlayerMoveStruct + MOVE_TYPE], a
|
|
|
|
xor a
|
|
ldh [hBattleTurn], a
|
|
|
|
callfar BattleCheckTypeMatchup
|
|
|
|
ld a, [wTypeMatchup]
|
|
cp EFFECTIVE
|
|
pop hl
|
|
jr c, .discourage
|
|
ret z
|
|
|
|
call AI_50_50
|
|
ret c
|
|
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
call Random
|
|
cp 10 percent
|
|
ret c
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Disable:
|
|
call AICompareSpeed
|
|
jr nc, .discourage
|
|
|
|
push hl
|
|
ld a, [wLastPlayerCounterMove]
|
|
ld hl, UsefulMoves
|
|
call AI_CheckMoveInList
|
|
|
|
pop hl
|
|
jr nc, .notencourage
|
|
|
|
call Random
|
|
cp 39 percent + 1
|
|
ret c
|
|
dec [hl]
|
|
ret
|
|
|
|
.notencourage
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
ret nz
|
|
|
|
.discourage
|
|
call Random
|
|
cp 8 percent
|
|
ret c
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_MeanLook:
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .discourage
|
|
|
|
push hl
|
|
call AICheckLastPlayerMon
|
|
pop hl
|
|
jp z, AIDiscourageMove
|
|
|
|
; 80% chance to greatly encourage this move if the enemy is badly poisoned.
|
|
; BUG: "Smart" AI encourages Mean Look if its own Pokémon is badly poisoned (see docs/bugs_and_glitches.md)
|
|
ld a, [wEnemySubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .encourage
|
|
|
|
; 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, .encourage
|
|
|
|
; Otherwise, discourage this move unless the player only has not very effective moves against the enemy.
|
|
push hl
|
|
callfar CheckPlayerMoveTypeMatchups
|
|
ld a, [wEnemyAISwitchScore]
|
|
cp BASE_AI_SWITCH_SCORE + 1 ; not very effective
|
|
pop hl
|
|
ret nc
|
|
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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, .skip
|
|
|
|
ld a, [hli]
|
|
or [hl]
|
|
ret nz
|
|
dec hl
|
|
|
|
.skip
|
|
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, .ghost_curse
|
|
ld a, [wEnemyMonType2]
|
|
cp GHOST
|
|
jr z, .ghost_curse
|
|
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .encourage
|
|
|
|
ld a, [wEnemyAtkLevel]
|
|
cp BASE_STAT_LEVEL + 4
|
|
jr nc, .encourage
|
|
cp BASE_STAT_LEVEL + 2
|
|
ret nc
|
|
|
|
ld a, [wBattleMonType1]
|
|
cp GHOST
|
|
jr z, .greatly_encourage
|
|
cp SPECIAL
|
|
ret nc
|
|
ld a, [wBattleMonType2]
|
|
cp SPECIAL
|
|
ret nc
|
|
call AI_80_20
|
|
ret c
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.approve
|
|
inc [hl]
|
|
inc [hl]
|
|
.greatly_encourage
|
|
inc [hl]
|
|
.encourage
|
|
inc [hl]
|
|
ret
|
|
|
|
.ghost_curse
|
|
ld a, [wPlayerSubStatus1]
|
|
bit SUBSTATUS_CURSE, a
|
|
jp nz, AIDiscourageMove
|
|
|
|
push hl
|
|
farcall FindAliveEnemyMons
|
|
pop hl
|
|
jr nc, .notlastmon
|
|
|
|
push hl
|
|
call AICheckLastPlayerMon
|
|
pop hl
|
|
jr nz, .approve
|
|
|
|
jr .ghost_continue
|
|
|
|
.notlastmon
|
|
push hl
|
|
call AICheckLastPlayerMon
|
|
pop hl
|
|
jr z, .maybe_greatly_encourage
|
|
|
|
.ghost_continue
|
|
call AICheckEnemyQuarterHP
|
|
jp nc, .approve
|
|
|
|
call AICheckEnemyHalfHP
|
|
jr nc, .greatly_encourage
|
|
|
|
call AICheckEnemyMaxHP
|
|
ret nc
|
|
|
|
ld a, [wPlayerTurnsTaken]
|
|
and a
|
|
ret nz
|
|
|
|
.maybe_greatly_encourage
|
|
call AI_50_50
|
|
ret c
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
AI_Smart_Protect:
|
|
; Greatly discourage this move if the enemy already used Protect.
|
|
ld a, [wEnemyProtectCount]
|
|
and a
|
|
jr nz, .greatly_discourage
|
|
|
|
; Discourage this move if the player is locked on.
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_LOCK_ON, a
|
|
jr nz, .discourage
|
|
|
|
; Encourage this move if the player's Fury Cutter is boosted enough.
|
|
ld a, [wPlayerFuryCutterCount]
|
|
cp 3
|
|
jr nc, .encourage
|
|
|
|
; Encourage this move if the player has charged a two-turn move.
|
|
ld a, [wPlayerSubStatus3]
|
|
bit SUBSTATUS_CHARGED, a
|
|
jr nz, .encourage
|
|
|
|
; Encourage this move if the player is affected by Toxic, Leech Seed, or Curse.
|
|
ld a, [wPlayerSubStatus5]
|
|
bit SUBSTATUS_TOXIC, a
|
|
jr nz, .encourage
|
|
ld a, [wPlayerSubStatus4]
|
|
bit SUBSTATUS_LEECH_SEED, a
|
|
jr nz, .encourage
|
|
ld a, [wPlayerSubStatus1]
|
|
bit SUBSTATUS_CURSE, a
|
|
jr nz, .encourage
|
|
|
|
; Discourage this move if the player's Rollout count is not boosted enough.
|
|
bit SUBSTATUS_ROLLOUT, a
|
|
jr z, .discourage
|
|
ld a, [wPlayerRolloutCount]
|
|
cp 3
|
|
jr c, .discourage
|
|
|
|
; 80% chance to encourage this move otherwise.
|
|
.encourage
|
|
call AI_80_20
|
|
ret c
|
|
|
|
dec [hl]
|
|
ret
|
|
|
|
.greatly_discourage
|
|
inc [hl]
|
|
|
|
.discourage
|
|
call Random
|
|
cp 8 percent
|
|
ret c
|
|
|
|
inc [hl]
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_Foresight:
|
|
; 60% chance to encourage this move if the enemy's accuracy is sharply lowered.
|
|
ld a, [wEnemyAccLevel]
|
|
cp BASE_STAT_LEVEL - 2
|
|
jr c, .encourage
|
|
|
|
; 60% chance to encourage this move if the player's evasion is sharply raised.
|
|
ld a, [wPlayerEvaLevel]
|
|
cp BASE_STAT_LEVEL + 3
|
|
jr nc, .encourage
|
|
|
|
; 60% chance to encourage this move if the player is a Ghost type.
|
|
ld a, [wBattleMonType1]
|
|
cp GHOST
|
|
jr z, .encourage
|
|
ld a, [wBattleMonType2]
|
|
cp GHOST
|
|
jr z, .encourage
|
|
|
|
; 92% chance to discourage this move otherwise.
|
|
call Random
|
|
cp 8 percent
|
|
ret c
|
|
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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 BASE_AI_SWITCH_SCORE
|
|
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, .greatly_discourage
|
|
|
|
ld a, [wBattleMonType2]
|
|
push hl
|
|
ld hl, .SandstormImmuneTypes
|
|
ld de, 1
|
|
call IsInArray
|
|
pop hl
|
|
jr c, .greatly_discourage
|
|
|
|
; Discourage this move if player's HP is below 50%.
|
|
call AICheckPlayerHalfHP
|
|
jr nc, .discourage
|
|
|
|
; 50% chance to encourage this move otherwise.
|
|
call AI_50_50
|
|
ret c
|
|
|
|
dec [hl]
|
|
ret
|
|
|
|
.greatly_discourage
|
|
inc [hl]
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
.SandstormImmuneTypes:
|
|
db ROCK
|
|
db GROUND
|
|
db STEEL
|
|
db -1 ; end
|
|
|
|
AI_Smart_Endure:
|
|
; Greatly discourage this move if the enemy already used Protect.
|
|
ld a, [wEnemyProtectCount]
|
|
and a
|
|
jr nz, .greatly_discourage
|
|
|
|
; Greatly discourage this move if the enemy's HP is full.
|
|
call AICheckEnemyMaxHP
|
|
jr c, .greatly_discourage
|
|
|
|
; Discourage this move if the enemy's HP is at least 25%.
|
|
call AICheckEnemyQuarterHP
|
|
jr c, .discourage
|
|
|
|
; If the enemy has Reversal...
|
|
ld b, EFFECT_REVERSAL
|
|
call AIHasMoveEffect
|
|
jr nc, .no_reversal
|
|
|
|
; ...80% chance to greatly encourage this move.
|
|
call AI_80_20
|
|
ret c
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.no_reversal
|
|
; If the enemy is not locked on, do nothing.
|
|
ld a, [wEnemySubStatus5]
|
|
bit SUBSTATUS_LOCK_ON, a
|
|
ret z
|
|
|
|
; 50% chance to greatly encourage this move.
|
|
call AI_50_50
|
|
ret c
|
|
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.greatly_discourage
|
|
inc [hl]
|
|
.discourage
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_FuryCutter:
|
|
; Encourage this move based on Fury Cutter's count.
|
|
|
|
ld a, [wEnemyFuryCutterCount]
|
|
and a
|
|
jr z, AI_Smart_Rollout
|
|
dec [hl]
|
|
|
|
cp 2
|
|
jr c, AI_Smart_Rollout
|
|
dec [hl]
|
|
dec [hl]
|
|
|
|
cp 3
|
|
jr c, AI_Smart_Rollout
|
|
dec [hl]
|
|
dec [hl]
|
|
dec [hl]
|
|
|
|
; 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, .maybe_discourage
|
|
|
|
ld a, [wEnemySubStatus3]
|
|
bit SUBSTATUS_CONFUSED, a
|
|
jr nz, .maybe_discourage
|
|
|
|
ld a, [wEnemyMonStatus]
|
|
bit PAR, a
|
|
jr nz, .maybe_discourage
|
|
|
|
; 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, .maybe_discourage
|
|
|
|
ld a, [wEnemyAccLevel]
|
|
cp BASE_STAT_LEVEL
|
|
jr c, .maybe_discourage
|
|
ld a, [wPlayerEvaLevel]
|
|
cp BASE_STAT_LEVEL + 1
|
|
jr nc, .maybe_discourage
|
|
|
|
; 80% chance to greatly encourage this move otherwise.
|
|
call Random
|
|
cp 79 percent - 1
|
|
ret nc
|
|
dec [hl]
|
|
dec [hl]
|
|
ret
|
|
|
|
.maybe_discourage
|
|
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]
|
|
push hl
|
|
call GetMoveIndexFromID
|
|
ld a, h
|
|
if HIGH(DIG)
|
|
cp HIGH(DIG)
|
|
else
|
|
and a
|
|
endc
|
|
ld a, l
|
|
pop hl
|
|
ret nz
|
|
cp LOW(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 BASE_AI_SWITCH_SCORE
|
|
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, .encourage
|
|
call AI_80_20
|
|
ret c
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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, .encourage
|
|
|
|
ld a, [wEnemySubStatus4]
|
|
bit SUBSTATUS_LEECH_SEED, a
|
|
jr nz, .encourage
|
|
|
|
ld a, [wEnemyScreens]
|
|
bit SCREENS_SPIKES, a
|
|
ret z
|
|
|
|
.encourage
|
|
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 BASE_STAT_LEVEL + 3
|
|
jr nc, .discourage
|
|
|
|
call AICheckEnemyMaxHP
|
|
ret c
|
|
|
|
inc [hl]
|
|
|
|
call AICheckEnemyHalfHP
|
|
ret c
|
|
|
|
.discourage
|
|
ld a, [hl]
|
|
add 5
|
|
ld [hl], a
|
|
ret
|
|
|
|
AI_Smart_PsychUp:
|
|
push hl
|
|
ld hl, wEnemyAtkLevel
|
|
ld b, NUM_LEVEL_STATS
|
|
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.
|
|
.enemy_loop
|
|
ld a, [hli]
|
|
sub BASE_STAT_LEVEL
|
|
add c
|
|
ld c, a
|
|
dec b
|
|
jr nz, .enemy_loop
|
|
|
|
; 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, NUM_LEVEL_STATS
|
|
ld d, 100
|
|
|
|
.player_loop
|
|
ld a, [hli]
|
|
sub BASE_STAT_LEVEL
|
|
add d
|
|
ld d, a
|
|
dec b
|
|
jr nz, .player_loop
|
|
|
|
; 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, .discourage
|
|
|
|
; Else, 80% chance to encourage this move unless player's accuracy level is lower than -1...
|
|
ld a, [wPlayerAccLevel]
|
|
cp BASE_STAT_LEVEL - 1
|
|
ret c
|
|
|
|
; ...or enemy's evasion level is higher than +0.
|
|
ld a, [wEnemyEvaLevel]
|
|
cp BASE_STAT_LEVEL + 1
|
|
ret nc
|
|
|
|
call AI_80_20
|
|
ret c
|
|
|
|
dec [hl]
|
|
ret
|
|
|
|
.discourage
|
|
inc [hl]
|
|
inc [hl]
|
|
ret
|
|
|
|
AI_Smart_MirrorCoat:
|
|
push hl
|
|
ld hl, wPlayerUsedMoves
|
|
ld c, NUM_MOVES
|
|
ld b, 0
|
|
|
|
.playermoveloop
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .skipmove
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr z, .skipmove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
cp SPECIAL
|
|
jr c, .skipmove
|
|
|
|
inc b
|
|
|
|
.skipmove
|
|
dec c
|
|
jr nz, .playermoveloop
|
|
|
|
pop hl
|
|
ld a, b
|
|
and a
|
|
jr z, .discourage
|
|
|
|
cp 3
|
|
jr nc, .encourage
|
|
|
|
ld a, [wLastPlayerCounterMove]
|
|
and a
|
|
jr z, .done
|
|
|
|
call AIGetEnemyMove
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_POWER]
|
|
and a
|
|
jr z, .done
|
|
|
|
ld a, [wEnemyMoveStruct + MOVE_TYPE]
|
|
cp SPECIAL
|
|
jr c, .done
|
|
|
|
.encourage
|
|
call Random
|
|
cp 39 percent + 1
|
|
jr c, .done
|
|
dec [hl]
|
|
|
|
.done
|
|
ret
|
|
|
|
.discourage
|
|
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]
|
|
push hl
|
|
call GetMoveIndexFromID
|
|
ld a, h
|
|
if HIGH(FLY)
|
|
cp HIGH(FLY)
|
|
else
|
|
and a
|
|
endc
|
|
ld a, l
|
|
pop hl
|
|
ret nz
|
|
cp LOW(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, underwater, or underground, and slower than the enemy.
|
|
|
|
call AICompareSpeed
|
|
ret nc
|
|
|
|
ld a, [wPlayerSubStatus3]
|
|
and 1 << SUBSTATUS_FLYING | 1 << SUBSTATUS_UNDERGROUND
|
|
jr nz, .player_hidden
|
|
ld a, [wPlayerSubStatus4]
|
|
and 1 << SUBSTATUS_UNDERWATER
|
|
ret z
|
|
|
|
.player_hidden
|
|
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, .encourage
|
|
|
|
cp WEATHER_RAIN
|
|
ret nz
|
|
|
|
call Random
|
|
cp 10 percent
|
|
ret c
|
|
|
|
inc [hl]
|
|
inc [hl]
|
|
ret
|
|
|
|
.encourage
|
|
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, .not_max
|
|
|
|
inc hl
|
|
ld a, [de]
|
|
cp [hl]
|
|
jr nz, .not_max
|
|
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
scf
|
|
ret
|
|
|
|
.not_max
|
|
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, NUM_MOVES
|
|
|
|
.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 de
|
|
push bc
|
|
push hl
|
|
ld b, NUM_MOVES
|
|
ld de, wEnemyMonMoves
|
|
.loop
|
|
ld a, [de]
|
|
inc de
|
|
and a
|
|
jr z, .next
|
|
call GetMoveIndexFromID
|
|
ld a, h
|
|
ld c, l
|
|
pop hl
|
|
push hl
|
|
push bc
|
|
push de
|
|
ld b, a
|
|
ld de, 2
|
|
call IsInWordArray
|
|
pop de
|
|
pop bc
|
|
jr c, .done
|
|
.next
|
|
dec b
|
|
jr nz, .loop
|
|
.done
|
|
pop hl
|
|
pop bc
|
|
pop de
|
|
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, .lowhp
|
|
|
|
; 50% chance to discourage stall moves if enemy's HP is between 25% and 50%.
|
|
call AI_50_50
|
|
ret c
|
|
|
|
.lowhp
|
|
ld hl, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld c, NUM_MOVES + 1
|
|
.checkmove
|
|
inc hl
|
|
dec c
|
|
jr z, .done
|
|
|
|
ld a, [de]
|
|
inc de
|
|
and a
|
|
jr z, .done
|
|
|
|
push hl
|
|
push de
|
|
push bc
|
|
ld hl, StallMoves
|
|
call AI_CheckMoveInList
|
|
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
jr nc, .checkmove
|
|
|
|
inc [hl]
|
|
jr .checkmove
|
|
|
|
.done
|
|
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 NUM_MOVES + 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
|
|
ret z
|
|
|
|
; Discourage moves that do less damage unless they're reckless too.
|
|
ld hl, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, 0
|
|
.checkmove2
|
|
inc b
|
|
ld a, b
|
|
cp NUM_MOVES + 1
|
|
ret z
|
|
|
|
; 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
|
|
|
|
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, .notconstant
|
|
callfar BattleCommand_ConstantDamage
|
|
ret
|
|
|
|
.notconstant
|
|
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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld c, NUM_MOVES + 1
|
|
.loop
|
|
inc hl
|
|
dec c
|
|
ret z
|
|
|
|
ld a, [de]
|
|
inc de
|
|
and a
|
|
ret z
|
|
|
|
push hl
|
|
push de
|
|
push bc
|
|
ld hl, ResidualMoves
|
|
call AI_CheckMoveInList
|
|
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
jr nc, .loop
|
|
|
|
call Random
|
|
cp 90 percent + 1
|
|
ret nc
|
|
|
|
inc [hl]
|
|
jr .loop
|
|
|
|
INCLUDE "data/battle/ai/residual_moves.asm"
|
|
|
|
|
|
AI_Status:
|
|
; Dismiss status moves that don't affect the player.
|
|
|
|
ld hl, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld b, NUM_MOVES + 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, wEnemyAIMoveScores - 1
|
|
ld de, wEnemyMonMoves
|
|
ld c, NUM_MOVES + 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
|
|
|
|
ld de, wEnemyMoveStruct
|
|
call GetMoveData
|
|
|
|
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
|
|
|
|
AI_CheckMoveInList:
|
|
push hl
|
|
call GetMoveIndexFromID
|
|
ld b, h
|
|
ld c, l
|
|
pop hl
|
|
ld de, 2
|
|
jp IsInWordArray
|