summaryrefslogtreecommitdiff
path: root/engine/battle/e.asm
diff options
context:
space:
mode:
Diffstat (limited to 'engine/battle/e.asm')
-rwxr-xr-xengine/battle/e.asm1563
1 files changed, 1563 insertions, 0 deletions
diff --git a/engine/battle/e.asm b/engine/battle/e.asm
new file mode 100755
index 00000000..ada3071e
--- /dev/null
+++ b/engine/battle/e.asm
@@ -0,0 +1,1563 @@
+Func_39680: ; 39680 (e:5680)
+ ld a, [H_WHOSETURN] ; $fff3
+ and a
+ ld a, [$d060]
+ ld hl, $d026
+ jr z, .asm_39691
+ ld a, [$d065]
+ ld hl, $cff7
+.asm_39691
+ ld c, $4
+ ld b, a
+.asm_39694
+ srl b
+ call c, Func_3969f
+ inc hl
+ inc hl
+ dec c
+ ret z
+ jr .asm_39694
+
+Func_3969f: ; 3969f (e:569f)
+ ld a, [hl]
+ add a
+ ld [hld], a
+ ld a, [hl]
+ rl a
+ ld [hli], a
+ ret
+
+Func_396a7: ; 396a7 (e:56a7)
+ ld a, [H_WHOSETURN] ; $fff3
+ and a
+ ld a, [$d061]
+ ld hl, W_PLAYERMONATK
+ jr z, .asm_396b8
+ ld a, [$d066]
+ ld hl, W_ENEMYMONATTACK
+.asm_396b8
+ ld c, $4
+ ld b, a
+.asm_396bb
+ srl b
+ call c, Func_396c6
+ inc hl
+ inc hl
+ dec c
+ ret z
+ jr .asm_396bb
+
+Func_396c6: ; 396c6 (e:56c6)
+ ld a, [hl]
+ srl a
+ ld [hli], a
+ rr [hl]
+ or [hl]
+ jr nz, .asm_396d1
+ ld [hl], $1
+.asm_396d1
+ dec hl
+ ret
+
+_ScrollTrainerPicAfterBattle: ; 396d3 (e:56d3)
+; Load the enemy trainer's pic and scrolls it into
+; the screen from the right.
+ xor a
+ ld [W_ENEMYMONID], a
+ ld b, $1
+ call GoPAL_SET
+ callab _LoadTrainerPic
+ FuncCoord 19, 0 ; $c3b3
+ ld hl, Coord
+ ld c, $0
+.asm_396e9
+ inc c
+ ld a, c
+ cp $7
+ ret z
+ ld d, $0
+ push bc
+ push hl
+.asm_396f2
+ call Func_39707
+ inc hl
+ ld a, $7
+ add d
+ ld d, a
+ dec c
+ jr nz, .asm_396f2
+ ld c, $4
+ call DelayFrames
+ pop hl
+ pop bc
+ dec hl
+ jr .asm_396e9
+
+Func_39707: ; 39707 (e:5707)
+ push hl
+ push de
+ push bc
+ ld e, $7
+.asm_3970c
+ ld [hl], d
+ ld bc, $14
+ add hl, bc
+ inc d
+ dec e
+ jr nz, .asm_3970c
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; creates a set of moves that may be used and returns its address in hl
+; unused slots are filled with 0, all used slots may be chosen with equal probability
+AIEnemyTrainerChooseMoves: ; 39719 (e:5719)
+ ld a, $a
+ ld hl, $cee9 ; init temporary move selection array. Only the moves with the lowest numbers are chosen in the end
+ ld [hli], a ; move 1
+ ld [hli], a ; move 2
+ ld [hli], a ; move 3
+ ld [hl], a ; move 4
+ ld a, [W_ENEMYDISABLEDMOVE] ; forbid disabled move (if any)
+ swap a
+ and $f
+ jr z, .noMoveDisabled
+ ld hl, $cee9
+ dec a
+ ld c, a
+ ld b, $0
+ add hl, bc ; advance pointer to forbidden move
+ ld [hl], $50 ; forbid (highly discourage) disabled move
+.noMoveDisabled
+ ld hl, TrainerClassMoveChoiceModifications ; 589B
+ ld a, [W_TRAINERCLASS]
+ ld b, a
+.loopTrainerClasses
+ dec b
+ jr z, .readTrainerClassData
+.loopTrainerClassData
+ ld a, [hli]
+ and a
+ jr nz, .loopTrainerClassData
+ jr .loopTrainerClasses
+.readTrainerClassData
+ ld a, [hl]
+ and a
+ jp z, .useOriginalMoveSet
+ push hl
+.nextMoveChoiceModification
+ pop hl
+ ld a, [hli]
+ and a
+ jr z, .loopFindMinimumEntries
+ push hl
+ ld hl, AIMoveChoiceModificationFunctionPointers ; $57a3
+ dec a
+ add a
+ ld c, a
+ ld b, $0
+ add hl, bc ; skip to pointer
+ ld a, [hli] ; read pointer into hl
+ ld h, [hl]
+ ld l, a
+ ld de, .nextMoveChoiceModification ; set return address
+ push de
+ jp [hl] ; execute modification function
+.loopFindMinimumEntries ; all entries will be decremented sequentially until one of them is zero
+ ld hl, $cee9 ; temp move selection array
+ ld de, W_ENEMYMONMOVES ; enemy moves
+ ld c, $4
+.loopDecrementEntries
+ ld a, [de]
+ inc de
+ and a
+ jr z, .loopFindMinimumEntries
+ dec [hl]
+ jr z, .minimumEntriesFound
+ inc hl
+ dec c
+ jr z, .loopFindMinimumEntries
+ jr .loopDecrementEntries
+.minimumEntriesFound
+ ld a, c
+.loopUndoPartialIteration ; undo last (partial) loop iteration
+ inc [hl]
+ dec hl
+ inc a
+ cp $5
+ jr nz, .loopUndoPartialIteration
+ ld hl, $cee9 ; temp move selection array
+ ld de, W_ENEMYMONMOVES ; enemy moves
+ ld c, $4
+.filterMinimalEntries ; all minimal entries now have value 1. All other slots will be disabled (move set to 0)
+ ld a, [de]
+ and a
+ jr nz, .moveExisting ; 0x3978a $1
+ ld [hl], a
+.moveExisting
+ ld a, [hl]
+ dec a
+ jr z, .slotWithMinimalValue
+ xor a
+ ld [hli], a ; disable move slot
+ jr .next
+.slotWithMinimalValue
+ ld a, [de]
+ ld [hli], a ; enable move slot
+.next
+ inc de
+ dec c
+ jr nz, .filterMinimalEntries
+ ld hl, $cee9 ; use created temporary array as move set
+ ret
+.useOriginalMoveSet
+ ld hl, W_ENEMYMONMOVES ; use original move set
+ ret
+
+AIMoveChoiceModificationFunctionPointers: ; 397a3 (e:57a3)
+ dw AIMoveChoiceModification1
+ dw AIMoveChoiceModification2
+ dw AIMoveChoiceModification3
+ dw AIMoveChoiceModification4 ; unused, does nothing
+
+; discourages moves that cause no damage but only a status ailment if player's mon already has one
+AIMoveChoiceModification1: ; 397ab (e:57ab)
+ ld a, [W_PLAYERMONSTATUS]
+ and a
+ ret z ; return if no status ailment on player's mon
+ ld hl, $cee8 ; temp move selection array (-1 byte offest)
+ ld de, W_ENEMYMONMOVES ; enemy moves
+ ld b, $5
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ ld a, [W_ENEMYMOVEPOWER]
+ and a
+ jr nz, .nextMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ push hl
+ push de
+ push bc
+ ld hl, StatusAilmentMoveEffects
+ ld de, $0001
+ call IsInArray
+ pop bc
+ pop de
+ pop hl
+ jr nc, .nextMove
+ ld a, [hl]
+ add $5 ; discourage move
+ ld [hl], a
+ jr .nextMove
+
+StatusAilmentMoveEffects ; 57e2
+ db $01 ; some sleep effect?
+ db SLEEP_EFFECT
+ db POISON_EFFECT
+ db PARALYZE_EFFECT
+ db $FF
+
+; slightly encourage moves with specific effects
+AIMoveChoiceModification2: ; 397e7 (e:57e7)
+ ld a, [$ccd5]
+ cp $1
+ ret nz
+ ld hl, $cee8 ; temp move selection array (-1 byte offest)
+ ld de, W_ENEMYMONMOVES ; enemy moves
+ ld b, $5
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ cp ATTACK_UP1_EFFECT
+ jr c, .nextMove
+ cp BIDE_EFFECT
+ jr c, .preferMove
+ cp ATTACK_UP2_EFFECT
+ jr c, .nextMove
+ cp POISON_EFFECT
+ jr c, .preferMove
+ jr .nextMove
+.preferMove
+ dec [hl] ; slighly encourage this move
+ jr .nextMove
+
+; encourages moves that are effective against the player's mon
+AIMoveChoiceModification3: ; 39817 (e:5817)
+ ld hl, $cee8 ; temp move selection array (-1 byte offest)
+ ld de, W_ENEMYMONMOVES ; enemy moves
+ ld b, $5
+.nextMove
+ dec b
+ ret z ; processed all 4 moves
+ inc hl
+ ld a, [de]
+ and a
+ ret z ; no more moves in move set
+ inc de
+ call ReadMove
+ push hl
+ push bc
+ push de
+ callab AIGetTypeEffectiveness
+ pop de
+ pop bc
+ pop hl
+ ld a, [$d11e]
+ cp $10
+ jr z, .nextMove
+ jr c, .notEffectiveMove
+ dec [hl] ; slighly encourage this move
+ jr .nextMove
+.notEffectiveMove ; discourages non-effective moves if better moves are available
+ push hl
+ push de
+ push bc
+ ld a, [W_ENEMYMOVETYPE]
+ ld d, a
+ ld hl, W_ENEMYMONMOVES ; enemy moves
+ ld b, $5
+ ld c, $0
+.loopMoves
+ dec b
+ jr z, .done
+ ld a, [hli]
+ and a
+ jr z, .done
+ call ReadMove
+ ld a, [W_ENEMYMOVEEFFECT]
+ cp SUPER_FANG_EFFECT
+ jr z, .betterMoveFound ; Super Fang is considered to be a better move
+ cp SPECIAL_DAMAGE_EFFECT
+ jr z, .betterMoveFound ; any special damage moves are considered to be better moves
+ cp FLY_EFFECT
+ jr z, .betterMoveFound ; Fly is considered to be a better move
+ ld a, [W_ENEMYMOVETYPE]
+ cp d
+ jr z, .loopMoves
+ ld a, [W_ENEMYMOVEPOWER]
+ and a
+ jr nz, .betterMoveFound ; damaging moves of a different type are considered to be better moves
+ jr .loopMoves
+.betterMoveFound
+ ld c, a
+.done
+ ld a, c
+ pop bc
+ pop de
+ pop hl
+ and a
+ jr z, .nextMove
+ inc [hl] ; slighly discourage this move
+ jr .nextMove
+AIMoveChoiceModification4: ; 39883 (e:5883)
+ ret
+
+ReadMove: ; 39884 (e:5884)
+ push hl
+ push de
+ push bc
+ dec a
+ ld hl,Moves
+ ld bc,6
+ call AddNTimes
+ ld de,$CFCC
+ call CopyData
+ pop bc
+ pop de
+ pop hl
+ ret
+
+; move choice modification methods that are applied for each trainer class
+; 0 is sentinel value
+TrainerClassMoveChoiceModifications: ; 3989b (e:589b)
+ db 0 ; YOUNGSTER
+ db 1,0 ; BUG CATCHER
+ db 1,0 ; LASS
+ db 1,3,0 ; SAILOR
+ db 1,0 ; JR__TRAINER_M
+ db 1,0 ; JR__TRAINER_F
+ db 1,2,3,0; POKEMANIAC
+ db 1,2,0 ; SUPER_NERD
+ db 1,0 ; HIKER
+ db 1,0 ; BIKER
+ db 1,3,0 ; BURGLAR
+ db 1,0 ; ENGINEER
+ db 1,2,0 ; JUGGLER_X
+ db 1,3,0 ; FISHER
+ db 1,3,0 ; SWIMMER
+ db 0 ; CUE_BALL
+ db 1,0 ; GAMBLER
+ db 1,3,0 ; BEAUTY
+ db 1,2,0 ; PSYCHIC_TR
+ db 1,3,0 ; ROCKER
+ db 1,0 ; JUGGLER
+ db 1,0 ; TAMER
+ db 1,0 ; BIRD_KEEPER
+ db 1,0 ; BLACKBELT
+ db 1,0 ; SONY1
+ db 1,3,0 ; PROF_OAK
+ db 1,2,0 ; CHIEF
+ db 1,2,0 ; SCIENTIST
+ db 1,3,0 ; GIOVANNI
+ db 1,0 ; ROCKET
+ db 1,3,0 ; COOLTRAINER_M
+ db 1,3,0 ; COOLTRAINER_F
+ db 1,0 ; BRUNO
+ db 1,0 ; BROCK
+ db 1,3,0 ; MISTY
+ db 1,3,0 ; LT__SURGE
+ db 1,3,0 ; ERIKA
+ db 1,3,0 ; KOGA
+ db 1,3,0 ; BLAINE
+ db 1,3,0 ; SABRINA
+ db 1,2,0 ; GENTLEMAN
+ db 1,3,0 ; SONY2
+ db 1,3,0 ; SONY3
+ db 1,2,3,0; LORELEI
+ db 1,0 ; CHANNELER
+ db 1,0 ; AGATHA
+ db 1,3,0 ; LANCE
+
+TrainerPicAndMoneyPointers: ; 39914 (e:5914)
+; trainer pic pointers and base money.
+; money received after battle = base money × level of highest-level enemy mon
+ dw YoungsterPic
+ db 0,$15,0
+
+ dw BugCatcherPic
+ db 0,$10,0
+
+ dw LassPic
+ db 0,$15,0
+
+ dw SailorPic
+ db 0,$30,0
+
+ dw JrTrainerMPic
+ db 0,$20,0
+
+ dw JrTrainerFPic
+ db 0,$20,0
+
+ dw PokemaniacPic
+ db 0,$50,0
+
+ dw SuperNerdPic
+ db 0,$25,0
+
+ dw HikerPic
+ db 0,$35,0
+
+ dw BikerPic
+ db 0,$20,0
+
+ dw BurglarPic
+ db 0,$90,0
+
+ dw EngineerPic
+ db 0,$50,0
+
+ dw JugglerPic
+ db 0,$35,0
+
+ dw FisherPic
+ db 0,$35,0
+
+ dw SwimmerPic
+ db 0,$05,0
+
+ dw CueBallPic
+ db 0,$25,0
+
+ dw GamblerPic
+ db 0,$70,0
+
+ dw BeautyPic
+ db 0,$70,0
+
+ dw PsychicPic
+ db 0,$10,0
+
+ dw RockerPic
+ db 0,$25,0
+
+ dw JugglerPic
+ db 0,$35,0
+
+ dw TamerPic
+ db 0,$40,0
+
+ dw BirdKeeperPic
+ db 0,$25,0
+
+ dw BlackbeltPic
+ db 0,$25,0
+
+ dw Rival1Pic
+ db 0,$35,0
+
+ dw ProfOakPic
+ db 0,$99,0
+
+ dw ChiefPic
+ db 0,$30,0
+
+ dw ScientistPic
+ db 0,$50,0
+
+ dw GiovanniPic
+ db 0,$99,0
+
+ dw RocketPic
+ db 0,$30,0
+
+ dw CooltrainerMPic
+ db 0,$35,0
+
+ dw CooltrainerFPic
+ db 0,$35,0
+
+ dw BrunoPic
+ db 0,$99,0
+
+ dw BrockPic
+ db 0,$99,0
+
+ dw MistyPic
+ db 0,$99,0
+
+ dw LtSurgePic
+ db 0,$99,0
+
+ dw ErikaPic
+ db 0,$99,0
+
+ dw KogaPic
+ db 0,$99,0
+
+ dw BlainePic
+ db 0,$99,0
+
+ dw SabrinaPic
+ db 0,$99,0
+
+ dw GentlemanPic
+ db 0,$70,0
+
+ dw Rival2Pic
+ db 0,$65,0
+
+ dw Rival3Pic
+ db 0,$99,0
+
+ dw LoreleiPic
+ db 0,$99,0
+
+ dw ChannelerPic
+ db 0,$30,0
+
+ dw AgathaPic
+ db 0,$99,0
+
+ dw LancePic
+ db 0,$99,0
+
+INCLUDE "text/trainer_names.asm"
+
+Func_39b87: ; 39b87 (e:5b87)
+ ld hl, $d0dc
+ ld de, $d0e1
+ ld b, $0
+.asm_39b8f
+ ld a, [hli]
+ and a
+ jr z, .asm_39bc1
+ push hl
+ ld [$d0b5], a
+ ld a, $2c
+ ld [$d0b7], a
+ ld a, MOVE_NAME
+ ld [W_LISTTYPE], a
+ call GetName
+ ld hl, $cd6d
+.asm_39ba7
+ ld a, [hli]
+ cp $50
+ jr z, .asm_39bb0
+ ld [de], a
+ inc de
+ jr .asm_39ba7
+.asm_39bb0
+ ld a, b
+ ld [$cd6c], a
+ inc b
+ ld a, $4e
+ ld [de], a
+ inc de
+ pop hl
+ ld a, b
+ cp $4
+ jr z, .asm_39bd1
+ jr .asm_39b8f
+.asm_39bc1
+ ld a, "-"
+ ld [de], a
+ inc de
+ inc b
+ ld a, b
+ cp $4
+ jr z, .asm_39bd1
+ ld a, $4e
+ ld [de], a
+ inc de
+ jr .asm_39bc1
+.asm_39bd1
+ ld a, "@"
+ ld [de], a
+ ret
+
+Func_39bd5: ; 39bd5 (e:5bd5)
+ ld a, [$d11b]
+ cp $1
+ jr nz, .asm_39be6
+ ld hl, wEnemyPartyCount ; $d89c
+ ld de, W_ENEMYMON1OT ; $d9ac OT names of other player
+ ld a, $6
+ jr .asm_39c18
+.asm_39be6
+ cp $4
+ jr nz, .calcAttackStat4
+ ld hl, W_NUMINPARTY ; $d163
+ ld de, W_PARTYMON1OT ; $d273
+ ld a, $5
+ jr .asm_39c18
+.calcAttackStat4
+ cp $5
+ jr nz, .asm_39c02
+ ld hl, $cf7b
+ ld de, MonsterNames ; $421e
+ ld a, $1
+ jr .asm_39c18
+.asm_39c02
+ cp $2
+ jr nz, .asm_39c10
+ ld hl, wNumBagItems ; $d31d
+ ld de, ItemNames ; $472b
+ ld a, $4
+ jr .asm_39c18
+.asm_39c10
+ ld hl, $cf7b
+ ld de, ItemNames ; $472b
+ ld a, ITEM_NAME
+.asm_39c18
+ ld [W_LISTTYPE], a
+ ld a, l
+ ld [$cf8b], a
+ ld a, h
+ ld [$cf8c], a
+ ld a, e
+ ld [$cf8d], a
+ ld a, d
+ ld [$cf8e], a
+ ld bc, ItemPrices ; $4608
+ ld a, c
+ ld [$cf8f], a
+ ld a, b
+ ld [$cf90], a
+ ret
+
+Func_39c37: ; 39c37 (e:5c37)
+ ld hl, W_PARTYMON1 ; $d164
+ ld a, [$cc49]
+ and a
+ jr z, .asm_39c4b
+ dec a
+ jr z, .asm_39c48
+ ld hl, $da81
+ jr .asm_39c4b
+.asm_39c48
+ ld hl, $d89d
+.asm_39c4b
+ ld d, $0
+ add hl, de
+ ld a, [hl]
+ ld [$cf91], a
+ ret
+
+ReadTrainer: ; 39c53 (e:5c53)
+
+; don't change any moves in a link battle
+ ld a,[W_ISLINKBATTLE]
+ and a
+ ret nz
+
+; set [wEnemyPartyCount] to 0, [$D89D] to FF
+; XXX first is total enemy pokemon?
+; XXX second is species of first pokemon?
+ ld hl,wEnemyPartyCount
+ xor a
+ ld [hli],a
+ dec a
+ ld [hl],a
+
+; get the pointer to trainer data for this class
+ ld a,[W_CUROPPONENT]
+ sub $C9 ; convert value from pokemon to trainer
+ add a,a
+ ld hl,TrainerDataPointers
+ ld c,a
+ ld b,0
+ add hl,bc ; hl points to trainer class
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ ld a,[W_TRAINERNO]
+ ld b,a
+; At this point b contains the trainer number,
+; and hl points to the trainer class.
+; Our next task is to iterate through the trainers,
+; decrementing b each time, until we get to the right one.
+.outer
+ dec b
+ jr z,.IterateTrainer
+.inner
+ ld a,[hli]
+ and a
+ jr nz,.inner
+ jr .outer
+
+; if the first byte of trainer data is FF,
+; - each pokemon has a specific level
+; (as opposed to the whole team being of the same level)
+; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
+; else the first byte is the level of every pokemon on the team
+.IterateTrainer
+ ld a,[hli]
+ cp $FF ; is the trainer special?
+ jr z,.SpecialTrainer ; if so, check for special moves
+ ld [W_CURENEMYLVL],a
+.LoopTrainerData
+ ld a,[hli]
+ and a ; have we reached the end of the trainer data?
+ jr z,.FinishUp
+ ld [$CF91],a ; write species somewhere (XXX why?)
+ ld a,1
+ ld [$CC49],a
+ push hl
+ call AddPokemonToParty
+ pop hl
+ jr .LoopTrainerData
+.SpecialTrainer
+; if this code is being run:
+; - each pokemon has a specific level
+; (as opposed to the whole team being of the same level)
+; - if [W_LONEATTACKNO] != 0, one pokemon on the team has a special move
+ ld a,[hli]
+ and a ; have we reached the end of the trainer data?
+ jr z,.AddLoneMove
+ ld [W_CURENEMYLVL],a
+ ld a,[hli]
+ ld [$CF91],a
+ ld a,1
+ ld [$CC49],a
+ push hl
+ call AddPokemonToParty
+ pop hl
+ jr .SpecialTrainer
+.AddLoneMove
+; does the trainer have a single monster with a different move
+ ld a,[W_LONEATTACKNO] ; Brock is 01, Misty is 02, Erika is 04, etc
+ and a
+ jr z,.AddTeamMove
+ dec a
+ add a,a
+ ld c,a
+ ld b,0
+ ld hl,LoneMoves
+ add hl,bc
+ ld a,[hli]
+ ld d,[hl]
+ ld hl,W_ENEMYMON1MOVE3
+ ld bc,W_ENEMYMON2MOVE3 - W_ENEMYMON1MOVE3
+ call AddNTimes
+ ld [hl],d
+ jr .FinishUp
+.AddTeamMove
+; check if our trainer's team has special moves
+
+; get trainer class number
+ ld a,[W_CUROPPONENT]
+ sub $C8
+ ld b,a
+ ld hl,TeamMoves
+
+; iterate through entries in TeamMoves, checking each for our trainer class
+.IterateTeamMoves
+ ld a,[hli]
+ cp b
+ jr z,.GiveTeamMoves ; is there a match?
+ inc hl ; if not, go to the next entry
+ inc a
+ jr nz,.IterateTeamMoves
+
+ ; no matches found. is this trainer champion rival?
+ ld a,b
+ cp SONY3
+ jr z,.ChampionRival
+ jr .FinishUp ; nope
+.GiveTeamMoves
+ ld a,[hl]
+ ld [$D95E],a
+ jr .FinishUp
+.ChampionRival ; give moves to his team
+
+; pidgeot
+ ld a,SKY_ATTACK
+ ld [W_ENEMYMON1MOVE3],a
+
+; starter
+ ld a,[W_RIVALSTARTER]
+ cp STARTER3
+ ld b,MEGA_DRAIN
+ jr z,.GiveStarterMove
+ cp STARTER1
+ ld b,FIRE_BLAST
+ jr z,.GiveStarterMove
+ ld b,BLIZZARD ; must be squirtle
+.GiveStarterMove
+ ld a,b
+ ld [W_ENEMYMON6MOVE3],a
+.FinishUp ; XXX this needs documenting
+ xor a ; clear D079-D07B
+ ld de,$D079
+ ld [de],a
+ inc de
+ ld [de],a
+ inc de
+ ld [de],a
+ ld a,[W_CURENEMYLVL]
+ ld b,a
+.LastLoop
+ ld hl,$D047
+ ld c,2
+ push bc
+ ld a,$B
+ call Predef
+ pop bc
+ inc de
+ inc de
+ dec b
+ jr nz,.LastLoop
+ ret
+
+INCLUDE "data/trainer_moves.asm"
+
+INCLUDE "data/trainer_parties.asm"
+
+TrainerAI: ; 3a52e (e:652e)
+;XXX called at 34964, 3c342, 3c398
+ and a
+ ld a,[W_ISINBATTLE]
+ dec a
+ ret z ; if not a trainer, we're done here
+ ld a,[W_ISLINKBATTLE]
+ cp 4
+ ret z
+ ld a,[W_TRAINERCLASS] ; what trainer class is this?
+ dec a
+ ld c,a
+ ld b,0
+ ld hl,TrainerAIPointers
+ add hl,bc
+ add hl,bc
+ add hl,bc
+ ld a,[wAICount]
+ and a
+ ret z ; if no AI uses left, we're done here
+ inc hl
+ inc a
+ jr nz,.getpointer
+ dec hl
+ ld a,[hli]
+ ld [wAICount],a
+.getpointer
+ ld a,[hli]
+ ld h,[hl]
+ ld l,a
+ call GenRandom
+ jp [hl]
+
+TrainerAIPointers: ; 3a55c (e:655c)
+; one entry per trainer class
+; first byte, number of times (per Pokémon) it can occur
+; next two bytes, pointer to AI subroutine for trainer class
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,JugglerAI ; juggler_x
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 3,JugglerAI ; juggler
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 2,BlackbeltAI ; blackbelt
+ dbw 3,GenericAI
+ dbw 3,GenericAI
+ dbw 1,GenericAI ; chief
+ dbw 3,GenericAI
+ dbw 1,GiovanniAI ; giovanni
+ dbw 3,GenericAI
+ dbw 2,CooltrainerMAI ; cooltrainerm
+ dbw 1,CooltrainerFAI ; cooltrainerf
+ dbw 2,BrunoAI ; bruno
+ dbw 5,BrockAI ; brock
+ dbw 1,MistyAI ; misty
+ dbw 1,LtSurgeAI ; surge
+ dbw 1,ErikaAI ; erika
+ dbw 2,KogaAI ; koga
+ dbw 2,BlaineAI ; blaine
+ dbw 1,SabrinaAI ; sabrina
+ dbw 3,GenericAI
+ dbw 1,Sony2AI ; sony2
+ dbw 1,Sony3AI ; sony3
+ dbw 2,LoreleiAI ; lorelei
+ dbw 3,GenericAI
+ dbw 2,AgathaAI ; agatha
+ dbw 1,LanceAI ; lance
+
+JugglerAI: ; 3a5e9 (e:65e9)
+ cp $40
+ ret nc
+ jp Func_3a72a
+
+BlackbeltAI: ; 3a5ef (e:65ef)
+ cp $20
+ ret nc
+ jp AIUseXAttack
+
+GiovanniAI: ; 3a5f5 (e:65f5)
+ cp $40
+ ret nc
+ jp AIUseGuardSpec
+
+CooltrainerMAI: ; 3a5fb (e:65fb)
+ cp $40
+ ret nc
+ jp AIUseXAttack
+
+CooltrainerFAI: ; 3a601 (e:6601)
+ cp $40
+ ld a,$A
+ call Func_3a7cf
+ jp c,AIUseHyperPotion
+ ld a,5
+ call Func_3a7cf
+ ret nc
+ jp Func_3a72a
+
+BrockAI: ; 3a614 (e:6614)
+; if his active monster has a status condition, use a full heal
+ ld a,[W_ENEMYMONSTATUS]
+ and a
+ ret z
+ jp AIUseFullHeal
+
+MistyAI: ; 3a61c (e:661c)
+ cp $40
+ ret nc
+ jp AIUseXDefend
+
+LtSurgeAI: ; 3a622 (e:6622)
+ cp $40
+ ret nc
+ jp AIUseXSpeed
+
+ErikaAI: ; 3a628 (e:6628)
+ cp $80
+ ret nc
+ ld a,$A
+ call Func_3a7cf
+ ret nc
+ jp AIUseSuperPotion
+
+KogaAI: ; 3a634 (e:6634)
+ cp $40
+ ret nc
+ jp AIUseXAttack
+
+BlaineAI: ; 3a63a (e:663a)
+ cp $40
+ ret nc
+ jp AIUseSuperPotion
+
+SabrinaAI: ; 3a640 (e:6640)
+ cp $40
+ ret nc
+ ld a,$A
+ call Func_3a7cf
+ ret nc
+ jp AIUseHyperPotion
+
+Sony2AI: ; 3a64c (e:664c)
+ cp $20
+ ret nc
+ ld a,5
+ call Func_3a7cf
+ ret nc
+ jp AIUsePotion
+
+Sony3AI: ; 3a658 (e:6658)
+ cp $20
+ ret nc
+ ld a,5
+ call Func_3a7cf
+ ret nc
+ jp AIUseFullRestore
+
+LoreleiAI: ; 3a664 (e:6664)
+ cp $80
+ ret nc
+ ld a,5
+ call Func_3a7cf
+ ret nc
+ jp AIUseSuperPotion
+
+BrunoAI: ; 3a670 (e:6670)
+ cp $40
+ ret nc
+ jp AIUseXDefend
+
+AgathaAI: ; 3a676 (e:6676)
+ cp $14
+ jp c,Func_3a72a
+ cp $80
+ ret nc
+ ld a,4
+ call Func_3a7cf
+ ret nc
+ jp AIUseSuperPotion
+
+LanceAI: ; 3a687 (e:6687)
+ cp $80
+ ret nc
+ ld a,5
+ call Func_3a7cf
+ ret nc
+ jp AIUseHyperPotion
+
+GenericAI: ; 3a693 (e:6693)
+ and a ; clear carry
+ ret
+
+; end of individual trainer AI routines
+
+DecrementAICount: ; 3a695 (e:6695)
+ ld hl,wAICount
+ dec [hl]
+ scf
+ ret
+
+Func_3a69b: ; 3a69b (e:669b)
+ ld a,(SFX_08_3e - SFX_Headers_08) / 3
+ jp PlaySoundWaitForCurrent
+
+AIUseFullRestore: ; 3a6a0 (e:66a0)
+ call AICureStatus
+ ld a,FULL_RESTORE
+ ld [$CF05],a
+ ld de,wHPBarOldHP
+ ld hl,$CFE7
+ ld a,[hld]
+ ld [de],a
+ inc de
+ ld a,[hl]
+ ld [de],a
+ inc de
+ ld hl,$CFF5
+ ld a,[hld]
+ ld [de],a
+ inc de
+ ld [wHPBarMaxHP],a
+ ld [$CFE7],a
+ ld a,[hl]
+ ld [de],a
+ ld [wHPBarMaxHP+1],a
+ ld [W_ENEMYMONCURHP],a
+ jr Func_3a718
+
+AIUsePotion: ; 3a6ca (e:66ca)
+; enemy trainer heals his monster with a potion
+ ld a,POTION
+ ld b,20
+ jr AIRecoverHP
+
+AIUseSuperPotion: ; 3a6d0 (e:66d0)
+; enemy trainer heals his monster with a super potion
+ ld a,SUPER_POTION
+ ld b,50
+ jr AIRecoverHP
+
+AIUseHyperPotion: ; 3a6d6 (e:66d6)
+; enemy trainer heals his monster with a hyper potion
+ ld a,HYPER_POTION
+ ld b,200
+ ; fallthrough
+
+AIRecoverHP: ; 3a6da (e:66da)
+; heal b HP and print "trainer used $(a) on pokemon!"
+ ld [$CF05],a
+ ld hl,$CFE7
+ ld a,[hl]
+ ld [wHPBarOldHP],a
+ add b
+ ld [hld],a
+ ld [wHPBarNewHP],a
+ ld a,[hl]
+ ld [wHPBarOldHP+1],a
+ ld [wHPBarNewHP+1],a
+ jr nc,.next
+ inc a
+ ld [hl],a
+ ld [wHPBarNewHP+1],a
+.next
+ inc hl
+ ld a,[hld]
+ ld b,a
+ ld de,$CFF5
+ ld a,[de]
+ dec de
+ ld [wHPBarMaxHP],a
+ sub b
+ ld a,[hli]
+ ld b,a
+ ld a,[de]
+ ld [wHPBarMaxHP+1],a
+ sbc b
+ jr nc,Func_3a718
+ inc de
+ ld a,[de]
+ dec de
+ ld [hld],a
+ ld [wHPBarNewHP],a
+ ld a,[de]
+ ld [hl],a
+ ld [wHPBarNewHP+1],a
+ ; fallthrough
+
+Func_3a718: ; 3a718 (e:6718)
+ call AIPrintItemUse_
+ FuncCoord 2, 2 ; $c3ca
+ ld hl,Coord
+ xor a
+ ld [$CF94],a
+ ld a,$48
+ call Predef
+ jp DecrementAICount
+
+Func_3a72a: ; 3a72a (e:672a)
+ ld a,[wEnemyPartyCount]
+ ld c,a
+ ld hl,W_ENEMYMON1HP
+
+ ld d,0 ; keep count of unfainted monsters
+
+ ; count how many monsters haven't fainted yet
+.loop
+ ld a,[hli]
+ ld b,a
+ ld a,[hld]
+ or b
+ jr z,.Fainted ; has monster fainted?
+ inc d
+.Fainted
+ push bc
+ ld bc,$2C
+ add hl,bc
+ pop bc
+ dec c
+ jr nz,.loop
+
+ ld a,d ; how many available monsters are there?
+ cp 2 ; don't bother if only 1 or 2
+ jp nc,Func_3a74b
+ and a
+ ret
+
+Func_3a74b: ; 3a74b (e:674b)
+
+; prepare to withdraw the active monster: copy hp, number, and status to roster
+
+ ld a,[W_ENEMYMONNUMBER]
+ ld hl,W_ENEMYMON1HP
+ ld bc,$2C
+ call AddNTimes
+ ld d,h
+ ld e,l
+ ld hl,W_ENEMYMONCURHP
+ ld bc,4
+ call CopyData
+
+ ld hl, AIBattleWithdrawText
+ call PrintText
+
+ ld a,1
+ ld [$D11D],a
+ callab EnemySendOut
+ xor a
+ ld [$D11D],a
+
+ ld a,[W_ISLINKBATTLE]
+ cp 4
+ ret z
+ scf
+ ret
+
+AIBattleWithdrawText: ; 3a781 (e:6781)
+ TX_FAR _AIBattleWithdrawText
+ db "@"
+
+AIUseFullHeal: ; 3a786 (e:6786)
+ call Func_3a69b
+ call AICureStatus
+ ld a,FULL_HEAL
+ jp AIPrintItemUse
+
+AICureStatus: ; 3a791 (e:6791)
+; cures the status of enemy's active pokemon
+ ld a,[W_ENEMYMONNUMBER]
+ ld hl,$D8A8
+ ld bc,$2C
+ call AddNTimes
+ xor a
+ ld [hl],a ; clear status in enemy team roster
+ ld [W_ENEMYMONSTATUS],a ; clear status of active enemy
+ ld hl,$D069
+ res 0,[hl]
+ ret
+
+AIUseXAccuracy: ; 0x3a7a8 unused
+ call Func_3a69b
+ ld hl,$D068
+ set 0,[hl]
+ ld a,X_ACCURACY
+ jp AIPrintItemUse
+
+AIUseGuardSpec: ; 3a7b5 (e:67b5)
+ call Func_3a69b
+ ld hl,$D068
+ set 1,[hl]
+ ld a,GUARD_SPEC_
+ jp AIPrintItemUse
+
+AIUseDireHit: ; 0x3a7c2 unused
+ call Func_3a69b
+ ld hl,$D068
+ set 2,[hl]
+ ld a,DIRE_HIT
+ jp AIPrintItemUse
+
+Func_3a7cf: ; 3a7cf (e:67cf)
+ ld [H_DIVISOR],a
+ ld hl,$CFF4
+ ld a,[hli]
+ ld [H_DIVIDEND],a
+ ld a,[hl]
+ ld [H_DIVIDEND + 1],a
+ ld b,2
+ call Divide
+ ld a,[H_QUOTIENT + 3]
+ ld c,a
+ ld a,[H_QUOTIENT + 2]
+ ld b,a
+ ld hl,$CFE7
+ ld a,[hld]
+ ld e,a
+ ld a,[hl]
+ ld d,a
+ ld a,d
+ sub b
+ ret nz
+ ld a,e
+ sub c
+ ret
+
+AIUseXAttack: ; 3a7f2 (e:67f2)
+ ld b,$A
+ ld a,X_ATTACK
+ jr AIIncreaseStat
+
+AIUseXDefend: ; 3a7f8 (e:67f8)
+ ld b,$B
+ ld a,X_DEFEND
+ jr AIIncreaseStat
+
+AIUseXSpeed: ; 3a7fe (e:67fe)
+ ld b,$C
+ ld a,X_SPEED
+ jr AIIncreaseStat
+
+AIUseXSpecial: ; 3a804 (e:6804)
+ ld b,$D
+ ld a,X_SPECIAL
+ ; fallthrough
+
+AIIncreaseStat: ; 3a808 (e:6808)
+ ld [$CF05],a
+ push bc
+ call AIPrintItemUse_
+ pop bc
+ ld hl,$CFCD
+ ld a,[hld]
+ push af
+ ld a,[hl]
+ push af
+ push hl
+ ld a,$AF
+ ld [hli],a
+ ld [hl],b
+ callab StatModifierUpEffect
+ pop hl
+ pop af
+ ld [hli],a
+ pop af
+ ld [hl],a
+ jp DecrementAICount
+
+AIPrintItemUse: ; 3a82c (e:682c)
+ ld [$CF05],a
+ call AIPrintItemUse_
+ jp DecrementAICount
+
+AIPrintItemUse_: ; 3a835 (e:6835)
+; print "x used [$CF05] on z!"
+ ld a,[$CF05]
+ ld [$D11E],a
+ call GetItemName
+ ld hl, AIBattleUseItemText
+ jp PrintText
+
+AIBattleUseItemText: ; 3a844 (e:6844)
+ TX_FAR _AIBattleUseItemText
+ db "@"
+
+DrawAllPokeballs: ; 3a849 (e:6849)
+ call LoadPartyPokeballGfx
+ call SetupOwnPartyPokeballs
+ ld a, [W_ISINBATTLE] ; $d057
+ dec a
+ ret z ; return if wild pokémon
+ jp SetupEnemyPartyPokeballs
+
+DrawEnemyPokeballs: ; 0x3a857
+ call LoadPartyPokeballGfx
+ jp SetupEnemyPartyPokeballs
+
+LoadPartyPokeballGfx: ; 3a85d (e:685d)
+ ld de, PokeballTileGraphics ; $697e
+ ld hl, $8310
+ ld bc, (BANK(PokeballTileGraphics) << 8) + $04
+ jp CopyVideoData
+
+SetupOwnPartyPokeballs: ; 3a869 (e:6869)
+ call PlacePlayerHUDTiles
+ ld hl, W_PARTYMON1DATA
+ ld de, W_NUMINPARTY ; $d163
+ call SetupPokeballs
+ ld a, $60
+ ld hl, W_BASECOORDX ; $d081
+ ld [hli], a
+ ld [hl], a
+ ld a, $8
+ ld [$cd3e], a
+ ld hl, wOAMBuffer
+ jp Func_3a8e1
+
+SetupEnemyPartyPokeballs: ; 3a887 (e:6887)
+ call PlaceEnemyHUDTiles
+ ld hl, wEnemyMons
+ ld de, wEnemyPartyCount ; $d89c
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; $d081
+ ld a, $48
+ ld [hli], a
+ ld [hl], $20
+ ld a, $f8
+ ld [$cd3e], a
+ ld hl, $c318
+ jp Func_3a8e1
+
+SetupPokeballs: ; 0x3a8a6
+ ld a, [de]
+ push af
+ ld de, wBuffer
+ ld c, $6 ; max num of partymons
+ ld a, $34 ; empty pokeball
+.emptyloop
+ ld [de], a
+ inc de
+ dec c
+ jr nz, .emptyloop ; 0x3a8b2 $fb
+ pop af
+ ld de, wBuffer
+.monloop
+ push af
+ call PickPokeball
+ inc de
+ pop af
+ dec a
+ jr nz, .monloop
+ ret
+
+PickPokeball: ; 3a8c2 (e:68c2)
+ inc hl
+ ld a, [hli]
+ and a
+ jr nz, .alive
+ ld a, [hl]
+ and a
+ ld b, $33 ; crossed ball (fainted)
+ jr z, .done_fainted
+.alive
+ inc hl
+ inc hl
+ ld a, [hl] ; status
+ and a
+ ld b, $32 ; black ball (status)
+ jr nz, .done
+ dec b ; regular ball
+ jr .done
+.done_fainted
+ inc hl
+ inc hl
+.done
+ ld a, b
+ ld [de], a
+ ld bc, $0028 ; rest of mon struct
+ add hl, bc
+ ret
+
+Func_3a8e1: ; 3a8e1 (e:68e1)
+ ld de, $cee9
+ ld c, $6
+.asm_3a8e6
+ ld a, [W_BASECOORDY] ; $d082
+ ld [hli], a
+ ld a, [W_BASECOORDX] ; $d081
+ ld [hli], a
+ ld a, [de]
+ ld [hli], a
+ xor a
+ ld [hli], a
+ ld a, [W_BASECOORDX] ; $d081
+ ld b, a
+ ld a, [$cd3e]
+ add b
+ ld [W_BASECOORDX], a ; $d081
+ inc de
+ dec c
+ jr nz, .asm_3a8e6
+ ret
+
+PlacePlayerHUDTiles: ; 3a902 (e:6902)
+ ld hl, PlayerBattleHUDGraphicsTiles ; $6916
+ ld de, $cd3f
+ ld bc, $3
+ call CopyData
+ FuncCoord 18, 10 ; $c47a
+ ld hl, Coord
+ ld de, rIE ; $ffff
+ jr PlaceHUDTiles
+
+PlayerBattleHUDGraphicsTiles: ; 3a916 (e:6916)
+; The tile numbers for specific parts of the battle display for the player's pokemon
+ db $73 ; unused ($73 is hardcoded into the routine that uses these bytes)
+ db $77 ; lower-right corner tile of the HUD
+ db $6F ; lower-left triangle tile of the HUD
+
+PlaceEnemyHUDTiles: ; 3a919 (e:6919)
+ ld hl, EnemyBattleHUDGraphicsTiles ; $692d
+ ld de, $cd3f
+ ld bc, $3
+ call CopyData
+ FuncCoord 1, 2 ; $c3c9
+ ld hl, Coord
+ ld de, $1
+ jr PlaceHUDTiles
+
+EnemyBattleHUDGraphicsTiles: ; 3a92d (e:692d)
+; The tile numbers for specific parts of the battle display for the enemy
+ db $73 ; unused ($73 is hardcoded in the routine that uses these bytes)
+ db $74 ; lower-left corner tile of the HUD
+ db $78 ; lower-right triangle tile of the HUD
+
+PlaceHUDTiles: ; 3a930 (e:6930)
+ ld [hl], $73
+ ld bc, $14
+ add hl, bc
+ ld a, [$cd40]
+ ld [hl], a
+ ld a, $8
+.asm_3a93c
+ add hl, de
+ ld [hl], $76
+ dec a
+ jr nz, .asm_3a93c
+ add hl, de
+ ld a, [$cd41]
+ ld [hl], a
+ ret
+
+SetupPlayerAndEnemyPokeballs: ; 3a948 (e:6948)
+ call LoadPartyPokeballGfx
+ ld hl, W_PARTYMON1_NUM ; $d16b (aliases: W_PARTYMON1DATA)
+ ld de, W_NUMINPARTY ; $d163
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; $d081
+ ld a, $50
+ ld [hli], a
+ ld [hl], $40
+ ld a, $8
+ ld [$cd3e], a
+ ld hl, wOAMBuffer
+ call Func_3a8e1
+ ld hl, wEnemyMons ; $d8a4
+ ld de, wEnemyPartyCount ; $d89c
+ call SetupPokeballs
+ ld hl, W_BASECOORDX ; $d081
+ ld a, $50
+ ld [hli], a
+ ld [hl], $68
+ ld hl, $c318
+ jp Func_3a8e1
+
+; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (faited) and pokeball slot (no mon)
+PokeballTileGraphics:: ; 3a97e (e:697e)
+ INCBIN "gfx/pokeball.2bpp" \ No newline at end of file