summaryrefslogtreecommitdiff
path: root/src/engine/ai/core.asm
diff options
context:
space:
mode:
authorElectroDeoxys <ElectroDeoxys@gmail.com>2021-09-29 09:02:02 +0100
committerElectroDeoxys <ElectroDeoxys@gmail.com>2021-09-29 09:02:02 +0100
commitbae47106f18266d2c3b97b6d954b91d9b16c0ccf (patch)
tree4d1a24de37ddb1b22ff22991a275fca351a3651d /src/engine/ai/core.asm
parentb0487fa979d0b5f3241e9e0659dd4b29a7e38f18 (diff)
Reorganise some folders in engine/
Diffstat (limited to 'src/engine/ai/core.asm')
-rw-r--r--src/engine/ai/core.asm2770
1 files changed, 0 insertions, 2770 deletions
diff --git a/src/engine/ai/core.asm b/src/engine/ai/core.asm
deleted file mode 100644
index f182375..0000000
--- a/src/engine/ai/core.asm
+++ /dev/null
@@ -1,2770 +0,0 @@
-INCLUDE "engine/ai/decks/unreferenced.asm"
-
-; returns carry if damage dealt from any of
-; a card's attacks KOs defending Pokémon
-; outputs index of the attack that KOs
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of attacking card to consider
-; output:
-; [wSelectedAttack] = attack index that KOs
-CheckIfAnyAttackKnocksOutDefendingCard: ; 140ae (5:40ae)
- xor a ; first attack
- call CheckIfAttackKnocksOutDefendingCard
- ret c
- ld a, SECOND_ATTACK
-; fallthrough
-
-CheckIfAttackKnocksOutDefendingCard: ; 140b5 (5:40b5)
- call EstimateDamage_VersusDefendingCard
- ld a, DUELVARS_ARENA_CARD_HP
- call GetNonTurnDuelistVariable
- ld hl, wDamage
- sub [hl]
- ret c
- ret nz
- scf
- ret
-
-; returns carry if any of the defending Pokémon's attacks
-; brings card at hTempPlayAreaLocation_ff9d down
-; to exactly 0 HP.
-; outputs that attack index in wSelectedAttack.
-CheckIfAnyDefendingPokemonAttackDealsSameDamageAsHP: ; 140c5 (5:40c5)
- xor a ; FIRST_ATTACK_OR_PKMN_POWER
- call .check_damage
- ret c
- ld a, SECOND_ATTACK
-
-.check_damage
- call EstimateDamage_FromDefendingPokemon
- ldh a, [hTempPlayAreaLocation_ff9d]
- add DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- ld hl, wDamage
- sub [hl]
- jr z, .true
- ret
-.true
- scf
- ret
-
-; checks AI scores for all benched Pokémon
-; returns the location of the card with highest score
-; in a and [hTempPlayAreaLocation_ff9d]
-FindHighestBenchScore: ; 140df (5:40df)
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- ld b, a
- ld c, 0
- ld e, c
- ld d, c
- ld hl, wPlayAreaAIScore + 1
- jp .next
-
-.loop
- ld a, [hli]
- cp e
- jr c, .next
- ld e, a
- ld d, c
-.next
- inc c
- dec b
- jr nz, .loop
-
- ld a, d
- ldh [hTempPlayAreaLocation_ff9d], a
- or a
- ret
-
-; adds a to wAIScore
-; if there's overflow, it's capped at $ff
-; output:
-; a = a + wAIScore (capped at $ff)
-AddToAIScore: ; 140fe (5:40fe)
- push hl
- ld hl, wAIScore
- add [hl]
- jr nc, .no_cap
- ld a, $ff
-.no_cap
- ld [hl], a
- pop hl
- ret
-
-; subs a from wAIScore
-; if there's underflow, it's capped at $00
-SubFromAIScore: ; 1410a (5:410a)
- push hl
- push de
- ld e, a
- ld hl, wAIScore
- ld a, [hl]
- or a
- jr z, .done
- sub e
- ld [hl], a
- jr nc, .done
- ld [hl], $00
-.done
- pop de
- pop hl
- ret
-
-; loads defending Pokémon's weakness/resistance
-; and the number of prize cards in both sides
-LoadDefendingPokemonColorWRAndPrizeCards: ; 1411d (5:411d)
- call SwapTurn
- call GetArenaCardColor
- call TranslateColorToWR
- ld [wAIPlayerColor], a
- call GetArenaCardWeakness
- ld [wAIPlayerWeakness], a
- call GetArenaCardResistance
- ld [wAIPlayerResistance], a
- call CountPrizes
- ld [wAIPlayerPrizeCount], a
- call SwapTurn
- call CountPrizes
- ld [wAIOpponentPrizeCount], a
- ret
-
-; called when AI has chosen its attack.
-; executes all effects and damage.
-; handles AI choosing parameters for certain attacks as well.
-AITryUseAttack: ; 14145 (5:4145)
- ld a, [wSelectedAttack]
- ldh [hTemp_ffa0], a
- ld e, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ldh [hTempCardIndex_ff9f], a
- ld d, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld a, OPPACTION_BEGIN_ATTACK
- bank1call AIMakeDecision
- ret c
-
- call AISelectSpecialAttackParameters
- jr c, .use_attack
- ld a, EFFECTCMDTYPE_AI_SELECTION
- call TryExecuteEffectCommandFunction
-
-.use_attack
- ld a, [wSelectedAttack]
- ld e, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld a, OPPACTION_USE_ATTACK
- bank1call AIMakeDecision
- ret c
-
- ld a, EFFECTCMDTYPE_AI_SWITCH_DEFENDING_PKMN
- call TryExecuteEffectCommandFunction
- ld a, OPPACTION_ATTACK_ANIM_AND_DAMAGE
- bank1call AIMakeDecision
- ret
-
-; return carry if any of the following is satisfied:
-; - deck index in a corresponds to a double colorless energy card;
-; - card type in wTempCardType is colorless;
-; - card ID in wTempCardID is a Pokémon card that has
-; attacks that require energy other than its color and
-; the deck index in a corresponds to that energy type;
-; - card ID is Eevee and a corresponds to an energy type
-; of water, fire or lightning;
-; - type of card in register a is the same as wTempCardType.
-; used for knowing if a given energy card can be discarded
-; from a given Pokémon card
-; input:
-; a = energy card attached to Pokémon to check
-; [wTempCardType] = TYPE_ENERGY_* of given Pokémon
-; [wTempCardID] = card index of Pokémon card to check
-CheckIfEnergyIsUseful: ; 14184 (5:4184)
- push de
- call GetCardIDFromDeckIndex
- ld a, e
- cp DOUBLE_COLORLESS_ENERGY
- jr z, .set_carry
- ld a, [wTempCardType]
- cp TYPE_ENERGY_DOUBLE_COLORLESS
- jr z, .set_carry
- ld a, [wTempCardID]
-
- ld d, PSYCHIC_ENERGY
- cp EXEGGCUTE
- jr z, .check_energy
- cp EXEGGUTOR
- jr z, .check_energy
- cp PSYDUCK
- jr z, .check_energy
- cp GOLDUCK
- jr z, .check_energy
-
- ld d, WATER_ENERGY
- cp SURFING_PIKACHU1
- jr z, .check_energy
- cp SURFING_PIKACHU2
- jr z, .check_energy
-
- cp EEVEE
- jr nz, .check_type
- ld a, e
- cp WATER_ENERGY
- jr z, .set_carry
- cp FIRE_ENERGY
- jr z, .set_carry
- cp LIGHTNING_ENERGY
- jr z, .set_carry
-
-.check_type
- ld d, $00 ; unnecessary?
- call GetCardType
- ld d, a
- ld a, [wTempCardType]
- cp d
- jr z, .set_carry
- pop de
- or a
- ret
-
-.check_energy
- ld a, d
- cp e
- jr nz, .check_type
-.set_carry
- pop de
- scf
- ret
-
-; pick a random Pokemon in the bench.
-; output:
-; - a = PLAY_AREA_* of Bench Pokemon picked.
-PickRandomBenchPokemon: ; 141da (5:41da)
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- dec a
- call Random
- inc a
- ret
-
-AIPickPrizeCards: ; 141e5 (5:41e5)
- ld a, [wNumberPrizeCardsToTake]
- ld b, a
-.loop
- call .PickPrizeCard
- ld a, DUELVARS_PRIZES
- call GetTurnDuelistVariable
- or a
- jr z, .done
- dec b
- jr nz, .loop
-.done
- ret
-
-; picks a prize card at random
-; and adds it to the hand.
-.PickPrizeCard: ; 141f8 (5:41f8)
- ld a, DUELVARS_PRIZES
- call GetTurnDuelistVariable
- push hl
- ld c, a
-
-; choose a random prize card until
-; one is found that isn't taken already.
-.loop_pick_prize
- ld a, 6
- call Random
- ld e, a
- ld d, $00
- ld hl, .prize_flags
- add hl, de
- ld a, [hl]
- and c
- jr z, .loop_pick_prize ; no prize
-
-; prize card was found
-; remove this prize from wOpponentPrizes
- ld a, [hl]
- pop hl
- cpl
- and [hl]
- ld [hl], a
-
-; add this prize card to the hand
- ld a, e
- add DUELVARS_PRIZE_CARDS
- call GetTurnDuelistVariable
- call AddCardToHand
- ret
-
-.prize_flags ; 1421e (5:421e)
- db $1 << 0
- db $1 << 1
- db $1 << 2
- db $1 << 3
- db $1 << 4
- db $1 << 5
- db $1 << 6
- db $1 << 7
-
-; routine for AI to play all Basic cards from its hand
-; in the beginning of the Duel.
-AIPlayInitialBasicCards: ; 14226 (5:4226)
- call CreateHandCardList
- ld hl, wDuelTempList
-.check_for_next_card
- ld a, [hli]
- ldh [hTempCardIndex_ff98], a
- cp $ff
- ret z ; return when done
-
- call LoadCardDataToBuffer1_FromDeckIndex
- ld a, [wLoadedCard1Type]
- cp TYPE_ENERGY
- jr nc, .check_for_next_card ; skip if not Pokemon card
- ld a, [wLoadedCard1Stage]
- or a
- jr nz, .check_for_next_card ; skip if not Basic Stage
-
-; play Basic card from hand
- push hl
- ldh a, [hTempCardIndex_ff98]
- call PutHandPokemonCardInPlayArea
- pop hl
- jr .check_for_next_card
-
-; returns carry if Pokémon at hTempPlayAreaLocation_ff9d
-; can't use an attack or if that selected attack doesn't have enough energy
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of Pokémon card
-; [wSelectedAttack] = selected attack to examine
-CheckIfSelectedAttackIsUnusable: ; 1424b (5:424b)
- ldh a, [hTempPlayAreaLocation_ff9d]
- or a
- jr nz, .bench
-
- bank1call HandleCantAttackSubstatus
- ret c
- bank1call CheckIfActiveCardParalyzedOrAsleep
- ret c
-
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- call CopyAttackDataAndDamage_FromDeckIndex
- call HandleAmnesiaSubstatus
- ret c
- ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1
- call TryExecuteEffectCommandFunction
- ret c
-
-.bench
- call CheckEnergyNeededForAttack
- ret c ; can't be used
- ld a, ATTACK_FLAG2_ADDRESS | FLAG_2_BIT_5_F
- call CheckLoadedAttackFlag
- ret
-
-; load selected attack from Pokémon in hTempPlayAreaLocation_ff9d
-; and checks if there is enough energy to execute the selected attack
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of Pokémon card
-; [wSelectedAttack] = selected attack to examine
-; output:
-; b = basic energy still needed
-; c = colorless energy still needed
-; e = output of ConvertColorToEnergyCardID, or $0 if not an attack
-; carry set if no attack
-; OR if it's a Pokémon Power
-; OR if not enough energy for attack
-CheckEnergyNeededForAttack: ; 14279 (5:4279)
- ldh a, [hTempPlayAreaLocation_ff9d]
- add DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld hl, wLoadedAttackName
- ld a, [hli]
- or [hl]
- jr z, .no_attack
- ld a, [wLoadedAttackCategory]
- cp POKEMON_POWER
- jr nz, .is_attack
-.no_attack
- lb bc, 0, 0
- ld e, c
- scf
- ret
-
-.is_attack
- ldh a, [hTempPlayAreaLocation_ff9d]
- ld e, a
- call GetPlayAreaCardAttachedEnergies
- bank1call HandleEnergyBurn
-
- xor a
- ld [wTempLoadedAttackEnergyCost], a
- ld [wTempLoadedAttackEnergyNeededAmount], a
- ld [wTempLoadedAttackEnergyNeededType], a
-
- ld hl, wAttachedEnergies
- ld de, wLoadedAttackEnergyCost
- ld b, 0
- ld c, (NUM_TYPES / 2) - 1
-
-.loop
- ; check all basic energy cards except colorless
- ld a, [de]
- swap a
- call CheckIfEnoughParticularAttachedEnergy
- ld a, [de]
- call CheckIfEnoughParticularAttachedEnergy
- inc de
- dec c
- jr nz, .loop
-
-; running CheckIfEnoughParticularAttachedEnergy back to back like this
-; overwrites the results of a previous call of this function,
-; however, no attack in the game has energy requirements for two
-; different energy types (excluding colorless), so this routine
-; will always just return the result for one type of basic energy,
-; while all others will necessarily have an energy cost of 0
-; if attacks are added to the game with energy requirements of
-; two different basic energy types, then this routine only accounts
-; for the type with the highest index
-
- ; colorless
- ld a, [de]
- swap a
- and %00001111
- ld b, a ; colorless energy still needed
- ld a, [wTempLoadedAttackEnergyCost]
- ld hl, wTempLoadedAttackEnergyNeededAmount
- sub [hl]
- ld c, a ; basic energy still needed
- ld a, [wTotalAttachedEnergies]
- sub c
- sub b
- jr c, .not_enough
-
- ld a, [wTempLoadedAttackEnergyNeededAmount]
- or a
- ret z
-
-; being here means the energy cost isn't satisfied,
-; including with colorless energy
- xor a
-.not_enough
- cpl
- inc a
- ld c, a ; colorless energy still needed
- ld a, [wTempLoadedAttackEnergyNeededAmount]
- ld b, a ; basic energy still needed
- ld a, [wTempLoadedAttackEnergyNeededType]
- call ConvertColorToEnergyCardID
- ld e, a
- ld d, 0
- scf
- ret
-
-; takes as input the energy cost of an attack for a
-; particular energy, stored in the lower nibble of a
-; if the attack costs some amount of this energy, the lower nibble of a != 0,
-; and this amount is stored in wTempLoadedAttackEnergyCost
-; sets carry flag if not enough energy of this type attached
-; input:
-; a = this energy cost of attack (lower nibble)
-; [hl] = attached energy
-; output:
-; carry set if not enough of this energy type attached
-CheckIfEnoughParticularAttachedEnergy: ; 142f4 (5:42f4)
- and %00001111
- jr nz, .check
-.has_enough
- inc hl
- inc b
- or a
- ret
-
-.check
- ld [wTempLoadedAttackEnergyCost], a
- sub [hl]
- jr z, .has_enough
- jr c, .has_enough
-
- ; not enough energy
- ld [wTempLoadedAttackEnergyNeededAmount], a
- ld a, b
- ld [wTempLoadedAttackEnergyNeededType], a
- inc hl
- inc b
- scf
- ret
-
-; input:
-; a = energy type
-; output:
-; a = energy card ID
-ConvertColorToEnergyCardID: ; 1430f (5:430f)
- push hl
- push de
- ld e, a
- ld d, 0
- ld hl, .card_id
- add hl, de
- ld a, [hl]
- pop de
- pop hl
- ret
-
-.card_id
- db FIRE_ENERGY
- db GRASS_ENERGY
- db LIGHTNING_ENERGY
- db WATER_ENERGY
- db FIGHTING_ENERGY
- db PSYCHIC_ENERGY
- db DOUBLE_COLORLESS_ENERGY
-
-; returns carry if loaded attack effect has
-; an "initial effect 2" or "require selection" command type
-; unreferenced
-Func_14323: ; 14323 (5:4323)
- ld hl, wLoadedAttackEffectCommands
- ld a, [hli]
- ld h, [hl]
- ld l, a
- ld a, EFFECTCMDTYPE_INITIAL_EFFECT_2
- push hl
- call CheckMatchingCommand
- pop hl
- jr nc, .set_carry
- ld a, EFFECTCMDTYPE_REQUIRE_SELECTION
- call CheckMatchingCommand
- jr nc, .set_carry
- or a
- ret
-.set_carry
- scf
- ret
-
-; return carry depending on card index in a:
-; - if energy card, return carry if no energy card has been played yet
-; - if basic Pokémon card, return carry if there's space in bench
-; - if evolution card, return carry if there's a Pokémon
-; in Play Area it can evolve
-; - if trainer card, return carry if it can be used
-; input:
-; a = card index to check
-CheckIfCardCanBePlayed: ; 1433d (5:433d)
- ldh [hTempCardIndex_ff9f], a
- call LoadCardDataToBuffer1_FromDeckIndex
- ld a, [wLoadedCard1Type]
- cp TYPE_ENERGY
- jr c, .pokemon_card
- cp TYPE_TRAINER
- jr z, .trainer_card
-
-; energy card
- ld a, [wAlreadyPlayedEnergy]
- or a
- ret z
- scf
- ret
-
-.pokemon_card
- ld a, [wLoadedCard1Stage]
- or a
- jr nz, .evolution_card
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- cp MAX_PLAY_AREA_POKEMON
- ccf
- ret
-
-.evolution_card
- bank1call IsPrehistoricPowerActive
- ret c
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- ld c, a
- ld b, 0
-.loop
- push bc
- ld e, b
- ldh a, [hTempCardIndex_ff9f]
- ld d, a
- call CheckIfCanEvolveInto
- pop bc
- ret nc
- inc b
- dec c
- jr nz, .loop
- scf
- ret
-
-.trainer_card
- bank1call CheckCantUseTrainerDueToHeadache
- ret c
- call LoadNonPokemonCardEffectCommands
- ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1
- call TryExecuteEffectCommandFunction
- ret
-
-; loads all the energy cards
-; in hand in wDuelTempList
-; return carry if no energy cards found
-CreateEnergyCardListFromHand: ; 1438c (5:438c)
- push hl
- push de
- push bc
- ld de, wDuelTempList
- ld b, a
- ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND
- call GetTurnDuelistVariable
- ld c, a
- inc c
- ld l, LOW(wOpponentHand)
- jr .decrease
-
-.loop
- ld a, [hli]
- push de
- call GetCardIDFromDeckIndex
- call GetCardType
- pop de
- and TYPE_ENERGY
- jr z, .decrease
- dec hl
- ld a, [hli]
- ld [de], a
- inc de
-.decrease
- dec c
- jr nz, .loop
-
- ld a, $ff
- ld [de], a
- pop bc
- pop de
- pop hl
- ld a, [wDuelTempList]
- cp $ff
- ccf
- ret
-
-; looks for card ID in hand and
-; sets carry if a card wasn't found
-; as opposed to LookForCardIDInHandList_Bank5
-; this function doesn't create a list
-; and preserves hl, de and bc
-; input:
-; a = card ID
-; output:
-; a = card deck index, if found
-; carry set if NOT found
-LookForCardIDInHand: ; 143bf (5:43bf)
- push hl
- push de
- push bc
- ld b, a
- ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND
- call GetTurnDuelistVariable
- ld c, a
- inc c
- ld l, DUELVARS_HAND
- jr .next
-
-.loop
- ld a, [hli]
- call GetCardIDFromDeckIndex
- ld a, e
- cp b
- jr z, .no_carry
-.next
- dec c
- jr nz, .loop
-
- pop bc
- pop de
- pop hl
- scf
- ret
-
-.no_carry
- dec hl
- ld a, [hl]
- pop bc
- pop de
- pop hl
- or a
- ret
-
-INCLUDE "engine/ai/damage_calculation.asm"
-
-AIProcessHandTrainerCards: ; 14663 (5:4663)
- farcall _AIProcessHandTrainerCards
- ret
-
-INCLUDE "engine/ai/deck_ai.asm"
-
-; return carry if card ID loaded in a is found in hand
-; and outputs in a the deck index of that card
-; as opposed to LookForCardIDInHand, this function
-; creates a list in wDuelTempList
-; input:
-; a = card ID
-; output:
-; a = card deck index, if found
-; carry set if found
-LookForCardIDInHandList_Bank5: ; 155d2 (5:55d2)
- ld [wTempCardIDToLook], a
- call CreateHandCardList
- ld hl, wDuelTempList
-
-.loop
- ld a, [hli]
- cp $ff
- ret z
- ldh [hTempCardIndex_ff98], a
- call LoadCardDataToBuffer1_FromDeckIndex
- ld b, a
- ld a, [wTempCardIDToLook]
- cp b
- jr nz, .loop
-
- ldh a, [hTempCardIndex_ff98]
- scf
- ret
-
-; returns carry if card ID in a
-; is found in Play Area, starting with
-; location in b
-; input:
-; a = card ID
-; b = PLAY_AREA_* to start with
-; output:
-; a = PLAY_AREA_* of found card
-; carry set if found
-LookForCardIDInPlayArea_Bank5: ; 155ef (5:55ef)
- ld [wTempCardIDToLook], a
-
-.loop
- ld a, DUELVARS_ARENA_CARD
- add b
- call GetTurnDuelistVariable
- cp $ff
- ret z
- call LoadCardDataToBuffer1_FromDeckIndex
- ld c, a
- ld a, [wTempCardIDToLook]
- cp c
- jr z, .found
- inc b
- ld a, MAX_PLAY_AREA_POKEMON
- cp b
- jr nz, .loop
-
- ld b, $ff
- or a
- ret
-.found
- ld a, b
- scf
- ret
-
-; check if energy card ID in e is in AI hand and,
-; if so, attaches it to card ID in d in Play Area.
-; input:
-; e = Energy card ID
-; d = Pokemon card ID
-AIAttachEnergyInHandToCardInPlayArea: ; 15612 (5:5612)
- ld a, e
- push de
- call LookForCardIDInHandList_Bank5
- pop de
- ret nc ; not in hand
- ld b, PLAY_AREA_ARENA
-
-.attach
- ld e, a
- ld a, d
- call LookForCardIDInPlayArea_Bank5
- ldh [hTempPlayAreaLocation_ffa1], a
- ld a, e
- ldh [hTemp_ffa0], a
- ld a, OPPACTION_PLAY_ENERGY
- bank1call AIMakeDecision
- ret
-
-; same as AIAttachEnergyInHandToCardInPlayArea but
-; only look for card ID in the Bench.
-AIAttachEnergyInHandToCardInBench: ; 1562b (5:562b)
- ld a, e
- push de
- call LookForCardIDInHandList_Bank5
- pop de
- ret nc
- ld b, PLAY_AREA_BENCH_1
- jr AIAttachEnergyInHandToCardInPlayArea.attach
-
-INCLUDE "engine/ai/init.asm"
-
-; load selected attack from Pokémon in hTempPlayAreaLocation_ff9d,
-; gets an energy card to discard and subsequently
-; check if there is enough energy to execute the selected attack
-; after removing that attached energy card.
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of Pokémon card
-; [wSelectedAttack] = selected attack to examine
-; output:
-; b = basic energy still needed
-; c = colorless energy still needed
-; e = output of ConvertColorToEnergyCardID, or $0 if not an attack
-; carry set if no attack
-; OR if it's a Pokémon Power
-; OR if not enough energy for attack
-CheckEnergyNeededForAttackAfterDiscard: ; 156c3 (5:56c3)
- ldh a, [hTempPlayAreaLocation_ff9d]
- add DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld hl, wLoadedAttackName
- ld a, [hli]
- or [hl]
- jr z, .no_attack
- ld a, [wLoadedAttackCategory]
- cp POKEMON_POWER
- jr nz, .is_attack
-.no_attack
- lb bc, 0, 0
- ld e, c
- scf
- ret
-
-.is_attack
- ldh a, [hTempPlayAreaLocation_ff9d]
- farcall AIPickEnergyCardToDiscard
- call LoadCardDataToBuffer1_FromDeckIndex
- cp DOUBLE_COLORLESS_ENERGY
- jr z, .colorless
-
-; color energy
-; decrease respective attached energy by 1.
- ld hl, wAttachedEnergies
- dec a
- ld c, a
- ld b, $00
- add hl, bc
- dec [hl]
- ld hl, wTotalAttachedEnergies
- dec [hl]
- jr .asm_1570c
-; decrease attached colorless by 2.
-.colorless
- ld hl, wAttachedEnergies + COLORLESS
- dec [hl]
- dec [hl]
- ld hl, wTotalAttachedEnergies
- dec [hl]
- dec [hl]
-
-.asm_1570c
- bank1call HandleEnergyBurn
- xor a
- ld [wTempLoadedAttackEnergyCost], a
- ld [wTempLoadedAttackEnergyNeededAmount], a
- ld [wTempLoadedAttackEnergyNeededType], a
- ld hl, wAttachedEnergies
- ld de, wLoadedAttackEnergyCost
- ld b, 0
- ld c, (NUM_TYPES / 2) - 1
-.loop
- ; check all basic energy cards except colorless
- ld a, [de]
- swap a
- call CheckIfEnoughParticularAttachedEnergy
- ld a, [de]
- call CheckIfEnoughParticularAttachedEnergy
- inc de
- dec c
- jr nz, .loop
-
- ld a, [de]
- swap a
- and $0f
- ld b, a ; colorless energy still needed
- ld a, [wTempLoadedAttackEnergyCost]
- ld hl, wTempLoadedAttackEnergyNeededAmount
- sub [hl]
- ld c, a ; basic energy still needed
- ld a, [wTotalAttachedEnergies]
- sub c
- sub b
- jr c, .not_enough_energy
-
- ld a, [wTempLoadedAttackEnergyNeededAmount]
- or a
- ret z
-
-; being here means the energy cost isn't satisfied,
-; including with colorless energy
- xor a
-.not_enough_energy
- cpl
- inc a
- ld c, a ; colorless energy still needed
- ld a, [wTempLoadedAttackEnergyNeededAmount]
- ld b, a ; basic energy still needed
- ld a, [wTempLoadedAttackEnergyNeededType]
- call ConvertColorToEnergyCardID
- ld e, a
- ld d, 0
- scf
- ret
-
-; zeroes a bytes starting at hl
-ClearMemory_Bank5: ; 1575e (5:575e)
- push af
- push bc
- push hl
- ld b, a
- xor a
-.clear_loop
- ld [hli], a
- dec b
- jr nz, .clear_loop
- pop hl
- pop bc
- pop af
- ret
-
-; returns in a the tens digit of value in a
-CalculateByteTensDigit: ; 1576b (5:576b)
- push bc
- ld c, 0
-.loop
- sub 10
- jr c, .done
- inc c
- jr .loop
-.done
- ld a, c
- pop bc
- ret
-
-; returns in a the result of
-; dividing b by a, rounded down
-; input:
-; a = divisor
-; b = dividend
-CalculateBDividedByA_Bank5: ; 15778 (5:5778)
- push bc
- ld c, a
- ld a, b
- ld b, c
- ld c, 0
-.loop
- sub b
- jr c, .done
- inc c
- jr .loop
-.done
- ld a, c
- pop bc
- ret
-
-; returns in a the number of energy cards attached
-; to Pokémon in location held by e
-; this assumes that colorless are paired so
-; that one colorless energy card provides 2 colorless energy
-; input:
-; e = location to check, i.e. PLAY_AREA_*
-; output:
-; a = number of energy cards attached
-CountNumberOfEnergyCardsAttached: ; 15787 (5:5787)
- call GetPlayAreaCardAttachedEnergies
- ld a, [wTotalAttachedEnergies]
- or a
- ret z
-
- xor a
- push hl
- push bc
- ld b, NUM_COLORED_TYPES
- ld hl, wAttachedEnergies
-; sum all the attached energies
-.loop
- add [hl]
- inc hl
- dec b
- jr nz, .loop
-
- ld b, [hl]
- srl b
-; counts colorless ad halves it
- add b
- pop bc
- pop hl
- ret
-
-; returns carry if any card with ID in e is found
-; in card location in a
-; input:
-; a = card location to look in;
-; e = card ID to look for.
-; output:
-; a = deck index of card found, if any
-CheckIfAnyCardIDinLocation: ; 157a3 (5:57a3)
- ld b, a
- ld c, e
- lb de, 0, 0
-.loop
- ld a, DUELVARS_CARD_LOCATIONS
- add e
- call GetTurnDuelistVariable
- cp b
- jr nz, .next
- ld a, e
- push de
- call GetCardIDFromDeckIndex
- ld a, e
- pop de
- cp c
- jr z, .set_carry
-.next
- inc e
- ld a, DECK_SIZE
- cp e
- jr nz, .loop
- or a
- ret
-.set_carry
- ld a, e
- scf
- ret
-
-; counts total number of energy cards in opponent's hand
-; plus all the cards attached in Turn Duelist's Play Area.
-; output:
-; a and wTempAI = total number of energy cards.
-CountOppEnergyCardsInHandAndAttached: ; 157c6 (5:57c6)
- xor a
- ld [wTempAI], a
- call CreateEnergyCardListFromHand
- jr c, .attached
-
-; counts number of energy cards in hand
- ld b, -1
- ld hl, wDuelTempList
-.loop_hand
- inc b
- ld a, [hli]
- cp $ff
- jr nz, .loop_hand
- ld a, b
- ld [wTempAI], a
-
-; counts number of energy cards
-; that are attached in Play Area
-.attached
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- ld d, a
- ld e, PLAY_AREA_ARENA
-.loop_play_area
- call CountNumberOfEnergyCardsAttached
- ld hl, wTempAI
- add [hl]
- ld [hl], a
- inc e
- dec d
- jr nz, .loop_play_area
- ret
-
-; returns carry if any card with ID in e is found
-; in the list that is pointed by hl.
-; if one is found, it is removed from the list.
-; input:
-; e = card ID to look for.
-; hl = list to look in
-RemoveCardIDInList: ; 157f3 (5:57f3)
- push hl
- push de
- push bc
- ld c, e
-
-.loop_1
- ld a, [hli]
- cp $ff
- jr z, .no_carry
-
- ldh [hTempCardIndex_ff98], a
- call GetCardIDFromDeckIndex
- ld a, c
- cp e
- jr nz, .loop_1
-
-; found
- ld d, h
- ld e, l
- dec hl
-
-; remove this index from the list
-; and reposition the rest of the list ahead.
-.loop_2
- ld a, [de]
- inc de
- ld [hli], a
- cp $ff
- jr nz, .loop_2
-
- ldh a, [hTempCardIndex_ff98]
- pop bc
- pop de
- pop hl
- scf
- ret
-
-.no_carry
- pop bc
- pop de
- pop hl
- or a
- ret
-
-; play Pokemon cards from the hand to set the starting
-; Play Area of Boss decks.
-; each Boss deck has two ID lists in order of preference.
-; one list is for the Arena card is the other is for the Bench cards.
-; if Arena card could not be set (due to hand not having any card in its list)
-; or if list is null, return carry and do not play any cards.
-TrySetUpBossStartingPlayArea: ; 1581b (5:581b)
- ld de, wAICardListArenaPriority
- ld a, d
- or a
- jr z, .set_carry ; return if null
-
-; pick Arena card
- call CreateHandCardList
- ld hl, wDuelTempList
- ld de, wAICardListArenaPriority
- call .PlayPokemonCardInOrder
- ret c
-
-; play Pokemon cards to Bench until there are
-; a maximum of 3 cards in Play Area.
-.loop
- ld de, wAICardListBenchPriority
- call .PlayPokemonCardInOrder
- jr c, .done
- cp 3
- jr c, .loop
-
-.done
- or a
- ret
-.set_carry
- scf
- ret
-
-; runs through input card ID list in de.
-; plays to Play Area first card that is found in hand.
-; returns carry if none of the cards in the list are found.
-; returns number of Pokemon in Play Area in a.
-.PlayPokemonCardInOrder ; 1583f (5:583f)
- ld a, [de]
- ld c, a
- inc de
- ld a, [de]
- ld d, a
- ld e, c
-
-; go in order of the list in de and
-; add first card that matches ID.
-; returns carry if hand doesn't have any card in list.
-.loop_id_list
- ld a, [de]
- inc de
- or a
- jr z, .not_found
- push de
- ld e, a
- call RemoveCardIDInList
- pop de
- jr nc, .loop_id_list
-
- ; play this card to Play Area and return
- push hl
- call PutHandPokemonCardInPlayArea
- pop hl
- or a
- ret
-
-.not_found
- scf
- ret
-
-; expects a $00-terminated list of 3-byte data with the following:
-; - non-zero value (anything but $1 is ignored)
-; - card ID to look for in Play Area
-; - number of energy cards
-; returns carry if a card ID is found in bench with at least the
-; listed number of energy cards
-; unreferenced
-Func_1585b: ; 1585b (5:585b)
- ld a, [hli]
- or a
- jr z, .no_carry
- dec a
- jr nz, .next_1
- ld a, [hli]
- ld b, PLAY_AREA_BENCH_1
- push hl
- call LookForCardIDInPlayArea_Bank5
- jr nc, .next_2
- ld e, a
- push de
- call CountNumberOfEnergyCardsAttached
- pop de
- pop hl
- ld b, [hl]
- cp b
- jr nc, .set_carry
- inc hl
- jr Func_1585b
-
-.next_1
- inc hl
- inc hl
- jr Func_1585b
-
-.next_2
- pop hl
- inc hl
- jr Func_1585b
-
-.no_carry
- or a
- ret
-
-.set_carry
- ld a, e
- scf
- ret
-
-; expects a $00-terminated list of 3-byte data with the following:
-; - non-zero value
-; - card ID
-; - number of energy cards
-; goes through the given list and if a card with a listed ID is found
-; with less than the number of energy cards corresponding to its entry
-; then have AI try to play an energy card from the hand to it
-; unreferenced
-Func_15886: ; 15886 (5:5886)
- push hl
- call CreateEnergyCardListFromHand
- pop hl
- ret c ; quit if no energy cards in hand
-
-.loop_energy_cards
- ld a, [hli]
- or a
- ret z ; done
- ld a, [hli]
- ld b, PLAY_AREA_ARENA
- push hl
- call LookForCardIDInPlayArea_Bank5
- jr nc, .next ; skip if not found in Play Area
- ld e, a
- push de
- call CountNumberOfEnergyCardsAttached
- pop de
- pop hl
- cp [hl]
- inc hl
- jr nc, .loop_energy_cards
- ld a, e
- ldh [hTempPlayAreaLocation_ff9d], a
- push hl
- call AITryToPlayEnergyCard
- pop hl
- ret c
- jr .loop_energy_cards
-.next
- pop hl
- inc hl
- jr .loop_energy_cards
-
-INCLUDE "engine/ai/retreat.asm"
-
-; Copy cards from wDuelTempList in hl to wHandTempList in de
-CopyHandCardList: ; 15ea6 (5:5ea6)
- ld a, [hli]
- ld [de], a
- cp $ff
- ret z
- inc de
- jr CopyHandCardList
-
-INCLUDE "engine/ai/hand_pokemon.asm"
-
-; check if player's active Pokémon is Mr Mime
-; if it isn't, set carry
-; if it is, check if Pokémon at a
-; can damage it, and if it can, set carry
-; input:
-; a = location of Pokémon card
-CheckDamageToMrMime: ; 16270 (5:6270)
- push af
- ld a, DUELVARS_ARENA_CARD
- call GetNonTurnDuelistVariable
- call SwapTurn
- call GetCardIDFromDeckIndex
- call SwapTurn
- ld a, e
- cp MR_MIME
- pop bc
- jr nz, .set_carry
- ld a, b
- call CheckIfCanDamageDefendingPokemon
- jr c, .set_carry
- or a
- ret
-.set_carry
- scf
- ret
-
-; returns carry if arena card
-; can knock out defending Pokémon
-CheckIfActiveCardCanKnockOut: ; 1628f (5:628f)
- xor a
- ldh [hTempPlayAreaLocation_ff9d], a
- call CheckIfAnyAttackKnocksOutDefendingCard
- jr nc, .fail
- call CheckIfSelectedAttackIsUnusable
- jp c, .fail
- scf
- ret
-
-.fail
- or a
- ret
-
-; outputs carry if any of the active Pokémon attacks
-; can be used and are not residual
-CheckIfActivePokemonCanUseAnyNonResidualAttack: ; 162a1 (5:62a1)
- xor a ; active card
- ldh [hTempPlayAreaLocation_ff9d], a
-; first atk
- ld [wSelectedAttack], a
- call CheckIfSelectedAttackIsUnusable
- jr c, .next_atk
- ld a, [wLoadedAttackCategory]
- and RESIDUAL
- jr z, .ok
-
-.next_atk
-; second atk
- ld a, $01
- ld [wSelectedAttack], a
- call CheckIfSelectedAttackIsUnusable
- jr c, .fail
- ld a, [wLoadedAttackCategory]
- and RESIDUAL
- jr z, .ok
-.fail
- or a
- ret
-
-.ok
- scf
- ret
-
-; looks for energy card(s) in hand depending on
-; what is needed for selected card, for both attacks
-; - if one basic energy is required, look for that energy;
-; - if one colorless is required, create a list at wDuelTempList
-; of all energy cards;
-; - if two colorless are required, look for double colorless;
-; return carry if successful in finding card
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of Pokémon card
-LookForEnergyNeededInHand: ; 162c8 (5:62c8)
- xor a ; first attack
- ld [wSelectedAttack], a
- call CheckEnergyNeededForAttack
- ld a, b
- add c
- cp 1
- jr z, .one_energy
- cp 2
- jr nz, .second_attack
- ld a, c
- cp 2
- jr z, .two_colorless
-
-.second_attack
- ld a, SECOND_ATTACK
- ld [wSelectedAttack], a
- call CheckEnergyNeededForAttack
- ld a, b
- add c
- cp 1
- jr z, .one_energy
- cp 2
- jr nz, .no_carry
- ld a, c
- cp 2
- jr z, .two_colorless
-.no_carry
- or a
- ret
-
-.one_energy
- ld a, b
- or a
- jr z, .one_colorless
- ld a, e
- call LookForCardIDInHandList_Bank5
- ret c
- jr .no_carry
-
-.one_colorless
- call CreateEnergyCardListFromHand
- jr c, .no_carry
- scf
- ret
-
-.two_colorless
- ld a, DOUBLE_COLORLESS_ENERGY
- call LookForCardIDInHandList_Bank5
- ret c
- jr .no_carry
-
-; looks for energy card(s) in hand depending on
-; what is needed for selected card and attack
-; - if one basic energy is required, look for that energy;
-; - if one colorless is required, create a list at wDuelTempList
-; of all energy cards;
-; - if two colorless are required, look for double colorless;
-; return carry if successful in finding card
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of Pokémon card
-; [wSelectedAttack] = selected attack to examine
-LookForEnergyNeededForAttackInHand: ; 16311 (5:6311)
- call CheckEnergyNeededForAttack
- ld a, b
- add c
- cp 1
- jr z, .one_energy
- cp 2
- jr nz, .done
- ld a, c
- cp 2
- jr z, .two_colorless
-.done
- or a
- ret
-
-.one_energy
- ld a, b
- or a
- jr z, .one_colorless
- ld a, e
- call LookForCardIDInHandList_Bank5
- ret c
- jr .done
-
-.one_colorless
- call CreateEnergyCardListFromHand
- jr c, .done
- scf
- ret
-
-.two_colorless
- ld a, DOUBLE_COLORLESS_ENERGY
- call LookForCardIDInHandList_Bank5
- ret c
- jr .done
-
-; goes through $00 terminated list pointed
-; by wAICardListPlayFromHandPriority and compares it to each card in hand.
-; Sorts the hand in wDuelTempList so that the found card IDs
-; are in the same order as the list pointed by de.
-SortTempHandByIDList: ; 1633f (5:633f)
- ld a, [wAICardListPlayFromHandPriority+1]
- or a
- ret z ; return if list is empty
-
-; start going down the ID list
- ld d, a
- ld a, [wAICardListPlayFromHandPriority]
- ld e, a
- ld c, 0
-.loop_list_id
-; get this item's ID
-; if $00, list has ended
- ld a, [de]
- or a
- ret z ; return when list is over
- inc de
- ld hl, wDuelTempList
- ld b, 0
- add hl, bc
- ld b, a
-
-; search in the hand card list
-.next_hand_card
- ld a, [hl]
- ldh [hTempCardIndex_ff98], a
- cp -1
- jr z, .loop_list_id
- push bc
- push de
- call GetCardIDFromDeckIndex
- ld a, e
- pop de
- pop bc
- cp b
- jr nz, .not_same
-
-; found
-; swap this hand card with the spot
-; in hand corresponding to c
- push bc
- push hl
- ld b, 0
- ld hl, wDuelTempList
- add hl, bc
- ld b, [hl]
- ldh a, [hTempCardIndex_ff98]
- ld [hl], a
- pop hl
- ld [hl], b
- pop bc
- inc c
-.not_same
- inc hl
- jr .next_hand_card
-
-; looks for energy card(s) in list at wDuelTempList
-; depending on energy flags set in a
-; return carry if successful in finding card
-; input:
-; a = energy flags needed
-CheckEnergyFlagsNeededInList: ; 1637b (5:637b)
- ld e, a
- ld hl, wDuelTempList
-.next_card
- ld a, [hli]
- cp $ff
- jr z, .no_carry
- push de
- call GetCardIDFromDeckIndex
- ld a, e
- pop de
-
-; fire
- cp FIRE_ENERGY
- jr nz, .grass
- ld a, FIRE_F
- jr .check_energy
-.grass
- cp GRASS_ENERGY
- jr nz, .lightning
- ld a, GRASS_F
- jr .check_energy
-.lightning
- cp LIGHTNING_ENERGY
- jr nz, .water
- ld a, LIGHTNING_F
- jr .check_energy
-.water
- cp WATER_ENERGY
- jr nz, .fighting
- ld a, WATER_F
- jr .check_energy
-.fighting
- cp FIGHTING_ENERGY
- jr nz, .psychic
- ld a, FIGHTING_F
- jr .check_energy
-.psychic
- cp PSYCHIC_ENERGY
- jr nz, .colorless
- ld a, PSYCHIC_F
- jr .check_energy
-.colorless
- cp DOUBLE_COLORLESS_ENERGY
- jr nz, .next_card
- ld a, COLORLESS_F
-
-; if energy card matches required energy, return carry
-.check_energy
- ld d, e
- and e
- ld e, d
- jr z, .next_card
- scf
- ret
-.no_carry
- or a
- ret
-
-; returns in a the energy cost of both attacks from card index in a
-; represented by energy flags
-; i.e. each bit represents a different energy type cost
-; if any colorless energy is required, all bits are set
-; input:
-; a = card index
-; output:
-; a = bits of each energy requirement
-GetAttacksEnergyCostBits: ; 163c9 (5:63c9)
- call LoadCardDataToBuffer2_FromDeckIndex
- ld hl, wLoadedCard2Atk1EnergyCost
- call GetEnergyCostBits
- ld b, a
-
- push bc
- ld hl, wLoadedCard2Atk2EnergyCost
- call GetEnergyCostBits
- pop bc
- or b
- ret
-
-; returns in a the energy cost of an attack in [hl]
-; represented by energy flags
-; i.e. each bit represents a different energy type cost
-; if any colorless energy is required, all bits are set
-; input:
-; [hl] = Loaded card attack energy cost
-; output:
-; a = bits of each energy requirement
-GetEnergyCostBits: ; 163dd (5:63dd)
- ld c, $00
- ld a, [hli]
- ld b, a
-
-; fire
- and $f0
- jr z, .grass
- ld c, FIRE_F
-.grass
- ld a, b
- and $0f
- jr z, .lightning
- ld a, GRASS_F
- or c
- ld c, a
-.lightning
- ld a, [hli]
- ld b, a
- and $f0
- jr z, .water
- ld a, LIGHTNING_F
- or c
- ld c, a
-.water
- ld a, b
- and $0f
- jr z, .fighting
- ld a, WATER_F
- or c
- ld c, a
-.fighting
- ld a, [hli]
- ld b, a
- and $f0
- jr z, .psychic
- ld a, FIGHTING_F
- or c
- ld c, a
-.psychic
- ld a, b
- and $0f
- jr z, .colorless
- ld a, PSYCHIC_F
- or c
- ld c, a
-.colorless
- ld a, [hli]
- ld b, a
- and $f0
- jr z, .done
- ld a, %11111111
- or c ; unnecessary
- ld c, a
-.done
- ld a, c
- ret
-
-; set carry flag if any card in
-; wDuelTempList evolves card index in a
-; if found, the evolution card index is returned in a
-; input:
-; a = card index to check evolution
-; output:
-; a = card index of evolution found
-CheckForEvolutionInList: ; 16422 (5:6422)
- ld b, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
-
- push af
- ld [hl], b
- ld hl, wDuelTempList
-.loop
- ld a, [hli]
- cp $ff
- jr z, .no_carry
- ld d, a
- ld e, PLAY_AREA_ARENA
- push de
- push hl
- call CheckIfCanEvolveInto
- pop hl
- pop de
- jr c, .loop
-
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- ld a, d
- scf
- ret
-
-.no_carry
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- or a
- ret
-
-; set carry if it finds an evolution for
-; the card index in a in the deck
-; if found, return that evolution card index in a
-; input:
-; a = card index to check evolution
-; output:
-; a = card index of evolution found
-CheckForEvolutionInDeck: ; 16451 (5:6451)
- ld b, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
-
- push af
- ld [hl], b
- ld e, 0
-.loop
- ld a, DUELVARS_CARD_LOCATIONS
- add e
- call GetTurnDuelistVariable
- cp CARD_LOCATION_DECK
- jr nz, .not_in_deck
- push de
- ld d, e
- ld e, PLAY_AREA_ARENA
- call CheckIfCanEvolveInto
- pop de
- jr nc, .set_carry
-
-; exit when it gets to the prize cards
-.not_in_deck
- inc e
- ld a, DUELVARS_PRIZE_CARDS
- cp e
- jr nz, .loop
-
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- or a
- ret
-
-.set_carry
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- ld a, e
- scf
- ret
-
-INCLUDE "engine/ai/energy.asm"
-
-INCLUDE "engine/ai/attacks.asm"
-
-INCLUDE "engine/ai/special_attacks.asm"
-
-; checks in other Play Area for non-basic cards.
-; afterwards, that card is checked for damage,
-; and if the damage counters it has is greater than or equal
-; to the max HP of the card stage below it,
-; return carry and that card's Play Area location in a.
-; output:
-; a = card location of Pokémon card, if found;
-; carry set if such a card is found.
-LookForCardThatIsKnockedOutOnDevolution: ; 17080 (5:7080)
- ldh a, [hTempPlayAreaLocation_ff9d]
- push af
- call SwapTurn
- ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA
- call GetTurnDuelistVariable
- ld b, a
- ld c, PLAY_AREA_ARENA
-
-.loop
- ld a, c
- ldh [hTempPlayAreaLocation_ff9d], a
- push bc
- bank1call GetCardOneStageBelow
- pop bc
- jr c, .next
- ; is not a basic card
- ; compare its HP with current damage
- ld a, d
- push bc
- call LoadCardDataToBuffer2_FromDeckIndex
- pop bc
- ld a, [wLoadedCard2HP]
- ld [wTempAI], a
- ld e, c
- push bc
- call GetCardDamageAndMaxHP
- pop bc
- ld e, a
- ld a, [wTempAI]
- cp e
- jr c, .set_carry
- jr z, .set_carry
-.next
- inc c
- ld a, c
- cp b
- jr nz, .loop
-
- call SwapTurn
- pop af
- ldh [hTempPlayAreaLocation_ff9d], a
- or a
- ret
-
-.set_carry
- call SwapTurn
- pop af
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, c
- scf
- ret
-
-; returns carry if the following conditions are met:
-; - arena card HP >= half max HP
-; - arena card Unknown2's 4 bit is not set or
-; is set but there's no evolution of card in hand/deck
-; - arena card can use second attack
-CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondAttack: ; 170c9 (5:70c9)
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- push de
- call LoadCardDataToBuffer1_FromDeckIndex
- ld a, DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wLoadedCard1HP]
- rrca
- cp d
- pop de
- jr nc, .no_carry
-
- ld a, [wLoadedCard1Unknown2]
- and %00010000
- jr z, .check_second_attack
- ld a, d
- call CheckCardEvolutionInHandOrDeck
- jr c, .no_carry
-
-.check_second_attack
- xor a ; active card
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, SECOND_ATTACK
- ld [wSelectedAttack], a
- push hl
- call CheckIfSelectedAttackIsUnusable
- pop hl
- jr c, .no_carry
- scf
- ret
-.no_carry
- or a
- ret
-
-; count Pokemon in the Bench that
-; meet the following conditions:
-; - card HP > half max HP
-; - card Unknown2's 4 bit is not set or
-; is set but there's no evolution of card in hand/deck
-; - card can use second attack
-; Outputs the number of Pokémon in bench
-; that meet these requirements in a
-; and returns carry if at least one is found
-CountNumberOfSetUpBenchPokemon: ; 17101 (5:7101)
- ldh a, [hTempPlayAreaLocation_ff9d]
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- push de
- ld a, DUELVARS_BENCH
- call GetTurnDuelistVariable
- lb bc, 0, 0
- push hl
-
-.next
- inc c
- pop hl
- ld a, [hli]
- push hl
- cp $ff
- jr z, .done
-
- ld d, a
- push de
- push bc
- call LoadCardDataToBuffer1_FromDeckIndex
- pop bc
-
-; compares card's current HP with max HP
- ld a, c
- add DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wLoadedCard1HP]
- rrca
-
-; a = max HP / 2
-; d = current HP
-; jumps if (current HP) <= (max HP / 2)
- cp d
- pop de
- jr nc, .next
-
- ld a, [wLoadedCard1Unknown2]
- and $10
- jr z, .check_second_attack
-
- ld a, d
- push bc
- call CheckCardEvolutionInHandOrDeck
- pop bc
- jr c, .next
-
-.check_second_attack
- ld a, c
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, SECOND_ATTACK
- ld [wSelectedAttack], a
- push bc
- push hl
- call CheckIfSelectedAttackIsUnusable
- pop hl
- pop bc
- jr c, .next
- inc b
- jr .next
-
-.done
- pop hl
- pop de
- ld a, e
- ld [wSelectedAttack], a
- ld a, d
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, b
- or a
- ret z
- scf
- ret
-
-; handles AI logic to determine some selections regarding certain attacks,
-; if any of these attacks were chosen to be used.
-; returns carry if selection was successful,
-; and no carry if unable to make one.
-; outputs in hTempPlayAreaLocation_ffa1 the chosen parameter.
-AISelectSpecialAttackParameters: ; 17161 (5:7161)
- ld a, [wSelectedAttack]
- push af
- call .SelectAttackParameters
- pop bc
- ld a, b
- ld [wSelectedAttack], a
- ret
-
-.SelectAttackParameters: ; 1716e (5:716e)
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- call GetCardIDFromDeckIndex
- ld a, e
- cp MEW3
- jr z, .DevolutionBeam
- cp MEWTWO3
- jr z, .EnergyAbsorption
- cp MEWTWO2
- jr z, .EnergyAbsorption
- cp EXEGGUTOR
- jr z, .Teleport
- cp ELECTRODE1
- jr z, .EnergySpike
- ; fallthrough
-
-.no_carry
- or a
- ret
-
-.DevolutionBeam
-; in case selected attack is Devolution Beam
-; store in hTempPlayAreaLocation_ffa1
-; the location of card to select to devolve
- ld a, [wSelectedAttack]
- or a
- jp z, .no_carry ; can be jr
-
- ld a, $01
- ldh [hTemp_ffa0], a
- call LookForCardThatIsKnockedOutOnDevolution
- ldh [hTempPlayAreaLocation_ffa1], a
-
-.set_carry_1
- scf
- ret
-
-.EnergyAbsorption
-; in case selected attack is Energy Absorption
-; make list from energy cards in Discard Pile
- ld a, [wSelectedAttack]
- or a
- jp nz, .no_carry ; can be jr
-
- ld a, $ff
- ldh [hTempPlayAreaLocation_ffa1], a
- ldh [hTempRetreatCostCards], a
-
-; search for Psychic energy cards in Discard Pile
- ld e, PSYCHIC_ENERGY
- ld a, CARD_LOCATION_DISCARD_PILE
- call CheckIfAnyCardIDinLocation
- ldh [hTemp_ffa0], a
- farcall CreateEnergyCardListFromDiscardPile_AllEnergy
-
-; find any energy card different from
-; the one found by CheckIfAnyCardIDinLocation.
-; since using this attack requires a Psychic energy card,
-; and another one is in hTemp_ffa0,
-; then any other energy card would account
-; for the Energy Cost of Psyburn.
- ld hl, wDuelTempList
-.loop_energy_cards
- ld a, [hli]
- cp $ff
- jr z, .set_carry_2
- ld b, a
- ldh a, [hTemp_ffa0]
- cp b
- jr z, .loop_energy_cards ; same card, keep looking
-
-; store the deck index of energy card found
- ld a, b
- ldh [hTempPlayAreaLocation_ffa1], a
- ; fallthrough
-
-.set_carry_2
- scf
- ret
-
-.Teleport
-; in case selected attack is Teleport
-; decide Bench card to switch to.
- ld a, [wSelectedAttack]
- or a
- jp nz, .no_carry ; can be jr
- call AIDecideBenchPokemonToSwitchTo
- jr c, .no_carry
- ldh [hTemp_ffa0], a
- scf
- ret
-
-.EnergySpike
-; in case selected attack is Energy Spike
-; decide basic energy card to fetch from Deck.
- ld a, [wSelectedAttack]
- or a
- jp z, .no_carry ; can be jr
-
- ld a, CARD_LOCATION_DECK
- ld e, LIGHTNING_ENERGY
-
-; if none were found in Deck, return carry...
- call CheckIfAnyCardIDinLocation
- ldh [hTemp_ffa0], a
- jp nc, .no_carry ; can be jr
-
-; ...else find a suitable Play Area Pokemon to
-; attach the energy card to.
- call AIProcessButDontPlayEnergy_SkipEvolution
- jp nc, .no_carry ; can be jr
- ldh a, [hTempPlayAreaLocation_ff9d]
- ldh [hTempPlayAreaLocation_ffa1], a
- scf
- ret
-
-; return carry if Pokémon at play area location
-; in hTempPlayAreaLocation_ff9d does not have
-; energy required for the attack index in wSelectedAttack
-; or has exactly the same amount of energy needed
-; input:
-; [hTempPlayAreaLocation_ff9d] = play area location
-; [wSelectedAttack] = attack index to check
-; output:
-; a = number of extra energy cards attached
-CheckIfNoSurplusEnergyForAttack: ; 171fb (5:71fb)
- ldh a, [hTempPlayAreaLocation_ff9d]
- add DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- call CopyAttackDataAndDamage_FromDeckIndex
- ld hl, wLoadedAttackName
- ld a, [hli]
- or [hl]
- jr z, .not_attack
- ld a, [wLoadedAttackCategory]
- cp POKEMON_POWER
- jr nz, .is_attack
-.not_attack
- scf
- ret
-
-.is_attack
- ldh a, [hTempPlayAreaLocation_ff9d]
- ld e, a
- call GetPlayAreaCardAttachedEnergies
- bank1call HandleEnergyBurn
- xor a
- ld [wTempLoadedAttackEnergyCost], a
- ld [wTempLoadedAttackEnergyNeededAmount], a
- ld [wTempLoadedAttackEnergyNeededType], a
- ld hl, wAttachedEnergies
- ld de, wLoadedAttackEnergyCost
- ld b, 0
- ld c, (NUM_TYPES / 2) - 1
-.loop
- ; check all basic energy cards except colorless
- ld a, [de]
- swap a
- call CalculateParticularAttachedEnergyNeeded
- ld a, [de]
- call CalculateParticularAttachedEnergyNeeded
- inc de
- dec c
- jr nz, .loop
-
- ; colorless
- ld a, [de]
- swap a
- and %00001111
- ld b, a
- ld hl, wTempLoadedAttackEnergyCost
- ld a, [wTotalAttachedEnergies]
- sub [hl]
- sub b
- ret c ; return if not enough energy
-
- or a
- ret nz ; return if surplus energy
-
- ; exactly the amount of energy needed
- scf
- ret
-
-; takes as input the energy cost of an attack for a
-; particular energy, stored in the lower nibble of a
-; if the attack costs some amount of this energy, the lower nibble of a != 0,
-; and this amount is stored in wTempLoadedAttackEnergyCost
-; also adds the amount of energy still needed
-; to wTempLoadedAttackEnergyNeededAmount
-; input:
-; a = this energy cost of attack (lower nibble)
-; [hl] = attached energy
-; output:
-; carry set if not enough of this energy type attached
-CalculateParticularAttachedEnergyNeeded: ; 17258 (5:7258)
- and %00001111
- jr nz, .check
-.done
- inc hl
- inc b
- ret
-
-.check
- ld [wTempLoadedAttackEnergyCost], a
- sub [hl]
- jr z, .done
- jr nc, .done
- push bc
- ld a, [wTempLoadedAttackEnergyCost]
- ld b, a
- ld a, [hl]
- sub b
- pop bc
- ld [wTempLoadedAttackEnergyNeededAmount], a
- jr .done
-
-; return carry if there is a card that
-; can evolve a Pokémon in hand or deck.
-; input:
-; a = deck index of card to check;
-; output:
-; a = deck index of evolution in hand, if found;
-; carry set if there's a card in hand that can evolve.
-CheckCardEvolutionInHandOrDeck: ; 17274 (5:7274)
- ld b, a
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- push af
- ld [hl], b
- ld e, 0
-
-.loop
- ld a, DUELVARS_CARD_LOCATIONS
- add e
- call GetTurnDuelistVariable
- cp CARD_LOCATION_DECK
- jr z, .deck_or_hand
- cp CARD_LOCATION_HAND
- jr nz, .next
-.deck_or_hand
- push de
- ld d, e
- ld e, PLAY_AREA_ARENA
- call CheckIfCanEvolveInto
- pop de
- jr nc, .set_carry
-.next
- inc e
- ld a, DECK_SIZE
- cp e
- jr nz, .loop
-
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- or a
- ret
-
-.set_carry
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- pop af
- ld [hl], a
- ld a, e
- scf
- ret
-
-INCLUDE "engine/ai/boss_deck_set_up.asm"
-
-; returns carry if Pokemon at PLAY_AREA* in a
-; can damage defending Pokémon with any of its attacks
-; input:
-; a = location of card to check
-CheckIfCanDamageDefendingPokemon: ; 17383 (5:7383)
- ldh [hTempPlayAreaLocation_ff9d], a
- xor a ; first attack
- ld [wSelectedAttack], a
- call CheckIfSelectedAttackIsUnusable
- jr c, .second_attack
- xor a
- call EstimateDamage_VersusDefendingCard
- ld a, [wDamage]
- or a
- jr nz, .set_carry
-
-.second_attack
- ld a, SECOND_ATTACK
- ld [wSelectedAttack], a
- call CheckIfSelectedAttackIsUnusable
- jr c, .no_carry
- ld a, $01
- call EstimateDamage_VersusDefendingCard
- ld a, [wDamage]
- or a
- jr nz, .set_carry
-
-.no_carry
- or a
- ret
-.set_carry
- scf
- ret
-
-; checks if defending Pokémon can knock out
-; card at hTempPlayAreaLocation_ff9d with any of its attacks
-; and if so, stores the damage to wce00 and wce01
-; sets carry if any on the attacks knocks out
-; also outputs the largest damage dealt in a
-; input:
-; [hTempPlayAreaLocation_ff9d] = location of card to check
-; output:
-; a = largest damage of both attacks
-; carry set if can knock out
-CheckIfDefendingPokemonCanKnockOut: ; 173b1 (5:73b1)
- xor a ; first attack
- ld [wce00], a
- ld [wce01], a
- call CheckIfDefendingPokemonCanKnockOutWithAttack
- jr nc, .second_attack
- ld a, [wDamage]
- ld [wce00], a
-
-.second_attack
- ld a, SECOND_ATTACK
- call CheckIfDefendingPokemonCanKnockOutWithAttack
- jr nc, .return_if_neither_kos
- ld a, [wDamage]
- ld [wce01], a
- jr .compare
-
-.return_if_neither_kos
- ld a, [wce00]
- or a
- ret z
-
-.compare
- ld a, [wce00]
- ld b, a
- ld a, [wce01]
- cp b
- jr nc, .set_carry
- ld a, b
-.set_carry
- scf
- ret
-
-; return carry if defending Pokémon can knock out
-; card at hTempPlayAreaLocation_ff9d
-; input:
-; a = attack index
-; [hTempPlayAreaLocation_ff9d] = location of card to check
-CheckIfDefendingPokemonCanKnockOutWithAttack: ; 173e4 (5:73e4)
- ld [wSelectedAttack], a
- ldh a, [hTempPlayAreaLocation_ff9d]
- push af
- xor a
- ldh [hTempPlayAreaLocation_ff9d], a
- call SwapTurn
- call CheckIfSelectedAttackIsUnusable
- call SwapTurn
- pop bc
- ld a, b
- ldh [hTempPlayAreaLocation_ff9d], a
- jr c, .done
-
-; player's active Pokémon can use attack
- ld a, [wSelectedAttack]
- call EstimateDamage_FromDefendingPokemon
- ldh a, [hTempPlayAreaLocation_ff9d]
- add DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- ld hl, wDamage
- sub [hl]
- jr z, .set_carry
- ret
-
-.set_carry
- scf
- ret
-
-.done
- or a
- ret
-
-; sets carry if Opponent's deck ID
-; is between LEGENDARY_MOLTRES_DECK_ID (inclusive)
-; and MUSCLES_FOR_BRAINS_DECK_ID (exclusive)
-; these are the decks for Grandmaster/Club Master/Ronald
-CheckIfOpponentHasBossDeckID: ; 17414 (5:7414)
- push af
- ld a, [wOpponentDeckID]
- cp LEGENDARY_MOLTRES_DECK_ID
- jr c, .no_carry
- cp MUSCLES_FOR_BRAINS_DECK_ID
- jr nc, .no_carry
- pop af
- scf
- ret
-
-.no_carry
- pop af
- or a
- ret
-
-; sets carry if not a boss fight
-; and if hasn't received legendary cards yet
-CheckIfNotABossDeckID: ; 17426 (5:7426)
- call EnableSRAM
- ld a, [sReceivedLegendaryCards]
- call DisableSRAM
- or a
- jr nz, .no_carry
- call CheckIfOpponentHasBossDeckID
- jr nc, .set_carry
-.no_carry
- or a
- ret
-
-.set_carry
- scf
- ret
-
-; probability to return carry:
-; - 50% if deck AI is playing is on the list;
-; - 25% for all other decks;
-; - 0% for boss decks.
-; used for certain decks to randomly choose
-; not to play Trainer card or use PKMN Power
-AIChooseRandomlyNotToDoAction: ; 1743b (5:743b)
-; boss decks always use Trainer cards.
- push hl
- push de
- call CheckIfNotABossDeckID
- jr c, .check_deck
- pop de
- pop hl
- ret
-
-.check_deck
- ld a, [wOpponentDeckID]
- cp MUSCLES_FOR_BRAINS_DECK_ID
- jr z, .carry_50_percent
- cp BLISTERING_POKEMON_DECK_ID
- jr z, .carry_50_percent
- cp WATERFRONT_POKEMON_DECK_ID
- jr z, .carry_50_percent
- cp BOOM_BOOM_SELFDESTRUCT_DECK_ID
- jr z, .carry_50_percent
- cp KALEIDOSCOPE_DECK_ID
- jr z, .carry_50_percent
- cp RESHUFFLE_DECK_ID
- jr z, .carry_50_percent
-
-; carry 25 percent
- ld a, 4
- call Random
- cp 1
- pop de
- pop hl
- ret
-
-.carry_50_percent
- ld a, 4
- call Random
- cp 2
- pop de
- pop hl
- ret
-
-; checks if any bench Pokémon has same ID
-; as input, and sets carry if it has more than
-; half health and can use its second attack
-; input:
-; a = card ID to check for
-; output:
-; carry set if the above requirements are met
-CheckForBenchIDAtHalfHPAndCanUseSecondAttack: ; 17474 (5:7474)
- ld [wcdf9], a
- ldh a, [hTempPlayAreaLocation_ff9d]
- ld d, a
- ld a, [wSelectedAttack]
- ld e, a
- push de
- ld a, DUELVARS_ARENA_CARD
- call GetTurnDuelistVariable
- lb bc, 0, PLAY_AREA_ARENA
- push hl
-
-.loop
- inc c
- pop hl
- ld a, [hli]
- push hl
- cp $ff
- jr z, .done
- ld d, a
- push de
- push bc
- call LoadCardDataToBuffer1_FromDeckIndex
- pop bc
- ld a, c
- add DUELVARS_ARENA_CARD_HP
- call GetTurnDuelistVariable
- ld d, a
- ld a, [wLoadedCard1HP]
- rrca
- cp d
- pop de
- jr nc, .loop
- ; half max HP < current HP
- ld a, [wLoadedCard1ID]
- ld hl, wcdf9
- cp [hl]
- jr nz, .loop
-
- ld a, c
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, SECOND_ATTACK
- ld [wSelectedAttack], a
- push bc
- call CheckIfSelectedAttackIsUnusable
- pop bc
- jr c, .loop
- inc b
-.done
- pop hl
- pop de
- ld a, e
- ld [wSelectedAttack], a
- ld a, d
- ldh [hTempPlayAreaLocation_ff9d], a
- ld a, b
- or a
- ret z
- scf
- ret
-
-; add 5 to wPlayAreaEnergyAIScore AI score corresponding to all cards
-; in bench that have same ID as register a
-; input:
-; a = card ID to look for
-RaiseAIScoreToAllMatchingIDsInBench: ; 174cd (5:74cd)
- ld d, a
- ld a, DUELVARS_BENCH
- call GetTurnDuelistVariable
- ld e, 0
-.loop
- inc e
- ld a, [hli]
- cp $ff
- ret z
- push de
- call GetCardIDFromDeckIndex
- ld a, e
- pop de
- cp d
- jr nz, .loop
- ld c, e
- ld b, $00
- push hl
- ld hl, wPlayAreaEnergyAIScore
- add hl, bc
- ld a, 5
- add [hl]
- ld [hl], a
- pop hl
- jr .loop
-
-; goes through each play area Pokémon, and
-; for all cards of the same ID, determine which
-; card has highest value calculated from Func_17583
-; the card with highest value gets increased wPlayAreaEnergyAIScore
-; while all others get decreased wPlayAreaEnergyAIScore
-Func_174f2: ; 174f2 (5:74f2)
- ld a, MAX_PLAY_AREA_POKEMON
- ld hl, wcdfa
- call ClearMemory_Bank5
- ld a, DUELVARS_BENCH
- call GetTurnDuelistVariable
- ld e, 0
-
-.loop_play_area
- push hl
- ld a, MAX_PLAY_AREA_POKEMON
- ld hl, wcdea
- call ClearMemory_Bank5
- pop hl
- inc e
- ld a, [hli]
- cp $ff
- ret z
-
- ld [wcdf9], a
- push de
- push hl
-
-; checks wcdfa + play area location in e
-; if != 0, go to next in play area
- ld d, $00
- ld hl, wcdfa
- add hl, de
- ld a, [hl]
- or a
- pop hl
- pop de
- jr nz, .loop_play_area
-
-; loads wcdf9 with card ID
-; and call Func_17583
- push de
- ld a, [wcdf9]
- call GetCardIDFromDeckIndex
- ld a, e
- ld [wcdf9], a
- pop de
- push hl
- push de
- call Func_17583
-
-; check play area Pokémon ahead
-; if there is a card with the same ID,
-; call Func_17583 for it as well
-.loop_1
- inc e
- ld a, [hli]
- cp $ff
- jr z, .check_if_repeated_id
- push de
- call GetCardIDFromDeckIndex
- ld a, [wcdf9]
- cp e
- pop de
- jr nz, .loop_1
- call Func_17583
- jr .loop_1
-
-; if there are more than 1 of the same ID
-; in play area, iterate bench backwards
-; and determines which card has highest
-; score in wcdea
-.check_if_repeated_id
- call Func_175a8
- jr c, .next
- lb bc, 0, 0
- ld hl, wcdea + MAX_BENCH_POKEMON
- ld d, MAX_PLAY_AREA_POKEMON
-.loop_2
- dec d
- jr z, .asm_17560
- ld a, [hld]
- cp b
- jr c, .loop_2
- ld b, a
- ld c, d
- jr .loop_2
-
-; c = play area location of highest score
-; decrease wPlayAreaEnergyAIScore score for all cards with same ID
-; except for the one with highest score
-; increase wPlayAreaEnergyAIScore score for card with highest ID
-.asm_17560
- ld hl, wPlayAreaEnergyAIScore
- ld de, wcdea
- ld b, PLAY_AREA_ARENA
-.loop_3
- ld a, c
- cp b
- jr z, .card_with_highest
- ld a, [de]
- or a
- jr z, .check_next
-; decrease score
- dec [hl]
- jr .check_next
-.card_with_highest
-; increase score
- inc [hl]
-.check_next
- inc b
- ld a, MAX_PLAY_AREA_POKEMON
- cp b
- jr z, .next
- inc de
- inc hl
- jr .loop_3
-
-.next
- pop de
- pop hl
- jp .loop_play_area
-
-; loads wcdea + play area location in e
-; with energy * 2 + $80 - floor(dam / 10)
-; loads wcdfa + play area location in e
-; with $01
-Func_17583: ; 17583 (5:7583)
- push hl
- push de
- call GetCardDamageAndMaxHP
- call CalculateByteTensDigit
- ld b, a
- push bc
- call CountNumberOfEnergyCardsAttached
- pop bc
- sla a
- add $80
- sub b
- pop de
- push de
- ld d, $00
- ld hl, wcdea
- add hl, de
- ld [hl], a
- ld hl, wcdfa
- add hl, de
- ld [hl], $01
- pop de
- pop hl
- ret
-
-; counts how many play area locations in wcdea
-; are != 0, and outputs result in a
-; also returns carry if result is < 2
-Func_175a8: ; 175a8 (5:75a8)
- ld hl, wcdea
- ld d, $00
- ld e, MAX_PLAY_AREA_POKEMON + 1
-.loop
- dec e
- jr z, .done
- ld a, [hli]
- or a
- jr z, .loop
- inc d
- jr .loop
-.done
- ld a, d
- cp 2
- ret
-
-; handle how AI scores giving out Energy Cards
-; when using Legendary Articuno deck
-HandleLegendaryArticunoEnergyScoring: ; 175bd (5:75bd)
- ld a, [wOpponentDeckID]
- cp LEGENDARY_ARTICUNO_DECK_ID
- jr z, .articuno_deck
- ret
-.articuno_deck
- call ScoreLegendaryArticunoCards
- ret