summaryrefslogtreecommitdiff
path: root/src/engine/ai/attacks.asm
diff options
context:
space:
mode:
authorElectroDeoxys <ElectroDeoxys@gmail.com>2021-09-29 09:02:02 +0100
committerElectroDeoxys <ElectroDeoxys@gmail.com>2021-09-29 09:02:02 +0100
commitbae47106f18266d2c3b97b6d954b91d9b16c0ccf (patch)
tree4d1a24de37ddb1b22ff22991a275fca351a3651d /src/engine/ai/attacks.asm
parentb0487fa979d0b5f3241e9e0659dd4b29a7e38f18 (diff)
Reorganise some folders in engine/
Diffstat (limited to 'src/engine/ai/attacks.asm')
-rw-r--r--src/engine/ai/attacks.asm721
1 files changed, 0 insertions, 721 deletions
diff --git a/src/engine/ai/attacks.asm b/src/engine/ai/attacks.asm
deleted file mode 100644
index 69ae2e1..0000000
--- a/src/engine/ai/attacks.asm
+++ /dev/null
@@ -1,721 +0,0 @@
-; have AI choose an attack to use, but do not execute it.
-; return carry if an attack is chosen.
-AIProcessButDontUseAttack: ; 169ca (5:69ca)
- ld a, $01
- ld [wAIExecuteProcessedAttack], a
-
-; backup wPlayAreaAIScore in wTempPlayAreaAIScore.
- ld de, wTempPlayAreaAIScore
- ld hl, wPlayAreaAIScore
- ld b, MAX_PLAY_AREA_POKEMON
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .loop
-
-; copies wAIScore to wTempAIScore
- ld a, [wAIScore]
- ld [de], a
- jr AIProcessAttacks
-
-; copies wTempPlayAreaAIScore to wPlayAreaAIScore
-; and loads wAIScore with value in wTempAIScore.
-; identical to RetrievePlayAreaAIScoreFromBackup1.
-RetrievePlayAreaAIScoreFromBackup2: ; 169e3 (5:69e3)
- push af
- ld de, wPlayAreaAIScore
- ld hl, wTempPlayAreaAIScore
- ld b, MAX_PLAY_AREA_POKEMON
-.loop
- ld a, [hli]
- ld [de], a
- inc de
- dec b
- jr nz, .loop
-
- ld a, [hl]
- ld [wAIScore], a
- pop af
- ret
-
-; have AI choose and execute an attack.
-; return carry if an attack was chosen and attempted.
-AIProcessAndTryToUseAttack: ; 169f8 (5:69f8)
- xor a
- ld [wAIExecuteProcessedAttack], a
- ; fallthrough
-
-; checks which of the Active card's attacks for AI to use.
-; If any of the attacks has enough AI score to be used,
-; AI will use it if wAIExecuteProcessedAttack is 0.
-; in either case, return carry if an attack is chosen to be used.
-AIProcessAttacks: ; 169fc (5:69fc)
-; if AI used Pluspower, load its attack index
- ld a, [wPreviousAIFlags]
- and AI_FLAG_USED_PLUSPOWER
- jr z, .no_pluspower
- ld a, [wAIPluspowerAttack]
- ld [wSelectedAttack], a
- jr .attack_chosen
-
-.no_pluspower
-; if Player is running Mewtwo1 mill deck,
-; skip attack if Barrier counter is 0.
- ld a, [wAIBarrierFlagCounter]
- cp AI_MEWTWO_MILL + 0
- jp z, .dont_attack
-
-; determine AI score of both attacks.
- xor a ; FIRST_ATTACK_OR_PKMN_POWER
- call GetAIScoreOfAttack
- ld a, [wAIScore]
- ld [wFirstAttackAIScore], a
- ld a, SECOND_ATTACK
- call GetAIScoreOfAttack
-
-; compare both attack scores
- ld c, SECOND_ATTACK
- ld a, [wFirstAttackAIScore]
- ld b, a
- ld a, [wAIScore]
- cp b
- jr nc, .check_score
- ; first attack has higher score
- dec c
- ld a, b
-
-; c holds the attack index chosen by AI,
-; and a holds its AI score.
-; first check if chosen attack has at least minimum score.
-; then check if first attack is better than second attack
-; in case the second one was chosen.
-.check_score
- cp $50 ; minimum score to use attack
- jr c, .dont_attack
- ; enough score, proceed
-
- ld a, c
- ld [wSelectedAttack], a
- or a
- jr z, .attack_chosen
- call CheckWhetherToSwitchToFirstAttack
-
-.attack_chosen
-; check whether to execute the attack chosen
- ld a, [wAIExecuteProcessedAttack]
- or a
- jr z, .execute
-
-; set carry and reset Play Area AI score
-; to the previous values.
- scf
- jp RetrievePlayAreaAIScoreFromBackup2
-
-.execute
- ld a, AI_TRAINER_CARD_PHASE_14
- call AIProcessHandTrainerCards
-
-; load this attack's damage output against
-; the current Defending Pokemon.
- xor a ; PLAY_AREA_ARENA
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, [wSelectedAttack]
- call EstimateDamage_VersusDefendingCard
- ld a, [wDamage]
-
- or a
- jr z, .check_damage_bench
- ; if damage is not 0, fallthrough
-
-.can_damage
- xor a
- ld [wcdb4], a
- jr .use_attack
-
-.check_damage_bench
-; check if it can otherwise damage player's bench
- ld a, ATTACK_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F
- call CheckLoadedAttackFlag
- jr c, .can_damage
-
-; cannot damage either Defending Pokemon or Bench
- ld hl, wcdb4
- inc [hl]
-
-; return carry if attack is chosen
-; and AI tries to use it.
-.use_attack
- ld a, TRUE
- ld [wAITriedAttack], a
- call AITryUseAttack
- scf
- ret
-
-.dont_attack
- ld a, [wAIExecuteProcessedAttack]
- or a
- jr z, .failed_to_use
-
-; reset Play Area AI score
-; to the previous values.
- jp RetrievePlayAreaAIScoreFromBackup2
-
-; return no carry if no viable attack.
-.failed_to_use
- ld hl, wcdb4
- inc [hl]
- or a
- ret
-
-; determines the AI score of attack index in a
-; of card in Play Area location hTempPlayAreaLocation_ff9d.
-GetAIScoreOfAttack: ; 16a86 (5:6a86)
-; initialize AI score.
- ld [wSelectedAttack], a
- ld a, $50
- ld [wAIScore], a
-
- xor a
- ldh [hTempPlayAreaLocation_ff9d], a
- call CheckIfSelectedAttackIsUnusable
- jr nc, .usable
-
-; return zero AI score.
-.unusable
- xor a
- ld [wAIScore], a
- jp .done
-
-; load arena card IDs
-.usable
- xor a
- ld [wAICannotDamage], a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- call GetCardIDFromDeckIndex
- ld a, e
- ld [wTempTurnDuelistCardID], a
- call SwapTurn
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- call GetCardIDFromDeckIndex
- ld a, e
- ld [wTempNonTurnDuelistCardID], a
-
-; handle the case where the player has No Damage substatus.
-; in the case the player does, check if this attack
-; has a residual effect, or if it can damage the opposing bench.
-; If none of those are true, render the attack unusable.
-; also if it's a PKMN power, consider it unusable as well.
- bank1call HandleNoDamageOrEffectSubstatus
- call SwapTurn
- jr nc, .check_if_can_ko
-
- ; player is under No Damage substatus
- ld a, $01
- ld [wAICannotDamage], a
- ld a, [wSelectedAttack]
- call EstimateDamage_VersusDefendingCard
- ld a, [wLoadedAttackCategory]
- cp POKEMON_POWER
- jr z, .unusable
- and RESIDUAL
- jr nz, .check_if_can_ko
- ld a, ATTACK_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F
- call CheckLoadedAttackFlag
- jr nc, .unusable
-
-; calculate damage to player to check if attack can KO.
-; encourage attack if it's able to KO.
-.check_if_can_ko
- ld a, [wSelectedAttack]
- call EstimateDamage_VersusDefendingCard
- ld a, DUELVARS_ARENA_CARD_HP
- call GetNonTurnDuelistVariable
- ld hl, wDamage
- sub [hl]
- jr c, .can_ko
- jr z, .can_ko
- jr .check_damage
-.can_ko
- ld a, 20
- call AddToAIScore
-
-; raise AI score by the number of damage counters that this attack deals.
-; if no damage is dealt, subtract AI score. in case wDamage is zero
-; but wMaxDamage is not, then encourage attack afterwards.
-; otherwise, if wMaxDamage is also zero, check for damage against
-; player's bench, and encourage attack in case there is.
-.check_damage
- xor a
- ld [wAIAttackIsNonDamaging], a
- ld a, [wDamage]
- ld [wTempAI], a
- or a
- jr z, .no_damage
- call CalculateByteTensDigit
- call AddToAIScore
- jr .check_recoil
-.no_damage
- ld a, $01
- ld [wAIAttackIsNonDamaging], a
- call SubFromAIScore
- ld a, [wAIMaxDamage]
- or a
- jr z, .no_max_damage
- ld a, 2
- call AddToAIScore
- xor a
- ld [wAIAttackIsNonDamaging], a
-.no_max_damage
- ld a, ATTACK_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F
- call CheckLoadedAttackFlag
- jr nc, .check_recoil
- ld a, 2
- call AddToAIScore
-
-; handle recoil attacks (low and high recoil).
-.check_recoil
- ld a, ATTACK_FLAG1_ADDRESS | LOW_RECOIL_F
- call CheckLoadedAttackFlag
- jr c, .is_recoil
- ld a, ATTACK_FLAG1_ADDRESS | HIGH_RECOIL_F
- call CheckLoadedAttackFlag
- jp nc, .check_defending_can_ko
-.is_recoil
- ; sub from AI score number of damage counters
- ; that attack deals to itself.
- ld a, [wLoadedAttackEffectParam]
- or a
- jp z, .check_defending_can_ko
- ld [wDamage], a
- call ApplyDamageModifiers_DamageToSelf
- ld a, e
- call CalculateByteTensDigit
- call SubFromAIScore
-
- push de
- ld a, ATTACK_FLAG1_ADDRESS | HIGH_RECOIL_F
- call CheckLoadedAttackFlag
- pop de
- jr c, .high_recoil
-
- ; if LOW_RECOIL KOs self, decrease AI score
- ld a, DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- cp e
- jr c, .kos_self
- jp nz, .check_defending_can_ko
-.kos_self
- ld a, 10
- call SubFromAIScore
-
-.high_recoil
- ; dismiss this attack if no benched Pokémon
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- cp 2
- jr c, .dismiss_high_recoil_atk
- ; has benched Pokémon
-
-; here the AI handles high recoil attacks differently
-; depending on what deck it's playing.
- ld a, [wOpponentDeckID]
- cp ROCK_CRUSHER_DECK_ID
- jr z, .rock_crusher_deck
- cp ZAPPING_SELFDESTRUCT_DECK_ID
- jr z, .zapping_selfdestruct_deck
- cp BOOM_BOOM_SELFDESTRUCT_DECK_ID
- jr z, .encourage_high_recoil_atk
- ; Boom Boom Selfdestruct deck always encourages
- cp POWER_GENERATOR_DECK_ID
- jr nz, .high_recoil_generic_checks
- ; Power Generator deck always dismisses
-
-.dismiss_high_recoil_atk
- xor a
- ld [wAIScore], a
- jp .done
-
-.encourage_high_recoil_atk
- ld a, 20
- call AddToAIScore
- jp .done
-
-; Zapping Selfdestruct deck only uses this attack
-; if number of cards in deck >= 30 and
-; HP of active card is < half max HP.
-.zapping_selfdestruct_deck
- ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK
- call GetTurnDuelistVariable
- cp 31
- jr nc, .high_recoil_generic_checks
- ld e, PLAY_AREA_ARENA
- call GetCardDamageAndMaxHP
- sla a
- cp c
- jr c, .high_recoil_generic_checks
- ld b, 0
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- call GetCardIDFromDeckIndex
- ld a, e
- cp MAGNEMITE1
- jr z, .magnemite1
- ld b, 10 ; bench damage
-.magnemite1
- ld a, 10
- add b
- ld b, a ; 20 bench damage if not Magnemite1
-
-; if this attack causes player to win the duel by
-; knocking out own Pokémon, dismiss attack.
- ld a, 1 ; count active Pokémon as KO'd
- call .check_if_kos_bench
- jr c, .dismiss_high_recoil_atk
- jr .encourage_high_recoil_atk
-
-; Rock Crusher Deck only uses this attack if
-; prize count is below 4 and attack wins (or potentially draws) the duel,
-; (i.e. at least gets KOs equal to prize cards left).
-.rock_crusher_deck
- call CountPrizes
- cp 4
- jr nc, .dismiss_high_recoil_atk
- ; prize count < 4
- ld b, 20 ; damage dealt to bench
- call SwapTurn
- xor a
- call .check_if_kos_bench
- call SwapTurn
- jr c, .encourage_high_recoil_atk
-
-; generic checks for all other deck IDs.
-; encourage attack if it wins (or potentially draws) the duel,
-; (i.e. at least gets KOs equal to prize cards left).
-; dismiss it if it causes the player to win.
-.high_recoil_generic_checks
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- call GetCardIDFromDeckIndex
- ld a, e
- cp CHANSEY
- jr z, .chansey
- cp MAGNEMITE1
- jr z, .magnemite1_or_weezing
- cp WEEZING
- jr z, .magnemite1_or_weezing
- ld b, 20 ; bench damage
- jr .check_bench_kos
-.magnemite1_or_weezing
- ld b, 10 ; bench damage
- jr .check_bench_kos
-.chansey
- ld b, 0 ; no bench damage
-
-.check_bench_kos
- push bc
- call SwapTurn
- xor a
- call .check_if_kos_bench
- call SwapTurn
- pop bc
- jr c, .wins_the_duel
- push de
- ld a, 1
- call .check_if_kos_bench
- pop bc
- jr nc, .count_own_ko_bench
-
-; attack causes player to draw all prize cards
- xor a
- ld [wAIScore], a
- jp .done
-
-; attack causes CPU to draw all prize cards
-.wins_the_duel
- ld a, 20
- call AddToAIScore
- jp .done
-
-; subtract from AI score number of own benched Pokémon KO'd
-.count_own_ko_bench
- push bc
- ld a, d
- or a
- jr z, .count_player_ko_bench
- dec a
- call SubFromAIScore
-
-; add to AI score number of player benched Pokémon KO'd
-.count_player_ko_bench
- pop bc
- ld a, b
- call AddToAIScore
- jr .check_defending_can_ko
-
-; local function that gets called to determine damage to
-; benched Pokémon caused by a HIGH_RECOIL attack.
-; return carry if using attack causes number of benched Pokémon KOs
-; equal to or larger than remaining prize cards.
-; this function is independent on duelist turn, so whatever
-; turn it is when this is called, it's that duelist's
-; bench/prize cards that get checked.
-; input:
-; a = initial number of KO's beside benched Pokémon,
-; so that if the active Pokémon is KO'd by the attack,
-; this counts towards the prize cards collected
-; b = damage dealt to bench Pokémon
-.check_if_kos_bench
- ld d, a
- ld a, DUELVARS_BENCH
- call GetTurnDuelistVariable
- ld e, PLAY_AREA_ARENA
-.loop
- inc e
- ld a, [hli]
- cp $ff
- jr z, .exit_loop
- ld a, e
- add DUELVARS_ARENA_CARD_HP
- push hl
- call GetTurnDuelistVariable
- pop hl
- cp b
- jr z, .increase_count
- jr nc, .loop
-.increase_count
- ; increase d if damage dealt KOs
- inc d
- jr .loop
-.exit_loop
- push de
- call SwapTurn
- call CountPrizes
- call SwapTurn
- pop de
- cp d
- jp c, .set_carry
- jp z, .set_carry
- or a
- ret
-.set_carry
- scf
- ret
-
-; if defending card can KO, encourage attack
-; unless attack is non-damaging.
-.check_defending_can_ko
- ld a, [wSelectedAttack]
- push af
- call CheckIfDefendingPokemonCanKnockOut
- pop bc
- ld a, b
- ld [wSelectedAttack], a
- jr nc, .check_discard
- ld a, 5
- call AddToAIScore
- ld a, [wAIAttackIsNonDamaging]
- or a
- jr z, .check_discard
- ld a, 5
- call SubFromAIScore
-
-; subtract from AI score if this attack requires
-; discarding any energy cards.
-.check_discard
- ld a, [wSelectedAttack]
- ld e, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld a, ATTACK_FLAG2_ADDRESS | DISCARD_ENERGY_F
- call CheckLoadedAttackFlag
- jr nc, .asm_16ca6
- ld a, 1
- call SubFromAIScore
- ld a, [wLoadedAttackEffectParam]
- call SubFromAIScore
-
-.asm_16ca6
- ld a, ATTACK_FLAG2_ADDRESS | FLAG_2_BIT_6_F
- call CheckLoadedAttackFlag
- jr nc, .check_nullify_flag
- ld a, [wLoadedAttackEffectParam]
- call AddToAIScore
-
-; encourage attack if it has a nullify or weaken attack effect.
-.check_nullify_flag
- ld a, ATTACK_FLAG2_ADDRESS | NULLIFY_OR_WEAKEN_ATTACK_F
- call CheckLoadedAttackFlag
- jr nc, .check_draw_flag
- ld a, 1
- call AddToAIScore
-
-; encourage attack if it has an effect to draw a card.
-.check_draw_flag
- ld a, ATTACK_FLAG1_ADDRESS | DRAW_CARD_F
- call CheckLoadedAttackFlag
- jr nc, .check_heal_flag
- ld a, 1
- call AddToAIScore
-
-.check_heal_flag
- ld a, ATTACK_FLAG2_ADDRESS | HEAL_USER_F
- call CheckLoadedAttackFlag
- jr nc, .check_status_effect
- ld a, [wLoadedAttackEffectParam]
- cp 1
- jr z, .tally_heal_score
- ld a, [wTempAI]
- call CalculateByteTensDigit
- ld b, a
- ld a, [wLoadedAttackEffectParam]
- cp 3
- jr z, .asm_16cec
- srl b
- jr nc, .asm_16cec
- inc b
-.asm_16cec
- ld a, DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- call CalculateByteTensDigit
- cp b
- jr c, .tally_heal_score
- ld a, b
-.tally_heal_score
- push af
- ld e, PLAY_AREA_ARENA
- call GetCardDamageAndMaxHP
- call CalculateByteTensDigit
- pop bc
- cp b ; wLoadedAttackEffectParam
- jr c, .add_heal_score
- ld a, b
-.add_heal_score
- call AddToAIScore
-
-.check_status_effect
- ld a, DUELVARS_ARENA_CARD
- call GetNonTurnDuelistVariable
- call SwapTurn
- call GetCardIDFromDeckIndex
- call SwapTurn
- ld a, e
- ; skip if player has Snorlax
- cp SNORLAX
- jp z, .handle_special_atks
-
- ld a, DUELVARS_ARENA_CARD_STATUS
- call GetNonTurnDuelistVariable
- ld [wTempAI], a
-
-; encourage a poison inflicting attack if opposing Pokémon
-; isn't (doubly) poisoned already.
-; if opposing Pokémon is only poisoned and not double poisoned,
-; and this attack has FLAG_2_BIT_6 set, discourage it
-; (possibly to make Nidoking's Toxic attack less likely to be chosen
-; if the other Pokémon is poisoned.)
- ld a, ATTACK_FLAG1_ADDRESS | INFLICT_POISON_F
- call CheckLoadedAttackFlag
- jr nc, .check_sleep
- ld a, [wTempAI]
- and DOUBLE_POISONED
- jr z, .add_poison_score
- and $40 ; only double poisoned?
- jr z, .check_sleep
- ld a, ATTACK_FLAG2_ADDRESS | FLAG_2_BIT_6_F
- call CheckLoadedAttackFlag
- jr nc, .check_sleep
- ld a, 2
- call SubFromAIScore
- jr .check_sleep
-.add_poison_score
- ld a, 2
- call AddToAIScore
-
-; encourage sleep-inducing attack if other Pokémon isn't asleep.
-.check_sleep
- ld a, ATTACK_FLAG1_ADDRESS | INFLICT_SLEEP_F
- call CheckLoadedAttackFlag
- jr nc, .check_paralysis
- ld a, [wTempAI]
- and CNF_SLP_PRZ
- cp ASLEEP
- jr z, .check_paralysis
- ld a, 1
- call AddToAIScore
-
-; encourage paralysis-inducing attack if other Pokémon isn't asleep.
-; otherwise, if other Pokémon is asleep, discourage attack.
-.check_paralysis
- ld a, ATTACK_FLAG1_ADDRESS | INFLICT_PARALYSIS_F
- call CheckLoadedAttackFlag
- jr nc, .check_confusion
- ld a, [wTempAI]
- and CNF_SLP_PRZ
- cp ASLEEP
- jr z, .sub_prz_score
- ld a, 1
- call AddToAIScore
- jr .check_confusion
-.sub_prz_score
- ld a, 1
- call SubFromAIScore
-
-; encourage confuse-inducing attack if other Pokémon isn't asleep
-; or confused already.
-; otherwise, if other Pokémon is asleep or confused,
-; discourage attack instead.
-.check_confusion
- ld a, ATTACK_FLAG1_ADDRESS | INFLICT_CONFUSION_F
- call CheckLoadedAttackFlag
- jr nc, .check_if_confused
- ld a, [wTempAI]
- and CNF_SLP_PRZ
- cp ASLEEP
- jr z, .sub_cnf_score
- ld a, [wTempAI]
- and CNF_SLP_PRZ
- cp CONFUSED
- jr z, .check_if_confused
- ld a, 1
- call AddToAIScore
- jr .check_if_confused
-.sub_cnf_score
- ld a, 1
- call SubFromAIScore
-
-; if this Pokémon is confused, subtract from score.
-.check_if_confused
- ld a, DUELVARS_ARENA_CARD_STATUS
- call GetTurnDuelistVariable
- and CNF_SLP_PRZ
- cp CONFUSED
- jr nz, .handle_special_atks
- ld a, 1
- call SubFromAIScore
-
-; SPECIAL_AI_HANDLING marks attacks that the AI handles individually.
-; each attack has its own checks and modifies AI score accordingly.
-.handle_special_atks
- ld a, ATTACK_FLAG3_ADDRESS | SPECIAL_AI_HANDLING_F
- call CheckLoadedAttackFlag
- jr nc, .done
- call HandleSpecialAIAttacks
- cp $80
- jr c, .negative_score
- sub $80
- call AddToAIScore
- jr .done
-.negative_score
- ld b, a
- ld a, $80
- sub b
- call SubFromAIScore
-
-.done
- ret