diff options
Diffstat (limited to 'src/engine/ai/trainer_cards.asm')
-rw-r--r-- | src/engine/ai/trainer_cards.asm | 6073 |
1 files changed, 0 insertions, 6073 deletions
diff --git a/src/engine/ai/trainer_cards.asm b/src/engine/ai/trainer_cards.asm deleted file mode 100644 index 4bee001..0000000 --- a/src/engine/ai/trainer_cards.asm +++ /dev/null @@ -1,6073 +0,0 @@ -INCLUDE "data/duel/ai_trainer_card_logic.asm" - -_AIProcessHandTrainerCards: ; 200e5 (8:40e5) - ld [wAITrainerCardPhase], a -; create hand list in wDuelTempList and wTempHandCardList. - call CreateHandCardList - ld hl, wDuelTempList - ld de, wTempHandCardList - call CopyBuffer - ld hl, wTempHandCardList - -.loop_hand - ld a, [hli] - ld [wAITrainerCardToPlay], a - cp $ff - ret z - - push hl - ld a, [wAITrainerCardPhase] - ld d, a - ld hl, AITrainerCardLogic -.loop_data - xor a - ld [wCurrentAIFlags], a - ld a, [hli] - cp $ff - jp z, .pop_hl - -; compare input to first byte in data and continue if equal. - cp d - jp nz, .inc_hl_by_5 - - ld a, [hli] - ld [wce17], a - ld a, [wAITrainerCardToPlay] - call LoadCardDataToBuffer1_FromDeckIndex - - cp SWITCH - jr nz, .skip_switch_check - - ld b, a - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_SWITCH - jr nz, .inc_hl_by_4 - ld a, b - -.skip_switch_check -; compare hand card to second byte in data and continue if equal. - ld b, a - ld a, [wce17] - cp b - jr nz, .inc_hl_by_4 - -; found Trainer card - push hl - push de - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - -; if Headache effects prevent playing card -; move on to the next item in list. - bank1call CheckCantUseTrainerDueToHeadache - jp c, .next_in_data - - call LoadNonPokemonCardEffectCommands - ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1 - call TryExecuteEffectCommandFunction - jp c, .next_in_data - -; AI can randomly choose not to play card. - farcall AIChooseRandomlyNotToDoAction - jr c, .next_in_data - -; call routine to decide whether to play Trainer card - pop de - pop hl - push hl - call CallIndirect - pop hl - jr nc, .inc_hl_by_4 - -; routine returned carry, which means -; this card should be played. - inc hl - inc hl - ld [wAITrainerCardParameter], a - -; show Play Trainer Card screen - push de - push hl - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_PLAY_TRAINER - bank1call AIMakeDecision - pop hl - pop de - jr c, .inc_hl_by_2 - -; execute the effects of the Trainer card - push hl - call CallIndirect - pop hl - - inc hl - inc hl - ld a, [wPreviousAIFlags] - ld b, a - ld a, [wCurrentAIFlags] - or b - ld [wPreviousAIFlags], a - pop hl - and AI_FLAG_MODIFIED_HAND - jp z, .loop_hand - -; the hand was modified during the Trainer effect -; so it needs to be re-listed again and -; looped from the top. - call CreateHandCardList - ld hl, wDuelTempList - ld de, wTempHandCardList - call CopyBuffer - ld hl, wTempHandCardList -; clear the AI_FLAG_MODIFIED_HAND flag - ld a, [wPreviousAIFlags] - and ~AI_FLAG_MODIFIED_HAND - ld [wPreviousAIFlags], a - jp .loop_hand - -.inc_hl_by_5 - inc hl -.inc_hl_by_4 - inc hl - inc hl -.inc_hl_by_2 - inc hl - inc hl - jp .loop_data - -.next_in_data - pop de - pop hl - inc hl - inc hl - inc hl - inc hl - jp .loop_data - -.pop_hl - pop hl - jp .loop_hand - -; makes AI use Potion card. -AIPlay_Potion: ; 201b5 (8:41b5) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld e, a - call GetCardDamageAndMaxHP - cp 20 - jr c, .play_card - ld a, 20 -.play_card - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; if AI doesn't decide to retreat this card, -; check if defending Pokémon can KO active card -; next turn after using Potion. -; if it cannot, return carry. -; also take into account whether attack is high recoil. -AIDecide_Potion1: ; 201d1 (8:41d1) - farcall AIDecideWhetherToRetreat - jr c, .no_carry - call AICheckIfAttackIsHighRecoil - jr c, .no_carry - xor a ; active card - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfDefendingPokemonCanKnockOut - jr nc, .no_carry - ld d, a - - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - ld h, a - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - cp 20 + 1 ; if damage <= 20 - jr c, .calculate_hp - ld a, 20 ; amount of Potion HP healing - -; if damage done by defending Pokémon next turn will still -; KO this card after healing, return no carry. -.calculate_hp - ld l, a - ld a, h - add l - sub d - jr c, .no_carry - jr z, .no_carry - -; return carry. - xor a - scf - ret -.no_carry - or a - ret - -; finds a card in Play Area to use Potion on. -; output: -; a = card to use Potion on; -; carry set if Potion should be used. -AIDecide_Potion2: ; 20204 (8:4204) - xor a - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfDefendingPokemonCanKnockOut - jr nc, .start_from_active -; can KO - ld d, a - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - ld h, a - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - cp 20 + 1 ; if damage <= 20 - jr c, .calculate_hp - ld a, 20 -; return if using healing prevents KO. -.calculate_hp - ld l, a - ld a, h - add l - sub d - jr c, .count_prizes - jr z, .count_prizes - or a - ret - -; using Potion on active card does not prevent a KO. -; if player is at last prize, start loop with active card. -; otherwise start loop at first bench Pokémon. -.count_prizes - call SwapTurn - call CountPrizes - call SwapTurn - dec a - jr z, .start_from_active - ld e, PLAY_AREA_BENCH_1 - jr .loop - -; find Play Area Pokémon with more than 10 damage. -; skip Pokémon if it has a BOOST_IF_TAKEN_DAMAGE attack. -.start_from_active - ld e, PLAY_AREA_ARENA -.loop - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - ret z - call .check_boost_if_taken_damage - jr c, .has_boost_damage - call GetCardDamageAndMaxHP - cp 20 ; if damage >= 20 - jr nc, .found -.has_boost_damage - inc e - jr .loop - -; a card was found, now to check if it's active or benched. -.found - ld a, e - or a - jr z, .active_card - -; bench card - push de - call SwapTurn - call CountPrizes - call SwapTurn - dec a - or a - jr z, .check_random - ld a, 10 - call Random - cp 3 -; 7/10 chance of returning carry. -.check_random - pop de - jr c, .no_carry - ld a, e - scf - ret - -; return carry for active card if not High Recoil. -.active_card - push de - call AICheckIfAttackIsHighRecoil - pop de - jr c, .no_carry - ld a, e - scf - ret -.no_carry - or a - ret - -; return carry if either of the attacks are usable -; and have the BOOST_IF_TAKEN_DAMAGE effect. -.check_boost_if_taken_damage ; 2027e (8:427e) - push de - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - farcall CheckIfSelectedAttackIsUnusable - jr c, .second_attack - ld a, ATTACK_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F - call CheckLoadedAttackFlag - jr c, .set_carry -.second_attack - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - farcall CheckIfSelectedAttackIsUnusable - jr c, .false - ld a, ATTACK_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F - call CheckLoadedAttackFlag - jr c, .set_carry -.false - pop de - or a - ret -.set_carry - pop de - scf - ret - -; makes AI use Super Potion card. -AIPlay_SuperPotion: ; 202a8 (8:42a8) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTempPlayAreaLocation_ffa1], a - call AIPickEnergyCardToDiscard - ldh [hTemp_ffa0], a - ld a, [wAITrainerCardParameter] - ld e, a - call GetCardDamageAndMaxHP - cp 40 - jr c, .play_card - ld a, 40 -.play_card - ldh [hTempRetreatCostCards], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; if AI doesn't decide to retreat this card and card has -; any energy cards attached, check if defending Pokémon can KO -; active card next turn after using Super Potion. -; if it cannot, return carry. -; also take into account whether attack is high recoil. -AIDecide_SuperPotion1: ; 202cc (8:42cc) - farcall AIDecideWhetherToRetreat - jr c, .no_carry - call AICheckIfAttackIsHighRecoil - jr c, .no_carry - xor a - ldh [hTempPlayAreaLocation_ff9d], a - ld e, a - call .check_attached_energy - ret nc - farcall CheckIfDefendingPokemonCanKnockOut - jr nc, .no_carry - - ld d, a - ld d, a - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - ld h, a - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - cp 40 + 1 ; if damage < 40 - jr c, .calculate_hp - ld a, 40 -.calculate_hp - ld l, a - ld a, h - add l - sub d - jr c, .no_carry - jr z, .no_carry - -; return carry - ld a, e - scf - ret -.no_carry - or a - ret - -; returns carry if card has energies attached. -.check_attached_energy ; 20305 (8:4305) - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - or a - ret z - scf - ret - -; finds a card in Play Area to use Super Potion on. -; output: -; a = card to use Super Potion on; -; carry set if Super Potion should be used. -AIDecide_SuperPotion2: ; 2030f (8:430f) - xor a - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfDefendingPokemonCanKnockOut - jr nc, .start_from_active -; can KO - ld d, a - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - ld h, a - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - cp 40 + 1 ; if damage < 40 - jr c, .calculate_hp - ld a, 40 -; return if using healing prevents KO. -.calculate_hp - ld l, a - ld a, h - add l - sub d - jr c, .count_prizes - jr z, .count_prizes - or a - ret - -; using Super Potion on active card does not prevent a KO. -; if player is at last prize, start loop with active card. -; otherwise start loop at first bench Pokémon. -.count_prizes - call SwapTurn - call CountPrizes - call SwapTurn - dec a - jr z, .start_from_active - ld e, PLAY_AREA_BENCH_1 - jr .loop - -; find Play Area Pokémon with more than 30 damage. -; skip Pokémon if it doesn't have any energy attached, -; has a BOOST_IF_TAKEN_DAMAGE attack, -; or if discarding makes any attack of its attacks unusable. -.start_from_active - ld e, PLAY_AREA_ARENA -.loop - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - ret z - ld d, a - call .check_attached_energy - jr nc, .next - call .check_boost_if_taken_damage - jr c, .next - call .check_energy_cost - jr c, .next - call GetCardDamageAndMaxHP - cp 40 ; if damage >= 40 - jr nc, .found -.next - inc e - jr .loop - -; a card was found, now to check if it's active or benched. -.found - ld a, e - or a - jr z, .active_card - -; bench card - push de - call SwapTurn - call CountPrizes - call SwapTurn - dec a - or a - jr z, .check_random - ld a, 10 - call Random - cp 3 -; 7/10 chance of returning carry. -.check_random - pop de - jr c, .no_carry - ld a, e - scf - ret - -; return carry for active card if not Hgh Recoil. -.active_card - push de - call AICheckIfAttackIsHighRecoil - pop de - jr c, .no_carry - ld a, e - scf - ret -.no_carry - or a - ret - -; returns carry if card has energies attached. -.check_attached_energy ; 20394 (8:4394) - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - or a - ret z - scf - ret - -; return carry if either of the attacks are usable -; and have the BOOST_IF_TAKEN_DAMAGE effect. -.check_boost_if_taken_damage ; 2039e (8:439e) - push de - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - farcall CheckIfSelectedAttackIsUnusable - jr c, .second_attack_1 - ld a, ATTACK_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F - call CheckLoadedAttackFlag - jr c, .true_1 -.second_attack_1 - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - farcall CheckIfSelectedAttackIsUnusable - jr c, .false_1 - ld a, ATTACK_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F - call CheckLoadedAttackFlag - jr c, .true_1 -.false_1 - pop de - or a - ret -.true_1 - pop de - scf - ret - -; returns carry if discarding energy card renders any attack unusable, -; given that they have enough energy to be used before discarding. -.check_energy_cost ; 203c8 (8:43c8) - push de - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr c, .second_attack_2 - farcall CheckEnergyNeededForAttackAfterDiscard - jr c, .true_2 - -.second_attack_2 - pop de - push de - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr c, .false_2 - farcall CheckEnergyNeededForAttackAfterDiscard - jr c, .true_2 - -.false_2 - pop de - or a - ret -.true_2 - pop de - scf - ret - -AIPlay_Defender: ; 203f8 (8:43f8) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - xor a - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; returns carry if using Defender can prevent a KO -; by the defending Pokémon. -; this takes into account both attacks and whether they're useable. -AIDecide_Defender1: ; 20406 (8:4406) - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .cannot_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry - -.cannot_ko -; check if any of the defending Pokémon's attacks deal -; damage exactly equal to current HP, and if so, -; only continue if that attack is useable. - farcall CheckIfAnyDefendingPokemonAttackDealsSameDamageAsHP - jr nc, .no_carry - call SwapTurn - farcall CheckIfSelectedAttackIsUnusable - call SwapTurn - jr c, .no_carry - - ld a, [wSelectedAttack] - farcall EstimateDamage_FromDefendingPokemon - ld a, [wDamage] - ld [wce06], a - ld d, a - -; load in a the attack that was not selected, -; and check if it is useable. - ld a, [wSelectedAttack] - ld b, a - ld a, $01 - sub b - ld [wSelectedAttack], a - push de - call SwapTurn - farcall CheckIfSelectedAttackIsUnusable - call SwapTurn - pop de - jr c, .switch_back - -; the other attack is useable. -; compare its damage to the selected attack. - ld a, [wSelectedAttack] - push de - farcall EstimateDamage_FromDefendingPokemon - pop de - ld a, [wDamage] - cp d - jr nc, .subtract - -; in case the non-selected attack is useable -; and deals less damage than the selected attack, -; switch back to the other attack. -.switch_back - ld a, [wSelectedAttack] - ld b, a - ld a, $01 - sub b - ld [wSelectedAttack], a - ld a, [wce06] - ld [wDamage], a - -; now the selected attack is the one that deals -; the most damage of the two (and is useable). -; if subtracting damage by using Defender -; still prevents a KO, return carry. -.subtract - ld a, [wDamage] - sub 20 - ld d, a - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - sub d - jr c, .no_carry - jr z, .no_carry - scf - ret -.no_carry - or a - ret - -; return carry if using Defender prevents Pokémon -; from being knocked out by an attack with recoil. -AIDecide_Defender2: ; 20486 (8:4486) - ld a, ATTACK_FLAG1_ADDRESS | HIGH_RECOIL_F - call CheckLoadedAttackFlag - jr c, .recoil - ld a, ATTACK_FLAG1_ADDRESS | LOW_RECOIL_F - call CheckLoadedAttackFlag - jr c, .recoil - or a - ret - -.recoil - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call LoadCardDataToBuffer2_FromDeckIndex - ld a, [wSelectedAttack] - or a - jr nz, .second_attack -; first attack - ld a, [wLoadedCard2Atk1EffectParam] - jr .check_weak -.second_attack - ld a, [wLoadedCard2Atk2EffectParam] - -; double recoil damage if card is weak to its own color. -.check_weak - ld d, a - push de - call GetArenaCardColor - call TranslateColorToWR - ld b, a - call GetArenaCardWeakness - and b - pop de - jr z, .check_resist - sla d - -; subtract 30 from recoil damage if card resists its own color. -; if this yields a negative number, return no carry. -.check_resist - push de - call GetArenaCardColor - call TranslateColorToWR - ld b, a - call GetArenaCardResistance - and b - pop de - jr z, .subtract - ld a, d - sub 30 - jr c, .no_carry - ld d, a - -; subtract damage prevented by Defender. -; if damage still knocks out card, return no carry. -; if damage does not knock out, return carry. -.subtract - ld a, d - or a - jr z, .no_carry - sub 20 - ld d, a - ld a, DUELVARS_ARENA_CARD_HP - call GetTurnDuelistVariable - sub d - jr c, .no_carry - jr z, .no_carry - scf - ret -.no_carry - or a - ret - -AIPlay_Pluspower: ; 204e8 (8:44e8) - ld a, [wCurrentAIFlags] - or AI_FLAG_USED_PLUSPOWER - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardParameter] - ld [wAIPluspowerAttack], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; returns carry if using a Pluspower can KO defending Pokémon -; if active card cannot KO without the boost. -; outputs in a the attack to use. -AIDecide_Pluspower1: ; 20501 (8:4501) -; this is mistakenly duplicated - xor a - ldh [hTempPlayAreaLocation_ff9d], a - xor a - ldh [hTempPlayAreaLocation_ff9d], a - -; continue if no attack can knock out. -; if there's an attack that can, only continue -; if it's unusable and there's no card in hand -; to fulfill its energy cost. - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .cannot_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry - -; cannot use an attack that knocks out. -.cannot_ko -; get active Pokémon's info. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - ld [wTempTurnDuelistCardID], a - -; get defending Pokémon's info and check -; its No Damage or Effect substatus. -; if substatus is active, return. - call SwapTurn - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - ld [wTempNonTurnDuelistCardID], a - bank1call HandleNoDamageOrEffectSubstatus - call SwapTurn - jr c, .no_carry - -; check both attacks and decide which one -; can KO with Pluspower boost. -; if neither can KO, return no carry. - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - call .check_ko_with_pluspower - jr c, .kos_with_pluspower_1 - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - call .check_ko_with_pluspower - jr c, .kos_with_pluspower_2 - -.no_carry - or a - ret - -; first attack can KO with Pluspower. -.kos_with_pluspower_1 - call .check_mr_mime - jr nc, .no_carry - xor a ; FIRST_ATTACK_OR_PKMN_POWER - scf - ret -; second attack can KO with Pluspower. -.kos_with_pluspower_2 - call .check_mr_mime - jr nc, .no_carry - ld a, SECOND_ATTACK - scf - ret - -; return carry if attack is useable and KOs -; defending Pokémon with Pluspower boost. -.check_ko_with_pluspower ; 20562 (8:4562) - farcall CheckIfSelectedAttackIsUnusable - jr c, .unusable - ld a, [wSelectedAttack] - farcall EstimateDamage_VersusDefendingCard - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - ld b, a - ld hl, wDamage - sub [hl] - jr c, .no_carry - jr z, .no_carry - ld a, [hl] - add 10 ; add Pluspower boost - ld c, a - ld a, b - sub c - ret c ; return carry if damage > HP left - ret nz ; does not KO - scf - ret ; KOs with Pluspower boost -.unusable - or a - ret - -; returns carry if Pluspower boost does -; not exceed 30 damage when facing Mr. Mime. -.check_mr_mime ; 20589 (8:4589) - ld a, [wDamage] - add 10 ; add Pluspower boost - cp 30 ; no danger in preventing damage - ret c - call SwapTurn - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - call SwapTurn - ld a, e - cp MR_MIME - ret z -; damage is >= 30 but not Mr. Mime - scf - ret - -; returns carry 7/10 of the time -; if selected attack is useable, can't KO without Pluspower boost -; can damage Mr. Mime even with Pluspower boost -; and has a minimum damage > 0. -; outputs in a the attack to use. -AIDecide_Pluspower2: ; 205a5 (8:45a5) - xor a - ldh [hTempPlayAreaLocation_ff9d], a - call .check_can_ko - jr nc, .no_carry - call .check_random - jr nc, .no_carry - call .check_mr_mime - jr nc, .no_carry - scf - ret -.no_carry - or a - ret - -; returns carry if Pluspower boost does -; not exceed 30 damage when facing Mr. Mime. -.check_mr_mime ; 205bb (8:45bb) - ld a, [wDamage] - add 10 ; add Pluspower boost - cp 30 ; no danger in preventing damage - ret c - call SwapTurn - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - call SwapTurn - ld a, e - cp MR_MIME - ret z -; damage is >= 30 but not Mr. Mime - scf - ret - -; return carry if attack is useable but cannot KO. -.check_can_ko ; 205d7 (8:45d7) - farcall CheckIfSelectedAttackIsUnusable - jr c, .unusable - ld a, [wSelectedAttack] - farcall EstimateDamage_VersusDefendingCard - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - ld b, a - ld hl, wDamage - sub [hl] - jr c, .no_carry - jr z, .no_carry -; can't KO. - scf - ret -.unusable - or a - ret - -; return carry 7/10 of the time if -; attack is useable and minimum damage > 0. -.check_random ; 205f6 (8:45f6) - farcall CheckIfSelectedAttackIsUnusable - jr c, .unusable - ld a, [wSelectedAttack] - farcall EstimateDamage_VersusDefendingCard - ld a, [wAIMinDamage] - cp 10 - jr c, .unusable - ld a, 10 - call Random - cp 3 - ret - -AIPlay_Switch: ; 20612 (8:4612) - ld a, [wCurrentAIFlags] - or AI_FLAG_USED_SWITCH - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - xor a - ld [wcdb4], a - ret - -; returns carry if the active card has less energy cards -; than the retreat cost and if AI can't play an energy -; card from the hand to fulfill the cost -AIDecide_Switch: ; 2062e (8:462e) -; check if AI can already play an energy card from hand to retreat - ld a, [wAIPlayEnergyCardForRetreat] - or a - jr z, .check_cost_amount - -; can't play energy card from hand to retreat -; compare number of energy cards attached to retreat cost - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call GetPlayAreaCardRetreatCost - push af - ld e, PLAY_AREA_ARENA - farcall CountNumberOfEnergyCardsAttached - ld b, a - pop af - sub b - ; jump if cards attached > retreat cost - jr c, .check_cost_amount - cp 2 - ; jump if retreat cost is 2 more energy cards - ; than the number of cards attached - jr nc, .switch - -.check_cost_amount - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call GetPlayAreaCardRetreatCost - cp 3 - ; jump if retreat cost >= 3 - jr nc, .switch - - push af - ld e, PLAY_AREA_ARENA - farcall CountNumberOfEnergyCardsAttached - pop bc - cp b - ; jump if energy cards attached < retreat cost - jr c, .switch - ret - -.switch - farcall AIDecideBenchPokemonToSwitchTo - ccf - ret - -AIPlay_GustOfWind: ; 20666 (8:4666) - ld a, [wCurrentAIFlags] - or AI_FLAG_USED_GUST_OF_WIND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_GustOfWind: ; 2067e (8:467e) - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetNonTurnDuelistVariable - dec a - or a - ret z ; no bench cards - -; if used Gust Of Wind already, -; do not use it again. - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_GUST_OF_WIND - ret nz - - farcall CheckIfActivePokemonCanUseAnyNonResidualAttack - ret nc ; no non-residual attack can be used - - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .check_id ; if can't KO - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry ; if KO attack is useable - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry ; if energy card is in hand - -.check_id - ; skip if current active card is MEW3 or MEWTWO1 - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - cp MEW3 - jr z, .no_carry - cp MEWTWO1 - jr z, .no_carry - - call .FindBenchCardToKnockOut - ret c - - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call .CheckIfNoAttackDealsDamage - jr c, .check_bench_energy - - ; skip if current arena card's color is - ; the defending card's weakness - call GetArenaCardColor - call TranslateColorToWR - ld b, a - call SwapTurn - call GetArenaCardWeakness - call SwapTurn - and b - jr nz, .no_carry - -; check weakness - call .FindBenchCardWithWeakness - ret nc ; no bench card weak to arena card - scf - ret ; found bench card weak to arena card - -.no_carry - or a - ret - -; being here means AI's arena card cannot damage player's arena card - -; first check if there is a card in player's bench that -; has no attached energy cards and that the AI can damage -.check_bench_energy - ; return carry if there's a bench card with weakness - call .FindBenchCardWithWeakness - ret c - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetNonTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA -; loop through bench and check attached energy cards -.loop_1 - inc e - dec d - jr z, .check_bench_hp - call SwapTurn - call GetPlayAreaCardAttachedEnergies - call SwapTurn - ld a, [wTotalAttachedEnergies] - or a - jr nz, .loop_1 ; skip if has energy attached - call .CheckIfCanDamageBenchedCard - jr nc, .loop_1 - ld a, e - scf - ret - -.check_bench_hp - ld a, $ff - ld [wce06], a - xor a - ld [wce08], a - ld e, a - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetNonTurnDuelistVariable - ld d, a - -; find bench card with least amount of available HP -.loop_2 - inc e - dec d - jr z, .check_found - ld a, e - add DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - ld b, a - ld a, [wce06] - inc b - cp b - jr c, .loop_2 - call .CheckIfCanDamageBenchedCard - jr nc, .loop_2 - dec b - ld a, b - ld [wce06], a - ld a, e - ld [wce08], a - jr .loop_2 - -.check_found - ld a, [wce08] - or a - jr z, .no_carry -; a card was found - -.set_carry - scf - ret - -.check_can_damage - push bc - push hl - xor a ; PLAY_AREA_ARENA - farcall CheckIfCanDamageDefendingPokemon - pop hl - pop bc - jr nc, .loop_3 - ld a, c - scf - ret - -; returns carry if any of the player's -; benched cards is weak to color in b -; and has a way to damage it -.FindBenchCardWithWeakness ; 2074d (8:474d) - ld a, DUELVARS_BENCH - call GetNonTurnDuelistVariable - ld c, PLAY_AREA_ARENA -.loop_3 - inc c - ld a, [hli] - cp $ff - jr z, .no_carry - call SwapTurn - call LoadCardDataToBuffer1_FromDeckIndex - call SwapTurn - ld a, [wLoadedCard1Weakness] - and b - jr nz, .check_can_damage - jr .loop_3 - -; returns carry if neither attack can deal damage -.CheckIfNoAttackDealsDamage ; 2076b (8:476b) - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - call .CheckIfAttackDealsNoDamage - jr c, .second_attack - ret -.second_attack - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - call .CheckIfAttackDealsNoDamage - jr c, .true - ret -.true - scf - ret - -; returns carry if attack is Pokemon Power -; or otherwise doesn't deal any damage -.CheckIfAttackDealsNoDamage ; 20782 (8:4782) - ld a, [wSelectedAttack] - ld e, a - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - ld d, a - call CopyAttackDataAndDamage_FromDeckIndex - ld a, [wLoadedAttackCategory] - - ; skip if attack is a Power or has 0 damage - cp POKEMON_POWER - jr z, .no_damage - ld a, [wDamage] - or a - ret z - - ; check damage against defending card - ld a, [wSelectedAttack] - farcall EstimateDamage_VersusDefendingCard - ld a, [wAIMaxDamage] - or a - ret nz - -.no_damage - scf - ret - -; returns carry if there is a player's bench card that -; the opponent's current active card can KO -.FindBenchCardToKnockOut ; 207a9 (8:47a9) - ld a, DUELVARS_BENCH - call GetNonTurnDuelistVariable - ld e, PLAY_AREA_BENCH_1 - -.loop_4 - ld a, [hli] - cp $ff - ret z - -; overwrite the player's active card and its HP -; with the current bench card that is being checked - push hl - push de - ld b, a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - push af - ld [hl], b - ld a, e - add DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - ld b, a - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - push af - ld [hl], b - - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call .CheckIfAnyAttackKnocksOut - jr nc, .next - farcall CheckIfSelectedAttackIsUnusable - jr nc, .found - farcall LookForEnergyNeededForAttackInHand - jr c, .found - -; the following two local routines can be condensed into one -; since they both revert the player's arena card -.next - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - pop af - ld [hl], a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - pop af - ld [hl], a - pop de - inc e - pop hl - jr .loop_4 - -; revert player's arena card and set carry -.found - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - pop af - ld [hl], a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - pop af - ld [hl], a - pop de - ld a, e - pop hl - scf - ret - -; returns carry if any of arena card's attacks -; KOs player card in location stored in e -.CheckIfAnyAttackKnocksOut ; 20806 (8:4806) - xor a ; FIRST_ATTACK_OR_PKMN_POWER - call .CheckIfAttackKnocksOut - ret c - ld a, SECOND_ATTACK - -; returns carry if attack KOs player card -; in location stored in e -.CheckIfAttackKnocksOut - push de - farcall EstimateDamage_VersusDefendingCard - pop de - ld a, DUELVARS_ARENA_CARD_HP - add e - call GetNonTurnDuelistVariable - ld hl, wDamage - sub [hl] - ret c - ret nz - scf - ret - -; returns carry if opponent's arena card can damage -; this benched card if it were switched with -; the player's arena card -.CheckIfCanDamageBenchedCard ; 20821 (8:4821) - push bc - push de - push hl - - ; overwrite arena card data - ld a, e - add DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - ld b, a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - push af - ld [hl], b - - ; overwrite arena card HP - ld a, e - add DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - ld b, a - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - push af - ld [hl], b - - xor a ; PLAY_AREA_ARENA - farcall CheckIfCanDamageDefendingPokemon - jr c, .can_damage - -; the following two local routines can be condensed into one -; since they both revert the player's arena card - -; can't damage - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - pop af - ld [hl], a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - pop af - ld [hl], a - pop hl - pop de - pop bc - or a - ret - -.can_damage - ld a, DUELVARS_ARENA_CARD_HP - call GetNonTurnDuelistVariable - pop af - ld [hl], a - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - pop af - ld [hl], a - pop hl - pop de - pop bc - scf - ret - -AIPlay_Bill: ; 2086d (8:486d) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; return carry if cards in deck > 9 -AIDecide_Bill: ; 20878 (8:4878) - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 9 - ret - -AIPlay_EnergyRemoval: ; 20880 (8:4880) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; picks an energy card in the player's Play Area to remove -AIDecide_EnergyRemoval: ; 20895 (8:4895) -; check if the current active card can KO player's card -; if it's possible to KO, then do not consider the player's -; active card to remove its attached energy - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .cannot_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .can_ko - farcall LookForEnergyNeededForAttackInHand - jr nc, .cannot_ko - -.can_ko - ; start checking from the bench - ld a, PLAY_AREA_BENCH_1 - ld [wce0f], a - jr .check_bench_energy -.cannot_ko - ; start checking from the arena card - xor a ; PLAY_AREA_ARENA - ld [wce0f], a - -; loop each card and check if it has enough energy to use any attack -; if it does, then proceed to pick an energy card to remove -.check_bench_energy - call SwapTurn - ld a, [wce0f] - ld e, a -.loop_1 - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - jr z, .default - - ld d, a - call .CheckIfCardHasEnergyAttached - jr nc, .next_1 - call .CheckIfNotEnoughEnergyToAttack - jr nc, .pick_energy ; jump if enough energy to attack -.next_1 - inc e - jr .loop_1 - -.pick_energy -; a play area card was picked to remove energy -; store the picked energy card to remove in wce1a -; and set carry - ld a, e - push af - call PickAttachedEnergyCardToRemove - ld [wce1a], a - pop af - call SwapTurn - scf - ret - -; if no card in player's Play Area was found with enough energy -; to attack, just pick an energy card from player's active card -; (in case the AI cannot KO it this turn) -.default - ld a, [wce0f] - or a - jr nz, .check_bench_damage ; not active card - call .CheckIfCardHasEnergyAttached - jr c, .pick_energy - -; lastly, check what attack on player's Play Area is highest damaging -; and pick an energy card attached to that Pokemon to remove -.check_bench_damage - xor a - ld [wce06], a - ld [wce08], a - - ld e, PLAY_AREA_BENCH_1 -.loop_2 - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - jr z, .found_damage - - ld d, a - call .CheckIfCardHasEnergyAttached - jr nc, .next_2 - call .FindHighestDamagingAttack -.next_2 - inc e - jr .loop_2 - -.found_damage - ld a, [wce08] - or a - jr z, .no_carry ; skip if none found - ld e, a - jr .pick_energy -.no_carry - call SwapTurn - or a - ret - -; returns carry if this card has any energy cards attached -.CheckIfCardHasEnergyAttached ; 2091a (8:491a) - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - or a - ret z - scf - ret - -; returns carry if this card does not -; have enough energy for either of its attacks -.CheckIfNotEnoughEnergyToAttack ; 20924 (8:4924) - push de - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr nc, .enough_energy - pop de - - push de - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr nc, .check_surplus - pop de - -; neither attack has enough energy - scf - ret - -.enough_energy - pop de - or a - ret - -; first attack doesn't have enough energy (or is just a Pokemon Power) -; but second attack has enough energy to be used -; check if there's surplus energy for attack and, if so, return carry -.check_surplus - farcall CheckIfNoSurplusEnergyForAttack - pop de - ccf - ret - -; stores in wce06 the highest damaging attack -; for the card in play area location in e -; and stores this card's location in wce08 -.FindHighestDamagingAttack ; 2094f (8:494f) - push de - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - - xor a ; FIRST_ATTACK_OR_PKMN_POWER - farcall EstimateDamage_VersusDefendingCard - ld a, [wDamage] - or a - jr z, .skip_1 - ld e, a - ld a, [wce06] - cp e - jr nc, .skip_1 - ld a, e - ld [wce06], a ; store this damage value - pop de - ld a, e - ld [wce08], a ; store this location - jr .second_attack - -.skip_1 - pop de - -.second_attack - push de - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - - ld a, SECOND_ATTACK - farcall EstimateDamage_VersusDefendingCard - ld a, [wDamage] - or a - jr z, .skip_2 - ld e, a - ld a, [wce06] - cp e - jr nc, .skip_2 - ld a, e - ld [wce06], a ; store this damage value - pop de - ld a, e - ld [wce08], a ; store this location - ret -.skip_2 - pop de - ret - -AIPlay_SuperEnergyRemoval: ; 20994 (8:4994) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce1b] - ldh [hTempRetreatCostCards], a - ld a, [wce1c] - ldh [hTempRetreatCostCards + 1], a - ld a, [wce1d] - ldh [hTempRetreatCostCards + 2], a - ld a, $ff - ldh [hTempRetreatCostCards + 3], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; picks two energy cards in the player's Play Area to remove -AIDecide_SuperEnergyRemoval: ; 209bc (8:49bc) - ld e, PLAY_AREA_BENCH_1 -.loop_1 -; first find an Arena card with a color energy card -; to discard for card effect -; return immediately if no Arena cards - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - jr z, .exit - - ld d, a - push de - call .LookForNonDoubleColorless - pop de - jr c, .not_double_colorless - inc e - jr .loop_1 - -; returns carry if an energy card other than double colorless -; is found attached to the card in play area location e -.LookForNonDoubleColorless - ld a, e - call CreateArenaOrBenchEnergyCardList - ld hl, wDuelTempList -.loop_2 - ld a, [hli] - cp $ff - ret z - call LoadCardDataToBuffer1_FromDeckIndex - cp DOUBLE_COLORLESS_ENERGY - ; any basic energy card - ; will set carry flag here - jr nc, .loop_2 - ret - -.exit - or a - ret - -; card in Play Area location e was found with -; a basic energy card -.not_double_colorless - ld a, e - ld [wce0f], a - -; check if the current active card can KO player's card -; if it's possible to KO, then do not consider the player's -; active card to remove its attached energy - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .cannot_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .can_ko - farcall LookForEnergyNeededForAttackInHand - jr nc, .cannot_ko - -.can_ko - ; start checking from the bench - call SwapTurn - ld e, PLAY_AREA_BENCH_1 - jr .loop_3 -.cannot_ko - ; start checking from the arena card - call SwapTurn - ld e, PLAY_AREA_ARENA - -; loop each card and check if it has enough energy to use any attack -; if it does, then proceed to pick energy cards to remove -.loop_3 - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - jr z, .no_carry - - ld d, a - call .CheckIfFewerThanTwoEnergyCards - jr c, .next_1 - call .CheckIfNotEnoughEnergyToAttack - jr nc, .found_card ; jump if enough energy to attack -.next_1 - inc e - jr .loop_3 - -.found_card -; a play area card was picked to remove energy -; if this is not the Arena Card, then check -; entire bench to pick the highest damage - ld a, e - or a - jr nz, .check_bench_damage - -; store the picked energy card to remove in wce1a -; and set carry -.pick_energy - ld [wce1b], a - call PickTwoAttachedEnergyCards - ld [wce1c], a - ld a, b - ld [wce1d], a - call SwapTurn - ld a, [wce0f] - push af - call AIPickEnergyCardToDiscard - ld [wce1a], a - pop af - scf - ret - -; check what attack on player's Play Area is highest damaging -; and pick an energy card attached to that Pokemon to remove -.check_bench_damage - xor a - ld [wce06], a - ld [wce08], a - - ld e, PLAY_AREA_BENCH_1 -.loop_4 - ld a, DUELVARS_ARENA_CARD - add e - call GetTurnDuelistVariable - cp $ff - jr z, .found_damage - - ld d, a - call .CheckIfFewerThanTwoEnergyCards - jr c, .next_2 - call .CheckIfNotEnoughEnergyToAttack - jr c, .next_2 - call .FindHighestDamagingAttack -.next_2 - inc e - jr .loop_4 - -.found_damage - ld a, [wce08] - or a - jr z, .no_carry - jr .pick_energy -.no_carry - call SwapTurn - or a - ret - -; returns carry if the number of energy cards attached -; is fewer than 2, or if all energy combined yields -; fewer than 2 energy -.CheckIfFewerThanTwoEnergyCards ; 20a77 (8:4a77) - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - cp 2 - ret c ; return if fewer than 2 attached cards - -; count all energy attached -; i.e. colored energy card = 1 -; and double colorless energy card = 2 - xor a - ld b, NUM_COLORED_TYPES - ld hl, wAttachedEnergies -.loop_5 - add [hl] - inc hl - dec b - jr nz, .loop_5 - ld b, [hl] - srl b - add b - cp 2 - ret - -; returns carry if this card does not -; have enough energy for either of its attacks -.CheckIfNotEnoughEnergyToAttack ; 20a92 (8:4a92) - push de - xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr nc, .enough_energy - pop de - - push de - ld a, SECOND_ATTACK - ld [wSelectedAttack], a - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - farcall CheckEnergyNeededForAttack - jr nc, .check_surplus - pop de - -; neither attack has enough energy - scf - ret - -.enough_energy - pop de - or a - ret - -; first attack doesn't have enough energy (or is just a Pokemon Power) -; but second attack has enough energy to be used -; check if there's surplus energy for attack and, if so, -; return carry if this surplus energy is at least 2 -.check_surplus - farcall CheckIfNoSurplusEnergyForAttack - cp 2 - jr c, .enough_energy - pop de - scf - ret - -; stores in wce06 the highest damaging attack -; for the card in play area location in e -; and stores this card's location in wce08 -.FindHighestDamagingAttack ; 20ac1 (8:4ac1) - push de - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - - xor a ; FIRST_ATTACK_OR_PKMN_POWER - farcall EstimateDamage_VersusDefendingCard - ld a, [wDamage] - or a - jr z, .skip_1 - ld e, a - ld a, [wce06] - cp e - jr nc, .skip_1 - ld a, e - ld [wce06], a ; store this damage value - pop de - ld a, e - ld [wce08], a ; store this location - jr .second_attack - -.skip_1 - pop de - -.second_attack - push de - ld a, e - ldh [hTempPlayAreaLocation_ff9d], a - - ld a, SECOND_ATTACK - farcall EstimateDamage_VersusDefendingCard - ld a, [wDamage] - or a - jr z, .skip_2 - ld e, a - ld a, [wce06] - cp e - jr nc, .skip_2 - ld a, e - ld [wce06], a ; store this damage value - pop de - ld a, e - ld [wce08], a ; store this location - ret -.skip_2 - pop de - ret - -AIPlay_PokemonBreeder: ; 20b06 (8:4b06) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce1a] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_PokemonBreeder: ; 20b1b (8:4b1b) - call IsPrehistoricPowerActive - jp c, .done - - ld a, 7 - ld hl, wce08 - call ClearMemory_Bank8 - - xor a - ld [wce06], a - call CreateHandCardList - ld hl, wDuelTempList - -.loop_hand_1 - ld a, [hli] - cp $ff - jr z, .not_found_in_hand - -; check if card in hand is any of the following -; stage 2 Pokemon cards - ld d, a - call LoadCardDataToBuffer1_FromDeckIndex - cp VENUSAUR1 - jr z, .found - cp VENUSAUR2 - jr z, .found - cp BLASTOISE - jr z, .found - cp VILEPLUME - jr z, .found - cp ALAKAZAM - jr z, .found - cp GENGAR - jr nz, .loop_hand_1 - -.found - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - push hl - call GetTurnDuelistVariable - pop hl - ld c, a - ld e, PLAY_AREA_ARENA - -; check Play Area for card that can evolve into -; the picked stage 2 Pokemon -.loop_play_area_1 - push hl - push bc - push de - call CheckIfCanEvolveInto_BasicToStage2 - pop de - call nc, .can_evolve - pop bc - pop hl - inc e - dec c - jr nz, .loop_play_area_1 - jr .loop_hand_1 - -.can_evolve - ld a, DUELVARS_ARENA_CARD_HP - add e - call GetTurnDuelistVariable - call ConvertHPToCounters - swap a - ld b, a - -; count number of energy cards attached and keep -; the lowest 4 bits (capped at $0f) - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - cp $10 - jr c, .not_maxed_out - ld a, %00001111 -.not_maxed_out - or b - -; 4 high bits of a = HP counters Pokemon still has -; 4 low bits of a = number of energy cards attached - -; store this score in wce08 + PLAY_AREA* - ld hl, wce08 - ld c, e - ld b, $00 - add hl, bc - ld [hl], a - -; store the deck index of stage 2 Pokemon in wce0f + PLAY_AREA* - ld hl, wce0f - add hl, bc - ld [hl], d - -; increase wce06 by one - ld hl, wce06 - inc [hl] - ret - -.not_found_in_hand - ld a, [wce06] - or a - jr z, .check_evolution_and_dragonite - -; an evolution has been found before - xor a - ld [wce06], a - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld c, a - ld e, $00 - ld d, $00 - -; find highest score in wce08 -.loop_score_1 - ld hl, wce08 - add hl, de - ld a, [wce06] - cp [hl] - jr nc, .not_higher - -; store this score to wce06 - ld a, [hl] - ld [wce06], a -; store this PLay Area location to wce07 - ld a, e - ld [wce07], a - -.not_higher - inc e - dec c - jr nz, .loop_score_1 - -; store the deck index of the stage 2 card -; that has been decided in wce1a, -; return the Play Area location of card -; to evolve in a and return carry - ld a, [wce07] - ld e, a - ld hl, wce0f - add hl, de - ld a, [hl] - ld [wce1a], a - ld a, [wce07] - scf - ret - -.check_evolution_and_dragonite - ld a, 7 - ld hl, wce08 - call ClearMemory_Bank8 - - xor a - ld [wce06], a - call CreateHandCardList - ld hl, wDuelTempList - push hl - -.loop_hand_2 - pop hl - ld a, [hli] - cp $ff - jr z, .check_evolution_found - - push hl - ld d, a - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld c, a - ld e, PLAY_AREA_ARENA - -.loop_play_area_2 -; check if evolution is possible - push bc - push de - call CheckIfCanEvolveInto_BasicToStage2 - pop de - call nc, .HandleDragonite1Evolution - call nc, .can_evolve - -; not possible to evolve or returned carry -; when handling Dragonite1 evolution - pop bc - inc e - dec c - jr nz, .loop_play_area_2 - jr .loop_hand_2 - -.check_evolution_found - ld a, [wce06] - or a - jr nz, .evolution_was_found -; no evolution was found before - or a - ret - -.evolution_was_found - xor a - ld [wce06], a - ld a, $ff - ld [wce07], a - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld c, a - ld e, $00 - ld d, $00 - -; find highest score in wce08 with at least -; 2 energy cards attached -.loop_score_2 - ld hl, wce08 - add hl, de - ld a, [wce06] - cp [hl] - jr nc, .next_score - -; take the lower 4 bits (total energy cards) -; and skip if less than 2 - ld a, [hl] - ld b, a - and %00001111 - cp 2 - jr c, .next_score - -; has at least 2 energy cards -; store the score in wce06 - ld a, b - ld [wce06], a -; store this PLay Area location to wce07 - ld a, e - ld [wce07], a - -.next_score - inc e - dec c - jr nz, .loop_score_2 - - ld a, [wce07] - cp $ff - jr z, .done - -; a card to evolve was found -; store the deck index of the stage 2 card -; that has been decided in wce1a, -; return the Play Area location of card -; to evolve in a and return carry - ld e, a - ld hl, wce0f - add hl, de - ld a, [hl] - ld [wce1a], a - ld a, [wce07] - scf - ret - -.done - or a - ret - -; return carry if card is evolving to Dragonite1 and if -; - the card that is evolving is not Arena card and -; number of damage counters in Play Area is under 8; -; - the card that is evolving is Arena card and has under 5 -; damage counters or has less than 3 energy cards attached. -.HandleDragonite1Evolution ; 20c5c (8:4c5c) - push af - push bc - push de - push hl - push de - -; check card ID - ld a, d - call GetCardIDFromDeckIndex - ld a, e - pop de - cp DRAGONITE1 - jr nz, .no_carry - -; check card Play Area location - ld a, e - or a - jr z, .active_card_dragonite - -; the card that is evolving is not active card - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld b, a - ld c, 0 - -; count damage counters in Play Area -.loop_play_area_damage - dec b - ld e, b - push bc - call GetCardDamageAndMaxHP - pop bc - call ConvertHPToCounters - add c - ld c, a - - ld a, b - or a - jr nz, .loop_play_area_damage - -; compare number of total damage counters -; with 7, if less or equal to that, set carry - ld a, 7 - cp c - jr c, .no_carry - jr .set_carry - -.active_card_dragonite -; the card that is evolving is active card -; compare number of this card's damage counters -; with 5, if less than that, set carry - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - cp 5 - jr c, .set_carry - -; compare number of this card's attached energy cards -; with 3, if less than that, set carry - ld e, PLAY_AREA_ARENA - farcall CountNumberOfEnergyCardsAttached - cp 3 - jr c, .set_carry - jr .no_carry - -.no_carry - pop hl - pop de - pop bc - pop af - ret - -.set_carry - pop hl - pop de - pop bc - pop af - scf - ret - -AIPlay_ProfessorOak: ; 20cae (8:4cae) - ld a, [wCurrentAIFlags] - or AI_FLAG_USED_PROFESSOR_OAK | AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; sets carry if AI determines a score of playing -; Professor Oak is over a certain threshold. -AIDecide_ProfessorOak: ; 20cc1 (8:4cc1) -; return if cards in deck <= 6 - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 6 - ret nc - - ld a, [wOpponentDeckID] - cp LEGENDARY_ARTICUNO_DECK_ID - jp z, .HandleLegendaryArticunoDeck - cp EXCAVATION_DECK_ID - jp z, .HandleExcavationDeck - cp WONDERS_OF_SCIENCE_DECK_ID - jp z, .HandleWondersOfScienceDeck - -; return if cards in deck <= 14 -.check_cards_deck - ld a, [hl] - cp DECK_SIZE - 14 - ret nc - -; initialize score - ld a, $1e - ld [wce06], a - -; check number of cards in hand -.check_cards_hand - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 4 - jr nc, .more_than_3_cards - -; less than 4 cards in hand - ld a, [wce06] - add $32 - ld [wce06], a - jr .check_energy_cards - -.more_than_3_cards - cp 9 - jr c, .check_energy_cards - -; more than 8 cards - ld a, [wce06] - sub $1e - ld [wce06], a - -.check_energy_cards - farcall CreateEnergyCardListFromHand - jr nc, .handle_blastoise - -; no energy cards in hand - ld a, [wce06] - add $28 - ld [wce06], a - -.handle_blastoise - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .check_hand - -; no Muk in Play Area - ld a, BLASTOISE - call CountPokemonIDInPlayArea - jr nc, .check_hand - -; at least one Blastoise in AI Play Area - ld a, WATER_ENERGY - farcall LookForCardIDInHand - jr nc, .check_hand - -; no Water energy in hand - ld a, [wce06] - add $0a - ld [wce06], a - -; this part seems buggy -; the AI loops through all the cards in hand and checks -; if any of them is not a Pokemon card and has Basic stage. -; it seems like the intention was that if there was -; any Basic Pokemon still in hand, the AI would add to the score. -.check_hand - call CreateHandCardList - ld hl, wDuelTempList -.loop_hand - ld a, [hli] - cp $ff - jr z, .check_evolution - - call LoadCardDataToBuffer1_FromDeckIndex - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr c, .loop_hand ; bug, should be jr nc - - ld a, [wLoadedCard1Stage] - or a - jr nz, .loop_hand - - ld a, [wce06] - add $0a - ld [wce06], a - -.check_evolution - xor a - ld [wce0f], a - ld [wce0f + 1], a - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -.loop_play_area - push de - call .LookForEvolution - pop de - jr nc, .not_in_hand - -; there's a card in hand that can evolve - ld a, $01 - ld [wce0f], a - -.not_in_hand -; check if a card that can evolve was found at all -; if not, go to the next card in the Play Area - ld a, [wce08] - cp $01 - jr nz, .next_play_area - -; if it was found, set wce0f + 1 to $01 - ld a, $01 - ld [wce0f + 1], a - -.next_play_area - inc e - dec d - jr nz, .loop_play_area - -; if a card was found that evolves... - ld a, [wce0f + 1] - or a - jr z, .check_score - -; ...but that card is not in the hand... - ld a, [wce0f] - or a - jr nz, .check_score - -; ...add to the score - ld a, [wce06] - add $0a - ld [wce06], a - -; only return carry if score > $3c -.check_score - ld a, [wce06] - ld b, $3c - cp b - jr nc, .set_carry - or a - ret - -.set_carry - scf - ret - -; return carry if there's a card in the hand that -; can evolve the card in Play Area location in e. -; sets wce08 to $01 if any card is found that can -; evolve regardless of card location. -.LookForEvolution ; 20d9d (8:4d9d) - xor a - ld [wce08], a - ld d, 0 - -; loop through the whole deck to check if there's -; a card that can evolve this Pokemon. -.loop_deck_evolution - push de - call CheckIfCanEvolveInto - pop de - jr nc, .can_evolve -.evolution_not_in_hand - inc d - ld a, DECK_SIZE - cp d - jr nz, .loop_deck_evolution - - or a - ret - -; a card was found that can evolve, set wce08 to $01 -; and if the card is in the hand, return carry. -; otherwise resume looping through deck. -.can_evolve - ld a, $01 - ld [wce08], a - ld a, DUELVARS_CARD_LOCATIONS - add d - call GetTurnDuelistVariable - cp CARD_LOCATION_HAND - jr nz, .evolution_not_in_hand - - scf - ret - -; handles Legendary Articuno Deck AI logic. -.HandleLegendaryArticunoDeck ; 20dc3 (8:4dc3) - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 3 - jr nc, .check_playable_cards - -; has less than 3 Pokemon in Play Area. - push af - call CreateHandCardList - pop af - ld d, a - ld e, PLAY_AREA_ARENA - -; if no cards in hand evolve cards in Play Area, -; returns carry. -.loop_play_area_articuno - ld a, DUELVARS_ARENA_CARD - add e - - push de - call GetTurnDuelistVariable - farcall CheckForEvolutionInList - pop de - jr c, .check_playable_cards - - inc e - ld a, d - cp e - jr nz, .loop_play_area_articuno - -.set_carry_articuno - scf - ret - -; if there are more than 3 energy cards in hand, -; return no carry, otherwise check for playable cards. -.check_playable_cards - call CountOppEnergyCardsInHand - cp 4 - jr nc, .no_carry_articuno - -; remove both Professor Oak cards from list -; before checking for playable cards - call CreateHandCardList - ld hl, wDuelTempList - ld e, PROFESSOR_OAK - farcall RemoveCardIDInList - ld e, PROFESSOR_OAK - farcall RemoveCardIDInList - -; look in hand for cards that can be played. -; if a card that cannot be played is found, return no carry. -; otherwise return carry. -.loop_hand_articuno - ld a, [hli] - cp $ff - jr z, .set_carry_articuno - push hl - farcall CheckIfCardCanBePlayed - pop hl - jr c, .loop_hand_articuno - -.no_carry_articuno - or a - ret - -; handles Excavation deck AI logic. -; sets score depending on whether there's no -; Mysterious Fossil in play and in hand. -.HandleExcavationDeck ; 20e11 (8:4e11) -; return no carry if cards in deck < 15 - ld a, [hl] - cp 46 - ret nc - -; look for Mysterious Fossil - ld a, MYSTERIOUS_FOSSIL - call LookForCardIDInHandAndPlayArea - jr c, .found_mysterious_fossil - ld a, $50 - ld [wce06], a - jp .check_cards_hand -.found_mysterious_fossil - ld a, $1e - ld [wce06], a - jp .check_cards_hand - -; handles Wonders of Science AI logic. -; if there's either Grimer or Muk in hand, -; do not play Professor Oak. -.HandleWondersOfScienceDeck ; 20e2c (8:4e2c) - ld a, GRIMER - call LookForCardIDInHandList_Bank8 - jr c, .found_grimer_or_muk - ld a, MUK - call LookForCardIDInHandList_Bank8 - jr c, .found_grimer_or_muk - - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - jp .check_cards_deck - -.found_grimer_or_muk - or a - ret - -AIPlay_EnergyRetrieval: ; 20e44 (8:4e44) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce1b] - ldh [hTempRetreatCostCards], a - cp $ff - jr z, .asm_20e68 - ld a, $ff - ldh [$ffa3], a -.asm_20e68 - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; checks whether AI can play Energy Retrieval and -; picks the energy cards from the discard pile, -; and duplicate cards in hand to discard. -AIDecide_EnergyRetrieval: ; 20e6e (8:4e6e) -; return no carry if no cards in hand - farcall CreateEnergyCardListFromHand - jp nc, .no_carry - -; handle Go Go Rain Dance deck -; return no carry if there's no Muk card in play and -; if there's no Blastoise card in Play Area -; if there's a Muk in play, continue as normal - ld a, [wOpponentDeckID] - cp GO_GO_RAIN_DANCE_DECK_ID - jr nz, .start - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .start - ld a, BLASTOISE - call CountPokemonIDInPlayArea - jp nc, .no_carry - -.start -; find duplicate cards in hand - call CreateHandCardList - ld hl, wDuelTempList - call FindDuplicateCards - jp c, .no_carry - - ld [wce06], a - ld a, CARD_LOCATION_DISCARD_PILE - call FindBasicEnergyCardsInLocation - jp c, .no_carry - -; some basic energy cards were found in Discard Pile - ld a, $ff - ld [wce1a], a - ld [wce1b], a - ld [wce1c], a - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -; first check if there are useful energy cards in the list -; and choose them for retrieval first -.loop_play_area - ld a, DUELVARS_ARENA_CARD - add e - push de - -; load this card's ID in wTempCardID -; and this card's Type in wTempCardType - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - ld [wTempCardID], a - call LoadCardDataToBuffer1_FromCardID - pop de - ld a, [wLoadedCard1Type] - or TYPE_ENERGY - ld [wTempCardType], a - -; loop the energy cards in the Discard Pile -; and check if they are useful for this Pokemon - ld hl, wDuelTempList -.loop_energy_cards_1 - ld a, [hli] - cp $ff - jr z, .next_play_area - - ld b, a - push hl - farcall CheckIfEnergyIsUseful - pop hl - jr nc, .loop_energy_cards_1 - - ld a, [wce1a] - cp $ff - jr nz, .second_energy_1 - -; check if there were already chosen cards, -; if this is the second chosen card, return carry - -; first energy card found - ld a, b - ld [wce1a], a - call RemoveCardFromList - jr .next_play_area -.second_energy_1 - ld a, b - ld [wce1b], a - jr .set_carry - -.next_play_area - inc e - dec d - jr nz, .loop_play_area - -; next, if there are still energy cards left to choose, -; loop through the energy cards again and select -; them in order. - ld hl, wDuelTempList -.loop_energy_cards_2 - ld a, [hli] - cp $ff - jr z, .check_chosen - ld b, a - ld a, [wce1a] - cp $ff - jr nz, .second_energy_2 - ld a, b - ld [wce1a], a - call RemoveCardFromList - jr .loop_energy_cards_2 - -.second_energy_2 - ld a, b - ld [wce1b], a - jr .set_carry - -; will set carry if at least one has been chosen -.check_chosen - ld a, [wce1a] - cp $ff - jr nz, .set_carry -.no_carry - or a - ret - -.set_carry - ld a, [wce06] - scf - ret - -; remove an element from the list -; and shortens it accordingly -; input: -; hl = pointer to element after the one to remove -RemoveCardFromList: ; 20f27 (8:4f27) - push de - ld d, h - ld e, l - dec hl - push hl -.loop_remove - ld a, [de] - ld [hli], a - cp $ff - jr z, .done_remove - inc de - jr .loop_remove -.done_remove - pop hl - pop de - ret - -; finds duplicates in card list in hl. -; if a duplicate of Pokemon cards are found, return in -; a the deck index of the second one. -; otherwise, if a duplicate of non-Pokemon cards are found -; return in a the deck index of the second one. -; if no duplicates found, return carry. -; input: -; hl = list to look in -; output: -; a = deck index of duplicate card -FindDuplicateCards: ; 20f38 (8:4f38) - ld a, $ff - ld [wce0f], a - ld [wce0f + 1], a - push hl - -.loop_outer -; get ID of current card - pop hl - ld a, [hli] - cp $ff - jr z, .check_found - call GetCardIDFromDeckIndex - ld b, e - push hl - -; loop the rest of the list to find -; another card with the same ID -.loop_inner - ld a, [hli] - cp $ff - jr z, .loop_outer - ld c, a - call GetCardIDFromDeckIndex - ld a, e - cp b - jr nz, .loop_inner - -; found two cards with same ID - push bc - call GetCardType - pop bc - cp TYPE_ENERGY - jr c, .not_energy - -; they are energy or trainer cards -; loads wce0f+1 with this card deck index - ld a, c - ld [wce0f + 1], a - jr .loop_outer - -.not_energy -; they are Pokemon cards -; loads wce0f with this card deck index - ld a, c - ld [wce0f], a - jr .loop_outer - -.check_found - ld a, [wce0f] - cp $ff - jr nz, .no_carry - ld a, [wce0f + 1] - cp $ff - jr nz, .no_carry - -; only set carry if duplicate cards were not found - scf - ret - -.no_carry -; two cards with the same ID were found -; of either Pokemon or Non-Pokemon cards - or a - ret - -AIPlay_SuperEnergyRetrieval: ; 20f80 (8:4f80) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce1b] - ldh [hTempRetreatCostCards], a - ld a, [wce1c] - ldh [$ffa3], a - cp $ff - jr z, .asm_20fbb - ld a, [wce1d] - ldh [$ffa4], a - cp $ff - jr z, .asm_20fbb - ld a, [wce1e] - ldh [$ffa5], a - cp $ff - jr z, .asm_20fbb - ld a, $ff - ldh [$ffa6], a -.asm_20fbb - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_SuperEnergyRetrieval: ; 20fc1 (8:4fc1) -; return no carry if no cards in hand - farcall CreateEnergyCardListFromHand - jp nc, .no_carry - -; handle Go Go Rain Dance deck -; return no carry if there's no Muk card in play and -; if there's no Blastoise card in Play Area -; if there's a Muk in play, continue as normal - ld a, [wOpponentDeckID] - cp GO_GO_RAIN_DANCE_DECK_ID - jr nz, .start - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .start - ld a, BLASTOISE - call CountPokemonIDInPlayArea - jp nc, .no_carry - -.start -; find duplicate cards in hand - call CreateHandCardList - ld hl, wDuelTempList - call FindDuplicateCards - jp c, .no_carry - -; remove the duplicate card in hand -; and run the hand check again - ld [wce06], a - ld hl, wDuelTempList - call FindAndRemoveCardFromList - call FindDuplicateCards - jp c, .no_carry - - ld [wce08], a - ld a, CARD_LOCATION_DISCARD_PILE - call FindBasicEnergyCardsInLocation - jp c, .no_carry - -; some basic energy cards were found in Discard Pile - ld a, $ff - ld [wce1b], a - ld [wce1c], a - ld [wce1d], a - ld [wce1e], a - ld [wce1f], a - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -; first check if there are useful energy cards in the list -; and choose them for retrieval first -.loop_play_area - ld a, DUELVARS_ARENA_CARD - add e - push de - -; load this card's ID in wTempCardID -; and this card's Type in wTempCardType - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - ld [wTempCardID], a - call LoadCardDataToBuffer1_FromCardID - pop de - ld a, [wLoadedCard1Type] - or TYPE_ENERGY - ld [wTempCardType], a - -; loop the energy cards in the Discard Pile -; and check if they are useful for this Pokemon - ld hl, wDuelTempList -.loop_energy_cards_1 - ld a, [hli] - cp $ff - jr z, .next_play_area - - ld b, a - push hl - farcall CheckIfEnergyIsUseful - pop hl - jr nc, .loop_energy_cards_1 - -; first energy - ld a, [wce1b] - cp $ff - jr nz, .second_energy_1 - ld a, b - ld [wce1b], a - call RemoveCardFromList - jr .next_play_area - -.second_energy_1 - ld a, [wce1c] - cp $ff - jr nz, .third_energy_1 - ld a, b - ld [wce1c], a - call RemoveCardFromList - jr .next_play_area - -.third_energy_1 - ld a, [wce1d] - cp $ff - jr nz, .fourth_energy_1 - ld a, b - ld [wce1d], a - call RemoveCardFromList - jr .next_play_area - -.fourth_energy_1 - ld a, b - ld [wce1e], a - jr .set_carry - -.next_play_area - inc e - dec d - jr nz, .loop_play_area - -; next, if there are still energy cards left to choose, -; loop through the energy cards again and select -; them in order. - ld hl, wDuelTempList -.loop_energy_cards_2 - ld a, [hli] - cp $ff - jr z, .check_chosen - ld b, a - ld a, [wce1b] - cp $ff - jr nz, .second_energy_2 - ld a, b - -; first energy - ld [wce1b], a - call RemoveCardFromList - jr .loop_energy_cards_2 - -.second_energy_2 - ld a, [wce1c] - cp $ff - jr nz, .third_energy_2 - ld a, b - ld [wce1c], a - call RemoveCardFromList - jr .loop_energy_cards_2 - -.third_energy_2 - ld a, [wce1d] - cp $ff - jr nz, .fourth_energy - ld a, b - ld [wce1d], a - call RemoveCardFromList - jr .loop_energy_cards_2 - -.fourth_energy - ld a, b - ld [wce1e], a - jr .set_carry - -; will set carry if at least one has been chosen -.check_chosen - ld a, [wce1b] - cp $ff - jr nz, .set_carry - -.no_carry - or a - ret -.set_carry - ld a, [wce08] - ld [wce1a], a - ld a, [wce06] - scf - ret - -; finds the card with deck index a in list hl, -; and removes it from the list. -; the card HAS to exist in the list, since this -; routine does not check for the terminating byte $ff! -; input: -; a = card deck index to look -; hl = pointer to list of cards -FindAndRemoveCardFromList: ; 210d5 (8:50d5) - push hl - ld b, a -.loop_duplicate - ld a, [hli] - cp b - jr nz, .loop_duplicate - call RemoveCardFromList - pop hl - ret - -AIPlay_PokemonCenter: ; 210e0 (8:50e0) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_PokemonCenter: ; 210eb (8:50eb) - xor a - ldh [hTempPlayAreaLocation_ff9d], a - -; return if active Pokemon can KO player's card. - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .start - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry - -.start - xor a - ld [wce06], a - ld [wce08], a - ld [wce0f], a - - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -.loop_play_area - ld a, DUELVARS_ARENA_CARD - add e - push de - call GetTurnDuelistVariable - call LoadCardDataToBuffer1_FromDeckIndex - ld a, e ; useless instruction - pop de - -; get this Pokemon's current HP in number of counters -; and add it to the total. - ld a, [wLoadedCard1HP] - call ConvertHPToCounters - ld b, a - ld a, [wce06] - add b - ld [wce06], a - -; get this Pokemon's current damage counters -; and add it to the total. - call GetCardDamageAndMaxHP - call ConvertHPToCounters - ld b, a - ld a, [wce08] - add b - ld [wce08], a - -; get this Pokemon's number of attached energy cards -; and add it to the total. -; if there's overflow, return no carry. - call GetPlayAreaCardAttachedEnergies - ld a, [wTotalAttachedEnergies] - ld b, a - ld a, [wce0f] - add b - jr c, .no_carry - ld [wce0f], a - - inc e - dec d - jr nz, .loop_play_area - -; if (number of damage counters / 2) < (total energy cards attached) -; return no carry. - ld a, [wce08] - srl a - ld hl, wce0f - cp [hl] - jr c, .no_carry - -; if (number of HP counters * 6 / 10) >= (number of damage counters) -; return no carry. - ld a, [wce06] - ld l, a - ld h, 6 - call HtimesL - call CalculateWordTensDigit - ld a, l - ld hl, wce08 - cp [hl] - jr nc, .no_carry - - scf - ret - -.no_carry - or a - ret - -AIPlay_ImposterProfessorOak: ; 21170 (8:5170) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; sets carry depending on player's number of cards -; in deck in in hand. -AIDecide_ImposterProfessorOak: ; 2117b (8:517b) - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetNonTurnDuelistVariable - cp DECK_SIZE - 14 - jr c, .more_than_14_cards - -; if player has less than 14 cards in deck, only -; set carry if number of cards in their hands < 6 - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetNonTurnDuelistVariable - cp 6 - jr c, .set_carry -.no_carry - or a - ret - -; if player has more than 14 cards in deck, only -; set carry if number of cards in their hands >= 9 -.more_than_14_cards - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetNonTurnDuelistVariable - cp 9 - jr c, .no_carry -.set_carry - scf - ret - -AIPlay_EnergySearch: ; 2119a (8:519a) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; AI checks for playing Energy Search -AIDecide_EnergySearch: ; 211aa (8:51aa) - farcall CreateEnergyCardListFromHand - jr c, .start - call .CheckForUsefulEnergyCards - jr c, .start - -; there are energy cards in hand and at least -; one of them is useful to a card in Play Area -.no_carry - or a - ret - -.start - ld a, [wOpponentDeckID] - cp HEATED_BATTLE_DECK_ID - jr z, .heated_battle - cp WONDERS_OF_SCIENCE_DECK_ID - jr z, .wonders_of_science - -; if no energy cards in deck, return no carry - ld a, CARD_LOCATION_DECK - call FindBasicEnergyCardsInLocation - jr c, .no_carry - -; if any of the energy cards in deck is useful -; return carry right away... - call .CheckForUsefulEnergyCards - jr c, .no_useful - scf - ret - -; ...otherwise save the list in a before return carry. -.no_useful - ld a, [wDuelTempList] - scf - ret - -; Heated Battle deck only searches for Fire and Lightning -; if they are found to be useful to some card in Play Area -.heated_battle - ld a, CARD_LOCATION_DECK - call FindBasicEnergyCardsInLocation - jr c, .no_carry - call .CheckUsefulFireOrLightningEnergy - jr c, .no_carry - scf - ret - -; this subroutine has a bug. -; it was supposed to use the .CheckUsefulGrassEnergy subroutine -; but uses .CheckUsefulFireOrLightningEnergy instead. -.wonders_of_science - ld a, CARD_LOCATION_DECK - call FindBasicEnergyCardsInLocation - jr c, .no_carry - call .CheckUsefulFireOrLightningEnergy - jr c, .no_carry - scf - ret - -; return carry if cards in wDuelTempList are not -; useful to any of the Play Area Pokemon -.CheckForUsefulEnergyCards ; 211f1 (8:51f1) - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -.loop_play_area_1 - ld a, DUELVARS_ARENA_CARD - add e - push de - call GetTurnDuelistVariable - -; store ID and type of card - call GetCardIDFromDeckIndex - ld a, e - ld [wTempCardID], a - call LoadCardDataToBuffer1_FromCardID - pop de - ld a, [wLoadedCard1Type] - or TYPE_ENERGY - ld [wTempCardType], a - -; look in list for a useful energy, -; is any is found return no carry. - ld hl, wDuelTempList -.loop_energy_1 - ld a, [hli] - cp $ff - jr z, .none_found - ld b, a - push hl - farcall CheckIfEnergyIsUseful - pop hl - jr nc, .loop_energy_1 - - ld a, b - or a - ret - -.none_found - inc e - ld a, e - cp d - jr nz, .loop_play_area_1 - - scf - ret - -; checks whether there are useful energies -; only for Fire and Lightning type Pokemon cards -; in Play Area. If none found, return carry. -.CheckUsefulFireOrLightningEnergy ; 2122e (8:522e) - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -.loop_play_area_2 - ld a, DUELVARS_ARENA_CARD - add e - push de - call GetTurnDuelistVariable - -; get card's ID and Type - call GetCardIDFromDeckIndex - ld a, e - ld [wTempCardID], a - call LoadCardDataToBuffer1_FromCardID - pop de - ld a, [wLoadedCard1Type] - or TYPE_ENERGY - -; only do check if the Pokemon's type -; is either Fire or Lightning - cp TYPE_ENERGY_FIRE - jr z, .fire_or_lightning - cp TYPE_ENERGY_LIGHTNING - jr nz, .next_play_area - -; loop each energy card in list -.fire_or_lightning - ld [wTempCardType], a - ld hl, wDuelTempList -.loop_energy_2 - ld a, [hli] - cp $ff - jr z, .next_play_area - -; if this energy card is useful, -; return no carry. - ld b, a - push hl - farcall CheckIfEnergyIsUseful - pop hl - jr nc, .loop_energy_2 - - ld a, b - or a - ret - -.next_play_area - inc e - ld a, e - cp d - jr nz, .loop_play_area_2 - -; no card was found to be useful -; for Fire/Lightning type Pokemon card. - scf - ret - -; checks whether there are useful energies -; only for Grass type Pokemon cards -; in Play Area. If none found, return carry. -.CheckUsefulGrassEnergy ; 21273 (8:5273) -; unreferenced - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - ld d, a - ld e, PLAY_AREA_ARENA - -.loop_play_area_3 - ld a, DUELVARS_ARENA_CARD - add e - push de - call GetTurnDuelistVariable - -; get card's ID and Type - call GetCardIDFromDeckIndex - ld a, e - ld [wTempCardID], a - call LoadCardDataToBuffer1_FromCardID - pop de - ld a, [wLoadedCard1Type] - or TYPE_ENERGY - -; only do check if the Pokemon's type is Grass - cp TYPE_ENERGY_GRASS - jr nz, .next_play_area_3 - -; loop each energy card in list - ld [wTempCardType], a - ld hl, wDuelTempList -.loop_energy_3 - ld a, [hli] - cp $ff - jr z, .next_play_area_3 - -; if this energy card is useful, -; return no carry. - ld b, a - push hl - farcall CheckIfEnergyIsUseful - pop hl - jr nc, .loop_energy_3 - - ld a, b - or a - ret - -.next_play_area_3 - inc e - ld a, e - cp d - jr nz, .loop_play_area_3 - -; no card was found to be useful -; for Grass type Pokemon card. - scf - ret - -AIPlay_Pokedex: ; 212b4 (8:52b4) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wce1a] - ldh [hTemp_ffa0], a - ld a, [wce1b] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce1c] - ldh [hTempRetreatCostCards], a - ld a, [wce1d] - ldh [$ffa3], a - ld a, [wce1e] - ldh [$ffa4], a - ld a, $ff - ldh [$ffa5], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_Pokedex: ; 212dc (8:52dc) - ld a, [wAIPokedexCounter] - cp 5 + 1 - jr c, .no_carry ; return if counter hasn't reached 6 yet - -; return no carry if number of cards in deck <= 4 - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 4 - jr nc, .no_carry - -; has a 3 in 10 chance of actually playing card - ld a, 10 - call Random - cp 3 - jr c, .pick_cards - -.no_carry - or a - ret - -.pick_cards -; the following comparison is disregarded -; the Wonders of Science deck was probably intended -; to use PickPokedexCards_Unreferenced instead - ld a, [wOpponentDeckID] - cp WONDERS_OF_SCIENCE_DECK_ID - jp PickPokedexCards ; bug, should be jp nz - -; picks order of the cards in deck from the effects of Pokedex. -; prioritizes Pokemon cards, then Trainer cards, then energy cards. -; stores the resulting order in wce1a. -PickPokedexCards_Unreferenced: ; 212ff (8:52ff) -; unreferenced - xor a - ld [wAIPokedexCounter], a ; reset counter - - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - add DUELVARS_DECK_CARDS - ld l, a - lb de, $00, $00 - ld b, 5 - -; run through 5 of the remaining cards in deck -.next_card - ld a, [hli] - ld c, a - call .GetCardType - -; load this card's deck index and type in memory -; wce08 = card types -; wce0f = card deck indices - push hl - ld hl, wce08 - add hl, de - ld [hl], a - ld hl, wce0f - add hl, de - ld [hl], c - pop hl - - inc e - dec b - jr nz, .next_card - -; terminate the wce08 list - ld a, $ff - ld [wce08 + 5], a - - ld de, wce1a - -; find Pokemon - ld hl, wce08 - ld c, -1 - ld b, $00 - -; run through the stored cards -; and look for any Pokemon cards. -.loop_pokemon - inc c - ld a, [hli] - cp $ff - jr z, .find_trainers - cp TYPE_ENERGY - jr nc, .loop_pokemon -; found a Pokemon card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_pokemon - -; run through the stored cards -; and look for any Trainer cards. -.find_trainers - ld hl, wce08 - ld c, -1 - ld b, $00 - -.loop_trainers - inc c - ld a, [hli] - cp $ff - jr z, .find_energy - cp TYPE_TRAINER - jr nz, .loop_trainers -; found a Trainer card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_trainers - -.find_energy - ld hl, wce08 - ld c, -1 - ld b, $00 - -; run through the stored cards -; and look for any energy cards. -.loop_energy - inc c - ld a, [hli] - cp $ff - jr z, .done - and TYPE_ENERGY - jr z, .loop_energy -; found an energy card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_energy - -.done - scf - ret - -.GetCardType ; 21383 (8:5383) - push bc - push de - call GetCardIDFromDeckIndex - call GetCardType - pop de - pop bc - ret - -; picks order of the cards in deck from the effects of Pokedex. -; prioritizes energy cards, then Pokemon cards, then Trainer cards. -; stores the resulting order in wce1a. -PickPokedexCards: ; 2138e (8:538e) - xor a - ld [wAIPokedexCounter], a ; reset counter ; reset counter - - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - add DUELVARS_DECK_CARDS - ld l, a - lb de, $00, $00 - ld b, 5 - -; run through 5 of the remaining cards in deck -.next_card - ld a, [hli] - ld c, a - call .GetCardType - -; load this card's deck index and type in memory -; wce08 = card types -; wce0f = card deck indices - push hl - ld hl, wce08 - add hl, de - ld [hl], a - ld hl, wce0f - add hl, de - ld [hl], c - pop hl - - inc e - dec b - jr nz, .next_card - -; terminate the wce08 list - ld a, $ff - ld [wce08 + 5], a - - ld de, wce1a - -; find energy - ld hl, wce08 - ld c, -1 - ld b, $00 - -; run through the stored cards -; and look for any energy cards. -.loop_energy - inc c - ld a, [hli] - cp $ff - jr z, .find_pokemon - and TYPE_ENERGY - jr z, .loop_energy -; found an energy card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_energy - -.find_pokemon - ld hl, wce08 - ld c, -1 - ld b, $00 - -; run through the stored cards -; and look for any Pokemon cards. -.loop_pokemon - inc c - ld a, [hli] - cp $ff - jr z, .find_trainers - cp TYPE_ENERGY - jr nc, .loop_pokemon -; found a Pokemon card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_pokemon - -; run through the stored cards -; and look for any Trainer cards. -.find_trainers - ld hl, wce08 - ld c, -1 - ld b, $00 - -.loop_trainers - inc c - ld a, [hli] - cp $ff - jr z, .done - cp TYPE_TRAINER - jr nz, .loop_trainers -; found a Trainer card -; store it in wce1a list - push hl - ld hl, wce0f - add hl, bc - ld a, [hl] - pop hl - ld [de], a - inc de - jr .loop_trainers - -.done - scf - ret - -.GetCardType ; 21412 (8:5412) - push bc - push de - call GetCardIDFromDeckIndex - call GetCardType - pop de - pop bc - ret - -AIPlay_FullHeal: ; 2141d (8:541d) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_FullHeal: ; 21428 (8:5428) - ld a, DUELVARS_ARENA_CARD_STATUS - call GetTurnDuelistVariable - -; skip if no status on arena card - or a ; NO_STATUS - jr z, .no_carry - - and CNF_SLP_PRZ - cp PARALYZED - jr z, .paralyzed - cp ASLEEP - jr z, .asleep - cp CONFUSED - jr z, .confused - ; if either PSN or DBLPSN, fallthrough - -.set_carry - scf - ret - -.asleep -; set carry if any of the following -; cards are in the Play Area. - ld a, GASTLY1 - ld b, PLAY_AREA_ARENA - call LookForCardIDInPlayArea_Bank8 - jr c, .set_carry - ld a, GASTLY2 - ld b, PLAY_AREA_ARENA - call LookForCardIDInPlayArea_Bank8 - jr c, .set_carry - ld a, HAUNTER2 - ld b, PLAY_AREA_ARENA - call LookForCardIDInPlayArea_Bank8 - jr c, .set_carry - -; otherwise fallthrough - -.paralyzed -; if Scoop Up is in hand and decided to be played, skip. - ld a, SCOOP_UP - call LookForCardIDInHandList_Bank8 - jr nc, .no_scoop_up_prz - call AIDecide_ScoopUp - jr c, .no_carry - -.no_scoop_up_prz -; if card can damage defending Pokemon... - xor a ; PLAY_AREA_ARENA - farcall CheckIfCanDamageDefendingPokemon - jr nc, .no_carry -; ...and can play an energy card to retreat, set carry. - ld a, [wAIPlayEnergyCardForRetreat] - or a - jr nz, .set_carry - -; if not, check whether it's a card it would rather retreat, -; and if it isn't, set carry. - farcall AIDecideWhetherToRetreat - jr nc, .set_carry - -.no_carry - or a - ret - -.confused -; if Scoop Up is in hand and decided to be played, skip. - ld a, SCOOP_UP - call LookForCardIDInHandList_Bank8 - jr nc, .no_scoop_up_cnf - call AIDecide_ScoopUp - jr c, .no_carry - -.no_scoop_up_cnf -; if card can damage defending Pokemon... - xor a ; PLAY_AREA_ARENA - farcall CheckIfCanDamageDefendingPokemon - jr nc, .no_carry -; ...and can play an energy card to retreat, set carry. - ld a, [wAIPlayEnergyCardForRetreat] - or a - jr nz, .set_carry -; if not, return no carry. - jr .no_carry - -AIPlay_MrFuji: ; 21497 (8:5497) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; AI logic for playing Mr Fuji -AIDecide_MrFuji: ; 214a7 (8:54a7) - ld a, $ff - ld [wce06], a - ld [wce08], a - -; if just one Pokemon in Play Area, skip. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 1 - ret z - - dec a - ld d, a - ld e, PLAY_AREA_BENCH_1 - -; find a Pokemon in the bench that has damage counters. -.loop_bench - ld a, DUELVARS_ARENA_CARD - add e - push de - call GetTurnDuelistVariable - call LoadCardDataToBuffer1_FromDeckIndex - pop de - - ld a, [wLoadedCard1HP] - ld b, a - - ; skip if zero damage counters - call GetCardDamageAndMaxHP - call ConvertHPToCounters - or a - jr z, .next - -; a = damage counters -; b = hp left - call CalculateBDividedByA_Bank8 - cp 20 - jr nc, .next - -; here, HP left in counters is less than twice -; the number of damage counters, that is: -; HP < 1/3 max HP - -; if value is less than the one found before, store this one. - ld hl, wce08 - cp [hl] - jr nc, .next - ld [hl], a - ld a, e - ld [wce06], a -.next - inc e - dec d - jr nz, .loop_bench - - ld a, [wce06] - cp $ff - ret z - - scf - ret - -AIPlay_ScoopUp: ; 214f1 (8:54f1) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_ScoopUp: ; 21506 (8:5506) - xor a - ldh [hTempPlayAreaLocation_ff9d], a - -; if only one Pokemon in Play Area, skip. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 2 - jr c, .no_carry - -; handle some decks differently - ld a, [wOpponentDeckID] - cp LEGENDARY_ARTICUNO_DECK_ID - jr z, .HandleLegendaryArticuno - cp LEGENDARY_RONALD_DECK_ID - jp z, .HandleLegendaryRonald - -; if can't KO defending Pokemon, check if defending Pokemon -; can KO this card. If so, then continue. -; If not, return no carry. - -; if it can KO the defending Pokemon this turn, -; return no carry. - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .cannot_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry - -.cannot_ko - ld a, DUELVARS_ARENA_CARD_STATUS - call GetTurnDuelistVariable - and CNF_SLP_PRZ - cp PARALYZED - jr z, .cannot_retreat - cp ASLEEP - jr z, .cannot_retreat - -; doesn't have a status that prevents retreat. -; so check if it has enough energy to retreat. -; if not, return no carry. - xor a - ldh [hTempPlayAreaLocation_ff9d], a - call GetPlayAreaCardRetreatCost - ld b, a - ld e, PLAY_AREA_ARENA - farcall CountNumberOfEnergyCardsAttached - cp b - jr c, .cannot_retreat - -.no_carry - or a - ret - -.cannot_retreat -; store damage and total HP left - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call LoadCardDataToBuffer1_FromDeckIndex - ld a, [wLoadedCard1HP] - call ConvertHPToCounters - ld d, a - -; skip if card has no damage counters. - ld e, PLAY_AREA_ARENA - call GetCardDamageAndMaxHP - or a - jr z, .no_carry - -; if (total damage / total HP counters) < 7 -; return carry. -; (this corresponds to damage counters -; being under 70% of the max HP) - ld b, a - ld a, d - call CalculateBDividedByA_Bank8 - cp 7 - jr c, .no_carry - -; store Pokemon to switch to in wce1a and set carry. -.decide_switch - farcall AIDecideBenchPokemonToSwitchTo - jr c, .no_carry - ld [wce1a], a - xor a - scf - ret - -; this deck will use Scoop Up on a benched Articuno2. -; it checks if the defending Pokemon is a Snorlax, -; but interestingly does not check for Muk in both Play Areas. -; will also use Scoop Up on -.HandleLegendaryArticuno -; if less than 3 Play Area Pokemon cards, skip. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 3 - jr c, .no_carry - -; look for Articuno2 in bench - ld a, ARTICUNO2 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank8 - jr c, .articuno_bench - -; check Arena card - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - cp ARTICUNO2 - jr z, .articuno_or_chansey - cp CHANSEY - jr nz, .no_carry - -; here either Articuno2 or Chansey -; is the Arena Card. -.articuno_or_chansey -; if can't KO defending Pokemon, check if defending Pokemon -; can KO this card. If so, then continue. -; If not, return no carry. - -; if it can KO the defending Pokemon this turn, -; return no carry. - farcall CheckIfAnyAttackKnocksOutDefendingCard - jr nc, .check_ko - farcall CheckIfSelectedAttackIsUnusable - jr nc, .no_carry - farcall LookForEnergyNeededForAttackInHand - jr c, .no_carry -.check_ko - farcall CheckIfDefendingPokemonCanKnockOut - jr nc, .no_carry - jr .decide_switch - -.articuno_bench -; skip if the defending card is Snorlax - push af - ld a, DUELVARS_ARENA_CARD - call GetNonTurnDuelistVariable - call SwapTurn - call GetCardIDFromDeckIndex - call SwapTurn - ld a, e - cp SNORLAX - pop bc - jr z, .no_carry - -; check attached energy cards. -; if it has any, return no carry. - ld a, b -.check_attached_energy - ld e, a - push af - farcall CountNumberOfEnergyCardsAttached - or a - pop bc - ld a, b - jr z, .no_energy - jp .no_carry - -.no_energy -; has decided to Scoop Up benched card, -; store $ff as the Pokemon card to switch to -; because there's no need to switch. - push af - ld a, $ff - ld [wce1a], a - pop af - scf - ret - -; this deck will use Scoop Up on a benched Articuno2, Zapdos3 or Moltres2. -; interestingly, does not check for Muk in both Play Areas. -.HandleLegendaryRonald ; 215e7 (8:55e7) -; if less than 3 Play Area Pokemon cards, skip. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 3 - jp c, .no_carry - - ld a, ARTICUNO2 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank8 - jr c, .articuno_bench - ld a, ZAPDOS3 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank8 - jr c, .check_attached_energy - ld a, MOLTRES2 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank8 - jr c, .check_attached_energy - jp .no_carry - -AIPlay_Maintenance: ; 2160f (8:560f) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wce1a] - ldh [hTemp_ffa0], a - ld a, [wce1b] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; AI logic for playing Maintenance -AIDecide_Maintenance: ; 2162c (8:562c) -; Imakuni? has his own thing - ld a, [wOpponentDeckID] - cp IMAKUNI_DECK_ID - jr z, .imakuni - -; skip if number of cars in hand < 4. - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 4 - jr c, .no_carry - -; list out all the hand cards and remove -; wAITrainerCardToPlay from list.Then find any duplicate cards. - call CreateHandCardList - ld hl, wDuelTempList - ld a, [wAITrainerCardToPlay] - call FindAndRemoveCardFromList -; if duplicates are not found, return no carry. - call FindDuplicateCards - jp c, .no_carry - -; store the first duplicate card and remove it from the list. -; run duplicate check again. - ld [wce1a], a - ld hl, wDuelTempList - call FindAndRemoveCardFromList -; if duplicates are not found, return no carry. - call FindDuplicateCards - jp c, .no_carry - -; store the second duplicate card and return carry. - ld [wce1b], a - scf - ret - -.no_carry - or a - ret - -.imakuni -; has a 2 in 10 chance of not skipping. - ld a, 10 - call Random - cp 2 - jr nc, .no_carry - -; skip if number of cards in hand < 3. - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 3 - jr c, .no_carry - -; shuffle hand cards - call CreateHandCardList - ld hl, wDuelTempList - call CountCardsInDuelTempList - call ShuffleCards - -; go through each card and find -; cards that are different from wAITrainerCardToPlay. -; if found, add those cards to wce1a and wce1a+1. - ld a, [wAITrainerCardToPlay] - ld b, a - ld c, 2 - ld de, wce1a - -.loop - ld a, [hli] - cp $ff - jr z, .no_carry - cp b - jr z, .loop - ld [de], a - inc de - dec c - jr nz, .loop - -; two cards were found, return carry. - scf - ret - -AIPlay_Recycle: ; 2169a (8:569a) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ldtx de, TrainerCardSuccessCheckText - bank1call TossCoin - jr nc, .asm_216ae - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - jr .asm_216b2 -.asm_216ae - ld a, $ff - ldh [hTemp_ffa0], a -.asm_216b2 - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; lists cards to look for in the Discard Pile. -; has priorities for Ghost Deck, and a "default" priority list -; (which is the Fire Charge deck, since it's the only other -; deck that runs a Recycle card in it.) -AIDecide_Recycle: ; 216b8 (8:56b8) -; no use checking if no cards in Discard Pile - call CreateDiscardPileCardList - jr c, .no_carry - - ld a, $ff - ld [wce08], a - ld [wce08 + 1], a - ld [wce08 + 2], a - ld [wce08 + 3], a - ld [wce08 + 4], a - -; handle Ghost deck differently - ld hl, wDuelTempList - ld a, [wOpponentDeckID] - cp GHOST_DECK_ID - jr z, .loop_2 - -; priority list for Fire Charge deck -.loop_1 - ld a, [hli] - cp $ff - jr z, .done - - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - -; double colorless - cp DOUBLE_COLORLESS_ENERGY - jr nz, .chansey - ld a, b - ld [wce08], a - jr .loop_1 - -.chansey - cp CHANSEY - jr nz, .tauros - ld a, b - ld [wce08 + 1], a - jr .loop_1 - -.tauros - cp TAUROS - jr nz, .jigglypuff - ld a, b - ld [wce08 + 2], a - jr .loop_1 - -.jigglypuff - cp JIGGLYPUFF1 - jr nz, .loop_1 - ld a, b - ld [wce08 + 3], a - jr .loop_1 - -; loop through wce08 and set carry -; on the first that was found in Discard Pile. -; if none were found, return no carry. -.done - ld hl, wce08 - ld b, 5 -.loop_found - ld a, [hli] - cp $ff - jr nz, .set_carry - dec b - jr nz, .loop_found -.no_carry - or a - ret -.set_carry - scf - ret - -; priority list for Ghost deck -.loop_2 - ld a, [hli] - cp $ff - jr z, .done - - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - -; gastly2 - cp GASTLY2 - jr nz, .gastly1 - ld a, b - ld [wce08], a - jr .loop_2 - -.gastly1 - cp GASTLY1 - jr nz, .zubat - ld a, b - ld [wce08 + 1], a - jr .loop_2 - -.zubat - cp ZUBAT - jr nz, .ditto - ld a, b - ld [wce08 + 2], a - jr .loop_2 - -.ditto - cp DITTO - jr nz, .meowth - ld a, b - ld [wce08 + 3], a - jr .loop_2 - -.meowth - cp MEOWTH2 - jr nz, .loop_2 - ld a, b - ld [wce08 + 4], a - jr .loop_2 - -AIPlay_Lass: ; 21755 (8:5755) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_Lass: ; 21768 (8:5768) -; skip if player has less than 7 cards in hand - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetNonTurnDuelistVariable - cp 7 - jr c, .no_carry - -; look for Trainer cards in hand (except for Lass) -; if any is found, return no carry. -; otherwise, return carry. - call CreateHandCardList - ld hl, wDuelTempList -.loop - ld a, [hli] - cp $ff - jr z, .set_carry - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - cp LASS - jr z, .loop - ld a, [wLoadedCard1Type] - cp TYPE_TRAINER - jr nz, .loop -.no_carry - or a - ret -.set_carry - scf - ret - -AIPlay_ItemFinder: ; 2178f (8:578f) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wce1a] - ldh [hTemp_ffa0], a - ld a, [wce1b] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wAITrainerCardParameter] - ldh [hTempRetreatCostCards], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; checks whether there's Energy Removal in Discard Pile. -; if so, find duplicate cards in hand to discard -; that are not Mr Mime and Pokemon Trader cards. -; this logic is suitable only for Strange Psyshock deck. -AIDecide_ItemFinder: ; 217b1 (8:57b1) -; skip if no Discard Pile. - call CreateDiscardPileCardList - jr c, .no_carry - -; look for Energy Removal in Discard Pile - ld hl, wDuelTempList -.loop_discard_pile - ld a, [hli] - cp $ff - jr z, .no_carry - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - cp ENERGY_REMOVAL - jr nz, .loop_discard_pile -; found, store this deck index - ld a, b - ld [wce06], a - -; before looking for cards to discard in hand, -; remove any Mr Mime and Pokemon Trader cards. -; this way these are guaranteed to not be discarded. - call CreateHandCardList - ld hl, wDuelTempList -.loop_hand - ld a, [hli] - cp $ff - jr z, .choose_discard - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - cp MR_MIME - jr nz, .pkmn_trader - call RemoveCardFromList - jr .loop_hand -.pkmn_trader - cp POKEMON_TRADER - jr nz, .loop_hand - call RemoveCardFromList - jr .loop_hand - -; choose cards to discard from hand. -.choose_discard - ld hl, wDuelTempList - -; do not discard wAITrainerCardToPlay - ld a, [wAITrainerCardToPlay] - call FindAndRemoveCardFromList -; find any duplicates, if not found, return no carry. - call FindDuplicateCards - jp c, .no_carry - -; store the duplicate found in wce1a and -; remove it from the hand list. - ld [wce1a], a - ld hl, wDuelTempList - call FindAndRemoveCardFromList -; find duplicates again, if not found, return no carry. - call FindDuplicateCards - jp c, .no_carry - -; store the duplicate found in wce1b. -; output the card to be recovered from the Discard Pile. - ld [wce1b], a - ld a, [wce06] - scf - ret - -.no_carry - or a - ret - -AIPlay_Imakuni: ; 21813 (8:5813) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; only sets carry if Active card is not confused. -AIDecide_Imakuni: ; 2181e (8:581e) - ld a, DUELVARS_ARENA_CARD_STATUS - call GetTurnDuelistVariable - and CNF_SLP_PRZ - cp CONFUSED - jr z, .confused - scf - ret -.confused - or a - ret - -AIPlay_Gambler: ; 2182d (8:582d) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wOpponentDeckID] - cp IMAKUNI_DECK_ID - jr z, .asm_2186a - ld hl, wRNG1 - ld a, [hli] - ld [wce06], a - ld a, [hli] - ld [wce08], a - ld a, [hl] - ld [wce0f], a - ld a, $50 - ld [hld], a - ld [hld], a - ld [hl], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ld hl, wRNG1 - ld a, [wce06] - ld [hli], a - ld a, [wce08] - ld [hli], a - ld a, [wce0f] - ld [hl], a - ret -.asm_2186a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; checks whether to play Gambler. -; aside from Imakuni?, all other opponents only -; play this card if Player is running Mewtwo1-only deck. -AIDecide_Gambler: ; 21875 (8:5875) -; Imakuni? has his own routine - ld a, [wOpponentDeckID] - cp IMAKUNI_DECK_ID - jr z, .imakuni - -; check if flag is set for Player using Mewtwo1 only deck - ld a, [wAIBarrierFlagCounter] - and AI_MEWTWO_MILL - jr z, .no_carry - -; set carry if number of cards in deck <= 4. -; this is done to counteract the deck out strategy -; of Mewtwo1 deck, by replenishing the deck with hand cards. - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 4 - jr nc, .set_carry -.no_carry - or a - ret - -.imakuni -; has a 2 in 10 chance of returning carry - ld a, 10 - call Random - cp 2 - jr nc, .no_carry -.set_carry - scf - ret - -AIPlay_Revive: ; 21899 (8:5899) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; checks certain cards in Discard Pile to use Revive on. -; suitable for Muscle For Brains deck only. -AIDecide_Revive: ; 218a9 (8:58a9) -; skip if no cards in Discard Pile - call CreateDiscardPileCardList - jr c, .no_carry - -; skip if number of Pokemon cards in Play Area >= 4 - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp 4 - jr nc, .no_carry - -; look in Discard Pile for specific cards. - ld hl, wDuelTempList -.loop_discard_pile - ld a, [hli] - cp $ff - jr z, .no_carry - ld b, a - call LoadCardDataToBuffer1_FromDeckIndex - -; these checks have a bug. -; it works fine for Hitmonchan and Hitmonlee, -; but in case it's a Tauros card, the routine will fallthrough -; into the Kangaskhan check. since it will never be equal to Kangaskhan, -; it will fallthrough into the set carry branch. -; in case it's a Kangaskhan card, the check will fail in the Tauros check -; and jump back into the loop. so just by accident the Tauros check works, -; but Kangaskhan will never be correctly checked because of this. - cp HITMONCHAN - jr z, .set_carry - cp HITMONLEE - jr z, .set_carry - cp TAUROS - jr nz, .loop_discard_pile ; bug, these two lines should be swapped - cp KANGASKHAN - jr z, .set_carry ; bug, these two lines should be swapped - -.set_carry - ld a, b - scf - ret -.no_carry - or a - ret - -AIPlay_PokemonFlute: ; 218d8 (8:58d8) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_PokemonFlute: ; 218e8 (8:58e8) -; if player has no Discard Pile, skip. - call SwapTurn - call CreateDiscardPileCardList - call SwapTurn - jr c, .no_carry - -; if player's Play Area is already full, skip. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetNonTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .no_carry - - ld a, [wOpponentDeckID] - cp IMAKUNI_DECK_ID - jr z, .imakuni - - ld a, $ff - ld [wce06], a - ld [wce08], a - -; find Basic stage Pokemon with lowest HP in Discard Pile - ld hl, wDuelTempList -.loop_1 - ld a, [hli] - cp $ff - jr z, .done - - ld b, a - call SwapTurn - call LoadCardDataToBuffer1_FromDeckIndex - call SwapTurn -; skip this card if it's not Pokemon card - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .loop_1 -; skip this card if it's not Basic Stage - ld a, [wLoadedCard1Stage] - or a ; BASIC - jr nz, .loop_1 - -; compare this HP with one stored - ld a, [wLoadedCard1HP] - push hl - ld hl, wce06 - cp [hl] - pop hl - jr nc, .loop_1 -; if lower, store this one - ld [wce06], a - ld a, b - ld [wce08], a - jr .loop_1 - -.done -; if lowest HP found >= 50, return no carry - ld a, [wce06] - cp 50 - jr nc, .no_carry -; otherwise output its deck index in a and set carry. - ld a, [wce08] - scf - ret -.no_carry - or a - ret - -.imakuni -; has 2 in 10 chance of not skipping - ld a, 10 - call Random - cp 2 - jr nc, .no_carry - -; look for any Basic Pokemon card - ld hl, wDuelTempList -.loop_2 - ld a, [hli] - cp $ff - jr z, .no_carry - ld b, a - call SwapTurn - call LoadCardDataToBuffer1_FromDeckIndex - call SwapTurn - ld a, [wLoadedCard1Type] - cp TYPE_ENERGY - jr nc, .loop_2 - ld a, [wLoadedCard1Stage] - or a ; BASIC - jr nz, .loop_2 - -; a Basic stage Pokemon was found, return carry - ld a, b - scf - ret - -AIPlay_ClefairyDollOrMysteriousFossil: ; 21977 (8:5977) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; AI logic for playing Clefairy Doll -AIDecide_ClefairyDollOrMysteriousFossil: ; 21982 (8:5982) -; if has max number of Play Area Pokemon, skip - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .no_carry - -; store number of Play Area Pokemon cards - ld [wce06], a - -; if the Arena card is Wigglytuff, return carry - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, e - cp WIGGLYTUFF - jr z, .set_carry - -; if number of Play Area Pokemon >= 4, return no carry - ld a, [wce06] - cp 4 - jr nc, .no_carry - -.set_carry - scf - ret -.no_carry - or a - ret - -AIPlay_Pokeball: ; 219a6 (8:59a6) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ldtx de, TrainerCardSuccessCheckText - bank1call TossCoin - ldh [hTemp_ffa0], a - jr nc, .asm_219bc - ld a, [wAITrainerCardParameter] - ldh [hTempPlayAreaLocation_ffa1], a - jr .asm_219c0 -.asm_219bc - ld a, $ff - ldh [hTempPlayAreaLocation_ffa1], a -.asm_219c0 - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_Pokeball: ; 219c6 (8:59c6) -; go to the routines associated with deck ID - ld a, [wOpponentDeckID] - cp FIRE_CHARGE_DECK_ID - jr z, .fire_charge - cp HARD_POKEMON_DECK_ID - jr z, .hard_pokemon - cp PIKACHU_DECK_ID - jr z, .pikachu - cp ETCETERA_DECK_ID - jr z, .etcetera - cp LOVELY_NIDORAN_DECK_ID - jp z, .lovely_nidoran - or a - ret - -; this deck runs a deck check for specific -; card IDs in order of decreasing priority -.fire_charge - ld e, CHANSEY - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, TAUROS - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, JIGGLYPUFF1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ret - -; this deck runs a deck check for specific -; card IDs in order of decreasing priority -.hard_pokemon - ld e, RHYHORN - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, RHYDON - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, ONIX - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ret - -; this deck runs a deck check for specific -; card IDs in order of decreasing priority -.pikachu - ld e, PIKACHU2 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, PIKACHU3 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, PIKACHU4 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, PIKACHU1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, FLYING_PIKACHU - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ret - -; this deck runs a deck check for specific -; card IDs in order of decreasing priority -; given a specific energy card in hand. -; also it avoids redundancy, so if it already -; has that card ID in the hand, it is skipped. -.etcetera -; fire - ld a, FIRE_ENERGY - call LookForCardIDInHandList_Bank8 - jr nc, .lightning - ld a, CHARMANDER - call LookForCardIDInHandList_Bank8 - jr c, .lightning - ld a, MAGMAR2 - call LookForCardIDInHandList_Bank8 - jr c, .lightning - ld e, CHARMANDER - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, MAGMAR2 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - -.lightning - ld a, LIGHTNING_ENERGY - call LookForCardIDInHandList_Bank8 - jr nc, .fighting - ld a, PIKACHU1 - call LookForCardIDInHandList_Bank8 - jr c, .fighting - ld a, MAGNEMITE1 - call LookForCardIDInHandList_Bank8 - jr c, .fighting - ld e, PIKACHU1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, MAGNEMITE1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - -.fighting - ld a, FIGHTING_ENERGY - call LookForCardIDInHandList_Bank8 - jr nc, .psychic - ld a, DIGLETT - call LookForCardIDInHandList_Bank8 - jr c, .psychic - ld a, MACHOP - call LookForCardIDInHandList_Bank8 - jr c, .psychic - ld e, DIGLETT - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, MACHOP - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - -.psychic - ld a, PSYCHIC_ENERGY - call LookForCardIDInHandList_Bank8 - jr nc, .done_etcetera - ld a, GASTLY1 - call LookForCardIDInHandList_Bank8 - jr c, .done_etcetera - ld a, JYNX - call LookForCardIDInHandList_Bank8 - jr c, .done_etcetera - ld e, GASTLY1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c - ld e, JYNX - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - ret c -.done_etcetera - or a - ret - -; this deck looks for card evolutions if -; its pre-evolution is in hand or in Play Area. -; if none of these are found, it looks for pre-evolutions -; of cards it has in hand. -; it does this for both the NidoranM (first) -; and NidoranF (second) families. -.lovely_nidoran - ld b, NIDORANM - ld a, NIDORINO - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - ret c - ld b, NIDORINO - ld a, NIDOKING - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - ret c - ld a, NIDORANM - ld b, NIDORINO - call LookForCardIDInDeck_GivenCardIDInHand - ret c - ld a, NIDORINO - ld b, NIDOKING - call LookForCardIDInDeck_GivenCardIDInHand - ret c - ld b, NIDORANF - ld a, NIDORINA - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - ret c - ld b, NIDORINA - ld a, NIDOQUEEN - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - ret c - ld a, NIDORANF - ld b, NIDORINA - call LookForCardIDInDeck_GivenCardIDInHand - ret c - ld a, NIDORINA - ld b, NIDOQUEEN - call LookForCardIDInDeck_GivenCardIDInHand - ret c - ret - -AIPlay_ComputerSearch: ; 21b12 (8:5b12) - ld a, [wCurrentAIFlags] - or AI_FLAG_MODIFIED_HAND - ld [wCurrentAIFlags], a - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTempRetreatCostCards], a - ld a, [wce1a] - ldh [hTemp_ffa0], a - ld a, [wce1b] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -; checks what Deck ID AI is playing and handle -; them in their own routine. -AIDecide_ComputerSearch: ; 21b34 (8:5b34) -; skip if number of cards in hand < 3 - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 3 - jr c, .no_carry - - ld a, [wOpponentDeckID] - cp ROCK_CRUSHER_DECK_ID - jr z, AIDecide_ComputerSearch_RockCrusher - cp WONDERS_OF_SCIENCE_DECK_ID - jp z, AIDecide_ComputerSearch_WondersOfScience - cp FIRE_CHARGE_DECK_ID - jp z, AIDecide_ComputerSearch_FireCharge - cp ANGER_DECK_ID - jp z, AIDecide_ComputerSearch_Anger - -.no_carry - or a - ret - -AIDecide_ComputerSearch_RockCrusher: ; 21b55 (8:5b55) -; if number of cards in hand is equal to 3, -; target Professor Oak in deck - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 3 - jr nz, .graveler - - ld e, PROFESSOR_OAK - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr c, .find_discard_cards_1 - ; no Professor Oak in deck, fallthrough - -.no_carry - or a - ret - -.find_discard_cards_1 - ld [wce06], a - ld a, $ff - ld [wce1a], a - ld [wce1b], a - - call CreateHandCardList - ld hl, wDuelTempList - ld de, wce1a -.loop_hand_1 - ld a, [hli] - cp $ff - jr z, .check_discard_cards - - ld c, a - call LoadCardDataToBuffer1_FromDeckIndex - -; if any of the following cards are in the hand, -; return no carry. - cp PROFESSOR_OAK - jr z, .no_carry - cp FIGHTING_ENERGY - jr z, .no_carry - cp DOUBLE_COLORLESS_ENERGY - jr z, .no_carry - cp DIGLETT - jr z, .no_carry - cp GEODUDE - jr z, .no_carry - cp ONIX - jr z, .no_carry - cp RHYHORN - jr z, .no_carry - -; if it's same as wAITrainerCardToPlay, skip this card. - ld a, [wAITrainerCardToPlay] - ld b, a - ld a, c - cp b - jr z, .loop_hand_1 - -; store this card index in memory - ld [de], a - inc de - jr .loop_hand_1 - -.check_discard_cards -; check if two cards were found -; if so, output in a the deck index -; of Professor Oak card found in deck and set carry. - ld a, [wce1b] - cp $ff - jr z, .no_carry - ld a, [wce06] - scf - ret - -; more than 3 cards in hand, so look for -; specific evolution cards. - -; checks if there is a Graveler card in the deck to target. -; if so, check if there's Geodude in hand or Play Area, -; and if there's no Graveler card in hand, proceed. -; also removes Geodude from hand list so that it is not discarded. -.graveler - ld e, GRAVELER - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr nc, .golem - ld [wce06], a - ld a, GEODUDE - call LookForCardIDInHandAndPlayArea - jr nc, .golem - ld a, GRAVELER - call LookForCardIDInHandList_Bank8 - jr c, .golem - call CreateHandCardList - ld hl, wDuelTempList - ld e, GEODUDE - farcall RemoveCardIDInList - jr .find_discard_cards_2 - -; checks if there is a Golem card in the deck to target. -; if so, check if there's Graveler in Play Area, -; and if there's no Golem card in hand, proceed. -.golem - ld e, GOLEM - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr nc, .dugtrio - ld [wce06], a - ld a, GRAVELER - call LookForCardIDInPlayArea_Bank8 - jr nc, .dugtrio - ld a, GOLEM - call LookForCardIDInHandList_Bank8 - jr c, .dugtrio - call CreateHandCardList - ld hl, wDuelTempList - jr .find_discard_cards_2 - -; checks if there is a Dugtrio card in the deck to target. -; if so, check if there's Diglett in Play Area, -; and if there's no Dugtrio card in hand, proceed. -.dugtrio - ld e, DUGTRIO - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry - ld [wce06], a - ld a, DIGLETT - call LookForCardIDInPlayArea_Bank8 - jp nc, .no_carry - ld a, DUGTRIO - call LookForCardIDInHandList_Bank8 - jp c, .no_carry - call CreateHandCardList - ld hl, wDuelTempList - jr .find_discard_cards_2 - -.find_discard_cards_2 - ld a, $ff - ld [wce1a], a - ld [wce1b], a - - ld bc, wce1a - ld d, $00 ; start considering Trainer cards only - -; stores wAITrainerCardToPlay in e so that -; all routines ignore it for the discard effects. - ld a, [wAITrainerCardToPlay] - ld e, a - -; this loop will store in wce1a cards to discard from hand. -; at the start it will only consider Trainer cards, -; then if there are still needed to discard, -; move on to Pokemon cards, and finally to Energy cards. -.loop_hand_2 - call RemoveFromListDifferentCardOfGivenType - jr c, .found - inc d ; move on to next type (Pokemon, then Energy) - ld a, $03 - cp d - jp z, .no_carry ; no more types to look - jr .loop_hand_2 -.found -; store this card in memory, -; and if there's still one more card to search for, -; jump back into the loop. - ld [bc], a - inc bc - ld a, [wce1b] - cp $ff - jr z, .loop_hand_2 - -; output in a Computer Search target and set carry. - ld a, [wce06] - scf - ret - -AIDecide_ComputerSearch_WondersOfScience: ; 21c56 (8:5c56) -; if number of cards in hand < 5, target Professor Oak in deck - ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND - call GetTurnDuelistVariable - cp 5 - jr nc, .look_in_hand - -; target Professor Oak for Computer Search - ld e, PROFESSOR_OAK - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .look_in_hand ; can be a jr - ld [wce06], a - jr .find_discard_cards - -; Professor Oak not in deck, move on to -; look for other cards instead. -; if Grimer or Muk are not in hand, -; check whether to use Computer Search on them. -.look_in_hand - ld a, GRIMER - call LookForCardIDInHandList_Bank8 - jr nc, .target_grimer - ld a, MUK - call LookForCardIDInHandList_Bank8 - jr nc, .target_muk - -.no_carry - or a - ret - -; first check Grimer -; if in deck, check cards to discard. -.target_grimer - ld e, GRIMER - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry ; can be a jr - ld [wce06], a - jr .find_discard_cards - -; first check Muk -; if in deck, check cards to discard. -.target_muk - ld e, MUK - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry ; can be a jr - ld [wce06], a - -; only discard Trainer cards from hand. -; if there are less than 2 Trainer cards to discard, -; then return with no carry. -; else, store the cards to discard and the -; target card deck index, and return carry. -.find_discard_cards - call CreateHandCardList - ld hl, wDuelTempList - ld d, $00 ; first consider Trainer cards - -; ignore wAITrainerCardToPlay for the discard effects. - ld a, [wAITrainerCardToPlay] - ld e, a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1a], a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1b], a - ld a, [wce06] - scf - ret - -AIDecide_ComputerSearch_FireCharge: ; 21cbb (8:5cbb) -; pick target card in deck from highest to lowest priority. -; if not found in hand, go to corresponding branch. - ld a, CHANSEY - call LookForCardIDInHandList_Bank8 - jr nc, .chansey - ld a, TAUROS - call LookForCardIDInHandList_Bank8 - jr nc, .tauros - ld a, JIGGLYPUFF1 - call LookForCardIDInHandList_Bank8 - jr nc, .jigglypuff - ; fallthrough - -.no_carry - or a - ret - -; for each card targeted, check if it's in deck and, -; if not, then return no carry. -; else, look for cards to discard. -.chansey - ld e, CHANSEY - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry - ld [wce06], a - jr .find_discard_cards -.tauros - ld e, TAUROS - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry - ld [wce06], a - jr .find_discard_cards -.jigglypuff - ld e, JIGGLYPUFF1 - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jp nc, .no_carry - ld [wce06], a - -; only discard Trainer cards from hand. -; if there are less than 2 Trainer cards to discard, -; then return with no carry. -; else, store the cards to discard and the -; target card deck index, and return carry. -.find_discard_cards - call CreateHandCardList - ld hl, wDuelTempList - ld d, $00 ; first consider Trainer cards - -; ignore wAITrainerCardToPlay for the discard effects. - ld a, [wAITrainerCardToPlay] - ld e, a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1a], a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1b], a - ld a, [wce06] - scf - ret - -AIDecide_ComputerSearch_Anger: ; 21d1e (8:5d1e) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, RATTATA - ld a, RATICATE - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_discard_cards - ld a, RATTATA - ld b, RATICATE - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_discard_cards - ld b, GROWLITHE - ld a, ARCANINE1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_discard_cards - ld a, GROWLITHE - ld b, ARCANINE1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_discard_cards - ld b, DODUO - ld a, DODRIO - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_discard_cards - ld a, DODUO - ld b, DODRIO - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_discard_cards - ; fallthrough - -.no_carry - or a - ret - -; only discard Trainer cards from hand. -; if there are less than 2 Trainer cards to discard, -; then return with no carry. -; else, store the cards to discard and the -; target card deck index, and return carry. -.find_discard_cards - ld [wce06], a - call CreateHandCardList - ld hl, wDuelTempList - ld d, $00 ; first consider Trainer cards - -; ignore wAITrainerCardToPlay for the discard effects. - ld a, [wAITrainerCardToPlay] - ld e, a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1a], a - call RemoveFromListDifferentCardOfGivenType - jr nc, .no_carry - ld [wce1b], a - ld a, [wce06] - scf - ret - -AIPlay_PokemonTrader: ; 21d7a (8:5d7a) - ld a, [wAITrainerCardToPlay] - ldh [hTempCardIndex_ff9f], a - ld a, [wAITrainerCardParameter] - ldh [hTemp_ffa0], a - ld a, [wce1a] - ldh [hTempPlayAreaLocation_ffa1], a - ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS - bank1call AIMakeDecision - ret - -AIDecide_PokemonTrader: ; 21d8f (8:5d8f) -; each deck has their own routine for picking -; what Pokemon to look for. - ld a, [wOpponentDeckID] - cp LEGENDARY_MOLTRES_DECK_ID - jr z, AIDecide_PokemonTrader_LegendaryMoltres - cp LEGENDARY_ARTICUNO_DECK_ID - jr z, AIDecide_PokemonTrader_LegendaryArticuno - cp LEGENDARY_DRAGONITE_DECK_ID - jp z, AIDecide_PokemonTrader_LegendaryDragonite - cp LEGENDARY_RONALD_DECK_ID - jp z, AIDecide_PokemonTrader_LegendaryRonald - cp BLISTERING_POKEMON_DECK_ID - jp z, AIDecide_PokemonTrader_BlisteringPokemon - cp SOUND_OF_THE_WAVES_DECK_ID - jp z, AIDecide_PokemonTrader_SoundOfTheWaves - cp POWER_GENERATOR_DECK_ID - jp z, AIDecide_PokemonTrader_PowerGenerator - cp FLOWER_GARDEN_DECK_ID - jp z, AIDecide_PokemonTrader_FlowerGarden - cp STRANGE_POWER_DECK_ID - jp z, AIDecide_PokemonTrader_StrangePower - cp FLAMETHROWER_DECK_ID - jp z, AIDecide_PokemonTrader_Flamethrower - or a - ret - -AIDecide_PokemonTrader_LegendaryMoltres: ; 21dc4 (8:5dc4) -; look for Moltres2 card in deck to trade with a -; card in hand different from Moltres1. - ld a, MOLTRES2 - ld e, MOLTRES1 - call LookForCardIDToTradeWithDifferentHandCard - jr nc, .no_carry -; success - ld [wce1a], a - ld a, e - scf - ret -.no_carry - or a - ret - -AIDecide_PokemonTrader_LegendaryArticuno: ; 21dd5 (8:5dd5) -; if has none of these cards in Hand or Play Area, proceed - ld a, ARTICUNO1 - call LookForCardIDInHandAndPlayArea - jr c, .no_carry - ld a, LAPRAS - call LookForCardIDInHandAndPlayArea - jr c, .no_carry - -; if doesn't have Seel in Hand or Play Area, -; look for it in the deck. -; otherwise, look for Dewgong instead. - ld a, SEEL - call LookForCardIDInHandAndPlayArea - jr c, .dewgong - - ld e, SEEL - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr nc, .dewgong - ld [wce1a], a - jr .check_hand - -.dewgong - ld a, DEWGONG - call LookForCardIDInHandAndPlayArea - jr c, .no_carry - ld e, DEWGONG - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr nc, .no_carry - ld [wce1a], a - -; a Seel or Dewgong was found in deck, -; check hand for card to trade for -.check_hand - ld a, CHANSEY - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, DITTO - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, ARTICUNO2 - call CheckIfHasCardIDInHand - jr c, .set_carry - ; doesn't have any of the cards in hand - -.no_carry - or a - ret - -.set_carry - scf - ret - -AIDecide_PokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) -; if has less than 5 cards of energy -; and of Pokemon in hand/Play Area, -; target a Kangaskhan in deck. - farcall CountOppEnergyCardsInHandAndAttached - cp 5 - jr c, .kangaskhan - call CountPokemonCardsInHandAndInPlayArea - cp 5 - jr c, .kangaskhan - ; total number of energy cards >= 5 - ; total number of Pokemon cards >= 5 - -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, MAGIKARP - ld a, GYARADOS - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, MAGIKARP - ld b, GYARADOS - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, DRATINI - ld a, DRAGONAIR - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld b, DRAGONAIR - ld a, DRAGONITE1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, DRATINI - ld b, DRAGONAIR - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld a, DRAGONAIR - ld b, DRAGONITE1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, CHARMANDER - ld a, CHARMELEON - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld b, CHARMELEON - ld a, CHARIZARD - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, CHARMANDER - ld b, CHARMELEON - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld a, CHARMELEON - ld b, CHARIZARD - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - jr .no_carry - -.kangaskhan - ld e, KANGASKHAN - ld a, CARD_LOCATION_DECK - call LookForCardIDInLocation - jr nc, .no_carry - -; card was found as target in deck, -; look for card in hand to trade with -.choose_hand - ld [wce1a], a - ld a, DRAGONAIR - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, CHARMELEON - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, GYARADOS - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, MAGIKARP - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, CHARMANDER - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, DRATINI - call CheckIfHasCardIDInHand - jr c, .set_carry - ; non found - -.no_carry - or a - ret -.set_carry - scf - ret - -AIDecide_PokemonTrader_LegendaryRonald: ; 21ec9 (8:5ec9) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, EEVEE - ld a, FLAREON1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld b, EEVEE - ld a, VAPOREON1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld b, EEVEE - ld a, JOLTEON1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, EEVEE - ld b, FLAREON1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld a, EEVEE - ld b, VAPOREON1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld a, EEVEE - ld b, JOLTEON1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, DRATINI - ld a, DRAGONAIR - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld b, DRAGONAIR - ld a, DRAGONITE1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, DRATINI - ld b, DRAGONAIR - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld a, DRAGONAIR - ld b, DRAGONITE1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - jr .no_carry - -; card was found as target in deck, -; look for card in hand to trade with -.choose_hand - ld [wce1a], a - ld a, ZAPDOS3 - call LookForCardIDInHandList_Bank8 - jr c, .set_carry - ld a, ARTICUNO2 - call LookForCardIDInHandList_Bank8 - jr c, .set_carry - ld a, MOLTRES2 - call LookForCardIDInHandList_Bank8 - jr c, .set_carry - ; none found - -.no_carry - or a - ret -.set_carry - scf - ret - -AIDecide_PokemonTrader_BlisteringPokemon: ; 21f41 (8:5f41) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, RHYHORN - ld a, RHYDON - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, RHYHORN - ld b, RHYDON - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, CUBONE - ld a, MAROWAK1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, CUBONE - ld b, MAROWAK1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, PONYTA - ld a, RAPIDASH - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, PONYTA - ld b, RAPIDASH - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - jr .no_carry - -; a card in deck was found to look for, -; check if there are duplicates in hand to trade with. -.find_duplicates - ld [wce1a], a - call FindDuplicatePokemonCards - jr c, .set_carry -.no_carry - or a - ret -.set_carry - scf - ret - -AIDecide_PokemonTrader_SoundOfTheWaves: ; 21f85 (8:5f85) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, SEEL - ld a, DEWGONG - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, SEEL - ld b, DEWGONG - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, KRABBY - ld a, KINGLER - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, KRABBY - ld b, KINGLER - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, SHELLDER - ld a, CLOYSTER - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, SHELLDER - ld b, CLOYSTER - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, HORSEA - ld a, SEADRA - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, HORSEA - ld b, SEADRA - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - ld b, TENTACOOL - ld a, TENTACRUEL - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .choose_hand - ld a, TENTACOOL - ld b, TENTACRUEL - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .choose_hand - jr .no_carry - -; card was found as target in deck, -; look for card in hand to trade with -.choose_hand - ld [wce1a], a - ld a, SEEL - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, KRABBY - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, HORSEA - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, SHELLDER - call CheckIfHasCardIDInHand - jr c, .set_carry - ld a, TENTACOOL - call CheckIfHasCardIDInHand - jr c, .set_carry - ; none found - -.no_carry - or a - ret -.set_carry - scf - ret - -AIDecide_PokemonTrader_PowerGenerator: ; 2200b (8:600b) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, PIKACHU2 - ld a, RAICHU1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jp c, .find_duplicates - ld b, PIKACHU1 - ld a, RAICHU1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, PIKACHU2 - ld b, RAICHU1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, PIKACHU1 - ld b, RAICHU1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, VOLTORB - ld a, ELECTRODE2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, VOLTORB - ld a, ELECTRODE1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, VOLTORB - ld b, ELECTRODE2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, VOLTORB - ld b, ELECTRODE1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, MAGNEMITE1 - ld a, MAGNETON2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, MAGNEMITE2 - ld a, MAGNETON2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, MAGNEMITE1 - ld a, MAGNETON1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, MAGNEMITE2 - ld a, MAGNETON1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, MAGNEMITE2 - ld b, MAGNETON2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, MAGNEMITE1 - ld b, MAGNETON2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, MAGNEMITE2 - ld b, MAGNETON1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, MAGNEMITE1 - ld b, MAGNETON1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ; bug, missing jr .no_carry - -; since this last check falls through regardless of result, -; register a might hold an invalid deck index, -; which might lead to hilarious results like Brandon -; trading a Pikachu with a Grass Energy from the deck. -; however, since it's deep in a tower of conditionals, -; reaching here is extremely unlikely. - -; a card in deck was found to look for, -; check if there are duplicates in hand to trade with. -.find_duplicates - ld [wce1a], a - call FindDuplicatePokemonCards - jr c, .set_carry - or a - ret -.set_carry - scf - ret - -AIDecide_PokemonTrader_FlowerGarden: ; 220a8 (8:60a8) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, BULBASAUR - ld a, IVYSAUR - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, IVYSAUR - ld a, VENUSAUR2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, BULBASAUR - ld b, IVYSAUR - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, IVYSAUR - ld b, VENUSAUR2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, BELLSPROUT - ld a, WEEPINBELL - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, WEEPINBELL - ld a, VICTREEBEL - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, BELLSPROUT - ld b, WEEPINBELL - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, WEEPINBELL - ld b, VICTREEBEL - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, ODDISH - ld a, GLOOM - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, GLOOM - ld a, VILEPLUME - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, ODDISH - ld b, GLOOM - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, GLOOM - ld b, VILEPLUME - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - jr .no_carry - -; a card in deck was found to look for, -; check if there are duplicates in hand to trade with. -.find_duplicates - ld [wce1a], a - call FindDuplicatePokemonCards - jr c, .found -.no_carry - or a - ret -.found - scf - ret - -AIDecide_PokemonTrader_StrangePower: ; 22122 (8:6122) -; looks for a Pokemon in hand to trade with Mr Mime in deck. -; inputting Mr Mime in register e for the function is redundant -; since it already checks whether a Mr Mime exists in the hand. - ld a, MR_MIME - ld e, MR_MIME - call LookForCardIDToTradeWithDifferentHandCard - jr nc, .no_carry -; found - ld [wce1a], a - ld a, e - scf - ret -.no_carry - or a - ret - -AIDecide_PokemonTrader_Flamethrower: ; 22133 (8:6133) -; for each of the following cards, -; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, choose it as target. -; otherwise, check if the evolution card is in -; hand and if so, choose it as target instead. - ld b, CHARMANDER - ld a, CHARMELEON - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld b, CHARMELEON - ld a, CHARIZARD - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, CHARMANDER - ld b, CHARMELEON - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld a, CHARMELEON - ld b, CHARIZARD - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, VULPIX - ld a, NINETALES1 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, VULPIX - ld b, NINETALES1 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, GROWLITHE - ld a, ARCANINE2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, GROWLITHE - ld b, ARCANINE2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - ld b, EEVEE - ld a, FLAREON2 - call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea - jr c, .find_duplicates - ld a, EEVEE - ld b, FLAREON2 - call LookForCardIDInDeck_GivenCardIDInHand - jr c, .find_duplicates - jr .no_carry - -; a card in deck was found to look for, -; check if there are duplicates in hand to trade with. -.find_duplicates - ld [wce1a], a - call FindDuplicatePokemonCards - jr c, .set_carry -.no_carry - or a - ret -.set_carry - scf - ret |