shithub: pokered

Download patch

ref: c2efe700ac1c5cca88bac710b98388a99665741e
parent: 52add272c6bca00d2ea827ef7fa4611a4bc41b47
parent: ce9940a2eb89caa9f53507a6d6071f8eaf85ee48
author: yenatch <yenatch@gmail.com>
date: Wed Apr 1 08:56:42 EDT 2015

Merge pull request #90 from xCrystal/master

Rename/split battle and move effect files. Battle functions, AI, and attack animations

--- a/engine/battle/1.asm
+++ /dev/null
@@ -1,104 +1,0 @@
-DrainHPEffect_: ; 783f (1:783f)
-	ld hl, W_DAMAGE 
-	ld a, [hl]
-	srl a ; divide damage by 2
-	ld [hli], a
-	ld a, [hl]
-	rr a
-	ld [hld], a
-	or [hl] ; is damage 0?
-	jr nz, .getAttackerHP
-; if damage is 0, increase to 1 so that the attacker gains at least 1 HP
-	inc hl
-	inc [hl]
-.getAttackerHP
-	ld hl, wBattleMonHP
-	ld de, wBattleMonMaxHP
-	ld a, [H_WHOSETURN]
-	and a
-	jp z, .addDamageToAttackerHP
-	ld hl, wEnemyMonHP 
-	ld de, wEnemyMonMaxHP 
-.addDamageToAttackerHP
-	ld bc, wHPBarOldHP+1
-; copy current HP to wHPBarOldHP
-	ld a, [hli]
-	ld [bc], a
-	ld a, [hl]
-	dec bc
-	ld [bc], a
-; copy max HP to wHPBarMaxHP
-	ld a, [de]
-	dec bc
-	ld [bc], a
-	inc de
-	ld a, [de]
-	dec bc
-	ld [bc], a
-; add damage to attacker's HP and copy new HP to wHPBarNewHP
-	ld a, [W_DAMAGE + 1]
-	ld b, [hl]
-	add b
-	ld [hld], a
-	ld [wHPBarNewHP], a
-	ld a, [W_DAMAGE] 
-	ld b, [hl]
-	adc b
-	ld [hli], a
-	ld [wHPBarNewHP+1], a
-	jr c, .capToMaxHP ; if HP > 65,535, cap to max HP
-; compare HP with max HP
-	ld a, [hld]
-	ld b, a
-	ld a, [de]
-	dec de
-	sub b
-	ld a, [hli]
-	ld b, a
-	ld a, [de]
-	inc de
-	sbc b
-	jr nc, .next
-.capToMaxHP
-	ld a, [de]
-	ld [hld], a
-	ld [wHPBarNewHP], a
-	dec de
-	ld a, [de]
-	ld [hli], a
-	ld [wHPBarNewHP+1], a
-	inc de
-.next
-	ld a, [H_WHOSETURN]
-	and a
-	hlCoord 10, 9
-	ld a, $1
-	jr z, .next2
-	hlCoord 2, 2
-	xor a
-.next2
-	ld [wHPBarType], a
-	predef UpdateHPBar2
-	predef DrawPlayerHUDAndHPBar
-	predef DrawEnemyHUDAndHPBar
-	callab ReadPlayerMonCurHPAndStatus
-	ld hl, SuckedHealthText
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [W_PLAYERMOVEEFFECT]
-	jr z, .next3
-	ld a, [W_ENEMYMOVEEFFECT] 
-.next3
-	cp DREAM_EATER_EFFECT
-	jr nz, .printText
-	ld hl, DreamWasEatenText
-.printText
-	jp PrintText
-
-SuckedHealthText: ; 78dc (1:78dc)
-	TX_FAR _SuckedHealthText
-	db "@"
-
-DreamWasEatenText: ; 78e1 (1:78e1)
-	TX_FAR _DreamWasEatenText
-	db "@"
--- a/engine/battle/14.asm
+++ /dev/null
@@ -1,94 +1,0 @@
-InitBattleVariables: ; 525af (14:65af)
-	ld a, [hTilesetType]
-	ld [wd0d4], a
-	xor a
-	ld [wcd6a], a
-	ld [wBattleResult], a
-	ld hl, wcc2b
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld [wListScrollOffset], a
-	ld [wCriticalHitOrOHKO], a
-	ld [wBattleMonSpecies], a
-	ld [wPartyGainExpFlags], a
-	ld [wPlayerMonNumber], a 
-	ld [wEscapedFromBattle], a
-	ld [wMapPalOffset], a
-	ld hl, wcf1d
-	ld [hli], a
-	ld [hl], a
-	ld hl, wccd3
-	ld b, $3c
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	inc a
-	ld [wccd9], a
-	ld a, [W_CURMAP] 
-	cp SAFARI_ZONE_EAST
-	jr c, .notSafariBattle
-	cp SAFARI_ZONE_REST_HOUSE_1
-	jr nc, .notSafariBattle
-	ld a, $2 ; safari battle
-	ld [W_BATTLETYPE], a
-.notSafariBattle
-	ld hl, PlayBattleMusic
-	ld b, BANK(PlayBattleMusic)
-	jp Bankswitch
-
-ParalyzeEffect_: ; 52601 (14:6601)
-	ld hl, wEnemyMonStatus
-	ld de, W_PLAYERMOVETYPE
-	ld a, [H_WHOSETURN]
-	and a
-	jp z, .next
-	ld hl, wBattleMonStatus 
-	ld de, W_ENEMYMOVETYPE
-.next
-	ld a, [hl]
-	and a ; does the target already have a status ailment?
-	jr nz, .didntAffect
-; check if the target is immune due to types
-	ld a, [de]
-	cp ELECTRIC
-	jr nz, .hitTest
-	ld b, h
-	ld c, l
-	inc bc
-	ld a, [bc]
-	cp GROUND
-	jr z, .doesntAffect
-	inc bc
-	ld a, [bc]
-	cp GROUND
-	jr z, .doesntAffect
-.hitTest
-	push hl
-	callab MoveHitTest
-	pop hl
-	ld a, [W_MOVEMISSED] 
-	and a
-	jr nz, .didntAffect
-	set PAR, [hl]
-	callab QuarterSpeedDueToParalysis
-	ld c, 30
-	call DelayFrames
-	callab PlayCurrentMoveAnimation
-	ld hl, PrintMayNotAttackText
-	ld b, BANK(PrintMayNotAttackText)
-	jp Bankswitch
-.didntAffect
-	ld c, 50
-	call DelayFrames
-	ld hl, PrintDidntAffectText
-	ld b, BANK(PrintDidntAffectText)
-	jp Bankswitch
-.doesntAffect
-	ld c, 50
-	call DelayFrames
-	ld hl, PrintDoesntAffectText
-	ld b, BANK(PrintDoesntAffectText)
-	jp Bankswitch
--- a/engine/battle/15.asm
+++ /dev/null
@@ -1,372 +1,0 @@
-GainExperience: ; 5524f (15:524f)
-	ld a, [wLinkState]
-	cp LINK_STATE_BATTLING
-	ret z ; return if link battle
-	call DivideExpDataByNumMonsGainingExp
-	ld hl, wPartyMon1
-	xor a
-	ld [wWhichPokemon], a
-.partyMonLoop ; loop over each mon and add gained exp
-	inc hl
-	ld a, [hli]
-	or [hl] ; is mon's HP 0?
-	jp z, .nextMon ; if so, go to next mon
-	push hl
-	ld hl, wPartyGainExpFlags
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, $2
-	predef FlagActionPredef
-	ld a, c
-	and a ; is mon's gain exp flag set?
-	pop hl
-	jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
-	ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
-	add hl, de
-	ld d, h
-	ld e, l
-	ld hl, wEnemyMonBaseStats
-	ld c, $5
-.gainStatExpLoop
-	ld a, [hli]
-	ld b, a ; enemy mon base stat
-	ld a, [de] ; stat exp
-	add b ; add enemy mon base state to stat exp
-	ld [de], a
-	jr nc, .nextBaseStat
-; if there was a carry, increment the upper byte
-	dec de
-	ld a, [de]
-	inc a
-	jr z, .maxStatExp ; jump if the value overflowed
-	ld [de], a
-	inc de
-	jr .nextBaseStat
-.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
-	ld a, $ff
-	ld [de], a
-	inc de
-	ld [de], a
-.nextBaseStat
-	dec c
-	jr z, .asm_552a1
-	inc de
-	inc de
-	jr .gainStatExpLoop
-.asm_552a1
-	xor a
-	ld [H_MULTIPLICAND], a
-	ld [H_MULTIPLICAND + 1], a
-	ld a, [wEnemyMonBaseExp]
-	ld [H_MULTIPLICAND + 2], a
-	ld a, [wEnemyMonLevel]
-	ld [H_MULTIPLIER], a
-	call Multiply
-	ld a, 7
-	ld [H_DIVISOR], a
-	ld b, 4
-	call Divide
-	ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
-	add hl, de
-	ld b, [hl] ; party mon OTID
-	inc hl
-	ld a, [wPlayerID]
-	cp b
-	jr nz, .tradedMon
-	ld b, [hl]
-	ld a, [wPlayerID + 1]
-	cp b
-	ld a, $0
-	jr z, .next
-.tradedMon
-	call BoostExp ; traded mon exp boost
-	ld a, $1
-.next
-	ld [wcf4d], a
-	ld a, [W_ISINBATTLE]
-	dec a ; is it a trainer battle?
-	call nz, BoostExp ; if so, boost exp
-	inc hl
-	inc hl
-	inc hl
-; add the gained exp to the party mon's exp
-	ld b, [hl]
-	ld a, [H_QUOTIENT + 3]
-	ld [wcf4c], a
-	add b
-	ld [hld], a
-	ld b, [hl]
-	ld a, [H_QUOTIENT + 2]
-	ld [wcf4b], a
-	adc b
-	ld [hl], a
-	jr nc, .noCarry
-	dec hl
-	inc [hl]
-	inc hl
-.noCarry
-; calculate exp for the mon at max level, and cap the exp at that value
-	inc hl
-	push hl
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, 0
-	ld hl, wPartySpecies
-	add hl, bc
-	ld a, [hl] ; species
-	ld [wd0b5], a
-	call GetMonHeader
-	ld d, MAX_LEVEL
-	callab CalcExperience ; get max exp
-; compare max exp with current exp
-	ld a, [$ff96]
-	ld b, a
-	ld a, [$ff97]
-	ld c, a
-	ld a, [$ff98]
-	ld d, a
-	pop hl
-	ld a, [hld]
-	sub d
-	ld a, [hld]
-	sbc c
-	ld a, [hl]
-	sbc b
-	jr c, .next2
-; the mon's exp is greater than the max exp, so overwrite it with the max exp
-	ld a, b
-	ld [hli], a
-	ld a, c
-	ld [hli], a
-	ld a, d
-	ld [hld], a
-	dec hl
-.next2
-	push hl
-	ld a, [wWhichPokemon]
-	ld hl, wPartyMonNicks
-	call GetPartyMonName
-	ld hl, GainedText
-	call PrintText
-	xor a ; party mon data
-	ld [wcc49], a
-	call LoadMonData
-	pop hl
-	ld bc, wPartyMon1Level - wPartyMon1Exp
-	add hl, bc
-	push hl
-	callba CalcLevelFromExperience
-	pop hl
-	ld a, [hl] ; current level
-	cp d
-	jp z, .nextMon ; if level didn't change, go to next mon
-	ld a, [W_CURENEMYLVL]
-	push af
-	push hl
-	ld a, d
-	ld [W_CURENEMYLVL], a
-	ld [hl], a
-	ld bc, wPartyMon1Species - wPartyMon1Level
-	add hl, bc
-	ld a, [hl] ; species
-	ld [wd0b5], a
-	ld [wd11e], a
-	call GetMonHeader
-	ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
-	add hl, bc
-	push hl
-	ld a, [hld]
-	ld c, a
-	ld b, [hl]
-	push bc ; push max HP (from before levelling up)
-	ld d, h
-	ld e, l
-	ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
-	add hl, bc
-	ld b, $1 ; consider stat exp when calculating stats
-	call CalcStats
-	pop bc ; pop max HP (from before levelling up)
-	pop hl
-	ld a, [hld]
-	sub c
-	ld c, a
-	ld a, [hl]
-	sbc b
-	ld b, a ; bc = difference between old max HP and new max HP after levelling
-	ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
-	add hl, de
-; add to the current HP the amount of max HP gained when levelling
-	ld a, [hl] ; wPartyMon1HP + 1
-	add c
-	ld [hld], a
-	ld a, [hl] ; wPartyMon1HP + 1
-	adc b
-	ld [hl], a ; wPartyMon1HP
-	ld a, [wPlayerMonNumber]
-	ld b, a
-	ld a, [wWhichPokemon]
-	cp b ; is the current mon in battle?
-	jr nz, .printGrewLevelText
-; current mon is in battle
-	ld de, wBattleMonHP
-; copy party mon HP to battle mon HP
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-; copy other stats from party mon to battle mon
-	ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
-	add hl, bc
-	push hl
-	ld de, wBattleMonLevel
-	ld bc, $b ; size of stats
-	call CopyData
-	pop hl
-	ld a, [W_PLAYERBATTSTATUS3]
-	bit 3, a ; is the mon transformed?
-	jr nz, .recalcStatChanges
-; the mon is not transformed, so update the unmodified stats
-	ld de, wPlayerMonUnmodifiedLevel
-	ld bc, $b
-	call CopyData
-.recalcStatChanges
-	xor a
-	ld [wd11e], a
-	callab CalculateModifiedStats
-	callab ApplyBurnAndParalysisPenaltiesToPlayer
-	callab ApplyBadgeStatBoosts
-	callab DrawPlayerHUDAndHPBar
-	callab PrintEmptyString
-	call SaveScreenTilesToBuffer1
-.printGrewLevelText
-	ld hl, GrewLevelText
-	call PrintText
-	xor a ; party mon data
-	ld [wcc49], a
-	call LoadMonData
-	ld d, $1
-	callab PrintStatsBox
-	call WaitForTextScrollButtonPress
-	call LoadScreenTilesFromBuffer1
-	xor a
-	ld [wcc49], a
-	ld a, [wd0b5]
-	ld [wd11e], a
-	predef LearnMoveFromLevelUp
-	ld hl, wccd3
-	ld a, [wWhichPokemon]
-	ld c, a
-	ld b, $1
-	predef FlagActionPredef
-	pop hl
-	pop af
-	ld [W_CURENEMYLVL], a
-
-.nextMon
-	ld a, [wPartyCount]
-	ld b, a
-	ld a, [wWhichPokemon]
-	inc a
-	cp b
-	jr z, .done
-	ld [wWhichPokemon], a
-	ld bc, wPartyMon2 - wPartyMon1
-	ld hl, wPartyMon1
-	call AddNTimes
-	jp .partyMonLoop
-.done
-	ld hl, wPartyGainExpFlags
-	xor a
-	ld [hl], a ; clear gain exp flags
-	ld a, [wPlayerMonNumber]
-	ld c, a
-	ld b, $1
-	push bc
-	predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
-	ld hl, wPartyFoughtCurrentEnemyFlags
-	xor a
-	ld [hl], a
-	pop bc
-	predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
-
-; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
-DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
-	ld a, [wPartyGainExpFlags]
-	ld b, a
-	xor a
-	ld c, $8
-	ld d, $0
-.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
-	xor a
-	srl b
-	adc d
-	ld d, a
-	dec c
-	jr nz, .countSetBitsLoop
-	cp $2
-	ret c ; return if only one mon is gaining exp
-	ld [wd11e], a ; store number of mons gaining exp
-	ld hl, wEnemyMonBaseStats
-	ld c, $7
-.divideLoop
-	xor a
-	ld [H_DIVIDEND], a
-	ld a, [hl]
-	ld [H_DIVIDEND + 1], a
-	ld a, [wd11e]
-	ld [H_DIVISOR], a
-	ld b, $2
-	call Divide ; divide value by number of mons gaining exp
-	ld a, [H_QUOTIENT + 3]
-	ld [hli], a
-	dec c
-	jr nz, .divideLoop
-	ret
-
-; multiplies exp by 1.5
-BoostExp: ; 5549f (15:549f)
-	ld a, [H_QUOTIENT + 2]
-	ld b, a
-	ld a, [H_QUOTIENT + 3]
-	ld c, a
-	srl b
-	rr c
-	add c
-	ld [H_QUOTIENT + 3], a
-	ld a, [H_QUOTIENT + 2]
-	adc b
-	ld [H_QUOTIENT + 2], a
-	ret
-
-GainedText: ; 554b2 (15:54b2)
-	TX_FAR _GainedText
-	db $08 ; asm
-	ld a, [wcc5b]
-	ld hl, WithExpAllText
-	and a
-	ret nz
-	ld hl, ExpPointsText
-	ld a, [wcf4d]
-	and a
-	ret z
-	ld hl, BoostedText
-	ret
-
-WithExpAllText: ; 554cb (15:54cb)
-	TX_FAR _WithExpAllText
-	db $08 ; asm
-	ld hl, ExpPointsText
-	ret
-
-BoostedText: ; 554d4 (15:54d4)
-	TX_FAR _BoostedText
-
-ExpPointsText: ; 554d8 (15:54d8)
-	TX_FAR _ExpPointsText
-	db "@"
-
-GrewLevelText: ; 554dd (15:54dd)
-	TX_FAR _GrewLevelText
-	db $0b
-	db "@"
--- a/engine/battle/16.asm
+++ /dev/null
@@ -1,238 +1,0 @@
-PrintBeginningBattleText: ; 58d99 (16:4d99)
-	ld a, [W_ISINBATTLE] ; W_ISINBATTLE
-	dec a
-	jr nz, .trainerBattle
-	ld a, [W_CURMAP] ; W_CURMAP
-	cp POKEMONTOWER_3
-	jr c, .notPokemonTower
-	cp LAVENDER_HOUSE_1
-	jr c, .pokemonTower
-.notPokemonTower
-	ld a, [wEnemyMonSpecies2]
-	call PlayCry
-	ld hl, WildMonAppearedText
-	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
-	and a
-	jr z, .notFishing
-	ld hl, HookedMonAttackedText
-.notFishing
-	jr .wildBattle
-.trainerBattle
-	call .playSFX
-	ld c, $14
-	call DelayFrames
-	ld hl, TrainerWantsToFightText
-.wildBattle
-	push hl
-	callab DrawAllPokeballs
-	pop hl
-	call PrintText
-	jr .done
-.pokemonTower
-	ld b, SILPH_SCOPE
-	call IsItemInBag
-	ld a, [wEnemyMonSpecies2]
-	ld [wcf91], a
-	cp MAROWAK
-	jr z, .isMarowak
-	ld a, b
-	and a
-	jr z, .noSilphScope
-	callab LoadEnemyMonData
-	jr .notPokemonTower
-.noSilphScope
-	ld hl, EnemyAppearedText
-	call PrintText
-	ld hl, GhostCantBeIDdText
-	call PrintText
-	jr .done
-.isMarowak
-	ld a, b
-	and a
-	jr z, .noSilphScope
-	ld hl, EnemyAppearedText
-	call PrintText
-	ld hl, UnveiledGhostText
-	call PrintText
-	callab LoadEnemyMonData
-	callab MarowakAnim
-	ld hl, WildMonAppearedText
-	call PrintText
-
-.playSFX
-	xor a
-	ld [wc0f1], a
-	ld a, $80
-	ld [wc0f2], a
-	ld a, (SFX_08_77 - SFX_Headers_08) / 3
-	call PlaySound
-	jp WaitForSoundToFinish
-.done
-	ret
-
-WildMonAppearedText: ; 58e3b (16:4e3b)
-	TX_FAR _WildMonAppearedText
-	db "@"
-
-HookedMonAttackedText: ; 58e40 (16:4e40)
-	TX_FAR _HookedMonAttackedText
-	db "@"
-
-EnemyAppearedText: ; 58e45 (16:4e45)
-	TX_FAR _EnemyAppearedText
-	db "@"
-
-TrainerWantsToFightText: ; 58e4a (16:4e4a)
-	TX_FAR _TrainerWantsToFightText
-	db "@"
-
-UnveiledGhostText: ; 58e4f (16:4e4f)
-	TX_FAR _UnveiledGhostText
-	db "@"
-
-GhostCantBeIDdText: ; 58e54 (16:4e54)
-	TX_FAR _GhostCantBeIDdText
-	db "@"
-
-PrintSendOutMonMessage: ; 58e59 (16:4e59)
-	ld hl, wEnemyMonHP
-	ld a, [hli]
-	or [hl]
-	ld hl, GoText
-	jr z, .printText
-	xor a
-	ld [H_MULTIPLICAND], a
-	ld hl, wEnemyMonHP
-	ld a, [hli]
-	ld [wcce3], a
-	ld [H_MULTIPLICAND + 1], a
-	ld a, [hl]
-	ld [wcce4], a
-	ld [H_MULTIPLICAND + 2], a
-	ld a, 25
-	ld [H_MULTIPLIER], a
-	call Multiply
-	ld hl, wEnemyMonMaxHP
-	ld a, [hli]
-	ld b, [hl]
-	srl a
-	rr b
-	srl a
-	rr b
-	ld a, b
-	ld b, $4
-	ld [H_DIVISOR], a ; enemy mon max HP divided by 4
-	call Divide
-	ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
-	ld hl, GoText ; 70% or greater
-	cp 70
-	jr nc, .printText
-	ld hl, DoItText ; 40% - 69%
-	cp 40
-	jr nc, .printText
-	ld hl, GetmText ; 10% - 39%
-	cp 10
-	jr nc, .printText
-	ld hl, EnemysWeakText ; 0% - 9%
-.printText
-	jp PrintText
-
-GoText: ; 58eae (16:4eae)
-	TX_FAR _GoText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-DoItText: ; 58eb5 (16:4eb5)
-	TX_FAR _DoItText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-GetmText: ; 58ebc (16:4ebc)
-	TX_FAR _GetmText
-	db $08 ; asm
-	jr PrintPlayerMon1Text
-
-EnemysWeakText: ; 58ec3 (16:4ec3)
-	TX_FAR _EnemysWeakText
-	db $08 ; asm
-
-PrintPlayerMon1Text:
-	ld hl, PlayerMon1Text
-	ret
-
-PlayerMon1Text: ; 58ecc (16:4ecc)
-	TX_FAR _PlayerMon1Text
-	db "@"
-
-RetreatMon: ; 58ed1 (16:4ed1)
-	ld hl, PlayerMon2Text
-	jp PrintText
-
-PlayerMon2Text: ; 58ed7 (16:4ed7)
-	TX_FAR _PlayerMon2Text
-	db $08 ; asm
-	push de
-	push bc
-	ld hl, wEnemyMonHP + 1
-	ld de, wcce4
-	ld b, [hl]
-	dec hl
-	ld a, [de]
-	sub b
-	ld [$ff98], a
-	dec de
-	ld b, [hl]
-	ld a, [de]
-	sbc b
-	ld [$ff97], a
-	ld a, $19
-	ld [H_POWEROFTEN], a
-	call Multiply
-	ld hl, wEnemyMonMaxHP
-	ld a, [hli]
-	ld b, [hl]
-	srl a
-	rr b
-	srl a
-	rr b
-	ld a, b
-	ld b, $4
-	ld [H_POWEROFTEN], a
-	call Divide
-	pop bc
-	pop de
-	ld a, [$ff98]
-	ld hl, EnoughText
-	and a
-	ret z
-	ld hl, ComeBackText
-	cp $1e
-	ret c
-	ld hl, OKExclamationText
-	cp $46
-	ret c
-	ld hl, GoodText
-	ret
-
-EnoughText: ; 58f25 (16:4f25)
-	TX_FAR _EnoughText
-	db $08 ; asm
-	jr PrintComeBackText
-
-OKExclamationText: ; 58f2c (16:4f2c)
-	TX_FAR _OKExclamationText
-	db $08 ; asm
-	jr PrintComeBackText
-
-GoodText: ; 58f33 (16:4f33)
-	TX_FAR _GoodText
-	db $08 ; asm
-	jr PrintComeBackText
-
-PrintComeBackText: ; 58f3a (16:4f3a)
-	ld hl, ComeBackText
-	ret
-
-ComeBackText: ; 58f3e (16:4f3e)
-	TX_FAR _ComeBackText
-	db "@"
--- a/engine/battle/1a.asm
+++ /dev/null
@@ -1,43 +1,0 @@
-DecrementPP: ; 68000 (1a:4000)
-; after using a move, decrement pp in battle and (if not transformed?) in party
-	ld a, [de]
-	cp a, STRUGGLE
-	ret z                ; if the pokemon is using "struggle", there's nothing to do
-	                     ; we don't decrement PP for "struggle"
-	ld hl, W_PLAYERBATTSTATUS1
-	ld a, [hli]          ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
-	                     ; W_PLAYERBATTSTATUS2 status flags later
-	and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
-	ret nz               ; if any of these statuses are true, don't decrement PP
-	bit UsingRage, [hl]         
-	ret nz               ; don't decrement PP either if Pokemon is using Rage
-	ld hl, wBattleMonPP  ; PP of first move (in battle)
-	
-; decrement PP in the battle struct	
-	call .DecrementPP    
-	
-; decrement PP in the party struct	
-	ld a, [W_PLAYERBATTSTATUS3]        
-	bit Transformed, a
-	ret nz               ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
-	                     ; separately from the "Pokemon in your party's" PP.  This is
-	                     ; duplication -- in all cases *other* than Pokemon with Transform.
-	                     ; Normally, this means we have to go on and make the same
-	                     ; modification to the "party's pokemon" PP that we made to the
-	                     ; "current pokemon's" PP.  But, if we're dealing with a Transformed
-	                     ; Pokemon, it has separate PP for the move set that it copied from
-	                     ; its opponent, which is *not* the same as its real PP as part of your
-	                     ; party.  So we return, and don't do that part.
-
-	ld hl, wPartyMon1PP  ; PP of first move (in party)
-	ld a, [wPlayerMonNumber] ; which mon in party is active
-	ld bc, wPartyMon2 - wPartyMon1 
-	call AddNTimes       ; calculate address of the mon to modify
-.DecrementPP
-	ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
-	ld c, a
-	ld b, 0
-	add hl ,bc           ; calculate the address in memory of the PP we need to decrement
-	                     ; based on the move chosen.
-	dec [hl]             ; Decrement PP
-	ret
--- a/engine/battle/1c.asm
+++ /dev/null
@@ -1,905 +1,0 @@
-MarowakAnim: ; 708ca (1c:48ca)
-; animate the ghost being unveiled as a Marowak
-	ld a, $e4
-	ld [rOBP1], a
-	call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
-; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
-	hlCoord 12, 0
-	ld bc, $707
-	call ClearScreenArea
-	call Delay3
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
-; replace ghost pic with Marowak in BG
-	ld a, MAROWAK
-	ld [wHPBarMaxHP], a
-	ld a, $1
-	ld [H_WHOSETURN], a
-	callab Func_79793
- ; alternate between black and light grey 8 times.
- ; this makes the ghost's body appear to flash
-	ld d, $80
-	call FlashSprite8Times
-.fadeOutGhostLoop
-	ld c, 10
-	call DelayFrames
-	ld a, [rOBP1]
-	sla a
-	sla a
-	ld [rOBP1], a
-	jr nz, .fadeOutGhostLoop
-	call ClearSprites
-	call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
-	ld b, $e4
-.fadeInMarowakLoop
-	ld c, 10
-	call DelayFrames
-	ld a, [rOBP1]
-	srl b
-	rra
-	srl b
-	rra
-	ld [rOBP1], a
-	ld a, b
-	and a
-	jr nz, .fadeInMarowakLoop
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
-	call Delay3
-	jp ClearSprites
-
-; copies a mon pic's  from background VRAM to sprite VRAM and sets up OAM
-CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
-	ld de, vFrontPic
-	ld hl, vSprites
-	ld bc, 7 * 7
-	call CopyVideoData
-	ld a, $10
-	ld [W_BASECOORDY], a
-	ld a, $70
-	ld [W_BASECOORDX], a
-	ld hl, wOAMBuffer
-	ld bc, $606
-	ld d, $8
-.oamLoop
-	push bc
-	ld a, [W_BASECOORDY]
-	ld e, a
-.oamInnerLoop
-	ld a, e
-	add $8
-	ld e, a
-	ld [hli], a
-	ld a, [W_BASECOORDX]
-	ld [hli], a
-	ld a, d
-	ld [hli], a
-	ld a, $10 ; use OBP1
-	ld [hli], a
-	inc d
-	dec c
-	jr nz, .oamInnerLoop
-	inc d
-	ld a, [W_BASECOORDX]
-	add $8
-	ld [W_BASECOORDX], a
-	pop bc
-	dec b
-	jr nz, .oamLoop
-	ret
-
-BattleTransition: ; 7096d (1c:496d)
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	call Delay3
-	xor a
-	ld [hWY], a
-	dec a
-	ld [wUpdateSpritesEnabled], a
-	call DelayFrame
-	ld hl, wSpriteStateData1 + 2
-	ld a, [H_DOWNARROWBLINKCNT2]
-	ld c, a
-	ld b, $0
-	ld de, $10
-.loop1
-	ld a, [hl]
-	cp $ff
-	jr z, .skip1
-	inc b
-.skip1
-	add hl, de
-	dec c
-	jr nz, .loop1
-	ld hl, wOAMBuffer + $10
-	ld c, $9
-.loop2
-	ld a, b
-	swap a
-	cp l
-	jr z, .skip2
-	push hl
-	push bc
-	ld bc, $10
-	xor a
-	call FillMemory
-	pop bc
-	pop hl
-.skip2
-	ld de, $10
-	add hl, de
-	dec c
-	jr nz, .loop2
-	call Delay3
-	call LoadBattleTransitionTile
-	ld bc, $0
-	ld a, [wLinkState]
-	cp LINK_STATE_BATTLING
-	jr z, .linkBattle
-	call GetBattleTransitionID_WildOrTrainer
-	call GetBattleTransitionID_CompareLevels
-	call GetBattleTransitionID_IsDungeonMap
-.linkBattle
-	ld hl, BattleTransitions
-	add hl, bc
-	add hl, bc
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp [hl]
-
-; the three GetBattleTransitionID functions set the first
-; three bits of c, which determines what transition animation
-; to play at the beginning of a battle
-; bit 0: set if trainer battle
-; bit 1: set if enemy is at least 3 levels higher than player
-; bit 2: set if dungeon map
-BattleTransitions: ; 709d2 (1c:49d2)
-	dw BattleTransition_DoubleCircle      ; %000
-	dw BattleTransition_Spiral            ; %001
-	dw BattleTransition_Circle            ; %010
-	dw BattleTransition_Spiral            ; %011
-	dw BattleTransition_HorizontalStripes ; %100
-	dw BattleTransition_Shrink            ; %101
-	dw BattleTransition_VerticalStripes   ; %110
-	dw BattleTransition_Split             ; %111
-
-GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
-	ld a, [W_CUROPPONENT]
-	cp $c8
-	jr nc, .trainer
-	res 0, c
-	ret
-.trainer
-	set 0, c
-	ret
-
-GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
-	ld hl, wPartyMon1HP
-.faintedLoop
-	ld a, [hli]
-	or [hl]
-	jr nz, .notFainted
-	ld de, wPartyMon2 - (wPartyMon1 + 1)
-	add hl, de
-	jr .faintedLoop
-.notFainted
-	ld de, wPartyMon1Level - (wPartyMon1HP + 1)
-	add hl, de
-	ld a, [hl]
-	add $3
-	ld e, a
-	ld a, [W_CURENEMYLVL]
-	sub e
-	jr nc, .highLevelEnemy
-	res 1, c
-	ld a, $1
-	ld [wcd47], a
-	ret
-.highLevelEnemy
-	set 1, c
-	xor a
-	ld [wcd47], a
-	ret
-
-; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
-; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
-; and SILPH_CO_[9-11]F as dungeon maps
-GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
-	ld a, [W_CURMAP]
-	ld e, a
-	ld hl, DungeonMaps1
-.loop1
-	ld a, [hli]
-	cp $ff
-	jr z, .noMatch1
-	cp e
-	jr nz, .loop1
-.match
-	set 2, c
-	ret
-.noMatch1
-	ld hl, DungeonMaps2
-.loop2
-	ld a, [hli]
-	cp $ff
-	jr z, .noMatch2
-	ld d, a
-	ld a, [hli]
-	cp e
-	jr c, .loop2
-	ld a, e
-	cp d
-	jr nc, .match
-.noMatch2
-	res 2, c
-	ret
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is equal to one of these maps
-DungeonMaps1: ; 70a3f (1c:4a3f)
-	db VIRIDIAN_FOREST
-	db ROCK_TUNNEL_1
-	db SEAFOAM_ISLANDS_1
-	db ROCK_TUNNEL_2
-	db $FF
-
-; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
-; is in between or equal to each pair of maps
-DungeonMaps2: ; 70a44 (1c:4a44)
-	; all MT_MOON maps
-	db MT_MOON_1
-	db MT_MOON_3
-
-	; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
-	db SS_ANNE_1
-	db HALL_OF_FAME
-
-	; all POKEMONTOWER maps and Lavender Town buildings
-	db LAVENDER_POKECENTER
-	db LAVENDER_HOUSE_2
-
-	; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
-	; except for SILPH_CO_1F
-	db SILPH_CO_2F
-	db UNKNOWN_DUNGEON_1
-	db $FF
-
-LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
-	ld hl, vChars1 + $7f0
-	ld de, BattleTransitionTile
-	ld bc, (BANK(BattleTransitionTile) << 8) + $01
-	jp CopyVideoData
-
-BattleTransitionTile: ; 70a59 (1c:4a59)
-	INCBIN "gfx/battle_transition.2bpp"
-
-BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
-	ld a, $ff
-	ld [rBGP], a
-	ld [rOBP0], a
-	ld [rOBP1], a
-	ret
-
-; for non-dungeon trainer battles
-; called regardless of mon levels, but does an
-; outward spiral if enemy is at least 3 levels
-; higher than player and does an inward spiral otherwise
-BattleTransition_Spiral: ; 70a72 (1c:4a72)
-	ld a, [wcd47]
-	and a
-	jr z, .outwardSpiral
-	call BattleTransition_InwardSpiral
-	jr .done
-.outwardSpiral
-	hlCoord 10, 10
-	ld a, $3
-	ld [wd09f], a
-	ld a, l
-	ld [wd09b], a
-	ld a, h
-	ld [wd09a], a
-	ld b, $78
-.loop1
-	ld c, $3
-.loop2
-	push bc
-	call BattleTransition_OutwardSpiral_
-	pop bc
-	dec c
-	jr nz, .loop2
-	call DelayFrame
-	dec b
-	jr nz, .loop1
-.done
-	call BattleTransition_BlackScreen
-	xor a
-	ld [wd09b], a
-	ld [wd09a], a
-	ret
-
-BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
-	ld a, $7
-	ld [wWhichTrade], a
-	ld hl, wTileMap
-	ld c, $11
-	ld de, $14
-	call BattleTransition_InwardSpiral_
-	inc c
-	jr .skip
-.loop
-	ld de, $14
-	call BattleTransition_InwardSpiral_
-.skip
-	inc c
-	ld de, $1
-	call BattleTransition_InwardSpiral_
-	dec c
-	dec c
-	ld de, $ffec
-	call BattleTransition_InwardSpiral_
-	inc c
-	ld de, rIE
-	call BattleTransition_InwardSpiral_
-	dec c
-	dec c
-	ld a, c
-	and a
-	jr nz, .loop
-	ret
-
-BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
-	push bc
-.loop
-	ld [hl], $ff
-	add hl, de
-	push bc
-	ld a, [wWhichTrade]
-	dec a
-	jr nz, .skip
-	call BattleTransition_TransferDelay3
-	ld a, $7
-.skip
-	ld [wWhichTrade], a
-	pop bc
-	dec c
-	jr nz, .loop
-	pop bc
-	ret
-
-BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
-	ld bc, $ffec
-	ld de, $14
-	ld a, [wd09b]
-	ld l, a
-	ld a, [wd09a]
-	ld h, a
-	ld a, [wd09f]
-	cp $0
-	jr z, .zero
-	cp $1
-	jr z, .one
-	cp $2
-	jr z, .two
-	cp $3
-	jr z, .three
-.done1
-	ld [hl], $ff
-.done2_
-	ld a, l
-	ld [wd09b], a
-	ld a, h
-	ld [wd09a], a
-	ret
-.zero
-	dec hl
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	inc hl
-	add hl, bc
-	jr .done1
-.one
-	add hl, de
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	add hl, bc
-	dec hl
-	jr .done1
-.two
-	inc hl
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	dec hl
-	add hl, de
-	jr .done1
-.three
-	add hl, bc
-	ld a, [hl]
-	cp $ff
-	jr nz, .done2
-	add hl, de
-	inc hl
-	jr .done1
-.done2
-	ld [hl], $ff
-	ld a, [wd09f]
-	inc a
-	cp $4
-	jr nz, .skip
-	xor a
-.skip
-	ld [wd09f], a
-	jr .done2_
-
-FlashScreen:
-BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
-	ld hl, BattleTransition_FlashScreenPalettes
-.loop
-	ld a, [hli]
-	cp $1
-	jr z, .done
-	ld [rBGP], a
-	ld c, $2
-	call DelayFrames
-	jr .loop
-.done
-	dec b
-	jr nz, BattleTransition_FlashScreen_
-	ret
-
-BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
-	db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
-	db $01 ; terminator
-
-; used for low level trainer dungeon battles
-BattleTransition_Shrink: ; 70b7f (1c:4b7f)
-	ld c, $9
-.loop
-	push bc
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	hlCoord 0, 7
-	deCoord 0, 8
-	ld bc, $ffd8
-	call BattleTransition_CopyTiles1
-	hlCoord 0, 10
-	deCoord 0, 9
-	ld bc, $28
-	call BattleTransition_CopyTiles1
-	hlCoord 8, 0
-	deCoord 9, 0
-	ld bc, $fffe
-	call BattleTransition_CopyTiles2
-	hlCoord 11, 0
-	deCoord 10, 0
-	ld bc, $2
-	call BattleTransition_CopyTiles2
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ld c, $6
-	call DelayFrames
-	pop bc
-	dec c
-	jr nz, .loop
-	call BattleTransition_BlackScreen
-	ld c, $a
-	jp DelayFrames
-
-; used for high level trainer dungeon battles
-BattleTransition_Split: ; 70bca (1c:4bca)
-	ld c, $9
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	hlCoord 0, 16
-	deCoord 0, 17
-	ld bc, $ffd8
-	call BattleTransition_CopyTiles1
-	hlCoord 0, 1
-	ld de, wTileMap
-	ld bc, $28
-	call BattleTransition_CopyTiles1
-	hlCoord 18, 0
-	deCoord 19, 0
-	ld bc, $fffe
-	call BattleTransition_CopyTiles2
-	hlCoord 1, 0
-	ld de, wTileMap
-	ld bc, $2
-	call BattleTransition_CopyTiles2
-	call BattleTransition_TransferDelay3
-	call Delay3
-	pop bc
-	dec c
-	jr nz, .loop
-	call BattleTransition_BlackScreen
-	ld c, $a
-	jp DelayFrames
-
-BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
-	ld a, c
-	ld [wWhichTrade], a
-	ld a, b
-	ld [wTrainerEngageDistance], a
-	ld c, $8
-.loop1
-	push bc
-	push hl
-	push de
-	ld bc, $14
-	call CopyData
-	pop hl
-	pop de
-	ld a, [wWhichTrade]
-	ld c, a
-	ld a, [wTrainerEngageDistance]
-	ld b, a
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop1
-	ld l, e
-	ld h, d
-	ld a, $ff
-	ld c, $14
-.loop2
-	ld [hli], a
-	dec c
-	jr nz, .loop2
-	ret
-
-BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
-	ld a, c
-	ld [wWhichTrade], a
-	ld a, b
-	ld [wTrainerEngageDistance], a
-	ld c, $9
-.loop1
-	push bc
-	push hl
-	push de
-	ld c, $12
-.loop2
-	ld a, [hl]
-	ld [de], a
-	ld a, e
-	add $14
-	jr nc, .noCarry1
-	inc d
-.noCarry1
-	ld e, a
-	ld a, l
-	add $14
-	jr nc, .noCarry2
-	inc h
-.noCarry2
-	ld l, a
-	dec c
-	jr nz, .loop2
-	pop hl
-	pop de
-	ld a, [wWhichTrade]
-	ld c, a
-	ld a, [wTrainerEngageDistance]
-	ld b, a
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop1
-	ld l, e
-	ld h, d
-	ld de, $14
-	ld c, $12
-.loop3
-	ld [hl], $ff
-	add hl, de
-	dec c
-	jr nz, .loop3
-	ret
-
-; used for high level wild dungeon battles
-BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
-	ld c, $12
-	ld hl, wTileMap
-	deCoord 1, 17
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	call BattleTransition_VerticalStripes_
-	pop hl
-	call BattleTransition_VerticalStripes_
-	call BattleTransition_TransferDelay3
-	pop hl
-	ld bc, $ffec
-	add hl, bc
-	ld e, l
-	ld d, h
-	pop hl
-	ld bc, $14
-	add hl, bc
-	pop bc
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
-	ld c, $a
-.loop
-	ld [hl], $ff
-	inc hl
-	inc hl
-	dec c
-	jr nz, .loop
-	ret
-
-; used for low level wild dungeon battles
-BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
-	ld c, $14
-	ld hl, wTileMap
-	deCoord 19, 1
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	call BattleTransition_HorizontalStripes_
-	pop hl
-	call BattleTransition_HorizontalStripes_
-	call BattleTransition_TransferDelay3
-	pop de
-	pop hl
-	pop bc
-	inc hl
-	dec de
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
-	ld c, $9
-	ld de, $28
-.loop
-	ld [hl], $ff
-	add hl, de
-	dec c
-	jr nz, .loop
-	ret
-
-; used for high level wild non-dungeon battles
-; makes one full circle around the screen
-; by animating each half circle one at a time
-BattleTransition_Circle: ; 70ce4 (1c:4ce4)
-	call BattleTransition_FlashScreen
-	ld bc, $000a
-	ld hl, BattleTransition_HalfCircle1
-	call BattleTransition_Circle_Sub1
-	ld c, $a
-	ld b, $1
-	ld hl, BattleTransition_HalfCircle2
-	call BattleTransition_Circle_Sub1
-	jp BattleTransition_BlackScreen
-
-BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
-	ld b, $3
-	call BattleTransition_FlashScreen_
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ret
-
-BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
-	push bc
-	push hl
-	ld a, b
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld bc, $0005
-	add hl, bc
-	call BattleTransition_TransferDelay3
-	pop bc
-	dec c
-	jr nz, BattleTransition_Circle_Sub1
-	ret
-
-BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
-	ld a, $1
-	ld [H_AUTOBGTRANSFERENABLED], a
-	call Delay3
-	xor a
-	ld [H_AUTOBGTRANSFERENABLED], a
-	ret
-
-; used for low level wild non-dungeon battles
-; makes two half circles around the screen
-; by animating both half circles at the same time
-BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
-	call BattleTransition_FlashScreen
-	ld c, $a
-	ld hl, BattleTransition_HalfCircle1
-	ld de, BattleTransition_HalfCircle2
-.loop
-	push bc
-	push hl
-	push de
-	push de
-	xor a
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld a, $1
-	call BattleTransition_Circle_Sub2
-	pop hl
-	ld bc, $5
-	add hl, bc
-	ld e, l
-	ld d, h
-	pop hl
-	add hl, bc
-	call BattleTransition_TransferDelay3
-	pop bc
-	dec c
-	jr nz, .loop
-	jp BattleTransition_BlackScreen
-
-BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
-	ld [wWhichTrade], a
-	ld a, [hli]
-	ld [wTrainerEngageDistance], a
-	ld a, [hli]
-	ld e, a
-	ld a, [hli]
-	ld d, a
-	ld a, [hli]
-	ld h, [hl]
-	ld l, a
-	jp BattleTransition_Circle_Sub3
-
-BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
-	db $01
-	dw BattleTransition_CircleData1
-	dwCoord 18, 6
-
-	db $01
-	dw BattleTransition_CircleData2
-	dwCoord 19, 3
-
-	db $01
-	dw BattleTransition_CircleData3
-	dwCoord 18, 0
-
-	db $01
-	dw BattleTransition_CircleData4
-	dwCoord 14, 0
-
-	db $01
-	dw BattleTransition_CircleData5
-	dwCoord 10, 0
-
-	db $00
-	dw BattleTransition_CircleData5
-	dwCoord 9, 0
-
-	db $00
-	dw BattleTransition_CircleData4
-	dwCoord 5, 0
-
-	db $00
-	dw BattleTransition_CircleData3
-	dwCoord 1, 0
-
-	db $00
-	dw BattleTransition_CircleData2
-	dwCoord 0, 3
-
-	db $00
-	dw BattleTransition_CircleData1
-	dwCoord 1, 6
-
-BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
-	db $00
-	dw BattleTransition_CircleData1
-	dwCoord 1, 11
-
-	db $00
-	dw BattleTransition_CircleData2
-	dwCoord 0, 14
-
-	db $00
-	dw BattleTransition_CircleData3
-	dwCoord 1, 17
-
-	db $00
-	dw BattleTransition_CircleData4
-	dwCoord 5, 17
-
-	db $00
-	dw BattleTransition_CircleData5
-	dwCoord 9, 17
-
-	db $01
-	dw BattleTransition_CircleData5
-	dwCoord 10, 17
-
-	db $01
-	dw BattleTransition_CircleData4
-	dwCoord 14, 17
-
-	db $01
-	dw BattleTransition_CircleData3
-	dwCoord 18, 17
-
-	db $01
-	dw BattleTransition_CircleData2
-	dwCoord 19, 14
-
-	db $01
-	dw BattleTransition_CircleData1
-	dwCoord 18, 11
-
-BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
-	push hl
-	ld a, [de]
-	ld c, a
-	inc de
-.loop1
-	ld [hl], $ff
-	ld a, [wTrainerEngageDistance]
-	and a
-	jr z, .skip1
-	inc hl
-	jr .skip2
-.skip1
-	dec hl
-.skip2
-	dec c
-	jr nz, .loop1
-	pop hl
-	ld a, [wWhichTrade]
-	and a
-	ld bc, $14
-	jr z, .skip3
-	ld bc, $ffec
-.skip3
-	add hl, bc
-	ld a, [de]
-	inc de
-	cp $ff
-	ret z
-	and a
-	jr z, BattleTransition_Circle_Sub3
-	ld c, a
-.loop2
-	ld a, [wTrainerEngageDistance]
-	and a
-	jr z, .skip4
-	dec hl
-	jr .skip5
-.skip4
-	inc hl
-.skip5
-	dec c
-	jr nz, .loop2
-	jr BattleTransition_Circle_Sub3
-
-BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
-	db $02,$03,$05,$04,$09,$FF
-
-BattleTransition_CircleData2: ; 70e04 (1c:4e04)
-	db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
-
-BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
-	db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
-
-BattleTransition_CircleData4: ; 70e20 (1c:4e20)
-	db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
-
-BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
-	db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- a/engine/battle/4.asm
+++ /dev/null
@@ -1,77 +1,0 @@
-; returns whether the player is one tile outside the map in Z
-IsPlayerJustOutsideMap: ; 128d8 (4:68d8)
-	ld a, [W_YCOORD]
-	ld b, a
-	ld a, [W_CURMAPHEIGHT]
-	call .compareCoordWithMapDimension
-	ret z
-	ld a, [W_XCOORD]
-	ld b, a
-	ld a, [W_CURMAPWIDTH]
-.compareCoordWithMapDimension
-	add a
-	cp b
-	ret z
-	inc b
-	ret
-
-DrawHP: ; 128ef (4:68ef)
-	call GetPredefRegisters
-	ld a, $1
-	jr DrawHP_
-
-DrawHP2: ; 128f6 (4:68f6)
-	call GetPredefRegisters
-	ld a, $2
-
-DrawHP_: ; 128fb (4:68fb)
-	ld [wHPBarType], a
-	push hl
-	ld a, [wLoadedMonHP]
-	ld b, a
-	ld a, [wLoadedMonHP + 1]
-	ld c, a
-	or b
-	jr nz, .nonzeroHP
-	xor a
-	ld c, a
-	ld e, a
-	ld a, $6
-	ld d, a
-	jp .drawHPBarAndPrintFraction
-.nonzeroHP
-	ld a, [wLoadedMonMaxHP]
-	ld d, a
-	ld a, [wLoadedMonMaxHP + 1]
-	ld e, a
-	predef HPBarLength
-	ld a, $6
-	ld d, a
-	ld c, a
-.drawHPBarAndPrintFraction
-	pop hl
-	push de
-	push hl
-	push hl
-	call DrawHPBar
-	pop hl
-	ld a, [hFlags_0xFFF6]
-	bit 0, a
-	jr z, .printFractionBelowBar
-	ld bc, $9 ; right of bar
-	jr .printFraction
-.printFractionBelowBar
-	ld bc, SCREEN_WIDTH + 1 ; below bar
-.printFraction
-	add hl, bc
-	ld de, wLoadedMonHP
-	ld bc, $203
-	call PrintNumber
-	ld a, "/"
-	ld [hli], a
-	ld de, wLoadedMonMaxHP
-	ld bc, $203
-	call PrintNumber
-	pop hl
-	pop de
-	ret
--- a/engine/battle/4_2.asm
+++ /dev/null
@@ -1,413 +1,0 @@
-EndOfBattle: ; 137aa (4:77aa)
-	ld a, [wLinkState]
-	cp LINK_STATE_BATTLING
-	jr nz, .notLinkBattle
-; link battle
-	ld a, [wEnemyMonPartyPos]
-	ld hl, wEnemyMon1Status
-	ld bc, wEnemyMon2 - wEnemyMon1
-	call AddNTimes
-	ld a, [wEnemyMonStatus]
-	ld [hl], a
-	call ClearScreen
-	callab DisplayLinkBattleVersusTextBox
-	ld a, [wBattleResult]
-	cp $1
-	ld de, YouWinText
-	jr c, .placeWinOrLoseString
-	ld de, YouLoseText
-	jr z, .placeWinOrLoseString
-	ld de, DrawText
-.placeWinOrLoseString
-	hlCoord 6, 8
-	call PlaceString
-	ld c, $c8
-	call DelayFrames
-	jr .evolution
-.notLinkBattle
-	ld a, [wBattleResult]
-	and a
-	jr nz, .resetVariables
-	ld hl, wTotalPayDayMoney
-	ld a, [hli]
-	or [hl]
-	inc hl
-	or [hl]
-	jr z, .evolution ; if pay day money is 0, jump
-	ld de, wPlayerMoney + 2
-	ld c, $3
-	predef AddBCDPredef
-	ld hl, PickUpPayDayMoneyText
-	call PrintText
-.evolution
-	xor a
-	ld [wccd4], a
-	predef EvolutionAfterBattle
-.resetVariables
-	xor a
-	ld [wLowHealthAlarm], a ;disable low health alarm
-	ld [wc02a], a
-	ld [W_ISINBATTLE], a
-	ld [W_BATTLETYPE], a
-	ld [W_MOVEMISSED], a
-	ld [W_CUROPPONENT], a
-	ld [wd11f], a
-	ld [wNumRunAttempts], a
-	ld [wEscapedFromBattle], a
-	ld hl, wcc2b
-	ld [hli], a
-	ld [hli], a
-	ld [hli], a
-	ld [hl], a
-	ld [wListScrollOffset], a
-	ld hl, wPlayerStatsToDouble
-	ld b, $18
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	ld hl, wd72c
-	set 0, [hl]
-	call WaitForSoundToFinish
-	call GBPalWhiteOut
-	ld a, $ff
-	ld [wDestinationWarpID], a
-	ret
-
-YouWinText: ; 13853 (4:7853)
-	db "YOU WIN@"
-
-YouLoseText: ; 1385b (4:785b)
-	db "YOU LOSE@"
-
-DrawText: ; 13864 (4:7864)
-	db "  DRAW@"
-
-PickUpPayDayMoneyText: ; 1386b (4:786b)
-	TX_FAR _PickUpPayDayMoneyText
-	db "@"
-
-; try to initiate a wild pokemon encounter
-; returns success in Z
-TryDoWildEncounter: ; 13870 (4:7870)
-	ld a, [wNPCMovementScriptPointerTableNum]
-	and a
-	ret nz
-	ld a, [wd736]
-	and a
-	ret nz
-	callab IsPlayerStandingOnDoorTileOrWarpTile
-	jr nc, .notStandingOnDoorOrWarpTile
-.CantEncounter
-	ld a, $1
-	and a
-	ret
-.notStandingOnDoorOrWarpTile
-	callab IsPlayerJustOutsideMap
-	jr z, .CantEncounter
-	ld a, [wRepelRemainingSteps]
-	and a
-	jr z, .asm_1389e
-	dec a
-	jr z, .lastRepelStep
-	ld [wRepelRemainingSteps], a
-.asm_1389e
-; determine if wild pok�mon can appear in the half-block we�re standing in	
-; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile?
-	hlCoord 9, 9
-	ld c, [hl]
-	ld a, [W_GRASSTILE]
-	cp c
-	ld a, [W_GRASSRATE]
-	jr z, .CanEncounter
-	ld a, $14 ; in all tilesets with a water tile, this is its id
-	cp c
-	ld a, [W_WATERRATE]
-	jr z, .CanEncounter
-; even if not in grass/water, standing anywhere we can encounter pok�mon
-; so long as the map is �indoor� and has wild pok�mon defined.
-; �as long as it�s not Viridian Forest or Safari Zone.
-	ld a, [W_CURMAP]
-	cp REDS_HOUSE_1F ; is this an indoor map?
-	jr c, .CantEncounter2
-	ld a, [W_CURMAPTILESET]
-	cp FOREST ; Viridian Forest/Safari Zone
-	jr z, .CantEncounter2
-	ld a, [W_GRASSRATE]
-.CanEncounter
-; compare encounter chance with a random number to determine if there will be an encounter
-	ld b, a
-	ld a, [hRandomAdd]
-	cp b
-	jr nc, .CantEncounter2
-	ld a, [hRandomSub]
-	ld b, a
-	ld hl, WildMonEncounterSlotChances
-.determineEncounterSlot
-	ld a, [hli]
-	cp b
-	jr nc, .gotEncounterSlot
-	inc hl
-	jr .determineEncounterSlot
-.gotEncounterSlot
-; determine which wild pok�mon (grass or water) can appear in the half-block we�re standing in
-	ld c, [hl]
-	ld hl, W_GRASSMONS
-	aCoord 8, 9	
-	cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile?	
-	jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default
-	ld hl, W_WATERMONS
-; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not,
-; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters.	
-.gotWildEncounterType
-	ld b, $0
-	add hl, bc
-	ld a, [hli]
-	ld [W_CURENEMYLVL], a
-	ld a, [hl]
-	ld [wcf91], a
-	ld [wEnemyMonSpecies2], a
-	ld a, [wRepelRemainingSteps]
-	and a
-	jr z, .willEncounter
-	ld a, [wPartyMon1Level]
-	ld b, a
-	ld a, [W_CURENEMYLVL]
-	cp b
-	jr c, .CantEncounter2 ; repel prevents encounters if the leading party mon's level is higher than the wild mon
-	jr .willEncounter
-.lastRepelStep
-	ld [wRepelRemainingSteps], a
-	ld a, $d2
-	ld [H_DOWNARROWBLINKCNT2], a
-	call EnableAutoTextBoxDrawing
-	call DisplayTextID
-.CantEncounter2
-	ld a, $1
-	and a
-	ret
-.willEncounter
-	xor a
-	ret
-
-WildMonEncounterSlotChances: ; 13918 (4:7918)
-; There are 10 slots for wild pokemon, and this is the table that defines how common each of
-; those 10 slots is. A random number is generated and then the first byte of each pair in this
-; table is compared against that random number. If the random number is less than or equal
-; to the first byte, then that slot is chosen.  The second byte is double the slot number.
-	db $32, $00 ; 51/256 = 19.9% chance of slot 0
-	db $65, $02 ; 51/256 = 19.9% chance of slot 1
-	db $8C, $04 ; 39/256 = 15.2% chance of slot 2
-	db $A5, $06 ; 25/256 =  9.8% chance of slot 3
-	db $BE, $08 ; 25/256 =  9.8% chance of slot 4
-	db $D7, $0A ; 25/256 =  9.8% chance of slot 5
-	db $E4, $0C ; 13/256 =  5.1% chance of slot 6
-	db $F1, $0E ; 13/256 =  5.1% chance of slot 7
-	db $FC, $10 ; 11/256 =  4.3% chance of slot 8
-	db $FF, $12 ;  3/256 =  1.2% chance of slot 9
-
-RecoilEffect_: ; 1392c (4:792c)
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [W_PLAYERMOVENUM]
-	ld hl, wBattleMonMaxHP
-	jr z, .asm_1393d
-	ld a, [W_ENEMYMOVENUM]
-	ld hl, wEnemyMonMaxHP
-.asm_1393d
-	ld d, a
-	ld a, [W_DAMAGE]
-	ld b, a
-	ld a, [W_DAMAGE + 1]
-	ld c, a
-	srl b
-	rr c
-	ld a, d
-	cp STRUGGLE
-	jr z, .asm_13953
-	srl b
-	rr c
-.asm_13953
-	ld a, b
-	or c
-	jr nz, .asm_13958
-	inc c
-.asm_13958
-	ld a, [hli]
-	ld [wHPBarMaxHP+1], a
-	ld a, [hl]
-	ld [wHPBarMaxHP], a
-	push bc
-	ld bc, $fff2
-	add hl, bc
-	pop bc
-	ld a, [hl]
-	ld [wHPBarOldHP], a
-	sub c
-	ld [hld], a
-	ld [wHPBarNewHP], a
-	ld a, [hl]
-	ld [wHPBarOldHP+1], a
-	sbc b
-	ld [hl], a
-	ld [wHPBarNewHP+1], a
-	jr nc, .asm_13982
-	xor a
-	ld [hli], a
-	ld [hl], a
-	ld hl, wHPBarNewHP
-	ld [hli], a
-	ld [hl], a
-.asm_13982
-	hlCoord 10, 9
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, $1
-	jr z, .asm_13990
-	hlCoord 2, 2
-	xor a
-.asm_13990
-	ld [wHPBarType], a
-	predef UpdateHPBar2
-	ld hl, HitWithRecoilText
-	jp PrintText
-HitWithRecoilText: ; 1399e (4:799e)
-	TX_FAR _HitWithRecoilText
-	db "@"
-
-ConversionEffect_: ; 139a3 (4:79a3)
-	ld hl, wEnemyMonType1
-	ld de, wBattleMonType1
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [W_ENEMYBATTSTATUS1]
-	jr z, .asm_139b8
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-	ld a, [W_PLAYERBATTSTATUS1]
-.asm_139b8
-	bit Invulnerable, a ; is mon immune to typical attacks (dig/fly)
-	jr nz, PrintButItFailedText
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	ld hl, PlayCurrentMoveAnimation
-	call CallBankF
-	ld hl, ConvertedTypeText
-	jp PrintText
-
-ConvertedTypeText: ; 139cd (4:79cd)
-	TX_FAR _ConvertedTypeText
-	db "@"
-
-PrintButItFailedText: ; 139d2 (4:79d2)
-	ld hl, PrintButItFailedText_
-CallBankF: ; 139d5 (4:79d5)
-	ld b, BANK(PrintButItFailedText_)
-	jp Bankswitch
-
-HazeEffect_: ; 139da (4:79da)
-	ld a, $7
-	ld hl, wPlayerMonAttackMod
-	call ResetStatMods
-	ld hl, wEnemyMonAttackMod
-	call ResetStatMods
-	ld hl, wPlayerMonUnmodifiedAttack
-	ld de, wBattleMonAttack
-	call ResetStats
-	ld hl, wEnemyMonUnmodifiedAttack
-	ld de, wEnemyMonAttack
-	call ResetStats
-	ld hl, wEnemyMonStatus
-	ld de, wEnemySelectedMove
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_13a09
-	ld hl, wBattleMonStatus
-	dec de
-
-.asm_13a09
-	ld a, [hl]
-	ld [hl], $0
-	and $27
-	jr z, .asm_13a13
-	ld a, $ff
-	ld [de], a
-
-.asm_13a13
-	xor a
-	ld [W_PLAYERDISABLEDMOVE], a
-	ld [W_ENEMYDISABLEDMOVE], a
-	ld hl, wccee
-	ld [hli], a
-	ld [hl], a
-	ld hl, W_PLAYERBATTSTATUS1
-	call CureStatuses
-	ld hl, W_ENEMYBATTSTATUS1
-	call CureStatuses
-	ld hl, PlayCurrentMoveAnimation
-	call CallBankF
-	ld hl, StatusChangesEliminatedText
-	jp PrintText
-
-CureStatuses: ; 13a37 (4:7a37)
-	res Confused, [hl]
-	inc hl ; BATTSTATUS2
-	ld a, [hl]
-	and (1 << UsingRage) | (1 << NeedsToRecharge) | (1 << HasSubstituteUp) | (1 << 3) ; clear all but these from BATTSTATUS2
-	ld [hli], a ; BATTSTATUS3
-	ld a, [hl]
-	and %11110000 | (1 << Transformed) ; clear Bad Poison, Reflect and Light Screen statuses
-	ld [hl], a
-	ret
-
-ResetStatMods: ; 13a43 (4:7a43)
-	ld b, $8
-.loop
-	ld [hli], a
-	dec b
-	jr nz, .loop
-	ret
-
-ResetStats: ; 13a4a (4:7a4a)
-	ld b, $8
-.loop
-	ld a, [hli]
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .loop
-	ret
-
-StatusChangesEliminatedText: ; 13a53 (4:7a53)
-	TX_FAR _StatusChangesEliminatedText
-	db "@"
-
-GetTrainerName_: ; 13a58 (4:7a58)
-	ld hl, W_GRASSRATE
-	ld a, [wLinkState]
-	and a
-	jr nz, .rival
-	ld hl, W_RIVALNAME
-	ld a, [W_TRAINERCLASS]
-	cp SONY1
-	jr z, .rival
-	cp SONY2
-	jr z, .rival
-	cp SONY3
-	jr z, .rival
-	ld [wd0b5], a
-	ld a, TRAINER_NAME
-	ld [wNameListType], a
-	ld a, BANK(TrainerNames)
-	ld [wPredefBank], a
-	call GetName
-	ld hl, wcd6d
-.rival
-	ld de, W_TRAINERNAME
-	ld bc, $d
-	jp CopyData
--- a/engine/battle/5.asm
+++ /dev/null
@@ -1,77 +1,0 @@
-SubstituteEffectHandler: ; 17dad (5:7dad)
-	ld c, 50
-	call DelayFrames
-	ld hl, wBattleMonMaxHP
-	ld de, wPlayerSubstituteHP
-	ld bc, W_PLAYERBATTSTATUS2
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .notEnemy
-	ld hl, wEnemyMonMaxHP
-	ld de, wEnemySubstituteHP
-	ld bc, W_ENEMYBATTSTATUS2
-.notEnemy
-	ld a, [bc]                    ;load flags
-	bit HasSubstituteUp, a        ;user already has substitute?
-	jr nz, .alreadyHasSubstitute  ;skip this code if so
-	                              ;user doesn't have a substitute [yet]
-	push bc
-	ld a, [hli]  ;load max hp
-	ld b, [hl]
-	srl a        ;max hp / 4, [quarter health to remove from user]
-	rr b
-	srl a
-	rr b
-	push de
-	ld de, wBattleMonHP - wBattleMonMaxHP
-	add hl, de    ; point hl to current HP
-	pop de
-	ld a, b
-	ld [de], a    ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has]
-	ld a, [hld]   ;load current hp
-	sub b         ;subtract [max hp / 4]
-	ld d, a       ;save low byte result in D
-	ld a, [hl]
-	sbc a, 0      ;borrow from high byte if needed
-	pop bc
-	jr c, .notEnoughHP  ;underflow means user would be left with negative health
-                        ;bug: note since it only brances on carry, it will possibly leave user with 0HP
-.userHasZeroOrMoreHP
-	ldi [hl], a  ;store high byte HP
-	ld [hl], d   ;store low byte HP
-	ld h, b
-	ld l, c
-	set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute
-	ld a, [W_OPTIONS]         ;load options
-	bit 7, a                  ;battle animation is enabled?
-	ld hl, PlayCurrentMoveAnimation         ;animation enabled: 0F:7BA8
-	ld b, BANK(PlayCurrentMoveAnimation)
-	jr z, .animationEnabled
-	ld hl, AnimationSubstitute ;animation disabled: 1E:56E0
-	ld b, BANK(AnimationSubstitute)
-.animationEnabled
-	call Bankswitch           ;jump to routine depending on animation setting
-	ld hl, SubstituteText
-	call PrintText
-	ld hl, DrawHUDsAndHPBars
-	ld b, BANK(DrawHUDsAndHPBars)
-	jp Bankswitch
-.alreadyHasSubstitute
-	ld hl, HasSubstituteText
-	jr .printText
-.notEnoughHP
-	ld hl, TooWeakSubstituteText
-.printText
-	jp PrintText
-
-SubstituteText: ; 17e1d (5:7e1d)
-	TX_FAR _SubstituteText
-	db "@"
-
-HasSubstituteText: ; 17e22 (5:7e22)
-	TX_FAR _HasSubstituteText
-	db "@"
-
-TooWeakSubstituteText: ; 17e27 (5:7e27)
-	TX_FAR _TooWeakSubstituteText
-	db "@"
--- a/engine/battle/9.asm
+++ /dev/null
@@ -1,190 +1,0 @@
-; [wd0b5] = pokemon ID
-; hl = dest addr
-PrintMonType: ; 27d6b (9:7d6b)
-	call GetPredefRegisters
-	push hl
-	call GetMonHeader
-	pop hl
-	push hl
-	ld a, [W_MONHTYPE1]
-	call PrintType
-	ld a, [W_MONHTYPE1]
-	ld b, a
-	ld a, [W_MONHTYPE2]
-	cp b
-	pop hl
-	jr z, EraseType2Text
-	ld bc, SCREEN_WIDTH * 2
-	add hl, bc
-
-; a = type
-; hl = dest addr
-PrintType: ; 27d89 (9:7d89)
-	push hl
-	jr PrintType_
-
-; erase "TYPE2/" if the mon only has 1 type
-EraseType2Text: ; 27d8c (9:7d8c)
-	ld a, " "
-	ld bc, $13
-	add hl, bc
-	ld bc, $6
-	jp FillMemory
-
-PrintMoveType: ; 27d98 (9:7d98)
-	call GetPredefRegisters
-	push hl
-	ld a, [W_PLAYERMOVETYPE]
-; fall through
-
-PrintType_: ; 27d9f (9:7d9f)
-	add a
-	ld hl, TypeNames
-	ld e, a
-	ld d, $0
-	add hl, de
-	ld a, [hli]
-	ld e, a
-	ld d, [hl]
-	pop hl
-	jp PlaceString
-
-INCLUDE "text/type_names.asm"
-
-SaveTrainerName: ; 27e4a (9:7e4a)
-	ld hl,TrainerNamePointers
-	ld a,[W_TRAINERCLASS]
-	dec a
-	ld c,a
-	ld b,0
-	add hl,bc
-	add hl,bc
-	ld a,[hli]
-	ld h,[hl]
-	ld l,a
-	ld de,wcd6d
-.CopyCharacter
-	ld a,[hli]
-	ld [de],a
-	inc de
-	cp "@"
-	jr nz,.CopyCharacter
-	ret
-
-TrainerNamePointers: ; 27e64 (9:7e64)
-; what is the point of these?
-	dw YoungsterName
-	dw BugCatcherName
-	dw LassName
-	dw W_TRAINERNAME
-	dw JrTrainerMName
-	dw JrTrainerFName
-	dw PokemaniacName
-	dw SuperNerdName
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw BurglarName
-	dw EngineerName
-	dw JugglerXName
-	dw W_TRAINERNAME
-	dw SwimmerName
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw BeautyName
-	dw W_TRAINERNAME
-	dw RockerName
-	dw JugglerName
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw BlackbeltName
-	dw W_TRAINERNAME
-	dw ProfOakName
-	dw ChiefName
-	dw ScientistName
-	dw W_TRAINERNAME
-	dw RocketName
-	dw CooltrainerMName
-	dw CooltrainerFName
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-	dw W_TRAINERNAME
-
-YoungsterName: ; 27ec2 (9:7ec2)
-	db "YOUNGSTER@"
-BugCatcherName: ; 27ecc (9:7ecc)
-	db "BUG CATCHER@"
-LassName: ; 27ed8 (9:7ed8)
-	db "LASS@"
-JrTrainerMName: ; 27edd (9:7edd)
-	db "JR.TRAINER♂@"
-JrTrainerFName: ; 27ee9 (9:7ee9)
-	db "JR.TRAINER♀@"
-PokemaniacName: ; 27ef5 (9:7ef5)
-	db "POKéMANIAC@"
-SuperNerdName: ; 27f00 (9:7f00)
-	db "SUPER NERD@"
-BurglarName: ; 27f0b (9:7f0b)
-	db "BURGLAR@"
-EngineerName: ; 27f13 (9:7f13)
-	db "ENGINEER@"
-JugglerXName: ; 27f1c (9:7f1c)
-	db "JUGGLER@"
-SwimmerName: ; 27f24 (9:7f24)
-	db "SWIMMER@"
-BeautyName: ; 27f2c (9:7f2c)
-	db "BEAUTY@"
-RockerName: ; 27f33 (9:7f33)
-	db "ROCKER@"
-JugglerName: ; 27f3a (9:7f3a)
-	db "JUGGLER@"
-BlackbeltName: ; 27f42 (9:7f42)
-	db "BLACKBELT@"
-ProfOakName: ; 27f4c (9:7f4c)
-	db "PROF.OAK@"
-ChiefName: ; 27f55 (9:7f55)
-	db "CHIEF@"
-ScientistName: ; 27f5b (9:7f5b)
-	db "SCIENTIST@"
-RocketName: ; 27f65 (9:7f65)
-	db "ROCKET@"
-CooltrainerMName: ; 27f6c (9:7f6c)
-	db "COOLTRAINER♂@"
-CooltrainerFName: ; 27f79 (9:7f79)
-	db "COOLTRAINER♀@"
-
-FocusEnergyEffect_: ; 27f86 (9:7f86)
-	ld hl, W_PLAYERBATTSTATUS2
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .notEnemy
-	ld hl, W_ENEMYBATTSTATUS2
-.notEnemy
-	bit GettingPumped, [hl] ; is mon already using focus energy?
-	jr nz, .alreadyUsing
-	set GettingPumped, [hl] ; mon is now using focus energy
-	callab PlayCurrentMoveAnimation
-	ld hl, GettingPumpedText
-	jp PrintText
-.alreadyUsing
-	ld c, $32
-	call DelayFrames
-	ld hl, PrintButItFailedText_
-	ld b, BANK(PrintButItFailedText_)
-	jp Bankswitch
-
-GettingPumpedText: ; 27fb3 (9:7fb3)
-	db $0a
-	TX_FAR _GettingPumpedText
-	db "@"
--- a/engine/battle/a.asm
+++ /dev/null
@@ -1,39 +1,0 @@
-LeechSeedEffect_: ; 2bea9 (a:7ea9)
-	callab MoveHitTest
-	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
-	and a
-	jr nz, .asm_2bee7
-	ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2
-	ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType)
-	ld a, [H_WHOSETURN] ; $fff3
-	and a
-	jr z, .asm_2bec8
-	ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2
-	ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType)
-.asm_2bec8
-	ld a, [de]
-	cp GRASS
-	jr z, .asm_2bee7
-	inc de
-	ld a, [de]
-	cp GRASS
-	jr z, .asm_2bee7
-	bit Seeded, [hl]
-	jr nz, .asm_2bee7
-	set Seeded, [hl]
-	callab PlayCurrentMoveAnimation
-	ld hl, WasSeededText ; $7ef2
-	jp PrintText
-.asm_2bee7
-	ld c, $32
-	call DelayFrames
-	ld hl, EvadedAttackText ; $7ef7
-	jp PrintText
-
-WasSeededText: ; 2bef2 (a:7ef2)
-	TX_FAR _WasSeededText
-	db "@"
-
-EvadedAttackText: ; 2bef7 (a:7ef7)
-	TX_FAR _EvadedAttackText
-	db "@"
--- a/engine/battle/animations.asm
+++ b/engine/battle/animations.asm
@@ -407,7 +407,7 @@
 	ld c,30
 	call DelayFrames
 .next4
-	call Func_78dbd ; reload pic and flash the pic in and out (to show damage)
+	call PlayApplyingAttackAnimation ; shake the screen or flash the pic in and out (to show damage)
 .AnimationFinished
 	call WaitForSoundToFinish
 	xor a
@@ -445,8 +445,10 @@
 	ld [W_ANIMATIONID],a
 	ret
 
-Func_78dbd: ; 78dbd (1e:4dbd)
-	ld a,[wcc5b]
+PlayApplyingAttackAnimation: ; 78dbd (1e:4dbd)
+; Generic animation that shows after the move's individual animation
+; Different animation depending on whether the move has an additional effect and on whose turn it is
+	ld a,[wAnimationType]
 	and a
 	ret z
 	dec a
@@ -453,7 +455,7 @@
 	add a
 	ld c,a
 	ld b,0
-	ld hl,PointerTable_78dcf
+	ld hl,AnimationTypePointerTable
 	add hl,bc
 	ld a,[hli]
 	ld h,[hl]
@@ -460,41 +462,41 @@
 	ld l,a
 	jp [hl]
 
-PointerTable_78dcf: ; 78dcf (1e:4dcf)
-	dw Func_78ddb
-	dw Func_78de3
-	dw Func_78deb
-	dw Func_78df0
-	dw Func_78df6
-	dw Func_78dfe
+AnimationTypePointerTable: ; 78dcf (1e:4dcf)
+	dw ShakeScreenVertically ; enemy mon has used a damaging move without a side effect
+	dw ShakeScreenHorizontallyHeavy ; enemy mon has used a damaging move with a side effect
+	dw ShakeScreenHorizontallySlow ; enemy mon has used a non-damaging move
+	dw BlinkEnemyMonSprite ; player mon has used a damaging move without a side effect
+	dw ShakeScreenHorizontallyLight ; player mon has used a damaging move with a side effect
+	dw ShakeScreenHorizontallySlow2 ; player mon has used a non-damaging move
 
-Func_78ddb: ; 78ddb (1e:4ddb)
-	call Func_79e6a
+ShakeScreenVertically: ; 78ddb (1e:4ddb)
+	call PlayApplyingAttackSound
 	ld b, $8
-	jp Func_79209
+	jp AnimationShakeScreenVertically
 
-Func_78de3: ; 78de3 (1e:4de3)
-	call Func_79e6a
+ShakeScreenHorizontallyHeavy: ; 78de3 (1e:4de3)
+	call PlayApplyingAttackSound
 	ld b, $8
-	jp Func_79210
+	jp AnimationShakeScreenHorizontallyFast
 
-Func_78deb: ; 78deb (1e:4deb)
+ShakeScreenHorizontallySlow: ; 78deb (1e:4deb)
 	ld bc, $602
-	jr Func_78e01
+	jr AnimationShakeScreenHorizontallySlow
 
-Func_78df0: ; 78df0 (1e:4df0)
-	call Func_79e6a
+BlinkEnemyMonSprite: ; 78df0 (1e:4df0)
+	call PlayApplyingAttackSound
 	jp AnimationBlinkEnemyMon
 
-Func_78df6: ; 78df6 (1e:4df6)
-	call Func_79e6a
+ShakeScreenHorizontallyLight: ; 78df6 (1e:4df6)
+	call PlayApplyingAttackSound
 	ld b, $2
-	jp Func_79210
+	jp AnimationShakeScreenHorizontallyFast
 
-Func_78dfe: ; 78dfe (1e:4dfe)
+ShakeScreenHorizontallySlow2: ; 78dfe (1e:4dfe)
 	ld bc, $302
 
-Func_78e01: ; 78e01 (1e:4e01)
+AnimationShakeScreenHorizontallySlow: ; 78e01 (1e:4e01)
 	push bc
 	push bc
 .asm_78e03
@@ -516,7 +518,7 @@
 	jr nz, .asm_78e11
 	pop bc
 	dec c
-	jr nz, Func_78e01
+	jr nz, AnimationShakeScreenHorizontallySlow
 	ret
 
 Func_78e23: ; 78e23 (1e:4e23)
@@ -1225,7 +1227,7 @@
 
 	ld b, $5
 
-Func_79209: ; 79209 (1e:5209)
+AnimationShakeScreenVertically: ; 79209 (1e:5209)
 	predef_jump Func_480ff
 
 AnimationShakeScreen: ; 7920e (1e:520e)
@@ -1232,7 +1234,7 @@
 ; Shakes the screen for a while. Used in Earthquake/Fissure/etc. animations.
 	ld b, $8
 
-Func_79210: ; 79210 (1e:5210)
+AnimationShakeScreenHorizontallyFast: ; 79210 (1e:5210)
 	predef_jump Func_48125
 
 AnimationWaterDropletsEverywhere: ; 79215 (1e:5215)
@@ -2929,9 +2931,11 @@
 	ld [W_ANIMATIONID],a
 	jp PlayAnimation
 
-Func_79e6a: ; 79e6a (1e:5e6a)
+PlayApplyingAttackSound: ; 79e6a (1e:5e6a)
+; play a different sound depending if move is not very effective, neutral, or super-effective
+; don't play any sound at all if move is ineffective
 	call WaitForSoundToFinish
-	ld a, [wd05b]
+	ld a, [wDamageMultipliers]
 	and $7f
 	ret z
 	cp $a
--- a/engine/battle/b.asm
+++ /dev/null
@@ -1,18 +1,0 @@
-DisplayEffectiveness: ; 2fb7b (b:7b7b)
-	ld a, [wd05b]
-	and a, $7F
-	cp a, $0A
-	ret z
-	ld hl, SuperEffectiveText
-	jr nc, .done
-	ld hl, NotVeryEffectiveText
-.done
-	jp PrintText
-
-SuperEffectiveText: ; 2fb8e (b:7b8e)
-	TX_FAR _SuperEffectiveText
-	db "@"
-
-NotVeryEffectiveText: ; 2fb93 (b:7b93)
-	TX_FAR _NotVeryEffectiveText
-	db "@"
--- a/engine/battle/b_2.asm
+++ /dev/null
@@ -1,129 +1,0 @@
-; scales both uncompressed sprite chunks by two in every dimension (creating 2x2 output pixels per input pixel)
-; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored
-; resulting in a 7*7 tile output sprite chunk
-ScaleSpriteByTwo: ; 2fe40 (b:7e40)
-	ld de, S_SPRITEBUFFER1 + (4*4*8) - 5          ; last byte of input data, last 4 rows already skipped
-	ld hl, S_SPRITEBUFFER0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
-	call ScaleLastSpriteColumnByTwo               ; last tile column is special case
-	call ScaleFirstThreeSpriteColumnsByTwo        ; scale first 3 tile columns
-	ld de, S_SPRITEBUFFER2 + (4*4*8) - 5          ; last byte of input data, last 4 rows already skipped
-	ld hl, S_SPRITEBUFFER1 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
-	call ScaleLastSpriteColumnByTwo               ; last tile column is special case
-
-ScaleFirstThreeSpriteColumnsByTwo: ; 2fe55 (b:7e55)
-	ld b, $3 ; 3 tile columns
-.columnLoop
-	ld c, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
-.columnInnerLoop
-	push bc
-	ld a, [de]
-	ld bc, -(7*8)+1       ; $ffc9, scale lower nybble and seek to previous output column
-	call ScalePixelsByTwo
-	ld a, [de]
-	dec de
-	swap a
-	ld bc, 7*8+1-2        ; $37, scale upper nybble and seek back to current output column and to the next 2 rows
-	call ScalePixelsByTwo
-	pop bc
-	dec c
-	jr nz, .columnInnerLoop
-	dec de
-	dec de
-	dec de
-	dec de
-	ld a, b
-	ld bc, -7*8 ; $ffc8, skip one output column (which has already been written along with the current one)
-	add hl, bc
-	ld b, a
-	dec b
-	jr nz, .columnLoop
-	ret
-
-ScaleLastSpriteColumnByTwo: ; 2fe7d (b:7e7d)
-	ld a, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
-	ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
-	ld bc, -1 ; $ffff
-.columnInnerLoop
-	ld a, [de]
-	dec de
-	swap a                    ; only high nybble contains information
-	call ScalePixelsByTwo
-	ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b
-	dec a
-	ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
-	jr nz, .columnInnerLoop
-	dec de                    ; skip last 4 rows of new column
-	dec de
-	dec de
-	dec de
-	ret
-
-; scales the given 4 bits in a (4x1 pixels) to 2 output bytes (8x2 pixels)
-; hl: destination pointer
-; bc: destination pointer offset (added after the two bytes have been written)
-ScalePixelsByTwo: ; 2fe97 (b:7e97)
-	push hl
-	and $f
-	ld hl, DuplicateBitsTable
-	add l
-	ld l, a
-	jr nc, .noCarry
-	inc h
-.noCarry
-	ld a, [hl]
-	pop hl
-	ld [hld], a  ; write output byte twice to make it 2 pixels high
-	ld [hl], a
-	add hl, bc   ; add offset
-	ret
-
-; repeats each input bit twice
-DuplicateBitsTable: ; 2fea8 (b:7ea8)
-	db $00, $03, $0c, $0f
-	db $30, $33, $3c, $3f
-	db $c0, $c3, $cc, $cf
-	db $f0, $f3, $fc, $ff
-
-PayDayEffect_ ; 2feb8 (b:7eb8)
-	xor a
-	ld hl, wcd6d
-	ld [hli], a
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [wBattleMonLevel]
-	jr z, .asm_2fec8
-	ld a, [wEnemyMonLevel]
-.asm_2fec8
-	add a
-	ld [H_DIVIDEND + 3], a
-	xor a
-	ld [H_DIVIDEND], a
-	ld [H_DIVIDEND + 1], a
-	ld [H_DIVIDEND + 2], a
-	ld a, $64
-	ld [H_DIVISOR], a
-	ld b, $4
-	call Divide
-	ld a, [H_QUOTIENT + 3]
-	ld [hli], a
-	ld a, [H_REMAINDER]
-	ld [H_DIVIDEND + 3], a
-	ld a, $a
-	ld [H_DIVISOR], a
-	ld b, $4
-	call Divide
-	ld a, [H_QUOTIENT + 3]
-	swap a
-	ld b, a
-	ld a, [H_REMAINDER]
-	add b
-	ld [hl], a
-	ld de, wTotalPayDayMoney + 2
-	ld c, $3
-	predef AddBCDPredef
-	ld hl, CoinsScatteredText
-	jp PrintText
-
-CoinsScatteredText: ; 2ff04 (b:7f04)
-	TX_FAR _CoinsScatteredText
-	db "@"
--- /dev/null
+++ b/engine/battle/bank_e_misc.asm
@@ -1,0 +1,122 @@
+; formats a string at wMovesString that lists the moves at wMoves
+FormatMovesString: ; 39b87 (e:5b87)
+	ld hl, wMoves
+	ld de, wMovesString
+	ld b, $0
+.printMoveNameLoop
+	ld a, [hli]
+	and a ; end of move list?
+	jr z, .printDashLoop ; print dashes when no moves are left
+	push hl
+	ld [wd0b5], a
+	ld a, BANK(MoveNames)
+	ld [wPredefBank], a
+	ld a, MOVE_NAME
+	ld [wNameListType], a
+	call GetName
+	ld hl, wcd6d
+.copyNameLoop
+	ld a, [hli]
+	cp $50
+	jr z, .doneCopyingName
+	ld [de], a
+	inc de
+	jr .copyNameLoop
+.doneCopyingName
+	ld a, b
+	ld [wcd6c], a
+	inc b
+	ld a, $4e ; line break
+	ld [de], a
+	inc de
+	pop hl
+	ld a, b
+	cp NUM_MOVES
+	jr z, .done
+	jr .printMoveNameLoop
+.printDashLoop
+	ld a, "-"
+	ld [de], a
+	inc de
+	inc b
+	ld a, b
+	cp NUM_MOVES
+	jr z, .done
+	ld a, $4e ; line break
+	ld [de], a
+	inc de
+	jr .printDashLoop
+.done
+	ld a, "@"
+	ld [de], a
+	ret
+
+; XXX this is called in a few places, but it doesn't appear to do anything useful
+Func_39bd5: ; 39bd5 (e:5bd5)
+	ld a, [wd11b]
+	cp $1
+	jr nz, .asm_39be6
+	ld hl, wEnemyPartyCount
+	ld de, wEnemyMonOT
+	ld a, ENEMYOT_NAME
+	jr .asm_39c18
+.asm_39be6
+	cp $4
+	jr nz, .calcAttackStat4
+	ld hl, wPartyCount
+	ld de, wPartyMonOT
+	ld a, PLAYEROT_NAME
+	jr .asm_39c18
+.calcAttackStat4
+	cp $5
+	jr nz, .asm_39c02
+	ld hl, wStringBuffer2 + 11
+	ld de, MonsterNames
+	ld a, MONSTER_NAME
+	jr .asm_39c18
+.asm_39c02
+	cp $2
+	jr nz, .asm_39c10
+	ld hl, wNumBagItems
+	ld de, ItemNames
+	ld a, ITEM_NAME
+	jr .asm_39c18
+.asm_39c10
+	ld hl, wStringBuffer2 + 11
+	ld de, ItemNames
+	ld a, ITEM_NAME
+.asm_39c18
+	ld [wNameListType], a
+	ld a, l
+	ld [wList], a
+	ld a, h
+	ld [wList + 1], a
+	ld a, e
+	ld [wcf8d], a
+	ld a, d
+	ld [wcf8e], a
+	ld bc, ItemPrices
+	ld a, c
+	ld [wItemPrices], a
+	ld a, b
+	ld [wItemPrices + 1], a
+	ret
+
+; get species of mon e in list [wcc49] for LoadMonData
+GetMonSpecies: ; 39c37 (e:5c37)
+	ld hl, wPartySpecies
+	ld a, [wcc49]
+	and a
+	jr z, .getSpecies
+	dec a
+	jr z, .enemyParty
+	ld hl, wBoxSpecies
+	jr .getSpecies
+.enemyParty
+	ld hl, wEnemyPartyMons
+.getSpecies
+	ld d, 0
+	add hl, de
+	ld a, [hl]
+	ld [wcf91], a
+	ret
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/battle_transitions.asm
@@ -1,0 +1,815 @@
+BattleTransition: ; 7096d (1c:496d)
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	call Delay3
+	xor a
+	ld [hWY], a
+	dec a
+	ld [wUpdateSpritesEnabled], a
+	call DelayFrame
+	ld hl, wSpriteStateData1 + 2
+	ld a, [H_DOWNARROWBLINKCNT2]
+	ld c, a
+	ld b, $0
+	ld de, $10
+.loop1
+	ld a, [hl]
+	cp $ff
+	jr z, .skip1
+	inc b
+.skip1
+	add hl, de
+	dec c
+	jr nz, .loop1
+	ld hl, wOAMBuffer + $10
+	ld c, $9
+.loop2
+	ld a, b
+	swap a
+	cp l
+	jr z, .skip2
+	push hl
+	push bc
+	ld bc, $10
+	xor a
+	call FillMemory
+	pop bc
+	pop hl
+.skip2
+	ld de, $10
+	add hl, de
+	dec c
+	jr nz, .loop2
+	call Delay3
+	call LoadBattleTransitionTile
+	ld bc, $0
+	ld a, [wLinkState]
+	cp LINK_STATE_BATTLING
+	jr z, .linkBattle
+	call GetBattleTransitionID_WildOrTrainer
+	call GetBattleTransitionID_CompareLevels
+	call GetBattleTransitionID_IsDungeonMap
+.linkBattle
+	ld hl, BattleTransitions
+	add hl, bc
+	add hl, bc
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp [hl]
+
+; the three GetBattleTransitionID functions set the first
+; three bits of c, which determines what transition animation
+; to play at the beginning of a battle
+; bit 0: set if trainer battle
+; bit 1: set if enemy is at least 3 levels higher than player
+; bit 2: set if dungeon map
+BattleTransitions: ; 709d2 (1c:49d2)
+	dw BattleTransition_DoubleCircle      ; %000
+	dw BattleTransition_Spiral            ; %001
+	dw BattleTransition_Circle            ; %010
+	dw BattleTransition_Spiral            ; %011
+	dw BattleTransition_HorizontalStripes ; %100
+	dw BattleTransition_Shrink            ; %101
+	dw BattleTransition_VerticalStripes   ; %110
+	dw BattleTransition_Split             ; %111
+
+GetBattleTransitionID_WildOrTrainer: ; 709e2 (1c:49e2)
+	ld a, [W_CUROPPONENT]
+	cp $c8
+	jr nc, .trainer
+	res 0, c
+	ret
+.trainer
+	set 0, c
+	ret
+
+GetBattleTransitionID_CompareLevels: ; 709ef (1c:49ef)
+	ld hl, wPartyMon1HP
+.faintedLoop
+	ld a, [hli]
+	or [hl]
+	jr nz, .notFainted
+	ld de, wPartyMon2 - (wPartyMon1 + 1)
+	add hl, de
+	jr .faintedLoop
+.notFainted
+	ld de, wPartyMon1Level - (wPartyMon1HP + 1)
+	add hl, de
+	ld a, [hl]
+	add $3
+	ld e, a
+	ld a, [W_CURENEMYLVL]
+	sub e
+	jr nc, .highLevelEnemy
+	res 1, c
+	ld a, $1
+	ld [wcd47], a
+	ret
+.highLevelEnemy
+	set 1, c
+	xor a
+	ld [wcd47], a
+	ret
+
+; fails to recognize VICTORY_ROAD_2, VICTORY_ROAD_3, all ROCKET_HIDEOUT maps,
+; MANSION_1, SEAFOAM_ISLANDS_[2-5], POWER_PLANT, DIGLETTS_CAVE
+; and SILPH_CO_[9-11]F as dungeon maps
+GetBattleTransitionID_IsDungeonMap: ; 70a19 (1c:4a19)
+	ld a, [W_CURMAP]
+	ld e, a
+	ld hl, DungeonMaps1
+.loop1
+	ld a, [hli]
+	cp $ff
+	jr z, .noMatch1
+	cp e
+	jr nz, .loop1
+.match
+	set 2, c
+	ret
+.noMatch1
+	ld hl, DungeonMaps2
+.loop2
+	ld a, [hli]
+	cp $ff
+	jr z, .noMatch2
+	ld d, a
+	ld a, [hli]
+	cp e
+	jr c, .loop2
+	ld a, e
+	cp d
+	jr nc, .match
+.noMatch2
+	res 2, c
+	ret
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is equal to one of these maps
+DungeonMaps1: ; 70a3f (1c:4a3f)
+	db VIRIDIAN_FOREST
+	db ROCK_TUNNEL_1
+	db SEAFOAM_ISLANDS_1
+	db ROCK_TUNNEL_2
+	db $FF
+
+; GetBattleTransitionID_IsDungeonMap checks if W_CURMAP
+; is in between or equal to each pair of maps
+DungeonMaps2: ; 70a44 (1c:4a44)
+	; all MT_MOON maps
+	db MT_MOON_1
+	db MT_MOON_3
+
+	; all SS_ANNE maps, VICTORY_ROAD_1, LANCES_ROOM, and HALL_OF_FAME
+	db SS_ANNE_1
+	db HALL_OF_FAME
+
+	; all POKEMONTOWER maps and Lavender Town buildings
+	db LAVENDER_POKECENTER
+	db LAVENDER_HOUSE_2
+
+	; SILPH_CO_[2-8]F, MANSION[2-4], SAFARI_ZONE, and UNKNOWN_DUNGEON maps,
+	; except for SILPH_CO_1F
+	db SILPH_CO_2F
+	db UNKNOWN_DUNGEON_1
+	db $FF
+
+LoadBattleTransitionTile: ; 70a4d (1c:4a4d)
+	ld hl, vChars1 + $7f0
+	ld de, BattleTransitionTile
+	ld bc, (BANK(BattleTransitionTile) << 8) + $01
+	jp CopyVideoData
+
+BattleTransitionTile: ; 70a59 (1c:4a59)
+	INCBIN "gfx/battle_transition.2bpp"
+
+BattleTransition_BlackScreen: ; 70a69 (1c:4a69)
+	ld a, $ff
+	ld [rBGP], a
+	ld [rOBP0], a
+	ld [rOBP1], a
+	ret
+
+; for non-dungeon trainer battles
+; called regardless of mon levels, but does an
+; outward spiral if enemy is at least 3 levels
+; higher than player and does an inward spiral otherwise
+BattleTransition_Spiral: ; 70a72 (1c:4a72)
+	ld a, [wcd47]
+	and a
+	jr z, .outwardSpiral
+	call BattleTransition_InwardSpiral
+	jr .done
+.outwardSpiral
+	hlCoord 10, 10
+	ld a, $3
+	ld [wd09f], a
+	ld a, l
+	ld [wd09b], a
+	ld a, h
+	ld [wd09a], a
+	ld b, $78
+.loop1
+	ld c, $3
+.loop2
+	push bc
+	call BattleTransition_OutwardSpiral_
+	pop bc
+	dec c
+	jr nz, .loop2
+	call DelayFrame
+	dec b
+	jr nz, .loop1
+.done
+	call BattleTransition_BlackScreen
+	xor a
+	ld [wd09b], a
+	ld [wd09a], a
+	ret
+
+BattleTransition_InwardSpiral: ; 70aaa (1c:4aaa)
+	ld a, $7
+	ld [wWhichTrade], a
+	ld hl, wTileMap
+	ld c, $11
+	ld de, $14
+	call BattleTransition_InwardSpiral_
+	inc c
+	jr .skip
+.loop
+	ld de, $14
+	call BattleTransition_InwardSpiral_
+.skip
+	inc c
+	ld de, $1
+	call BattleTransition_InwardSpiral_
+	dec c
+	dec c
+	ld de, $ffec
+	call BattleTransition_InwardSpiral_
+	inc c
+	ld de, rIE
+	call BattleTransition_InwardSpiral_
+	dec c
+	dec c
+	ld a, c
+	and a
+	jr nz, .loop
+	ret
+
+BattleTransition_InwardSpiral_: ; 70ae0 (1c:4ae0)
+	push bc
+.loop
+	ld [hl], $ff
+	add hl, de
+	push bc
+	ld a, [wWhichTrade]
+	dec a
+	jr nz, .skip
+	call BattleTransition_TransferDelay3
+	ld a, $7
+.skip
+	ld [wWhichTrade], a
+	pop bc
+	dec c
+	jr nz, .loop
+	pop bc
+	ret
+
+BattleTransition_OutwardSpiral_: ; 70af9 (1c:4af9)
+	ld bc, $ffec
+	ld de, $14
+	ld a, [wd09b]
+	ld l, a
+	ld a, [wd09a]
+	ld h, a
+	ld a, [wd09f]
+	cp $0
+	jr z, .zero
+	cp $1
+	jr z, .one
+	cp $2
+	jr z, .two
+	cp $3
+	jr z, .three
+.done1
+	ld [hl], $ff
+.done2_
+	ld a, l
+	ld [wd09b], a
+	ld a, h
+	ld [wd09a], a
+	ret
+.zero
+	dec hl
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	inc hl
+	add hl, bc
+	jr .done1
+.one
+	add hl, de
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	add hl, bc
+	dec hl
+	jr .done1
+.two
+	inc hl
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	dec hl
+	add hl, de
+	jr .done1
+.three
+	add hl, bc
+	ld a, [hl]
+	cp $ff
+	jr nz, .done2
+	add hl, de
+	inc hl
+	jr .done1
+.done2
+	ld [hl], $ff
+	ld a, [wd09f]
+	inc a
+	cp $4
+	jr nz, .skip
+	xor a
+.skip
+	ld [wd09f], a
+	jr .done2_
+
+FlashScreen:
+BattleTransition_FlashScreen_: ; 70b5d (1c:4b5d)
+	ld hl, BattleTransition_FlashScreenPalettes
+.loop
+	ld a, [hli]
+	cp $1
+	jr z, .done
+	ld [rBGP], a
+	ld c, $2
+	call DelayFrames
+	jr .loop
+.done
+	dec b
+	jr nz, BattleTransition_FlashScreen_
+	ret
+
+BattleTransition_FlashScreenPalettes: ; 70b72 (1c:4b72)
+	db $F9,$FE,$FF,$FE,$F9,$E4,$90,$40,$00,$40,$90,$E4
+	db $01 ; terminator
+
+; used for low level trainer dungeon battles
+BattleTransition_Shrink: ; 70b7f (1c:4b7f)
+	ld c, $9
+.loop
+	push bc
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	hlCoord 0, 7
+	deCoord 0, 8
+	ld bc, $ffd8
+	call BattleTransition_CopyTiles1
+	hlCoord 0, 10
+	deCoord 0, 9
+	ld bc, $28
+	call BattleTransition_CopyTiles1
+	hlCoord 8, 0
+	deCoord 9, 0
+	ld bc, $fffe
+	call BattleTransition_CopyTiles2
+	hlCoord 11, 0
+	deCoord 10, 0
+	ld bc, $2
+	call BattleTransition_CopyTiles2
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ld c, $6
+	call DelayFrames
+	pop bc
+	dec c
+	jr nz, .loop
+	call BattleTransition_BlackScreen
+	ld c, $a
+	jp DelayFrames
+
+; used for high level trainer dungeon battles
+BattleTransition_Split: ; 70bca (1c:4bca)
+	ld c, $9
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	hlCoord 0, 16
+	deCoord 0, 17
+	ld bc, $ffd8
+	call BattleTransition_CopyTiles1
+	hlCoord 0, 1
+	ld de, wTileMap
+	ld bc, $28
+	call BattleTransition_CopyTiles1
+	hlCoord 18, 0
+	deCoord 19, 0
+	ld bc, $fffe
+	call BattleTransition_CopyTiles2
+	hlCoord 1, 0
+	ld de, wTileMap
+	ld bc, $2
+	call BattleTransition_CopyTiles2
+	call BattleTransition_TransferDelay3
+	call Delay3
+	pop bc
+	dec c
+	jr nz, .loop
+	call BattleTransition_BlackScreen
+	ld c, $a
+	jp DelayFrames
+
+BattleTransition_CopyTiles1: ; 70c12 (1c:4c12)
+	ld a, c
+	ld [wWhichTrade], a
+	ld a, b
+	ld [wTrainerEngageDistance], a
+	ld c, $8
+.loop1
+	push bc
+	push hl
+	push de
+	ld bc, $14
+	call CopyData
+	pop hl
+	pop de
+	ld a, [wWhichTrade]
+	ld c, a
+	ld a, [wTrainerEngageDistance]
+	ld b, a
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop1
+	ld l, e
+	ld h, d
+	ld a, $ff
+	ld c, $14
+.loop2
+	ld [hli], a
+	dec c
+	jr nz, .loop2
+	ret
+
+BattleTransition_CopyTiles2: ; 70c3f (1c:4c3f)
+	ld a, c
+	ld [wWhichTrade], a
+	ld a, b
+	ld [wTrainerEngageDistance], a
+	ld c, $9
+.loop1
+	push bc
+	push hl
+	push de
+	ld c, $12
+.loop2
+	ld a, [hl]
+	ld [de], a
+	ld a, e
+	add $14
+	jr nc, .noCarry1
+	inc d
+.noCarry1
+	ld e, a
+	ld a, l
+	add $14
+	jr nc, .noCarry2
+	inc h
+.noCarry2
+	ld l, a
+	dec c
+	jr nz, .loop2
+	pop hl
+	pop de
+	ld a, [wWhichTrade]
+	ld c, a
+	ld a, [wTrainerEngageDistance]
+	ld b, a
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop1
+	ld l, e
+	ld h, d
+	ld de, $14
+	ld c, $12
+.loop3
+	ld [hl], $ff
+	add hl, de
+	dec c
+	jr nz, .loop3
+	ret
+
+; used for high level wild dungeon battles
+BattleTransition_VerticalStripes: ; 70c7e (1c:4c7e)
+	ld c, $12
+	ld hl, wTileMap
+	deCoord 1, 17
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	call BattleTransition_VerticalStripes_
+	pop hl
+	call BattleTransition_VerticalStripes_
+	call BattleTransition_TransferDelay3
+	pop hl
+	ld bc, $ffec
+	add hl, bc
+	ld e, l
+	ld d, h
+	pop hl
+	ld bc, $14
+	add hl, bc
+	pop bc
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_VerticalStripes_: ; 70caa (1c:4caa)
+	ld c, $a
+.loop
+	ld [hl], $ff
+	inc hl
+	inc hl
+	dec c
+	jr nz, .loop
+	ret
+
+; used for low level wild dungeon battles
+BattleTransition_HorizontalStripes: ; 70cb4 (1c:4cb4)
+	ld c, $14
+	ld hl, wTileMap
+	deCoord 19, 1
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	call BattleTransition_HorizontalStripes_
+	pop hl
+	call BattleTransition_HorizontalStripes_
+	call BattleTransition_TransferDelay3
+	pop de
+	pop hl
+	pop bc
+	inc hl
+	dec de
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_HorizontalStripes_: ; 70cd8 (1c:4cd8)
+	ld c, $9
+	ld de, $28
+.loop
+	ld [hl], $ff
+	add hl, de
+	dec c
+	jr nz, .loop
+	ret
+
+; used for high level wild non-dungeon battles
+; makes one full circle around the screen
+; by animating each half circle one at a time
+BattleTransition_Circle: ; 70ce4 (1c:4ce4)
+	call BattleTransition_FlashScreen
+	ld bc, $000a
+	ld hl, BattleTransition_HalfCircle1
+	call BattleTransition_Circle_Sub1
+	ld c, $a
+	ld b, $1
+	ld hl, BattleTransition_HalfCircle2
+	call BattleTransition_Circle_Sub1
+	jp BattleTransition_BlackScreen
+
+BattleTransition_FlashScreen: ; 70cfd (1c:4cfd)
+	ld b, $3
+	call BattleTransition_FlashScreen_
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ret
+
+BattleTransition_Circle_Sub1: ; 70d06 (1c:4d06)
+	push bc
+	push hl
+	ld a, b
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld bc, $0005
+	add hl, bc
+	call BattleTransition_TransferDelay3
+	pop bc
+	dec c
+	jr nz, BattleTransition_Circle_Sub1
+	ret
+
+BattleTransition_TransferDelay3: ; 70d19 (1c:4d19)
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a
+	call Delay3
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a
+	ret
+
+; used for low level wild non-dungeon battles
+; makes two half circles around the screen
+; by animating both half circles at the same time
+BattleTransition_DoubleCircle: ; 70d24 (1c:4d24)
+	call BattleTransition_FlashScreen
+	ld c, $a
+	ld hl, BattleTransition_HalfCircle1
+	ld de, BattleTransition_HalfCircle2
+.loop
+	push bc
+	push hl
+	push de
+	push de
+	xor a
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld a, $1
+	call BattleTransition_Circle_Sub2
+	pop hl
+	ld bc, $5
+	add hl, bc
+	ld e, l
+	ld d, h
+	pop hl
+	add hl, bc
+	call BattleTransition_TransferDelay3
+	pop bc
+	dec c
+	jr nz, .loop
+	jp BattleTransition_BlackScreen
+
+BattleTransition_Circle_Sub2: ; 70d50 (1c:4d50)
+	ld [wWhichTrade], a
+	ld a, [hli]
+	ld [wTrainerEngageDistance], a
+	ld a, [hli]
+	ld e, a
+	ld a, [hli]
+	ld d, a
+	ld a, [hli]
+	ld h, [hl]
+	ld l, a
+	jp BattleTransition_Circle_Sub3
+
+BattleTransition_HalfCircle1: ; 70d61 (1c:4d61)
+	db $01
+	dw BattleTransition_CircleData1
+	dwCoord 18, 6
+
+	db $01
+	dw BattleTransition_CircleData2
+	dwCoord 19, 3
+
+	db $01
+	dw BattleTransition_CircleData3
+	dwCoord 18, 0
+
+	db $01
+	dw BattleTransition_CircleData4
+	dwCoord 14, 0
+
+	db $01
+	dw BattleTransition_CircleData5
+	dwCoord 10, 0
+
+	db $00
+	dw BattleTransition_CircleData5
+	dwCoord 9, 0
+
+	db $00
+	dw BattleTransition_CircleData4
+	dwCoord 5, 0
+
+	db $00
+	dw BattleTransition_CircleData3
+	dwCoord 1, 0
+
+	db $00
+	dw BattleTransition_CircleData2
+	dwCoord 0, 3
+
+	db $00
+	dw BattleTransition_CircleData1
+	dwCoord 1, 6
+
+BattleTransition_HalfCircle2: ; 70d93 (1c:4d93)
+	db $00
+	dw BattleTransition_CircleData1
+	dwCoord 1, 11
+
+	db $00
+	dw BattleTransition_CircleData2
+	dwCoord 0, 14
+
+	db $00
+	dw BattleTransition_CircleData3
+	dwCoord 1, 17
+
+	db $00
+	dw BattleTransition_CircleData4
+	dwCoord 5, 17
+
+	db $00
+	dw BattleTransition_CircleData5
+	dwCoord 9, 17
+
+	db $01
+	dw BattleTransition_CircleData5
+	dwCoord 10, 17
+
+	db $01
+	dw BattleTransition_CircleData4
+	dwCoord 14, 17
+
+	db $01
+	dw BattleTransition_CircleData3
+	dwCoord 18, 17
+
+	db $01
+	dw BattleTransition_CircleData2
+	dwCoord 19, 14
+
+	db $01
+	dw BattleTransition_CircleData1
+	dwCoord 18, 11
+
+BattleTransition_Circle_Sub3: ; 70dc5 (1c:4dc5)
+	push hl
+	ld a, [de]
+	ld c, a
+	inc de
+.loop1
+	ld [hl], $ff
+	ld a, [wTrainerEngageDistance]
+	and a
+	jr z, .skip1
+	inc hl
+	jr .skip2
+.skip1
+	dec hl
+.skip2
+	dec c
+	jr nz, .loop1
+	pop hl
+	ld a, [wWhichTrade]
+	and a
+	ld bc, $14
+	jr z, .skip3
+	ld bc, $ffec
+.skip3
+	add hl, bc
+	ld a, [de]
+	inc de
+	cp $ff
+	ret z
+	and a
+	jr z, BattleTransition_Circle_Sub3
+	ld c, a
+.loop2
+	ld a, [wTrainerEngageDistance]
+	and a
+	jr z, .skip4
+	dec hl
+	jr .skip5
+.skip4
+	inc hl
+.skip5
+	dec c
+	jr nz, .loop2
+	jr BattleTransition_Circle_Sub3
+
+BattleTransition_CircleData1: ; 70dfe (1c:4dfe)
+	db $02,$03,$05,$04,$09,$FF
+
+BattleTransition_CircleData2: ; 70e04 (1c:4e04)
+	db $01,$01,$02,$02,$04,$02,$04,$02,$03,$FF
+
+BattleTransition_CircleData3: ; 70e0e (1c:4e0e)
+	db $02,$01,$03,$01,$04,$01,$04,$01,$04,$01,$03,$01,$02,$01,$01,$01,$01,$FF
+
+BattleTransition_CircleData4: ; 70e20 (1c:4e20)
+	db $04,$01,$04,$00,$03,$01,$03,$00,$02,$01,$02,$00,$01,$FF
+
+BattleTransition_CircleData5: ; 70e2e (1c:4e2e)
+	db $04,$00,$03,$00,$03,$00,$02,$00,$02,$00,$01,$00,$01,$00,$01,$FF
--- a/engine/battle/c.asm
+++ /dev/null
@@ -1,58 +1,0 @@
-MistEffect_: ; 33f2b (c:7f2b)
-	ld hl, W_PLAYERBATTSTATUS2
-	ld a, [$fff3]
-	and a
-	jr z, .asm_33f36
-	ld hl, W_ENEMYBATTSTATUS2
-.asm_33f36
-	bit ProtectedByMist, [hl] ; is mon protected by mist?
-	jr nz, .asm_33f4a
-	set ProtectedByMist, [hl] ; mon is now protected by mist
-	callab PlayCurrentMoveAnimation
-	ld hl, ShroudedInMistText
-	jp PrintText
-.asm_33f4a
-	ld hl, PrintButItFailedText_
-	ld b, BANK(PrintButItFailedText_)
-	jp Bankswitch
-
-ShroudedInMistText: ; 33f52 (c:7f52)
-	TX_FAR _ShroudedInMistText
-	db "@"
-
-OneHitKOEffect_: ; 33f57 (c:7f57)
-	ld hl, W_DAMAGE 
-	xor a
-	ld [hli], a
-	ld [hl], a ; set the damage output to zero
-	dec a
-	ld [wCriticalHitOrOHKO], a
-	ld hl, wBattleMonSpeed + 1
-	ld de, wEnemyMonSpeed + 1
-	ld a, [H_WHOSETURN] ; $fff3
-	and a
-	jr z, .asm_33f72
-	ld hl, wEnemyMonSpeed + 1
-	ld de, wBattleMonSpeed + 1
-.asm_33f72
-	ld a, [de]
-	dec de
-	ld b, a
-	ld a, [hld]
-	sub b
-	ld a, [de]
-	ld b, a
-	ld a, [hl]
-	sbc b
-	jr c, .asm_33f8a
-	ld hl, W_DAMAGE 
-	ld a, $ff
-	ld [hli], a
-	ld [hl], a
-	ld a, $2
-	ld [wCriticalHitOrOHKO], a
-	ret
-.asm_33f8a
-	ld a, $1
-	ld [W_MOVEMISSED], a 
-	ret
--- /dev/null
+++ b/engine/battle/common_text.asm
@@ -1,0 +1,238 @@
+PrintBeginningBattleText: ; 58d99 (16:4d99)
+	ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+	dec a
+	jr nz, .trainerBattle
+	ld a, [W_CURMAP] ; W_CURMAP
+	cp POKEMONTOWER_3
+	jr c, .notPokemonTower
+	cp LAVENDER_HOUSE_1
+	jr c, .pokemonTower
+.notPokemonTower
+	ld a, [wEnemyMonSpecies2]
+	call PlayCry
+	ld hl, WildMonAppearedText
+	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
+	and a
+	jr z, .notFishing
+	ld hl, HookedMonAttackedText
+.notFishing
+	jr .wildBattle
+.trainerBattle
+	call .playSFX
+	ld c, $14
+	call DelayFrames
+	ld hl, TrainerWantsToFightText
+.wildBattle
+	push hl
+	callab DrawAllPokeballs
+	pop hl
+	call PrintText
+	jr .done
+.pokemonTower
+	ld b, SILPH_SCOPE
+	call IsItemInBag
+	ld a, [wEnemyMonSpecies2]
+	ld [wcf91], a
+	cp MAROWAK
+	jr z, .isMarowak
+	ld a, b
+	and a
+	jr z, .noSilphScope
+	callab LoadEnemyMonData
+	jr .notPokemonTower
+.noSilphScope
+	ld hl, EnemyAppearedText
+	call PrintText
+	ld hl, GhostCantBeIDdText
+	call PrintText
+	jr .done
+.isMarowak
+	ld a, b
+	and a
+	jr z, .noSilphScope
+	ld hl, EnemyAppearedText
+	call PrintText
+	ld hl, UnveiledGhostText
+	call PrintText
+	callab LoadEnemyMonData
+	callab MarowakAnim
+	ld hl, WildMonAppearedText
+	call PrintText
+
+.playSFX
+	xor a
+	ld [wc0f1], a
+	ld a, $80
+	ld [wc0f2], a
+	ld a, (SFX_08_77 - SFX_Headers_08) / 3
+	call PlaySound
+	jp WaitForSoundToFinish
+.done
+	ret
+
+WildMonAppearedText: ; 58e3b (16:4e3b)
+	TX_FAR _WildMonAppearedText
+	db "@"
+
+HookedMonAttackedText: ; 58e40 (16:4e40)
+	TX_FAR _HookedMonAttackedText
+	db "@"
+
+EnemyAppearedText: ; 58e45 (16:4e45)
+	TX_FAR _EnemyAppearedText
+	db "@"
+
+TrainerWantsToFightText: ; 58e4a (16:4e4a)
+	TX_FAR _TrainerWantsToFightText
+	db "@"
+
+UnveiledGhostText: ; 58e4f (16:4e4f)
+	TX_FAR _UnveiledGhostText
+	db "@"
+
+GhostCantBeIDdText: ; 58e54 (16:4e54)
+	TX_FAR _GhostCantBeIDdText
+	db "@"
+
+PrintSendOutMonMessage: ; 58e59 (16:4e59)
+	ld hl, wEnemyMonHP
+	ld a, [hli]
+	or [hl]
+	ld hl, GoText
+	jr z, .printText
+	xor a
+	ld [H_MULTIPLICAND], a
+	ld hl, wEnemyMonHP
+	ld a, [hli]
+	ld [wcce3], a
+	ld [H_MULTIPLICAND + 1], a
+	ld a, [hl]
+	ld [wcce4], a
+	ld [H_MULTIPLICAND + 2], a
+	ld a, 25
+	ld [H_MULTIPLIER], a
+	call Multiply
+	ld hl, wEnemyMonMaxHP
+	ld a, [hli]
+	ld b, [hl]
+	srl a
+	rr b
+	srl a
+	rr b
+	ld a, b
+	ld b, $4
+	ld [H_DIVISOR], a ; enemy mon max HP divided by 4
+	call Divide
+	ld a, [H_QUOTIENT + 3] ; a = (enemy mon current HP * 25) / (enemy max HP / 4); this approximates the current percentage of max HP
+	ld hl, GoText ; 70% or greater
+	cp 70
+	jr nc, .printText
+	ld hl, DoItText ; 40% - 69%
+	cp 40
+	jr nc, .printText
+	ld hl, GetmText ; 10% - 39%
+	cp 10
+	jr nc, .printText
+	ld hl, EnemysWeakText ; 0% - 9%
+.printText
+	jp PrintText
+
+GoText: ; 58eae (16:4eae)
+	TX_FAR _GoText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+DoItText: ; 58eb5 (16:4eb5)
+	TX_FAR _DoItText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+GetmText: ; 58ebc (16:4ebc)
+	TX_FAR _GetmText
+	db $08 ; asm
+	jr PrintPlayerMon1Text
+
+EnemysWeakText: ; 58ec3 (16:4ec3)
+	TX_FAR _EnemysWeakText
+	db $08 ; asm
+
+PrintPlayerMon1Text:
+	ld hl, PlayerMon1Text
+	ret
+
+PlayerMon1Text: ; 58ecc (16:4ecc)
+	TX_FAR _PlayerMon1Text
+	db "@"
+
+RetreatMon: ; 58ed1 (16:4ed1)
+	ld hl, PlayerMon2Text
+	jp PrintText
+
+PlayerMon2Text: ; 58ed7 (16:4ed7)
+	TX_FAR _PlayerMon2Text
+	db $08 ; asm
+	push de
+	push bc
+	ld hl, wEnemyMonHP + 1
+	ld de, wcce4
+	ld b, [hl]
+	dec hl
+	ld a, [de]
+	sub b
+	ld [$ff98], a
+	dec de
+	ld b, [hl]
+	ld a, [de]
+	sbc b
+	ld [$ff97], a
+	ld a, $19
+	ld [H_POWEROFTEN], a
+	call Multiply
+	ld hl, wEnemyMonMaxHP
+	ld a, [hli]
+	ld b, [hl]
+	srl a
+	rr b
+	srl a
+	rr b
+	ld a, b
+	ld b, $4
+	ld [H_POWEROFTEN], a
+	call Divide
+	pop bc
+	pop de
+	ld a, [$ff98]
+	ld hl, EnoughText
+	and a
+	ret z
+	ld hl, ComeBackText
+	cp $1e
+	ret c
+	ld hl, OKExclamationText
+	cp $46
+	ret c
+	ld hl, GoodText
+	ret
+
+EnoughText: ; 58f25 (16:4f25)
+	TX_FAR _EnoughText
+	db $08 ; asm
+	jr PrintComeBackText
+
+OKExclamationText: ; 58f2c (16:4f2c)
+	TX_FAR _OKExclamationText
+	db $08 ; asm
+	jr PrintComeBackText
+
+GoodText: ; 58f33 (16:4f33)
+	TX_FAR _GoodText
+	db $08 ; asm
+	jr PrintComeBackText
+
+PrintComeBackText: ; 58f3a (16:4f3a)
+	ld hl, ComeBackText
+	ret
+
+ComeBackText: ; 58f3e (16:4f3e)
+	TX_FAR _ComeBackText
+	db "@"
--- a/engine/battle/core.asm
+++ b/engine/battle/core.asm
@@ -454,7 +454,8 @@
 	ld b, 0
 	add hl, bc
 	ld a, [hl]
-	cp METRONOME ; a MIRROR MOVE check is missing, might lead to a desync in link battles when combined with multi-turn moves
+	cp METRONOME ; a MIRROR MOVE check is missing, might lead to a desync in link battles
+	             ; when combined with multi-turn moves
 	jr nz, .asm_3c2dd
 	ld [wPlayerSelectedMove], a
 .asm_3c2dd
@@ -581,7 +582,7 @@
 .poisoned
 	call PrintText
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a,BURN_PSN_ANIM
 	call PlayMoveAnimation   ; play burn/poison animation
 	pop hl
@@ -602,7 +603,7 @@
 	xor $1
 	ld [H_WHOSETURN], a
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a,ABSORB
 	call PlayMoveAnimation ; play leech seed animation (from opposing mon)
 	pop af
@@ -874,7 +875,7 @@
 	call WaitForSoundToFinish
 	jr .sfxplayed
 .wild_win
-	call Func_3c643
+	call EndLowHealthAlarm
 	ld a, MUSIC_DEFEATED_WILD_MON
 	call PlayBattleVictoryMusic
 .sfxplayed
@@ -918,7 +919,7 @@
 ; if exp all is in the bag, this will be only be half of the stat exp and normal exp, due to the above loop
 .giveExpToMonsThatFought
 	xor a
-	ld [wcc5b], a
+	ld [wBoostExpByExpAll], a
 	callab GainExperience
 	pop af
 	ret z ; return if no exp all
@@ -927,7 +928,7 @@
 ; now, set the gain exp flag for every party member
 ; half of the total stat exp and normal exp will divided evenly amongst every party member
 	ld a, $1
-	ld [wcc5b], a
+	ld [wBoostExpByExpAll], a
 	ld a, [wPartyCount]
 	ld b, 0
 .gainExpFlagsLoop
@@ -945,7 +946,7 @@
 	TX_FAR _EnemyMonFaintedText
 	db "@"
 
-Func_3c643: ; 3c643 (f:4643)
+EndLowHealthAlarm: ; 3c643 (f:4643)
 	xor a
 	ld [wLowHealthAlarm], a ;disable low health alarm
 	ld [wc02a], a
@@ -990,12 +991,12 @@
 	xor a
 	ld [W_ENEMYMOVENUM], a
 	ld [wcd6a], a
-	ld [wccd5], a
+	ld [wAILayer2Encouragement], a
 	inc a ; reset Z flag
 	ret
 
 TrainerBattleVictory: ; 3c696 (f:4696)
-	call Func_3c643
+	call EndLowHealthAlarm
 	ld b, MUSIC_DEFEATED_GYM_LEADER
 	ld a, [W_GYMLEADERNO]
 	and a
@@ -1640,7 +1641,8 @@
 	ld b, a
 	ld a, [H_QUOTIENT + 3]
 	cp b
-	jr nc, .canEscape ; if the random value was less than or equal to the quotient plus 30 times the number of attempts, the player can escape
+	jr nc, .canEscape ; if the random value was less than or equal to the quotient 
+	                  ; plus 30 times the number of attempts, the player can escape
 ; can't escape
 	ld a, $1
 	ld [wcd6a], a
@@ -1809,8 +1811,8 @@
 	ld hl, wcc2d
 	ld [hli], a
 	ld [hl], a
-	ld [wcc5b], a
-	ld [wd05b], a
+	ld [wBoostExpByExpAll], a
+	ld [wDamageMultipliers], a
 	ld [W_PLAYERMOVENUM], a
 	ld hl, wPlayerUsedMove
 	ld [hli], a
@@ -2046,8 +2048,10 @@
 	jp GoPAL_SET
 
 ; center's mon's name on the battle screen
-; if the name is 1 or 2 letters long, it is printed 2 spaces more to the right than usual (i.e. for names longer than 4 letters)
-; if the name is 3 or 4 letters long, it is printed 1 space more to the right than usual (i.e. for names longer than 4 letters)
+; if the name is 1 or 2 letters long, it is printed 2 spaces more to the right than usual
+; (i.e. for names longer than 4 letters)
+; if the name is 3 or 4 letters long, it is printed 1 space more to the right than usual
+; (i.e. for names longer than 4 letters)
 CenterMonName: ; 3ce9c (f:4e9c)
 	push de
 	inc hl
@@ -2204,7 +2208,8 @@
 	ld [wcc2d], a
 	jr z, .handleMenuSelection
 ; not Safari battle
-; swap the IDs of the item menu and party menu (this is probably because they swapped the positions of these menu items in first generation English versions)
+; swap the IDs of the item menu and party menu (this is probably because they swapped the positions
+; of these menu items in first generation English versions)
 	cp $1 ; was the item menu selected?
 	jr nz, .notItemMenu
 ; item menu was selected
@@ -3123,10 +3128,10 @@
 	jp z, ExecutePlayerMoveDone ; for selected move = FF, skip most of player's turn
 	xor a
 	ld [W_MOVEMISSED], a
-	ld [wcced], a
-	ld [wccf4], a
+	ld [wMonIsDisobedient], a
+	ld [wMoveDidntMiss], a
 	ld a, $a
-	ld [wd05b], a
+	ld [wDamageMultipliers], a
 	ld a, [wcd6a]
 	and a
 	jp nz, ExecutePlayerMoveDone
@@ -3155,8 +3160,8 @@
 PlayerCanExecuteChargingMove: ; 3d6a9 (f:56a9)
 	ld hl,W_PLAYERBATTSTATUS1
 	res ChargingUp,[hl] ; reset charging up and invulnerability statuses if mon was charging up for an attack
-	           ; being fully paralyzed or hurting oneself in confusion removes charging up status
-	           ; resulting in the Pokemon being invulnerable for the whole battle
+	                    ; being fully paralyzed or hurting oneself in confusion removes charging up status
+	                    ; resulting in the Pokemon being invulnerable for the whole battle
 	res Invulnerable,[hl]
 PlayerCanExecuteMove: ; 3d6b0 (f:56b0)
 	call PrintMonName1Text
@@ -3183,30 +3188,30 @@
 	jp c,.moveHitTest ; SetDamageEffects moves (e.g. Seismic Toss and Super Fang) skip damage calculation
 	call CriticalHitTest
 	call HandleCounterMove
-	jr z,asm_3d705
+	jr z,handleIfPlayerMoveMissed
 	call GetDamageVarsForPlayerAttack
 	call CalculateDamage
-	jp z,asm_3d74b ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest
+	jp z,playerCheckIfFlyOrChargeEffect ; for moves with 0 BP, skip any further damage calculation and, for now, skip MoveHitTest
 	               ; for these moves, accuracy tests will only occur if they are called as part of the effect itself
 	call AdjustDamageForMoveType
 	call RandomizeDamage
 .moveHitTest
 	call MoveHitTest
-asm_3d705
+handleIfPlayerMoveMissed
 	ld a,[W_MOVEMISSED]
 	and a
-	jr z,asm_3d714
+	jr z,getPlayerAnimationType
 	ld a,[W_PLAYERMOVEEFFECT]
 	sub a,EXPLODE_EFFECT 
-	jr z,asm_3d71e ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
-	jr asm_3d74b
-asm_3d714
+	jr z,playPlayerMoveAnimation ; don't play any animation if the move missed, unless it was EXPLODE_EFFECT
+	jr playerCheckIfFlyOrChargeEffect
+getPlayerAnimationType
 	ld a,[W_PLAYERMOVEEFFECT]
 	and a
-	ld a,4
-	jr z,asm_3d71e
-	ld a,5
-asm_3d71e
+	ld a,4 ; move has no effect other than dealing damage
+	jr z,playPlayerMoveAnimation
+	ld a,5 ; move has effect
+playPlayerMoveAnimation
 	push af
 	ld a,[W_PLAYERBATTSTATUS2]
 	bit 4,a
@@ -3214,7 +3219,7 @@
 	ld b,BANK(Func_79747)
 	call nz,Bankswitch
 	pop af
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,[W_PLAYERMOVENUM]
 	call PlayMoveAnimation
 	call HandleExplodingAnimation
@@ -3225,7 +3230,7 @@
 	ld b,BANK(Func_79771)
 	call nz,Bankswitch
 	jr MirrorMoveCheck
-asm_3d74b
+playerCheckIfFlyOrChargeEffect
 	ld c,$1E
 	call DelayFrames
 	ld a,[W_PLAYERMOVEEFFECT]
@@ -3236,7 +3241,7 @@
 	jr MirrorMoveCheck
 .playAnim
 	xor a
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,STATUS_AFFECTED_ANIM
 	call PlayMoveAnimation
 MirrorMoveCheck
@@ -3246,7 +3251,7 @@
 	call MirrorMoveCopyMove
 	jp z,ExecutePlayerMoveDone
 	xor a
-	ld [wcced],a
+	ld [wMonIsDisobedient],a
 	jp CheckIfPlayerNeedsToChargeUp ; if Mirror Move was successful go back to damage calculation for copied move
 .metronomeCheck
 	cp a,METRONOME_EFFECT
@@ -3272,7 +3277,7 @@
 	call PrintCriticalOHKOText
 	callab DisplayEffectiveness
 	ld a,1
-	ld [wccf4],a
+	ld [wMoveDidntMiss],a
 .notDone
 	ld a,[W_PLAYERMOVEEFFECT]
 	ld hl,AlwaysHappenSideEffects
@@ -3292,8 +3297,8 @@
 	ld a,[wPlayerNumAttacksLeft]
 	dec a
 	ld [wPlayerNumAttacksLeft],a
-	jp nz,asm_3d714 ; for multi-hit moves, apply attack until PlayerNumAttacksLeft hits 0 or the enemy faints. 
-	                ; damage calculation and accuracy tests only happen for the first hit
+	jp nz,getPlayerAnimationType ; for multi-hit moves, apply attack until PlayerNumAttacksLeft hits 0 or the enemy faints. 
+	                             ; damage calculation and accuracy tests only happen for the first hit
 	res AttackingMultipleTimes,[hl] ; clear attacking multiple times status when all attacks are over
 	ld hl,MultiHitText
 	call PrintText
@@ -3307,9 +3312,9 @@
 	ld de,1
 	call IsInArray
 	call nc,JumpMoveEffect ; move effects not included in SpecialEffects or in either of the ResidualEffect arrays,
-	                       ; which are the effects not covered yet. Rage's effect will be executed for a second time (although it's irrelevant). 
-	                       ; Includes side effects that only need to be called if the target didn't faint.
-	                       ; Responsible for executing Twineedle's second effect (poison)
+	; which are the effects not covered yet. Rage effect will be executed for a second time (though it's irrelevant).
+	; Includes side effects that only need to be called if the target didn't faint.
+	; Responsible for executing Twineedle's second side effect (poison).
 	jp ExecutePlayerMoveDone
 
 MultiHitText: ; 3d805 (f:5805)
@@ -3381,7 +3386,7 @@
 	jr z,.WakeUp ; if the number of turns hit 0, wake up
 ; fast asleep
 	xor a
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,SLP_ANIM - 1
 	call PlayMoveAnimation
 	ld hl,FastAsleepText
@@ -3465,7 +3470,7 @@
 	ld hl,IsConfusedText
 	call PrintText
 	xor a
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,CONF_ANIM - 1
 	call PlayMoveAnimation
 	call BattleRandom
@@ -3514,7 +3519,7 @@
 
 .FlyOrChargeEffect
 	xor a
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,STATUS_AFFECTED_ANIM
 	call PlayMoveAnimation
 .NotFlyOrChargeEffect
@@ -3568,7 +3573,7 @@
 	ld [hl],a
 	ld a,BIDE
 	ld [W_PLAYERMOVENUM],a
-	ld hl,asm_3d705 ; skip damage calculation, DecrementPP and MoveHitTest
+	ld hl,handleIfPlayerMoveMissed ; skip damage calculation, DecrementPP and MoveHitTest
 	jp .returnToHL
 
 .ThrashingAboutCheck
@@ -3602,7 +3607,8 @@
 	ld a,[wPlayerNumAttacksLeft]
 	dec a ; did multi-turn move end?
 	ld [wPlayerNumAttacksLeft],a
-	ld hl,asm_3d714 ; if it didn't, skip damage calculation (deal damage equal to last hit), DecrementPP and MoveHitTest
+	ld hl,getPlayerAnimationType ; if it didn't, skip damage calculation (deal damage equal to last hit), 
+	                ; DecrementPP and MoveHitTest
 	jp nz,.returnToHL
 	jp .returnToHL
 
@@ -3734,7 +3740,8 @@
 	xor a
 	ld [hl], a
 	call GetDamageVarsForPlayerAttack
-	call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage, and MoveHitTest (always hits)
+	call CalculateDamage ; ignores AdjustDamageForMoveType (type-less damage), RandomizeDamage,
+	                     ; and MoveHitTest (always hits)
 	pop af
 	pop hl
 	ld [hl], a
@@ -3744,7 +3751,7 @@
 	pop af
 	ld [hl], a
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	inc a
 	ld [H_WHOSETURN], a
 	call PlayMoveAnimation
@@ -3771,12 +3778,12 @@
 	ld [hl], a
 	ld [wd11e], a
 	call Func_3db85
-	ld a, [wcced]
+	ld a, [wMonIsDisobedient]
 	and a
 	ld hl, Used2Text
 	ret nz
 	ld a, [wd11e]
-	cp DOUBLESLAP
+	cp 3
 	ld hl, Used2Text
 	ret c
 	ld hl, Used1Text
@@ -3792,7 +3799,7 @@
 	db $08 ; asm
 
 PrintInsteadText: ; 3db39 (f:5b39)
-	ld a, [wcced]
+	ld a, [wMonIsDisobedient]
 	and a
 	jr z, PrintCF4BText
 	ld hl, InsteadText
@@ -3894,7 +3901,7 @@
 	ld de, W_ENEMYMOVEEFFECT
 .playersTurn
 	ld hl, DoesntAffectMonText
-	ld a, [wd05b]
+	ld a, [wDamageMultipliers]
 	and $7f
 	jr z, .gotTextToPrint
 	ld hl, AttackMissedText
@@ -3914,7 +3921,8 @@
 
 	; if you get here, the mon used jump kick or hi jump kick and missed
 	ld hl, W_DAMAGE ; since the move missed, W_DAMAGE will always contain 0 at this point.
-	                ; Thus, recoil damage will always be equal to 1 even if it was intended to be potential damage/8.
+	                ; Thus, recoil damage will always be equal to 1 
+	                ; even if it was intended to be potential damage/8.
 	ld a, [hli]
 	ld b, [hl]
 	srl a
@@ -3999,7 +4007,7 @@
 ; stores whether the mon will use a move in Z flag
 CheckForDisobedience: ; 3dc88 (f:5c88)
 	xor a
-	ld [wcced], a
+	ld [wMonIsDisobedient], a
 	ld a, [wLinkState]
 	cp LINK_STATE_BATTLING
 	jr nz, .checkIfMonIsTraded
@@ -4140,7 +4148,7 @@
 	cp b
 	jr z, .monDoesNothing ; mon will not use move if only one move has remaining PP
 	ld a, $1
-	ld [wcced], a
+	ld [wMonIsDisobedient], a
 	ld a, [wMaxMenuItem]
 	ld b, a
 	ld a, [wCurrentMenuItem]
@@ -4296,7 +4304,8 @@
 	jr nz, .next
 	inc l ; if the player's offensive stat is 0, bump it up to 1
 .next
-	ld b, l ; b = player's offensive stat (possibly scaled) (c already contains enemy's defensive stat (possibly scaled))
+	ld b, l ; b = player's offensive stat (possibly scaled)
+	        ; (c already contains enemy's defensive stat (possibly scaled))
 	ld a, [wBattleMonLevel]
 	ld e, a ; e = level
 	ld a, [wCriticalHitOrOHKO]
@@ -4408,7 +4417,8 @@
 	jr nz, .next
 	inc l ; if the enemy's offensive stat is 0, bump it up to 1
 .next
-	ld b, l ; b = enemy's offensive stat (possibly scaled) (c already contains player's defensive stat (possibly scaled))
+	ld b, l ; b = enemy's offensive stat (possibly scaled)
+	        ; (c already contains player's defensive stat (possibly scaled))
 	ld a, [wEnemyMonLevel]
 	ld e, a
 	ld a, [wCriticalHitOrOHKO]
@@ -4471,7 +4481,7 @@
 ;	d: base power
 ;	e: level
 
-	ld a, [$fff3] ; whose turn?
+	ld a, [H_WHOSETURN] ; whose turn?
 	and a
 	ld a, [W_PLAYERMOVEEFFECT]
 	jr z, .effect
@@ -4494,7 +4504,7 @@
 
 ; Calculate OHKO damage based on remaining HP.
 	cp a, OHKO_EFFECT
-	jp z, Func_3e016
+	jp z, JumpToOHKOMoveEffect
 
 ; Don't calculate damage for moves that don't do any.
 	ld a, d ; base power
@@ -4626,7 +4636,7 @@
 	and a
 	ret
 
-Func_3e016: ; 3e016 (f:6016)
+JumpToOHKOMoveEffect: ; 3e016 (f:6016)
 	call JumpMoveEffect
 	ld a, [W_MOVEMISSED]
 	dec a
@@ -5025,8 +5035,10 @@
 AttackSubstitute: ; 3e25e (f:625e)
 ; Unlike the two ApplyAttackToPokemon functions, Attack Substitute is shared by player and enemy.
 ; Self-confusion damage as well as Hi-Jump Kick and Jump Kick recoil cause a momentary turn swap before being applied.
-; If the user has a Substitute up and would take damage because of that, damage will be applied to the other player's Substitute.
-; Normal recoil such as from Double-Edge isn't affected by this glitch, because this function is never called in that case.
+; If the user has a Substitute up and would take damage because of that, 
+; damage will be applied to the other player's Substitute.
+; Normal recoil such as from Double-Edge isn't affected by this glitch, 
+; because this function is never called in that case.
 
 	ld hl,SubstituteTookDamageText
 	call PrintText
@@ -5050,10 +5062,11 @@
 	ld [de],a
 	ret nc
 .substituteBroke
-; If the target's Substitute breaks, W_DAMAGE isn't updated with the amount of HP the Substitute had before being attacked.
+; If the target's Substitute breaks, W_DAMAGE isn't updated with the amount of HP 
+; the Substitute had before being attacked.
 	ld h,b
 	ld l,c
-	res 4,[hl] ; unset the substitute bit
+	res HasSubstituteUp,[hl] ; unset the substitute bit
 	ld hl,SubstituteBrokeText
 	call PrintText
 ; flip whose turn it is for the next function call
@@ -5185,7 +5198,7 @@
 ; function that picks a random move for metronome
 MetronomePickMove: ; 3e348 (f:6348)
 	xor a
-	ld [wcc5b],a
+	ld [wAnimationType],a
 	ld a,METRONOME
 	call PlayMoveAnimation ; play Metronome's animation
 ; values for player turn
@@ -5293,7 +5306,7 @@
 	ld [W_DAMAGE],a
 	ld a,l
 	ld [W_DAMAGE + 1],a
-	ld hl,wd05b
+	ld hl,wDamageMultipliers
 	set 7,[hl]
 .skipSameTypeAttackBonus
 	ld a,[wd11e]
@@ -5316,13 +5329,13 @@
 	push hl
 	push bc
 	inc hl
-	ld a,[wd05b]
+	ld a,[wDamageMultipliers]
 	and a,$80
 	ld b,a
 	ld a,[hl] ; a = damage multiplier
 	ld [H_MULTIPLIER],a
 	add b
-	ld [wd05b],a
+	ld [wDamageMultipliers],a
 	xor a
 	ld [H_MULTIPLICAND],a
 	ld hl,W_DAMAGE
@@ -5536,7 +5549,8 @@
 .next
 	ld a,$0e
 	sub c
-	ld c,a ; c = 14 - EVASIONMOD (this "reflects" the value over 7, so that an increase in the target's evasion decreases the hit chance instead of increasing the hit chance)
+	ld c,a ; c = 14 - EVASIONMOD (this "reflects" the value over 7, so that an increase in the target's evasion
+	       ; decreases the hit chance instead of increasing the hit chance)
 ; zero the high bytes of the multiplicand
 	xor a
 	ld [H_MULTIPLICAND],a
@@ -5545,7 +5559,8 @@
 	ld [H_MULTIPLICAND + 2],a ; set multiplicand to move accuracy
 	push hl
 	ld d,$02 ; loop has two iterations
-; loop to do the calculations, the first iteration multiplies by the accuracy ratio and the second iteration multiplies by the evasion ratio
+; loop to do the calculations, the first iteration multiplies by the accuracy ratio and
+; the second iteration multiplies by the evasion ratio
 .loop
 	push bc
 	ld hl, StatModifierRatios  ; $76cb ; stat modifier ratios
@@ -5559,7 +5574,8 @@
 	ld [H_MULTIPLIER],a ; set multiplier to the numerator of the ratio
 	call Multiply
 	ld a,[hl]
-	ld [H_DIVISOR],a ; set divisor to the the denominator of the ratio (the dividend is the product of the previous multiplication)
+	ld [H_DIVISOR],a ; set divisor to the the denominator of the ratio
+	                 ; (the dividend is the product of the previous multiplication)
 	ld b,$04 ; number of bytes in the dividend
 	call Divide
 	ld a,[H_QUOTIENT + 3]
@@ -5623,6 +5639,7 @@
 	ld [hl], a
 	ret
 
+; for more detailed commentary, see equivalent function for player side (ExecutePlayerMove)
 ExecuteEnemyMove: ; 3e6bc (f:66bc)
 	ld a, [wEnemySelectedMove]
 	inc a
@@ -5639,13 +5656,13 @@
 	cp $4
 	ret nc
 .executeEnemyMove
-	ld hl, wccd5
+	ld hl, wAILayer2Encouragement
 	inc [hl]
 	xor a
 	ld [W_MOVEMISSED], a
-	ld [wccf4], a
+	ld [wMoveDidntMiss], a
 	ld a, $a
-	ld [wd05b], a
+	ld [wDamageMultipliers], a
 	call CheckEnemyStatusConditions
 	jr nz, .enemyHasNoSpecialConditions
 	jp [hl]
@@ -5677,7 +5694,7 @@
 	call CopyStringToCF4B
 EnemyCanExecuteMove: ; 3e72b (f:672b)
 	xor a
-	ld [wcced], a
+	ld [wMonIsDisobedient], a
 	call PrintMonName1Text
 	ld a, [W_ENEMYMOVEEFFECT]
 	ld hl, ResidualEffects1
@@ -5695,21 +5712,21 @@
 	ld hl, SetDamageEffects
 	ld de, $1
 	call IsInArray
-	jp c, Func_3e77f
+	jp c, EnemyMoveHitTest
 	call CriticalHitTest
 	call HandleCounterMove
-	jr z, asm_3e782
+	jr z, handleIfEnemyMoveMissed
 	call SwapPlayerAndEnemyLevels
 	call GetDamageVarsForEnemyAttack
 	call SwapPlayerAndEnemyLevels
 	call CalculateDamage
-	jp z, Func_3e7d1
+	jp z, EnemyCheckIfFlyOrChargeEffect
 	call AdjustDamageForMoveType
 	call RandomizeDamage
 
-Func_3e77f: ; 3e77f (f:677f)
+EnemyMoveHitTest: ; 3e77f (f:677f)
 	call MoveHitTest
-asm_3e782: ; 3e782 (f:6782)
+handleIfEnemyMoveMissed: ; 3e782 (f:6782)
 	ld a, [W_MOVEMISSED]
 	and a
 	jr z, .asm_3e791
@@ -5716,21 +5733,21 @@
 	ld a, [W_ENEMYMOVEEFFECT]
 	cp EXPLODE_EFFECT
 	jr z, asm_3e7a0
-	jr Func_3e7d1
+	jr EnemyCheckIfFlyOrChargeEffect
 .asm_3e791
 	call SwapPlayerAndEnemyLevels
 
-Func_3e794: ; 3e794 (f:6794)
+GetEnemyAnimationType: ; 3e794 (f:6794)
 	ld a, [W_ENEMYMOVEEFFECT]
 	and a
 	ld a, $1
-	jr z, asm_3e7a4
+	jr z, playEnemyMoveAnimation
 	ld a, $2
-	jr asm_3e7a4
+	jr playEnemyMoveAnimation
 asm_3e7a0: ; 3e7a0 (f:67a0)
 	call SwapPlayerAndEnemyLevels
 	xor a
-asm_3e7a4: ; 3e7a4 (f:67a4)
+playEnemyMoveAnimation: ; 3e7a4 (f:67a4)
 	push af
 	ld a, [W_ENEMYBATTSTATUS2]
 	bit HasSubstituteUp, a ; does mon have a substitute?
@@ -5738,7 +5755,7 @@
 	ld b, BANK(Func_79747)
 	call nz, Bankswitch
 	pop af
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a, [W_ENEMYMOVENUM]
 	call PlayMoveAnimation
 	call HandleExplodingAnimation
@@ -5748,24 +5765,24 @@
 	ld hl, Func_79771
 	ld b, BANK(Func_79771)
 	call nz, Bankswitch ; slide the substitute's sprite out
-	jr asm_3e7ef
+	jr EnemyCheckIfMirrorMoveEffect
 
-Func_3e7d1: ; 3e7d1 (f:67d1)
+EnemyCheckIfFlyOrChargeEffect: ; 3e7d1 (f:67d1)
 	call SwapPlayerAndEnemyLevels
 	ld c, $1e
 	call DelayFrames
 	ld a, [W_ENEMYMOVEEFFECT]
 	cp FLY_EFFECT
-	jr z, .asm_3e7e6
+	jr z, .playAnim
 	cp CHARGE_EFFECT
-	jr z, .asm_3e7e6
-	jr asm_3e7ef
-.asm_3e7e6
+	jr z, .playAnim
+	jr EnemyCheckIfMirrorMoveEffect
+.playAnim
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a,STATUS_AFFECTED_ANIM
 	call PlayMoveAnimation
-asm_3e7ef: ; 3e7ef (f:67ef)
+EnemyCheckIfMirrorMoveEffect: ; 3e7ef (f:67ef)
 	ld a, [W_ENEMYMOVEEFFECT]
 	cp MIRROR_MOVE_EFFECT
 	jr nz, .notMirrorMoveEffect
@@ -5796,7 +5813,7 @@
 	call PrintCriticalOHKOText
 	callab DisplayEffectiveness
 	ld a, 1
-	ld [wccf4], a
+	ld [wMoveDidntMiss], a
 .asm_3e83e
 	ld a, [W_ENEMYMOVEEFFECT]
 	ld hl, AlwaysHappenSideEffects
@@ -5816,7 +5833,7 @@
 	ld hl, wEnemyNumAttacksLeft
 	dec [hl]
 	pop hl
-	jp nz, Func_3e794
+	jp nz, GetEnemyAnimationType
 	res AttackingMultipleTimes, [hl] ; mon is no longer hitting multiple times
 	ld hl, HitXTimesText
 	call PrintText
@@ -5854,7 +5871,7 @@
 	ld hl, FastAsleepText
 	call PrintText
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a,SLP_ANIM
 	call PlayMoveAnimation
 	jr .next1
@@ -5930,7 +5947,7 @@
 	ld hl, IsConfusedText
 	call PrintText
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a,CONF_ANIM
 	call PlayMoveAnimation
 	call BattleRandom
@@ -5973,7 +5990,7 @@
 	pop af
 	ld [hl], a
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld [H_WHOSETURN], a
 	ld a, POUND
 	call PlayMoveAnimation
@@ -6014,7 +6031,7 @@
 	jr .notFlyOrChargeEffect
 .flyOrChargeEffect
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a, STATUS_AFFECTED_ANIM
 	call PlayMoveAnimation
 .notFlyOrChargeEffect
@@ -6068,7 +6085,7 @@
 	ld a, BIDE
 	ld [W_ENEMYMOVENUM], a
 	call SwapPlayerAndEnemyLevels
-	ld hl, asm_3e782
+	ld hl, handleIfEnemyMoveMissed
 	jp .enemyReturnToHL
 .checkIfThrashingAbout
 	bit ThrashingAbout, [hl] ; is mon using thrash or petal dance?
@@ -6099,7 +6116,7 @@
 	call PrintText
 	ld hl, wEnemyNumAttacksLeft
 	dec [hl]
-	ld hl, Func_3e794
+	ld hl, GetEnemyAnimationType
 	jp nz, .enemyReturnToHL
 	jp .enemyReturnToHL
 .checkIfUsingRage
@@ -6787,7 +6804,7 @@
 	and a
 	ret nz
 	ld a, 5
-	ld [wcc5b], a
+	ld [wAnimationType], a
 
 PlayMoveAnimation: ; 3ef07 (f:6f07)
 	ld [W_ANIMATIONID],a
@@ -6955,6 +6972,7 @@
 	ld c, a
 	jp LoadUncompressedSpriteData
 
+; unreferenced
 Func_3f069: ; 3f069 (f:7069)
 	xor a
 	ld [wc0f1], a
@@ -7030,6 +7048,7 @@
 	dec b
 	jr nz, .asm_3f0de
 	ret
+	
 .asm_3f0ed
 	push bc
 	ld b, $0
@@ -7053,7 +7072,7 @@
 	jr nz, .asm_3f0f4
 	ret
 
-LoadMonBackPic:
+LoadMonBackPic: ; 3f103 (f:7103)
 ; Assumes the monster's attributes have
 ; been loaded with GetMonHeader.
 	ld a, [wBattleMonSpecies2]
@@ -7080,14 +7099,14 @@
 	ret
 
 _JumpMoveEffect: ; 3f138 (f:7138)
-	ld a, [$fff3]  ;whose turn?
+	ld a, [H_WHOSETURN]
 	and a
 	ld a, [W_PLAYERMOVEEFFECT]
 	jr z, .next1
 	ld a, [W_ENEMYMOVEEFFECT]
 .next1
-	dec a         ;subtract 1, there is no special effect for 00
-	add a         ;x2, 16bit pointers
+	dec a ; subtract 1, there is no special effect for 00
+	add a ; x2, 16bit pointers
 	ld hl, MoveEffectPointerTable
 	ld b, 0
 	ld c, a
@@ -7095,7 +7114,7 @@
 	ld a, [hli]
 	ld h, [hl]
 	ld l, a
-	jp [hl]       ;jump to special effect handler
+	jp [hl] ; jump to special effect handler
 
 MoveEffectPointerTable: ; 3f150 (f:7150)
 	 dw SleepEffect               ; unused effect
@@ -7223,7 +7242,7 @@
 	and $7
 	jr z, .setSleepCounter
 	ld [de], a
-	call Func_3fb89
+	call PlayCurrentMoveAnimation2
 	ld hl, FellAsleepText
 	jp PrintText
 .didntAffect
@@ -7309,10 +7328,10 @@
 	cp POISON_EFFECT
 	jr z, .asm_3f2cd
 	ld a, b
-	call Func_3fb96
+	call PlayBattleAnimation2
 	jp PrintText
 .asm_3f2cd
-	call Func_3fb89
+	call PlayCurrentMoveAnimation2
 	jp PrintText
 .noEffect
 	ld a, [de]
@@ -7357,10 +7376,10 @@
 
 FreezeBurnParalyzeEffect: ; 3f30c (f:730c)
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	call CheckTargetSubstitute ; test bit 4 of d063/d068 flags [target has substitute flag]
 	ret nz ; return if they have a substitute, can't effect them
-	ld a, [$fff3]
+	ld a, [H_WHOSETURN]
 	and a
 	jp nz, opponentAttacker
 	ld a, [wEnemyMonStatus]
@@ -7472,7 +7491,7 @@
 ; any fire-type move that has a chance inflict burn (all but Fire Spin) will defrost a frozen target
 	and a, 1 << FRZ	; are they frozen?
 	ret z ; return if so
-	ld a, [$fff3]
+	ld a, [H_WHOSETURN]
 	and a
 	jr nz, .opponent
 	;player [attacker]
@@ -7568,7 +7587,7 @@
 	jr nz, .recalculateStat
 	ld a, [hl]
 	sbc 999 / $100
-	jp z, Func_3f520
+	jp z, RestoreOriginalStatModifier
 .recalculateStat ; recalculate affected stat
                  ; paralysis and burn penalties, as well as badge boosts are ignored
 	push hl
@@ -7661,7 +7680,7 @@
 	call QuarterSpeedDueToParalysis ; apply speed penalty to the player whose turn is not, if it's paralyzed
 	jp HalveAttackDueToBurn ; apply attack penalty to the player whose turn is not, if it's burned
 
-Func_3f520: ; 3f520 (f:7520)
+RestoreOriginalStatModifier: ; 3f520 (f:7520)
 	pop hl
 	dec [hl]
 
@@ -7838,7 +7857,7 @@
 	ld a, [de]
 	cp $44
 	jr nc, .ApplyBadgeBoostsAndStatusPenalties
-	call Func_3fb89
+	call PlayCurrentMoveAnimation2
 .ApplyBadgeBoostsAndStatusPenalties
 	ld a, [H_WHOSETURN]
 	and a
@@ -7869,7 +7888,7 @@
 	ld a, [de]
 	cp $44
 	ret nc
-	jp Func_3fb4e
+	jp ConditionalPrintButItFailed
 
 MonsStatsFellText: ; 3f661 (f:7661)
 	TX_FAR _MonsStatsFellText
@@ -7961,7 +7980,7 @@
 	ld [bc], a ; set Bide counter to 2 or 3 at random
 	ld a, [H_WHOSETURN]
 	add XSTATITEM_ANIM
-	jp Func_3fb96
+	jp PlayBattleAnimation2
 
 ThrashPetalDanceEffect: ; 3f717 (f:7717)
 	ld hl, W_PLAYERBATTSTATUS1
@@ -7980,7 +7999,7 @@
 	ld [de], a ; set thrash/petal dance counter to 2 or 3 at random
 	ld a, [H_WHOSETURN]
 	add ANIM_B0
-	jp Func_3fb96
+	jp PlayBattleAnimation2
 
 SwitchAndTeleportEffect: ; 3f739 (f:7739)
 	ld a, [H_WHOSETURN]
@@ -8014,7 +8033,7 @@
 .asm_3f76e
 	call ReadPlayerMonCurHPAndStatus
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	inc a
 	ld [wEscapedFromBattle], a
 	ld a, [W_PLAYERMOVENUM]
@@ -8056,7 +8075,7 @@
 .asm_3f7c1
 	call ReadPlayerMonCurHPAndStatus
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	inc a
 	ld [wEscapedFromBattle], a
 	ld a, [W_ENEMYMOVENUM]
@@ -8068,7 +8087,7 @@
 	ld a, [W_ENEMYMOVENUM]
 	cp TELEPORT
 	jp nz, PrintText
-	jp Func_3fb4e
+	jp ConditionalPrintButItFailed
 .asm_3f7e4
 	push af
 	call PlayBattleAnimation
@@ -8197,7 +8216,7 @@
 	ld b, ANIM_C0
 .notDigOrFly
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a, b
 	call PlayBattleAnimation
 	ld a, [de]
@@ -8329,7 +8348,7 @@
 	ld [bc], a ; confusion status will last 2-5 turns
 	pop af
 	cp CONFUSION_SIDE_EFFECT
-	call nz, Func_3fb89
+	call nz, PlayCurrentMoveAnimation2
 	ld hl, BecameConfusedText
 	jp PrintText
 
@@ -8342,7 +8361,7 @@
 	ret z
 	ld c, $32
 	call DelayFrames
-	jp Func_3fb4e
+	jp ConditionalPrintButItFailed
 
 ParalyzeEffect: ; 3f9b1 (f:79b1)
 	ld hl, ParalyzeEffect_
@@ -8350,8 +8369,8 @@
 	jp Bankswitch
 
 SubstituteEffect: ; 3f9b9 (f:79b9)
-	ld hl, SubstituteEffectHandler
-	ld b, BANK(SubstituteEffectHandler)
+	ld hl, SubstituteEffect_
+	ld b, BANK(SubstituteEffect_)
 	jp Bankswitch
 
 HyperBeamEffect: ; 3f9c1 (f:79c1)
@@ -8534,7 +8553,7 @@
 	swap c
 	add c
 	ld [de], a
-	call Func_3fb89
+	call PlayCurrentMoveAnimation2
 	ld hl, wccee
 	ld a, [H_WHOSETURN]
 	and a
@@ -8597,10 +8616,10 @@
 	TX_FAR _NoEffectText
 	db "@"
 
-Func_3fb4e: ; 3fb4e (f:7b4e)
-	ld a, [wccf4]
+ConditionalPrintButItFailed: ; 3fb4e (f:7b4e)
+	ld a, [wMoveDidntMiss]
 	and a
-	ret nz
+	ret nz ; return if the side effect failed, yet the attack was successful
 
 PrintButItFailedText_: ; 3fb53 (f:7b53)
 	ld hl, ButItFailedText
@@ -8642,30 +8661,35 @@
 	pop hl
 	ret
 
-Func_3fb89: ; 3fb89 (f:7b89)
+PlayCurrentMoveAnimation2: ; 3fb89 (f:7b89)
+; animation at MOVENUM will be played unless MOVENUM is 0
+; plays wAnimationType 3 or 6
 	ld a, [H_WHOSETURN]
 	and a
 	ld a, [W_PLAYERMOVENUM]
-	jr z, .asm_3fb94
+	jr z, .notEnemyTurn
 	ld a, [W_ENEMYMOVENUM]
-.asm_3fb94
+.notEnemyTurn
 	and a
 	ret z
 
-Func_3fb96: ; 3fb96 (f:7b96)
+PlayBattleAnimation2: ; 3fb96 (f:7b96)
+; play animation ID at a and animation type 6 or 3
 	ld [W_ANIMATIONID], a
 	ld a, [H_WHOSETURN]
 	and a
 	ld a, $6
-	jr z, .asm_3fba2
+	jr z, .storeAnimationType
 	ld a, $3
-.asm_3fba2
-	ld [wcc5b], a
-	jp Func_3fbbc
+.storeAnimationType
+	ld [wAnimationType], a
+	jp PlayBattleAnimationGotID
 
 PlayCurrentMoveAnimation: ; 3fba8 (f:7ba8)
+; animation at MOVENUM will be played unless MOVENUM is 0
+; resets wAnimationType
 	xor a
-	ld [wcc5b], a
+	ld [wAnimationType], a
 	ld a, [H_WHOSETURN]
 	and a
 	ld a, [W_PLAYERMOVENUM]
@@ -8676,9 +8700,11 @@
 	ret z
 
 PlayBattleAnimation: ; 3fbb9 (f:7bb9)
+; play animation ID at a and predefined animation type
 	ld [W_ANIMATIONID], a
 
-Func_3fbbc: ; 3fbbc (f:7bbc)
+PlayBattleAnimationGotID: ; 3fbbc (f:7bbc)
+; play animation at W_ANIMATIONID
 	push hl
 	push de
 	push bc
--- a/engine/battle/d.asm
+++ /dev/null
@@ -1,23 +1,0 @@
-; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names
-DisplayLinkBattleVersusTextBox: ; 372d6 (d:72d6)
-	call LoadTextBoxTilePatterns
-	hlCoord 3, 4
-	ld b, $7
-	ld c, $c
-	call TextBoxBorder
-	hlCoord 4, 5
-	ld de, wPlayerName
-	call PlaceString
-	hlCoord 4, 10
-	ld de, wLinkEnemyTrainerName
-	call PlaceString
-; place bold "VS" tiles between the names
-	hlCoord 9, 8
-	ld a, $69
-	ld [hli], a
-	ld [hl], $6a
-	xor a
-	ld [wUpdateSpritesEnabled], a
-	callab SetupPlayerAndEnemyPokeballs
-	ld c, 150
-	jp DelayFrames
--- /dev/null
+++ b/engine/battle/decrement_pp.asm
@@ -1,0 +1,43 @@
+DecrementPP: ; 68000 (1a:4000)
+; after using a move, decrement pp in battle and (if not transformed?) in party
+	ld a, [de]
+	cp a, STRUGGLE
+	ret z                ; if the pokemon is using "struggle", there's nothing to do
+	                     ; we don't decrement PP for "struggle"
+	ld hl, W_PLAYERBATTSTATUS1
+	ld a, [hli]          ; load the W_PLAYERBATTSTATUS1 pokemon status flags and increment hl to load the
+	                     ; W_PLAYERBATTSTATUS2 status flags later
+	and a, (1 << StoringEnergy) | (1 << ThrashingAbout) | (1 << AttackingMultipleTimes)
+	ret nz               ; if any of these statuses are true, don't decrement PP
+	bit UsingRage, [hl]         
+	ret nz               ; don't decrement PP either if Pokemon is using Rage
+	ld hl, wBattleMonPP  ; PP of first move (in battle)
+	
+; decrement PP in the battle struct	
+	call .DecrementPP    
+	
+; decrement PP in the party struct	
+	ld a, [W_PLAYERBATTSTATUS3]        
+	bit Transformed, a
+	ret nz               ; Return if transformed. Pokemon Red stores the "current pokemon's" PP
+	                     ; separately from the "Pokemon in your party's" PP.  This is
+	                     ; duplication -- in all cases *other* than Pokemon with Transform.
+	                     ; Normally, this means we have to go on and make the same
+	                     ; modification to the "party's pokemon" PP that we made to the
+	                     ; "current pokemon's" PP.  But, if we're dealing with a Transformed
+	                     ; Pokemon, it has separate PP for the move set that it copied from
+	                     ; its opponent, which is *not* the same as its real PP as part of your
+	                     ; party.  So we return, and don't do that part.
+
+	ld hl, wPartyMon1PP  ; PP of first move (in party)
+	ld a, [wPlayerMonNumber] ; which mon in party is active
+	ld bc, wPartyMon2 - wPartyMon1 
+	call AddNTimes       ; calculate address of the mon to modify
+.DecrementPP
+	ld a, [wPlayerMoveListIndex] ; which move (0, 1, 2, 3) did we use?
+	ld c, a
+	ld b, 0
+	add hl ,bc           ; calculate the address in memory of the PP we need to decrement
+	                     ; based on the move chosen.
+	dec [hl]             ; Decrement PP
+	ret
--- /dev/null
+++ b/engine/battle/display_effectiveness.asm
@@ -1,0 +1,18 @@
+DisplayEffectiveness: ; 2fb7b (b:7b7b)
+	ld a, [wDamageMultipliers]
+	and a, $7F
+	cp a, $0A
+	ret z
+	ld hl, SuperEffectiveText
+	jr nc, .done
+	ld hl, NotVeryEffectiveText
+.done
+	jp PrintText
+
+SuperEffectiveText: ; 2fb8e (b:7b8e)
+	TX_FAR _SuperEffectiveText
+	db "@"
+
+NotVeryEffectiveText: ; 2fb93 (b:7b93)
+	TX_FAR _NotVeryEffectiveText
+	db "@"
--- /dev/null
+++ b/engine/battle/draw_hud_pokeball_gfx.asm
@@ -1,0 +1,191 @@
+DrawAllPokeballs: ; 3a849 (e:6849)
+	call LoadPartyPokeballGfx
+	call SetupOwnPartyPokeballs
+	ld a, [W_ISINBATTLE] ; W_ISINBATTLE
+	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, vSprites + $310
+	ld bc, (BANK(PokeballTileGraphics) << 8) + $04
+	jp CopyVideoData
+
+SetupOwnPartyPokeballs: ; 3a869 (e:6869)
+	call PlacePlayerHUDTiles
+	ld hl, wPartyMon1
+	ld de, wPartyCount ; wPartyCount
+	call SetupPokeballs
+	ld a, $60
+	ld hl, W_BASECOORDX ; wd081
+	ld [hli], a
+	ld [hl], a
+	ld a, $8
+	ld [wTrainerEngageDistance], a
+	ld hl, wOAMBuffer
+	jp WritePokeballOAMData
+
+SetupEnemyPartyPokeballs: ; 3a887 (e:6887)
+	call PlaceEnemyHUDTiles
+	ld hl, wEnemyMons
+	ld de, wEnemyPartyCount ; wEnemyPartyCount
+	call SetupPokeballs
+	ld hl, W_BASECOORDX ; wd081
+	ld a, $48
+	ld [hli], a
+	ld [hl], $20
+	ld a, $f8
+	ld [wTrainerEngageDistance], a
+	ld hl, wOAMBuffer + PARTY_LENGTH * 4
+	jp WritePokeballOAMData
+
+SetupPokeballs: ; 0x3a8a6
+	ld a, [de]
+	push af
+	ld de, wBuffer
+	ld c, PARTY_LENGTH
+	ld a, $34 ; empty pokeball
+.emptyloop
+	ld [de], a
+	inc de
+	dec c
+	jr nz, .emptyloop
+	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
+
+WritePokeballOAMData: ; 3a8e1 (e:68e1)
+	ld de, wBuffer
+	ld c, PARTY_LENGTH
+.loop
+	ld a, [W_BASECOORDY] ; wd082
+	ld [hli], a
+	ld a, [W_BASECOORDX] ; wd081
+	ld [hli], a
+	ld a, [de]
+	ld [hli], a
+	xor a
+	ld [hli], a
+	ld a, [W_BASECOORDX] ; wd081
+	ld b, a
+	ld a, [wTrainerEngageDistance]
+	add b
+	ld [W_BASECOORDX], a ; wd081
+	inc de
+	dec c
+	jr nz, .loop
+	ret
+
+PlacePlayerHUDTiles: ; 3a902 (e:6902)
+	ld hl, PlayerBattleHUDGraphicsTiles ; $6916
+	ld de, wTrainerFacingDirection
+	ld bc, $3
+	call CopyData
+	hlCoord 18, 10
+	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, wTrainerFacingDirection
+	ld bc, $3
+	call CopyData
+	hlCoord 1, 2
+	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, [wTrainerScreenY]
+	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, [wTrainerScreenX]
+	ld [hl], a
+	ret
+
+SetupPlayerAndEnemyPokeballs: ; 3a948 (e:6948)
+	call LoadPartyPokeballGfx
+	ld hl, wPartyMon1Species ; wPartyMon1Species (aliases: wPartyMon1)
+	ld de, wPartyCount ; wPartyCount
+	call SetupPokeballs
+	ld hl, W_BASECOORDX ; wd081
+	ld a, $50
+	ld [hli], a
+	ld [hl], $40
+	ld a, $8
+	ld [wTrainerEngageDistance], a
+	ld hl, wOAMBuffer
+	call WritePokeballOAMData
+	ld hl, wEnemyMons ; wEnemyMon1Species
+	ld de, wEnemyPartyCount ; wEnemyPartyCount
+	call SetupPokeballs
+	ld hl, W_BASECOORDX ; wd081
+	ld a, $50
+	ld [hli], a
+	ld [hl], $68
+	ld hl, wOAMBuffer + $18
+	jp WritePokeballOAMData
+
+; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (faited) and pokeball slot (no mon)
+PokeballTileGraphics:: ; 3a97e (e:697e)
+	INCBIN "gfx/pokeball.2bpp"
--- a/engine/battle/e.asm
+++ /dev/null
@@ -1,1565 +1,0 @@
-; does nothing since no stats are ever selected (barring glitches)
-DoubleSelectedStats: ; 39680 (e:5680)
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [wPlayerStatsToDouble]
-	ld hl, wBattleMonAttack + 1
-	jr z, .notEnemyTurn
-	ld a, [wEnemyStatsToDouble]
-	ld hl, wEnemyMonAttack + 1
-.notEnemyTurn
-	ld c, 4
-	ld b, a
-.loop
-	srl b
-	call c, .doubleStat
-	inc hl
-	inc hl
-	dec c
-	ret z
-	jr .loop
-
-.doubleStat
-	ld a, [hl]
-	add a
-	ld [hld], a
-	ld a, [hl]
-	rl a
-	ld [hli], a
-	ret
-
-; does nothing since no stats are ever selected (barring glitches)
-HalveSelectedStats: ; 396a7 (e:56a7)
-	ld a, [H_WHOSETURN]
-	and a
-	ld a, [wPlayerStatsToHalve]
-	ld hl, wBattleMonAttack
-	jr z, .notEnemyTurn
-	ld a, [wEnemyStatsToHalve]
-	ld hl, wEnemyMonAttack
-.notEnemyTurn
-	ld c, 4
-	ld b, a
-.loop
-	srl b
-	call c, .halveStat
-	inc hl
-	inc hl
-	dec c
-	ret z
-	jr .loop
-
-.halveStat
-	ld a, [hl]
-	srl a
-	ld [hli], a
-	rr [hl]
-	or [hl]
-	jr nz, .nonzeroStat
-	ld [hl], 1
-.nonzeroStat
-	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 [wEnemyMonSpecies2], a
-	ld b, $1
-	call GoPAL_SET
-	callab _LoadTrainerPic
-	hlCoord 19, 0
-	ld c, $0
-.scrollLoop
-	inc c
-	ld a, c
-	cp 7
-	ret z
-	ld d, $0
-	push bc
-	push hl
-.drawTrainerPicLoop
-	call DrawTrainerPicColumn
-	inc hl
-	ld a, 7
-	add d
-	ld d, a
-	dec c
-	jr nz, .drawTrainerPicLoop
-	ld c, 4
-	call DelayFrames
-	pop hl
-	pop bc
-	dec hl
-	jr .scrollLoop
-
-; write one 7-tile column of the trainer pic to the tilemap
-DrawTrainerPicColumn: ; 39707 (e:5707)
-	push hl
-	push de
-	push bc
-	ld e, 7
-.loop
-	ld [hl], d
-	ld bc, SCREEN_WIDTH
-	add hl, bc
-	inc d
-	dec e
-	jr nz, .loop
-	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, wHPBarMaxHP  ; 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, wHPBarMaxHP
-	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, wHPBarMaxHP  ; temp move selection array
-	ld de, wEnemyMonMoves  ; 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, wHPBarMaxHP  ; temp move selection array
-	ld de, wEnemyMonMoves  ; 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, wHPBarMaxHP    ; use created temporary array as move set
-	ret
-.useOriginalMoveSet
-	ld hl, wEnemyMonMoves    ; 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, [wBattleMonStatus]
-	and a
-	ret z       ; return if no status ailment on player's mon
-	ld hl, wBuffer - 1  ; temp move selection array (-1 byte offest)
-	ld de, wEnemyMonMoves  ; 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, [wccd5]
-	cp $1
-	ret nz
-	ld hl, wBuffer - 1  ; temp move selection array (-1 byte offest)
-	ld de, wEnemyMonMoves  ; 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, wBuffer - 1  ; temp move selection array (-1 byte offest)
-	ld de, wEnemyMonMoves  ; 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, [wd11e]
-	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, wEnemyMonMoves  ; 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,W_ENEMYMOVENUM
-	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
-	money 1500
-
-	dw BugCatcherPic
-	money 1000
-
-	dw LassPic
-	money 1500
-
-	dw SailorPic
-	money 3000
-
-	dw JrTrainerMPic
-	money 2000
-
-	dw JrTrainerFPic
-	money 2000
-
-	dw PokemaniacPic
-	money 5000
-
-	dw SuperNerdPic
-	money 2500
-
-	dw HikerPic
-	money 3500
-
-	dw BikerPic
-	money 2000
-
-	dw BurglarPic
-	money 9000
-
-	dw EngineerPic
-	money 5000
-
-	dw JugglerPic
-	money 3500
-
-	dw FisherPic
-	money 3500
-
-	dw SwimmerPic
-	money 500
-
-	dw CueBallPic
-	money 2500
-
-	dw GamblerPic
-	money 7000
-
-	dw BeautyPic
-	money 7000
-
-	dw PsychicPic
-	money 1000
-
-	dw RockerPic
-	money 2500
-
-	dw JugglerPic
-	money 3500
-
-	dw TamerPic
-	money 4000
-
-	dw BirdKeeperPic
-	money 2500
-
-	dw BlackbeltPic
-	money 2500
-
-	dw Rival1Pic
-	money 3500
-
-	dw ProfOakPic
-	money 9900
-
-	dw ChiefPic
-	money 3000
-
-	dw ScientistPic
-	money 5000
-
-	dw GiovanniPic
-	money 9900
-
-	dw RocketPic
-	money 3000
-
-	dw CooltrainerMPic
-	money 3500
-
-	dw CooltrainerFPic
-	money 3500
-
-	dw BrunoPic
-	money 9900
-
-	dw BrockPic
-	money 9900
-
-	dw MistyPic
-	money 9900
-
-	dw LtSurgePic
-	money 9900
-
-	dw ErikaPic
-	money 9900
-
-	dw KogaPic
-	money 9900
-
-	dw BlainePic
-	money 9900
-
-	dw SabrinaPic
-	money 9900
-
-	dw GentlemanPic
-	money 7000
-
-	dw Rival2Pic
-	money 6500
-
-	dw Rival3Pic
-	money 9900
-
-	dw LoreleiPic
-	money 9900
-
-	dw ChannelerPic
-	money 3000
-
-	dw AgathaPic
-	money 9900
-
-	dw LancePic
-	money 9900
-
-INCLUDE "text/trainer_names.asm"
-
-; formats a string at wMovesString that lists the moves at wMoves
-FormatMovesString: ; 39b87 (e:5b87)
-	ld hl, wMoves
-	ld de, wMovesString
-	ld b, $0
-.printMoveNameLoop
-	ld a, [hli]
-	and a ; end of move list?
-	jr z, .printDashLoop ; print dashes when no moves are left
-	push hl
-	ld [wd0b5], a
-	ld a, BANK(MoveNames)
-	ld [wPredefBank], a
-	ld a, MOVE_NAME
-	ld [wNameListType], a
-	call GetName
-	ld hl, wcd6d
-.copyNameLoop
-	ld a, [hli]
-	cp $50
-	jr z, .doneCopyingName
-	ld [de], a
-	inc de
-	jr .copyNameLoop
-.doneCopyingName
-	ld a, b
-	ld [wcd6c], a
-	inc b
-	ld a, $4e ; line break
-	ld [de], a
-	inc de
-	pop hl
-	ld a, b
-	cp NUM_MOVES
-	jr z, .done
-	jr .printMoveNameLoop
-.printDashLoop
-	ld a, "-"
-	ld [de], a
-	inc de
-	inc b
-	ld a, b
-	cp NUM_MOVES
-	jr z, .done
-	ld a, $4e ; line break
-	ld [de], a
-	inc de
-	jr .printDashLoop
-.done
-	ld a, "@"
-	ld [de], a
-	ret
-
-; XXX this is called in a few places, but it doesn't appear to do anything useful
-Func_39bd5: ; 39bd5 (e:5bd5)
-	ld a, [wd11b]
-	cp $1
-	jr nz, .asm_39be6
-	ld hl, wEnemyPartyCount
-	ld de, wEnemyMonOT
-	ld a, ENEMYOT_NAME
-	jr .asm_39c18
-.asm_39be6
-	cp $4
-	jr nz, .calcAttackStat4
-	ld hl, wPartyCount
-	ld de, wPartyMonOT
-	ld a, PLAYEROT_NAME
-	jr .asm_39c18
-.calcAttackStat4
-	cp $5
-	jr nz, .asm_39c02
-	ld hl, wStringBuffer2 + 11
-	ld de, MonsterNames
-	ld a, MONSTER_NAME
-	jr .asm_39c18
-.asm_39c02
-	cp $2
-	jr nz, .asm_39c10
-	ld hl, wNumBagItems
-	ld de, ItemNames
-	ld a, ITEM_NAME
-	jr .asm_39c18
-.asm_39c10
-	ld hl, wStringBuffer2 + 11
-	ld de, ItemNames
-	ld a, ITEM_NAME
-.asm_39c18
-	ld [wNameListType], a
-	ld a, l
-	ld [wList], a
-	ld a, h
-	ld [wList + 1], a
-	ld a, e
-	ld [wcf8d], a
-	ld a, d
-	ld [wcf8e], a
-	ld bc, ItemPrices
-	ld a, c
-	ld [wItemPrices], a
-	ld a, b
-	ld [wItemPrices + 1], a
-	ret
-
-; get species of mon e in list [wcc49] for LoadMonData
-GetMonSpecies: ; 39c37 (e:5c37)
-	ld hl, wPartySpecies
-	ld a, [wcc49]
-	and a
-	jr z, .getSpecies
-	dec a
-	jr z, .enemyParty
-	ld hl, wBoxSpecies
-	jr .getSpecies
-.enemyParty
-	ld hl, wEnemyPartyMons
-.getSpecies
-	ld d, 0
-	add hl, de
-	ld a, [hl]
-	ld [wcf91], a
-	ret
-
-ReadTrainer: ; 39c53 (e:5c53)
-
-; don't change any moves in a link battle
-	ld a,[wLinkState]
-	and a
-	ret nz
-
-; set [wEnemyPartyCount] to 0, [wEnemyPartyMons] 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 [wcf91],a ; write species somewhere (XXX why?)
-	ld a,1
-	ld [wcc49],a
-	push hl
-	call AddPartyMon
-	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 [wcf91],a
-	ld a,1
-	ld [wcc49],a
-	push hl
-	call AddPartyMon
-	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,wEnemyMon1Moves + 2
-	ld bc,wEnemyMon2 - wEnemyMon1
-	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 [wEnemyMon5Moves + 2],a
-	jr .FinishUp
-.ChampionRival ; give moves to his team
-
-; pidgeot
-	ld a,SKY_ATTACK
-	ld [wEnemyMon1Moves + 2],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 [wEnemyMon6Moves + 2],a
-.FinishUp ; XXX this needs documenting
-	xor a       ; clear D079-D07B
-	ld de,wd079
-	ld [de],a
-	inc de
-	ld [de],a
-	inc de
-	ld [de],a
-	ld a,[W_CURENEMYLVL]
-	ld b,a
-.LastLoop
-	ld hl,wd047
-	ld c,2
-	push bc
-	predef AddBCDPredef
-	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,[wLinkState]
-	cp LINK_STATE_BATTLING
-	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 Random
-	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 AISwitchIfEnoughMons
-
-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 AICheckIfHPBelowFraction
-	jp c,AIUseHyperPotion
-	ld a,5
-	call AICheckIfHPBelowFraction
-	ret nc
-	jp AISwitchIfEnoughMons
-
-BrockAI: ; 3a614 (e:6614)
-; if his active monster has a status condition, use a full heal
-	ld a,[wEnemyMonStatus]
-	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 AICheckIfHPBelowFraction
-	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 AICheckIfHPBelowFraction
-	ret nc
-	jp AIUseHyperPotion
-
-Sony2AI: ; 3a64c (e:664c)
-	cp $20
-	ret nc
-	ld a,5
-	call AICheckIfHPBelowFraction
-	ret nc
-	jp AIUsePotion
-
-Sony3AI: ; 3a658 (e:6658)
-	cp $20
-	ret nc
-	ld a,5
-	call AICheckIfHPBelowFraction
-	ret nc
-	jp AIUseFullRestore
-
-LoreleiAI: ; 3a664 (e:6664)
-	cp $80
-	ret nc
-	ld a,5
-	call AICheckIfHPBelowFraction
-	ret nc
-	jp AIUseSuperPotion
-
-BrunoAI: ; 3a670 (e:6670)
-	cp $40
-	ret nc
-	jp AIUseXDefend
-
-AgathaAI: ; 3a676 (e:6676)
-	cp $14
-	jp c,AISwitchIfEnoughMons
-	cp $80
-	ret nc
-	ld a,4
-	call AICheckIfHPBelowFraction
-	ret nc
-	jp AIUseSuperPotion
-
-LanceAI: ; 3a687 (e:6687)
-	cp $80
-	ret nc
-	ld a,5
-	call AICheckIfHPBelowFraction
-	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 [wcf05],a
-	ld de,wHPBarOldHP
-	ld hl,wEnemyMonHP + 1
-	ld a,[hld]
-	ld [de],a
-	inc de
-	ld a,[hl]
-	ld [de],a
-	inc de
-	ld hl,wEnemyMonMaxHP + 1
-	ld a,[hld]
-	ld [de],a
-	inc de
-	ld [wHPBarMaxHP],a
-	ld [wEnemyMonHP + 1],a
-	ld a,[hl]
-	ld [de],a
-	ld [wHPBarMaxHP+1],a
-	ld [wEnemyMonHP],a
-	jr AIPrintItemUseAndUpdateHPBar
-
-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 [wcf05],a
-	ld hl,wEnemyMonHP + 1
-	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,wEnemyMonMaxHP + 1
-	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,AIPrintItemUseAndUpdateHPBar
-	inc de
-	ld a,[de]
-	dec de
-	ld [hld],a
-	ld [wHPBarNewHP],a
-	ld a,[de]
-	ld [hl],a
-	ld [wHPBarNewHP+1],a
-	; fallthrough
-
-AIPrintItemUseAndUpdateHPBar: ; 3a718 (e:6718)
-	call AIPrintItemUse_
-	hlCoord 2, 2
-	xor a
-	ld [wHPBarType],a
-	predef UpdateHPBar2
-	jp DecrementAICount
-
-AISwitchIfEnoughMons: ; 3a72a (e:672a)
-; enemy trainer switches if there are 3 or more unfainted mons in party
-	ld a,[wEnemyPartyCount]
-	ld c,a
-	ld hl,wEnemyMon1HP
-
-	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,SwitchEnemyMon
-	and a
-	ret
-
-SwitchEnemyMon: ; 3a74b (e:674b)
-
-; prepare to withdraw the active monster: copy hp, number, and status to roster
-
-	ld a,[wEnemyMonPartyPos]
-	ld hl,wEnemyMon1HP
-	ld bc,wEnemyMon2 - wEnemyMon1
-	call AddNTimes
-	ld d,h
-	ld e,l
-	ld hl,wEnemyMonHP
-	ld bc,4
-	call CopyData
-
-	ld hl, AIBattleWithdrawText
-	call PrintText
-
-	ld a,1
-	ld [wd11d],a
-	callab EnemySendOut
-	xor a
-	ld [wd11d],a
-
-	ld a,[wLinkState]
-	cp LINK_STATE_BATTLING
-	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,[wEnemyMonPartyPos]
-	ld hl,wEnemyMon1Status
-	ld bc,wEnemyMon2 - wEnemyMon1
-	call AddNTimes
-	xor a
-	ld [hl],a ; clear status in enemy team roster
-	ld [wEnemyMonStatus],a ; clear status of active enemy
-	ld hl,W_ENEMYBATTSTATUS3
-	res 0,[hl]
-	ret
-
-AIUseXAccuracy: ; 0x3a7a8 unused
-	call Func_3a69b
-	ld hl,W_ENEMYBATTSTATUS2
-	set 0,[hl]
-	ld a,X_ACCURACY
-	jp AIPrintItemUse
-
-AIUseGuardSpec: ; 3a7b5 (e:67b5)
-	call Func_3a69b
-	ld hl,W_ENEMYBATTSTATUS2
-	set 1,[hl]
-	ld a,GUARD_SPEC_
-	jp AIPrintItemUse
-
-AIUseDireHit: ; 0x3a7c2 unused
-	call Func_3a69b
-	ld hl,W_ENEMYBATTSTATUS2
-	set 2,[hl]
-	ld a,DIRE_HIT
-	jp AIPrintItemUse
-
-AICheckIfHPBelowFraction: ; 3a7cf (e:67cf)
-; return carry if enemy trainer's current HP is below 1 / a of the maximum
-	ld [H_DIVISOR],a
-	ld hl,wEnemyMonMaxHP
-	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,wEnemyMonHP + 1
-	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 [wcf05],a
-	push bc
-	call AIPrintItemUse_
-	pop bc
-	ld hl,W_ENEMYMOVEEFFECT
-	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 [wcf05],a
-	call AIPrintItemUse_
-	jp DecrementAICount
-
-AIPrintItemUse_: ; 3a835 (e:6835)
-; print "x used [wcf05] on z!"
-	ld a,[wcf05]
-	ld [wd11e],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] ; W_ISINBATTLE
-	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, vSprites + $310
-	ld bc, (BANK(PokeballTileGraphics) << 8) + $04
-	jp CopyVideoData
-
-SetupOwnPartyPokeballs: ; 3a869 (e:6869)
-	call PlacePlayerHUDTiles
-	ld hl, wPartyMon1
-	ld de, wPartyCount ; wPartyCount
-	call SetupPokeballs
-	ld a, $60
-	ld hl, W_BASECOORDX ; wd081
-	ld [hli], a
-	ld [hl], a
-	ld a, $8
-	ld [wTrainerEngageDistance], a
-	ld hl, wOAMBuffer
-	jp WritePokeballOAMData
-
-SetupEnemyPartyPokeballs: ; 3a887 (e:6887)
-	call PlaceEnemyHUDTiles
-	ld hl, wEnemyMons
-	ld de, wEnemyPartyCount ; wEnemyPartyCount
-	call SetupPokeballs
-	ld hl, W_BASECOORDX ; wd081
-	ld a, $48
-	ld [hli], a
-	ld [hl], $20
-	ld a, $f8
-	ld [wTrainerEngageDistance], a
-	ld hl, wOAMBuffer + PARTY_LENGTH * 4
-	jp WritePokeballOAMData
-
-SetupPokeballs: ; 0x3a8a6
-	ld a, [de]
-	push af
-	ld de, wBuffer
-	ld c, PARTY_LENGTH
-	ld a, $34 ; empty pokeball
-.emptyloop
-	ld [de], a
-	inc de
-	dec c
-	jr nz, .emptyloop
-	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
-
-WritePokeballOAMData: ; 3a8e1 (e:68e1)
-	ld de, wBuffer
-	ld c, PARTY_LENGTH
-.loop
-	ld a, [W_BASECOORDY] ; wd082
-	ld [hli], a
-	ld a, [W_BASECOORDX] ; wd081
-	ld [hli], a
-	ld a, [de]
-	ld [hli], a
-	xor a
-	ld [hli], a
-	ld a, [W_BASECOORDX] ; wd081
-	ld b, a
-	ld a, [wTrainerEngageDistance]
-	add b
-	ld [W_BASECOORDX], a ; wd081
-	inc de
-	dec c
-	jr nz, .loop
-	ret
-
-PlacePlayerHUDTiles: ; 3a902 (e:6902)
-	ld hl, PlayerBattleHUDGraphicsTiles ; $6916
-	ld de, wTrainerFacingDirection
-	ld bc, $3
-	call CopyData
-	hlCoord 18, 10
-	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, wTrainerFacingDirection
-	ld bc, $3
-	call CopyData
-	hlCoord 1, 2
-	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, [wTrainerScreenY]
-	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, [wTrainerScreenX]
-	ld [hl], a
-	ret
-
-SetupPlayerAndEnemyPokeballs: ; 3a948 (e:6948)
-	call LoadPartyPokeballGfx
-	ld hl, wPartyMon1Species ; wPartyMon1Species (aliases: wPartyMon1)
-	ld de, wPartyCount ; wPartyCount
-	call SetupPokeballs
-	ld hl, W_BASECOORDX ; wd081
-	ld a, $50
-	ld [hli], a
-	ld [hl], $40
-	ld a, $8
-	ld [wTrainerEngageDistance], a
-	ld hl, wOAMBuffer
-	call WritePokeballOAMData
-	ld hl, wEnemyMons ; wEnemyMon1Species
-	ld de, wEnemyPartyCount ; wEnemyPartyCount
-	call SetupPokeballs
-	ld hl, W_BASECOORDX ; wd081
-	ld a, $50
-	ld [hli], a
-	ld [hl], $68
-	ld hl, wOAMBuffer + $18
-	jp WritePokeballOAMData
-
-; four tiles: pokeball, black pokeball (status ailment), crossed out pokeball (faited) and pokeball slot (no mon)
-PokeballTileGraphics:: ; 3a97e (e:697e)
-	INCBIN "gfx/pokeball.2bpp"
--- a/engine/battle/e_2.asm
+++ /dev/null
@@ -1,301 +1,0 @@
-HealEffect_: ; 3b9ec (e:79ec)
-	ld a, [H_WHOSETURN]
-	and a
-	ld de, wBattleMonHP
-	ld hl, wBattleMonMaxHP
-	ld a, [W_PLAYERMOVENUM]
-	jr z, .asm_3ba03
-	ld de, wEnemyMonHP
-	ld hl, wEnemyMonMaxHP
-	ld a, [W_ENEMYMOVENUM]
-.asm_3ba03
-	ld b, a
-	ld a, [de]
-	cp [hl]
-	inc de
-	inc hl
-	ld a, [de]
-	sbc [hl]
-	jp z, .failed
-	ld a, b
-	cp REST
-	jr nz, .asm_3ba37
-	push hl
-	push de
-	push af
-	ld c, 50
-	call DelayFrames
-	ld hl, wBattleMonStatus
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_3ba25
-	ld hl, wEnemyMonStatus
-.asm_3ba25
-	ld a, [hl]
-	and a
-	ld [hl], 2 ; Number of turns from Rest
-	ld hl, StartedSleepingEffect
-	jr z, .asm_3ba31
-	ld hl, FellAsleepBecameHealthyText
-.asm_3ba31
-	call PrintText
-	pop af
-	pop de
-	pop hl
-.asm_3ba37
-	ld a, [hld]
-	ld [wHPBarMaxHP], a
-	ld c, a
-	ld a, [hl]
-	ld [wHPBarMaxHP+1], a
-	ld b, a
-	jr z, .asm_3ba47
-	srl b
-	rr c
-.asm_3ba47
-	ld a, [de]
-	ld [wHPBarOldHP], a
-	add c
-	ld [de], a
-	ld [wHPBarNewHP], a
-	dec de
-	ld a, [de]
-	ld [wHPBarOldHP+1], a
-	adc b
-	ld [de], a
-	ld [wHPBarNewHP+1], a
-	inc hl
-	inc de
-	ld a, [de]
-	dec de
-	sub [hl]
-	dec hl
-	ld a, [de]
-	sbc [hl]
-	jr c, .asm_3ba6f
-	ld a, [hli]
-	ld [de], a
-	ld [wHPBarNewHP+1], a
-	inc de
-	ld a, [hl]
-	ld [de], a
-	ld [wHPBarNewHP], a
-.asm_3ba6f
-	ld hl, PlayCurrentMoveAnimation
-	call BankswitchEtoF
-	ld a, [H_WHOSETURN]
-	and a
-	hlCoord 10, 9
-	ld a, $1
-	jr z, .asm_3ba83
-	hlCoord 2, 2
-	xor a
-.asm_3ba83
-	ld [wHPBarType], a
-	predef UpdateHPBar2
-	ld hl, DrawHUDsAndHPBars
-	call BankswitchEtoF
-	ld hl, RegainedHealthText
-	jp PrintText
-.failed
-	ld c, 50
-	call DelayFrames
-	ld hl, PrintButItFailedText_
-	jp BankswitchEtoF
-
-StartedSleepingEffect: ; 3baa2 (e:7aa2)
-	TX_FAR _StartedSleepingEffect
-	db "@"
-
-FellAsleepBecameHealthyText: ; 3baa7 (e:7aa7)
-	TX_FAR _FellAsleepBecameHealthyText
-	db "@"
-
-RegainedHealthText: ; 3baac (e:7aac)
-	TX_FAR _RegainedHealthText
-	db "@"
-
-TransformEffect_: ; 3bab1 (e:7ab1)
-	ld hl, wBattleMonSpecies
-	ld de, wEnemyMonSpecies
-	ld bc, W_ENEMYBATTSTATUS3
-	ld a, [W_ENEMYBATTSTATUS1]
-	ld a, [H_WHOSETURN]
-	and a
-	jr nz, .asm_3bad1
-	ld hl, wEnemyMonSpecies
-	ld de, wBattleMonSpecies
-	ld bc, W_PLAYERBATTSTATUS3
-	ld [wPlayerMoveListIndex], a
-	ld a, [W_PLAYERBATTSTATUS1]
-.asm_3bad1
-	bit Invulnerable, a ; is mon invulnerable to typical attacks? (fly/dig)
-	jp nz, .failed
-	push hl
-	push de
-	push bc
-	ld hl, W_PLAYERBATTSTATUS2
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_3bae4
-	ld hl, W_ENEMYBATTSTATUS2
-.asm_3bae4
-	bit HasSubstituteUp, [hl]
-	push af
-	ld hl, Func_79747
-	ld b, BANK(Func_79747)
-	call nz, Bankswitch
-	ld a, [W_OPTIONS]
-	add a
-	ld hl, PlayCurrentMoveAnimation
-	ld b, BANK(PlayCurrentMoveAnimation)
-	jr nc, .asm_3baff
-	ld hl, AnimationTransformMon
-	ld b, BANK(AnimationTransformMon)
-.asm_3baff
-	call Bankswitch
-	ld hl, Func_79771
-	ld b, BANK(Func_79771)
-	pop af
-	call nz, Bankswitch
-	pop bc
-	ld a, [bc]
-	set Transformed, a
-	ld [bc], a
-	pop de
-	pop hl
-	push hl
-	ld a, [hl]
-	ld [de], a
-	ld bc, $5
-	add hl, bc
-	inc de
-	inc de
-	inc de
-	inc de
-	inc de
-	inc bc
-	inc bc
-	call CopyData
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_3bb32
-	ld a, [de]
-	ld [wcceb], a
-	inc de
-	ld a, [de]
-	ld [wccec], a
-	dec de
-.asm_3bb32
-	ld a, [hli]
-	ld [de], a
-	inc de
-	ld a, [hli]
-	ld [de], a
-	inc de
-	inc hl
-	inc hl
-	inc hl
-	inc de
-	inc de
-	inc de
-	ld bc, $8
-	call CopyData
-	ld bc, $ffef
-	add hl, bc
-	ld b, $4
-.asm_3bb4a
-	ld a, [hli]
-	and a
-	jr z, .asm_3bb57
-	ld a, $5
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .asm_3bb4a
-	jr .asm_3bb5d
-.asm_3bb57
-	xor a
-	ld [de], a
-	inc de
-	dec b
-	jr nz, .asm_3bb57
-.asm_3bb5d
-	pop hl
-	ld a, [hl]
-	ld [wd11e], a
-	call GetMonName
-	ld hl, wEnemyMonUnmodifiedAttack
-	ld de, wPlayerMonUnmodifiedAttack
-	call .copyBasedOnTurn
-	ld hl, wEnemyMonStatMods
-	ld de, wPlayerMonStatMods
-	call .copyBasedOnTurn
-	ld hl, TransformedText
-	jp PrintText
-
-.copyBasedOnTurn
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_3bb86
-	push hl
-	ld h, d
-	ld l, e
-	pop de
-.asm_3bb86
-	ld bc, $8
-	jp CopyData
-
-.failed
-	ld hl, PrintButItFailedText_
-	jp BankswitchEtoF
-
-TransformedText: ; 3bb92 (e:7b92)
-	TX_FAR _TransformedText
-	db "@"
-
-ReflectLightScreenEffect_: ; 3bb97 (e:7b97)
-	ld hl, W_PLAYERBATTSTATUS3
-	ld de, W_PLAYERMOVEEFFECT
-	ld a, [H_WHOSETURN]
-	and a
-	jr z, .asm_3bba8
-	ld hl, W_ENEMYBATTSTATUS3
-	ld de, W_ENEMYMOVEEFFECT
-.asm_3bba8
-	ld a, [de]
-	cp LIGHT_SCREEN_EFFECT
-	jr nz, .reflect
-	bit HasLightScreenUp, [hl] ; is mon already protected by light screen?
-	jr nz, .moveFailed
-	set HasLightScreenUp, [hl] ; mon is now protected by light screen
-	ld hl, LightScreenProtectedText
-	jr .asm_3bbc1
-.reflect
-	bit HasReflectUp, [hl] ; is mon already protected by reflect?
-	jr nz, .moveFailed
-	set HasReflectUp, [hl] ; mon is now protected by reflect
-	ld hl, ReflectGainedArmorText
-.asm_3bbc1
-	push hl
-	ld hl, PlayCurrentMoveAnimation
-	call BankswitchEtoF
-	pop hl
-	jp PrintText
-.moveFailed
-	ld c, $32
-	call DelayFrames
-	ld hl, PrintButItFailedText_
-	jp BankswitchEtoF
-
-LightScreenProtectedText: ; 3bbd7 (e:7bd7)
-	TX_FAR _LightScreenProtectedText
-	db "@"
-
-ReflectGainedArmorText: ; 3bbdc (e:7bdc)
-	TX_FAR _ReflectGainedArmorText
-	db "@"
-
-BankswitchEtoF: ; 3bbe1 (e:7be1)
-	ld b, BANK(BattleCore)
-	jp Bankswitch
--- /dev/null
+++ b/engine/battle/end_of_battle.asm
@@ -1,0 +1,88 @@
+EndOfBattle: ; 137aa (4:77aa)
+	ld a, [wLinkState]
+	cp LINK_STATE_BATTLING
+	jr nz, .notLinkBattle
+; link battle
+	ld a, [wEnemyMonPartyPos]
+	ld hl, wEnemyMon1Status
+	ld bc, wEnemyMon2 - wEnemyMon1
+	call AddNTimes
+	ld a, [wEnemyMonStatus]
+	ld [hl], a
+	call ClearScreen
+	callab DisplayLinkBattleVersusTextBox
+	ld a, [wBattleResult]
+	cp $1
+	ld de, YouWinText
+	jr c, .placeWinOrLoseString
+	ld de, YouLoseText
+	jr z, .placeWinOrLoseString
+	ld de, DrawText
+.placeWinOrLoseString
+	hlCoord 6, 8
+	call PlaceString
+	ld c, $c8
+	call DelayFrames
+	jr .evolution
+.notLinkBattle
+	ld a, [wBattleResult]
+	and a
+	jr nz, .resetVariables
+	ld hl, wTotalPayDayMoney
+	ld a, [hli]
+	or [hl]
+	inc hl
+	or [hl]
+	jr z, .evolution ; if pay day money is 0, jump
+	ld de, wPlayerMoney + 2
+	ld c, $3
+	predef AddBCDPredef
+	ld hl, PickUpPayDayMoneyText
+	call PrintText
+.evolution
+	xor a
+	ld [wccd4], a
+	predef EvolutionAfterBattle
+.resetVariables
+	xor a
+	ld [wLowHealthAlarm], a ;disable low health alarm
+	ld [wc02a], a
+	ld [W_ISINBATTLE], a
+	ld [W_BATTLETYPE], a
+	ld [W_MOVEMISSED], a
+	ld [W_CUROPPONENT], a
+	ld [wd11f], a
+	ld [wNumRunAttempts], a
+	ld [wEscapedFromBattle], a
+	ld hl, wcc2b
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld [wListScrollOffset], a
+	ld hl, wPlayerStatsToDouble
+	ld b, $18
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	ld hl, wd72c
+	set 0, [hl]
+	call WaitForSoundToFinish
+	call GBPalWhiteOut
+	ld a, $ff
+	ld [wDestinationWarpID], a
+	ret
+
+YouWinText: ; 13853 (4:7853)
+	db "YOU WIN@"
+
+YouLoseText: ; 1385b (4:785b)
+	db "YOU LOSE@"
+
+DrawText: ; 13864 (4:7864)
+	db "  DRAW@"
+
+PickUpPayDayMoneyText: ; 1386b (4:786b)
+	TX_FAR _PickUpPayDayMoneyText
+	db "@"
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/experience.asm
@@ -1,0 +1,372 @@
+GainExperience: ; 5524f (15:524f)
+	ld a, [wLinkState]
+	cp LINK_STATE_BATTLING
+	ret z ; return if link battle
+	call DivideExpDataByNumMonsGainingExp
+	ld hl, wPartyMon1
+	xor a
+	ld [wWhichPokemon], a
+.partyMonLoop ; loop over each mon and add gained exp
+	inc hl
+	ld a, [hli]
+	or [hl] ; is mon's HP 0?
+	jp z, .nextMon ; if so, go to next mon
+	push hl
+	ld hl, wPartyGainExpFlags
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, $2
+	predef FlagActionPredef
+	ld a, c
+	and a ; is mon's gain exp flag set?
+	pop hl
+	jp z, .nextMon ; if mon's gain exp flag not set, go to next mon
+	ld de, (wPartyMon1HPExp + 1) - (wPartyMon1HP + 1)
+	add hl, de
+	ld d, h
+	ld e, l
+	ld hl, wEnemyMonBaseStats
+	ld c, $5
+.gainStatExpLoop
+	ld a, [hli]
+	ld b, a ; enemy mon base stat
+	ld a, [de] ; stat exp
+	add b ; add enemy mon base state to stat exp
+	ld [de], a
+	jr nc, .nextBaseStat
+; if there was a carry, increment the upper byte
+	dec de
+	ld a, [de]
+	inc a
+	jr z, .maxStatExp ; jump if the value overflowed
+	ld [de], a
+	inc de
+	jr .nextBaseStat
+.maxStatExp ; if the upper byte also overflowed, then we have hit the max stat exp
+	ld a, $ff
+	ld [de], a
+	inc de
+	ld [de], a
+.nextBaseStat
+	dec c
+	jr z, .asm_552a1
+	inc de
+	inc de
+	jr .gainStatExpLoop
+.asm_552a1
+	xor a
+	ld [H_MULTIPLICAND], a
+	ld [H_MULTIPLICAND + 1], a
+	ld a, [wEnemyMonBaseExp]
+	ld [H_MULTIPLICAND + 2], a
+	ld a, [wEnemyMonLevel]
+	ld [H_MULTIPLIER], a
+	call Multiply
+	ld a, 7
+	ld [H_DIVISOR], a
+	ld b, 4
+	call Divide
+	ld hl, -((wPartyMon1HPExp + 1) - wPartyMon1OTID + 4 * 2)
+	add hl, de
+	ld b, [hl] ; party mon OTID
+	inc hl
+	ld a, [wPlayerID]
+	cp b
+	jr nz, .tradedMon
+	ld b, [hl]
+	ld a, [wPlayerID + 1]
+	cp b
+	ld a, $0
+	jr z, .next
+.tradedMon
+	call BoostExp ; traded mon exp boost
+	ld a, $1
+.next
+	ld [wGainBoostedExp], a
+	ld a, [W_ISINBATTLE]
+	dec a ; is it a trainer battle?
+	call nz, BoostExp ; if so, boost exp
+	inc hl
+	inc hl
+	inc hl
+; add the gained exp to the party mon's exp
+	ld b, [hl]
+	ld a, [H_QUOTIENT + 3]
+	ld [wcf4c], a
+	add b
+	ld [hld], a
+	ld b, [hl]
+	ld a, [H_QUOTIENT + 2]
+	ld [wcf4b], a
+	adc b
+	ld [hl], a
+	jr nc, .noCarry
+	dec hl
+	inc [hl]
+	inc hl
+.noCarry
+; calculate exp for the mon at max level, and cap the exp at that value
+	inc hl
+	push hl
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, 0
+	ld hl, wPartySpecies
+	add hl, bc
+	ld a, [hl] ; species
+	ld [wd0b5], a
+	call GetMonHeader
+	ld d, MAX_LEVEL
+	callab CalcExperience ; get max exp
+; compare max exp with current exp
+	ld a, [$ff96]
+	ld b, a
+	ld a, [$ff97]
+	ld c, a
+	ld a, [$ff98]
+	ld d, a
+	pop hl
+	ld a, [hld]
+	sub d
+	ld a, [hld]
+	sbc c
+	ld a, [hl]
+	sbc b
+	jr c, .next2
+; the mon's exp is greater than the max exp, so overwrite it with the max exp
+	ld a, b
+	ld [hli], a
+	ld a, c
+	ld [hli], a
+	ld a, d
+	ld [hld], a
+	dec hl
+.next2
+	push hl
+	ld a, [wWhichPokemon]
+	ld hl, wPartyMonNicks
+	call GetPartyMonName
+	ld hl, GainedText
+	call PrintText
+	xor a ; party mon data
+	ld [wcc49], a
+	call LoadMonData
+	pop hl
+	ld bc, wPartyMon1Level - wPartyMon1Exp
+	add hl, bc
+	push hl
+	callba CalcLevelFromExperience
+	pop hl
+	ld a, [hl] ; current level
+	cp d
+	jp z, .nextMon ; if level didn't change, go to next mon
+	ld a, [W_CURENEMYLVL]
+	push af
+	push hl
+	ld a, d
+	ld [W_CURENEMYLVL], a
+	ld [hl], a
+	ld bc, wPartyMon1Species - wPartyMon1Level
+	add hl, bc
+	ld a, [hl] ; species
+	ld [wd0b5], a
+	ld [wd11e], a
+	call GetMonHeader
+	ld bc, (wPartyMon1MaxHP + 1) - wPartyMon1Species
+	add hl, bc
+	push hl
+	ld a, [hld]
+	ld c, a
+	ld b, [hl]
+	push bc ; push max HP (from before levelling up)
+	ld d, h
+	ld e, l
+	ld bc, (wPartyMon1HPExp - 1) - wPartyMon1MaxHP
+	add hl, bc
+	ld b, $1 ; consider stat exp when calculating stats
+	call CalcStats
+	pop bc ; pop max HP (from before levelling up)
+	pop hl
+	ld a, [hld]
+	sub c
+	ld c, a
+	ld a, [hl]
+	sbc b
+	ld b, a ; bc = difference between old max HP and new max HP after levelling
+	ld de, (wPartyMon1HP + 1) - wPartyMon1MaxHP
+	add hl, de
+; add to the current HP the amount of max HP gained when levelling
+	ld a, [hl] ; wPartyMon1HP + 1
+	add c
+	ld [hld], a
+	ld a, [hl] ; wPartyMon1HP + 1
+	adc b
+	ld [hl], a ; wPartyMon1HP
+	ld a, [wPlayerMonNumber]
+	ld b, a
+	ld a, [wWhichPokemon]
+	cp b ; is the current mon in battle?
+	jr nz, .printGrewLevelText
+; current mon is in battle
+	ld de, wBattleMonHP
+; copy party mon HP to battle mon HP
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+; copy other stats from party mon to battle mon
+	ld bc, wPartyMon1Level - (wPartyMon1HP + 1)
+	add hl, bc
+	push hl
+	ld de, wBattleMonLevel
+	ld bc, $b ; size of stats
+	call CopyData
+	pop hl
+	ld a, [W_PLAYERBATTSTATUS3]
+	bit 3, a ; is the mon transformed?
+	jr nz, .recalcStatChanges
+; the mon is not transformed, so update the unmodified stats
+	ld de, wPlayerMonUnmodifiedLevel
+	ld bc, $b
+	call CopyData
+.recalcStatChanges
+	xor a
+	ld [wd11e], a
+	callab CalculateModifiedStats
+	callab ApplyBurnAndParalysisPenaltiesToPlayer
+	callab ApplyBadgeStatBoosts
+	callab DrawPlayerHUDAndHPBar
+	callab PrintEmptyString
+	call SaveScreenTilesToBuffer1
+.printGrewLevelText
+	ld hl, GrewLevelText
+	call PrintText
+	xor a ; party mon data
+	ld [wcc49], a
+	call LoadMonData
+	ld d, $1
+	callab PrintStatsBox
+	call WaitForTextScrollButtonPress
+	call LoadScreenTilesFromBuffer1
+	xor a
+	ld [wcc49], a
+	ld a, [wd0b5]
+	ld [wd11e], a
+	predef LearnMoveFromLevelUp
+	ld hl, wccd3
+	ld a, [wWhichPokemon]
+	ld c, a
+	ld b, $1
+	predef FlagActionPredef
+	pop hl
+	pop af
+	ld [W_CURENEMYLVL], a
+
+.nextMon
+	ld a, [wPartyCount]
+	ld b, a
+	ld a, [wWhichPokemon]
+	inc a
+	cp b
+	jr z, .done
+	ld [wWhichPokemon], a
+	ld bc, wPartyMon2 - wPartyMon1
+	ld hl, wPartyMon1
+	call AddNTimes
+	jp .partyMonLoop
+.done
+	ld hl, wPartyGainExpFlags
+	xor a
+	ld [hl], a ; clear gain exp flags
+	ld a, [wPlayerMonNumber]
+	ld c, a
+	ld b, $1
+	push bc
+	predef FlagActionPredef ; set the gain exp flag for the mon that is currently out
+	ld hl, wPartyFoughtCurrentEnemyFlags
+	xor a
+	ld [hl], a
+	pop bc
+	predef_jump FlagActionPredef ; set the fought current enemy flag for the mon that is currently out
+
+; divide enemy base stats, catch rate, and base exp by the number of mons gaining exp
+DivideExpDataByNumMonsGainingExp: ; 5546c (15:546c)
+	ld a, [wPartyGainExpFlags]
+	ld b, a
+	xor a
+	ld c, $8
+	ld d, $0
+.countSetBitsLoop ; loop to count set bits in wPartyGainExpFlags
+	xor a
+	srl b
+	adc d
+	ld d, a
+	dec c
+	jr nz, .countSetBitsLoop
+	cp $2
+	ret c ; return if only one mon is gaining exp
+	ld [wd11e], a ; store number of mons gaining exp
+	ld hl, wEnemyMonBaseStats
+	ld c, $7
+.divideLoop
+	xor a
+	ld [H_DIVIDEND], a
+	ld a, [hl]
+	ld [H_DIVIDEND + 1], a
+	ld a, [wd11e]
+	ld [H_DIVISOR], a
+	ld b, $2
+	call Divide ; divide value by number of mons gaining exp
+	ld a, [H_QUOTIENT + 3]
+	ld [hli], a
+	dec c
+	jr nz, .divideLoop
+	ret
+
+; multiplies exp by 1.5
+BoostExp: ; 5549f (15:549f)
+	ld a, [H_QUOTIENT + 2]
+	ld b, a
+	ld a, [H_QUOTIENT + 3]
+	ld c, a
+	srl b
+	rr c
+	add c
+	ld [H_QUOTIENT + 3], a
+	ld a, [H_QUOTIENT + 2]
+	adc b
+	ld [H_QUOTIENT + 2], a
+	ret
+
+GainedText: ; 554b2 (15:54b2)
+	TX_FAR _GainedText
+	db $08 ; asm
+	ld a, [wBoostExpByExpAll]
+	ld hl, WithExpAllText
+	and a
+	ret nz
+	ld hl, ExpPointsText
+	ld a, [wGainBoostedExp]
+	and a
+	ret z
+	ld hl, BoostedText
+	ret
+
+WithExpAllText: ; 554cb (15:54cb)
+	TX_FAR _WithExpAllText
+	db $08 ; asm
+	ld hl, ExpPointsText
+	ret
+
+BoostedText: ; 554d4 (15:54d4)
+	TX_FAR _BoostedText
+
+ExpPointsText: ; 554d8 (15:54d8)
+	TX_FAR _ExpPointsText
+	db "@"
+
+GrewLevelText: ; 554dd (15:54dd)
+	TX_FAR _GrewLevelText
+	db $0b
+	db "@"
--- /dev/null
+++ b/engine/battle/get_trainer_name.asm
@@ -1,0 +1,24 @@
+GetTrainerName_: ; 13a58 (4:7a58)
+	ld hl, W_GRASSRATE
+	ld a, [wLinkState]
+	and a
+	jr nz, .rival
+	ld hl, W_RIVALNAME
+	ld a, [W_TRAINERCLASS]
+	cp SONY1
+	jr z, .rival
+	cp SONY2
+	jr z, .rival
+	cp SONY3
+	jr z, .rival
+	ld [wd0b5], a
+	ld a, TRAINER_NAME
+	ld [wNameListType], a
+	ld a, BANK(TrainerNames)
+	ld [wPredefBank], a
+	call GetName
+	ld hl, wcd6d
+.rival
+	ld de, W_TRAINERNAME
+	ld bc, $d
+	jp CopyData
--- /dev/null
+++ b/engine/battle/ghost_marowak_anim.asm
@@ -1,0 +1,89 @@
+MarowakAnim: ; 708ca (1c:48ca)
+; animate the ghost being unveiled as a Marowak
+	ld a, $e4
+	ld [rOBP1], a
+	call CopyMonPicFromBGToSpriteVRAM ; cover the BG ghost pic with a sprite ghost pic that looks the same
+; now that the ghost pic is being displayed using sprites, clear the ghost pic from the BG tilemap
+	hlCoord 12, 0
+	ld bc, $707
+	call ClearScreenArea
+	call Delay3
+	xor a
+	ld [H_AUTOBGTRANSFERENABLED], a ; disable BG transfer so we don't see the Marowak too soon
+; replace ghost pic with Marowak in BG
+	ld a, MAROWAK
+	ld [wHPBarMaxHP], a
+	ld a, $1
+	ld [H_WHOSETURN], a
+	callab Func_79793
+ ; alternate between black and light grey 8 times.
+ ; this makes the ghost's body appear to flash
+	ld d, $80
+	call FlashSprite8Times
+.fadeOutGhostLoop
+	ld c, 10
+	call DelayFrames
+	ld a, [rOBP1]
+	sla a
+	sla a
+	ld [rOBP1], a
+	jr nz, .fadeOutGhostLoop
+	call ClearSprites
+	call CopyMonPicFromBGToSpriteVRAM ; copy Marowak pic from BG to sprite VRAM
+	ld b, $e4
+.fadeInMarowakLoop
+	ld c, 10
+	call DelayFrames
+	ld a, [rOBP1]
+	srl b
+	rra
+	srl b
+	rra
+	ld [rOBP1], a
+	ld a, b
+	and a
+	jr nz, .fadeInMarowakLoop
+	ld a, $1
+	ld [H_AUTOBGTRANSFERENABLED], a ; enable BG transfer so the BG Marowak pic will be visible after the sprite one is cleared
+	call Delay3
+	jp ClearSprites
+
+; copies a mon pic's  from background VRAM to sprite VRAM and sets up OAM
+CopyMonPicFromBGToSpriteVRAM: ; 7092a (1c:492a)
+	ld de, vFrontPic
+	ld hl, vSprites
+	ld bc, 7 * 7
+	call CopyVideoData
+	ld a, $10
+	ld [W_BASECOORDY], a
+	ld a, $70
+	ld [W_BASECOORDX], a
+	ld hl, wOAMBuffer
+	ld bc, $606
+	ld d, $8
+.oamLoop
+	push bc
+	ld a, [W_BASECOORDY]
+	ld e, a
+.oamInnerLoop
+	ld a, e
+	add $8
+	ld e, a
+	ld [hli], a
+	ld a, [W_BASECOORDX]
+	ld [hli], a
+	ld a, d
+	ld [hli], a
+	ld a, $10 ; use OBP1
+	ld [hli], a
+	inc d
+	dec c
+	jr nz, .oamInnerLoop
+	inc d
+	ld a, [W_BASECOORDX]
+	add $8
+	ld [W_BASECOORDX], a
+	pop bc
+	dec b
+	jr nz, .oamLoop
+	ret
--- /dev/null
+++ b/engine/battle/init_battle_variables.asm
@@ -1,0 +1,40 @@
+InitBattleVariables: ; 525af (14:65af)
+	ld a, [hTilesetType]
+	ld [wd0d4], a
+	xor a
+	ld [wcd6a], a
+	ld [wBattleResult], a
+	ld hl, wcc2b
+	ld [hli], a
+	ld [hli], a
+	ld [hli], a
+	ld [hl], a
+	ld [wListScrollOffset], a
+	ld [wCriticalHitOrOHKO], a
+	ld [wBattleMonSpecies], a
+	ld [wPartyGainExpFlags], a
+	ld [wPlayerMonNumber], a 
+	ld [wEscapedFromBattle], a
+	ld [wMapPalOffset], a
+	ld hl, wcf1d
+	ld [hli], a
+	ld [hl], a
+	ld hl, wccd3
+	ld b, $3c
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	inc a
+	ld [wccd9], a
+	ld a, [W_CURMAP] 
+	cp SAFARI_ZONE_EAST
+	jr c, .notSafariBattle
+	cp SAFARI_ZONE_REST_HOUSE_1
+	jr nc, .notSafariBattle
+	ld a, $2 ; safari battle
+	ld [W_BATTLETYPE], a
+.notSafariBattle
+	ld hl, PlayBattleMusic
+	ld b, BANK(PlayBattleMusic)
+	jp Bankswitch
--- /dev/null
+++ b/engine/battle/link_battle_versus_text.asm
@@ -1,0 +1,23 @@
+; display "[player] VS [enemy]" text box with pokeballs representing their parties next to the names
+DisplayLinkBattleVersusTextBox: ; 372d6 (d:72d6)
+	call LoadTextBoxTilePatterns
+	hlCoord 3, 4
+	ld b, $7
+	ld c, $c
+	call TextBoxBorder
+	hlCoord 4, 5
+	ld de, wPlayerName
+	call PlaceString
+	hlCoord 4, 10
+	ld de, wLinkEnemyTrainerName
+	call PlaceString
+; place bold "VS" tiles between the names
+	hlCoord 9, 8
+	ld a, $69
+	ld [hli], a
+	ld [hl], $6a
+	xor a
+	ld [wUpdateSpritesEnabled], a
+	callab SetupPlayerAndEnemyPokeballs
+	ld c, 150
+	jp DelayFrames
--- /dev/null
+++ b/engine/battle/moveEffects/conversion_effect.asm
@@ -1,0 +1,34 @@
+ConversionEffect_: ; 139a3 (4:79a3)
+	ld hl, wEnemyMonType1
+	ld de, wBattleMonType1
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [W_ENEMYBATTSTATUS1]
+	jr z, .asm_139b8
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+	ld a, [W_PLAYERBATTSTATUS1]
+.asm_139b8
+	bit Invulnerable, a ; is mon immune to typical attacks (dig/fly)
+	jr nz, PrintButItFailedText
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	ld hl, PlayCurrentMoveAnimation
+	call CallBankF
+	ld hl, ConvertedTypeText
+	jp PrintText
+
+ConvertedTypeText: ; 139cd (4:79cd)
+	TX_FAR _ConvertedTypeText
+	db "@"
+
+PrintButItFailedText: ; 139d2 (4:79d2)
+	ld hl, PrintButItFailedText_
+CallBankF: ; 139d5 (4:79d5)
+	ld b, BANK(PrintButItFailedText_)
+	jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/drain_hp_effect.asm
@@ -1,0 +1,104 @@
+DrainHPEffect_: ; 783f (1:783f)
+	ld hl, W_DAMAGE 
+	ld a, [hl]
+	srl a ; divide damage by 2
+	ld [hli], a
+	ld a, [hl]
+	rr a
+	ld [hld], a
+	or [hl] ; is damage 0?
+	jr nz, .getAttackerHP
+; if damage is 0, increase to 1 so that the attacker gains at least 1 HP
+	inc hl
+	inc [hl]
+.getAttackerHP
+	ld hl, wBattleMonHP
+	ld de, wBattleMonMaxHP
+	ld a, [H_WHOSETURN]
+	and a
+	jp z, .addDamageToAttackerHP
+	ld hl, wEnemyMonHP 
+	ld de, wEnemyMonMaxHP 
+.addDamageToAttackerHP
+	ld bc, wHPBarOldHP+1
+; copy current HP to wHPBarOldHP
+	ld a, [hli]
+	ld [bc], a
+	ld a, [hl]
+	dec bc
+	ld [bc], a
+; copy max HP to wHPBarMaxHP
+	ld a, [de]
+	dec bc
+	ld [bc], a
+	inc de
+	ld a, [de]
+	dec bc
+	ld [bc], a
+; add damage to attacker's HP and copy new HP to wHPBarNewHP
+	ld a, [W_DAMAGE + 1]
+	ld b, [hl]
+	add b
+	ld [hld], a
+	ld [wHPBarNewHP], a
+	ld a, [W_DAMAGE] 
+	ld b, [hl]
+	adc b
+	ld [hli], a
+	ld [wHPBarNewHP+1], a
+	jr c, .capToMaxHP ; if HP > 65,535, cap to max HP
+; compare HP with max HP
+	ld a, [hld]
+	ld b, a
+	ld a, [de]
+	dec de
+	sub b
+	ld a, [hli]
+	ld b, a
+	ld a, [de]
+	inc de
+	sbc b
+	jr nc, .next
+.capToMaxHP
+	ld a, [de]
+	ld [hld], a
+	ld [wHPBarNewHP], a
+	dec de
+	ld a, [de]
+	ld [hli], a
+	ld [wHPBarNewHP+1], a
+	inc de
+.next
+	ld a, [H_WHOSETURN]
+	and a
+	hlCoord 10, 9
+	ld a, $1
+	jr z, .next2
+	hlCoord 2, 2
+	xor a
+.next2
+	ld [wHPBarType], a
+	predef UpdateHPBar2
+	predef DrawPlayerHUDAndHPBar
+	predef DrawEnemyHUDAndHPBar
+	callab ReadPlayerMonCurHPAndStatus
+	ld hl, SuckedHealthText
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [W_PLAYERMOVEEFFECT]
+	jr z, .next3
+	ld a, [W_ENEMYMOVEEFFECT] 
+.next3
+	cp DREAM_EATER_EFFECT
+	jr nz, .printText
+	ld hl, DreamWasEatenText
+.printText
+	jp PrintText
+
+SuckedHealthText: ; 78dc (1:78dc)
+	TX_FAR _SuckedHealthText
+	db "@"
+
+DreamWasEatenText: ; 78e1 (1:78e1)
+	TX_FAR _DreamWasEatenText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/focus_energy_effect.asm
@@ -1,0 +1,24 @@
+FocusEnergyEffect_: ; 27f86 (9:7f86)
+	ld hl, W_PLAYERBATTSTATUS2
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .notEnemy
+	ld hl, W_ENEMYBATTSTATUS2
+.notEnemy
+	bit GettingPumped, [hl] ; is mon already using focus energy?
+	jr nz, .alreadyUsing
+	set GettingPumped, [hl] ; mon is now using focus energy
+	callab PlayCurrentMoveAnimation
+	ld hl, GettingPumpedText
+	jp PrintText
+.alreadyUsing
+	ld c, $32
+	call DelayFrames
+	ld hl, PrintButItFailedText_
+	ld b, BANK(PrintButItFailedText_)
+	jp Bankswitch
+
+GettingPumpedText: ; 27fb3 (9:7fb3)
+	db $0a
+	TX_FAR _GettingPumpedText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/haze_effect.asm
@@ -1,0 +1,76 @@
+HazeEffect_: ; 139da (4:79da)
+	ld a, $7
+	ld hl, wPlayerMonAttackMod
+	call ResetStatMods
+	ld hl, wEnemyMonAttackMod
+	call ResetStatMods
+	ld hl, wPlayerMonUnmodifiedAttack
+	ld de, wBattleMonAttack
+	call ResetStats
+	ld hl, wEnemyMonUnmodifiedAttack
+	ld de, wEnemyMonAttack
+	call ResetStats
+	ld hl, wEnemyMonStatus
+	ld de, wEnemySelectedMove
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_13a09
+	ld hl, wBattleMonStatus
+	dec de
+
+.asm_13a09
+	ld a, [hl]
+	ld [hl], $0
+	and $27
+	jr z, .asm_13a13
+	ld a, $ff
+	ld [de], a
+
+.asm_13a13
+	xor a
+	ld [W_PLAYERDISABLEDMOVE], a
+	ld [W_ENEMYDISABLEDMOVE], a
+	ld hl, wccee
+	ld [hli], a
+	ld [hl], a
+	ld hl, W_PLAYERBATTSTATUS1
+	call CureStatuses
+	ld hl, W_ENEMYBATTSTATUS1
+	call CureStatuses
+	ld hl, PlayCurrentMoveAnimation
+	call CallBankF
+	ld hl, StatusChangesEliminatedText
+	jp PrintText
+
+CureStatuses: ; 13a37 (4:7a37)
+	res Confused, [hl]
+	inc hl ; BATTSTATUS2
+	ld a, [hl]
+	and (1 << UsingRage) | (1 << NeedsToRecharge) | (1 << HasSubstituteUp) | (1 << 3) ; clear all but these from BATTSTATUS2
+	ld [hli], a ; BATTSTATUS3
+	ld a, [hl]
+	and %11110000 | (1 << Transformed) ; clear Bad Poison, Reflect and Light Screen statuses
+	ld [hl], a
+	ret
+
+ResetStatMods: ; 13a43 (4:7a43)
+	ld b, $8
+.loop
+	ld [hli], a
+	dec b
+	jr nz, .loop
+	ret
+
+ResetStats: ; 13a4a (4:7a4a)
+	ld b, $8
+.loop
+	ld a, [hli]
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .loop
+	ret
+
+StatusChangesEliminatedText: ; 13a53 (4:7a53)
+	TX_FAR _StatusChangesEliminatedText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/heal_effect.asm
@@ -1,0 +1,116 @@
+HealEffect_: ; 3b9ec (e:79ec)
+	ld a, [H_WHOSETURN]
+	and a
+	ld de, wBattleMonHP
+	ld hl, wBattleMonMaxHP
+	ld a, [W_PLAYERMOVENUM]
+	jr z, .asm_3ba03
+	ld de, wEnemyMonHP
+	ld hl, wEnemyMonMaxHP
+	ld a, [W_ENEMYMOVENUM]
+.asm_3ba03
+	ld b, a
+	ld a, [de]
+	cp [hl]
+	inc de
+	inc hl
+	ld a, [de]
+	sbc [hl]
+	jp z, .failed
+	ld a, b
+	cp REST
+	jr nz, .asm_3ba37
+	push hl
+	push de
+	push af
+	ld c, 50
+	call DelayFrames
+	ld hl, wBattleMonStatus
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_3ba25
+	ld hl, wEnemyMonStatus
+.asm_3ba25
+	ld a, [hl]
+	and a
+	ld [hl], 2 ; Number of turns from Rest
+	ld hl, StartedSleepingEffect
+	jr z, .asm_3ba31
+	ld hl, FellAsleepBecameHealthyText
+.asm_3ba31
+	call PrintText
+	pop af
+	pop de
+	pop hl
+.asm_3ba37
+	ld a, [hld]
+	ld [wHPBarMaxHP], a
+	ld c, a
+	ld a, [hl]
+	ld [wHPBarMaxHP+1], a
+	ld b, a
+	jr z, .asm_3ba47
+	srl b
+	rr c
+.asm_3ba47
+	ld a, [de]
+	ld [wHPBarOldHP], a
+	add c
+	ld [de], a
+	ld [wHPBarNewHP], a
+	dec de
+	ld a, [de]
+	ld [wHPBarOldHP+1], a
+	adc b
+	ld [de], a
+	ld [wHPBarNewHP+1], a
+	inc hl
+	inc de
+	ld a, [de]
+	dec de
+	sub [hl]
+	dec hl
+	ld a, [de]
+	sbc [hl]
+	jr c, .asm_3ba6f
+	ld a, [hli]
+	ld [de], a
+	ld [wHPBarNewHP+1], a
+	inc de
+	ld a, [hl]
+	ld [de], a
+	ld [wHPBarNewHP], a
+.asm_3ba6f
+	ld hl, PlayCurrentMoveAnimation
+	call BankswitchEtoF
+	ld a, [H_WHOSETURN]
+	and a
+	hlCoord 10, 9
+	ld a, $1
+	jr z, .asm_3ba83
+	hlCoord 2, 2
+	xor a
+.asm_3ba83
+	ld [wHPBarType], a
+	predef UpdateHPBar2
+	ld hl, DrawHUDsAndHPBars
+	call BankswitchEtoF
+	ld hl, RegainedHealthText
+	jp PrintText
+.failed
+	ld c, 50
+	call DelayFrames
+	ld hl, PrintButItFailedText_
+	jp BankswitchEtoF
+
+StartedSleepingEffect: ; 3baa2 (e:7aa2)
+	TX_FAR _StartedSleepingEffect
+	db "@"
+
+FellAsleepBecameHealthyText: ; 3baa7 (e:7aa7)
+	TX_FAR _FellAsleepBecameHealthyText
+	db "@"
+
+RegainedHealthText: ; 3baac (e:7aac)
+	TX_FAR _RegainedHealthText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/leech_seed_effect.asm
@@ -1,0 +1,39 @@
+LeechSeedEffect_: ; 2bea9 (a:7ea9)
+	callab MoveHitTest
+	ld a, [W_MOVEMISSED] ; W_MOVEMISSED
+	and a
+	jr nz, .asm_2bee7
+	ld hl, W_ENEMYBATTSTATUS2 ; W_ENEMYBATTSTATUS2
+	ld de, wEnemyMonType1 ; wcfea (aliases: wEnemyMonType)
+	ld a, [H_WHOSETURN] ; $fff3
+	and a
+	jr z, .asm_2bec8
+	ld hl, W_PLAYERBATTSTATUS2 ; W_PLAYERBATTSTATUS2
+	ld de, wBattleMonType1 ; wd019 (aliases: wBattleMonType)
+.asm_2bec8
+	ld a, [de]
+	cp GRASS
+	jr z, .asm_2bee7
+	inc de
+	ld a, [de]
+	cp GRASS
+	jr z, .asm_2bee7
+	bit Seeded, [hl]
+	jr nz, .asm_2bee7
+	set Seeded, [hl]
+	callab PlayCurrentMoveAnimation
+	ld hl, WasSeededText ; $7ef2
+	jp PrintText
+.asm_2bee7
+	ld c, $32
+	call DelayFrames
+	ld hl, EvadedAttackText ; $7ef7
+	jp PrintText
+
+WasSeededText: ; 2bef2 (a:7ef2)
+	TX_FAR _WasSeededText
+	db "@"
+
+EvadedAttackText: ; 2bef7 (a:7ef7)
+	TX_FAR _EvadedAttackText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/mist_effect.asm
@@ -1,0 +1,21 @@
+MistEffect_: ; 33f2b (c:7f2b)
+	ld hl, W_PLAYERBATTSTATUS2
+	ld a, [$fff3]
+	and a
+	jr z, .asm_33f36
+	ld hl, W_ENEMYBATTSTATUS2
+.asm_33f36
+	bit ProtectedByMist, [hl] ; is mon protected by mist?
+	jr nz, .asm_33f4a
+	set ProtectedByMist, [hl] ; mon is now protected by mist
+	callab PlayCurrentMoveAnimation
+	ld hl, ShroudedInMistText
+	jp PrintText
+.asm_33f4a
+	ld hl, PrintButItFailedText_
+	ld b, BANK(PrintButItFailedText_)
+	jp Bankswitch
+
+ShroudedInMistText: ; 33f52 (c:7f52)
+	TX_FAR _ShroudedInMistText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/one_hit_ko_effect.asm
@@ -1,0 +1,36 @@
+OneHitKOEffect_: ; 33f57 (c:7f57)
+	ld hl, W_DAMAGE 
+	xor a
+	ld [hli], a
+	ld [hl], a ; set the damage output to zero
+	dec a
+	ld [wCriticalHitOrOHKO], a
+	ld hl, wBattleMonSpeed + 1
+	ld de, wEnemyMonSpeed + 1
+	ld a, [H_WHOSETURN] ; $fff3
+	and a
+	jr z, .asm_33f72
+	ld hl, wEnemyMonSpeed + 1
+	ld de, wBattleMonSpeed + 1
+.asm_33f72
+	ld a, [de]
+	dec de
+	ld b, a
+	ld a, [hld]
+	sub b
+	ld a, [de]
+	ld b, a
+	ld a, [hl]
+	sbc b
+	jr c, .asm_33f8a
+	ld hl, W_DAMAGE 
+	ld a, $ff
+	ld [hli], a
+	ld [hl], a
+	ld a, $2
+	ld [wCriticalHitOrOHKO], a
+	ret
+.asm_33f8a
+	ld a, $1
+	ld [W_MOVEMISSED], a 
+	ret
--- /dev/null
+++ b/engine/battle/moveEffects/paralyze_effect.asm
@@ -1,0 +1,53 @@
+ParalyzeEffect_: ; 52601 (14:6601)
+	ld hl, wEnemyMonStatus
+	ld de, W_PLAYERMOVETYPE
+	ld a, [H_WHOSETURN]
+	and a
+	jp z, .next
+	ld hl, wBattleMonStatus 
+	ld de, W_ENEMYMOVETYPE
+.next
+	ld a, [hl]
+	and a ; does the target already have a status ailment?
+	jr nz, .didntAffect
+; check if the target is immune due to types
+	ld a, [de]
+	cp ELECTRIC
+	jr nz, .hitTest
+	ld b, h
+	ld c, l
+	inc bc
+	ld a, [bc]
+	cp GROUND
+	jr z, .doesntAffect
+	inc bc
+	ld a, [bc]
+	cp GROUND
+	jr z, .doesntAffect
+.hitTest
+	push hl
+	callab MoveHitTest
+	pop hl
+	ld a, [W_MOVEMISSED] 
+	and a
+	jr nz, .didntAffect
+	set PAR, [hl]
+	callab QuarterSpeedDueToParalysis
+	ld c, 30
+	call DelayFrames
+	callab PlayCurrentMoveAnimation
+	ld hl, PrintMayNotAttackText
+	ld b, BANK(PrintMayNotAttackText)
+	jp Bankswitch
+.didntAffect
+	ld c, 50
+	call DelayFrames
+	ld hl, PrintDidntAffectText
+	ld b, BANK(PrintDidntAffectText)
+	jp Bankswitch
+.doesntAffect
+	ld c, 50
+	call DelayFrames
+	ld hl, PrintDoesntAffectText
+	ld b, BANK(PrintDoesntAffectText)
+	jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/pay_day_effect.asm
@@ -1,0 +1,43 @@
+PayDayEffect_ ; 2feb8 (b:7eb8)
+	xor a
+	ld hl, wcd6d
+	ld [hli], a
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [wBattleMonLevel]
+	jr z, .asm_2fec8
+	ld a, [wEnemyMonLevel]
+.asm_2fec8
+	add a
+	ld [H_DIVIDEND + 3], a
+	xor a
+	ld [H_DIVIDEND], a
+	ld [H_DIVIDEND + 1], a
+	ld [H_DIVIDEND + 2], a
+	ld a, $64
+	ld [H_DIVISOR], a
+	ld b, $4
+	call Divide
+	ld a, [H_QUOTIENT + 3]
+	ld [hli], a
+	ld a, [H_REMAINDER]
+	ld [H_DIVIDEND + 3], a
+	ld a, $a
+	ld [H_DIVISOR], a
+	ld b, $4
+	call Divide
+	ld a, [H_QUOTIENT + 3]
+	swap a
+	ld b, a
+	ld a, [H_REMAINDER]
+	add b
+	ld [hl], a
+	ld de, wTotalPayDayMoney + 2
+	ld c, $3
+	predef AddBCDPredef
+	ld hl, CoinsScatteredText
+	jp PrintText
+
+CoinsScatteredText: ; 2ff04 (b:7f04)
+	TX_FAR _CoinsScatteredText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/recoil_effect.asm
@@ -1,0 +1,68 @@
+RecoilEffect_: ; 1392c (4:792c)
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [W_PLAYERMOVENUM]
+	ld hl, wBattleMonMaxHP
+	jr z, .asm_1393d
+	ld a, [W_ENEMYMOVENUM]
+	ld hl, wEnemyMonMaxHP
+.asm_1393d
+	ld d, a
+	ld a, [W_DAMAGE]
+	ld b, a
+	ld a, [W_DAMAGE + 1]
+	ld c, a
+	srl b
+	rr c
+	ld a, d
+	cp STRUGGLE
+	jr z, .asm_13953
+	srl b
+	rr c
+.asm_13953
+	ld a, b
+	or c
+	jr nz, .asm_13958
+	inc c
+.asm_13958
+	ld a, [hli]
+	ld [wHPBarMaxHP+1], a
+	ld a, [hl]
+	ld [wHPBarMaxHP], a
+	push bc
+	ld bc, $fff2
+	add hl, bc
+	pop bc
+	ld a, [hl]
+	ld [wHPBarOldHP], a
+	sub c
+	ld [hld], a
+	ld [wHPBarNewHP], a
+	ld a, [hl]
+	ld [wHPBarOldHP+1], a
+	sbc b
+	ld [hl], a
+	ld [wHPBarNewHP+1], a
+	jr nc, .asm_13982
+	xor a
+	ld [hli], a
+	ld [hl], a
+	ld hl, wHPBarNewHP
+	ld [hli], a
+	ld [hl], a
+.asm_13982
+	hlCoord 10, 9
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, $1
+	jr z, .asm_13990
+	hlCoord 2, 2
+	xor a
+.asm_13990
+	ld [wHPBarType], a
+	predef UpdateHPBar2
+	ld hl, HitWithRecoilText
+	jp PrintText
+HitWithRecoilText: ; 1399e (4:799e)
+	TX_FAR _HitWithRecoilText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/reflect_light_screen_effect.asm
@@ -1,0 +1,45 @@
+ReflectLightScreenEffect_: ; 3bb97 (e:7b97)
+	ld hl, W_PLAYERBATTSTATUS3
+	ld de, W_PLAYERMOVEEFFECT
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_3bba8
+	ld hl, W_ENEMYBATTSTATUS3
+	ld de, W_ENEMYMOVEEFFECT
+.asm_3bba8
+	ld a, [de]
+	cp LIGHT_SCREEN_EFFECT
+	jr nz, .reflect
+	bit HasLightScreenUp, [hl] ; is mon already protected by light screen?
+	jr nz, .moveFailed
+	set HasLightScreenUp, [hl] ; mon is now protected by light screen
+	ld hl, LightScreenProtectedText
+	jr .asm_3bbc1
+.reflect
+	bit HasReflectUp, [hl] ; is mon already protected by reflect?
+	jr nz, .moveFailed
+	set HasReflectUp, [hl] ; mon is now protected by reflect
+	ld hl, ReflectGainedArmorText
+.asm_3bbc1
+	push hl
+	ld hl, PlayCurrentMoveAnimation
+	call BankswitchEtoF
+	pop hl
+	jp PrintText
+.moveFailed
+	ld c, $32
+	call DelayFrames
+	ld hl, PrintButItFailedText_
+	jp BankswitchEtoF
+
+LightScreenProtectedText: ; 3bbd7 (e:7bd7)
+	TX_FAR _LightScreenProtectedText
+	db "@"
+
+ReflectGainedArmorText: ; 3bbdc (e:7bdc)
+	TX_FAR _ReflectGainedArmorText
+	db "@"
+
+BankswitchEtoF: ; 3bbe1 (e:7be1)
+	ld b, BANK(BattleCore)
+	jp Bankswitch
--- /dev/null
+++ b/engine/battle/moveEffects/substitute_effect.asm
@@ -1,0 +1,77 @@
+SubstituteEffect_: ; 17dad (5:7dad)
+	ld c, 50
+	call DelayFrames
+	ld hl, wBattleMonMaxHP
+	ld de, wPlayerSubstituteHP
+	ld bc, W_PLAYERBATTSTATUS2
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .notEnemy
+	ld hl, wEnemyMonMaxHP
+	ld de, wEnemySubstituteHP
+	ld bc, W_ENEMYBATTSTATUS2
+.notEnemy
+	ld a, [bc]                    ;load flags
+	bit HasSubstituteUp, a        ;user already has substitute?
+	jr nz, .alreadyHasSubstitute  ;skip this code if so
+	                              ;user doesn't have a substitute [yet]
+	push bc
+	ld a, [hli]  ;load max hp
+	ld b, [hl]
+	srl a        ;max hp / 4, [quarter health to remove from user]
+	rr b
+	srl a
+	rr b
+	push de
+	ld de, wBattleMonHP - wBattleMonMaxHP
+	add hl, de    ; point hl to current HP
+	pop de
+	ld a, b
+	ld [de], a    ;save copy of HP to subtract in ccd7/ccd8 [how much HP substitute has]
+	ld a, [hld]   ;load current hp
+	sub b         ;subtract [max hp / 4]
+	ld d, a       ;save low byte result in D
+	ld a, [hl]
+	sbc a, 0      ;borrow from high byte if needed
+	pop bc
+	jr c, .notEnoughHP  ;underflow means user would be left with negative health
+                        ;bug: note since it only brances on carry, it will possibly leave user with 0HP
+.userHasZeroOrMoreHP
+	ldi [hl], a  ;store high byte HP
+	ld [hl], d   ;store low byte HP
+	ld h, b
+	ld l, c
+	set HasSubstituteUp, [hl] ;set bit 4 of flags, user now has substitute
+	ld a, [W_OPTIONS]         ;load options
+	bit 7, a                  ;battle animation is enabled?
+	ld hl, PlayCurrentMoveAnimation         ;animation enabled: 0F:7BA8
+	ld b, BANK(PlayCurrentMoveAnimation)
+	jr z, .animationEnabled
+	ld hl, AnimationSubstitute ;animation disabled: 1E:56E0
+	ld b, BANK(AnimationSubstitute)
+.animationEnabled
+	call Bankswitch           ;jump to routine depending on animation setting
+	ld hl, SubstituteText
+	call PrintText
+	ld hl, DrawHUDsAndHPBars
+	ld b, BANK(DrawHUDsAndHPBars)
+	jp Bankswitch
+.alreadyHasSubstitute
+	ld hl, HasSubstituteText
+	jr .printText
+.notEnoughHP
+	ld hl, TooWeakSubstituteText
+.printText
+	jp PrintText
+
+SubstituteText: ; 17e1d (5:7e1d)
+	TX_FAR _SubstituteText
+	db "@"
+
+HasSubstituteText: ; 17e22 (5:7e22)
+	TX_FAR _HasSubstituteText
+	db "@"
+
+TooWeakSubstituteText: ; 17e27 (5:7e27)
+	TX_FAR _TooWeakSubstituteText
+	db "@"
--- /dev/null
+++ b/engine/battle/moveEffects/transform_effect.asm
@@ -1,0 +1,138 @@
+TransformEffect_: ; 3bab1 (e:7ab1)
+	ld hl, wBattleMonSpecies
+	ld de, wEnemyMonSpecies
+	ld bc, W_ENEMYBATTSTATUS3
+	ld a, [W_ENEMYBATTSTATUS1]
+	ld a, [H_WHOSETURN]
+	and a
+	jr nz, .asm_3bad1
+	ld hl, wEnemyMonSpecies
+	ld de, wBattleMonSpecies
+	ld bc, W_PLAYERBATTSTATUS3
+	ld [wPlayerMoveListIndex], a
+	ld a, [W_PLAYERBATTSTATUS1]
+.asm_3bad1
+	bit Invulnerable, a ; is mon invulnerable to typical attacks? (fly/dig)
+	jp nz, .failed
+	push hl
+	push de
+	push bc
+	ld hl, W_PLAYERBATTSTATUS2
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_3bae4
+	ld hl, W_ENEMYBATTSTATUS2
+.asm_3bae4
+	bit HasSubstituteUp, [hl]
+	push af
+	ld hl, Func_79747
+	ld b, BANK(Func_79747)
+	call nz, Bankswitch
+	ld a, [W_OPTIONS]
+	add a
+	ld hl, PlayCurrentMoveAnimation
+	ld b, BANK(PlayCurrentMoveAnimation)
+	jr nc, .asm_3baff
+	ld hl, AnimationTransformMon
+	ld b, BANK(AnimationTransformMon)
+.asm_3baff
+	call Bankswitch
+	ld hl, Func_79771
+	ld b, BANK(Func_79771)
+	pop af
+	call nz, Bankswitch
+	pop bc
+	ld a, [bc]
+	set Transformed, a
+	ld [bc], a
+	pop de
+	pop hl
+	push hl
+	ld a, [hl]
+	ld [de], a
+	ld bc, $5
+	add hl, bc
+	inc de
+	inc de
+	inc de
+	inc de
+	inc de
+	inc bc
+	inc bc
+	call CopyData
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_3bb32
+	ld a, [de]
+	ld [wcceb], a
+	inc de
+	ld a, [de]
+	ld [wccec], a
+	dec de
+.asm_3bb32
+	ld a, [hli]
+	ld [de], a
+	inc de
+	ld a, [hli]
+	ld [de], a
+	inc de
+	inc hl
+	inc hl
+	inc hl
+	inc de
+	inc de
+	inc de
+	ld bc, $8
+	call CopyData
+	ld bc, $ffef
+	add hl, bc
+	ld b, $4
+.asm_3bb4a
+	ld a, [hli]
+	and a
+	jr z, .asm_3bb57
+	ld a, $5
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .asm_3bb4a
+	jr .asm_3bb5d
+.asm_3bb57
+	xor a
+	ld [de], a
+	inc de
+	dec b
+	jr nz, .asm_3bb57
+.asm_3bb5d
+	pop hl
+	ld a, [hl]
+	ld [wd11e], a
+	call GetMonName
+	ld hl, wEnemyMonUnmodifiedAttack
+	ld de, wPlayerMonUnmodifiedAttack
+	call .copyBasedOnTurn
+	ld hl, wEnemyMonStatMods
+	ld de, wPlayerMonStatMods
+	call .copyBasedOnTurn
+	ld hl, TransformedText
+	jp PrintText
+
+.copyBasedOnTurn
+	ld a, [H_WHOSETURN]
+	and a
+	jr z, .asm_3bb86
+	push hl
+	ld h, d
+	ld l, e
+	pop de
+.asm_3bb86
+	ld bc, $8
+	jp CopyData
+
+.failed
+	ld hl, PrintButItFailedText_
+	jp BankswitchEtoF
+
+TransformedText: ; 3bb92 (e:7b92)
+	TX_FAR _TransformedText
+	db "@"
--- /dev/null
+++ b/engine/battle/print_type.asm
@@ -1,0 +1,52 @@
+; [wd0b5] = pokemon ID
+; hl = dest addr
+PrintMonType: ; 27d6b (9:7d6b)
+	call GetPredefRegisters
+	push hl
+	call GetMonHeader
+	pop hl
+	push hl
+	ld a, [W_MONHTYPE1]
+	call PrintType
+	ld a, [W_MONHTYPE1]
+	ld b, a
+	ld a, [W_MONHTYPE2]
+	cp b
+	pop hl
+	jr z, EraseType2Text
+	ld bc, SCREEN_WIDTH * 2
+	add hl, bc
+
+; a = type
+; hl = dest addr
+PrintType: ; 27d89 (9:7d89)
+	push hl
+	jr PrintType_
+
+; erase "TYPE2/" if the mon only has 1 type
+EraseType2Text: ; 27d8c (9:7d8c)
+	ld a, " "
+	ld bc, $13
+	add hl, bc
+	ld bc, $6
+	jp FillMemory
+
+PrintMoveType: ; 27d98 (9:7d98)
+	call GetPredefRegisters
+	push hl
+	ld a, [W_PLAYERMOVETYPE]
+; fall through
+
+PrintType_: ; 27d9f (9:7d9f)
+	add a
+	ld hl, TypeNames
+	ld e, a
+	ld d, $0
+	add hl, de
+	ld a, [hli]
+	ld e, a
+	ld d, [hl]
+	pop hl
+	jp PlaceString
+
+INCLUDE "text/type_names.asm"
--- /dev/null
+++ b/engine/battle/read_trainer_party.asm
@@ -1,0 +1,164 @@
+ReadTrainer: ; 39c53 (e:5c53)
+
+; don't change any moves in a link battle
+	ld a,[wLinkState]
+	and a
+	ret nz
+
+; set [wEnemyPartyCount] to 0, [wEnemyPartyMons] 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 [wcf91],a ; write species somewhere (XXX why?)
+	ld a,1
+	ld [wcc49],a
+	push hl
+	call AddPartyMon
+	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 [wcf91],a
+	ld a,1
+	ld [wcc49],a
+	push hl
+	call AddPartyMon
+	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,wEnemyMon1Moves + 2
+	ld bc,wEnemyMon2 - wEnemyMon1
+	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 [wEnemyMon5Moves + 2],a
+	jr .FinishUp
+.ChampionRival ; give moves to his team
+
+; pidgeot
+	ld a,SKY_ATTACK
+	ld [wEnemyMon1Moves + 2],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 [wEnemyMon6Moves + 2],a
+.FinishUp ; XXX this needs documenting
+	xor a       ; clear D079-D07B
+	ld de,wd079
+	ld [de],a
+	inc de
+	ld [de],a
+	inc de
+	ld [de],a
+	ld a,[W_CURENEMYLVL]
+	ld b,a
+.LastLoop
+	ld hl,wd047
+	ld c,2
+	push bc
+	predef AddBCDPredef
+	pop bc
+	inc de
+	inc de
+	dec b
+	jr nz,.LastLoop
+	ret
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/save_trainer_name.asm
@@ -1,0 +1,112 @@
+SaveTrainerName: ; 27e4a (9:7e4a)
+	ld hl,TrainerNamePointers
+	ld a,[W_TRAINERCLASS]
+	dec a
+	ld c,a
+	ld b,0
+	add hl,bc
+	add hl,bc
+	ld a,[hli]
+	ld h,[hl]
+	ld l,a
+	ld de,wcd6d
+.CopyCharacter
+	ld a,[hli]
+	ld [de],a
+	inc de
+	cp "@"
+	jr nz,.CopyCharacter
+	ret
+
+TrainerNamePointers: ; 27e64 (9:7e64)
+; what is the point of these?
+	dw YoungsterName
+	dw BugCatcherName
+	dw LassName
+	dw W_TRAINERNAME
+	dw JrTrainerMName
+	dw JrTrainerFName
+	dw PokemaniacName
+	dw SuperNerdName
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw BurglarName
+	dw EngineerName
+	dw JugglerXName
+	dw W_TRAINERNAME
+	dw SwimmerName
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw BeautyName
+	dw W_TRAINERNAME
+	dw RockerName
+	dw JugglerName
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw BlackbeltName
+	dw W_TRAINERNAME
+	dw ProfOakName
+	dw ChiefName
+	dw ScientistName
+	dw W_TRAINERNAME
+	dw RocketName
+	dw CooltrainerMName
+	dw CooltrainerFName
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+	dw W_TRAINERNAME
+
+YoungsterName: ; 27ec2 (9:7ec2)
+	db "YOUNGSTER@"
+BugCatcherName: ; 27ecc (9:7ecc)
+	db "BUG CATCHER@"
+LassName: ; 27ed8 (9:7ed8)
+	db "LASS@"
+JrTrainerMName: ; 27edd (9:7edd)
+	db "JR.TRAINER♂@"
+JrTrainerFName: ; 27ee9 (9:7ee9)
+	db "JR.TRAINER♀@"
+PokemaniacName: ; 27ef5 (9:7ef5)
+	db "POKéMANIAC@"
+SuperNerdName: ; 27f00 (9:7f00)
+	db "SUPER NERD@"
+BurglarName: ; 27f0b (9:7f0b)
+	db "BURGLAR@"
+EngineerName: ; 27f13 (9:7f13)
+	db "ENGINEER@"
+JugglerXName: ; 27f1c (9:7f1c)
+	db "JUGGLER@"
+SwimmerName: ; 27f24 (9:7f24)
+	db "SWIMMER@"
+BeautyName: ; 27f2c (9:7f2c)
+	db "BEAUTY@"
+RockerName: ; 27f33 (9:7f33)
+	db "ROCKER@"
+JugglerName: ; 27f3a (9:7f3a)
+	db "JUGGLER@"
+BlackbeltName: ; 27f42 (9:7f42)
+	db "BLACKBELT@"
+ProfOakName: ; 27f4c (9:7f4c)
+	db "PROF.OAK@"
+ChiefName: ; 27f55 (9:7f55)
+	db "CHIEF@"
+ScientistName: ; 27f5b (9:7f5b)
+	db "SCIENTIST@"
+RocketName: ; 27f65 (9:7f65)
+	db "ROCKET@"
+CooltrainerMName: ; 27f6c (9:7f6c)
+	db "COOLTRAINER♂@"
+CooltrainerFName: ; 27f79 (9:7f79)
+	db "COOLTRAINER♀@"
--- /dev/null
+++ b/engine/battle/scale_sprites.asm
@@ -1,0 +1,85 @@
+; scales both uncompressed sprite chunks by two in every dimension (creating 2x2 output pixels per input pixel)
+; assumes that input sprite chunks are 4x4 tiles, and the rightmost and bottommost 4 pixels will be ignored
+; resulting in a 7*7 tile output sprite chunk
+ScaleSpriteByTwo: ; 2fe40 (b:7e40)
+	ld de, S_SPRITEBUFFER1 + (4*4*8) - 5          ; last byte of input data, last 4 rows already skipped
+	ld hl, S_SPRITEBUFFER0 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
+	call ScaleLastSpriteColumnByTwo               ; last tile column is special case
+	call ScaleFirstThreeSpriteColumnsByTwo        ; scale first 3 tile columns
+	ld de, S_SPRITEBUFFER2 + (4*4*8) - 5          ; last byte of input data, last 4 rows already skipped
+	ld hl, S_SPRITEBUFFER1 + SPRITEBUFFERSIZE - 1 ; end of destination buffer
+	call ScaleLastSpriteColumnByTwo               ; last tile column is special case
+
+ScaleFirstThreeSpriteColumnsByTwo: ; 2fe55 (b:7e55)
+	ld b, $3 ; 3 tile columns
+.columnLoop
+	ld c, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
+.columnInnerLoop
+	push bc
+	ld a, [de]
+	ld bc, -(7*8)+1       ; $ffc9, scale lower nybble and seek to previous output column
+	call ScalePixelsByTwo
+	ld a, [de]
+	dec de
+	swap a
+	ld bc, 7*8+1-2        ; $37, scale upper nybble and seek back to current output column and to the next 2 rows
+	call ScalePixelsByTwo
+	pop bc
+	dec c
+	jr nz, .columnInnerLoop
+	dec de
+	dec de
+	dec de
+	dec de
+	ld a, b
+	ld bc, -7*8 ; $ffc8, skip one output column (which has already been written along with the current one)
+	add hl, bc
+	ld b, a
+	dec b
+	jr nz, .columnLoop
+	ret
+
+ScaleLastSpriteColumnByTwo: ; 2fe7d (b:7e7d)
+	ld a, 4*8 - 4 ; $1c, 4 tiles minus 4 unused rows
+	ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+	ld bc, -1 ; $ffff
+.columnInnerLoop
+	ld a, [de]
+	dec de
+	swap a                    ; only high nybble contains information
+	call ScalePixelsByTwo
+	ld a, [H_SPRITEINTERLACECOUNTER] ; $ff8b
+	dec a
+	ld [H_SPRITEINTERLACECOUNTER], a ; $ff8b
+	jr nz, .columnInnerLoop
+	dec de                    ; skip last 4 rows of new column
+	dec de
+	dec de
+	dec de
+	ret
+
+; scales the given 4 bits in a (4x1 pixels) to 2 output bytes (8x2 pixels)
+; hl: destination pointer
+; bc: destination pointer offset (added after the two bytes have been written)
+ScalePixelsByTwo: ; 2fe97 (b:7e97)
+	push hl
+	and $f
+	ld hl, DuplicateBitsTable
+	add l
+	ld l, a
+	jr nc, .noCarry
+	inc h
+.noCarry
+	ld a, [hl]
+	pop hl
+	ld [hld], a  ; write output byte twice to make it 2 pixels high
+	ld [hl], a
+	add hl, bc   ; add offset
+	ret
+
+; repeats each input bit twice
+DuplicateBitsTable: ; 2fea8 (b:7ea8)
+	db $00, $03, $0c, $0f
+	db $30, $33, $3c, $3f
+	db $c0, $c3, $cc, $cf
+	db $f0, $f3, $fc, $ff
--- /dev/null
+++ b/engine/battle/scroll_draw_trainer_pic.asm
@@ -1,0 +1,50 @@
+_ScrollTrainerPicAfterBattle: ; 396d3 (e:56d3)
+; Load the enemy trainer's pic and scrolls it into
+; the screen from the right.
+	xor a
+	ld [wEnemyMonSpecies2], a
+	ld b, $1
+	call GoPAL_SET
+	callab _LoadTrainerPic
+	hlCoord 19, 0
+	ld c, $0
+.scrollLoop
+	inc c
+	ld a, c
+	cp 7
+	ret z
+	ld d, $0
+	push bc
+	push hl
+.drawTrainerPicLoop
+	call DrawTrainerPicColumn
+	inc hl
+	ld a, 7
+	add d
+	ld d, a
+	dec c
+	jr nz, .drawTrainerPicLoop
+	ld c, 4
+	call DelayFrames
+	pop hl
+	pop bc
+	dec hl
+	jr .scrollLoop
+
+; write one 7-tile column of the trainer pic to the tilemap
+DrawTrainerPicColumn: ; 39707 (e:5707)
+	push hl
+	push de
+	push bc
+	ld e, 7
+.loop
+	ld [hl], d
+	ld bc, SCREEN_WIDTH
+	add hl, bc
+	inc d
+	dec e
+	jr nz, .loop
+	pop bc
+	pop de
+	pop hl
+	ret
--- /dev/null
+++ b/engine/battle/trainer_ai.asm
@@ -1,0 +1,837 @@
+; 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, wHPBarMaxHP  ; 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, wHPBarMaxHP
+	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, wHPBarMaxHP  ; temp move selection array
+	ld de, wEnemyMonMoves  ; 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, wHPBarMaxHP  ; temp move selection array
+	ld de, wEnemyMonMoves  ; 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, wHPBarMaxHP    ; use created temporary array as move set
+	ret
+.useOriginalMoveSet
+	ld hl, wEnemyMonMoves    ; 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, [wBattleMonStatus]
+	and a
+	ret z ; return if no status ailment on player's mon
+	ld hl, wBuffer - 1 ; temp move selection array (-1 byte offest)
+	ld de, wEnemyMonMoves ; enemy moves
+	ld b, NUM_MOVES + 1
+.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 ; heavily discourage move
+	ld [hl], a
+	jr .nextMove
+
+StatusAilmentMoveEffects ; 57e2
+	db $01 ; unused sleep effect
+	db SLEEP_EFFECT
+	db POISON_EFFECT
+	db PARALYZE_EFFECT
+	db $FF
+
+; slightly encourage moves with specific effects.
+; in particular, stat-modifying moves and other move effects
+; that fall in-bewteen
+AIMoveChoiceModification2: ; 397e7 (e:57e7)
+	ld a, [wAILayer2Encouragement]
+	cp $1 
+	ret nz
+	ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
+	ld de, wEnemyMonMoves ; enemy moves
+	ld b, NUM_MOVES + 1
+.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] ; sligthly encourage this move
+	jr .nextMove
+
+; encourages moves that are effective against the player's mon (even if non-damaging).
+; discourage damaging moves that are ineffective or not very effective against the player's mon,
+; unless there's no damaging move that deals at least neutral damage
+AIMoveChoiceModification3: ; 39817 (e:5817)
+	ld hl, wBuffer - 1 ; temp move selection array (-1 byte offset)
+	ld de, wEnemyMonMoves ; 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, [wd11e]
+	cp $10
+	jr z, .nextMove
+	jr c, .notEffectiveMove
+	dec [hl] ; sligthly 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, wEnemyMonMoves  ; enemy moves
+	ld b, NUM_MOVES + 1
+	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] ; sligthly 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,W_ENEMYMOVENUM
+	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
+
+INCLUDE "engine/battle/trainer_pic_money_pointers.asm"
+	
+INCLUDE "text/trainer_names.asm"	
+
+INCLUDE "engine/battle/bank_e_misc.asm"
+
+INCLUDE "engine/battle/read_trainer_party.asm"
+
+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,[wLinkState]
+	cp LINK_STATE_BATTLING
+	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 Random
+	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 AISwitchIfEnoughMons
+
+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 AICheckIfHPBelowFraction
+	jp c,AIUseHyperPotion
+	ld a,5
+	call AICheckIfHPBelowFraction
+	ret nc
+	jp AISwitchIfEnoughMons
+
+BrockAI: ; 3a614 (e:6614)
+; if his active monster has a status condition, use a full heal
+	ld a,[wEnemyMonStatus]
+	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 AICheckIfHPBelowFraction
+	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 AICheckIfHPBelowFraction
+	ret nc
+	jp AIUseHyperPotion
+
+Sony2AI: ; 3a64c (e:664c)
+	cp $20
+	ret nc
+	ld a,5
+	call AICheckIfHPBelowFraction
+	ret nc
+	jp AIUsePotion
+
+Sony3AI: ; 3a658 (e:6658)
+	cp $20
+	ret nc
+	ld a,5
+	call AICheckIfHPBelowFraction
+	ret nc
+	jp AIUseFullRestore
+
+LoreleiAI: ; 3a664 (e:6664)
+	cp $80
+	ret nc
+	ld a,5
+	call AICheckIfHPBelowFraction
+	ret nc
+	jp AIUseSuperPotion
+
+BrunoAI: ; 3a670 (e:6670)
+	cp $40
+	ret nc
+	jp AIUseXDefend
+
+AgathaAI: ; 3a676 (e:6676)
+	cp $14
+	jp c,AISwitchIfEnoughMons
+	cp $80
+	ret nc
+	ld a,4
+	call AICheckIfHPBelowFraction
+	ret nc
+	jp AIUseSuperPotion
+
+LanceAI: ; 3a687 (e:6687)
+	cp $80
+	ret nc
+	ld a,5
+	call AICheckIfHPBelowFraction
+	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 [wcf05],a
+	ld de,wHPBarOldHP
+	ld hl,wEnemyMonHP + 1
+	ld a,[hld]
+	ld [de],a
+	inc de
+	ld a,[hl]
+	ld [de],a
+	inc de
+	ld hl,wEnemyMonMaxHP + 1
+	ld a,[hld]
+	ld [de],a
+	inc de
+	ld [wHPBarMaxHP],a
+	ld [wEnemyMonHP + 1],a
+	ld a,[hl]
+	ld [de],a
+	ld [wHPBarMaxHP+1],a
+	ld [wEnemyMonHP],a
+	jr AIPrintItemUseAndUpdateHPBar
+
+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 [wcf05],a
+	ld hl,wEnemyMonHP + 1
+	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,wEnemyMonMaxHP + 1
+	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,AIPrintItemUseAndUpdateHPBar
+	inc de
+	ld a,[de]
+	dec de
+	ld [hld],a
+	ld [wHPBarNewHP],a
+	ld a,[de]
+	ld [hl],a
+	ld [wHPBarNewHP+1],a
+	; fallthrough
+
+AIPrintItemUseAndUpdateHPBar: ; 3a718 (e:6718)
+	call AIPrintItemUse_
+	hlCoord 2, 2
+	xor a
+	ld [wHPBarType],a
+	predef UpdateHPBar2
+	jp DecrementAICount
+
+AISwitchIfEnoughMons: ; 3a72a (e:672a)
+; enemy trainer switches if there are 3 or more unfainted mons in party
+	ld a,[wEnemyPartyCount]
+	ld c,a
+	ld hl,wEnemyMon1HP
+
+	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,SwitchEnemyMon
+	and a
+	ret
+
+SwitchEnemyMon: ; 3a74b (e:674b)
+
+; prepare to withdraw the active monster: copy hp, number, and status to roster
+
+	ld a,[wEnemyMonPartyPos]
+	ld hl,wEnemyMon1HP
+	ld bc,wEnemyMon2 - wEnemyMon1
+	call AddNTimes
+	ld d,h
+	ld e,l
+	ld hl,wEnemyMonHP
+	ld bc,4
+	call CopyData
+
+	ld hl, AIBattleWithdrawText
+	call PrintText
+
+	ld a,1
+	ld [wd11d],a
+	callab EnemySendOut
+	xor a
+	ld [wd11d],a
+
+	ld a,[wLinkState]
+	cp LINK_STATE_BATTLING
+	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,[wEnemyMonPartyPos]
+	ld hl,wEnemyMon1Status
+	ld bc,wEnemyMon2 - wEnemyMon1
+	call AddNTimes
+	xor a
+	ld [hl],a ; clear status in enemy team roster
+	ld [wEnemyMonStatus],a ; clear status of active enemy
+	ld hl,W_ENEMYBATTSTATUS3
+	res 0,[hl]
+	ret
+
+AIUseXAccuracy: ; 0x3a7a8 unused
+	call Func_3a69b
+	ld hl,W_ENEMYBATTSTATUS2
+	set 0,[hl]
+	ld a,X_ACCURACY
+	jp AIPrintItemUse
+
+AIUseGuardSpec: ; 3a7b5 (e:67b5)
+	call Func_3a69b
+	ld hl,W_ENEMYBATTSTATUS2
+	set 1,[hl]
+	ld a,GUARD_SPEC_
+	jp AIPrintItemUse
+
+AIUseDireHit: ; 0x3a7c2 unused
+	call Func_3a69b
+	ld hl,W_ENEMYBATTSTATUS2
+	set 2,[hl]
+	ld a,DIRE_HIT
+	jp AIPrintItemUse
+
+AICheckIfHPBelowFraction: ; 3a7cf (e:67cf)
+; return carry if enemy trainer's current HP is below 1 / a of the maximum
+	ld [H_DIVISOR],a
+	ld hl,wEnemyMonMaxHP
+	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,wEnemyMonHP + 1
+	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 [wcf05],a
+	push bc
+	call AIPrintItemUse_
+	pop bc
+	ld hl,W_ENEMYMOVEEFFECT
+	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 [wcf05],a
+	call AIPrintItemUse_
+	jp DecrementAICount
+
+AIPrintItemUse_: ; 3a835 (e:6835)
+; print "x used [wcf05] on z!"
+	ld a,[wcf05]
+	ld [wd11e],a
+	call GetItemName
+	ld hl, AIBattleUseItemText
+	jp PrintText
+
+AIBattleUseItemText: ; 3a844 (e:6844)
+	TX_FAR _AIBattleUseItemText
+	db "@"
--- /dev/null
+++ b/engine/battle/trainer_pic_money_pointers.asm
@@ -1,0 +1,143 @@
+TrainerPicAndMoneyPointers: ; 39914 (e:5914)
+; trainer pic pointers and base money.
+; money received after battle = base money × level of highest-level enemy mon
+	dw YoungsterPic
+	money 1500
+
+	dw BugCatcherPic
+	money 1000
+
+	dw LassPic
+	money 1500
+
+	dw SailorPic
+	money 3000
+
+	dw JrTrainerMPic
+	money 2000
+
+	dw JrTrainerFPic
+	money 2000
+
+	dw PokemaniacPic
+	money 5000
+
+	dw SuperNerdPic
+	money 2500
+
+	dw HikerPic
+	money 3500
+
+	dw BikerPic
+	money 2000
+
+	dw BurglarPic
+	money 9000
+
+	dw EngineerPic
+	money 5000
+
+	dw JugglerPic
+	money 3500
+
+	dw FisherPic
+	money 3500
+
+	dw SwimmerPic
+	money 500
+
+	dw CueBallPic
+	money 2500
+
+	dw GamblerPic
+	money 7000
+
+	dw BeautyPic
+	money 7000
+
+	dw PsychicPic
+	money 1000
+
+	dw RockerPic
+	money 2500
+
+	dw JugglerPic
+	money 3500
+
+	dw TamerPic
+	money 4000
+
+	dw BirdKeeperPic
+	money 2500
+
+	dw BlackbeltPic
+	money 2500
+
+	dw Rival1Pic
+	money 3500
+
+	dw ProfOakPic
+	money 9900
+
+	dw ChiefPic
+	money 3000
+
+	dw ScientistPic
+	money 5000
+
+	dw GiovanniPic
+	money 9900
+
+	dw RocketPic
+	money 3000
+
+	dw CooltrainerMPic
+	money 3500
+
+	dw CooltrainerFPic
+	money 3500
+
+	dw BrunoPic
+	money 9900
+
+	dw BrockPic
+	money 9900
+
+	dw MistyPic
+	money 9900
+
+	dw LtSurgePic
+	money 9900
+
+	dw ErikaPic
+	money 9900
+
+	dw KogaPic
+	money 9900
+
+	dw BlainePic
+	money 9900
+
+	dw SabrinaPic
+	money 9900
+
+	dw GentlemanPic
+	money 7000
+
+	dw Rival2Pic
+	money 6500
+
+	dw Rival3Pic
+	money 9900
+
+	dw LoreleiPic
+	money 9900
+
+	dw ChannelerPic
+	money 3000
+
+	dw AgathaPic
+	money 9900
+
+	dw LancePic
+	money 9900
\ No newline at end of file
--- /dev/null
+++ b/engine/battle/unused_stats_functions.asm
@@ -1,0 +1,62 @@
+; does nothing since no stats are ever selected (barring glitches)
+DoubleSelectedStats: ; 39680 (e:5680)
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [wPlayerStatsToDouble]
+	ld hl, wBattleMonAttack + 1
+	jr z, .notEnemyTurn
+	ld a, [wEnemyStatsToDouble]
+	ld hl, wEnemyMonAttack + 1
+.notEnemyTurn
+	ld c, 4
+	ld b, a
+.loop
+	srl b
+	call c, .doubleStat
+	inc hl
+	inc hl
+	dec c
+	ret z
+	jr .loop
+
+.doubleStat
+	ld a, [hl]
+	add a
+	ld [hld], a
+	ld a, [hl]
+	rl a
+	ld [hli], a
+	ret
+
+; does nothing since no stats are ever selected (barring glitches)
+HalveSelectedStats: ; 396a7 (e:56a7)
+	ld a, [H_WHOSETURN]
+	and a
+	ld a, [wPlayerStatsToHalve]
+	ld hl, wBattleMonAttack
+	jr z, .notEnemyTurn
+	ld a, [wEnemyStatsToHalve]
+	ld hl, wEnemyMonAttack
+.notEnemyTurn
+	ld c, 4
+	ld b, a
+.loop
+	srl b
+	call c, .halveStat
+	inc hl
+	inc hl
+	dec c
+	ret z
+	jr .loop
+
+.halveStat
+	ld a, [hl]
+	srl a
+	ld [hli], a
+	rr [hl]
+	or [hl]
+	jr nz, .nonzeroStat
+	ld [hl], 1
+.nonzeroStat
+	dec hl
+	ret
--- /dev/null
+++ b/engine/battle/wild_encounters.asm
@@ -1,0 +1,118 @@
+; try to initiate a wild pokemon encounter
+; returns success in Z
+TryDoWildEncounter: ; 13870 (4:7870)
+	ld a, [wNPCMovementScriptPointerTableNum]
+	and a
+	ret nz
+	ld a, [wd736]
+	and a
+	ret nz
+	callab IsPlayerStandingOnDoorTileOrWarpTile
+	jr nc, .notStandingOnDoorOrWarpTile
+.CantEncounter
+	ld a, $1
+	and a
+	ret
+.notStandingOnDoorOrWarpTile
+	callab IsPlayerJustOutsideMap
+	jr z, .CantEncounter
+	ld a, [wRepelRemainingSteps]
+	and a
+	jr z, .asm_1389e
+	dec a
+	jr z, .lastRepelStep
+	ld [wRepelRemainingSteps], a
+.asm_1389e
+; determine if wild pok�mon can appear in the half-block we�re standing in	
+; is the bottom right tile (9,9) of the half-block we're standing in a grass/water tile?
+	hlCoord 9, 9
+	ld c, [hl]
+	ld a, [W_GRASSTILE]
+	cp c
+	ld a, [W_GRASSRATE]
+	jr z, .CanEncounter
+	ld a, $14 ; in all tilesets with a water tile, this is its id
+	cp c
+	ld a, [W_WATERRATE]
+	jr z, .CanEncounter
+; even if not in grass/water, standing anywhere we can encounter pok�mon
+; so long as the map is �indoor� and has wild pok�mon defined.
+; �as long as it�s not Viridian Forest or Safari Zone.
+	ld a, [W_CURMAP]
+	cp REDS_HOUSE_1F ; is this an indoor map?
+	jr c, .CantEncounter2
+	ld a, [W_CURMAPTILESET]
+	cp FOREST ; Viridian Forest/Safari Zone
+	jr z, .CantEncounter2
+	ld a, [W_GRASSRATE]
+.CanEncounter
+; compare encounter chance with a random number to determine if there will be an encounter
+	ld b, a
+	ld a, [hRandomAdd]
+	cp b
+	jr nc, .CantEncounter2
+	ld a, [hRandomSub]
+	ld b, a
+	ld hl, WildMonEncounterSlotChances
+.determineEncounterSlot
+	ld a, [hli]
+	cp b
+	jr nc, .gotEncounterSlot
+	inc hl
+	jr .determineEncounterSlot
+.gotEncounterSlot
+; determine which wild pok�mon (grass or water) can appear in the half-block we�re standing in
+	ld c, [hl]
+	ld hl, W_GRASSMONS
+	aCoord 8, 9	
+	cp $14 ; is the bottom left tile (8,9) of the half-block we're standing in a water tile?	
+	jr nz, .gotWildEncounterType ; else, it's treated as a grass tile by default
+	ld hl, W_WATERMONS
+; since the bottom right tile of a "left shore" half-block is $14 but the bottom left tile is not,
+; "left shore" half-blocks (such as the one in the east coast of Cinnabar) load grass encounters.	
+.gotWildEncounterType
+	ld b, $0
+	add hl, bc
+	ld a, [hli]
+	ld [W_CURENEMYLVL], a
+	ld a, [hl]
+	ld [wcf91], a
+	ld [wEnemyMonSpecies2], a
+	ld a, [wRepelRemainingSteps]
+	and a
+	jr z, .willEncounter
+	ld a, [wPartyMon1Level]
+	ld b, a
+	ld a, [W_CURENEMYLVL]
+	cp b
+	jr c, .CantEncounter2 ; repel prevents encounters if the leading party mon's level is higher than the wild mon
+	jr .willEncounter
+.lastRepelStep
+	ld [wRepelRemainingSteps], a
+	ld a, $d2
+	ld [H_DOWNARROWBLINKCNT2], a
+	call EnableAutoTextBoxDrawing
+	call DisplayTextID
+.CantEncounter2
+	ld a, $1
+	and a
+	ret
+.willEncounter
+	xor a
+	ret
+
+WildMonEncounterSlotChances: ; 13918 (4:7918)
+; There are 10 slots for wild pokemon, and this is the table that defines how common each of
+; those 10 slots is. A random number is generated and then the first byte of each pair in this
+; table is compared against that random number. If the random number is less than or equal
+; to the first byte, then that slot is chosen.  The second byte is double the slot number.
+	db $32, $00 ; 51/256 = 19.9% chance of slot 0
+	db $65, $02 ; 51/256 = 19.9% chance of slot 1
+	db $8C, $04 ; 39/256 = 15.2% chance of slot 2
+	db $A5, $06 ; 25/256 =  9.8% chance of slot 3
+	db $BE, $08 ; 25/256 =  9.8% chance of slot 4
+	db $D7, $0A ; 25/256 =  9.8% chance of slot 5
+	db $E4, $0C ; 13/256 =  5.1% chance of slot 6
+	db $F1, $0E ; 13/256 =  5.1% chance of slot 7
+	db $FC, $10 ; 11/256 =  4.3% chance of slot 8
+	db $FF, $12 ;  3/256 =  1.2% chance of slot 9
--- a/engine/items/items.asm
+++ b/engine/items/items.asm
@@ -320,8 +320,8 @@
 	ld [W_ANIMATIONID],a
 	xor a
 	ld [$fff3],a
-	ld [wcc5b],a
-	ld [wd05b],a
+	ld [wAnimationType],a
+	ld [wDamageMultipliers],a
 	ld a,[wWhichPokemon]
 	push af
 	ld a,[wcf91]
--- a/engine/menu/status_screen.asm
+++ b/engine/menu/status_screen.asm
@@ -1,3 +1,67 @@
+DrawHP: ; 128ef (4:68ef)
+; Draws the HP bar in the stats screen
+	call GetPredefRegisters
+	ld a, $1
+	jr DrawHP_
+
+DrawHP2: ; 128f6 (4:68f6)
+; Draws the HP bar in the party screen
+	call GetPredefRegisters
+	ld a, $2
+
+DrawHP_: ; 128fb (4:68fb)
+	ld [wHPBarType], a
+	push hl
+	ld a, [wLoadedMonHP]
+	ld b, a
+	ld a, [wLoadedMonHP + 1]
+	ld c, a
+	or b
+	jr nz, .nonzeroHP
+	xor a
+	ld c, a
+	ld e, a
+	ld a, $6
+	ld d, a
+	jp .drawHPBarAndPrintFraction
+.nonzeroHP
+	ld a, [wLoadedMonMaxHP]
+	ld d, a
+	ld a, [wLoadedMonMaxHP + 1]
+	ld e, a
+	predef HPBarLength
+	ld a, $6
+	ld d, a
+	ld c, a
+.drawHPBarAndPrintFraction
+	pop hl
+	push de
+	push hl
+	push hl
+	call DrawHPBar
+	pop hl
+	ld a, [hFlags_0xFFF6]
+	bit 0, a
+	jr z, .printFractionBelowBar
+	ld bc, $9 ; right of bar
+	jr .printFraction
+.printFractionBelowBar
+	ld bc, SCREEN_WIDTH + 1 ; below bar
+.printFraction
+	add hl, bc
+	ld de, wLoadedMonHP
+	ld bc, $203
+	call PrintNumber
+	ld a, "/"
+	ld [hli], a
+	ld de, wLoadedMonMaxHP
+	ld bc, $203
+	call PrintNumber
+	pop hl
+	pop de
+	ret
+
+
 ; Predef 0x37
 StatusScreen: ; 12953 (4:6953)
 	call LoadMonData
--- /dev/null
+++ b/engine/overworld/is_player_just_outside_map.asm
@@ -1,0 +1,16 @@
+; returns whether the player is one tile outside the map in Z
+IsPlayerJustOutsideMap: ; 128d8 (4:68d8)
+	ld a, [W_YCOORD]
+	ld b, a
+	ld a, [W_CURMAPHEIGHT]
+	call .compareCoordWithMapDimension
+	ret z
+	ld a, [W_XCOORD]
+	ld b, a
+	ld a, [W_CURMAPWIDTH]
+.compareCoordWithMapDimension
+	add a
+	cp b
+	ret z
+	inc b
+	ret
--- a/main.asm
+++ b/main.asm
@@ -1907,7 +1907,7 @@
 	db $ff ; list terminator
 
 
-INCLUDE "engine/battle/1.asm"
+INCLUDE "engine/battle/moveEffects/drain_hp_effect.asm"
 
 INCLUDE "engine/menu/players_pc.asm"
 
@@ -4755,7 +4755,7 @@
 
 SECTION "Battle (bank 4)", ROMX, BANK[$4]
 
-INCLUDE "engine/battle/4.asm"
+INCLUDE "engine/overworld/is_player_just_outside_map.asm"
 INCLUDE "engine/menu/status_screen.asm"
 INCLUDE "engine/menu/party_menu.asm"
 
@@ -4766,7 +4766,12 @@
 INCLUDE "engine/turn_sprite.asm"
 INCLUDE "engine/menu/start_sub_menus.asm"
 INCLUDE "engine/items/tms.asm"
-INCLUDE "engine/battle/4_2.asm"
+INCLUDE "engine/battle/end_of_battle.asm"
+INCLUDE "engine/battle/wild_encounters.asm"
+INCLUDE "engine/battle/moveEffects/recoil_effect.asm"
+INCLUDE "engine/battle/moveEffects/conversion_effect.asm"
+INCLUDE "engine/battle/moveEffects/haze_effect.asm"
+INCLUDE "engine/battle/get_trainer_name.asm"
 INCLUDE "engine/random.asm"
 
 
@@ -4820,7 +4825,7 @@
 INCLUDE "engine/overworld/map_sprites.asm"
 INCLUDE "engine/overworld/emotion_bubbles.asm"
 INCLUDE "engine/evolve_trade.asm"
-INCLUDE "engine/battle/5.asm"
+INCLUDE "engine/battle/moveEffects/substitute_effect.asm"
 INCLUDE "engine/menu/pc.asm"
 
 
@@ -5149,7 +5154,9 @@
 
 
 SECTION "Battle (bank 9)", ROMX, BANK[$9]
-INCLUDE "engine/battle/9.asm"
+INCLUDE "engine/battle/print_type.asm"
+INCLUDE "engine/battle/save_trainer_name.asm"
+INCLUDE "engine/battle/moveEffects/focus_energy_effect.asm"
 
 
 SECTION "Pics 2", ROMX, BANK[PICS_2]
@@ -5221,7 +5228,7 @@
 
 
 SECTION "Battle (bank A)", ROMX, BANK[$A]
-INCLUDE "engine/battle/a.asm"
+INCLUDE "engine/battle/moveEffects/leech_seed_effect.asm"
 
 
 SECTION "Pics 3", ROMX, BANK[PICS_3]
@@ -5300,7 +5307,7 @@
 
 SECTION "Battle (bank B)", ROMX, BANK[$B]
 
-INCLUDE "engine/battle/b.asm"
+INCLUDE "engine/battle/display_effectiveness.asm"
 
 TrainerInfoTextBoxTileGraphics:  INCBIN "gfx/trainer_info.2bpp"
 BlankLeaderNames:                INCBIN "gfx/blank_leader_names.2bpp"
@@ -5308,7 +5315,8 @@
 BadgeNumbersTileGraphics:        INCBIN "gfx/badge_numbers.2bpp"
 
 INCLUDE "engine/items/tmhm.asm"
-INCLUDE "engine/battle/b_2.asm"
+INCLUDE "engine/battle/scale_sprites.asm"
+INCLUDE "engine/battle/moveEffects/pay_day_effect.asm"
 INCLUDE "engine/game_corner_slots2.asm"
 
 
@@ -5378,7 +5386,8 @@
 
 
 SECTION "Battle (bank C)", ROMX, BANK[$C]
-INCLUDE "engine/battle/c.asm"
+INCLUDE "engine/battle/moveEffects/mist_effect.asm"
+INCLUDE "engine/battle/moveEffects/one_hit_ko_effect.asm"
 
 
 SECTION "Pics 5", ROMX, BANK[PICS_5]
@@ -5442,7 +5451,7 @@
 SECTION "Battle (bank D)", ROMX, BANK[$D]
 
 INCLUDE "engine/titlescreen2.asm"
-INCLUDE "engine/battle/d.asm"
+INCLUDE "engine/battle/link_battle_versus_text.asm"
 INCLUDE "engine/slot_machine.asm"
 INCLUDE "engine/overworld/pewter_guys.asm"
 INCLUDE "engine/multiply_divide.asm"
@@ -5454,7 +5463,10 @@
 INCLUDE "data/moves.asm"
 BaseStats: INCLUDE "data/base_stats.asm"
 INCLUDE "data/cries.asm"
-INCLUDE "engine/battle/e.asm"
+INCLUDE "engine/battle/unused_stats_functions.asm"
+INCLUDE "engine/battle/scroll_draw_trainer_pic.asm"
+INCLUDE "engine/battle/trainer_ai.asm"
+INCLUDE "engine/battle/draw_hud_pokeball_gfx.asm"
 
 TradingAnimationGraphics:
 	INCBIN "gfx/game_boy.norepeat.2bpp"
@@ -5465,7 +5477,9 @@
 	INCBIN "gfx/trade2.2bpp"
 
 INCLUDE "engine/evos_moves.asm"
-INCLUDE "engine/battle/e_2.asm"
+INCLUDE "engine/battle/moveEffects/heal_effect.asm"
+INCLUDE "engine/battle/moveEffects/transform_effect.asm"
+INCLUDE "engine/battle/moveEffects/reflect_light_screen_effect.asm"
 
 
 SECTION "bankF",ROMX,BANK[$F]
@@ -5938,7 +5952,8 @@
 INCLUDE "data/mapObjects/mansion4.asm"
 Mansion4Blocks: INCBIN "maps/mansion4.blk"
 
-INCLUDE "engine/battle/14.asm"
+INCLUDE "engine/battle/init_battle_variables.asm"
+INCLUDE "engine/battle/moveEffects/paralyze_effect.asm"
 
 INCLUDE "engine/overworld/card_key.asm"
 
@@ -5999,7 +6014,7 @@
 
 FuchsiaHouse3Blocks: INCBIN "maps/fuchsiahouse3.blk"
 
-INCLUDE "engine/battle/15.asm"
+INCLUDE "engine/battle/experience.asm"
 
 INCLUDE "scripts/route2.asm"
 INCLUDE "scripts/route3.asm"
@@ -6079,7 +6094,7 @@
 
 	INCBIN "maps/unusedblocks58d7d.blk"
 
-INCLUDE "engine/battle/16.asm"
+INCLUDE "engine/battle/common_text.asm"
 
 INCLUDE "engine/experience.asm"
 
@@ -6436,7 +6451,7 @@
 
 SECTION "bank1A",ROMX,BANK[$1A]
 
-INCLUDE "engine/battle/1a.asm"
+INCLUDE "engine/battle/decrement_pp.asm"
 
 Version_GFX:
 IF DEF(_RED)
@@ -6493,7 +6508,8 @@
 INCLUDE "engine/hall_of_fame.asm"
 INCLUDE "engine/overworld/healing_machine.asm"
 INCLUDE "engine/overworld/player_animations.asm"
-INCLUDE "engine/battle/1c.asm"
+INCLUDE "engine/battle/ghost_marowak_anim.asm"
+INCLUDE "engine/battle/battle_transitions.asm"
 INCLUDE "engine/town_map.asm"
 INCLUDE "engine/mon_party_sprites.asm"
 INCLUDE "engine/in_game_trades.asm"
--- a/wram.asm
+++ b/wram.asm
@@ -351,6 +351,10 @@
 	ds 2
 
 wHallOfFame:: ; cc5b
+wBoostExpByExpAll:: ; cc5b
+wAnimationType:: ; cc5b
+; values between 0-6. Shake screen horizontally, shake screen vertically, blink Pokemon...
+
 wcc5b:: ds 1
 wcc5c:: ds 1
 wcc5d:: ds 1
@@ -377,8 +381,12 @@
 
 wccd3:: ds 1
 wccd4:: ds 1
-wccd5:: ds 2
 
+; if [ccd5] != 1, the second AI layer is not applied
+wAILayer2Encouragement:: ; ccd5
+	ds 1
+	ds 1
+
 ; current HP of player and enemy substitutes
 wPlayerSubstituteHP:: ; ccd7
 	ds 1
@@ -424,7 +432,7 @@
 
 wcceb:: ds 1
 wccec:: ds 1
-wcced:: ds 1
+wMonIsDisobedient:: ds 1
 wccee:: ds 1
 wccef:: ds 1
 wccf0:: ds 1
@@ -431,7 +439,7 @@
 wPlayerUsedMove:: ds 1
 wEnemyUsedMove:: ds 1
 wccf3:: ds 1
-wccf4:: ds 1
+wMoveDidntMiss:: ds 1
 
 wPartyFoughtCurrentEnemyFlags::
 ; flags that indicate which party members have fought the current enemy mon
@@ -783,7 +791,9 @@
 wcf37:: ds 20
 wcf4b:: ds 1
 wcf4c:: ds 1
-wcf4d:: ds 18
+wGainBoostedExp:: ; cf4d
+    ds 1
+	ds 17
 
 wGymCityName:: ; cf5f
 wStringBuffer1:: ; cf5f
@@ -967,7 +977,14 @@
 ; in safari battle, this is 2
 	ds 1
 
-wd05b:: ds 1
+wDamageMultipliers:: ; d05b
+; bits 0-6: Effectiveness
+   ;  $0 = immune
+   ;  $5 = not very effective
+   ;  $a = neutral
+   ; $14 = super-effective
+; bit 7: STAB
+    ds 1
 
 W_LONEATTACKNO:: ; d05c
 ; which entry in LoneAttacks to use