diff options
Diffstat (limited to 'src/engine/ai/attacks.asm')
-rw-r--r-- | src/engine/ai/attacks.asm | 721 |
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 |