pokecrystal-board/engine/battle/ai/switch.asm

659 lines
8.4 KiB
NASM
Raw Normal View History

2018-06-24 07:09:41 -07:00
CheckPlayerMoveTypeMatchups:
; Check how well the moves you've already used
; fare against the enemy's Pokemon. Used to
; score a potential switch.
push hl
push de
push bc
2020-10-21 18:34:18 -07:00
ld a, BASE_AI_SWITCH_SCORE
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
2018-01-23 14:39:09 -08:00
ld hl, wPlayerUsedMoves
ld a, [hl]
and a
jr z, .unknown_moves
ld d, NUM_MOVES
ld e, 0
.loop
ld a, [hli]
and a
jr z, .exit
push hl
dec a
ld hl, Moves + MOVE_POWER
call GetMoveAttr
and a
jr z, .next
inc hl
call GetMoveByte
2018-01-23 14:39:09 -08:00
ld hl, wEnemyMonType
call CheckTypeMatchup
ld a, [wTypeMatchup]
2018-08-07 05:38:41 -07:00
cp EFFECTIVE + 1 ; 1.0 + 0.1
jr nc, .super_effective
and a
jr z, .next
2018-08-07 05:38:41 -07:00
cp EFFECTIVE ; 1.0
jr nc, .neutral
2020-10-21 18:34:18 -07:00
; not very effective
ld a, e
cp 1 ; 0.1
jr nc, .next
ld e, 1
jr .next
.neutral
ld e, 2
jr .next
.super_effective
call .DecreaseScore
pop hl
jr .done
.next
pop hl
dec d
jr nz, .loop
.exit
ld a, e
cp 2
jr z, .done
call .IncreaseScore
ld a, e
and a
jr nz, .done
call .IncreaseScore
jr .done
.unknown_moves
2018-01-23 14:39:09 -08:00
ld a, [wBattleMonType1]
ld b, a
2018-01-23 14:39:09 -08:00
ld hl, wEnemyMonType1
call CheckTypeMatchup
ld a, [wTypeMatchup]
2018-08-07 05:38:41 -07:00
cp EFFECTIVE + 1 ; 1.0 + 0.1
jr c, .ok
call .DecreaseScore
.ok
2018-01-23 14:39:09 -08:00
ld a, [wBattleMonType2]
cp b
jr z, .ok2
call CheckTypeMatchup
ld a, [wTypeMatchup]
2018-08-07 05:38:41 -07:00
cp EFFECTIVE + 1 ; 1.0 + 0.1
jr c, .ok2
call .DecreaseScore
.ok2
.done
call .CheckEnemyMoveMatchups
pop bc
pop de
pop hl
ret
2018-06-24 07:09:41 -07:00
.CheckEnemyMoveMatchups:
2018-01-23 14:39:09 -08:00
ld de, wEnemyMonMoves
ld b, NUM_MOVES + 1
ld c, 0
ld a, [wTypeMatchup]
push af
.loop2
dec b
jr z, .exit2
ld a, [de]
and a
jr z, .exit2
inc de
dec a
ld hl, Moves + MOVE_POWER
call GetMoveAttr
and a
jr z, .loop2
inc hl
call GetMoveByte
2018-01-23 14:39:09 -08:00
ld hl, wBattleMonType1
call CheckTypeMatchup
ld a, [wTypeMatchup]
; immune
and a
jr z, .loop2
; not very effective
inc c
2018-08-07 05:38:41 -07:00
cp EFFECTIVE
jr c, .loop2
; neutral
inc c
inc c
inc c
inc c
inc c
2018-08-07 05:38:41 -07:00
cp EFFECTIVE
jr z, .loop2
; super effective
ld c, 100
jr .loop2
.exit2
pop af
ld [wTypeMatchup], a
ld a, c
and a
jr z, .doubledown ; double down
cp 5
jr c, .DecreaseScore ; down
cp 100
ret c
jr .IncreaseScore ; up
.doubledown
call .DecreaseScore
2018-06-24 07:09:41 -07:00
.DecreaseScore:
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
dec a
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
ret
2018-06-24 07:09:41 -07:00
.IncreaseScore:
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
inc a
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
ret
2018-06-24 07:09:41 -07:00
CheckAbleToSwitch:
xor a
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
call FindAliveEnemyMons
ret c
2018-01-23 14:39:09 -08:00
ld a, [wEnemySubStatus1]
bit SUBSTATUS_PERISH, a
jr z, .no_perish
2018-01-23 14:39:09 -08:00
ld a, [wEnemyPerishCount]
cp 1
jr nz, .no_perish
; Perish count is 1
2015-11-08 16:09:36 -08:00
call FindAliveEnemyMons
call FindEnemyMonsWithAtLeastQuarterMaxHP
2015-11-08 16:09:36 -08:00
call FindEnemyMonsThatResistPlayer
call FindAliveEnemyMonsWithASuperEffectiveMove
ld a, e
cp 2
jr nz, .not_2
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
add $30 ; maximum chance
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
ret
.not_2
2015-11-08 16:09:36 -08:00
call FindAliveEnemyMons
sla c
sla c
ld b, $ff
.loop1
inc b
sla c
jr nc, .loop1
ld a, b
add $30 ; maximum chance
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
ret
.no_perish
call CheckPlayerMoveTypeMatchups
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
cp 11
ret nc
2018-01-23 14:39:09 -08:00
ld a, [wLastPlayerCounterMove]
and a
2015-11-08 16:09:36 -08:00
jr z, .no_last_counter_move
call FindEnemyMonsImmuneToLastCounterMove
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
and a
2015-11-08 16:09:36 -08:00
jr z, .no_last_counter_move
ld c, a
call FindEnemyMonsWithASuperEffectiveMove
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
cp $ff
ret z
ld b, a
ld a, e
cp 2
2015-11-08 16:09:36 -08:00
jr z, .not_2_again
call CheckPlayerMoveTypeMatchups
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
cp 10
ret nc
ld a, b
add $10
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
ret
2015-11-08 16:09:36 -08:00
.not_2_again
ld c, $10
call CheckPlayerMoveTypeMatchups
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
cp 10
2015-11-08 16:09:36 -08:00
jr nc, .okay
ld c, $20
2015-11-08 16:09:36 -08:00
.okay
ld a, b
add c
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
ret
2015-11-08 16:09:36 -08:00
.no_last_counter_move
call CheckPlayerMoveTypeMatchups
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
cp 10
ret nc
2015-11-08 16:09:36 -08:00
call FindAliveEnemyMons
call FindEnemyMonsWithAtLeastQuarterMaxHP
2015-11-08 16:09:36 -08:00
call FindEnemyMonsThatResistPlayer
call FindAliveEnemyMonsWithASuperEffectiveMove
ld a, e
cp $2
ret nz
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
add $10
2015-11-08 16:09:36 -08:00
ld [wEnemySwitchMonParam], a
ret
2018-06-24 07:09:41 -07:00
FindAliveEnemyMons:
2018-01-23 14:39:09 -08:00
ld a, [wOTPartyCount]
cp 2
jr c, .only_one
ld d, a
ld e, 0
ld b, 1 << (PARTY_LENGTH - 1)
ld c, 0
2018-01-23 14:39:09 -08:00
ld hl, wOTPartyMon1HP
.loop
2018-01-23 14:39:09 -08:00
ld a, [wCurOTMon]
cp e
jr z, .next
push bc
ld b, [hl]
inc hl
ld a, [hld]
or b
pop bc
jr z, .next
ld a, c
or b
ld c, a
.next
srl b
push bc
ld bc, PARTYMON_STRUCT_LENGTH
add hl, bc
pop bc
inc e
dec d
jr nz, .loop
ld a, c
and a
jr nz, .more_than_one
.only_one
scf
ret
.more_than_one
and a
ret
2018-06-24 07:09:41 -07:00
FindEnemyMonsImmuneToLastCounterMove:
2018-01-23 14:39:09 -08:00
ld hl, wOTPartyMon1
ld a, [wOTPartyCount]
ld b, a
ld c, 1 << (PARTY_LENGTH - 1)
ld d, 0
xor a
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
.loop
2018-01-23 14:39:09 -08:00
ld a, [wCurOTMon]
cp d
push hl
jr z, .next
push hl
push bc
; If the Pokemon has at least 1 HP...
ld bc, MON_HP
add hl, bc
pop bc
ld a, [hli]
or [hl]
pop hl
jr z, .next
ld a, [hl]
2018-01-23 14:39:09 -08:00
ld [wCurSpecies], a
call GetBaseData
; the player's last move is damaging...
2018-01-23 14:39:09 -08:00
ld a, [wLastPlayerCounterMove]
dec a
ld hl, Moves + MOVE_POWER
call GetMoveAttr
and a
jr z, .next
; and the Pokemon is immune to it...
inc hl
call GetMoveByte
2018-01-23 14:39:09 -08:00
ld hl, wBaseType
call CheckTypeMatchup
ld a, [wTypeMatchup]
and a
jr nz, .next
; ... encourage that Pokemon.
2016-01-12 09:46:18 -08:00
ld a, [wEnemyAISwitchScore]
or c
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
.next
pop hl
dec b
ret z
push bc
ld bc, PARTYMON_STRUCT_LENGTH
add hl, bc
pop bc
inc d
srl c
jr .loop
2018-06-24 07:09:41 -07:00
FindAliveEnemyMonsWithASuperEffectiveMove:
push bc
2018-01-23 14:39:09 -08:00
ld a, [wOTPartyCount]
ld e, a
2018-01-23 14:39:09 -08:00
ld hl, wOTPartyMon1HP
ld b, 1 << (PARTY_LENGTH - 1)
ld c, 0
2015-11-08 16:09:36 -08:00
.loop
ld a, [hli]
or [hl]
2015-11-08 16:09:36 -08:00
jr z, .next
ld a, b
or c
ld c, a
2015-11-08 16:09:36 -08:00
.next
srl b
push bc
2018-01-23 14:39:09 -08:00
ld bc, wPartyMon2HP - (wPartyMon1HP + 1)
add hl, bc
pop bc
dec e
2015-11-08 16:09:36 -08:00
jr nz, .loop
ld a, c
pop bc
and c
ld c, a
2018-06-25 09:24:18 -07:00
; fallthrough
2018-06-25 09:24:18 -07:00
FindEnemyMonsWithASuperEffectiveMove:
ld a, -1
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
2018-01-23 14:39:09 -08:00
ld hl, wOTPartyMon1Moves
ld b, 1 << (PARTY_LENGTH - 1)
ld d, 0
ld e, 0
2015-11-08 16:09:36 -08:00
.loop
ld a, b
and c
2015-11-08 16:09:36 -08:00
jr z, .next
push hl
push bc
; for move on mon:
ld b, NUM_MOVES
ld c, 0
2015-11-08 16:09:36 -08:00
.loop3
; if move is None: break
ld a, [hli]
and a
push hl
2015-11-08 16:09:36 -08:00
jr z, .break3
; if move has no power: continue
dec a
ld hl, Moves + MOVE_POWER
call GetMoveAttr
and a
2015-11-08 16:09:36 -08:00
jr z, .nope
; check type matchups
inc hl
call GetMoveByte
2018-01-23 14:39:09 -08:00
ld hl, wBattleMonType1
call CheckTypeMatchup
; if immune or not very effective: continue
ld a, [wTypeMatchup]
cp 10
2015-11-08 16:09:36 -08:00
jr c, .nope
; if neutral: load 1 and continue
ld e, 1
2018-08-07 05:38:41 -07:00
cp EFFECTIVE + 1
2015-11-08 16:09:36 -08:00
jr c, .nope
; if super-effective: load 2 and break
ld e, 2
2015-11-08 16:09:36 -08:00
jr .break3
2015-11-08 16:09:36 -08:00
.nope
pop hl
dec b
2015-11-08 16:09:36 -08:00
jr nz, .loop3
2015-11-08 16:09:36 -08:00
jr .done
2015-11-08 16:09:36 -08:00
.break3
pop hl
2015-11-08 16:09:36 -08:00
.done
ld a, e
pop bc
pop hl
cp 2
jr z, .done2 ; at least one move is super-effective
cp 1
jr nz, .next ; no move does more than half damage
; encourage this pokemon
ld a, d
or b
ld d, a
jr .next ; such a long jump
2015-11-08 16:09:36 -08:00
.next
; next pokemon?
push bc
ld bc, PARTYMON_STRUCT_LENGTH
add hl, bc
pop bc
srl b
2015-11-08 16:09:36 -08:00
jr nc, .loop
; if no pokemon has a super-effective move: return
ld a, d
ld b, a
and a
ret z
2015-11-08 16:09:36 -08:00
.done2
; convert the bit flag to an int and return
push bc
sla b
sla b
ld c, $ff
2015-11-08 16:09:36 -08:00
.loop2
inc c
sla b
2015-11-08 16:09:36 -08:00
jr nc, .loop2
ld a, c
2016-01-12 09:46:18 -08:00
ld [wEnemyAISwitchScore], a
pop bc
ret
2018-06-24 07:09:41 -07:00
FindEnemyMonsThatResistPlayer:
push bc
2018-01-23 14:39:09 -08:00
ld hl, wOTPartySpecies
ld b, 1 << (PARTY_LENGTH - 1)
ld c, 0
2015-11-08 16:09:36 -08:00
.loop
ld a, [hli]
cp $ff
2015-11-08 16:09:36 -08:00
jr z, .done
push hl
2018-01-23 14:39:09 -08:00
ld [wCurSpecies], a
call GetBaseData
2018-01-23 14:39:09 -08:00
ld a, [wLastPlayerCounterMove]
and a
2015-11-08 16:09:36 -08:00
jr z, .skip_move
dec a
ld hl, Moves + MOVE_POWER
call GetMoveAttr
and a
2015-11-08 16:09:36 -08:00
jr z, .skip_move
inc hl
call GetMoveByte
2015-11-08 16:09:36 -08:00
jr .check_type
2015-11-08 16:09:36 -08:00
.skip_move
2018-01-23 14:39:09 -08:00
ld a, [wBattleMonType1]
ld hl, wBaseType
call CheckTypeMatchup
ld a, [wTypeMatchup]
2015-11-08 16:09:36 -08:00
cp 10 + 1
jr nc, .dont_choose_mon
2018-01-23 14:39:09 -08:00
ld a, [wBattleMonType2]
2015-11-08 16:09:36 -08:00
.check_type
2018-01-23 14:39:09 -08:00
ld hl, wBaseType
call CheckTypeMatchup
ld a, [wTypeMatchup]
2018-08-07 05:38:41 -07:00
cp EFFECTIVE + 1
2015-11-08 16:09:36 -08:00
jr nc, .dont_choose_mon
ld a, b
or c
ld c, a
2015-11-08 16:09:36 -08:00
.dont_choose_mon
srl b
pop hl
2015-11-08 16:09:36 -08:00
jr .loop
2015-11-08 16:09:36 -08:00
.done
ld a, c
pop bc
and c
ld c, a
ret
2018-06-24 07:09:41 -07:00
FindEnemyMonsWithAtLeastQuarterMaxHP:
push bc
2018-01-23 14:39:09 -08:00
ld de, wOTPartySpecies
ld b, 1 << (PARTY_LENGTH - 1)
ld c, 0
2018-01-23 14:39:09 -08:00
ld hl, wOTPartyMon1HP
.loop
ld a, [de]
inc de
cp $ff
jr z, .done
push hl
push bc
ld b, [hl]
inc hl
ld c, [hl]
inc hl
inc hl
2015-11-08 16:09:36 -08:00
; hl = MaxHP + 1
; bc = [CurHP] * 4
srl c
rl b
srl c
rl b
; if bc >= [hl], encourage
ld a, [hld]
cp c
ld a, [hl]
sbc b
pop bc
jr nc, .next
ld a, b
or c
ld c, a
.next
srl b
pop hl
push bc
ld bc, PARTYMON_STRUCT_LENGTH
add hl, bc
pop bc
jr .loop
.done
ld a, c
pop bc
and c
ld c, a
ret