From e38d9f1de3abe1cdb54e7292ead677151348bd4e Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Sat, 25 Apr 2020 17:45:32 +0100 Subject: Terror Strike effect command and related routines --- src/data/effect_commands.asm | 6 +- src/engine/effect_functions.asm | 147 +++++++++++++++++++++++++++++++++++++++- src/engine/home.asm | 22 ++++-- src/text/text1.asm | 2 +- src/text/text_offsets.asm | 2 +- 5 files changed, 165 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/data/effect_commands.asm b/src/data/effect_commands.asm index 0e1886e..171c241 100644 --- a/src/data/effect_commands.asm +++ b/src/data/effect_commands.asm @@ -42,9 +42,9 @@ EkansWrapEffectCommands: db $00 ArbokTerrorStrikeEffectCommands: - dbw EFFECTCMDTYPE_AFTER_DAMAGE, $4726 - dbw EFFECTCMDTYPE_REQUIRE_SELECTION, $470a - dbw EFFECTCMDTYPE_SWITCH_DEFENDING_PKMN, $470a + dbw EFFECTCMDTYPE_AFTER_DAMAGE, TerrorStrike_SwitchDefendingPokemon + dbw EFFECTCMDTYPE_REQUIRE_SELECTION, TerrorStrike_50PercentSelectSwitchPokemon + dbw EFFECTCMDTYPE_SWITCH_DEFENDING_PKMN, TerrorStrike_50PercentSelectSwitchPokemon db $00 ArbokPoisonFangEffectCommands: diff --git a/src/engine/effect_functions.asm b/src/engine/effect_functions.asm index 116d545..8832134 100644 --- a/src/engine/effect_functions.asm +++ b/src/engine/effect_functions.asm @@ -301,7 +301,111 @@ Func_2c166: ; 2c166 (b:4166) ret ; 0x2c174 - INCROM $2c174, $2c6f0 + INCROM $2c174, $2c1ec + +HandleSwitchDefendingPokemonEffect: ; 2c1ec (b:41ec) + ld e, a + cp $ff + ret z + +; check Defending Pokemon's HP + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + or a + jr nz, .switch + +; if 0, handle Destiny Bond first + push de + bank1call HandleDestinyBondSubstatus + pop de + +.switch + call .HandleNoDamageOrEffect + ret c + +; attack was successful, switch Defending Pokemon + call SwapTurn + call SwapArenaWithBenchPokemon + call SwapTurn + + xor a + ld [wccc5], a + ld [wDuelDisplayedScreen], a + inc a + ld [wccef], a + ret +; 0x2c216 + +; returns carry if Defending has No Damage or Effect +; if so, print its appropriate text. +.HandleNoDamageOrEffect: ; 2c216 (b:4216) + call CheckNoDamageOrEffect + ret nc + ld a, l + or h + call nz, DrawWideTextBox_PrintText + scf + ret +; 0x2c221 + + INCROM $2c221, $2c487 + +; handles the selection of a forced switch +; by link/AI opponent or by the player. +; outputs the Play Area location of the chosen +; bench card in hTempPlayAreaLocation_ff9d. +DuelistSelectForcedSwitch: ; 2c487 (b:4487) + ld a, DUELVARS_DUELIST_TYPE + call GetNonTurnDuelistVariable + cp DUELIST_TYPE_LINK_OPP + jr z, .link_opp + + cp DUELIST_TYPE_PLAYER + jr z, .player + +; AI opponent + call SwapTurn + bank1call Func_2bc7 + call SwapTurn + + ld a, [wPlayerAttackingMoveIndex] + ld e, a + ld a, [wPlayerAttackingCardIndex] + ld d, a + ld a, [wPlayerAttackingCardID] + call CopyMoveDataAndDamage_FromCardID + call Func_16f6 + ret + +.player + ldtx hl, SelectPkmnOnBenchToSwitchWithActiveText + call DrawWideTextBox_WaitForInput + call SwapTurn + bank1call HasAlivePokemonInBench + ld a, $01 + ld [wcbd4], a +.asm_2c4c0 + bank1call OpenPlayAreaScreenForSelection + jr c, .asm_2c4c0 + call SwapTurn + ret + +.link_opp +; get selection from link opponent + ld a, OPPACTION_FORCE_SWITCH_ACTIVE + call SetOppAction_SerialSendDuelData +.loop + call SerialRecvByte + jr nc, .received + halt + nop + jr .loop +.received + ldh [hTempPlayAreaLocation_ff9d], a + ret +; 0x2c4da + + INCROM $2c4da, $2c6f0 SpitPoison_AIEffect: ; 2c6f0 (b:46f0) ld a, 5 @@ -320,7 +424,44 @@ SpitPoison_Poison50PercentEffect: ; 2c6f8 (b:46f8) ret ; 0x2c70a - INCROM $2c70a, $2c730 +; outputs in hTemp_ffa0 the result of the coin toss +; (0 = tails, 1 = heads) and, in case it was heads, +; stores in hTempPlayAreaLocation_ffa1 the location +; of the Bench Pokemon that was selected for switch. +TerrorStrike_50PercentSelectSwitchPokemon: ; 2c70a (b:470a) + xor a + ldh [hTemp_ffa0], a + +; return failure if no Pokemon to switch to + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + cp 2 + ret c + +; toss coin and store whether it was tails (0) +; or heads (1) in hTemp_ffa0 +; return if it was tails. + ldtx de, IfHeadsChangeOpponentsActivePokemonText + call Func_2c08a + ldh [hTemp_ffa0], a + ret nc + + call DuelistSelectForcedSwitch + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hTempPlayAreaLocation_ffa1], a + ret +; 0x2c726 + +; if coin toss was heads and it's possible, +; switch Defending Pokemon +TerrorStrike_SwitchDefendingPokemon: ; 2c726 (b:4726) + ldh a, [hTemp_ffa0] + or a + ret z + ldh a, [hTempPlayAreaLocation_ffa1] + call HandleSwitchDefendingPokemonEffect + ret +; 0x2c730 PoisonFang_AIEffect: ; 2c730 (b:4730) ld a, 10 @@ -538,4 +679,4 @@ Toxic_DoublePoisonEffect: ; 2c994 (b:4994) ret ; 0x2c998 - INCROM $2c998, $30000 + INCROM $2c998, $30000 \ No newline at end of file diff --git a/src/engine/home.asm b/src/engine/home.asm index 545995a..4f9fc31 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -8301,34 +8301,44 @@ Func_2bcf: ; 2bcf (0:2bcf) Func_2bd7: ; 2bd7 (0:2bd7) ld a, $5 - jr Func_2bdb + jr Func_2bdb ; this line is not needed Func_2bdb: ; 2bdb (0:2bdb) ld c, a + +; load bank for Opponent Deck pointer table ldh a, [hBankROM] push af ld a, BANK(PointerTable_14000) call BankswitchROM + +; load hl with the corresponding pointer ld a, [wOpponentDeckID] ld l, a ld h, $0 - add hl, hl + add hl, hl ; two bytes per deck ld de, PointerTable_14000 add hl, de ld a, [hli] ld h, [hl] ld l, a + ld a, c or a - jr nz, .asm_2bfe + jr nz, .not_zero + +; if input was 0, copy deck data of turn player ld e, [hl] inc hl ld d, [hl] call CopyDeckData - jr .asm_2c01 -.asm_2bfe + jr .done + +; jump to corresponding AI routine related to input +.not_zero call JumpToFunctionInTable -.asm_2c01 + +.done ld c, a pop af call BankswitchROM diff --git a/src/text/text1.asm b/src/text/text1.asm index 69f44f6..07d7a7a 100644 --- a/src/text/text1.asm +++ b/src/text/text1.asm @@ -1103,7 +1103,7 @@ Text00ea: ; 37e03 (d:7e03) line "Heads, damage to yours if Tails." done -Text00eb: ; 37e46 (d:7e46) +IfHeadsChangeOpponentsActivePokemonText: ; 37e46 (d:7e46) text "If Heads, change opponent's" line "Active Pokémon." done diff --git a/src/text/text_offsets.asm b/src/text/text_offsets.asm index 3149307..d027768 100644 --- a/src/text/text_offsets.asm +++ b/src/text/text_offsets.asm @@ -236,7 +236,7 @@ TextOffsets:: ; 34000 (d:40 textpointer Text00e8 ; 0x00e8 textpointer IfHeadPlus10IfTails10ToYourselfText ; 0x00e9 textpointer Text00ea ; 0x00ea - textpointer Text00eb ; 0x00eb + textpointer IfHeadsChangeOpponentsActivePokemonText ; 0x00eb textpointer Text00ec ; 0x00ec textpointer Text00ed ; 0x00ed textpointer Text00ee ; 0x00ee -- cgit v1.2.3 From 7d9ea8a30d19fae6a39bb36981e27db6edbea5e7 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Tue, 28 Apr 2020 20:20:20 +0100 Subject: AI routines and Energy Trans logic --- src/constants/duel_constants.asm | 41 ++- src/engine/bank01.asm | 1 + src/engine/bank05.asm | 589 +++++++++++++++++++++++++++------------ src/engine/bank08.asm | 447 ++++++++++++++++++++++++++++- src/engine/effect_functions.asm | 92 +++++- src/engine/home.asm | 2 +- src/hram.asm | 14 + src/wram.asm | 39 ++- 8 files changed, 1013 insertions(+), 212 deletions(-) (limited to 'src') diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index 65f58e3..b667c50 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -232,21 +232,32 @@ AI_FLAG_USED_PROFESSOR_OAK EQU 1 << 2 AI_FLAG_MODIFIED_HAND EQU 1 << 3 AI_FLAG_USED_GUST_OF_WIND EQU 1 << 4 +; used as input for AIProcessEnergyCards to determine what to check +; and whether to play card after the routine is over. +; I suspect AI_ENERGY_FLAG_DONT_PLAY to be a flag to signal the routine +; not to actually play the energy card after it's finished, +; but AIProcessEnergyCards checks whether ANY flag is set in order +; to decide not to play it, so it's redundant in the presence of another flag. +AI_ENERGY_FLAG_DONT_PLAY EQU 1 << 0 ; whether to play energy card (?) +AI_ENERGY_FLAG_SKIP_EVOLUTION EQU 1 << 1 ; whether to check if card has evolutions +AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in determining which card to attach energy + ; used to determine which Trainer cards for AI ; to process in AIProcessHandTrainerCards. ; aside from a few exceptions, these go in chronological order. -AI_TRAINER_CARD_PHASE_01 EQU $1 -AI_TRAINER_CARD_PHASE_02 EQU $2 -AI_TRAINER_CARD_PHASE_03 EQU $3 -AI_TRAINER_CARD_PHASE_04 EQU $4 -AI_TRAINER_CARD_PHASE_05 EQU $5 -AI_TRAINER_CARD_PHASE_06 EQU $6 -AI_TRAINER_CARD_PHASE_07 EQU $7 -AI_TRAINER_CARD_PHASE_08 EQU $8 -AI_TRAINER_CARD_PHASE_09 EQU $9 -AI_TRAINER_CARD_PHASE_10 EQU $a -AI_TRAINER_CARD_PHASE_11 EQU $b -AI_TRAINER_CARD_PHASE_12 EQU $c -AI_TRAINER_CARD_PHASE_13 EQU $d -AI_TRAINER_CARD_PHASE_14 EQU $e -AI_TRAINER_CARD_PHASE_15 EQU $f + const_def 1 + const AI_TRAINER_CARD_PHASE_01 ; $1 + const AI_TRAINER_CARD_PHASE_02 ; $2 + const AI_TRAINER_CARD_PHASE_03 ; $3 + const AI_TRAINER_CARD_PHASE_04 ; $4 + const AI_TRAINER_CARD_PHASE_05 ; $5 + const AI_TRAINER_CARD_PHASE_06 ; $6 + const AI_TRAINER_CARD_PHASE_07 ; $7 + const AI_TRAINER_CARD_PHASE_08 ; $8 + const AI_TRAINER_CARD_PHASE_09 ; $9 + const AI_TRAINER_CARD_PHASE_10 ; $a + const AI_TRAINER_CARD_PHASE_11 ; $b + const AI_TRAINER_CARD_PHASE_12 ; $c + const AI_TRAINER_CARD_PHASE_13 ; $d + const AI_TRAINER_CARD_PHASE_14 ; $e + const AI_TRAINER_CARD_PHASE_15 ; $f diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index b73b47c..7668903 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -6835,6 +6835,7 @@ OppAction_ExecutePokemonPowerEffect: ; 6b07 (1:6b07) ret ; 0x6b15 +; execute the EFFECTCMDTYPE_AFTER_DAMAGE command of the used Pokemon Power OppAction_6b15: ; 6b15 (1:6b15) ld a, EFFECTCMDTYPE_AFTER_DAMAGE call TryExecuteEffectCommandFunction diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index ee45de4..ba0a565 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -74,8 +74,8 @@ Func_14078: ; 14078 (5:4078) call AIDecideBenchPokemonToSwitchTo call AIChooseEnergyToDiscardForRetreatCost .asm_14091 - call AIDecidePlayEnergyCardFromHand - call Func_169f8 + call AIProcessAndTryToPlayEnergy + call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision @@ -220,8 +220,44 @@ LoadDefendingPokemonColorWRAndPrizeCards: ; 1411d (5:411d) ret ; 0x14145 -Func_14145: ; 14145 (5:4145) - INCROM $14145, $14184 +; 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 CopyMoveDataAndDamage_FromDeckIndex + ld a, OPPACTION_BEGIN_ATTACK + bank1call AIMakeDecision + ret c + + call AISelectSpecialAttackParameters + jr c, .use_attack + ld a, OPPACTION_BEGIN_ATTACK + call TryExecuteEffectCommandFunction + +.use_attack + ld a, [wSelectedAttack] + ld e, a + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + ld d, a + call CopyMoveDataAndDamage_FromDeckIndex + ld a, OPPACTION_USE_ATTACK + bank1call AIMakeDecision + ret c + + ld a, OPPACTION_ATTACK_ANIM_AND_DAMAGE + call TryExecuteEffectCommandFunction + ld a, OPPACTION_ATTACK_ANIM_AND_DAMAGE + bank1call AIMakeDecision + ret +; 0x14184 ; return carry if any of the following is satisfied: ; - deck index in a corresponds to a double colorless energy card; @@ -1145,7 +1181,7 @@ PointerTable_14668: ; 14668 (05:4668) dw Func_14674 ; not used dw Func_14674 ; general AI for battles dw Func_14678 ; basic pokemon placement / cheater shuffling on better AI - dw Func_1467f + dw Func_1467f ; deciding which Bench Pokemon to switch to dw Func_14683 dw Func_14687 @@ -1160,11 +1196,11 @@ Func_14678: ; 14678 (5:4678) ret Func_1467f: ; 1467f (5:467f) - call $5b72 + call AIDecideBenchPokemonToSwitchTo ret Func_14683: ; 14683 (5:4683) - call $5b72 + call AIDecideBenchPokemonToSwitchTo ret Func_14687: ; 14687 (5:4687) @@ -1174,105 +1210,108 @@ Func_14687: ; 14687 (5:4687) ; AI for general decks i think Func_1468b: ; 1468b (5:468b) call Func_15649 - ld a, $1 + + ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - farcall $8, $67d3 - jp nc, $4776 - farcall $8, $6790 - farcall $8, $66a3 - farcall $8, $637f + farcall Func_227d3 + jp nc, .asm_14776 + + farcall Func_22790 + farcall Func_226a3 + farcall Func_2237f ret c - farcall $8, $662d - ld a, $2 + + farcall Func_2262d + + ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards - ld a, $3 + ld a, AI_TRAINER_CARD_PHASE_03 call AIProcessHandTrainerCards - ld a, $4 + ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards - call $5eae + call AIDecidePlayPokemonCard ret c - ld a, $5 + + ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards - ld a, $6 + ld a, AI_TRAINER_CARD_PHASE_06 call AIProcessHandTrainerCards - ld a, $7 + ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - ld a, $8 + ld a, AI_TRAINER_CARD_PHASE_08 call AIProcessHandTrainerCards - call $4786 - ld a, $a + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards - ld a, $b + ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards - ld a, $c + ld a, AI_TRAINER_CARD_PHASE_12 call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a jr nz, .asm_146ed - call $64e8 - + call AIProcessAndTryToPlayEnergy .asm_146ed - call $5eae - farcall $8, $66a3 - farcall $8, $637f + call AIDecidePlayPokemonCard + farcall Func_226a3 + farcall Func_2237f ret c - farcall $8, $6790 - ld a, $d - farcall $8, $619b - ld a, $d + farcall Func_22790 + ld a, $0d + farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards - ld a, $f + ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK + and $04 jr z, .asm_14776 - ld a, $1 + ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - ld a, $2 + ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards - ld a, $3 + ld a, AI_TRAINER_CARD_PHASE_03 call AIProcessHandTrainerCards - ld a, $4 + ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards - call $5eae + call AIDecidePlayPokemonCard ret c - ld a, $5 + ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards - ld a, $6 + ld a, AI_TRAINER_CARD_PHASE_06 call AIProcessHandTrainerCards - ld a, $7 + ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - ld a, $8 + ld a, AI_TRAINER_CARD_PHASE_08 call AIProcessHandTrainerCards - call $4786 - ld a, $a + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards - ld a, $b + ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards - ld a, $c + ld a, AI_TRAINER_CARD_PHASE_12 call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a jr nz, .asm_1475b - call $64e8 - + call AIProcessAndTryToPlayEnergy .asm_1475b - call $5eae - farcall $8, $66a3 - farcall $8, $637f + call AIDecidePlayPokemonCard + farcall Func_226a3 + farcall Func_2237f ret c - farcall $8, $6790 - ld a, $d - farcall $8, $619b - ld a, $d + farcall Func_22790 + ld a, $0d + farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards .asm_14776 - ld a, $e - farcall $8, $619b - call $69f8 + ld a, $0e + farcall HandleAIEnergyTrans + call AIProcessAndTryToUseAttack ret c - ld a, $5 + ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x14786 @@ -1735,6 +1774,8 @@ CountNumberOfEnergyCardsAttached: ; 15787 (5:5787) ; 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 @@ -2207,7 +2248,7 @@ AIDecideWhetherToRetreat: ; 158b2 (5:58b2) .one_or_none call CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondMove jr c, .check_defending_can_ko - call CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove + call CountNumberOfSetUpBenchPokemon cp 2 jr c, .check_defending_can_ko call AddToAIScore @@ -2324,7 +2365,8 @@ Func_15b54: ; 15b54 (5:5b54) ; calculates AI score for bench Pokémon ; returns in hTempPlayAreaLocation_ff9d the -; Play Area location of best card to switch to +; Play Area location of best card to switch to. +; returns carry if no Bench Pokemon. AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -2376,17 +2418,17 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) xor a ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable - call nc, .calculate_damage + call nc, .HandleAttackDamageScore ld a, $01 ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable - call nc, .calculate_damage + call nc, .HandleAttackDamageScore jr .check_energy_card ; adds to AI score depending on amount of damage ; it can inflict to the defending Pokémon ; AI score += floor(Damage / 10) + 1 -.calculate_damage +.HandleAttackDamageScore ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, [wDamage] @@ -4006,47 +4048,58 @@ CheckForEvolutionInDeck: ; 16451 (5:6451) Func_16488 ; 16488 (5:6488) INCROM $16488, $164a1 -; copies wPlayAreaAIScore to wTempPlayAreaAIScore. -; copies AIScore to wcde3. -; decides which card to get energy card. -Func_164a1: ; 164a1 (5:64a1) - ld a, $03 - ld [wcdd8], a +; have AI choose an energy card to play, but do not play it. +; does not consider whether the cards have evolutions to be played. +; return carry if an energy card is chosen to use in any Play Area card, +; and if so, return its Play Area location in hTempPlayAreaLocation_ff9d. +AIProcessButDontPlayEnergy_SkipEvolution: ; 164a1 (5:64a1) + ld a, AI_ENERGY_FLAG_DONT_PLAY | AI_ENERGY_FLAG_SKIP_EVOLUTION + ld [wAIEnergyAttachLogicFlags], a + +; backup wPlayAreaAIScore in wTempPlayAreaAIScore. ld de, wTempPlayAreaAIScore ld hl, wPlayAreaAIScore ld b, MAX_PLAY_AREA_POKEMON -.loop_play_area +.loop ld a, [hli] ld [de], a inc de dec b - jr nz, .loop_play_area + jr nz, .loop ld a, [wAIScore] ld [de], a - jr AIDecideWhichCardToAttachEnergy -Func_164ba: ; 164ba (5:64ba) - ld a, $83 - ld [wcdd8], a + jr AIProcessEnergyCards + +; have AI choose an energy card to play, but do not play it. +; does not consider whether the cards have evolutions to be played. +; return carry if an energy card is chosen to use in any Bench card, +; and if so, return its Play Area location in hTempPlayAreaLocation_ff9d. +AIProcessButDontPlayEnergy_SkipEvolutionAndArena: ; 164ba (5:64ba) + ld a, AI_ENERGY_FLAG_DONT_PLAY | AI_ENERGY_FLAG_SKIP_EVOLUTION | AI_ENERGY_FLAG_SKIP_ARENA_CARD + ld [wAIEnergyAttachLogicFlags], a + +; backup wPlayAreaAIScore in wTempPlayAreaAIScore. ld de, wTempPlayAreaAIScore ld hl, wPlayAreaAIScore ld b, MAX_PLAY_AREA_POKEMON -.asm_164c7 +.loop ld a, [hli] ld [de], a inc de dec b - jr nz, .asm_164c7 + jr nz, .loop ld a, [wAIScore] ld [de], a - jr AIDecideWhichCardToAttachEnergy + + jr AIProcessEnergyCards ; copies wTempPlayAreaAIScore to wPlayAreaAIScore -; and loads wAIscore with value in wcde3. -; identical to Func_169e3. -Func_164d3: ; 164d3 (5:64d3) +; and loads wAIscore with value in wTempAIScore. +; identical to RetrievePlayAreaAIScoreFromBackup2. +RetrievePlayAreaAIScoreFromBackup1: ; 164d3 (5:64d3) push af ld de, wPlayAreaAIScore ld hl, wTempPlayAreaAIScore @@ -4065,34 +4118,37 @@ Func_164d3: ; 164d3 (5:64d3) ; have AI decide whether to play energy card from hand ; and determine which card is best to attach it. -AIDecidePlayEnergyCardFromHand: ; 164e8 (5:64e8) +AIProcessAndTryToPlayEnergy: ; 164e8 (5:64e8) xor a - ld [wcdd8], a + ld [wAIEnergyAttachLogicFlags], a call CreateEnergyCardListFromHand - jr nc, AIDecideWhichCardToAttachEnergy + jr nc, AIProcessEnergyCards ; no energy - ld a, [wcdd8] + ld a, [wAIEnergyAttachLogicFlags] or a jr z, .exit - jp Func_164d3 + jp RetrievePlayAreaAIScoreFromBackup1 .exit or a ret ; have AI decide whether to play energy card ; and determine which card is best to attach it. -AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) +AIProcessEnergyCards: ; 164fc (5:64fc) +; initialize Play Area AI score ld a, $80 ld b, MAX_PLAY_AREA_POKEMON - ld hl, wcde4 + ld hl, wPlayAreaEnergyAIScore .loop ld [hli], a dec b jr nz, .loop +; Legendary Articuno Deck has its own energy card logic call HandleLegendaryArticunoEnergyScoring +; start the main Play Area loop ld b, PLAY_AREA_ARENA ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable @@ -4106,8 +4162,8 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ld [wAIScore], a ld a, $ff ld [wTempAI], a - ld a, [wcdd8] - and $02 + ld a, [wAIEnergyAttachLogicFlags] + and AI_ENERGY_FLAG_SKIP_EVOLUTION jr nz, .check_venusaur ; check if energy needed is found in hand @@ -4125,7 +4181,7 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ld a, [wCurCardCanAttack] call CheckForEvolutionInList jr nc, .no_evolution_in_hand - ld [wTempAI], a + ld [wTempAI], a ; store evolution card found ld a, 2 call AddToAIScore jr .check_venusaur @@ -4137,8 +4193,9 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ld a, 1 call AddToAIScore -; if there's no Muk in Play Area -; and there's Venusaur2, add to AI score +; if there's no Muk in any Play Area +; and there's Venusaur2 in own Play Area, +; add to AI score .check_venusaur ld a, MUK call CountPokemonIDInBothPlayAreas @@ -4157,27 +4214,27 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ; arena ld a, [wcda7] bit 7, a - jr z, .check_arena_hp + jr z, .skip_subtracting_score ld a, 5 call SubFromAIScore jr .check_defending_can_ko -; lower AI score if poison/double poison -; will KO Pokémon between turns -; or if the defending Pokémon can KO -.check_arena_hp +.skip_subtracting_score ld a, 4 call AddToAIScore +; lower AI score if poison/double poison +; will KO Pokémon between turns +; or if the defending Pokémon can KO ld a, DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable call CalculateByteTensDigit cp 3 jr nc, .check_defending_can_ko -; hp < 30 + ; hp < 30 cp 2 jr z, .has_20_hp -; hp = 10 + ; hp = 10 ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable and POISONED @@ -4288,11 +4345,12 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) .check_boss_deck call CheckIfNotABossDeckID jr c, .skip_boss_deck + call Func_174f2 ldh a, [hTempPlayAreaLocation_ff9d] ld c, a ld b, $00 - ld hl, wcde4 + ld hl, wPlayAreaEnergyAIScore add hl, bc ld a, [hl] cp $80 @@ -4336,24 +4394,24 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ; for each card has been calculated. ; now to determine the highest score. call FindPlayAreaCardWithHighestAIScore - jp nc, .asm_1668a + jp nc, .not_found - ld a, [wcdd8] + ld a, [wAIEnergyAttachLogicFlags] or a jr z, .play_card scf - jp Func_164d3 + jp RetrievePlayAreaAIScoreFromBackup1 .play_card call CreateEnergyCardListFromHand jp AITryToPlayEnergyCard -.asm_1668a: ; 1668a (5:668a) - ld a, [wcdd8] +.not_found: ; 1668a (5:668a) + ld a, [wAIEnergyAttachLogicFlags] or a - jr z, .asm_16693 - jp Func_164d3 -.asm_16693 + jr z, .no_carry + jp RetrievePlayAreaAIScoreFromBackup1 +.no_carry or a ret ; 0x16695 @@ -4562,15 +4620,17 @@ DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) ; of the card with the highest Play Area AI score, unless ; the highest score is below $85. ; if it succeeds in return a card location, set carry. +; if AI_ENERGY_FLAG_SKIP_ARENA_CARD is set in wAIEnergyAttachLogicFlags +; doesn't include the Arena card and there's no minimum score. FindPlayAreaCardWithHighestAIScore: ; 167b5 (5:67b5) - ld a, [wcdd8] - and $80 - jr nz, .asm_167e1 + ld a, [wAIEnergyAttachLogicFlags] + and AI_ENERGY_FLAG_SKIP_ARENA_CARD + jr nz, .only_bench ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable ld b, a - ld c, 0 ; PLAY_AREA_ARENA + ld c, PLAY_AREA_ARENA ld e, c ld d, c ld hl, wPlayAreaAIScore @@ -4601,7 +4661,7 @@ FindPlayAreaCardWithHighestAIScore: ; 167b5 (5:67b5) ret ; same as above but only check bench Pokémon scores. -.asm_167e1 +.only_bench ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable dec a @@ -4624,6 +4684,7 @@ FindPlayAreaCardWithHighestAIScore: ; 167b5 (5:67b5) dec b jr nz, .loop_2 +; in this case, there is no minimum threshold AI score. ld a, d ldh [hTempPlayAreaLocation_ff9d], a scf @@ -4694,16 +4755,16 @@ GetEnergyCardForDiscardOrEnergyBoostAttack: ; 1683b (5:683b) jr z, .first_attack ; check if second attack is Zapdos2's Thunderbolt, -; Charizard's Fire Spin or Exeggcutor's Big Eggsplosion, +; Charizard's Fire Spin or Exeggutor's Big Eggsplosion, ; for these to be treated differently. ; for both attacks, load its energy cost. ld a, b cp ZAPDOS2 jr z, .zapdos2 cp CHARIZARD - jr z, .charizard_or_exeggcutor + jr z, .charizard_or_exeggutor cp EXEGGUTOR - jr z, .charizard_or_exeggcutor + jr z, .charizard_or_exeggutor ld hl, wLoadedCard2Move2EnergyCost jr .fire .first_attack @@ -4758,9 +4819,9 @@ GetEnergyCardForDiscardOrEnergyBoostAttack: ; 1683b (5:683b) or a ret -; Charizard's Fire Spin and Exeggcutor's Big Eggsplosion, +; Charizard's Fire Spin and Exeggutor's Big Eggsplosion, ; return carry. -.charizard_or_exeggcutor +.charizard_or_exeggutor lb bc, $00, $01 scf ret @@ -5019,11 +5080,13 @@ CheckSpecificDecksToAttachDoubleColorless: ; 1696e (5:696e) ret ; 0x169ca -Func_169ca: ; 169ca (5:69ca) +; have AI choose an attack to use, but do not execute it. +; return carry if an attack is chosen. +AIProcessButDontUseAttack: ; 169ca (5:69ca) ld a, $01 - ld [wcdd9], a + ld [wAIExecuteProcessedAttack], a -; copy wPlayAreaAIScore to wTempPlayAreaAIScore. +; backup wPlayAreaAIScore in wTempPlayAreaAIScore. ld de, wTempPlayAreaAIScore ld hl, wPlayAreaAIScore ld b, MAX_PLAY_AREA_POKEMON @@ -5034,15 +5097,15 @@ Func_169ca: ; 169ca (5:69ca) dec b jr nz, .loop -; copies wAIScore to wcde3 +; copies wAIScore to wTempAIScore ld a, [wAIScore] ld [de], a - jr Func_169fc + jr AIProcessAttacks ; copies wTempPlayAreaAIScore to wPlayAreaAIScore -; and loads wAIscore with value in wcde3. -; identical to Func_164d3. -Func_169e3: ; 169e3 (5:69e3) +; and loads wAIscore with value in wTempAIScore. +; identical to RetrievePlayAreaAIScoreFromBackup1. +RetrievePlayAreaAIScoreFromBackup2: ; 169e3 (5:69e3) push af ld de, wPlayAreaAIScore ld hl, wTempPlayAreaAIScore @@ -5060,12 +5123,18 @@ Func_169e3: ; 169e3 (5:69e3) ret ; 0x169f8 -Func_169f8: ; 169f8 (5:69f8) +; have AI choose and execute an attack. +; return carry if an attack was chosen and attempted. +AIProcessAndTryToUseAttack: ; 169f8 (5:69f8) xor a - ld [wcdd9], a + ld [wAIExecuteProcessedAttack], a ; fallthrough -Func_169fc: ; 169fc (5:69fc) +; checks which of the Active card's attacks for AI to use. +; If any of the attacks has enough AI score to be used, +; AI will use it if wAIExecuteProcessedAttack is 0. +; in either case, return carry if an attack is chosen to be used. +AIProcessAttacks: ; 169fc (5:69fc) ; if AI used Pluspower, load its attack index ld a, [wPreviousAIFlags] and AI_FLAG_USED_PLUSPOWER @@ -5077,23 +5146,23 @@ Func_169fc: ; 169fc (5:69fc) .no_pluspower ld a, [wcda7] cp $80 - jp z, .asm_16a77 + jp z, .dont_attack ; determine AI score of both attacks. xor a ; FIRST_ATTACK_OR_PKMN_POWER call GetAIScoreOfAttack ld a, [wAIScore] - ld [wPlayAreaAIScore], a + ld [wFirstAttackAIScore], a ld a, SECOND_ATTACK call GetAIScoreOfAttack ; compare both attack scores ld c, SECOND_ATTACK - ld a, [wPlayAreaAIScore] + ld a, [wFirstAttackAIScore] ld b, a ld a, [wAIScore] cp b - jr nc, .asm_16a30 + jr nc, .check_score ; first attack has higher score dec c ld a, b @@ -5103,9 +5172,9 @@ Func_169fc: ; 169fc (5:69fc) ; first check if chosen attack has at least minimum score. ; then check if first attack is better than second attack ; in case the second one was chosen. -.asm_16a30 +.check_score cp $50 ; minimum score to use attack - jr c, .asm_16a77 + jr c, .dont_attack ; enough score, proceed ld a, c @@ -5115,14 +5184,18 @@ Func_169fc: ; 169fc (5:69fc) call CheckWhetherToSwitchToFirstAttack .attack_chosen - ld a, [wcdd9] +; check whether to execute the attack chosen + ld a, [wAIExecuteProcessedAttack] or a - jr z, .asm_16a48 + jr z, .execute + +; set carry and reset Play Area AI score +; to the previous values. scf - jp Func_169e3 + jp RetrievePlayAreaAIScoreFromBackup2 -.asm_16a48 - ld a, $0e +.execute + ld a, AI_TRAINER_CARD_PHASE_14 call AIProcessHandTrainerCards ; load this attack's damage output against @@ -5134,39 +5207,52 @@ Func_169fc: ; 169fc (5:69fc) ld a, [wDamage] or a - jr z, .asm_16a62 - ; if damage is 0, fallthrough + jr z, .check_damage_bench + ; if damage is not 0, fallthrough -.cannot_damage +.can_damage xor a ld [wcdb4], a - jr .asm_16a6d + jr .use_attack -.asm_16a62 +.check_damage_bench +; check if it can otherwise damage player's bench ld a, MOVE_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F call CheckLoadedMoveFlag - jr c, .cannot_damage + jr c, .can_damage + +; cannot damage either Defending Pokemon or Bench ld hl, wcdb4 inc [hl] -.asm_16a6d + +; return carry if attack is chosen +; and AI tries to use it. +.use_attack ld a, $01 ld [wcddb], a - call Func_14145 + call AITryUseAttack scf ret -.asm_16a77 - ld a, [wcdd9] + +.dont_attack + ld a, [wAIExecuteProcessedAttack] or a - jr z, .asm_16a80 - jp Func_169e3 -.asm_16a80 + jr z, .failed_to_use + +; reset Play Area AI score +; to the previous values. + jp RetrievePlayAreaAIScoreFromBackup2 + +; return no carry if no viable attack. +.failed_to_use ld hl, wcdb4 inc [hl] or a ret ; 0x16a86 -; determines the AI score of attack index in a. +; determines the AI score of attack index in a +; of card in Play Area location hTempPlayAreaLocation_ff9d. GetAIScoreOfAttack: ; 16a86 (5:6a86) ; initialize AI score. ld [wSelectedAttack], a @@ -5737,7 +5823,7 @@ HandleSpecialAIMoves: ; 16dcd (5:6dcd) cp BELLSPROUT jr z, HandleCallForFamily cp EXEGGUTOR - jp z, HandleExeggcutorTeleport + jp z, HandleExeggutorTeleport cp SCYTHER jp z, HandleSwordsDanceAndFocusEnergy cp KRABBY @@ -5864,7 +5950,7 @@ HandleJigglypuff2FriendshipSong: ; 16ead (5:6ead) ret ; if AI decides to retreat, return a score of $80 + 10. -HandleExeggcutorTeleport: ; 16ec2 (5:6ec2) +HandleExeggutorTeleport: ; 16ec2 (5:6ec2) call AIDecideWhetherToRetreat jp nc, HandleSpecialAIMoves.zero ld a, $8a @@ -5942,14 +6028,14 @@ HandlePorygonConversion: ; 16f18 (5:6f18) jr nz, .conversion_2 ; conversion 1 - call CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove + call CountNumberOfSetUpBenchPokemon cp 2 jr c, .low_score ld a, $82 ret .conversion_2 - call CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove + call CountNumberOfSetUpBenchPokemon cp 2 jr nc, .low_score ld a, $82 @@ -6097,7 +6183,7 @@ HandleElectrode1EnergySpike: ; 16ff2 (5:6ff2) ld e, LIGHTNING_ENERGY call CheckIfAnyCardIDinLocation jp nc, HandleSpecialAIMoves.zero - call Func_164a1 + call AIProcessButDontPlayEnergy_SkipEvolution jp nc, HandleSpecialAIMoves.zero ld a, $83 ret @@ -6125,7 +6211,7 @@ HandleHyperBeam: ; 17005 (5:7005) CheckWhetherToSwitchToFirstAttack: ; 17019 (5:7019) ; this checks whether the first attack is also viable ; (has more than minimum score to be used) - ld a, [wPlayAreaAIScore] + ld a, [wFirstAttackAIScore] cp $50 jr c, .keep_second_attack @@ -6209,7 +6295,7 @@ CheckIfAnyBasicPokemonInDeck: ; 17057 (5:7057) ; return carry and that card's Play Area location in a. ; output: ; a = card location of Pokémon card, if found; -; cerry set if such a card is found. +; carry set if such a card is found. LookForCardThatIsKnockedOutOnDevolution: ; 17080 (5:7080) ldh a, [hTempPlayAreaLocation_ff9d] push af @@ -6307,15 +6393,16 @@ CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondMove: ; 170c9 (5:70c9) ret ; 0x17101 -; returns carry if at least one Pokémon in bench -; meets the following conditions: -; - card HP >= half max HP +; 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 move -; Also outputs the number of Pokémon in bench +; Outputs the number of Pokémon in bench ; that meet these requirements in a -CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) +; and returns carry if at least one is found +CountNumberOfSetUpBenchPokemon: ; 17101 (5:7101) ldh a, [hTempPlayAreaLocation_ff9d] ld d, a ld a, [wSelectedAttack] @@ -6333,17 +6420,24 @@ CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) 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 @@ -6386,8 +6480,138 @@ CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) ret ; 0x17161 -Func_17161 ; 17161 (5:7161) - INCROM $17161, $171fb +; 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 +; 0x1716e + +.SelectAttackParameters: ; 1716e (5:716e) + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp MEW3 + jr z, .devolution_beam + cp MEWTWO3 + jr z, .energy_absorption + cp MEWTWO2 + jr z, .energy_absorption + cp EXEGGUTOR + jr z, .teleport + cp ELECTRODE1 + jr z, .energy_spike + ; fallthrough + +.no_carry + or a + ret + +.devolution_beam +; 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 + +.energy_absorption +; 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 CreateEnergyCardListFromOpponentDiscardPile + +; find any energy card different from +; the one found by CheckIfAnyCardIDinLocation. +; since using this move 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 + +.energy_spike +; 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 +; 0x171fb ; return carry if Pokémon at play area location ; in hTempPlayAreaLocation_ff9d does not have @@ -6591,7 +6815,7 @@ CheckIfCanDamageDefendingPokemon: ; 17383 (5:7383) ; sets carry if any on the moves knocks out ; also outputs the largest damage dealt in a ; input: -; [hTempPlayAreaLocation_ff9d] = locaion of card to check +; [hTempPlayAreaLocation_ff9d] = location of card to check ; output: ; a = largest damage of both moves ; carry set if can knock out @@ -6825,7 +7049,7 @@ CheckForBenchIDAtHalfHPAndCanUseSecondMove: ; 17474 (5:7474) ret ; 0x174cd -; add 5 to wcde4 AI score corresponding to all cards +; 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 @@ -6848,7 +7072,7 @@ RaiseAIScoreToAllMatchingIDsInBench: ; 174cd (5:74cd) ld c, e ld b, $00 push hl - ld hl, wcde4 + ld hl, wPlayAreaEnergyAIScore add hl, bc ld a, 5 add [hl] @@ -6860,8 +7084,8 @@ RaiseAIScoreToAllMatchingIDsInBench: ; 174cd (5:74cd) ; 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 wcde4 -; while all others get decreased wcde4 +; 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 @@ -6880,6 +7104,7 @@ Func_174f2: ; 174f2 (5:74f2) ld a, [hli] cp $ff ret z + ld [wcdf9], a push de push hl @@ -6945,11 +7170,11 @@ Func_174f2: ; 174f2 (5:74f2) jr .loop_2 ; c = play area location of highest score -; decrease wcde4 score for all cards with same ID +; decrease wPlayAreaEnergyAIScore score for all cards with same ID ; except for the one with highest score -; increase wcde4 score for card with highest ID +; increase wPlayAreaEnergyAIScore score for card with highest ID .asm_17560 - ld hl, wcde4 + ld hl, wPlayAreaEnergyAIScore ld de, wcdea ld b, PLAY_AREA_ARENA .loop_3 diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 5a0f535..6850b82 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6219,8 +6219,449 @@ AIDecide_PokemonTrader_Flamethrower: ; 22133 (8:6133) ret ; 0x2219b -Func_2219b: ; 2219b (8:219b) - INCROM $2219b, $227f6 +; handle AI routines for Energy Trans. +; depending on input, AI can use Energy Trans to +; give Arena or Bench cards some Grass energy cards, +; depending whether it's for attack, retreat, etc. +HandleAIEnergyTrans: ; 2219b (8:619b) + ld [wce06], a + +; choose to randomly return + farcall ChooseRandomlyNotToPlayTrainerCard + ret c + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + ret z ; return if no Bench cards + + ld a, VENUSAUR2 + call CountPokemonIDInPlayArea + ret nc ; return if no Venusaur2 found in own Play Area + + ld a, MUK + call CountPokemonIDInBothPlayAreas + ret c ; return if Muk found in any Play Area + + ld a, [wce06] + cp $09 + jr z, .check_retreat + + cp $0e + jp z, .TransferEnergyToBench + + call .CheckEnoughGrassEnergyCardsForAttack + ret nc + jr .TransferEnergyToArena + +.check_retreat + call .CheckEnoughGrassEnergyCardsForRetreatCost + ret nc + +; use Energy Trans to transfer number of Grass energy cards +; equal to input a from the Bench to the Arena card. +.TransferEnergyToArena + ld [wAINumberOfEnergyTransCards], a + +; look for Venusaur2 in Play Area +; so that its PKMN Power can be used. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + ld b, a +.loop_play_area_1 + ld a, DUELVARS_ARENA_CARD + add b + call GetTurnDuelistVariable + ldh [hTempCardIndex_ff9f], a + call GetCardIDFromDeckIndex + ld a, e + cp VENUSAUR2 + jr z, .use_pkmn_power_1 + + ld a, b + or a + ret z ; return when finished Play Area loop + + dec b + jr .loop_play_area_1 + +; use Energy Trans Pkmn Power +.use_pkmn_power_1 + ld a, b + ldh [hTemp_ffa0], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + + xor a ; PLAY_AREA_ARENA + ldh [hAIEnergyTransPlayAreaLocation], a + ld a, [wAINumberOfEnergyTransCards] + ld d, a + +; look for Grass energy cards that +; are currently attached to a Bench card. + ld e, 0 +.loop_deck_locations_1 + ld a, DUELVARS_CARD_LOCATIONS + add e + call GetTurnDuelistVariable + and %00011111 + cp CARD_LOCATION_BENCH_1 + jr c, .next_card_1 + + and %00001111 + ldh [hTempPlayAreaLocation_ffa1], a + + ld a, e + push de + call GetCardIDFromDeckIndex + ld a, e + pop de + cp GRASS_ENERGY + jr nz, .next_card_1 + + ; store the deck index of energy card + ld a, e + ldh [hAIEnergyTransEnergyCard], a + + push de + ld d, 30 +.small_delay_1 + call DoFrame + dec d + jr nz, .small_delay_1 + + ld a, OPPACTION_6B15 + bank1call AIMakeDecision + pop de + dec d + jr z, .done_transfer_1 + +.next_card_1 + inc e + ld a, DECK_SIZE + cp e + jr nz, .loop_deck_locations_1 + +; transfer is done, perform delay +; and return to main scene. +.done_transfer_1 + ld d, 60 +.big_delay_1 + call DoFrame + dec d + jr nz, .big_delay_1 + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x22246 + +; checks if the Arena card has not enough energy for second attack, +; and if not, return carry if transferring Grass energy from Bench +; would be enough to use it and outputs number of energy cards needed in a. +.CheckEnoughGrassEnergyCardsForAttack ; 22246 (8:6246) + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp EXEGGUTOR + jr z, .is_exeggutor + + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + ld a, SECOND_ATTACK + ld [wSelectedAttack], a + farcall CheckEnergyNeededForAttack + jr nc, .attack_false ; return if no energy needed + +; check if colorless energy is needed... + ld a, c + or a + jr nz, .count_if_enough + +; ...otherwise check if basic energy card is needed +; and it's grass energy. + ld a, b + or a + jr z, .attack_false + ld a, e + cp GRASS_ENERGY + jr nz, .attack_false + ld c, b + jr .count_if_enough + +.attack_false + or a + ret + +.count_if_enough +; if there's enough Grass energy cards in Bench +; to satisfy the attack energy cost, return carry. + push bc + call .CountGrassEnergyInBench + pop bc + cp c + jr c, .attack_false + ld a, c + scf + ret + +.is_exeggutor +; in case it's Exeggutor in Arena, return carry +; if there are any Grass energy cards in Bench. + call .CountGrassEnergyInBench + or a + jr z, .attack_false + + scf + ret +; 0x22286 + +; outputs in a the number of Grass energy cards +; currently attached to Bench cards. +.CountGrassEnergyInBench ; 22286 (8:6286) + lb de, 0, 0 +.count_loop + ld a, DUELVARS_CARD_LOCATIONS + add e + call GetTurnDuelistVariable + and %00011111 + cp CARD_LOCATION_BENCH_1 + jr c, .count_next + +; is in bench + ld a, e + push de + call GetCardIDFromDeckIndex + ld a, e + pop de + cp GRASS_ENERGY + jr nz, .count_next + inc d +.count_next + inc e + ld a, DECK_SIZE + cp e + jr nz, .count_loop + ld a, d + ret +; 0x222a9 + +; returns carry if there are enough Grass energy cards in Bench +; to satisfy the retreat cost of the Arena card. +; if so, output the number of energy cards still needed in a. +.CheckEnoughGrassEnergyCardsForRetreatCost ; 222a9 (8:62a9) + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call GetPlayAreaCardRetreatCost + ld b, a + ld e, PLAY_AREA_ARENA + farcall CountNumberOfEnergyCardsAttached + cp b + jr nc, .retreat_false ; return if enough to retreat + +; see if there's enough Grass energy cards +; in the Bench to satisfy retreat cost + ld c, a + ld a, b + sub c + ld c, a + push bc + call .CountGrassEnergyInBench + pop bc + cp c + jr c, .retreat_false ; return if less cards than needed + +; output number of cards needed to retreat + ld a, c + scf + ret +.retreat_false + or a + ret +; 0x222ca + +; AI logic to determine whether to use Energy Trans Pkmn Power +; to transfer energy cards attached from the Arena Pokemon to +; some card in the Bench. +.TransferEnergyToBench ; 222ca (8:62ca) + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckIfDefendingPokemonCanKnockOut + ret nc ; return if Defending can't KO + +; processes attacks and see if any attack would be used by AI. +; if so, return. + farcall AIProcessButDontUseAttack + ret c + +; return if Arena card has no Grass energy cards attached. + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + GRASS] + or a + ret z + +; if no energy card attachment is needed, return. + farcall AIProcessButDontPlayEnergy_SkipEvolutionAndArena + ret nc + +; AI decided that an energy card is needed +; so look for Venusaur2 in Play Area +; so that its PKMN Power can be used. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + ld b, a +.loop_play_area_2 + ld a, DUELVARS_ARENA_CARD + add b + call GetTurnDuelistVariable + ldh [hTempCardIndex_ff9f], a + ld [wAIVenusaur2DeckIndex], a + call GetCardIDFromDeckIndex + ld a, e + cp VENUSAUR2 + jr z, .use_pkmn_power_2 + + ld a, b + or a + ret z ; return when Play Area loop is ended + + dec b + jr .loop_play_area_2 + +; use Energy Trans Pkmn Power +.use_pkmn_power_2 + ld a, b + ldh [hTemp_ffa0], a + ld [wAIVenusaur2PlayAreaLocation], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + +; loop for each energy cards that are going to be transferred. +.loop_energy + xor a + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wAIVenusaur2PlayAreaLocation] + ldh [hTemp_ffa0], a + + ; returns when Arena card has no Grass energy cards attached. + ld e, PLAY_AREA_ARENA + call GetPlayAreaCardAttachedEnergies + ld a, [wAttachedEnergies + GRASS] + or a + jr z, .done_transfer_2 + +; look for Grass energy cards that +; are currently attached to Arena card. + ld e, 0 +.loop_deck_locations_2 + ld a, DUELVARS_CARD_LOCATIONS + add e + call GetTurnDuelistVariable + cp CARD_LOCATION_ARENA + jr nz, .next_card_2 + + ld a, e + push de + call GetCardIDFromDeckIndex + ld a, e + pop de + cp GRASS_ENERGY + jr nz, .next_card_2 + + ; store the deck index of energy card + ld a, e + ldh [hAIEnergyTransEnergyCard], a + jr .transfer + +.next_card_2 + inc e + ld a, DECK_SIZE + cp e + jr nz, .loop_deck_locations_2 + jr .done_transfer_2 + +.transfer +; get the Bench card location to transfer Grass energy card to. + farcall AIProcessButDontPlayEnergy_SkipEvolutionAndArena + jr nc, .done_transfer_2 + ldh a, [hTempPlayAreaLocation_ff9d] + ldh [hAIEnergyTransPlayAreaLocation], a + + ld d, 30 +.small_delay_2 + call DoFrame + dec d + jr nz, .small_delay_2 + + ld a, [wAIVenusaur2DeckIndex] + ldh [hTempCardIndex_ff9f], a + ld d, a + ld e, FIRST_ATTACK_OR_PKMN_POWER + call CopyMoveDataAndDamage_FromDeckIndex + ld a, OPPACTION_6B15 + bank1call AIMakeDecision + jr .loop_energy + +; transfer is done, perform delay +; and return to main scene. +.done_transfer_2 + ld d, 60 +.big_delay_2 + call DoFrame + dec d + jr nz, .big_delay_2 + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x2237f + +Func_2237f: ; 2237f (8:237f) + INCROM $2237f, $2262d + +Func_2262d: ; 2262d (8:262d) + INCROM $2262d, $226a3 + +Func_226a3: ; 226a3 (8:26a3) + INCROM $226a3, $22790 + +Func_22790: ; 22790 (8:2790) + INCROM $22790, $227d3 + +; checks wcda7 and Pokemon in Play Area that are set up. +; if there's at least 4, goes to AI_TRAINER_CARD_PHASE_05. +; else, returns carry. +Func_227d3: ; 227d3 (8:67d3) + ld a, [wcda7] + bit 7, a + jr z, .set_carry + cp %10000010 + jr c, .asm_227e4 + + xor a + ld [wcda7], a + jr .set_carry + +.asm_227e4 + farcall CountNumberOfSetUpBenchPokemon + cp 4 + jr c, .set_carry + + ld a, AI_TRAINER_CARD_PHASE_05 + farcall AIProcessHandTrainerCards + or a + ret + +.set_carry + scf + ret +; 0x227f6 ; lists in wDuelTempList all the basic energy cards ; in card location of a. @@ -7128,7 +7569,7 @@ FindDuplicatePokemonCards: ; 22b6f (8:6b6f) ; return carry flag if move is not high recoil. Func_22bad: ; 22bad (8:6bad) - farcall Func_169ca + farcall AIProcessButDontUseAttack ret nc ld a, [wSelectedAttack] ld e, a diff --git a/src/engine/effect_functions.asm b/src/engine/effect_functions.asm index 8832134..dbda9ad 100644 --- a/src/engine/effect_functions.asm +++ b/src/engine/effect_functions.asm @@ -292,7 +292,9 @@ ApplySubstatus2ToDefendingCard: ; 2c149 (b:4149) ret ; 0x2c166 -Func_2c166: ; 2c166 (b:4166) +; overwrites in wDamage, wAIMinDamage and wAIMaxDamage +; with the value in a. +StoreDamageInfo: ; 2c166 (b:4166) ld [wDamage], a ld [wAIMinDamage], a ld [wAIMaxDamage], a @@ -348,7 +350,77 @@ HandleSwitchDefendingPokemonEffect: ; 2c1ec (b:41ec) ret ; 0x2c221 - INCROM $2c221, $2c487 + INCROM $2c221, $2c2a4 + +; makes a list in wDuelTempList with the deck indices +; of all the energy cards found in opponent's Discard Pile. +; if (c == 0), all energy cards are allowed; +; if (c != 0), double colorless energy cards are not counted. +; returns carry if no energy cards were found. +CreateEnergyCardListFromOpponentDiscardPile: ; 2c2a4 (b:42a4) + ld c, $00 + +; get number of cards in Discard Pile +; and have hl point to the end of the +; Discard Pile list in wOpponentDeckCards. + ld a, DUELVARS_NUMBER_OF_CARDS_IN_DISCARD_PILE + call GetTurnDuelistVariable + ld b, a + add DUELVARS_DECK_CARDS + ld l, a + + ld de, wDuelTempList + inc b + jr .next_card + +.check_energy + ld a, [hl] + call LoadCardDataToBuffer2_FromDeckIndex + ld a, [wLoadedCard2Type] + and TYPE_ENERGY + jr z, .next_card + +; if (c != $00), then we dismiss Double Colorless +; energy cards found. + ld a, c + or a + jr z, .copy + ld a, [wLoadedCard2Type] + cp TYPE_ENERGY_DOUBLE_COLORLESS + jr nc, .next_card + +.copy + ld a, [hl] + ld [de], a + inc de + +; goes through Discard Pile list +; in wOpponentDeckCards in descending order. +.next_card + dec l + dec b + jr nz, .check_energy + +; terminating byte on wDuelTempList + ld a, $ff + ld [de], a + +; check if any energy card was found +; by checking whether the first byte +; in wDuelTempList is $ff. +; if none were found, return carry. + ld a, [wDuelTempList] + cp $ff + jr z, .set_carry + or a + ret + +.set_carry + scf + ret +; 0x2c2e0 + + INCROM $2c2e0, $2c487 ; handles the selection of a forced switch ; by link/AI opponent or by the player. @@ -558,7 +630,7 @@ Twineedle_MultiplierEffect: ; 2c7f5 (b:47f5) add a add e call ATimes10 - call Func_2c166 + call StoreDamageInfo ret ; 0x2c80d @@ -679,4 +751,16 @@ Toxic_DoublePoisonEffect: ; 2c994 (b:4994) ret ; 0x2c998 - INCROM $2c998, $30000 \ No newline at end of file + INCROM $2c998, $2cbfb + +Func_2cbfb: ; 2cbfb (b:4bfb) + ldh a, [hAIEnergyTransPlayAreaLocation] + ld e, a + ldh a, [hAIEnergyTransEnergyCard] + call AddCardToHand + call PutHandCardInPlayArea + bank1call PrintPlayAreaCardList_EnableLCD + ret +; 0x2cc0a + + INCROM $2cc0a, $30000 \ No newline at end of file diff --git a/src/engine/home.asm b/src/engine/home.asm index 4f9fc31..338dbb0 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -5218,7 +5218,7 @@ Func_1bca: ; 1bca (0:1bca) ret ; 0x1c05 -; return in a the retreat cost of the turn holder's arena or benchx Pokemon +; return in a the retreat cost of the turn holder's arena or bench Pokemon ; given the PLAY_AREA_* value in hTempPlayAreaLocation_ff9d GetPlayAreaCardRetreatCost: ; 1c05 (0:1c05) ldh a, [hTempPlayAreaLocation_ff9d] diff --git a/src/hram.asm b/src/hram.asm index 9cdba06..2b4fbc9 100644 --- a/src/hram.asm +++ b/src/hram.asm @@ -85,10 +85,24 @@ hTemp_ffa0:: ; ffa0 hTempPlayAreaLocation_ffa1:: ; ffa1 ds $1 +UNION + ; $ff-terminated list of cards to be discarded upon retreat hTempRetreatCostCards:: ; ffa2 ds $6 +NEXTU + +; parameters chosen by AI in Energy Trans routine. +; the deck index (0-59) of the energy card to transfer +; and the Play Area location (PLAY_AREA_*) of card to receive that energy card. +hAIEnergyTransEnergyCard:: ; ffa2 + ds $1 +hAIEnergyTransPlayAreaLocation:: ; ffa3 + ds $1 + +ENDU + ; hffa8 through hffb0 belong to the text engine hffa8:: ; ffa8 ds $1 diff --git a/src/wram.asm b/src/wram.asm index e5fc9c6..2a10fe2 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1230,11 +1230,21 @@ wTempCardType:: ; cdba wAIScore:: ; cdbe ds $1 +UNION + ; used for AI decisions that involve ; each card in the Play Area. wPlayAreaAIScore:: ; cdbf ds MAX_PLAY_AREA_POKEMON +NEXTU + +; stores the score determined by AI for first attack +wFirstAttackAIScore:: ; cdbf + ds $1 + +ENDU + ds $0a ; information about the defending Pokémon and @@ -1274,10 +1284,16 @@ wAIPluspowerAttack:: ; cdd6 wAIPlayEnergyCardForRetreat:: ; cdd7 ds $1 -wcdd8:: ; cdd8 +; flags defined by AI_ENERGY_FLAG_* constants +; used as input for AIProcessEnergyCards +; to determine what to check in the routine. +wAIEnergyAttachLogicFlags:: ; cdd8 ds $1 -wcdd9:: ; cdd9 +; used as input to AIProcessAttacks. +; if 0, execute the attack chosen by the AI. +; if not 0, return without executing attack. +wAIExecuteProcessedAttack:: ; cdd9 ds $1 wcdda:: ; cdda @@ -1289,15 +1305,17 @@ wcddb:: ; cddb wcddc:: ; cddc ds $1 -; used to compliment wPlayAreaAIScore, -; to temporarily do calculations and store results. +; used to temporarily backup wPlayAreaAIScore values. wTempPlayAreaAIScore:: ; cddd ds MAX_PLAY_AREA_POKEMON -wcde3:: ; cde3 +wTempAIScore:: ; cde3 ds $1 -wcde4:: ; cde4 +; used for AI decisions that involve +; each card in the Play Area involving +; attaching Energy cards. +wPlayAreaEnergyAIScore:: ; cde4 ds MAX_PLAY_AREA_POKEMON wcdea:: ; cdea @@ -1355,8 +1373,15 @@ wAIMoveIsNonDamaging:: ; ce02 wce03:: ; ce03 ds $1 - ds $2 +; used by AI to store information of Venusaur2 +; while handling Energy Trans logic. +wAIVenusaur2DeckIndex:: ; ce04 + ds $1 +wAIVenusaur2PlayAreaLocation:: ; ce05 + ds $1 +; number of cards to be transferred by AI using Energy Trans. +wAINumberOfEnergyTransCards:: wce06:: ; ce06 ds $1 -- cgit v1.2.3 From ee139f3840b69878ca57acb2a2ecbd72a4375fc8 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 29 Apr 2020 09:47:16 +0100 Subject: Disassemble AI Pkmn Power routine --- src/engine/bank05.asm | 50 ++++--- src/engine/bank08.asm | 363 +++++++++++++++++++++++++++++++++++++++++++++++--- src/wram.asm | 2 +- 3 files changed, 376 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index ba0a565..1118699 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1216,8 +1216,8 @@ Func_1468b: ; 1468b (5:468b) farcall Func_227d3 jp nc, .asm_14776 - farcall Func_22790 - farcall Func_226a3 + farcall HandleAIGoGoRainDanceEnergy + farcall HandleAIDamageSwap farcall Func_2237f ret c @@ -1253,10 +1253,10 @@ Func_1468b: ; 1468b (5:468b) call AIProcessAndTryToPlayEnergy .asm_146ed call AIDecidePlayPokemonCard - farcall Func_226a3 + farcall HandleAIDamageSwap farcall Func_2237f ret c - farcall Func_22790 + farcall HandleAIGoGoRainDanceEnergy ld a, $0d farcall HandleAIEnergyTrans ld a, AI_TRAINER_CARD_PHASE_13 @@ -1297,10 +1297,10 @@ Func_1468b: ; 1468b (5:468b) call AIProcessAndTryToPlayEnergy .asm_1475b call AIDecidePlayPokemonCard - farcall Func_226a3 + farcall HandleAIDamageSwap farcall Func_2237f ret c - farcall Func_22790 + farcall HandleAIGoGoRainDanceEnergy ld a, $0d farcall HandleAIEnergyTrans ld a, AI_TRAINER_CARD_PHASE_13 @@ -1496,15 +1496,19 @@ Func_15636: ; 15636 (5:5636) ld [wcda5], a ret +; initializes some variables and +; sets value of wcda7. Func_15649: ; 15649 (5:5649) ld a, [wcda6] inc a ld [wcda6], a + xor a ld [wPreviousAIFlags], a ld [wcddb], a ld [wcddc], a ld [wce03], a + ld a, [wPlayerAttackingMoveIndex] cp $ff jr z, .asm_156b1 @@ -1513,19 +1517,22 @@ Func_15649: ; 15649 (5:5649) ld a, [wPlayerAttackingCardIndex] cp $ff jr z, .asm_156b1 + call SwapTurn call GetCardIDFromDeckIndex call SwapTurn ld a, e - cp MEWTWO1 ; I believe this is a check for Mewtwo1's Barrier move + cp MEWTWO1 jr nz, .asm_156b1 + +; handle Mewtwo1-only deck ld a, [wcda7] bit 7, a jr nz, .asm_156aa inc a ld [wcda7], a - cp $3 - jr c, .asm_156c2 + cp $03 + jr c, .done ld a, DUELVARS_ARENA_CARD call GetNonTurnDuelistVariable call SwapTurn @@ -1534,18 +1541,17 @@ Func_15649: ; 15649 (5:5649) ld a, e cp MEWTWO1 jr nz, .asm_156a4 - farcall $8, $67a9 + farcall CheckIfPlayerHasPokemonOtherThanMewtwo1 jr nc, .asm_156aa - .asm_156a4 +; reset wcda7 xor a ld [wcda7], a - jr .asm_156c2 - + jr .done .asm_156aa ld a, $80 ld [wcda7], a - jr .asm_156c2 + jr .done .asm_156b1 ld a, [wcda7] @@ -1553,13 +1559,13 @@ Func_15649: ; 15649 (5:5649) jr z, .asm_156be inc a ld [wcda7], a - jr .asm_156c2 + jr .done .asm_156be +; reset wcda7 xor a ld [wcda7], a - -.asm_156c2 +.done ret ; 0x156c3 @@ -4214,12 +4220,14 @@ AIProcessEnergyCards: ; 164fc (5:64fc) ; arena ld a, [wcda7] bit 7, a - jr z, .skip_subtracting_score + jr z, .add_to_score + +; subtract from score ld a, 5 call SubFromAIScore jr .check_defending_can_ko -.skip_subtracting_score +.add_to_score ld a, 4 call AddToAIScore @@ -6937,8 +6945,8 @@ CheckIfNotABossDeckID: ; 17426 (5:7426) ; - 25% for all other decks; ; - 0% for boss decks. ; used for certain decks to randomly choose -; not to play Trainer card in hand. -ChooseRandomlyNotToPlayTrainerCard: ; 1743b (5:743b) +; not to play Trainer card or use PKMN Power +AIChooseRandomlyNotToDoAction: ; 1743b (5:743b) ; boss decks always use Trainer cards. push hl push de diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 6850b82..9ef590b 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -114,7 +114,7 @@ _AIProcessHandTrainerCards: ; 200e5 (8:40e5) jp c, .next_in_data ; AI can randomly choose not to play card. - farcall ChooseRandomlyNotToPlayTrainerCard + farcall AIChooseRandomlyNotToDoAction jr c, .next_in_data ; call routine to decide whether to play Trainer card @@ -6227,7 +6227,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ld [wce06], a ; choose to randomly return - farcall ChooseRandomlyNotToPlayTrainerCard + farcall AIChooseRandomlyNotToDoAction ret c ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA @@ -6328,10 +6328,10 @@ HandleAIEnergyTrans: ; 2219b (8:619b) push de ld d, 30 -.small_delay_1 +.small_delay_loop_1 call DoFrame dec d - jr nz, .small_delay_1 + jr nz, .small_delay_loop_1 ld a, OPPACTION_6B15 bank1call AIMakeDecision @@ -6349,10 +6349,10 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; and return to main scene. .done_transfer_1 ld d, 60 -.big_delay_1 +.big_delay_loop_1 call DoFrame dec d - jr nz, .big_delay_1 + jr nz, .big_delay_loop_1 ld a, OPPACTION_DUEL_MAIN_SCENE bank1call AIMakeDecision ret @@ -6595,10 +6595,10 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ldh [hAIEnergyTransPlayAreaLocation], a ld d, 30 -.small_delay_2 +.small_delay_loop_2 call DoFrame dec d - jr nz, .small_delay_2 + jr nz, .small_delay_loop_2 ld a, [wAIVenusaur2DeckIndex] ldh [hTempCardIndex_ff9f], a @@ -6613,26 +6613,354 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; and return to main scene. .done_transfer_2 ld d, 60 -.big_delay_2 +.big_delay_loop_2 call DoFrame dec d - jr nz, .big_delay_2 + jr nz, .big_delay_loop_2 ld a, OPPACTION_DUEL_MAIN_SCENE bank1call AIMakeDecision ret ; 0x2237f -Func_2237f: ; 2237f (8:237f) - INCROM $2237f, $2262d +Func_2237f: ; 2237f (8:637f) + ld a, MUK + call CountPokemonIDInBothPlayAreas + ccf + ret nc ; return no carry if Muk is in play + + farcall AIChooseRandomlyNotToDoAction + ccf + ret nc ; return no carry if AI randomly decides to + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld b, a + ld c, PLAY_AREA_ARENA + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and CNF_SLP_PRZ + jr nz, .next_2 + +.loop_play_area + ld a, DUELVARS_ARENA_CARD + add c + call GetTurnDuelistVariable + ld [wce08], a + + push af + push bc + ld d, a + ld a, c + ldh [hTempPlayAreaLocation_ff9d], a + ld e, FIRST_ATTACK_OR_PKMN_POWER + call CopyMoveDataAndDamage_FromDeckIndex + ld a, [wLoadedMoveCategory] + cp POKEMON_POWER + jr z, .execute_effect + pop bc + jr .next_3 + +.execute_effect + ld a, EFFECTCMDTYPE_INITIAL_EFFECT_2 + bank1call TryExecuteEffectCommandFunction + pop bc + jr c, .next_3 + +; TryExecuteEffectCommandFunction was successful, +; so check what Pkmn Power this is through card's ID. + pop af + call GetCardIDFromDeckIndex + ld a, e + push bc + +; check heal + cp VILEPLUME + jr nz, .check_shift + call Func_22402 + jr .next_1 +.check_shift + cp VENOMOTH + jr nz, .check_peek + call Func_22476 + jr .next_1 +.check_peek + cp MANKEY + jr nz, .check_strange_behavior + call Func_224e6 + jr .next_1 +.check_strange_behavior + cp SLOWBRO + jr nz, .check_curse + call Func_2255d + jr .next_1 +.check_curse + cp GENGAR + jr nz, .next_1 + call z, Func_225b5 + jr c, .done + +.next_1 + pop bc +.next_2 + inc c + ld a, c + cp b + jr nz, .loop_play_area + ret + +.next_3 + pop af + jr .next_2 -Func_2262d: ; 2262d (8:262d) +.done + pop bc + ret +; 0x22402 + +Func_22402: ; 22402 (8:6402) + INCROM $22402, $22476 + +Func_22476: ; 22476 (8:6476) + INCROM $22476, $224e6 + +Func_224e6: ; 224e6 (8:64e6) + INCROM $224e6, $2255d + +Func_2255d: ; 2255d (8:655d) + INCROM $2255d, $225b5 + +Func_225b5: ; 225b5 (8:65b5) + INCROM $225b5, $2262d + +Func_2262d: ; 2262d (8:662d) INCROM $2262d, $226a3 -Func_226a3: ; 226a3 (8:26a3) - INCROM $226a3, $22790 +; AI logic for Damage Swap to transfer damage from Arena card +; to a card in Bench with more than 10 HP remaining +; and with no energy cards attached. +HandleAIDamageSwap: ; 226a3 (8:66a3) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + ret z ; return if no Bench Pokemon + + farcall AIChooseRandomlyNotToDoAction + ret c + + ld a, ALAKAZAM + call CountPokemonIDInPlayArea + ret nc ; return if no Alakazam + ld a, MUK + call CountPokemonIDInBothPlayAreas + ret c ; return if there's Muk in play + +; only take damage off certain cards in Arena + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp ALAKAZAM + jr z, .ok + cp KADABRA + jr z, .ok + cp ABRA + jr z, .ok + cp MR_MIME + ret nz + +.ok + ld e, PLAY_AREA_ARENA + call GetCardDamage + or a + ret z ; return if no damage + + call ConvertHPToCounters + ld [wce06], a + ld a, ALAKAZAM + ld b, PLAY_AREA_BENCH_1 + farcall LookForCardIDInPlayArea_Bank5 + jr c, .is_in_bench + +; Alakazam is Arena card + xor a +.is_in_bench + ld [wce08], a + call .CheckForDamageSwapTargetInBench + ret c ; return if not found + +; use Damage Swap + ld a, [wce08] + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + ldh [hTempCardIndex_ff9f], a + ld a, [wce08] + ldh [hTemp_ffa0], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision -Func_22790: ; 22790 (8:2790) - INCROM $22790, $227d3 + ld a, [wce06] + ld e, a +.loop_damage + ld d, 30 +.small_delay_loop + call DoFrame + dec d + jr nz, .small_delay_loop + + push de + call .CheckForDamageSwapTargetInBench + jr c, .no_more_target + + ldh [hTempRetreatCostCards], a + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ffa1], a + ld a, OPPACTION_6B15 + bank1call AIMakeDecision + pop de + dec e + jr nz, .loop_damage + +.done + ld d, 60 +.big_delay_loop + call DoFrame + dec d + jr nz, .big_delay_loop + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret + +.no_more_target + pop de + jr .done +; 0x2273c + +; looks for a target in the bench to receive damage counters. +; returns carry if one is found, and outputs remaining HP in a. +.CheckForDamageSwapTargetInBench ; 2273c (8:673c) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld b, a + ld c, PLAY_AREA_BENCH_1 + lb de, $ff, $ff + +; look for candidates in bench to get the damage counters +; only target specific card IDs. +.loop_bench + ld a, c + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + push de + call GetCardIDFromDeckIndex + ld a, e + pop de + cp CHANSEY + jr z, .found_candidate + cp KANGASKHAN + jr z, .found_candidate + cp SNORLAX + jr z, .found_candidate + cp MR_MIME + jr z, .found_candidate + +.next_play_area + inc c + ld a, c + cp b + jr nz, .loop_bench + +; done + ld a, e + cp $ff + jr nz, .no_carry + ld a, d + cp $ff + jr z, .set_carry +.no_carry + or a + ret + +.found_candidate +; found a potential candidate to receive damage counters + ld a, DUELVARS_ARENA_CARD_HP + add c + call GetTurnDuelistVariable + cp 20 + jr c, .next_play_area ; ignore cards with only 10 HP left + + ld d, c ; store damage + push de + push bc + ld e, c + farcall CountNumberOfEnergyCardsAttached + pop bc + pop de + or a + jr nz, .next_play_area ; ignore cards with attached energy + ld e, c ; store deck index + jr .next_play_area + +.set_carry + scf + ret +; 0x22790 + +; handles AI logic for attaching energy cards +; in Go Go Rain Dance deck. +HandleAIGoGoRainDanceEnergy: ; 22790 (8:6790) + ld a, [wOpponentDeckID] + cp GO_GO_RAIN_DANCE_DECK_ID + ret nz ; return if not Go Go Rain Dance deck + + ld a, BLASTOISE + call CountPokemonIDInPlayArea + ret nc ; return if no Blastoise + ld a, MUK + call CountPokemonIDInBothPlayAreas + ret c ; return if there's Muk in play + +; play all the energy cards that is needed. +.loop + farcall AIProcessAndTryToPlayEnergy + jr c, .loop + ret +; 0x227a9 + +; runs through Player's whole deck and +; sets carry if there's any Pokemon other +; than Mewtwo1. +CheckIfPlayerHasPokemonOtherThanMewtwo1: ; 227a9 (8:67a9) + call SwapTurn + ld e, 0 +.loop_deck + ld a, e + push de + call LoadCardDataToBuffer2_FromDeckIndex + pop de + ld a, [wLoadedCard2Type] + cp TYPE_ENERGY + jp nc, .next ; can be a jr + ld a, [wLoadedCard2ID] + cp MEWTWO1 + jr nz, .not_mewtwo1 +.next + inc e + ld a, DECK_SIZE + cp e + jr nz, .loop_deck + +; no carry + call SwapTurn + or a + ret + +.not_mewtwo1 + call SwapTurn + scf + ret +; 0x227d3 ; checks wcda7 and Pokemon in Play Area that are set up. ; if there's at least 4, goes to AI_TRAINER_CARD_PHASE_05. @@ -6644,6 +6972,7 @@ Func_227d3: ; 227d3 (8:67d3) cp %10000010 jr c, .asm_227e4 +; reset wcda7 xor a ld [wcda7], a jr .set_carry diff --git a/src/wram.asm b/src/wram.asm index 2a10fe2..9c20732 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1380,9 +1380,9 @@ wAIVenusaur2DeckIndex:: ; ce04 wAIVenusaur2PlayAreaLocation:: ; ce05 ds $1 +wce06:: ; ce06 ; number of cards to be transferred by AI using Energy Trans. wAINumberOfEnergyTransCards:: -wce06:: ; ce06 ds $1 wce07:: ; ce07 -- cgit v1.2.3 From d53e2db59a1562abf1b198602123672becfccda8 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 29 Apr 2020 16:43:44 +0100 Subject: Disassemble AI Pkmn Power routines --- src/engine/bank05.asm | 6 +- src/engine/bank08.asm | 472 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/engine/home.asm | 1 + src/hram.asm | 9 + src/wram.asm | 3 + 5 files changed, 471 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 1118699..349e7d3 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1218,7 +1218,7 @@ Func_1468b: ; 1468b (5:468b) farcall HandleAIGoGoRainDanceEnergy farcall HandleAIDamageSwap - farcall Func_2237f + farcall HandleAIPkmnPowers ret c farcall Func_2262d @@ -1254,7 +1254,7 @@ Func_1468b: ; 1468b (5:468b) .asm_146ed call AIDecidePlayPokemonCard farcall HandleAIDamageSwap - farcall Func_2237f + farcall HandleAIPkmnPowers ret c farcall HandleAIGoGoRainDanceEnergy ld a, $0d @@ -1298,7 +1298,7 @@ Func_1468b: ; 1468b (5:468b) .asm_1475b call AIDecidePlayPokemonCard farcall HandleAIDamageSwap - farcall Func_2237f + farcall HandleAIPkmnPowers ret c farcall HandleAIGoGoRainDanceEnergy ld a, $0d diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 9ef590b..b5a794b 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6622,7 +6622,14 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ret ; 0x2237f -Func_2237f: ; 2237f (8:637f) +; handles AI logic for using some Pkmn Powers. +; Pkmn Powers handled here are: +; - Heal; +; - Shift; +; - Peek; +; - Strange Behavior; +; - Curse. +HandleAIPkmnPowers: ; 2237f (8:637f) ld a, MUK call CountPokemonIDInBothPlayAreas ccf @@ -6676,27 +6683,27 @@ Func_2237f: ; 2237f (8:637f) ; check heal cp VILEPLUME jr nz, .check_shift - call Func_22402 + call HandleAIHeal jr .next_1 .check_shift cp VENOMOTH jr nz, .check_peek - call Func_22476 + call HandleAIShift jr .next_1 .check_peek cp MANKEY jr nz, .check_strange_behavior - call Func_224e6 + call HandleAIPeek jr .next_1 .check_strange_behavior cp SLOWBRO jr nz, .check_curse - call Func_2255d + call HandleAIStrangeBehavior jr .next_1 .check_curse cp GENGAR jr nz, .next_1 - call z, Func_225b5 + call z, HandleAICurse jr c, .done .next_1 @@ -6717,20 +6724,450 @@ Func_2237f: ; 2237f (8:637f) ret ; 0x22402 -Func_22402: ; 22402 (8:6402) - INCROM $22402, $22476 +; checks whether AI uses Heal on Pokemon in Play Area. +; input: +; c = Play Area location (PLAY_AREA_*) of Vileplume. +HandleAIHeal: ; 22402 (8:6402) + ld a, c + ldh [hTemp_ffa0], a + call .CheckHealTarget + ret nc ; return if no target to heal + push af + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + pop af + ldh [hAIHealCard], a + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x22422 + +; finds a target suitable for AI to use Heal on. +; only heals Arena card if the Defending Pokemon +; cannot KO it after Heal is used. +; returns carry if target was found and outputs +; in a the Play Area location of that card. +.CheckHealTarget ; 22422 (8:6422) +; check if Arena card has any damage counters, +; if not, check Bench instead. + ld e, PLAY_AREA_ARENA + call GetCardDamage + or a + jr z, .check_bench + + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckIfDefendingPokemonCanKnockOut + jr nc, .set_carry ; return carry if can't KO + ld d, a + ld a, DUELVARS_ARENA_CARD_HP + call GetTurnDuelistVariable + ld h, a + ld e, PLAY_AREA_ARENA + call GetCardDamage + ; this seems useless since it was already + ; checked that Arena card has damage, + ; so card damage is at least 10. + cp 10 + 1 + jr c, .check_remaining + ld a, 10 + ; a = min(10, CardDamage) + +; checks if Defending Pokemon can still KO +; if Heal is used on this card. +; if Heal prevents KO, return carry. +.check_remaining + ld l, a + ld a, h ; load remaining HP + add l ; add 1 counter to account for heal + sub d ; subtract damage of strongest opponent attack + jr c, .check_bench + jr z, .check_bench + +.set_carry + xor a ; PLAY_AREA_ARENA + scf + ret + +; check Bench for Pokemon with damage counters +; and find the one with the most damage. +.check_bench + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + lb bc, 0, 0 + ld e, PLAY_AREA_BENCH_1 +.loop_bench + ld a, e + cp d + jr z, .done + push bc + call GetCardDamage + pop bc + cp b + jr c, .next_bench + jr z, .next_bench + ld b, a ; store this damage + ld c, e ; store this Play Area location +.next_bench + inc e + jr .loop_bench + +; check if a Pokemon with damage counters was found +; in the Bench and, if so, return carry. +.done + ld a, c + or a + jr z, .not_found +; found + scf + ret +.not_found + or a + ret +; 0x22476 + +; checks whether AI uses Shift. +; input: +; c = Play Area location (PLAY_AREA_*) of Venomoth +HandleAIShift: ; 22476 (8:6476) + ld a, c + or a + ret nz ; return if Venomoth is not Arena card + + ldh [hTemp_ffa0], a + call GetArenaCardColor + call TranslateColorToWR + ld b, a + call SwapTurn + call GetArenaCardWeakness + ld [wAIDefendingPokemonWeakness], a + call SwapTurn + or a + ret z ; return if Defending Pokemon has no weakness + and b + ret nz ; return if Venomoth is already Defending card's weakness type + +; check whether there's a card in play with +; the same color as the Player's card weakness + call .CheckWhetherTurnDuelistHasColor + jr c, .found + call SwapTurn + call .CheckWhetherTurnDuelistHasColor + call SwapTurn + ret nc ; return if no color found + +.found + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + +; converts WR_* to apropriate color + ld a, [wAIDefendingPokemonWeakness] + ld b, 0 +.loop_color + bit 7, a + jr nz, .done + inc b + rlca + jr .loop_color + +; use Pkmn Power effect +.done + ld a, b + ldh [hAIPkmnPowerEffectParam], a + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x224c6 + +; returns carry if turn Duelist has a Pokemon +; with same color as wAIDefendingPokemonWeakness. +.CheckWhetherTurnDuelistHasColor ; 224c6 (8:64c6) + ld a, [wAIDefendingPokemonWeakness] + ld b, a + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable +.loop_play_area + ld a, [hli] + cp $ff + jr z, .false + push bc + call GetCardIDFromDeckIndex + call GetCardType + call TranslateColorToWR + pop bc + and b + jr z, .loop_play_area +; true + scf + ret +.false + or a + ret +; 0x224e6 + +; checks whether AI uses Peek. +; input: +; c = Play Area location (PLAY_AREA_*) of Mankey. +HandleAIPeek: ; 224e6 (8:64e6) + ld a, c + ldh [hTemp_ffa0], a + ld a, 50 + call Random + cp 3 + ret nc ; return 47 out of 50 times + +; check what to use Peek on at random + ld a, 3 + call Random + or a + jr z, .check_player_prizes + cp 2 + jr c, .check_player_hand + +; check Player's Deck + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetNonTurnDuelistVariable + cp DECK_SIZE - 1 + ret nc ; return if Player has one or no cards in Deck + ld a, $ff + jr .use_peek + +.check_player_prizes + ld a, DUELVARS_PRIZES + call GetTurnDuelistVariable + ld hl, wcda5 + and [hl] + ld [hl], a + or a + ret z ; return if no prizes (should never happen) + + ld c, a + ld b, $1 + ld d, 0 +.loop_prizes + ld a, c + and b + jr nz, .found_prize + sla b + inc d + jr .loop_prizes +.found_prize +; remove this prize's flag from the prize list +; and use Peek on first one in list (lowest bit set) + ld a, c + sub b + ld [hl], a + ld a, $40 + add d + jr .use_peek + +.check_player_hand + call SwapTurn + call CreateHandCardList + call SwapTurn + or a + ret z ; return if no cards in Hand +; shuffle list and pick the first entry to Peek + ld hl, wDuelTempList + call CountCardsInDuelTempList + call ShuffleCards + ld a, [wDuelTempList] + or $80 + +.use_peek + push af + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + pop af + ldh [hAIPkmnPowerEffectParam], a + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x2255d + +; checks whether AI uses Strange Behavior. +; input: +; c = Play Area location (PLAY_AREA_*) of Slowbro. +HandleAIStrangeBehavior: ; 2255d (8:655d) + ld a, c + or a + ret z ; return if Slowbro is Arena card + + ldh [hTemp_ffa0], a + ld e, PLAY_AREA_ARENA + call GetCardDamage + or a + ret z ; return if Arena card has no damage counters + + ld [wce06], a + ldh a, [hTemp_ffa0] + add DUELVARS_ARENA_CARD_HP + call GetTurnDuelistVariable + sub 10 + ret z ; return if Slowbro has only 10 HP remaining + +; if Slowbro can't receive all damage counters, +; only transfer remaining HP - 10 damage + ld hl, wce06 + cp [hl] + jr c, .use_strange_behavior + ld a, [hl] ; can receive all damage counters + +.use_strange_behavior + push af + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + xor a + ldh [hAIPkmnPowerEffectParam], a + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + pop af + +; loop counters chosen to transfer and use Pkmn Power + call ConvertHPToCounters + ld e, a +.loop_counters + ld d, 30 +.small_delay_loop + call DoFrame + dec d + jr nz, .small_delay_loop + push de + ld a, OPPACTION_6B15 + bank1call AIMakeDecision + pop de + dec e + jr nz, .loop_counters + +; return to main scene + ld d, 60 +.big_delay_loop + call DoFrame + dec d + jr nz, .big_delay_loop + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x225b5 + +; checks whether AI uses Curse. +; input: +; c = Play Area location (PLAY_AREA_*) of Gengar. +HandleAICurse: ; 225b5 (8:65b5) + ld a, c + ldh [hTemp_ffa0], a + +; loop Player's Play Area and checks their damage. +; finds the card with lowest remaining HP and +; stores its HP and its Play Area location + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + lb bc, 0, $ff + ld h, PLAY_AREA_ARENA + call SwapTurn +.loop_play_area_1 + push bc + call GetCardDamage + pop bc + or a + jr z, .next_1 + + inc b + ld a, e + add DUELVARS_ARENA_CARD_HP + push hl + call GetTurnDuelistVariable + pop hl + cp c + jr nc, .next_1 + ; lower HP than one stored + ld c, a ; store this HP + ld h, e ; store this Play Area location + +.next_1 + inc e + ld a, e + cp d + jr nz, .loop_play_area_1 ; reached end of Play Area + + ld a, 1 + cp b + jr nc, .failed ; return if less than 2 cards with damage + +; card in Play Area with lowest HP remaining was found. +; look for another card to take damage counter from. + ld a, h + ldh [hTempRetreatCostCards], a + ld b, a + ld a, 10 + cp c + jr z, .hp_10_remaining + ; if has more than 10 HP remaining, + ; skip Arena card in choosing which + ; card to take damage counter from. + ld e, PLAY_AREA_BENCH_1 + jr .second_card -Func_22476: ; 22476 (8:6476) - INCROM $22476, $224e6 +.hp_10_remaining + ; if Curse can KO, then include + ; Player's Arena card to take + ; damage counter from. + ld e, PLAY_AREA_ARENA -Func_224e6: ; 224e6 (8:64e6) - INCROM $224e6, $2255d +.second_card + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a +.loop_play_area_2 + ld a, e + cp b + jr z, .next_2 ; skip same Pokemon card + push bc + call GetCardDamage + pop bc + jr nz, .use_curse ; has damage counters, choose this card +.next_2 + inc e + ld a, e + cp d + jr nz, .loop_play_area_2 -Func_2255d: ; 2255d (8:655d) - INCROM $2255d, $225b5 +.failed + call SwapTurn + or a + ret -Func_225b5: ; 225b5 (8:65b5) - INCROM $225b5, $2262d +.use_curse + ld a, e + ldh [hAIPkmnPowerEffectParam], a + call SwapTurn + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + ret +; 0x2262d Func_2262d: ; 2262d (8:662d) INCROM $2262d, $226a3 @@ -6815,7 +7252,7 @@ HandleAIDamageSwap: ; 226a3 (8:66a3) ldh [hTempRetreatCostCards], a xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ffa1], a + ldh [hAIPkmnPowerEffectParam], a ld a, OPPACTION_6B15 bank1call AIMakeDecision pop de @@ -6823,6 +7260,7 @@ HandleAIDamageSwap: ; 226a3 (8:66a3) jr nz, .loop_damage .done +; return to main scene ld d, 60 .big_delay_loop call DoFrame diff --git a/src/engine/home.asm b/src/engine/home.asm index 338dbb0..c56e0c6 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -3419,6 +3419,7 @@ CreateArenaOrBenchEnergyCardList: ; 120a (0:120a) ; fill wDuelTempList with the turn holder's hand cards (their 0-59 deck indexes) ; return carry if the turn holder has no cards in hand +; and outputs in a number of cards. CreateHandCardList: ; 123b (0:123b) call FindLastCardInHand inc b diff --git a/src/hram.asm b/src/hram.asm index 2b4fbc9..f22b172 100644 --- a/src/hram.asm +++ b/src/hram.asm @@ -83,6 +83,8 @@ hTemp_ffa0:: ; ffa0 ; a PLAY_AREA_* constant (0: arena card, 1-5: bench card) hTempPlayAreaLocation_ffa1:: ; ffa1 +; parameter to be used by the AI's Pkmn Power effect +hAIPkmnPowerEffectParam:: ; ffa1 ds $1 UNION @@ -101,6 +103,13 @@ hAIEnergyTransEnergyCard:: ; ffa2 hAIEnergyTransPlayAreaLocation:: ; ffa3 ds $1 +NEXTU + +; Play Area location (PLAY_AREA_*) of card +; chosen by AI to use Heal Pkmn Power on. +hAIHealCard:: ; ffa2 + ds $1 + ENDU ; hffa8 through hffb0 belong to the text engine diff --git a/src/wram.asm b/src/wram.asm index 9c20732..c4536f6 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1383,6 +1383,9 @@ wAIVenusaur2PlayAreaLocation:: ; ce05 wce06:: ; ce06 ; number of cards to be transferred by AI using Energy Trans. wAINumberOfEnergyTransCards:: +; used for storing weakness of Player's Arena card +; in AI routine dealing with Shift Pkmn Power. +wAIDefendingPokemonWeakness:: ds $1 wce07:: ; ce07 -- cgit v1.2.3 From ed0543d3d31c879a5f331c23384971f7d316b93e Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 29 Apr 2020 18:13:57 +0100 Subject: AI Cowardice routines --- src/engine/bank05.asm | 89 ++++++++++++++++++++++++++++++++++++++----------- src/engine/bank08.asm | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/wram.asm | 1 + 3 files changed, 160 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 349e7d3..d6a99b9 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -137,7 +137,7 @@ CheckIfAnyDefendingPokemonAttackDealsSameDamageAsHP: ; 140c5 (5:40c5) ; checks AI scores for all benched Pokémon ; returns the location of the card with highest score -; in hTempPlayAreaLocation_ff9d +; in a and [hTempPlayAreaLocation_ff9d] FindHighestBenchScore: ; 140df (5:40df) ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable @@ -1214,14 +1214,14 @@ Func_1468b: ; 1468b (5:468b) ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards farcall Func_227d3 - jp nc, .asm_14776 + jp nc, .try_attack farcall HandleAIGoGoRainDanceEnergy farcall HandleAIDamageSwap farcall HandleAIPkmnPowers ret c - farcall Func_2262d + farcall HandleAICowardice ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards @@ -1247,25 +1247,32 @@ Func_1468b: ; 1468b (5:468b) call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_12 call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_146ed + jr nz, .already_played_energy_1 call AIProcessAndTryToPlayEnergy -.asm_146ed + +.already_played_energy_1 call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap farcall HandleAIPkmnPowers ret c farcall HandleAIGoGoRainDanceEnergy - ld a, $0d + ld a, $0d ; attack farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] - and $04 - jr z, .asm_14776 + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + +; used Professor Oak ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -1276,6 +1283,7 @@ Func_1468b: ; 1468b (5:468b) call AIProcessHandTrainerCards call AIDecidePlayPokemonCard ret c + ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_06 @@ -1290,34 +1298,72 @@ Func_1468b: ; 1468b (5:468b) ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_1475b + jr nz, .already_played_energy_2 call AIProcessAndTryToPlayEnergy -.asm_1475b +.already_played_energy_2 call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap farcall HandleAIPkmnPowers ret c farcall HandleAIGoGoRainDanceEnergy - ld a, $0d + ld a, $0d ; attack farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards -.asm_14776 +.try_attack ld a, $0e farcall HandleAIEnergyTrans + call AIProcessAndTryToUseAttack - ret c + ret c ; return if AI attacked ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x14786 +; handles retreating Func_14786: ; 14786 (5:4786) - INCROM $14786, $14c91 + ld a, [wce03] + or a + ret nz + + call AIDecideWhetherToRetreat + ret nc ; return if not retreating + + call AIDecideBenchPokemonToSwitchTo + ret c ; return if no Bench Pokemon + + ld [wcdd5], a + ld a, $01 + ld [wce03], a + + ld a, AI_TRAINER_CARD_PHASE_09 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_SWITCH + jr nz, .used_switch + ld a, [wcdd5] + call AIChooseEnergyToDiscardForRetreatCost + ret + +.used_switch + ld a, [wPreviousAIFlags] + and ~AI_FLAG_USED_SWITCH ; clear Switch flag + ld [wPreviousAIFlags], a + ld a, $09 ; retreat + farcall HandleAIEnergyTrans + ret +; 0x147bd + +Func_147bd: ; 147bd (5:47bd) + INCROM $147bd, $14c91 ; this routine handles how Legendary Articuno ; prioritises playing energy cards to each Pokémon. @@ -2370,7 +2416,7 @@ Func_15b54: ; 15b54 (5:5b54) ; 0x15b72 ; calculates AI score for bench Pokémon -; returns in hTempPlayAreaLocation_ff9d the +; returns in a and [hTempPlayAreaLocation_ff9d] the ; Play Area location of best card to switch to. ; returns carry if no Bench Pokemon. AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) @@ -2626,11 +2672,11 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) .asm_15d0c ld b, a - ld a, [$cdb1] + ld a, [wcdb0 + 1] or a jr z, .store_score ld h, a - ld a, [$cdb0] + ld a, [wcdb0] ld l, a .loop @@ -2675,7 +2721,12 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; handles AI action of retreating Arena Pokémon ; and chooses which energy cards to discard -; if card can't discard, return carry +; if card can't discard, return carry. +; in case it's Clefairy Doll or Mysterious Fossil, +; handle its effect to discard itself instead of retreating. +; input: +; - a = Play Area location (PLAY_AREA_*) of card to retreat to +; in case Clefairy Doll/Mysterious Fossil effect is used. AIChooseEnergyToDiscardForRetreatCost: ; 15d4f (5:5d4f) push af ld a, [wAIPlayEnergyCardForRetreat] @@ -2907,7 +2958,7 @@ AIChooseEnergyToDiscardForRetreatCost: ; 15d4f (5:5d4f) ld a, OPPACTION_USE_PKMN_POWER bank1call AIMakeDecision pop af - ldh [hTempPlayAreaLocation_ffa1], a + ldh [hAIPkmnPowerEffectParam], a ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT bank1call AIMakeDecision ld a, OPPACTION_DUEL_MAIN_SCENE diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index b5a794b..1113dc9 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6629,6 +6629,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; - Peek; ; - Strange Behavior; ; - Curse. +; returns carry if turn ended. HandleAIPkmnPowers: ; 2237f (8:637f) ld a, MUK call CountPokemonIDInBothPlayAreas @@ -7169,8 +7170,94 @@ HandleAICurse: ; 225b5 (8:65b5) ret ; 0x2262d -Func_2262d: ; 2262d (8:662d) - INCROM $2262d, $226a3 +; handles AI logic for Cowardice +HandleAICowardice: ; 2262d (8:662d) + ld a, MUK + call CountPokemonIDInBothPlayAreas + ret c ; return if there's Muk in play + + farcall AIChooseRandomlyNotToDoAction + ret c ; randomly return + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 1 + ret z ; return if only one Pokemon in Play Area + + ld b, a + ld c, PLAY_AREA_ARENA + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and CNF_SLP_PRZ + jr nz, .next +.loop + ld a, DUELVARS_ARENA_CARD + add c + call GetTurnDuelistVariable + ld [wce08], a + call GetCardIDFromDeckIndex + ld a, e + push bc + cp TENTACOOL + call z, .CheckWhetherToUseCowardice + pop bc + jr nc, .next + + dec b ; subtract 1 from number of Pokemon in Play Area + ld a, 1 + cp b + ret z ; return if no longer has Bench Pokemon + ld c, PLAY_AREA_ARENA ; reset back to Arena + jr .loop + +.next + inc c + ld a, c + cp b + jr nz, .loop + ret +; 0x22671 + +; checks whether AI uses Cowardice. +; return carry if Pkmn Power was used. +; input: +; c = Play Area location (PLAY_AREA_*) of Tentacool. +.CheckWhetherToUseCowardice ; 22671 (8:6671) + ld a, c + ldh [hTemp_ffa0], a + ld e, a + call GetCardDamage +.asm_22678 + or a + ret z ; return if has no damage counters + + ldh a, [hTemp_ffa0] + or a + jr nz, .is_benched + farcall AIDecideBenchPokemonToSwitchTo +; in case this routine is called with no Bench Pokemon, +; this introduces a bug. +; since it's only called in HandleAICowardice in case +; there's more than 1 Pokemon in Play Area, this never sets carry. + jr c, .asm_22678 + jr .use_cowardice +.is_benched + ld a, $ff +.use_cowardice + push af + ld a, [wce08] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_USE_PKMN_POWER + bank1call AIMakeDecision + pop af + ldh [hAIPkmnPowerEffectParam], a + ld a, OPPACTION_EXECUTE_PKMN_POWER_EFFECT + bank1call AIMakeDecision + ld a, OPPACTION_DUEL_MAIN_SCENE + bank1call AIMakeDecision + scf + ret +; 0x226a3 ; AI logic for Damage Swap to transfer damage from Arena card ; to a card in Bench with more than 10 HP remaining diff --git a/src/wram.asm b/src/wram.asm index c4536f6..cb97ddc 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1194,6 +1194,7 @@ wcda7:: ; cda7 wcdae:: ; cdae ds $2 +wcdb0:: ; cdb0 ds $2 ; these seem to hold pointer to some kind of -- cgit v1.2.3 From 75678c46233e53c4508c811a80923216b36c61bb Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 29 Apr 2020 20:42:00 +0100 Subject: AI init duel and turn logic --- src/engine/bank01.asm | 10 ++--- src/engine/bank05.asm | 122 ++++++++++++++++++++++++++++++++++++++------------ src/engine/bank08.asm | 12 ++--- src/wram.asm | 11 ++++- 4 files changed, 114 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index 7668903..7eb7340 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -3720,7 +3720,7 @@ Func_57df: ; 57df (1:57df) Func_5805: ; 5805 (1:5805) call Func_3b31 - ld a, [wccc8] + ld a, [wNumberPrizeCardsToTake] ld l, a ld h, $00 call LoadTxRam3 @@ -3731,7 +3731,7 @@ Func_5805: ; 5805 (1:5805) ldtx hl, WillDrawNPrizesText call DrawWideTextBox_WaitForInput - ld a, [wccc8] + ld a, [wNumberPrizeCardsToTake] call Func_310a ld hl, hTemp_ffa0 ld d, [hl] @@ -3775,7 +3775,7 @@ Func_5805: ; 5805 (1:5805) call nz, AddCardToHand .asm_586f ld a, [wcbfc] - ld hl, wccc8 + ld hl, wNumberPrizeCardsToTake cp [hl] jr nc, .asm_587e ld l, a @@ -7525,7 +7525,7 @@ Func_6fa5: ; 6fa5 (1:6fa5) ret ; 0x6fc7 -; return in wccc8 the amount of Pokemon in the turn holder's +; return in wNumberPrizeCardsToTake the amount of Pokemon in the turn holder's ; play area that are still there despite having 0 HP. ; that is, the number of Pokemon that have just been knocked out. ; Clefairy Doll and Mysterious Fossil don't count. @@ -7558,7 +7558,7 @@ CountKnockedOutPokemon: ; 6fc7 (1:6fc7) dec c jr nz, .loop ld a, b - ld [wccc8], a + ld [wNumberPrizeCardsToTake], a or a ret z scf diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index d6a99b9..d8a0a31 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -333,24 +333,90 @@ CheckIfEnergyIsUseful: ; 14184 (5:4184) ; 0x141da Func_141da: ; 141da (5:41da) - INCROM $141da, $14226 + INCROM $141da, $141e5 -Func_14226: ; 14226 (5:4226) +_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 +; 0x141f8 + +; 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 +; 0x14226 + +; 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 + ret z ; return when done call LoadCardDataToBuffer1_FromDeckIndex ld a, [wLoadedCard1Type] cp TYPE_ENERGY - jr nc, .check_for_next_card + jr nc, .check_for_next_card ; skip if not Pokemon card ld a, [wLoadedCard1Stage] or a - jr nz, .check_for_next_card + jr nz, .check_for_next_card ; skip if not Basic Stage + +; play Basic card from hand push hl ldh a, [hTempCardIndex_ff98] call PutHandPokemonCardInPlayArea @@ -1178,24 +1244,23 @@ AIProcessHandTrainerCards: ; 14663 (5:4663) ; GENERAL DECK POINTER LIST - Not sure on all of these. ; This is an example of an AI pointer table, there's one for each AI type. PointerTable_14668: ; 14668 (05:4668) - dw Func_14674 ; not used - dw Func_14674 ; general AI for battles - dw Func_14678 ; basic pokemon placement / cheater shuffling on better AI - dw Func_1467f ; deciding which Bench Pokemon to switch to + dw AIMainTurnLogic ; not used + dw AIMainTurnLogic ; general AI for battles + dw AIDuelStart ; basic pokemon placement / cheater shuffling on better AI + dw AIRetreatLogic ; deciding which Bench Pokemon to switch to dw Func_14683 - dw Func_14687 + dw AIPickPrizeCards -; when battle AI gets called -Func_14674: ; 14674 (5:4674) - call Func_1468b +AIMainTurnLogic: ; 14674 (5:4674) + call _AIMainTurnLogic ret -Func_14678: ; 14678 (5:4678) - call Func_15636 - call $4226 +AIDuelStart: ; 14678 (5:4678) + call InitAIDuelVars + call AIPlayInitialBasicCards ret -Func_1467f: ; 1467f (5:467f) +AIRetreatLogic: ; 1467f (5:467f) call AIDecideBenchPokemonToSwitchTo ret @@ -1203,13 +1268,13 @@ Func_14683: ; 14683 (5:4683) call AIDecideBenchPokemonToSwitchTo ret -Func_14687: ; 14687 (5:4687) - call $41e5 +AIPickPrizeCards: ; 14687 (5:4687) + call _AIPickPrizeCards ret -; AI for general decks i think -Func_1468b: ; 1468b (5:468b) - call Func_15649 +; handle AI routines for a whole turn +_AIMainTurnLogic: ; 1468b (5:468b) + call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards @@ -1532,22 +1597,23 @@ LookForCardIDInPlayArea_Bank5: ; 155ef (5:55ef) Func_15612: ; 15612 (5:5612) INCROM $15612, $15636 -Func_15636: ; 15636 (5:5636) +InitAIDuelVars: ; 15636 (5:5636) ld a, $10 ld hl, wcda5 call ClearMemory_Bank5 - ld a, $5 - ld [wcda6], a + ld a, 5 + ld [wAIPokedexCounter], a ld a, $ff ld [wcda5], a ret ; initializes some variables and ; sets value of wcda7. -Func_15649: ; 15649 (5:5649) - ld a, [wcda6] +InitAITurnVars: ; 15649 (5:5649) +; increase Pokedex counter by one + ld a, [wAIPokedexCounter] inc a - ld [wcda6], a + ld [wAIPokedexCounter], a xor a ld [wPreviousAIFlags], a diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 1113dc9..1c6f82a 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -3589,9 +3589,9 @@ AIPlay_Pokedex: ; 212b4 (8:52b4) ; 0x212dc AIDecide_Pokedex: ; 212dc (8:52dc) - ld a, [wcda6] - cp $06 - jr c, .no_carry + 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 @@ -3624,7 +3624,7 @@ AIDecide_Pokedex: ; 212dc (8:52dc) PickPokedexCards_Unreferenced: ; 212ff (8:52ff) ; unreferenced xor a - ld [wcda6], a + ld [wAIPokedexCounter], a ; reset counter ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable @@ -3756,7 +3756,7 @@ PickPokedexCards_Unreferenced: ; 212ff (8:52ff) ; stores the resulting order in wce1a. PickPokedexCards: ; 2138e (8:538e) xor a - ld [wcda6], a + ld [wAIPokedexCounter], a ; reset counter ; reset counter ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable @@ -6949,7 +6949,7 @@ HandleAIPeek: ; 224e6 (8:64e6) and [hl] ld [hl], a or a - ret z ; return if no prizes (should never happen) + ret z ; return if no prizes ld c, a ld b, $1 diff --git a/src/wram.asm b/src/wram.asm index cb97ddc..534297e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -967,7 +967,7 @@ wNoDamageOrEffect:: ; ccc7 ; used by CountKnockedOutPokemon and Func_5805 to store the amount ; of prizes to take (equal to the number of Pokemon knocked out) -wccc8:: ; ccc8 +wNumberPrizeCardsToTake:: ; ccc8 ds $1 ; set to 1 if the coin toss in the confusion check is heads (CheckSelfConfusionDamage) @@ -1182,7 +1182,14 @@ wcd9f:: ; cd9f wcda5:: ; cda5 ds $1 -wcda6:: ; cda6 +; this is used by AI in order to determine whether +; it should use Pokedex Trainer card. +; duel starts at 5 and counts up by one every turn. +; only when it's higher than 5 is AI allowed to use Pokedex, +; in which case it set the counter to 0. +; this stops the AI from using Pokedex right after using another one +; while still drawing cards that were ordered. +wAIPokedexCounter:: ; cda6 ds $1 wcda7:: ; cda7 -- cgit v1.2.3 From 47736d7c415ea5b38f5d9df83e7fb1e9b12a9e9e Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 11:20:19 +0100 Subject: Disassemble Sam duel scripts --- src/engine/bank05.asm | 283 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 273 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index d8a0a31..bb77536 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1,5 +1,5 @@ PointerTable_14000: ; 14000 (05:4000) - dw $47bd ; SAMS_PRACTICE_DECK + dw PointerTable_147bd ; SAMS_PRACTICE_DECK dw PointerTable_14668 ; PRACTICE_PLAYER_DECK dw PointerTable_14668 ; SAMS_NORMAL_DECK dw PointerTable_14668 ; CHARMANDER_AND_FRIENDS_DECK @@ -332,8 +332,17 @@ CheckIfEnergyIsUseful: ; 14184 (5:4184) ret ; 0x141da -Func_141da: ; 141da (5:41da) - INCROM $141da, $141e5 +; 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 +; 0x141e5 _AIPickPrizeCards: ; 141e5 (5:41e5) ld a, [wNumberPrizeCardsToTake] @@ -1427,8 +1436,229 @@ Func_14786: ; 14786 (5:4786) ret ; 0x147bd -Func_147bd: ; 147bd (5:47bd) - INCROM $147bd, $14c91 +PointerTable_147bd: ; 147bd (05:47bd) + dw Func_147c9 + dw Func_147c9 + dw Func_147d6 + dw Func_147da + dw Func_147e7 + dw Func_147f4 + +Func_147c9: ; 147c9 (5:47c9) + call IsAIPracticeScriptedTurn + jr nc, .scripted +; not scripted, use AI main turn logic + call _AIMainTurnLogic + ret +.scripted ; use scripted actions instead + call AIPerformSciptedTurn + ret +; 0x147d6 + +Func_147d6: ; 147d6 (5:47d6) + call Func_14801 + ret +; 0x147da + +Func_147da: ; 147da (5:47da) + call IsAIPracticeScriptedTurn + jr nc, .scripted + call AIDecideBenchPokemonToSwitchTo + ret +.scripted + call PickRandomBenchPokemon + ret +; 0x147e7 + +Func_147e7: ; 147e7 (5:47e7) + call IsAIPracticeScriptedTurn + jr nc, .scripted + call AIDecideBenchPokemonToSwitchTo + ret +.scripted + call GetPlayAreaLocationOfRaticateOrRattata + ret +; 0x147f4 + +Func_147f4: ; 147f4 (5:47f4) + call _AIPickPrizeCards + ret +; 0x147f8 + +; returns carry if number of turns +; the AI has taken >= 7. +; used to know whether AI Sam is still +; doing scripted turns. +IsAIPracticeScriptedTurn: ; 147f8 (5:47f8) + ld a, [wDuelTurns] + srl a + cp 7 + ccf + ret +; 0x14801 + +; places one Machop from the hand to the Play Area +; and sets the number of prizes to 2. +Func_14801: ; 14801 (5:4801) + call CreateHandCardList + ld hl, wDuelTempList +.loop_hand + ld a, [hli] + ldh [hTempCardIndex_ff98], a + cp $ff + ret z + call LoadCardDataToBuffer1_FromDeckIndex + cp MACHOP + jr nz, .loop_hand + ldh a, [hTempCardIndex_ff98] + call PutHandPokemonCardInPlayArea + ld a, 2 + ld [wDuelInitialPrizes], a + ret +; 0x1481f + +; outputs in a Play Area location of Raticate or Rattata +; in the Bench. If neither is found, just output PLAY_AREA_BENCH_1. +GetPlayAreaLocationOfRaticateOrRattata: ; 1481f (5:481f) + ld a, RATICATE + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + cp $ff + jr nz, .found + ld a, RATTATA + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + cp $ff + jr nz, .found + ld a, PLAY_AREA_BENCH_1 +.found + ldh [hTempPlayAreaLocation_ff9d], a + ret +; 0x1483a + +; has AI execute some scripted actions depending on Duel turn. +AIPerformSciptedTurn: ; 1483a (5:483a) + ld a, [wDuelTurns] + srl a + ld hl, .scripted_actions_list + call JumpToFunctionInTable + +; always attack with Arena card's first attack. +; if it's unusable end turn without attacking. + xor a + ldh [hTempPlayAreaLocation_ff9d], a + ld [wSelectedAttack], a + call CheckIfSelectedMoveIsUnusable + jr c, .unusable + call AITryUseAttack + ret + +.unusable + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x1485a + +.scripted_actions_list ; 1485a (05:485a) + dw .turn_1 + dw .turn_2 + dw .turn_3 + dw .turn_4 + dw .turn_5 + dw .turn_6 + dw .turn_7 +; 0x14868 + +.turn_1 ; 14868 (5:4868) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x14870 + +.turn_2 ; 14870 (5:4870) + ld a, RATTATA + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + ld d, RATTATA + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x14884 + +.turn_3 ; 14884 (5:4884) + ld a, RATTATA + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank5 + ldh [hTempPlayAreaLocation_ffa1], a + ld a, RATICATE + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_EVOLVE_PKMN + bank1call AIMakeDecision + ld d, RATICATE + ld e, LIGHTNING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148a1 + +.turn_4 ; 148a1 (5:48a1) + ld d, RATICATE + ld e, LIGHTNING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148a9 + +.turn_5 ; 148a9 (5:48a9) + ld a, MACHOP + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInBench + +; this is a bug, it's attempting to compare a card ID with a deck index. +; the intention was to change the card to switch to depending on whether +; the first Machop was KO'd at this point in the Duel or not. +; because of the buggy comparison, this will always jump the +; 'inc a' instruction and switch to PLAY_AREA_BENCH_1. +; in a normal Practice Duel following Dr. Mason's instructions, +; this will always lead to the AI correctly switching Raticate with Machop, +; but in case of a "Free" Duel where the first Machop is not KO'd, +; the intention was to switch to PLAY_AREA_BENCH_2 instead. +; but due to 'inc a' always being skipped, it will switch to Raticate. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + cp MACHOP ; wrong + ld a, PLAY_AREA_BENCH_1 + jr nz, .retreat + inc a ; PLAY_AREA_BENCH_2 + +.retreat + call AIChooseEnergyToDiscardForRetreatCost + ret +; 0x148cc + +.turn_6 ; 148cc (5:48cc) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148d4 + +.turn_7 ; 148d4 (5:48d4) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148dc + +Func_148dc: ; 148dc (5:48dc) + INCROM $148dc, $14c91 ; this routine handles how Legendary Articuno ; prioritises playing energy cards to each Pokémon. @@ -1594,8 +1824,42 @@ LookForCardIDInPlayArea_Bank5: ; 155ef (5:55ef) ret ; 0x15612 -Func_15612: ; 15612 (5:5612) - INCROM $15612, $15636 +; 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 +; 0x1562b + +; 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 +; 0x15636 InitAIDuelVars: ; 15636 (5:5636) ld a, $10 @@ -2786,13 +3050,12 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; 0x15d4f ; handles AI action of retreating Arena Pokémon -; and chooses which energy cards to discard +; and chooses which energy cards to discard. ; if card can't discard, return carry. ; in case it's Clefairy Doll or Mysterious Fossil, ; handle its effect to discard itself instead of retreating. ; input: -; - a = Play Area location (PLAY_AREA_*) of card to retreat to -; in case Clefairy Doll/Mysterious Fossil effect is used. +; - a = Play Area location (PLAY_AREA_*) of card to retreat to. AIChooseEnergyToDiscardForRetreatCost: ; 15d4f (5:5d4f) push af ld a, [wAIPlayEnergyCardForRetreat] -- cgit v1.2.3 From cf9a3c313b63c78ebcb4077e827eeff9a5940ba0 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 16:04:07 +0100 Subject: Unpack Legendary Moltres AI --- src/constants/duel_constants.asm | 2 + src/engine/bank05.asm | 513 +++++++++++++++++++++++++++++++++++++-- src/wram.asm | 9 +- 3 files changed, 507 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index b667c50..9cdc73b 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -3,6 +3,8 @@ MAX_PLAY_AREA_POKEMON EQU 6 ; arena + bench MAX_HP EQU 120 HP_BAR_LENGTH EQU MAX_HP / 10 +STARTING_HAND_SIZE EQU 7 + ; hWhoseTurn constants PLAYER_TURN EQUS "HIGH(wPlayerDuelVariables)" OPPONENT_TURN EQUS "HIGH(wOpponentDuelVariables)" diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index bb77536..92fc0aa 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -11,7 +11,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14668 ; LIGHTNING_AND_FIRE_DECK dw PointerTable_14668 ; WATER_AND_FIGHTING_DECK dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK - dw $49e8 ; LEGENDARY_MOLTRES_DECK + dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK dw $4b0f ; LEGENDARY_ZAPDOS_DECK dw $4c0b ; LEGENDARY_ARTICUNO_DECK dw $4d60 ; LEGENDARY_DRAGONITE_DECK @@ -1658,7 +1658,245 @@ AIPerformSciptedTurn: ; 1483a (5:483a) ; 0x148dc Func_148dc: ; 148dc (5:48dc) - INCROM $148dc, $14c91 + INCROM $148dc, $149e8 + +PointerTable_149e8: ; 149e8 (05:49e8) + dw Func_149f4 + dw Func_149f4 + dw Func_149f8 + dw Func_14a09 + dw Func_14a0d + dw Func_14a11 + +Func_149f4: ; 149f4 (5:49f4) + call Func_14a81 + ret +; 0x149f8 + +Func_149f8: ; 149f8 (5:49f8) + call InitAIDuelVars + call Func_14a4a + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc ; Play Area set up was successful + call AIPlayInitialBasicCards + ret +; 0x14a09 + +Func_14a09: ; 14a09 (5:4a09) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a0d + +Func_14a0d: ; 14a0d (5:4a0d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a11 + +Func_14a11: ; 14a11 (5:4a11) + call _AIPickPrizeCards + ret +; 0x14a15 + +Data_14a15: ; 14a15 (5:4a15) + db MAGMAR2 + db GROWLITHE + db VULPIX + db MAGMAR1 + db MOLTRES1 + db MOLTRES2 + db $00 + +Data_14a1c: ; 14a1c (5:4a1c) + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +Data_14a22: ; 14a22 (5:4a22) + db MOLTRES2 + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +Data_14a29: ; 14a29 (5:4a29) + db GROWLITHE + db $80 - 5 + db VULPIX + db $80 - 5 + db $00 + +Data_14a2e: ; 14a2e (5:4a2e) + db VULPIX + db 3 + db $80 + 0 + + db NINETAILS2 + db 3 + db $80 + 1 + + db GROWLITHE + db 3 + db $80 + 1 + + db ARCANINE2 + db 4 + db $80 + 1 + + db MAGMAR1 + db 4 + db $80 - 1 + + db MAGMAR2 + db 1 + db $80 - 1 + + db MOLTRES2 + db 3 + db $80 + 2 + + db MOLTRES1 + db 4 + db $80 + 2 + + db $00 + +Data_14a47: ; 14a47 (5:4a47) + db ENERGY_REMOVAL + db MOLTRES2 + db $00 + +Func_14a4a: ; 14a4a (5:4a4a) + ld hl, wcda8 + ld de, Data_14a47 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14a15 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14a1c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14a22 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb0 + ld de, Data_14a29 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_14a2e + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14a81 + +Func_14a81: ; 14a81 (5:4a81) + call InitAITurnVars + farcall Func_227d3 + jp nc, .try_attack + + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + +; check if AI can play Moltres2 from hand +; if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 9 + jr nc, .skip_moltres ; skip if cards in deck <= 9 + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .skip_moltres ; skip if Muk in play + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank5 + jr nc, .skip_moltres ; skip if no Moltres2 in hand + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + +.skip_moltres + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + +; handle attaching energy from hand + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_attach_energy + +; if Magmar2 is the Arena card and has no energy attached, +; try attaching an energy card to it from the hand. +; otherwise, run normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, MAGMAR2 + cp e + jr nz, .attach_normally + ; Magmar2 is the Arena card + call CreateEnergyCardListFromHand + jr c, .skip_attach_energy + ld e, PLAY_AREA_ARENA + call CountNumberOfEnergyCardsAttached + or a + jr nz, .attach_normally + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .skip_attach_energy + +.attach_normally + call AIProcessAndTryToPlayEnergy + +.skip_attach_energy +; try playing Pokemon cards from hand again + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + +.try_attack + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14b0f + +Func_14b0f: ; 14b0f (5:4b0f) + INCROM $14b0f, $14c91 ; this routine handles how Legendary Articuno ; prioritises playing energy cards to each Pokémon. @@ -2279,8 +2517,82 @@ RemoveCardIDInList: ; 157f3 (5:57f3) ret ; 0x1581b -Func_1581b: ; 1581b (5:581b) - INCROM $1581b, $158b2 +; 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, wcdaa + ld a, d + or a + jr z, .set_carry ; return if null + +; pick Arena card + call CreateHandCardList + ld hl, wDuelTempList + ld de, wcdaa + call .PlayPokemonCardInOrder + ret c + +; play Pokemon cards to Bench until there are +; a maximum of 3 cards in Play Area. +.loop + ld de, wcdac + call .PlayPokemonCardInOrder + jr c, .done + cp 3 + jr c, .loop + +.done + or a + ret +.set_carry + scf + ret +; 0x1583f + +; 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 +; 0x1585b + +Func_1585b: ; 1585b (5:585b) + INCROM $1585b, $158b2 ; determine AI score for retreating ; return carry if AI decides to retreat @@ -3009,26 +3321,26 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ld a, [wcdb0] ld l, a -.loop +.loop_ids ld a, [hli] or a - jr z, .store_score + jr z, .store_score ; list is over cp b - jr nz, .asm_15d32 + jr nz, .next_id ld a, [hl] cp $80 jr c, .asm_15d2b sub $80 call AddToAIScore - jr .asm_15d32 + jr .next_id .asm_15d2b ld c, a ld a, $80 sub c call SubFromAIScore -.asm_15d32 +.next_id inc hl - jr .loop + jr .loop_ids .store_score ldh a, [hTempPlayAreaLocation_ff9d] @@ -4126,19 +4438,19 @@ LookForEnergyNeededForMoveInHand: ; 16311 (5:6311) SortTempHandByIDList: ; 1633f (5:633f) ld a, [wcdae+1] or a - ret z + ret z ; return if list is empty ; start going down the ID list ld d, a ld a, [wcdae] ld e, a ld c, 0 -.next_list_id +.loop_list_id ; get this item's ID ; if $00, list has ended ld a, [de] or a - ret z + ret z ; return when list is over inc de ld hl, wDuelTempList ld b, 0 @@ -4150,7 +4462,7 @@ SortTempHandByIDList: ; 1633f (5:633f) ld a, [hl] ldh [hTempCardIndex_ff98], a cp -1 - jr z, .next_list_id + jr z, .loop_list_id push bc push de call GetCardIDFromDeckIndex @@ -4703,6 +5015,7 @@ AIProcessEnergyCards: ; 164fc (5:64fc) pop de cp d jr c, .check_id_score + ; already reached target number of energy cards ld a, 10 call SubFromAIScore jr .store_score @@ -7159,8 +7472,176 @@ CheckCardEvolutionInHandOrDeck: ; 17274 (5:7274) ret ; 0x172af -Func_172af ; 172af (5:72af) - INCROM $172af, $17383 +; sets up the inital hand of boss deck. +; always draws at least 2 Basic Pokemon cards and 2 Energy cards. +; also sets up so that the next cards to be drawn have +; some minimum number of Basic Pokemon and Energy cards +; and avoids deck-specific list of cards. +SetUpBossStartingHandAndDeck: ; 172af (5:72af) +; shuffle all hand cards in deck + ld a, DUELVARS_HAND + call GetTurnDuelistVariable + ld b, STARTING_HAND_SIZE +.asm_172b6 + ld a, [hl] + call RemoveCardFromHand + call ReturnCardToDeck + dec b + jr nz, .asm_172b6 + jr .count_energy_basic + +.shuffle_deck + call ShuffleDeck + +; count number of Energy and basic Pokemon cards +; in the first STARTING_HAND_SIZE in deck. +.count_energy_basic + xor a + ld [wce06], a + ld [wce08], a + + ld a, DUELVARS_DECK_CARDS + call GetTurnDuelistVariable + ld b, STARTING_HAND_SIZE +.loop_deck_1 + ld a, [hli] + push bc + call LoadCardDataToBuffer1_FromDeckIndex + pop bc + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr c, .pokemon_card_1 + cp TYPE_TRAINER + jr z, .next_card_deck_1 + +; energy card + ld a, [wce08] + inc a + ld [wce08], a + jr .next_card_deck_1 + +.pokemon_card_1 + ld a, [wLoadedCard1Stage] + or a + jr nz, .next_card_deck_1 ; not basic + ld a, [wce06] + inc a + ld [wce06], a + +.next_card_deck_1 + dec b + jr nz, .loop_deck_1 + +; tally the number of Energy and basic Pokemon cards +; and if any of them is smaller than 2, re-shuffle deck. + ld a, [wce06] + cp 2 + jr c, .shuffle_deck + ld a, [wce08] + cp 2 + jr c, .shuffle_deck + +; now check the following 6 cards. +; re-shuffle deck if any of these cards is listed in wcda8. + ld b, 6 +.check_card_ids + ld a, [hli] + push bc + call .CheckIfIDIsInList + pop bc + jr c, .shuffle_deck + dec b + jr nz, .check_card_ids + +; finally, check 6 cards after that. +; if Energy or Basic Pokemon counter is below 4 +; (counting with the ones found in the initial hand) +; then re-shuffle deck. + ld b, 6 +.loop_deck_2 + ld a, [hli] + push bc + call LoadCardDataToBuffer1_FromDeckIndex + pop bc + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr c, .pokemon_card_2 + cp TYPE_TRAINER + jr z, .next_card_deck_2 + +; energy card + ld a, [wce08] + inc a + ld [wce08], a + jr .next_card_deck_2 + +.pokemon_card_2 + ld a, [wLoadedCard1Stage] + or a + jr nz, .next_card_deck_2 + ld a, [wce06] + inc a + ld [wce06], a + +.next_card_deck_2 + dec b + jr nz, .loop_deck_2 + + ld a, [wce06] + cp 4 + jp c, .shuffle_deck + ld a, [wce08] + cp 4 + jp c, .shuffle_deck + +; draw new set of hand cards + ld a, DUELVARS_DECK_CARDS + call GetTurnDuelistVariable + ld b, STARTING_HAND_SIZE +.draw_loop + ld a, [hli] + call SearchCardInDeckAndAddToHand + call AddCardToHand + dec b + jr nz, .draw_loop + ret +; 0x17366 + +; expectation: return carry if card ID corresponding +; to the input deck index is listed in wcda8; +; reality: always returns no carry because when checking terminating +; byte in wcda8 ($00), it wrongfully uses 'cp a' instead of 'or a', +; so it always ends up returning in the first item in list. +; input: +; - a = deck index of card to check +.CheckIfIDIsInList ; 17366 (5:7366) + ld b, a + ld a, [wcda8 + 1] + or a + ret z ; null + push hl + ld h, a + ld a, [wcda8] + ld l, a + + ld a, b + call GetCardIDFromDeckIndex +.loop_id_list + ld a, [hli] + cp a ; bug, should be 'or a' + jr z, .false + cp e + jr nz, .loop_id_list + +; true + pop hl + scf + ret +.false + pop hl + or a + ret +; 0x17383 ; returns carry if Pokemon at PLAY_AREA* in a ; can damage defending Pokémon with any of its moves diff --git a/src/wram.asm b/src/wram.asm index 534297e..cae7f88 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1195,7 +1195,14 @@ wAIPokedexCounter:: ; cda6 wcda7:: ; cda7 ds $1 - ds $6 +wcda8:: ; cda8 + ds $2 + +wcdaa:: ; cdaa + ds $2 + +wcdac:: ; cdac + ds $2 ; pointer to a list of card IDs for sorting AI hand wcdae:: ; cdae -- cgit v1.2.3 From 034658ba2b623cce0d1b8626ff41c0cdf9dfd6cb Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 17:01:35 +0100 Subject: Unpack Legendary Zapdos AI --- src/engine/bank05.asm | 146 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 142 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 92fc0aa..df1fa5d 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -12,7 +12,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14668 ; WATER_AND_FIGHTING_DECK dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK - dw $4b0f ; LEGENDARY_ZAPDOS_DECK + dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK dw $4c0b ; LEGENDARY_ARTICUNO_DECK dw $4d60 ; LEGENDARY_DRAGONITE_DECK dw $4e89 ; FIRST_STRIKE_DECK @@ -1895,8 +1895,146 @@ Func_14a81: ; 14a81 (5:4a81) ret ; 0x14b0f -Func_14b0f: ; 14b0f (5:4b0f) - INCROM $14b0f, $14c91 +PointerTable_14b0f: ; 14b0f (05:4b0f) + dw Func_14b1b + dw Func_14b1b + dw Func_14b1f + dw Func_14b30 + dw Func_14b34 + dw Func_14b38 + +Func_14b1b: ; 14b1b (5:4b1b) + INCROM $14b1b, $14b1f + +Func_14b1f: ; 14b1f (5:4b1f) + call InitAIDuelVars + call Func_14b6c + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14b30 + +Func_14b30: ; 14b30 (5:4b30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b34 + +Func_14b34: ; 14b34 (5:4b34) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b38 + +Func_14b38: ; 14b38 (5:4b38) + call _AIPickPrizeCards + ret +; 0x14b3c + +Data_14b3c: ; 14b3c (5:4b3c) + db ELECTABUZZ2 + db VOLTORB + db EEVEE + db ZAPDOS1 + db ZAPDOS2 + db ZAPDOS3 + db $00 + +Data_14b43: ; 14b43 (5:4b43) + db ZAPDOS2 + db ZAPDOS1 + db EEVEE + db VOLTORB + db ELECTABUZZ2 + db $00 + +Data_14b49: ; 14b49 (5:4b49) + db EEVEE + db $80 - 5 + db VOLTORB + db $80 - 5 + db ELECTABUZZ2 + db $80 - 5 + db $00 + +Data_14b50: ; 14b50 (5:4b50) + db VOLTORB + db 1 + db $80 - 1 + + db ELECTRODE1 + db 3 + db $80 + 0 + + db ELECTABUZZ2 + db 2 + db $80 - 1 + + db JOLTEON2 + db 3 + db $80 + 1 + + db ZAPDOS1 + db 4 + db $80 + 2 + + db ZAPDOS2 + db 4 + db $80 + 2 + + db ZAPDOS3 + db 3 + db $80 + 1 + + db EEVEE + db 3 + db $80 + 0 + + db $00 + +Data_14b69: ; 14b69 (5:4b69) + db GAMBLER + db ZAPDOS3 + db $00 + +Func_14b6c: ; 14b6c (5:4b6c) + ld hl, wcda8 + ld de, Data_14b69 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14b3c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14b43 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14b43 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14b50 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14b9a + +Func_14b9a: ; 14b9a (5:4b9a) + INCROM $14b9a, $14c91 ; this routine handles how Legendary Articuno ; prioritises playing energy cards to each Pokémon. @@ -2002,7 +2140,7 @@ Data_1514f: ; 1514f (5:514f) ; input: ; a = card ID ; output: -; a = card deck index, if found +; a = card deck index, if found ; carry set if found LookForCardIDInHandList_Bank5: ; 155d2 (5:55d2) ld [wTempCardIDToLook], a -- cgit v1.2.3 From ca8bac48dc6870062ff6cf546d908643f3b6fbca Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 17:58:11 +0100 Subject: Unpack Legendary Articuno AI --- src/engine/bank05.asm | 136 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 134 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index df1fa5d..b2f8c47 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -13,7 +13,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK - dw $4c0b ; LEGENDARY_ARTICUNO_DECK + dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK dw $4d60 ; LEGENDARY_DRAGONITE_DECK dw $4e89 ; FIRST_STRIKE_DECK dw $4f0e ; ROCK_CRUSHER_DECK @@ -2034,7 +2034,139 @@ Func_14b6c: ; 14b6c (5:4b6c) ; 0x14b9a Func_14b9a: ; 14b9a (5:4b9a) - INCROM $14b9a, $14c91 + INCROM $14b9a, $14c0b + +PointerTable_14c0b: ; 14c0b (5:4c0b) + dw Func_14c17 + dw Func_14c17 + dw Func_14c1b + dw Func_14c2c + dw Func_14c30 + dw Func_14c34 + +Func_14c17: ; 14c17 (5:4c17) + INCROM $14c17, $14c1b + +Func_14c1b: ; 14c1b (5:4c1b) + call InitAIDuelVars + call Func_14c63 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14c2c + +Func_14c2c: ; 14c2c (5:4c2c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c30 + +Func_14c30: ; 14c30 (5:4c30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c34 + +Func_14c34: ; 14c34 (5:4c34) + call _AIPickPrizeCards + ret +; 0x14c38 + +Data_14c38: ; 14c38 (5:4c38) + db CHANSEY + db LAPRAS + db DITTO + db SEEL + db ARTICUNO1 + db ARTICUNO2 + db $00 + +Data_14c3f: ; 14c3f (5:4c3f) + db ARTICUNO1 + db SEEL + db LAPRAS + db CHANSEY + db DITTO + db $00 + +Data_14c45: ; 14c45 (5:4c45) + db SEEL + db $80 - 3 + db DITTO + db $80 - 3 + db $00 + +Data_14c4a: ; 14c4a (5:4c4a) + db SEEL + db 3 + db $80 + 1 + + db DEWGONG + db 4 + db $80 + 0 + + db LAPRAS + db 3 + db $80 + 0 + + db ARTICUNO1 + db 4 + db $80 + 1 + + db ARTICUNO2 + db 3 + db $80 + 0 + + db CHANSEY + db 0 + db $80 - 8 + + db DITTO + db 3 + db $80 + 0 + + db $00 + +Data_14c60: ; 14c60 (5:4c60) + db GAMBLER + db ARTICUNO2 + db $00 + +Func_14c63: ; 14c63 (5:4c63) + ld hl, wcda8 + ld de, Data_14c60 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14c38 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14c3f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14c3f + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14c4a + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14c91 ; this routine handles how Legendary Articuno ; prioritises playing energy cards to each Pokémon. -- cgit v1.2.3 From 6cf73da905c32beeb8e1abc63b503e12871b775d Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 18:51:41 +0100 Subject: Unpack Legendary Dragonite AI --- src/engine/bank05.asm | 151 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index b2f8c47..2e57173 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -14,7 +14,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK - dw $4d60 ; LEGENDARY_DRAGONITE_DECK + dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK dw $4e89 ; FIRST_STRIKE_DECK dw $4f0e ; ROCK_CRUSHER_DECK dw $4f8f ; GO_GO_RAIN_DANCE_DECK @@ -2244,7 +2244,154 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) ; 0x14cf7 Func_14cf7: ; 14cf7 (5:4cf7) - INCROM $14cf7, $1514f + INCROM $14cf7, $14d60 + +PointerTable_14d60: ; 14d60 (05:4d60) + dw Func_14d6c + dw Func_14d6c + dw Func_14d70 + dw Func_14d81 + dw Func_14d85 + dw Func_14d89 + +Func_14d6c: ; 14d6c (5:4d6c) + INCROM $14d6c, $14d70 + +Func_14d70: ; 14d70 (5:4d70) + call InitAIDuelVars + call Func_14dc1 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14d81 + +Func_14d81: ; 14d81 (5:4d81) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d85 + +Func_14d85: ; 14d85 (5:4d85) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d89 + +Func_14d89: ; 14d89 (5:4d89) + call _AIPickPrizeCards + ret +; 0x14d8d + +Data_14d8d: ; 14d8d (5:4d8d) + db KANGASKHAN + db LAPRAS + db CHARMANDER + db DRATINI + db MAGIKARP + db $00 + +Data_14d93: ; 14d93 (5:4d93) + db CHARMANDER + db MAGIKARP + db DRATINI + db LAPRAS + db KANGASKHAN + db $00 + +Data_14d99: ; 14d99 (5:4d99) + db CHARMANDER + db $80 - 1 + db MAGIKARP + db $80 - 5 + db $00 + +Data_14d9e: ; 14d9e (5:4d9e) + db CHARMANDER + db 3 + db $80 + 1 + + db CHARMELEON + db 4 + db $80 + 1 + + db CHARIZARD + db 5 + db $80 + 0 + + db MAGIKARP + db 3 + db $80 + 1 + + db GYARADOS + db 4 + db $80 - 1 + + db DRATINI + db 2 + db $80 + 0 + + db DRAGONAIR + db 4 + db $80 + 0 + + db DRAGONITE1 + db 3 + db $80 - 1 + + db KANGASKHAN + db 2 + db $80 - 2 + + db LAPRAS + db 3 + db $80 + 0 + + db $00 + +Data_14dbd: ; 14dbd (5:4dbd) + db GAMBLER + db DRAGONITE1 + db KANGASKHAN + db $00 + +Func_14dc1: ; 14dc1 (5:4dc1) + ld hl, wcda8 + ld de, Data_14dbd + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14d8d + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14d93 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14d93 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14d9e + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14def + +Func_14def: ; 14def (5:4def) + INCROM $14def, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From 2e1c7a1934382df139e2c396e58c10516186d349 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 19:18:33 +0100 Subject: Unpack First Strike AI --- src/engine/bank05.asm | 138 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 2e57173..002c670 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -15,7 +15,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK - dw $4e89 ; FIRST_STRIKE_DECK + dw PointerTable_14e89 ; FIRST_STRIKE_DECK dw $4f0e ; ROCK_CRUSHER_DECK dw $4f8f ; GO_GO_RAIN_DANCE_DECK dw $5019 ; ZAPPING_SELFDESTRUCT_DECK @@ -2391,7 +2391,141 @@ Func_14dc1: ; 14dc1 (5:4dc1) ; 0x14def Func_14def: ; 14def (5:4def) - INCROM $14def, $1514f + INCROM $14def, $14e89 + +PointerTable_14e89: ; 14e89 (5:4e89) + dw Func_14e95 + dw Func_14e95 + dw Func_14e99 + dw Func_14eaa + dw Func_14eae + dw Func_14eb2 + +Func_14e95: ; 14e95 (5:4e95) + INCROM $14e95, $14e99 + +Func_14e99: ; 14e99 (5:4e99) + call InitAIDuelVars + call Func_14ee0 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14eaa + +Func_14eaa: ; 14eaa (5:4eaa) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eae + +Func_14eae: ; 14eae (5:4eae) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eb2 + +Func_14eb2: ; 14eb2 (5:4eb2) + call _AIPickPrizeCards + ret +; 0x14eb6 + +Data_14eb6: ; 14eb6 (5:1eb6) + db HITMONCHAN + db MACHOP + db HITMONLEE + db MANKEY + db $00 + +Data_14ebb: ; 14ebb (5:1ebb) + db MACHOP + db HITMONLEE + db HITMONCHAN + db MANKEY + db $00 + +Data_14ec0: ; 14ec0 (5:1ec0) + db MACHOP + db $80 - 1 + db MACHOKE + db $80 - 1 + db MANKEY + db $80 - 2 + db $00 + +Data_14ec7: ; 14ec7 (5:1ec7) + db MACHOP + db 3 + db $80 + + db MACHOKE + db 4 + db $80 + + db MACHAMP + db 4 + db $80 - 1 + + db HITMONCHAN + db 3 + db $80 + + db HITMONLEE + db 3 + db $80 + + db MANKEY + db 2 + db $80 - 1 + + db PRIMEAPE + db 3 + db $80 - 1 + + db $00 + +Data_14edd: ; 14edd (5:1edd) + db HITMONLEE + db HITMONCHAN + db $00 + +Func_14ee0: ; 14ee0 (5:4ee0) + ld hl, wcda8 + ld de, Data_14edd + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14eb6 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14ebb + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14ebb + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14ec7 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14f0e + +Func_14f0e: ; 14f0e (5:4f0e) + INCROM $14f0e, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From 242195b1b96e7abba4f561be00431a3d5ec222fd Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 19:32:51 +0100 Subject: Unpack Rock Crusher AI --- src/engine/bank05.asm | 133 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 002c670..c430880 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -16,7 +16,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK dw PointerTable_14e89 ; FIRST_STRIKE_DECK - dw $4f0e ; ROCK_CRUSHER_DECK + dw PointerTable_14f0e ; ROCK_CRUSHER_DECK dw $4f8f ; GO_GO_RAIN_DANCE_DECK dw $5019 ; ZAPPING_SELFDESTRUCT_DECK dw $509b ; FLOWER_POWER_DECK @@ -2524,8 +2524,135 @@ Func_14ee0: ; 14ee0 (5:4ee0) ret ; 0x14f0e -Func_14f0e: ; 14f0e (5:4f0e) - INCROM $14f0e, $1514f +PointerTable_14f0e: ; 14f0e (5:4f0e) + dw Func_14f1a + dw Func_14f1a + dw Func_14f1e + dw Func_14f2f + dw Func_14f33 + dw Func_14f37 + +Func_14f1a: ; 14f1a (5:4f1a) + INCROM $14f1a, $14f1e + +Func_14f1e: ; 14f1e (5:4f1e) + call InitAIDuelVars + call Func_14f61 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14f2f + +Func_14f2f: ; 14f2f (5:4f2f) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f33 + +Func_14f33: ; 14f33 (5:4f33) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f37 + +Func_14f37: ; 14f37 (5:4f37) + call _AIPickPrizeCards + ret +; 0x14f3b + +Data_14f3b: ; 14f3b (5:4f3b) + db RHYHORN + db ONIX + db GEODUDE + db DIGLETT + db $00 + +Data_14f40: ; 14f40 (5:4f40) + db DIGLETT + db GEODUDE + db RHYHORN + db ONIX + db $00 + +Data_14f45: ; 14f45 (5:4f45) + db DIGLETT + db $80 - 1 + db $00 + +Data_14f48: ; 14f48 (5:4f48) + db DIGLETT + db 3 + db $80 + 1 + + db DUGTRIO + db 4 + db $80 + 0 + + db GEODUDE + db 2 + db $80 + 1 + + db GRAVELER + db 3 + db $80 + 0 + + db GOLEM + db 4 + db $80 + 0 + + db ONIX + db 2 + db $80 - 1 + + db RHYHORN + db 3 + db $80 + 0 + + db $00 + +Data_14f5e: ; 14f5e (5:4f5e) + db ENERGY_REMOVAL + db RHYHORN + db $00 + +Func_14f61: ; 14f61 (5:4f61) + ld hl, wcda8 + ld de, Data_14f5e + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14f3b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14f40 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14f40 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14f48 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14f8f + +Func_14f8f: ; 14f8f (5:4f8f) + INCROM $14f8f, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From a75b2f973a9a16cd8e2d4886e8bf7532492ba86c Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 19:49:44 +0100 Subject: Unpack Go Go Rain Dance AI --- src/engine/bank05.asm | 143 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index c430880..ad2d6b4 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -17,7 +17,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK dw PointerTable_14e89 ; FIRST_STRIKE_DECK dw PointerTable_14f0e ; ROCK_CRUSHER_DECK - dw $4f8f ; GO_GO_RAIN_DANCE_DECK + dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK dw $5019 ; ZAPPING_SELFDESTRUCT_DECK dw $509b ; FLOWER_POWER_DECK dw $5122 ; STRANGE_PSYSHOCK_DECK @@ -2651,8 +2651,145 @@ Func_14f61: ; 14f61 (5:4f61) ret ; 0x14f8f -Func_14f8f: ; 14f8f (5:4f8f) - INCROM $14f8f, $1514f +PointerTable_14f8f: ; 14f8f (5:4f8f) + dw Func_14f9b + dw Func_14f9b + dw Func_14f9f + dw Func_14fb0 + dw Func_14fb4 + dw Func_14fb8 + +Func_14f9b: ; 14f9b (5:4f9b) + INCROM $14f9b, $14f9f + +Func_14f9f: ; 14f9f (5:4f9f) + call InitAIDuelVars + call Func_14feb + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14fb0 + +Func_14fb0: ; 14fb0 (5:4fb0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb4 + +Func_14fb4: ; 14fb4 (5:4fb4) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb8 + +Func_14fb8: ; 14fb8 (5:4fb8) + call _AIPickPrizeCards + ret +; 0x14fbc + +Data_14fbc: ; 14fbc (5:4fbc) + db LAPRAS + db HORSEA + db GOLDEEN + db SQUIRTLE + db $00 + +Data_14fc1: ; 14fc1 (5:4fc1) + db SQUIRTLE + db HORSEA + db GOLDEEN + db LAPRAS + db $00 + +Data_14fc6: ; 14fc6 (5:4fc6) + db SQUIRTLE + db $80 - 3 + db WARTORTLE + db $80 - 2 + db HORSEA + db $80 - 1 + db $00 + +Data_14fcd: ; 14fcd (5:4fcd) + db SQUIRTLE + db 2 + db $80 + 0 + + db WARTORTLE + db 3 + db $80 + 0 + + db BLASTOISE + db 5 + db $80 + 0 + + db GOLDEEN + db 1 + db $80 + 0 + + db SEAKING + db 2 + db $80 + 0 + + db HORSEA + db 2 + db $80 + 0 + + db SEADRA + db 3 + db $80 + 0 + + db LAPRAS + db 3 + db $80 + 0 + + db $00 + +Data_14fe6: ; 14fe6 (5:4fe6) + db GAMBLER + db ENERGY_RETRIEVAL + db SUPER_ENERGY_RETRIEVAL + db BLASTOISE + db $00 + +Func_14feb: ; 14feb (5:4feb) + ld hl, wcda8 + ld de, Data_14fe6 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14fbc + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14fc1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14fc1 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14fcd + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15019 + +Func_15019: ; 15019 (5:5019) + INCROM $15019, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From d162e1bda676fb51a656472960bb63f354919b37 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 20:01:20 +0100 Subject: Unpack Zapping Selfdestruct AI --- src/engine/bank05.asm | 132 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 129 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index ad2d6b4..a5abcd8 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -18,7 +18,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14e89 ; FIRST_STRIKE_DECK dw PointerTable_14f0e ; ROCK_CRUSHER_DECK dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK - dw $5019 ; ZAPPING_SELFDESTRUCT_DECK + dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK dw $509b ; FLOWER_POWER_DECK dw $5122 ; STRANGE_PSYSHOCK_DECK dw $51ad ; WONDERS_OF_SCIENCE_DECK @@ -2788,8 +2788,134 @@ Func_14feb: ; 14feb (5:4feb) ret ; 0x15019 -Func_15019: ; 15019 (5:5019) - INCROM $15019, $1514f +PointerTable_15019: ; 15019 (5:5019) + dw Func_15025 + dw Func_15025 + dw Func_15029 + dw Func_1503a + dw Func_1503e + dw Func_15042 + +Func_15025: ; 15025 (5:5025) + INCROM $15025, $15029 + +Func_15029: ; 15029 (5:5029) + call InitAIDuelVars + call Func_1506d + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1503a + +Func_1503a: ; 1503a (5:503a) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1503e + +Func_1503e: ; 1503e (5:503e) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15042 + +Func_15042: ; 15042 (5:5042) + call _AIPickPrizeCards + ret +; 0x15046 + +Data_15046: ; 15046 (5:5046) + db KANGASKHAN + db ELECTABUZZ2 + db TAUROS + db MAGNEMITE1 + db VOLTORB + db $00 + +Data_1504c: ; 1504c (5:504c) + db MAGNEMITE1 + db VOLTORB + db ELECTABUZZ2 + db TAUROS + db KANGASKHAN + db $00 + +Data_15052: ; 15052 (5:5052) + db VOLTORB + db $80 - 1 + db $00 + +Data_15055: ; 15055 (5:5055) + db MAGNEMITE1 + db 3 + db $80 + 1 + + db MAGNETON1 + db 4 + db $80 + 0 + + db VOLTORB + db 3 + db $80 + 1 + + db ELECTRODE1 + db 3 + db $80 + 0 + + db ELECTABUZZ2 + db 1 + db $80 + 0 + + db KANGASKHAN + db 2 + db $80 - 2 + + db TAUROS + db 3 + db $80 + 0 + + db $00 + +Data_1506b: ; 1506b (5:506b) + db KANGASKHAN + db $00 + +Func_1506d: ; 1506d (5:506d) + ld hl, wcda8 + ld de, Data_1506b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15046 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_1504c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_1504c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_15055 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1509b + +Func_1509b: ; 1509b (5:509b) + INCROM $1509b, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From cd81fb59453cb8306c93a8ec9d4f05113f3a2b48 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 20:22:06 +0100 Subject: Unpack Flower Power AI --- src/engine/bank05.asm | 140 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index a5abcd8..2d5d8cc 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -19,7 +19,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14f0e ; ROCK_CRUSHER_DECK dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK - dw $509b ; FLOWER_POWER_DECK + dw PointerTable_1509b ; FLOWER_POWER_DECK dw $5122 ; STRANGE_PSYSHOCK_DECK dw $51ad ; WONDERS_OF_SCIENCE_DECK dw $5232 ; FIRE_CHARGE_DECK @@ -2914,8 +2914,142 @@ Func_1506d: ; 1506d (5:506d) ret ; 0x1509b -Func_1509b: ; 1509b (5:509b) - INCROM $1509b, $1514f +PointerTable_1509b: ; 1509b (5:509b) + dw Func_150a7 + dw Func_150a7 + dw Func_150ab + dw Func_150bc + dw Func_150c0 + dw Func_150c4 + +Func_150a7: ; 150a7 (5:50a7) + INCROM $150a7, $150ab + +Func_150ab: ; 150ab (5:50ab) + call InitAIDuelVars + call Func_150f4 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x150bc + +Func_150bc: ; 150bc (5:50bc) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c0 + +Func_150c0: ; 150c0 (5:50c0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c4 + +Func_150c4: ; 150c4 (5:50c4) + call _AIPickPrizeCards + ret +; 0x150c8 + +Data_150c8 ; 150c8 (5:50c8) + db ODDISH + db EXEGGCUTE + db BULBASAUR + db $00 + +Data_150cc ; 150cc (5:50cc) + db BULBASAUR + db EXEGGCUTE + db ODDISH + db $00 + +Data_150cf ; 150cf (5:50cf) + db GLOOM + db $80 - 2 + db VILEPLUME + db $80 - 2 + db BULBASAUR + db $80 - 2 + db IVYSAUR + db $80 - 2 + db $00 + +Data_150d9 ; 150d9 (5:50d9) + db BULBASAUR + db 3 + db $80 + 0 + + db IVYSAUR + db 4 + db $80 + 0 + + db VENUSAUR2 + db 4 + db $80 + 0 + + db ODDISH + db 2 + db $80 + 0 + + db GLOOM + db 3 + db $80 - 1 + + db VILEPLUME + db 3 + db $80 - 1 + + db EXEGGCUTE + db 3 + db $80 + 0 + + db EXEGGUTOR + db 22 + db $80 + 0 + + db $00 + +Data_150f2 ; 150f2 (5:50f2) + db VENUSAUR2 + db $00 + +Func_150f4: ; 150f4 (5:50f4) + ld hl, wcda8 + ld de, Data_150f2 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_150c8 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_150cc + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_150cc + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_150d9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15122 + +Func_15122: ; 15122 (5:5122) + INCROM $15122, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand -- cgit v1.2.3 From ba22f3fa6b065bd84f5f8605ffd46b9e9fe91d1c Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 20:39:15 +0100 Subject: Unpack Strange Psyshock AI --- src/engine/bank05.asm | 128 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 122 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 2d5d8cc..6ee57ae 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -20,7 +20,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK dw PointerTable_1509b ; FLOWER_POWER_DECK - dw $5122 ; STRANGE_PSYSHOCK_DECK + dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK dw $51ad ; WONDERS_OF_SCIENCE_DECK dw $5232 ; FIRE_CHARGE_DECK dw $52bd ; IM_RONALD_DECK @@ -3048,11 +3048,42 @@ Func_150f4: ; 150f4 (5:50f4) ret ; 0x15122 -Func_15122: ; 15122 (5:5122) - INCROM $15122, $1514f +PointerTable_15122: ; 15122 (5:5122) + dw Func_1512e + dw Func_1512e + dw Func_15132 + dw Func_15143 + dw Func_15147 + dw Func_1514b + +Func_1512e: ; 1512e (5:512e) + INCROM $1512e, $15132 + +Func_15132: ; 15132 (5:5132) + call InitAIDuelVars + call Func_1517f + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15143 + +Func_15143: ; 15143 (5:5143) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15147 + +Func_15147: ; 15147 (5:5147) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1514b + +Func_1514b: ; 1514b (5:514b) + call _AIPickPrizeCards + ret +; 0x1514f -; these seem to be lists of card IDs -; for the AI to look up in their hand Data_1514f: ; 1514f (5:514f) db KANGASKHAN db CHANSEY @@ -3061,6 +3092,7 @@ Data_1514f: ; 1514f (5:514f) db ABRA db $00 +Data_15155: ; 15155 (5:5155) db ABRA db MR_MIME db KANGASKHAN @@ -3068,7 +3100,91 @@ Data_1514f: ; 1514f (5:514f) db CHANSEY db $00 - INCROM $1515b, $155d2 +Data_1515b: ; 1515b (5:515b) + db ABRA + db $80 - 3 + db SNORLAX + db $80 - 3 + db KANGASKHAN + db $80 - 1 + db CHANSEY + db $80 - 1 + db $00 + +Data_15164 ; 15164 (5:5164) + db ABRA + db 3 + db $80 + 1 + + db KADABRA + db 3 + db $80 + 0 + + db ALAKAZAM + db 3 + db $80 + 0 + + db MR_MIME + db 2 + db $80 + 0 + + db CHANSEY + db 2 + db $80 - 2 + + db KANGASKHAN + db 4 + db $80 - 2 + + db SNORLAX + db 0 + db $80 - 8 + + db $00 + +Data_1517a ; 1517a (5:517a) + db GAMBLER + db MR_MIME + db ALAKAZAM + db SWITCH + db $00 + +Func_1517f: ; 1517f (5:517f) + ld hl, wcda8 + ld de, Data_1517a + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1514f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15155 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15155 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_15164 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x151ad + +Func_151ad: ; 151ad (5:51ad) + INCROM $151ad, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From 1d3fb18c67c686ea666d570de76314f2821a8f14 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 20:52:18 +0100 Subject: Unpack Wonders of Science AI --- src/engine/bank05.asm | 136 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 6ee57ae..58eb240 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -21,7 +21,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK dw PointerTable_1509b ; FLOWER_POWER_DECK dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK - dw $51ad ; WONDERS_OF_SCIENCE_DECK + dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK dw $5232 ; FIRE_CHARGE_DECK dw $52bd ; IM_RONALD_DECK dw $534b ; POWERFUL_RONALD_DECK @@ -3183,8 +3183,138 @@ Func_1517f: ; 1517f (5:517f) ret ; 0x151ad -Func_151ad: ; 151ad (5:51ad) - INCROM $151ad, $155d2 +PointerTable_151ad: ; 151ad (5:51ad) + dw Func_151b9 + dw Func_151b9 + dw Func_151bd + dw Func_151ce + dw Func_151d2 + dw Func_151d6 + +Func_151b9: ; 151b9 (5:51b9) + INCROM $151b9, $151bd + +Func_151bd: ; 151bd (5:51bd) + call InitAIDuelVars + call Func_15204 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x151ce + +Func_151ce: ; 151ce (5:51ce) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d2 + +Func_151d2: ; 151d2 (5:51d2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d6 + +Func_151d6: ; 151d6 (5:51d6) + call _AIPickPrizeCards + ret +; 0x151da + +Data_151da: ; 151da (5:51da) + db MEWTWO1 + db MEWTWO3 + db MEWTWO2 + db GRIMER + db KOFFING + db PORYGON + db $00 + +Data_151e1: ; 151e1 (5:51e1) + db GRIMER + db KOFFING + db MEWTWO3 + db MEWTWO2 + db MEWTWO1 + db PORYGON + db $00 + +Data_151e8: ; 151e8 (5:51e8) + db $00 + +Data_151e9: ; 151e9 (5:51e9) + db GRIMER + db 3 + db $80 + 0 + + db MUK + db 4 + db $80 + 0 + + db KOFFING + db 2 + db $80 + 0 + + db WEEZING + db 3 + db $80 + 0 + + db MEWTWO1 + db 2 + db $80 - 1 + + db MEWTWO3 + db 2 + db $80 - 1 + + db MEWTWO2 + db 2 + db $80 - 1 + + db PORYGON + db 2 + db $80 - 1 + + db $00 + +Data_15202: ; 15202 (5:5202) + db MUK + db $00 + +Func_15204: ; 15204 (5:5204) + ld hl, wcda8 + ld de, Data_15202 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_151da + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_151e1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_151e1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_151e9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15232 + +Func_15232: ; 15232 (5:5232) + INCROM $15232, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From e123bd3c3f54ad74143b19ef1497d25eb61cf72c Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 21:15:26 +0100 Subject: Unpack Fire Charge AI --- src/engine/bank05.asm | 142 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 139 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 58eb240..973f753 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -22,7 +22,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_1509b ; FLOWER_POWER_DECK dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK - dw $5232 ; FIRE_CHARGE_DECK + dw PointerTable_15232 ; FIRE_CHARGE_DECK dw $52bd ; IM_RONALD_DECK dw $534b ; POWERFUL_RONALD_DECK dw $53e8 ; INVINCIBLE_RONALD_DECK @@ -3313,8 +3313,144 @@ Func_15204: ; 15204 (5:5204) ret ; 0x15232 -Func_15232: ; 15232 (5:5232) - INCROM $15232, $155d2 +PointerTable_15232: ; 15232 (5:5232) + dw Func_1523e + dw Func_1523e + dw Func_15242 + dw Func_15253 + dw Func_15257 + dw Func_1525b + +Func_1523e: ; 1523e (5:523e) + INCROM $1523e, $15242 + +Func_15242: ; 15242 (5:5242) + call InitAIDuelVars + call Func_1528f + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15253 + +Func_15253: ; 15253 (5:5253) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15257 + +Func_15257: ; 15257 (5:5257) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1525b + +Func_1525b: ; 1525b (5:525b) + call _AIPickPrizeCards + ret +; 0x1525f + +Data_1525f: ; 1525f (5:525f) + db JIGGLYPUFF3 + db CHANSEY + db TAUROS + db MAGMAR1 + db JIGGLYPUFF1 + db GROWLITHE + db $00 + +Data_15266: ; 15266 (5:5266) + db JIGGLYPUFF3 + db CHANSEY + db GROWLITHE + db MAGMAR1 + db JIGGLYPUFF1 + db TAUROS + db $00 + +Data_1526e: ; 1526e (5:526e) + db JIGGLYPUFF1 + db $80 - 1 + db CHANSEY + db $80 - 1 + db GROWLITHE + db $80 - 1 + db $00 + +Data_15274: ; 15274 (5:5274) + db GROWLITHE + db 3 + db $80 + 0 + + db ARCANINE2 + db 4 + db $80 + 0 + + db MAGMAR1 + db 3 + db $80 + 0 + + db JIGGLYPUFF1 + db 3 + db $80 + 0 + + db JIGGLYPUFF3 + db 2 + db $80 + 0 + + db WIGGLYTUFF + db 3 + db $80 + 0 + + db CHANSEY + db 4 + db $80 + 0 + + db TAUROS + db 3 + db $80 + 0 + + db $00 + +Data_1528d: ; 1528d (5:528d) + db GAMBLER + db $00 + +Func_1528f: ; 1528f (5:528f) + ld hl, wcda8 + ld de, Data_1528d + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1525f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15266 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15266 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_15274 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x152bd + +Func_152bd: ; 152bd (5:52bd) + INCROM $152bd, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From 6669dbb15e57a350eba01d54964192223c9df234 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 21:35:43 +0100 Subject: Unpack Im Ronald AI --- src/engine/bank05.asm | 151 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 147 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 973f753..1521c27 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -23,7 +23,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK dw PointerTable_15232 ; FIRE_CHARGE_DECK - dw $52bd ; IM_RONALD_DECK + dw PointerTable_152bd ; IM_RONALD_DECK dw $534b ; POWERFUL_RONALD_DECK dw $53e8 ; INVINCIBLE_RONALD_DECK dw $546f ; LEGENDARY_RONALD_DECK @@ -3313,7 +3313,7 @@ Func_15204: ; 15204 (5:5204) ret ; 0x15232 -PointerTable_15232: ; 15232 (5:5232) +PointerTable_15232: ; 15232 (5:52PointerTable_12) dw Func_1523e dw Func_1523e dw Func_15242 @@ -3449,8 +3449,151 @@ Func_1528f: ; 1528f (5:528f) ret ; 0x152bd -Func_152bd: ; 152bd (5:52bd) - INCROM $152bd, $155d2 + +PointerTable_152bd: ; 152bd (5:52bd) + dw Func_152c9 + dw Func_152c9 + dw Func_152cd + dw Func_152de + dw Func_152e2 + dw Func_152e6 + +Func_152c9: ; 152c9 (5:52c9) + INCROM $152c9, $152cd + +Func_152cd: ; 152cd (5:52cd) + call InitAIDuelVars + call Func_1531d + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x152de + +Func_152de: ; 152de (5:52de) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e2 + +Func_152e2: ; 152e2 (5:52e2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e6 + +Func_152e6: ; 152e6 (5:52e6) + call _AIPickPrizeCards + ret +; 0x152ea + +Data_152ea: ; 152ea (5:52ea) + db LAPRAS + db SEEL + db CHARMANDER + db CUBONE + db SQUIRTLE + db GROWLITHE + db $00 + +Data_152f1: ; 152f1 (5:52f1) + db CHARMANDER + db SQUIRTLE + db SEEL + db CUBONE + db GROWLITHE + db LAPRAS + db $00 + +Data_152f8: ; 152f8 (5:52f8) + db $00 + +Data_152f9: ; 152f9 (5:52f9) + db CHARMANDER + db 3 + db $80 + 0 + + db CHARMELEON + db 5 + db $80 + 0 + + db GROWLITHE + db 2 + db $80 + 0 + + db ARCANINE2 + db 4 + db $80 + 0 + + db SQUIRTLE + db 2 + db $80 + 0 + + db WARTORTLE + db 3 + db $80 + 0 + + db SEEL + db 3 + db $80 + 0 + + db DEWGONG + db 4 + db $80 + 0 + + db LAPRAS + db 3 + db $80 + 0 + + db CUBONE + db 3 + db $80 + 0 + + db MAROWAK1 + db 3 + db $80 + 0 + + db $00 + +Data_1531b: ; 1531b (5:531b) + db LAPRAS + db $00 + +Func_1531d: ; 1531d (5:531d) + ld hl, wcda8 + ld de, Data_1531b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_152ea + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_152f1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_152f1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_152f9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1534b + +Func_1534b: ; 1534b (5:534b) + INCROM $1534b, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From 6018422a4fc24799a24ef72fb58404fb4f3b9a7c Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 22:00:05 +0100 Subject: Unpack Powerful Ronald AI --- src/engine/bank05.asm | 164 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 1521c27..74635c8 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -24,7 +24,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK dw PointerTable_15232 ; FIRE_CHARGE_DECK dw PointerTable_152bd ; IM_RONALD_DECK - dw $534b ; POWERFUL_RONALD_DECK + dw PointerTable_1534b ; POWERFUL_RONALD_DECK dw $53e8 ; INVINCIBLE_RONALD_DECK dw $546f ; LEGENDARY_RONALD_DECK dw $48dc ; MUSCLES_FOR_BRAINS_DECK @@ -3449,7 +3449,6 @@ Func_1528f: ; 1528f (5:528f) ret ; 0x152bd - PointerTable_152bd: ; 152bd (5:52bd) dw Func_152c9 dw Func_152c9 @@ -3592,8 +3591,165 @@ Func_1531d: ; 1531d (5:531d) ret ; 0x1534b -Func_1534b: ; 1534b (5:534b) - INCROM $1534b, $155d2 +PointerTable_1534b: ; 1534b (5:534b) + dw Func_15357 + dw Func_15357 + dw Func_1535b + dw Func_1536c + dw Func_15370 + dw Func_15374 + +Func_15357: ; 15357 (5:5357) + INCROM $15357, $1535b + +Func_1535b: ; 1535b (5:535b) + call InitAIDuelVars + call Func_153ba + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1536c + +Func_1536c: ; 1536c (5:536c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15370 + +Func_15370: ; 15370 (5:5370) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15374 + +Func_15374: ; 15374 (5:5374) + call _AIPickPrizeCards + ret +; 0x15378 + +Data_15378: ; 15378 (5:5378) + db KANGASKHAN + db ELECTABUZZ2 + db HITMONCHAN + db MR_MIME + db LICKITUNG + db HITMONLEE + db TAUROS + db JYNX + db MEWTWO1 + db DODUO + db $00 + +Data_15383: ; 15383 (5:5383) + db KANGASKHAN + db HITMONLEE + db HITMONCHAN + db TAUROS + db DODUO + db JYNX + db MEWTWO1 + db ELECTABUZZ2 + db MR_MIME + db LICKITUNG + db $00 + +Data_1538e: ; 1538e (5:538e) + db KANGASKHAN + db $80 - 1 + db DODUO + db $80 - 1 + db DODRIO + db $80 - 1 + db $00 + +Data_15395: ; 15395 (5:5395) + db ELECTABUZZ2 + db 2 + db $80 + 1 + + db HITMONLEE + db 3 + db $80 + 1 + + db HITMONCHAN + db 3 + db $80 + 1 + + db MR_MIME + db 2 + db $80 + 0 + + db JYNX + db 3 + db $80 + 0 + + db MEWTWO1 + db 2 + db $80 + 0 + + db DODUO + db 3 + db $80 - 1 + + db DODRIO + db 3 + db $80 - 1 + + db LICKITUNG + db 2 + db $80 + 0 + + db KANGASKHAN + db 4 + db $80 - 1 + + db TAUROS + db 3 + db $80 + 0 + + db $00 + +Data_153b7: ; 153b7 (5:53b7) + db GAMBLER + db ENERGY_REMOVAL + db $00 + +Func_153ba: ; 153ba (5:53ba) + ld hl, wcda8 + ld de, Data_153b7 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15378 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15383 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15383 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_15395 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x153e8 + +Func_153e8: ; 153e8 (5:53e8) + INCROM $153e8, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From 0097fcd47d38496f8118667c900463e4a958322b Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 22:12:08 +0100 Subject: Unpack Invincible Ronald AI --- src/engine/bank05.asm | 138 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 74635c8..ea8543d 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -25,7 +25,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_15232 ; FIRE_CHARGE_DECK dw PointerTable_152bd ; IM_RONALD_DECK dw PointerTable_1534b ; POWERFUL_RONALD_DECK - dw $53e8 ; INVINCIBLE_RONALD_DECK + dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK dw $546f ; LEGENDARY_RONALD_DECK dw $48dc ; MUSCLES_FOR_BRAINS_DECK dw PointerTable_14668 ; HEATED_BATTLE_DECK @@ -3748,8 +3748,140 @@ Func_153ba: ; 153ba (5:53ba) ret ; 0x153e8 -Func_153e8: ; 153e8 (5:53e8) - INCROM $153e8, $155d2 +PointerTable_153e8: ; 153e8 (5:53e8) + dw Func_153f4 + dw Func_153f4 + dw Func_153f8 + dw Func_15409 + dw Func_1540d + dw Func_15411 + +Func_153f4: ; 153f4 (5:53f4) + INCROM $153f4, $153f8 + +Func_153f8: ; 153f8 (5:53f8) + call InitAIDuelVars + call Func_15441 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15409 + +Func_15409: ; 15409 (5:5409) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1540d + +Func_1540d: ; 1540d (5:540d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15411 + +Func_15411: ; 15411 (5:5411) + call _AIPickPrizeCards + ret +; 0x15415 + +Data_15415: ; 15415 (5:5415) + db KANGASKHAN + db MAGMAR2 + db CHANSEY + db GEODUDE + db SCYTHER + db GRIMER + db $00 + +Data_1541c: ; 1541c (5:541c) + db GRIMER + db SCYTHER + db GEODUDE + db CHANSEY + db MAGMAR2 + db KANGASKHAN + db $00 + +Data_15423: ; 15423 (5:5423) + db GRIMER + db $80 - 1 + db $00 + +Data_15426: ; 15426 (5:5426) + db GRIMER + db 1 + db $80 - 1 + + db MUK + db 3 + db $80 - 1 + + db SCYTHER + db 4 + db $80 + 1 + + db MAGMAR2 + db 2 + db $80 + 0 + + db GEODUDE + db 2 + db $80 + 0 + + db GRAVELER + db 3 + db $80 + 0 + + db CHANSEY + db 4 + db $80 + 0 + + db KANGASKHAN + db 4 + db $80 - 1 + + db $00 + +Data_1543f: ; 1543f (5:543f) + db GAMBLER + db $00 + +Func_15441: ; 15441 (5:5441) + ld hl, wcda8 + ld de, Data_1543f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15415 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_1541c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_1541c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_15426 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1546f + +Func_1546f: ; 1546f (5:546f) + INCROM $1546f, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From d128e3c263654b20455f00fbd73d046758754789 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 22:22:47 +0100 Subject: Unpack Legendary Ronald AI --- src/engine/bank05.asm | 160 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index ea8543d..44ab4df 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -26,7 +26,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_152bd ; IM_RONALD_DECK dw PointerTable_1534b ; POWERFUL_RONALD_DECK dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK - dw $546f ; LEGENDARY_RONALD_DECK + dw PointerTable_1546f ; LEGENDARY_RONALD_DECK dw $48dc ; MUSCLES_FOR_BRAINS_DECK dw PointerTable_14668 ; HEATED_BATTLE_DECK dw PointerTable_14668 ; LOVE_TO_BATTLE_DECK @@ -3880,8 +3880,162 @@ Func_15441: ; 15441 (5:5441) ret ; 0x1546f -Func_1546f: ; 1546f (5:546f) - INCROM $1546f, $155d2 +PointerTable_1546f: ; 1546f (5:546f) + dw Func_1547b + dw Func_1547b + dw Func_1547f + dw Func_15490 + dw Func_15494 + dw Func_15498 + +Func_1547b: ; 1547b (5:547b) + INCROM $1547b, $1547f + +Func_1547f: ; 1547f (5:547f) + call InitAIDuelVars + call Func_154d9 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15490 + +Func_15490: ; 15490 (5:5490) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15494 + +Func_15494: ; 15494 (5:5494) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15498 + +Func_15498: ; 15498 (5:5498) + call _AIPickPrizeCards + ret +; 0x1549c + +Data_1549c: ; 1549c (5:549c) + db KANGASKHAN + db DRATINI + db EEVEE + db ZAPDOS3 + db ARTICUNO2 + db MOLTRES2 + db $00 + +Data_154a3: ; 154a3 (5:54a3) + db KANGASKHAN + db DRATINI + db EEVEE + db $00 + +Data_154a7: ; 154a7 (5:54a7) + db MOLTRES2 + db ZAPDOS3 + db KANGASKHAN + db DRATINI + db EEVEE + db ARTICUNO2 + db $00 + +Data_154ae: ; 154ae (5:54ae) + db EEVEE + db $80 - 2 + db $00 + +Data_154b1: ; 154b1 (5:54b1) + db FLAREON1 + db 3 + db $80 + + db MOLTRES2 + db 3 + db $80 + + db VAPOREON1 + db 3 + db $80 + + db ARTICUNO2 + db 0 + db $78 + + db JOLTEON1 + db 4 + db $80 + + db ZAPDOS3 + db 0 + db $78 + + db KANGASKHAN + db 4 + db $7f + + db EEVEE + db 3 + db $80 + + db DRATINI + db 3 + db $80 + + db DRAGONAIR + db 4 + db $80 + + db DRAGONITE1 + db 3 + db $80 + + db $00 + +Data_154d3: ; 154d3 (5:54d3) + db MOLTRES2 + db ARTICUNO2 + db ZAPDOS3 + db DRAGONITE1 + db GAMBLER + db $00 + +Func_154d9: ; 154d9 (5:54d9) + ld hl, wcda8 + ld de, Data_154d3 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1549c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_154a3 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_154a7 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_154b1 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15507 + +Func_15507: ; 15507 (5:5507) + INCROM $15507, $155d2 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card -- cgit v1.2.3 From a8aa9e3ce480725646534ea4a2c13049c72a0770 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 30 Apr 2020 22:28:33 +0100 Subject: Unpack Muscle For Brains AI --- src/engine/bank05.asm | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 44ab4df..2b2b3f8 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -27,7 +27,7 @@ PointerTable_14000: ; 14000 (05:4000) dw PointerTable_1534b ; POWERFUL_RONALD_DECK dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK dw PointerTable_1546f ; LEGENDARY_RONALD_DECK - dw $48dc ; MUSCLES_FOR_BRAINS_DECK + dw PointerTable_148dc ; MUSCLES_FOR_BRAINS_DECK dw PointerTable_14668 ; HEATED_BATTLE_DECK dw PointerTable_14668 ; LOVE_TO_BATTLE_DECK dw PointerTable_14668 ; EXCAVATION_DECK @@ -1657,8 +1657,40 @@ AIPerformSciptedTurn: ; 1483a (5:483a) ret ; 0x148dc -Func_148dc: ; 148dc (5:48dc) - INCROM $148dc, $149e8 +PointerTable_148dc: ; 148dc (5:48dc) + dw Func_148e8 + dw Func_148e8 + dw Func_148ec + dw Func_148f3 + dw Func_148f7 + dw Func_148fb + +Func_148e8: ; 148e8 (5:48e8) + INCROM $148e8, $148ec + +Func_148ec: ; 148ec (5:48ec) + call InitAIDuelVars + call AIPlayInitialBasicCards + ret +; 0x148f3 + +Func_148f3: ; 148f3 (5:48f3) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148f7 + +Func_148f7: ; 148f7 (5:48f7) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148fb + +Func_148fb: ; 148fb (5:48fb) + call _AIPickPrizeCards + ret +; 0x148ff + +Func_148ff: ; 148ff (5:48ff) + INCROM $148ff, $149e8 PointerTable_149e8: ; 149e8 (05:49e8) dw Func_149f4 -- cgit v1.2.3 From 3f7b71184a621c9238ebd24908f78d8618de1b76 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 1 May 2020 10:53:20 +0100 Subject: Re-structure deck AI routines and macros --- src/data/deck_ai_pointers.asm | 55 + src/engine/bank05.asm | 2465 +---------------------------------------- src/engine/deck_ai.asm | 2011 +++++++++++++++++++++++++++++++++ 3 files changed, 2068 insertions(+), 2463 deletions(-) create mode 100644 src/data/deck_ai_pointers.asm create mode 100644 src/engine/deck_ai.asm (limited to 'src') diff --git a/src/data/deck_ai_pointers.asm b/src/data/deck_ai_pointers.asm new file mode 100644 index 0000000..13f148b --- /dev/null +++ b/src/data/deck_ai_pointers.asm @@ -0,0 +1,55 @@ +PointerTable_14000: ; 14000 (05:4000) + dw PointerTable_147bd ; SAMS_PRACTICE_DECK + dw PointerTable_14668 ; PRACTICE_PLAYER_DECK + dw PointerTable_14668 ; SAMS_NORMAL_DECK + dw PointerTable_14668 ; CHARMANDER_AND_FRIENDS_DECK + dw PointerTable_14668 ; CHARMANDER_EXTRA_DECK + dw PointerTable_14668 ; SQUIRTLE_AND_FRIENDS_DECK + dw PointerTable_14668 ; SQUIRTLE_EXTRA_DECK + dw PointerTable_14668 ; BULBASAUR_AND_FRIENDS_DECK + dw PointerTable_14668 ; BULBASAUR_EXTRA_DECK + dw PointerTable_14668 ; LIGHTNING_AND_FIRE_DECK + dw PointerTable_14668 ; WATER_AND_FIGHTING_DECK + dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK + dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK + dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK + dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK + dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK + dw PointerTable_14e89 ; FIRST_STRIKE_DECK + dw PointerTable_14f0e ; ROCK_CRUSHER_DECK + dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK + dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK + dw PointerTable_1509b ; FLOWER_POWER_DECK + dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK + dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK + dw PointerTable_15232 ; FIRE_CHARGE_DECK + dw PointerTable_152bd ; IM_RONALD_DECK + dw PointerTable_1534b ; POWERFUL_RONALD_DECK + dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK + dw PointerTable_1546f ; LEGENDARY_RONALD_DECK + dw PointerTable_148dc ; MUSCLES_FOR_BRAINS_DECK + dw PointerTable_14668 ; HEATED_BATTLE_DECK + dw PointerTable_14668 ; LOVE_TO_BATTLE_DECK + dw PointerTable_14668 ; EXCAVATION_DECK + dw PointerTable_14668 ; BLISTERING_POKEMON_DECK + dw PointerTable_14668 ; HARD_POKEMON_DECK + dw PointerTable_14668 ; WATERFRONT_POKEMON_DECK + dw PointerTable_14668 ; LONELY_FRIENDS_DECK + dw PointerTable_14668 ; SOUND_OF_THE_WAVES_DECK + dw PointerTable_14668 ; PIKACHU_DECK + dw PointerTable_14668 ; BOOM_BOOM_SELFDESTRUCT_DECK + dw PointerTable_14668 ; POWER_GENERATOR_DECK + dw PointerTable_14668 ; ETCETERA_DECK + dw PointerTable_14668 ; FLOWER_GARDEN_DECK + dw PointerTable_14668 ; KALEIDOSCOPE_DECK + dw PointerTable_14668 ; GHOST_DECK + dw PointerTable_14668 ; NAP_TIME_DECK + dw PointerTable_14668 ; STRANGE_POWER_DECK + dw PointerTable_14668 ; FLYIN_POKEMON_DECK + dw PointerTable_14668 ; LOVELY_NIDORAN_DECK + dw PointerTable_14668 ; POISON_DECK + dw PointerTable_14668 ; ANGER_DECK + dw PointerTable_14668 ; FLAMETHROWER_DECK + dw PointerTable_14668 ; RESHUFFLE_DECK + dw PointerTable_148dc ; IMAKUNI_DECK +; 1406a diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 2b2b3f8..96ebe50 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1,58 +1,4 @@ -PointerTable_14000: ; 14000 (05:4000) - dw PointerTable_147bd ; SAMS_PRACTICE_DECK - dw PointerTable_14668 ; PRACTICE_PLAYER_DECK - dw PointerTable_14668 ; SAMS_NORMAL_DECK - dw PointerTable_14668 ; CHARMANDER_AND_FRIENDS_DECK - dw PointerTable_14668 ; CHARMANDER_EXTRA_DECK - dw PointerTable_14668 ; SQUIRTLE_AND_FRIENDS_DECK - dw PointerTable_14668 ; SQUIRTLE_EXTRA_DECK - dw PointerTable_14668 ; BULBASAUR_AND_FRIENDS_DECK - dw PointerTable_14668 ; BULBASAUR_EXTRA_DECK - dw PointerTable_14668 ; LIGHTNING_AND_FIRE_DECK - dw PointerTable_14668 ; WATER_AND_FIGHTING_DECK - dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK - dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK - dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK - dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK - dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK - dw PointerTable_14e89 ; FIRST_STRIKE_DECK - dw PointerTable_14f0e ; ROCK_CRUSHER_DECK - dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK - dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK - dw PointerTable_1509b ; FLOWER_POWER_DECK - dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK - dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK - dw PointerTable_15232 ; FIRE_CHARGE_DECK - dw PointerTable_152bd ; IM_RONALD_DECK - dw PointerTable_1534b ; POWERFUL_RONALD_DECK - dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK - dw PointerTable_1546f ; LEGENDARY_RONALD_DECK - dw PointerTable_148dc ; MUSCLES_FOR_BRAINS_DECK - dw PointerTable_14668 ; HEATED_BATTLE_DECK - dw PointerTable_14668 ; LOVE_TO_BATTLE_DECK - dw PointerTable_14668 ; EXCAVATION_DECK - dw PointerTable_14668 ; BLISTERING_POKEMON_DECK - dw PointerTable_14668 ; HARD_POKEMON_DECK - dw PointerTable_14668 ; WATERFRONT_POKEMON_DECK - dw PointerTable_14668 ; LONELY_FRIENDS_DECK - dw PointerTable_14668 ; SOUND_OF_THE_WAVES_DECK - dw PointerTable_14668 ; PIKACHU_DECK - dw PointerTable_14668 ; BOOM_BOOM_SELFDESTRUCT_DECK - dw PointerTable_14668 ; POWER_GENERATOR_DECK - dw PointerTable_14668 ; ETCETERA_DECK - dw PointerTable_14668 ; FLOWER_GARDEN_DECK - dw PointerTable_14668 ; KALEIDOSCOPE_DECK - dw PointerTable_14668 ; GHOST_DECK - dw PointerTable_14668 ; NAP_TIME_DECK - dw PointerTable_14668 ; STRANGE_POWER_DECK - dw PointerTable_14668 ; FLYIN_POKEMON_DECK - dw PointerTable_14668 ; LOVELY_NIDORAN_DECK - dw PointerTable_14668 ; POISON_DECK - dw PointerTable_14668 ; ANGER_DECK - dw PointerTable_14668 ; FLAMETHROWER_DECK - dw PointerTable_14668 ; RESHUFFLE_DECK - dw $48dc ; IMAKUNI_DECK -; 1406a +INCLUDE "data/deck_ai_pointers.asm" PointerTable_1406a: ; 1406a (5:406a) dw $406c @@ -1657,2414 +1603,7 @@ AIPerformSciptedTurn: ; 1483a (5:483a) ret ; 0x148dc -PointerTable_148dc: ; 148dc (5:48dc) - dw Func_148e8 - dw Func_148e8 - dw Func_148ec - dw Func_148f3 - dw Func_148f7 - dw Func_148fb - -Func_148e8: ; 148e8 (5:48e8) - INCROM $148e8, $148ec - -Func_148ec: ; 148ec (5:48ec) - call InitAIDuelVars - call AIPlayInitialBasicCards - ret -; 0x148f3 - -Func_148f3: ; 148f3 (5:48f3) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x148f7 - -Func_148f7: ; 148f7 (5:48f7) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x148fb - -Func_148fb: ; 148fb (5:48fb) - call _AIPickPrizeCards - ret -; 0x148ff - -Func_148ff: ; 148ff (5:48ff) - INCROM $148ff, $149e8 - -PointerTable_149e8: ; 149e8 (05:49e8) - dw Func_149f4 - dw Func_149f4 - dw Func_149f8 - dw Func_14a09 - dw Func_14a0d - dw Func_14a11 - -Func_149f4: ; 149f4 (5:49f4) - call Func_14a81 - ret -; 0x149f8 - -Func_149f8: ; 149f8 (5:49f8) - call InitAIDuelVars - call Func_14a4a - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc ; Play Area set up was successful - call AIPlayInitialBasicCards - ret -; 0x14a09 - -Func_14a09: ; 14a09 (5:4a09) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14a0d - -Func_14a0d: ; 14a0d (5:4a0d) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14a11 - -Func_14a11: ; 14a11 (5:4a11) - call _AIPickPrizeCards - ret -; 0x14a15 - -Data_14a15: ; 14a15 (5:4a15) - db MAGMAR2 - db GROWLITHE - db VULPIX - db MAGMAR1 - db MOLTRES1 - db MOLTRES2 - db $00 - -Data_14a1c: ; 14a1c (5:4a1c) - db MOLTRES1 - db VULPIX - db GROWLITHE - db MAGMAR2 - db MAGMAR1 - db $00 - -Data_14a22: ; 14a22 (5:4a22) - db MOLTRES2 - db MOLTRES1 - db VULPIX - db GROWLITHE - db MAGMAR2 - db MAGMAR1 - db $00 - -Data_14a29: ; 14a29 (5:4a29) - db GROWLITHE - db $80 - 5 - db VULPIX - db $80 - 5 - db $00 - -Data_14a2e: ; 14a2e (5:4a2e) - db VULPIX - db 3 - db $80 + 0 - - db NINETAILS2 - db 3 - db $80 + 1 - - db GROWLITHE - db 3 - db $80 + 1 - - db ARCANINE2 - db 4 - db $80 + 1 - - db MAGMAR1 - db 4 - db $80 - 1 - - db MAGMAR2 - db 1 - db $80 - 1 - - db MOLTRES2 - db 3 - db $80 + 2 - - db MOLTRES1 - db 4 - db $80 + 2 - - db $00 - -Data_14a47: ; 14a47 (5:4a47) - db ENERGY_REMOVAL - db MOLTRES2 - db $00 - -Func_14a4a: ; 14a4a (5:4a4a) - ld hl, wcda8 - ld de, Data_14a47 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14a15 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14a1c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14a22 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb0 - ld de, Data_14a29 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_14a2e - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14a81 - -Func_14a81: ; 14a81 (5:4a81) - call InitAITurnVars - farcall Func_227d3 - jp nc, .try_attack - - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - -; check if AI can play Moltres2 from hand -; if so, play it. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .skip_moltres ; skip if bench is full - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 9 - jr nc, .skip_moltres ; skip if cards in deck <= 9 - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .skip_moltres ; skip if Muk in play - ld a, MOLTRES2 - call LookForCardIDInHandList_Bank5 - jr nc, .skip_moltres ; skip if no Moltres2 in hand - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - -.skip_moltres - call AIDecidePlayPokemonCard - ret c - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - call Func_14786 - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - -; handle attaching energy from hand - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_attach_energy - -; if Magmar2 is the Arena card and has no energy attached, -; try attaching an energy card to it from the hand. -; otherwise, run normal AI energy attach routine. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, MAGMAR2 - cp e - jr nz, .attach_normally - ; Magmar2 is the Arena card - call CreateEnergyCardListFromHand - jr c, .skip_attach_energy - ld e, PLAY_AREA_ARENA - call CountNumberOfEnergyCardsAttached - or a - jr nz, .attach_normally - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call AITryToPlayEnergyCard - jr c, .skip_attach_energy - -.attach_normally - call AIProcessAndTryToPlayEnergy - -.skip_attach_energy -; try playing Pokemon cards from hand again - call AIDecidePlayPokemonCard - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - -.try_attack - call AIProcessAndTryToUseAttack - ret c - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14b0f - -PointerTable_14b0f: ; 14b0f (05:4b0f) - dw Func_14b1b - dw Func_14b1b - dw Func_14b1f - dw Func_14b30 - dw Func_14b34 - dw Func_14b38 - -Func_14b1b: ; 14b1b (5:4b1b) - INCROM $14b1b, $14b1f - -Func_14b1f: ; 14b1f (5:4b1f) - call InitAIDuelVars - call Func_14b6c - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14b30 - -Func_14b30: ; 14b30 (5:4b30) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14b34 - -Func_14b34: ; 14b34 (5:4b34) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14b38 - -Func_14b38: ; 14b38 (5:4b38) - call _AIPickPrizeCards - ret -; 0x14b3c - -Data_14b3c: ; 14b3c (5:4b3c) - db ELECTABUZZ2 - db VOLTORB - db EEVEE - db ZAPDOS1 - db ZAPDOS2 - db ZAPDOS3 - db $00 - -Data_14b43: ; 14b43 (5:4b43) - db ZAPDOS2 - db ZAPDOS1 - db EEVEE - db VOLTORB - db ELECTABUZZ2 - db $00 - -Data_14b49: ; 14b49 (5:4b49) - db EEVEE - db $80 - 5 - db VOLTORB - db $80 - 5 - db ELECTABUZZ2 - db $80 - 5 - db $00 - -Data_14b50: ; 14b50 (5:4b50) - db VOLTORB - db 1 - db $80 - 1 - - db ELECTRODE1 - db 3 - db $80 + 0 - - db ELECTABUZZ2 - db 2 - db $80 - 1 - - db JOLTEON2 - db 3 - db $80 + 1 - - db ZAPDOS1 - db 4 - db $80 + 2 - - db ZAPDOS2 - db 4 - db $80 + 2 - - db ZAPDOS3 - db 3 - db $80 + 1 - - db EEVEE - db 3 - db $80 + 0 - - db $00 - -Data_14b69: ; 14b69 (5:4b69) - db GAMBLER - db ZAPDOS3 - db $00 - -Func_14b6c: ; 14b6c (5:4b6c) - ld hl, wcda8 - ld de, Data_14b69 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14b3c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14b43 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14b43 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14b50 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14b9a - -Func_14b9a: ; 14b9a (5:4b9a) - INCROM $14b9a, $14c0b - -PointerTable_14c0b: ; 14c0b (5:4c0b) - dw Func_14c17 - dw Func_14c17 - dw Func_14c1b - dw Func_14c2c - dw Func_14c30 - dw Func_14c34 - -Func_14c17: ; 14c17 (5:4c17) - INCROM $14c17, $14c1b - -Func_14c1b: ; 14c1b (5:4c1b) - call InitAIDuelVars - call Func_14c63 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14c2c - -Func_14c2c: ; 14c2c (5:4c2c) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14c30 - -Func_14c30: ; 14c30 (5:4c30) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14c34 - -Func_14c34: ; 14c34 (5:4c34) - call _AIPickPrizeCards - ret -; 0x14c38 - -Data_14c38: ; 14c38 (5:4c38) - db CHANSEY - db LAPRAS - db DITTO - db SEEL - db ARTICUNO1 - db ARTICUNO2 - db $00 - -Data_14c3f: ; 14c3f (5:4c3f) - db ARTICUNO1 - db SEEL - db LAPRAS - db CHANSEY - db DITTO - db $00 - -Data_14c45: ; 14c45 (5:4c45) - db SEEL - db $80 - 3 - db DITTO - db $80 - 3 - db $00 - -Data_14c4a: ; 14c4a (5:4c4a) - db SEEL - db 3 - db $80 + 1 - - db DEWGONG - db 4 - db $80 + 0 - - db LAPRAS - db 3 - db $80 + 0 - - db ARTICUNO1 - db 4 - db $80 + 1 - - db ARTICUNO2 - db 3 - db $80 + 0 - - db CHANSEY - db 0 - db $80 - 8 - - db DITTO - db 3 - db $80 + 0 - - db $00 - -Data_14c60: ; 14c60 (5:4c60) - db GAMBLER - db ARTICUNO2 - db $00 - -Func_14c63: ; 14c63 (5:4c63) - ld hl, wcda8 - ld de, Data_14c60 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14c38 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14c3f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14c3f - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14c4a - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14c91 - -; this routine handles how Legendary Articuno -; prioritises playing energy cards to each Pokémon. -; first, it makes sure that all Lapras have at least -; 3 energy cards before moving on to Articuno, -; and then to Dewgong and Seel -ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) - call SwapTurn - call CountPrizes - call SwapTurn - cp 3 - ret c - -; player prizes >= 3 -; if Lapras has more than half HP and -; can use second move, check next for Articuno -; otherwise, check if Articuno or Dewgong -; have more than half HP and can use second move -; and if so, the next Pokémon to check is Lapras - ld a, LAPRAS - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .articuno - ld a, ARTICUNO1 - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .lapras - ld a, DEWGONG - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .lapras - jr .articuno - -; the following routines check for certain card IDs in bench -; and call RaiseAIScoreToAllMatchingIDsInBench if these are found. -; for Lapras, an additional check is made to its -; attached energy count, which skips calling the routine -; if this count is >= 3 -.lapras - ld a, LAPRAS - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .articuno - ld e, a - call CountNumberOfEnergyCardsAttached - cp 3 - jr nc, .articuno - ld a, LAPRAS - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.articuno - ld a, ARTICUNO1 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .dewgong - ld a, ARTICUNO1 - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.dewgong - ld a, DEWGONG - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .seel - ld a, DEWGONG - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.seel - ld a, SEEL - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - ret nc - ld a, SEEL - call RaiseAIScoreToAllMatchingIDsInBench - ret -; 0x14cf7 - -Func_14cf7: ; 14cf7 (5:4cf7) - INCROM $14cf7, $14d60 - -PointerTable_14d60: ; 14d60 (05:4d60) - dw Func_14d6c - dw Func_14d6c - dw Func_14d70 - dw Func_14d81 - dw Func_14d85 - dw Func_14d89 - -Func_14d6c: ; 14d6c (5:4d6c) - INCROM $14d6c, $14d70 - -Func_14d70: ; 14d70 (5:4d70) - call InitAIDuelVars - call Func_14dc1 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14d81 - -Func_14d81: ; 14d81 (5:4d81) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14d85 - -Func_14d85: ; 14d85 (5:4d85) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14d89 - -Func_14d89: ; 14d89 (5:4d89) - call _AIPickPrizeCards - ret -; 0x14d8d - -Data_14d8d: ; 14d8d (5:4d8d) - db KANGASKHAN - db LAPRAS - db CHARMANDER - db DRATINI - db MAGIKARP - db $00 - -Data_14d93: ; 14d93 (5:4d93) - db CHARMANDER - db MAGIKARP - db DRATINI - db LAPRAS - db KANGASKHAN - db $00 - -Data_14d99: ; 14d99 (5:4d99) - db CHARMANDER - db $80 - 1 - db MAGIKARP - db $80 - 5 - db $00 - -Data_14d9e: ; 14d9e (5:4d9e) - db CHARMANDER - db 3 - db $80 + 1 - - db CHARMELEON - db 4 - db $80 + 1 - - db CHARIZARD - db 5 - db $80 + 0 - - db MAGIKARP - db 3 - db $80 + 1 - - db GYARADOS - db 4 - db $80 - 1 - - db DRATINI - db 2 - db $80 + 0 - - db DRAGONAIR - db 4 - db $80 + 0 - - db DRAGONITE1 - db 3 - db $80 - 1 - - db KANGASKHAN - db 2 - db $80 - 2 - - db LAPRAS - db 3 - db $80 + 0 - - db $00 - -Data_14dbd: ; 14dbd (5:4dbd) - db GAMBLER - db DRAGONITE1 - db KANGASKHAN - db $00 - -Func_14dc1: ; 14dc1 (5:4dc1) - ld hl, wcda8 - ld de, Data_14dbd - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14d8d - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14d93 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14d93 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14d9e - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14def - -Func_14def: ; 14def (5:4def) - INCROM $14def, $14e89 - -PointerTable_14e89: ; 14e89 (5:4e89) - dw Func_14e95 - dw Func_14e95 - dw Func_14e99 - dw Func_14eaa - dw Func_14eae - dw Func_14eb2 - -Func_14e95: ; 14e95 (5:4e95) - INCROM $14e95, $14e99 - -Func_14e99: ; 14e99 (5:4e99) - call InitAIDuelVars - call Func_14ee0 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14eaa - -Func_14eaa: ; 14eaa (5:4eaa) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14eae - -Func_14eae: ; 14eae (5:4eae) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14eb2 - -Func_14eb2: ; 14eb2 (5:4eb2) - call _AIPickPrizeCards - ret -; 0x14eb6 - -Data_14eb6: ; 14eb6 (5:1eb6) - db HITMONCHAN - db MACHOP - db HITMONLEE - db MANKEY - db $00 - -Data_14ebb: ; 14ebb (5:1ebb) - db MACHOP - db HITMONLEE - db HITMONCHAN - db MANKEY - db $00 - -Data_14ec0: ; 14ec0 (5:1ec0) - db MACHOP - db $80 - 1 - db MACHOKE - db $80 - 1 - db MANKEY - db $80 - 2 - db $00 - -Data_14ec7: ; 14ec7 (5:1ec7) - db MACHOP - db 3 - db $80 - - db MACHOKE - db 4 - db $80 - - db MACHAMP - db 4 - db $80 - 1 - - db HITMONCHAN - db 3 - db $80 - - db HITMONLEE - db 3 - db $80 - - db MANKEY - db 2 - db $80 - 1 - - db PRIMEAPE - db 3 - db $80 - 1 - - db $00 - -Data_14edd: ; 14edd (5:1edd) - db HITMONLEE - db HITMONCHAN - db $00 - -Func_14ee0: ; 14ee0 (5:4ee0) - ld hl, wcda8 - ld de, Data_14edd - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14eb6 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14ebb - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14ebb - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14ec7 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14f0e - -PointerTable_14f0e: ; 14f0e (5:4f0e) - dw Func_14f1a - dw Func_14f1a - dw Func_14f1e - dw Func_14f2f - dw Func_14f33 - dw Func_14f37 - -Func_14f1a: ; 14f1a (5:4f1a) - INCROM $14f1a, $14f1e - -Func_14f1e: ; 14f1e (5:4f1e) - call InitAIDuelVars - call Func_14f61 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14f2f - -Func_14f2f: ; 14f2f (5:4f2f) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14f33 - -Func_14f33: ; 14f33 (5:4f33) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14f37 - -Func_14f37: ; 14f37 (5:4f37) - call _AIPickPrizeCards - ret -; 0x14f3b - -Data_14f3b: ; 14f3b (5:4f3b) - db RHYHORN - db ONIX - db GEODUDE - db DIGLETT - db $00 - -Data_14f40: ; 14f40 (5:4f40) - db DIGLETT - db GEODUDE - db RHYHORN - db ONIX - db $00 - -Data_14f45: ; 14f45 (5:4f45) - db DIGLETT - db $80 - 1 - db $00 - -Data_14f48: ; 14f48 (5:4f48) - db DIGLETT - db 3 - db $80 + 1 - - db DUGTRIO - db 4 - db $80 + 0 - - db GEODUDE - db 2 - db $80 + 1 - - db GRAVELER - db 3 - db $80 + 0 - - db GOLEM - db 4 - db $80 + 0 - - db ONIX - db 2 - db $80 - 1 - - db RHYHORN - db 3 - db $80 + 0 - - db $00 - -Data_14f5e: ; 14f5e (5:4f5e) - db ENERGY_REMOVAL - db RHYHORN - db $00 - -Func_14f61: ; 14f61 (5:4f61) - ld hl, wcda8 - ld de, Data_14f5e - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14f3b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14f40 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14f40 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14f48 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x14f8f - -PointerTable_14f8f: ; 14f8f (5:4f8f) - dw Func_14f9b - dw Func_14f9b - dw Func_14f9f - dw Func_14fb0 - dw Func_14fb4 - dw Func_14fb8 - -Func_14f9b: ; 14f9b (5:4f9b) - INCROM $14f9b, $14f9f - -Func_14f9f: ; 14f9f (5:4f9f) - call InitAIDuelVars - call Func_14feb - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14fb0 - -Func_14fb0: ; 14fb0 (5:4fb0) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14fb4 - -Func_14fb4: ; 14fb4 (5:4fb4) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14fb8 - -Func_14fb8: ; 14fb8 (5:4fb8) - call _AIPickPrizeCards - ret -; 0x14fbc - -Data_14fbc: ; 14fbc (5:4fbc) - db LAPRAS - db HORSEA - db GOLDEEN - db SQUIRTLE - db $00 - -Data_14fc1: ; 14fc1 (5:4fc1) - db SQUIRTLE - db HORSEA - db GOLDEEN - db LAPRAS - db $00 - -Data_14fc6: ; 14fc6 (5:4fc6) - db SQUIRTLE - db $80 - 3 - db WARTORTLE - db $80 - 2 - db HORSEA - db $80 - 1 - db $00 - -Data_14fcd: ; 14fcd (5:4fcd) - db SQUIRTLE - db 2 - db $80 + 0 - - db WARTORTLE - db 3 - db $80 + 0 - - db BLASTOISE - db 5 - db $80 + 0 - - db GOLDEEN - db 1 - db $80 + 0 - - db SEAKING - db 2 - db $80 + 0 - - db HORSEA - db 2 - db $80 + 0 - - db SEADRA - db 3 - db $80 + 0 - - db LAPRAS - db 3 - db $80 + 0 - - db $00 - -Data_14fe6: ; 14fe6 (5:4fe6) - db GAMBLER - db ENERGY_RETRIEVAL - db SUPER_ENERGY_RETRIEVAL - db BLASTOISE - db $00 - -Func_14feb: ; 14feb (5:4feb) - ld hl, wcda8 - ld de, Data_14fe6 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14fbc - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14fc1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14fc1 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14fcd - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x15019 - -PointerTable_15019: ; 15019 (5:5019) - dw Func_15025 - dw Func_15025 - dw Func_15029 - dw Func_1503a - dw Func_1503e - dw Func_15042 - -Func_15025: ; 15025 (5:5025) - INCROM $15025, $15029 - -Func_15029: ; 15029 (5:5029) - call InitAIDuelVars - call Func_1506d - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x1503a - -Func_1503a: ; 1503a (5:503a) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1503e - -Func_1503e: ; 1503e (5:503e) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15042 - -Func_15042: ; 15042 (5:5042) - call _AIPickPrizeCards - ret -; 0x15046 - -Data_15046: ; 15046 (5:5046) - db KANGASKHAN - db ELECTABUZZ2 - db TAUROS - db MAGNEMITE1 - db VOLTORB - db $00 - -Data_1504c: ; 1504c (5:504c) - db MAGNEMITE1 - db VOLTORB - db ELECTABUZZ2 - db TAUROS - db KANGASKHAN - db $00 - -Data_15052: ; 15052 (5:5052) - db VOLTORB - db $80 - 1 - db $00 - -Data_15055: ; 15055 (5:5055) - db MAGNEMITE1 - db 3 - db $80 + 1 - - db MAGNETON1 - db 4 - db $80 + 0 - - db VOLTORB - db 3 - db $80 + 1 - - db ELECTRODE1 - db 3 - db $80 + 0 - - db ELECTABUZZ2 - db 1 - db $80 + 0 - - db KANGASKHAN - db 2 - db $80 - 2 - - db TAUROS - db 3 - db $80 + 0 - - db $00 - -Data_1506b: ; 1506b (5:506b) - db KANGASKHAN - db $00 - -Func_1506d: ; 1506d (5:506d) - ld hl, wcda8 - ld de, Data_1506b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15046 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_1504c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_1504c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_15055 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x1509b - -PointerTable_1509b: ; 1509b (5:509b) - dw Func_150a7 - dw Func_150a7 - dw Func_150ab - dw Func_150bc - dw Func_150c0 - dw Func_150c4 - -Func_150a7: ; 150a7 (5:50a7) - INCROM $150a7, $150ab - -Func_150ab: ; 150ab (5:50ab) - call InitAIDuelVars - call Func_150f4 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x150bc - -Func_150bc: ; 150bc (5:50bc) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x150c0 - -Func_150c0: ; 150c0 (5:50c0) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x150c4 - -Func_150c4: ; 150c4 (5:50c4) - call _AIPickPrizeCards - ret -; 0x150c8 - -Data_150c8 ; 150c8 (5:50c8) - db ODDISH - db EXEGGCUTE - db BULBASAUR - db $00 - -Data_150cc ; 150cc (5:50cc) - db BULBASAUR - db EXEGGCUTE - db ODDISH - db $00 - -Data_150cf ; 150cf (5:50cf) - db GLOOM - db $80 - 2 - db VILEPLUME - db $80 - 2 - db BULBASAUR - db $80 - 2 - db IVYSAUR - db $80 - 2 - db $00 - -Data_150d9 ; 150d9 (5:50d9) - db BULBASAUR - db 3 - db $80 + 0 - - db IVYSAUR - db 4 - db $80 + 0 - - db VENUSAUR2 - db 4 - db $80 + 0 - - db ODDISH - db 2 - db $80 + 0 - - db GLOOM - db 3 - db $80 - 1 - - db VILEPLUME - db 3 - db $80 - 1 - - db EXEGGCUTE - db 3 - db $80 + 0 - - db EXEGGUTOR - db 22 - db $80 + 0 - - db $00 - -Data_150f2 ; 150f2 (5:50f2) - db VENUSAUR2 - db $00 - -Func_150f4: ; 150f4 (5:50f4) - ld hl, wcda8 - ld de, Data_150f2 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_150c8 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_150cc - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_150cc - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_150d9 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x15122 - -PointerTable_15122: ; 15122 (5:5122) - dw Func_1512e - dw Func_1512e - dw Func_15132 - dw Func_15143 - dw Func_15147 - dw Func_1514b - -Func_1512e: ; 1512e (5:512e) - INCROM $1512e, $15132 - -Func_15132: ; 15132 (5:5132) - call InitAIDuelVars - call Func_1517f - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15143 - -Func_15143: ; 15143 (5:5143) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15147 - -Func_15147: ; 15147 (5:5147) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1514b - -Func_1514b: ; 1514b (5:514b) - call _AIPickPrizeCards - ret -; 0x1514f - -Data_1514f: ; 1514f (5:514f) - db KANGASKHAN - db CHANSEY - db SNORLAX - db MR_MIME - db ABRA - db $00 - -Data_15155: ; 15155 (5:5155) - db ABRA - db MR_MIME - db KANGASKHAN - db SNORLAX - db CHANSEY - db $00 - -Data_1515b: ; 1515b (5:515b) - db ABRA - db $80 - 3 - db SNORLAX - db $80 - 3 - db KANGASKHAN - db $80 - 1 - db CHANSEY - db $80 - 1 - db $00 - -Data_15164 ; 15164 (5:5164) - db ABRA - db 3 - db $80 + 1 - - db KADABRA - db 3 - db $80 + 0 - - db ALAKAZAM - db 3 - db $80 + 0 - - db MR_MIME - db 2 - db $80 + 0 - - db CHANSEY - db 2 - db $80 - 2 - - db KANGASKHAN - db 4 - db $80 - 2 - - db SNORLAX - db 0 - db $80 - 8 - - db $00 - -Data_1517a ; 1517a (5:517a) - db GAMBLER - db MR_MIME - db ALAKAZAM - db SWITCH - db $00 - -Func_1517f: ; 1517f (5:517f) - ld hl, wcda8 - ld de, Data_1517a - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1514f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15155 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15155 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_15164 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x151ad - -PointerTable_151ad: ; 151ad (5:51ad) - dw Func_151b9 - dw Func_151b9 - dw Func_151bd - dw Func_151ce - dw Func_151d2 - dw Func_151d6 - -Func_151b9: ; 151b9 (5:51b9) - INCROM $151b9, $151bd - -Func_151bd: ; 151bd (5:51bd) - call InitAIDuelVars - call Func_15204 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x151ce - -Func_151ce: ; 151ce (5:51ce) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x151d2 - -Func_151d2: ; 151d2 (5:51d2) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x151d6 - -Func_151d6: ; 151d6 (5:51d6) - call _AIPickPrizeCards - ret -; 0x151da - -Data_151da: ; 151da (5:51da) - db MEWTWO1 - db MEWTWO3 - db MEWTWO2 - db GRIMER - db KOFFING - db PORYGON - db $00 - -Data_151e1: ; 151e1 (5:51e1) - db GRIMER - db KOFFING - db MEWTWO3 - db MEWTWO2 - db MEWTWO1 - db PORYGON - db $00 - -Data_151e8: ; 151e8 (5:51e8) - db $00 - -Data_151e9: ; 151e9 (5:51e9) - db GRIMER - db 3 - db $80 + 0 - - db MUK - db 4 - db $80 + 0 - - db KOFFING - db 2 - db $80 + 0 - - db WEEZING - db 3 - db $80 + 0 - - db MEWTWO1 - db 2 - db $80 - 1 - - db MEWTWO3 - db 2 - db $80 - 1 - - db MEWTWO2 - db 2 - db $80 - 1 - - db PORYGON - db 2 - db $80 - 1 - - db $00 - -Data_15202: ; 15202 (5:5202) - db MUK - db $00 - -Func_15204: ; 15204 (5:5204) - ld hl, wcda8 - ld de, Data_15202 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_151da - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_151e1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_151e1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_151e9 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x15232 - -PointerTable_15232: ; 15232 (5:52PointerTable_12) - dw Func_1523e - dw Func_1523e - dw Func_15242 - dw Func_15253 - dw Func_15257 - dw Func_1525b - -Func_1523e: ; 1523e (5:523e) - INCROM $1523e, $15242 - -Func_15242: ; 15242 (5:5242) - call InitAIDuelVars - call Func_1528f - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15253 - -Func_15253: ; 15253 (5:5253) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15257 - -Func_15257: ; 15257 (5:5257) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1525b - -Func_1525b: ; 1525b (5:525b) - call _AIPickPrizeCards - ret -; 0x1525f - -Data_1525f: ; 1525f (5:525f) - db JIGGLYPUFF3 - db CHANSEY - db TAUROS - db MAGMAR1 - db JIGGLYPUFF1 - db GROWLITHE - db $00 - -Data_15266: ; 15266 (5:5266) - db JIGGLYPUFF3 - db CHANSEY - db GROWLITHE - db MAGMAR1 - db JIGGLYPUFF1 - db TAUROS - db $00 - -Data_1526e: ; 1526e (5:526e) - db JIGGLYPUFF1 - db $80 - 1 - db CHANSEY - db $80 - 1 - db GROWLITHE - db $80 - 1 - db $00 - -Data_15274: ; 15274 (5:5274) - db GROWLITHE - db 3 - db $80 + 0 - - db ARCANINE2 - db 4 - db $80 + 0 - - db MAGMAR1 - db 3 - db $80 + 0 - - db JIGGLYPUFF1 - db 3 - db $80 + 0 - - db JIGGLYPUFF3 - db 2 - db $80 + 0 - - db WIGGLYTUFF - db 3 - db $80 + 0 - - db CHANSEY - db 4 - db $80 + 0 - - db TAUROS - db 3 - db $80 + 0 - - db $00 - -Data_1528d: ; 1528d (5:528d) - db GAMBLER - db $00 - -Func_1528f: ; 1528f (5:528f) - ld hl, wcda8 - ld de, Data_1528d - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1525f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15266 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15266 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_15274 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x152bd - -PointerTable_152bd: ; 152bd (5:52bd) - dw Func_152c9 - dw Func_152c9 - dw Func_152cd - dw Func_152de - dw Func_152e2 - dw Func_152e6 - -Func_152c9: ; 152c9 (5:52c9) - INCROM $152c9, $152cd - -Func_152cd: ; 152cd (5:52cd) - call InitAIDuelVars - call Func_1531d - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x152de - -Func_152de: ; 152de (5:52de) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x152e2 - -Func_152e2: ; 152e2 (5:52e2) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x152e6 - -Func_152e6: ; 152e6 (5:52e6) - call _AIPickPrizeCards - ret -; 0x152ea - -Data_152ea: ; 152ea (5:52ea) - db LAPRAS - db SEEL - db CHARMANDER - db CUBONE - db SQUIRTLE - db GROWLITHE - db $00 - -Data_152f1: ; 152f1 (5:52f1) - db CHARMANDER - db SQUIRTLE - db SEEL - db CUBONE - db GROWLITHE - db LAPRAS - db $00 - -Data_152f8: ; 152f8 (5:52f8) - db $00 - -Data_152f9: ; 152f9 (5:52f9) - db CHARMANDER - db 3 - db $80 + 0 - - db CHARMELEON - db 5 - db $80 + 0 - - db GROWLITHE - db 2 - db $80 + 0 - - db ARCANINE2 - db 4 - db $80 + 0 - - db SQUIRTLE - db 2 - db $80 + 0 - - db WARTORTLE - db 3 - db $80 + 0 - - db SEEL - db 3 - db $80 + 0 - - db DEWGONG - db 4 - db $80 + 0 - - db LAPRAS - db 3 - db $80 + 0 - - db CUBONE - db 3 - db $80 + 0 - - db MAROWAK1 - db 3 - db $80 + 0 - - db $00 - -Data_1531b: ; 1531b (5:531b) - db LAPRAS - db $00 - -Func_1531d: ; 1531d (5:531d) - ld hl, wcda8 - ld de, Data_1531b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_152ea - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_152f1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_152f1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_152f9 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x1534b - -PointerTable_1534b: ; 1534b (5:534b) - dw Func_15357 - dw Func_15357 - dw Func_1535b - dw Func_1536c - dw Func_15370 - dw Func_15374 - -Func_15357: ; 15357 (5:5357) - INCROM $15357, $1535b - -Func_1535b: ; 1535b (5:535b) - call InitAIDuelVars - call Func_153ba - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x1536c - -Func_1536c: ; 1536c (5:536c) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15370 - -Func_15370: ; 15370 (5:5370) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15374 - -Func_15374: ; 15374 (5:5374) - call _AIPickPrizeCards - ret -; 0x15378 - -Data_15378: ; 15378 (5:5378) - db KANGASKHAN - db ELECTABUZZ2 - db HITMONCHAN - db MR_MIME - db LICKITUNG - db HITMONLEE - db TAUROS - db JYNX - db MEWTWO1 - db DODUO - db $00 - -Data_15383: ; 15383 (5:5383) - db KANGASKHAN - db HITMONLEE - db HITMONCHAN - db TAUROS - db DODUO - db JYNX - db MEWTWO1 - db ELECTABUZZ2 - db MR_MIME - db LICKITUNG - db $00 - -Data_1538e: ; 1538e (5:538e) - db KANGASKHAN - db $80 - 1 - db DODUO - db $80 - 1 - db DODRIO - db $80 - 1 - db $00 - -Data_15395: ; 15395 (5:5395) - db ELECTABUZZ2 - db 2 - db $80 + 1 - - db HITMONLEE - db 3 - db $80 + 1 - - db HITMONCHAN - db 3 - db $80 + 1 - - db MR_MIME - db 2 - db $80 + 0 - - db JYNX - db 3 - db $80 + 0 - - db MEWTWO1 - db 2 - db $80 + 0 - - db DODUO - db 3 - db $80 - 1 - - db DODRIO - db 3 - db $80 - 1 - - db LICKITUNG - db 2 - db $80 + 0 - - db KANGASKHAN - db 4 - db $80 - 1 - - db TAUROS - db 3 - db $80 + 0 - - db $00 - -Data_153b7: ; 153b7 (5:53b7) - db GAMBLER - db ENERGY_REMOVAL - db $00 - -Func_153ba: ; 153ba (5:53ba) - ld hl, wcda8 - ld de, Data_153b7 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15378 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15383 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15383 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_15395 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x153e8 - -PointerTable_153e8: ; 153e8 (5:53e8) - dw Func_153f4 - dw Func_153f4 - dw Func_153f8 - dw Func_15409 - dw Func_1540d - dw Func_15411 - -Func_153f4: ; 153f4 (5:53f4) - INCROM $153f4, $153f8 - -Func_153f8: ; 153f8 (5:53f8) - call InitAIDuelVars - call Func_15441 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15409 - -Func_15409: ; 15409 (5:5409) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1540d - -Func_1540d: ; 1540d (5:540d) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15411 - -Func_15411: ; 15411 (5:5411) - call _AIPickPrizeCards - ret -; 0x15415 - -Data_15415: ; 15415 (5:5415) - db KANGASKHAN - db MAGMAR2 - db CHANSEY - db GEODUDE - db SCYTHER - db GRIMER - db $00 - -Data_1541c: ; 1541c (5:541c) - db GRIMER - db SCYTHER - db GEODUDE - db CHANSEY - db MAGMAR2 - db KANGASKHAN - db $00 - -Data_15423: ; 15423 (5:5423) - db GRIMER - db $80 - 1 - db $00 - -Data_15426: ; 15426 (5:5426) - db GRIMER - db 1 - db $80 - 1 - - db MUK - db 3 - db $80 - 1 - - db SCYTHER - db 4 - db $80 + 1 - - db MAGMAR2 - db 2 - db $80 + 0 - - db GEODUDE - db 2 - db $80 + 0 - - db GRAVELER - db 3 - db $80 + 0 - - db CHANSEY - db 4 - db $80 + 0 - - db KANGASKHAN - db 4 - db $80 - 1 - - db $00 - -Data_1543f: ; 1543f (5:543f) - db GAMBLER - db $00 - -Func_15441: ; 15441 (5:5441) - ld hl, wcda8 - ld de, Data_1543f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15415 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_1541c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_1541c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_15426 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x1546f - -PointerTable_1546f: ; 1546f (5:546f) - dw Func_1547b - dw Func_1547b - dw Func_1547f - dw Func_15490 - dw Func_15494 - dw Func_15498 - -Func_1547b: ; 1547b (5:547b) - INCROM $1547b, $1547f - -Func_1547f: ; 1547f (5:547f) - call InitAIDuelVars - call Func_154d9 - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15490 - -Func_15490: ; 15490 (5:5490) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15494 - -Func_15494: ; 15494 (5:5494) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15498 - -Func_15498: ; 15498 (5:5498) - call _AIPickPrizeCards - ret -; 0x1549c - -Data_1549c: ; 1549c (5:549c) - db KANGASKHAN - db DRATINI - db EEVEE - db ZAPDOS3 - db ARTICUNO2 - db MOLTRES2 - db $00 - -Data_154a3: ; 154a3 (5:54a3) - db KANGASKHAN - db DRATINI - db EEVEE - db $00 - -Data_154a7: ; 154a7 (5:54a7) - db MOLTRES2 - db ZAPDOS3 - db KANGASKHAN - db DRATINI - db EEVEE - db ARTICUNO2 - db $00 - -Data_154ae: ; 154ae (5:54ae) - db EEVEE - db $80 - 2 - db $00 - -Data_154b1: ; 154b1 (5:54b1) - db FLAREON1 - db 3 - db $80 - - db MOLTRES2 - db 3 - db $80 - - db VAPOREON1 - db 3 - db $80 - - db ARTICUNO2 - db 0 - db $78 - - db JOLTEON1 - db 4 - db $80 - - db ZAPDOS3 - db 0 - db $78 - - db KANGASKHAN - db 4 - db $7f - - db EEVEE - db 3 - db $80 - - db DRATINI - db 3 - db $80 - - db DRAGONAIR - db 4 - db $80 - - db DRAGONITE1 - db 3 - db $80 - - db $00 - -Data_154d3: ; 154d3 (5:54d3) - db MOLTRES2 - db ARTICUNO2 - db ZAPDOS3 - db DRAGONITE1 - db GAMBLER - db $00 - -Func_154d9: ; 154d9 (5:54d9) - ld hl, wcda8 - ld de, Data_154d3 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1549c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_154a3 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_154a7 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_154b1 - ld [hl], e - inc hl - ld [hl], d - - ret -; 0x15507 +INCLUDE "engine/deck_ai.asm" Func_15507: ; 15507 (5:5507) INCROM $15507, $155d2 diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm new file mode 100644 index 0000000..f62239e --- /dev/null +++ b/src/engine/deck_ai.asm @@ -0,0 +1,2011 @@ +; AI card retreat score bonus +; when the AI retreat routine runs through the Bench to choose +; a Pokemon to switch to, it looks up in this list and if +; a card ID matches, applies a retreat score bonus to this card. +; positive (negative) means more (less) likely to switch to this card. +airetreat: MACRO + db \1 ; card ID + db $80 + \2 ; retreat score (ranges between -128 and 127) +ENDM + +; AI card energy attach score bonus +; when the AI energy attachment run through the Play Area to choose +; a Pokemon to attach an energy card, it looks up in this list and if +; a card ID matches, skips this card if the maximum number of energy +; cards attached has been reached. If it hasn't been reached, additionally +; applies a positive (or negative) AI score to attach energy to this card. +aienergy: MACRO + db \1 ; card ID + db \2 ; maximum number of attached cards + db $80 + \3 ; energy score (ranges between -128 and 127) +ENDM + +PointerTable_148dc: ; 148dc (5:48dc) + dw Func_148e8 + dw Func_148e8 + dw Func_148ec + dw Func_148f3 + dw Func_148f7 + dw Func_148fb + +Func_148e8: ; 148e8 (5:48e8) + INCROM $148e8, $148ec + +Func_148ec: ; 148ec (5:48ec) + call InitAIDuelVars + call AIPlayInitialBasicCards + ret +; 0x148f3 + +Func_148f3: ; 148f3 (5:48f3) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148f7 + +Func_148f7: ; 148f7 (5:48f7) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148fb + +Func_148fb: ; 148fb (5:48fb) + call _AIPickPrizeCards + ret +; 0x148ff + +Func_148ff: ; 148ff (5:48ff) + INCROM $148ff, $149e8 + +PointerTable_149e8: ; 149e8 (05:49e8) + dw Func_149f4 + dw Func_149f4 + dw Func_149f8 + dw Func_14a09 + dw Func_14a0d + dw Func_14a11 + +Func_149f4: ; 149f4 (5:49f4) + call Func_14a81 + ret +; 0x149f8 + +Func_149f8: ; 149f8 (5:49f8) + call InitAIDuelVars + call Func_14a4a + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc ; Play Area set up was successful + call AIPlayInitialBasicCards + ret +; 0x14a09 + +Func_14a09: ; 14a09 (5:4a09) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a0d + +Func_14a0d: ; 14a0d (5:4a0d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a11 + +Func_14a11: ; 14a11 (5:4a11) + call _AIPickPrizeCards + ret +; 0x14a15 + +Data_14a15: ; 14a15 (5:4a15) + db MAGMAR2 + db GROWLITHE + db VULPIX + db MAGMAR1 + db MOLTRES1 + db MOLTRES2 + db $00 + +Data_14a1c: ; 14a1c (5:4a1c) + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +Data_14a22: ; 14a22 (5:4a22) + db MOLTRES2 + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +Data_14a29: ; 14a29 (5:4a29) + airetreat GROWLITHE, -5 + airetreat VULPIX, -5 + db $00 + +Data_14a2e: ; 14a2e (5:4a2e) + aienergy VULPIX, 3, +0 + aienergy NINETAILS2, 3, +1 + aienergy GROWLITHE, 3, +1 + aienergy ARCANINE2, 4, +1 + aienergy MAGMAR1, 4, -1 + aienergy MAGMAR2, 1, -1 + aienergy MOLTRES2, 3, +2 + aienergy MOLTRES1, 4, +2 + db $00 + +Data_14a47: ; 14a47 (5:4a47) + db ENERGY_REMOVAL + db MOLTRES2 + db $00 + +Func_14a4a: ; 14a4a (5:4a4a) + ld hl, wcda8 + ld de, Data_14a47 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14a15 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14a1c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14a22 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb0 + ld de, Data_14a29 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdb2 + ld de, Data_14a2e + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14a81 + +Func_14a81: ; 14a81 (5:4a81) + call InitAITurnVars + farcall Func_227d3 + jp nc, .try_attack + + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + +; check if AI can play Moltres2 from hand +; if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 9 + jr nc, .skip_moltres ; skip if cards in deck <= 9 + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .skip_moltres ; skip if Muk in play + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank5 + jr nc, .skip_moltres ; skip if no Moltres2 in hand + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + +.skip_moltres + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + +; handle attaching energy from hand + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_attach_energy + +; if Magmar2 is the Arena card and has no energy attached, +; try attaching an energy card to it from the hand. +; otherwise, run normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, MAGMAR2 + cp e + jr nz, .attach_normally + ; Magmar2 is the Arena card + call CreateEnergyCardListFromHand + jr c, .skip_attach_energy + ld e, PLAY_AREA_ARENA + call CountNumberOfEnergyCardsAttached + or a + jr nz, .attach_normally + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .skip_attach_energy + +.attach_normally + call AIProcessAndTryToPlayEnergy + +.skip_attach_energy +; try playing Pokemon cards from hand again + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + +.try_attack + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14b0f + +PointerTable_14b0f: ; 14b0f (05:4b0f) + dw Func_14b1b + dw Func_14b1b + dw Func_14b1f + dw Func_14b30 + dw Func_14b34 + dw Func_14b38 + +Func_14b1b: ; 14b1b (5:4b1b) + INCROM $14b1b, $14b1f + +Func_14b1f: ; 14b1f (5:4b1f) + call InitAIDuelVars + call Func_14b6c + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14b30 + +Func_14b30: ; 14b30 (5:4b30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b34 + +Func_14b34: ; 14b34 (5:4b34) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b38 + +Func_14b38: ; 14b38 (5:4b38) + call _AIPickPrizeCards + ret +; 0x14b3c + +Data_14b3c: ; 14b3c (5:4b3c) + db ELECTABUZZ2 + db VOLTORB + db EEVEE + db ZAPDOS1 + db ZAPDOS2 + db ZAPDOS3 + db $00 + +Data_14b43: ; 14b43 (5:4b43) + db ZAPDOS2 + db ZAPDOS1 + db EEVEE + db VOLTORB + db ELECTABUZZ2 + db $00 + +Data_14b49: ; 14b49 (5:4b49) + airetreat EEVEE, -5 + airetreat VOLTORB, -5 + airetreat ELECTABUZZ2, -5 + db $00 + +Data_14b50: ; 14b50 (5:4b50) + aienergy VOLTORB, 1, -1 + aienergy ELECTRODE1, 3, +0 + aienergy ELECTABUZZ2, 2, -1 + aienergy JOLTEON2, 3, +1 + aienergy ZAPDOS1, 4, +2 + aienergy ZAPDOS2, 4, +2 + aienergy ZAPDOS3, 3, +1 + aienergy EEVEE, 3, +0 + db $00 + +Data_14b69: ; 14b69 (5:4b69) + db GAMBLER + db ZAPDOS3 + db $00 + +Func_14b6c: ; 14b6c (5:4b6c) + ld hl, wcda8 + ld de, Data_14b69 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14b3c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14b43 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14b43 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14b50 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14b9a + +Func_14b9a: ; 14b9a (5:4b9a) + INCROM $14b9a, $14c0b + +PointerTable_14c0b: ; 14c0b (5:4c0b) + dw Func_14c17 + dw Func_14c17 + dw Func_14c1b + dw Func_14c2c + dw Func_14c30 + dw Func_14c34 + +Func_14c17: ; 14c17 (5:4c17) + INCROM $14c17, $14c1b + +Func_14c1b: ; 14c1b (5:4c1b) + call InitAIDuelVars + call Func_14c63 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14c2c + +Func_14c2c: ; 14c2c (5:4c2c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c30 + +Func_14c30: ; 14c30 (5:4c30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c34 + +Func_14c34: ; 14c34 (5:4c34) + call _AIPickPrizeCards + ret +; 0x14c38 + +Data_14c38: ; 14c38 (5:4c38) + db CHANSEY + db LAPRAS + db DITTO + db SEEL + db ARTICUNO1 + db ARTICUNO2 + db $00 + +Data_14c3f: ; 14c3f (5:4c3f) + db ARTICUNO1 + db SEEL + db LAPRAS + db CHANSEY + db DITTO + db $00 + +Data_14c45: ; 14c45 (5:4c45) + airetreat SEEL, -3 + airetreat DITTO, -3 + db $00 + +Data_14c4a: ; 14c4a (5:4c4a) + aienergy SEEL, 3, +1 + aienergy DEWGONG, 4, +0 + aienergy LAPRAS, 3, +0 + aienergy ARTICUNO1, 4, +1 + aienergy ARTICUNO2, 3, +0 + aienergy CHANSEY, 0, -8 + aienergy DITTO, 3, +0 + db $00 + +Data_14c60: ; 14c60 (5:4c60) + db GAMBLER + db ARTICUNO2 + db $00 + +Func_14c63: ; 14c63 (5:4c63) + ld hl, wcda8 + ld de, Data_14c60 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14c38 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14c3f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14c3f + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14c4a + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14c91 + +; this routine handles how Legendary Articuno +; prioritises playing energy cards to each Pokémon. +; first, it makes sure that all Lapras have at least +; 3 energy cards before moving on to Articuno, +; and then to Dewgong and Seel +ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) + call SwapTurn + call CountPrizes + call SwapTurn + cp 3 + ret c + +; player prizes >= 3 +; if Lapras has more than half HP and +; can use second move, check next for Articuno +; otherwise, check if Articuno or Dewgong +; have more than half HP and can use second move +; and if so, the next Pokémon to check is Lapras + ld a, LAPRAS + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .articuno + ld a, ARTICUNO1 + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .lapras + ld a, DEWGONG + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .lapras + jr .articuno + +; the following routines check for certain card IDs in bench +; and call RaiseAIScoreToAllMatchingIDsInBench if these are found. +; for Lapras, an additional check is made to its +; attached energy count, which skips calling the routine +; if this count is >= 3 +.lapras + ld a, LAPRAS + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .articuno + ld e, a + call CountNumberOfEnergyCardsAttached + cp 3 + jr nc, .articuno + ld a, LAPRAS + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.articuno + ld a, ARTICUNO1 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .dewgong + ld a, ARTICUNO1 + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.dewgong + ld a, DEWGONG + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .seel + ld a, DEWGONG + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.seel + ld a, SEEL + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + ret nc + ld a, SEEL + call RaiseAIScoreToAllMatchingIDsInBench + ret +; 0x14cf7 + +Func_14cf7: ; 14cf7 (5:4cf7) + INCROM $14cf7, $14d60 + +PointerTable_14d60: ; 14d60 (05:4d60) + dw Func_14d6c + dw Func_14d6c + dw Func_14d70 + dw Func_14d81 + dw Func_14d85 + dw Func_14d89 + +Func_14d6c: ; 14d6c (5:4d6c) + INCROM $14d6c, $14d70 + +Func_14d70: ; 14d70 (5:4d70) + call InitAIDuelVars + call Func_14dc1 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14d81 + +Func_14d81: ; 14d81 (5:4d81) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d85 + +Func_14d85: ; 14d85 (5:4d85) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d89 + +Func_14d89: ; 14d89 (5:4d89) + call _AIPickPrizeCards + ret +; 0x14d8d + +Data_14d8d: ; 14d8d (5:4d8d) + db KANGASKHAN + db LAPRAS + db CHARMANDER + db DRATINI + db MAGIKARP + db $00 + +Data_14d93: ; 14d93 (5:4d93) + db CHARMANDER + db MAGIKARP + db DRATINI + db LAPRAS + db KANGASKHAN + db $00 + +Data_14d99: ; 14d99 (5:4d99) + airetreat CHARMANDER, -1 + airetreat MAGIKARP, -5 + db $00 + +Data_14d9e: ; 14d9e (5:4d9e) + aienergy CHARMANDER, 3, +1 + aienergy CHARMELEON, 4, +1 + aienergy CHARIZARD, 5, +0 + aienergy MAGIKARP, 3, +1 + aienergy GYARADOS, 4, -1 + aienergy DRATINI, 2, +0 + aienergy DRAGONAIR, 4, +0 + aienergy DRAGONITE1, 3, -1 + aienergy KANGASKHAN, 2, -2 + aienergy LAPRAS, 3, +0 + db $00 + +Data_14dbd: ; 14dbd (5:4dbd) + db GAMBLER + db DRAGONITE1 + db KANGASKHAN + db $00 + +Func_14dc1: ; 14dc1 (5:4dc1) + ld hl, wcda8 + ld de, Data_14dbd + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14d8d + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14d93 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14d93 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14d9e + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14def + +Func_14def: ; 14def (5:4def) + INCROM $14def, $14e89 + +PointerTable_14e89: ; 14e89 (5:4e89) + dw Func_14e95 + dw Func_14e95 + dw Func_14e99 + dw Func_14eaa + dw Func_14eae + dw Func_14eb2 + +Func_14e95: ; 14e95 (5:4e95) + INCROM $14e95, $14e99 + +Func_14e99: ; 14e99 (5:4e99) + call InitAIDuelVars + call Func_14ee0 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14eaa + +Func_14eaa: ; 14eaa (5:4eaa) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eae + +Func_14eae: ; 14eae (5:4eae) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eb2 + +Func_14eb2: ; 14eb2 (5:4eb2) + call _AIPickPrizeCards + ret +; 0x14eb6 + +Data_14eb6: ; 14eb6 (5:1eb6) + db HITMONCHAN + db MACHOP + db HITMONLEE + db MANKEY + db $00 + +Data_14ebb: ; 14ebb (5:1ebb) + db MACHOP + db HITMONLEE + db HITMONCHAN + db MANKEY + db $00 + +Data_14ec0: ; 14ec0 (5:1ec0) + airetreat MACHOP, - 1 + airetreat MACHOKE, - 1 + airetreat MANKEY, - 2 + db $00 + +Data_14ec7: ; 14ec7 (5:1ec7) + aienergy MACHOP, 3, +0 + aienergy MACHOKE, 4, +0 + aienergy MACHAMP, 4, -1 + aienergy HITMONCHAN, 3, +0 + aienergy HITMONLEE, 3, +0 + aienergy MANKEY, 2, -1 + aienergy PRIMEAPE, 3, -1 + db $00 + +Data_14edd: ; 14edd (5:1edd) + db HITMONLEE + db HITMONCHAN + db $00 + +Func_14ee0: ; 14ee0 (5:4ee0) + ld hl, wcda8 + ld de, Data_14edd + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14eb6 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14ebb + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14ebb + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14ec7 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14f0e + +PointerTable_14f0e: ; 14f0e (5:4f0e) + dw Func_14f1a + dw Func_14f1a + dw Func_14f1e + dw Func_14f2f + dw Func_14f33 + dw Func_14f37 + +Func_14f1a: ; 14f1a (5:4f1a) + INCROM $14f1a, $14f1e + +Func_14f1e: ; 14f1e (5:4f1e) + call InitAIDuelVars + call Func_14f61 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14f2f + +Func_14f2f: ; 14f2f (5:4f2f) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f33 + +Func_14f33: ; 14f33 (5:4f33) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f37 + +Func_14f37: ; 14f37 (5:4f37) + call _AIPickPrizeCards + ret +; 0x14f3b + +Data_14f3b: ; 14f3b (5:4f3b) + db RHYHORN + db ONIX + db GEODUDE + db DIGLETT + db $00 + +Data_14f40: ; 14f40 (5:4f40) + db DIGLETT + db GEODUDE + db RHYHORN + db ONIX + db $00 + +Data_14f45: ; 14f45 (5:4f45) + airetreat DIGLETT, -1 + db $00 + +Data_14f48: ; 14f48 (5:4f48) + aienergy DIGLETT, 3, +1 + aienergy DUGTRIO, 4, +0 + aienergy GEODUDE, 2, +1 + aienergy GRAVELER, 3, +0 + aienergy GOLEM, 4, +0 + aienergy ONIX, 2, -1 + aienergy RHYHORN, 3, +0 + db $00 + +Data_14f5e: ; 14f5e (5:4f5e) + db ENERGY_REMOVAL + db RHYHORN + db $00 + +Func_14f61: ; 14f61 (5:4f61) + ld hl, wcda8 + ld de, Data_14f5e + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14f3b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14f40 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14f40 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14f48 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x14f8f + +PointerTable_14f8f: ; 14f8f (5:4f8f) + dw Func_14f9b + dw Func_14f9b + dw Func_14f9f + dw Func_14fb0 + dw Func_14fb4 + dw Func_14fb8 + +Func_14f9b: ; 14f9b (5:4f9b) + INCROM $14f9b, $14f9f + +Func_14f9f: ; 14f9f (5:4f9f) + call InitAIDuelVars + call Func_14feb + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14fb0 + +Func_14fb0: ; 14fb0 (5:4fb0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb4 + +Func_14fb4: ; 14fb4 (5:4fb4) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb8 + +Func_14fb8: ; 14fb8 (5:4fb8) + call _AIPickPrizeCards + ret +; 0x14fbc + +Data_14fbc: ; 14fbc (5:4fbc) + db LAPRAS + db HORSEA + db GOLDEEN + db SQUIRTLE + db $00 + +Data_14fc1: ; 14fc1 (5:4fc1) + db SQUIRTLE + db HORSEA + db GOLDEEN + db LAPRAS + db $00 + +Data_14fc6: ; 14fc6 (5:4fc6) + airetreat SQUIRTLE, -3 + airetreat WARTORTLE, -2 + airetreat HORSEA, -1 + db $00 + +Data_14fcd: ; 14fcd (5:4fcd) + aienergy SQUIRTLE, 2, +0 + aienergy WARTORTLE, 3, +0 + aienergy BLASTOISE, 5, +0 + aienergy GOLDEEN, 1, +0 + aienergy SEAKING, 2, +0 + aienergy HORSEA, 2, +0 + aienergy SEADRA, 3, +0 + aienergy LAPRAS, 3, +0 + db $00 + +Data_14fe6: ; 14fe6 (5:4fe6) + db GAMBLER + db ENERGY_RETRIEVAL + db SUPER_ENERGY_RETRIEVAL + db BLASTOISE + db $00 + +Func_14feb: ; 14feb (5:4feb) + ld hl, wcda8 + ld de, Data_14fe6 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_14fbc + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_14fc1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_14fc1 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_14fcd + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15019 + +PointerTable_15019: ; 15019 (5:5019) + dw Func_15025 + dw Func_15025 + dw Func_15029 + dw Func_1503a + dw Func_1503e + dw Func_15042 + +Func_15025: ; 15025 (5:5025) + INCROM $15025, $15029 + +Func_15029: ; 15029 (5:5029) + call InitAIDuelVars + call Func_1506d + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1503a + +Func_1503a: ; 1503a (5:503a) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1503e + +Func_1503e: ; 1503e (5:503e) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15042 + +Func_15042: ; 15042 (5:5042) + call _AIPickPrizeCards + ret +; 0x15046 + +Data_15046: ; 15046 (5:5046) + db KANGASKHAN + db ELECTABUZZ2 + db TAUROS + db MAGNEMITE1 + db VOLTORB + db $00 + +Data_1504c: ; 1504c (5:504c) + db MAGNEMITE1 + db VOLTORB + db ELECTABUZZ2 + db TAUROS + db KANGASKHAN + db $00 + +Data_15052: ; 15052 (5:5052) + airetreat VOLTORB, -1 + db $00 + +Data_15055: ; 15055 (5:5055) + aienergy MAGNEMITE1, 3, +1 + aienergy MAGNETON1, 4, +0 + aienergy VOLTORB, 3, +1 + aienergy ELECTRODE1, 3, +0 + aienergy ELECTABUZZ2, 1, +0 + aienergy KANGASKHAN, 2, -2 + aienergy TAUROS, 3, +0 + db $00 + +Data_1506b: ; 1506b (5:506b) + db KANGASKHAN + db $00 + +Func_1506d: ; 1506d (5:506d) + ld hl, wcda8 + ld de, Data_1506b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15046 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_1504c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_1504c + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_15055 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1509b + +PointerTable_1509b: ; 1509b (5:509b) + dw Func_150a7 + dw Func_150a7 + dw Func_150ab + dw Func_150bc + dw Func_150c0 + dw Func_150c4 + +Func_150a7: ; 150a7 (5:50a7) + INCROM $150a7, $150ab + +Func_150ab: ; 150ab (5:50ab) + call InitAIDuelVars + call Func_150f4 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x150bc + +Func_150bc: ; 150bc (5:50bc) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c0 + +Func_150c0: ; 150c0 (5:50c0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c4 + +Func_150c4: ; 150c4 (5:50c4) + call _AIPickPrizeCards + ret +; 0x150c8 + +Data_150c8 ; 150c8 (5:50c8) + db ODDISH + db EXEGGCUTE + db BULBASAUR + db $00 + +Data_150cc ; 150cc (5:50cc) + db BULBASAUR + db EXEGGCUTE + db ODDISH + db $00 + +Data_150cf ; 150cf (5:50cf) + airetreat GLOOM, -2 + airetreat VILEPLUME, -2 + airetreat BULBASAUR, -2 + airetreat IVYSAUR, -2 + db $00 + +Data_150d9 ; 150d9 (5:50d9) + aienergy BULBASAUR, 3, +0 + aienergy IVYSAUR, 4, +0 + aienergy VENUSAUR2, 4, +0 + aienergy ODDISH, 2, +0 + aienergy GLOOM, 3, -1 + aienergy VILEPLUME, 3, -1 + aienergy EXEGGCUTE, 3, +0 + aienergy EXEGGUTOR, 22, +0 + db $00 + +Data_150f2 ; 150f2 (5:50f2) + db VENUSAUR2 + db $00 + +Func_150f4: ; 150f4 (5:50f4) + ld hl, wcda8 + ld de, Data_150f2 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_150c8 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_150cc + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_150cc + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_150d9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15122 + +PointerTable_15122: ; 15122 (5:5122) + dw Func_1512e + dw Func_1512e + dw Func_15132 + dw Func_15143 + dw Func_15147 + dw Func_1514b + +Func_1512e: ; 1512e (5:512e) + INCROM $1512e, $15132 + +Func_15132: ; 15132 (5:5132) + call InitAIDuelVars + call Func_1517f + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15143 + +Func_15143: ; 15143 (5:5143) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15147 + +Func_15147: ; 15147 (5:5147) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1514b + +Func_1514b: ; 1514b (5:514b) + call _AIPickPrizeCards + ret +; 0x1514f + +Data_1514f: ; 1514f (5:514f) + db KANGASKHAN + db CHANSEY + db SNORLAX + db MR_MIME + db ABRA + db $00 + +Data_15155: ; 15155 (5:5155) + db ABRA + db MR_MIME + db KANGASKHAN + db SNORLAX + db CHANSEY + db $00 + +Data_1515b: ; 1515b (5:515b) + airetreat ABRA, -3 + airetreat SNORLAX, -3 + airetreat KANGASKHAN, -1 + airetreat CHANSEY, -1 + db $00 + +Data_15164 ; 15164 (5:5164) + aienergy ABRA, 3, +1 + aienergy KADABRA, 3, +0 + aienergy ALAKAZAM, 3, +0 + aienergy MR_MIME, 2, +0 + aienergy CHANSEY, 2, -2 + aienergy KANGASKHAN, 4, -2 + aienergy SNORLAX, 0, -8 + db $00 + +Data_1517a ; 1517a (5:517a) + db GAMBLER + db MR_MIME + db ALAKAZAM + db SWITCH + db $00 + +Func_1517f: ; 1517f (5:517f) + ld hl, wcda8 + ld de, Data_1517a + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1514f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15155 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15155 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_15164 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x151ad + +PointerTable_151ad: ; 151ad (5:51ad) + dw Func_151b9 + dw Func_151b9 + dw Func_151bd + dw Func_151ce + dw Func_151d2 + dw Func_151d6 + +Func_151b9: ; 151b9 (5:51b9) + INCROM $151b9, $151bd + +Func_151bd: ; 151bd (5:51bd) + call InitAIDuelVars + call Func_15204 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x151ce + +Func_151ce: ; 151ce (5:51ce) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d2 + +Func_151d2: ; 151d2 (5:51d2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d6 + +Func_151d6: ; 151d6 (5:51d6) + call _AIPickPrizeCards + ret +; 0x151da + +Data_151da: ; 151da (5:51da) + db MEWTWO1 + db MEWTWO3 + db MEWTWO2 + db GRIMER + db KOFFING + db PORYGON + db $00 + +Data_151e1: ; 151e1 (5:51e1) + db GRIMER + db KOFFING + db MEWTWO3 + db MEWTWO2 + db MEWTWO1 + db PORYGON + db $00 + +Data_151e8: ; 151e8 (5:51e8) + db $00 + +Data_151e9: ; 151e9 (5:51e9) + aienergy GRIMER, 3, +0 + aienergy MUK, 4, +0 + aienergy KOFFING, 2, +0 + aienergy WEEZING, 3, +0 + aienergy MEWTWO1, 2, -1 + aienergy MEWTWO3, 2, -1 + aienergy MEWTWO2, 2, -1 + aienergy PORYGON, 2, -1 + db $00 + +Data_15202: ; 15202 (5:5202) + db MUK + db $00 + +Func_15204: ; 15204 (5:5204) + ld hl, wcda8 + ld de, Data_15202 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_151da + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_151e1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_151e1 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_151e9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15232 + +PointerTable_15232: ; 15232 (5:52PointerTable_12) + dw Func_1523e + dw Func_1523e + dw Func_15242 + dw Func_15253 + dw Func_15257 + dw Func_1525b + +Func_1523e: ; 1523e (5:523e) + INCROM $1523e, $15242 + +Func_15242: ; 15242 (5:5242) + call InitAIDuelVars + call Func_1528f + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15253 + +Func_15253: ; 15253 (5:5253) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15257 + +Func_15257: ; 15257 (5:5257) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1525b + +Func_1525b: ; 1525b (5:525b) + call _AIPickPrizeCards + ret +; 0x1525f + +Data_1525f: ; 1525f (5:525f) + db JIGGLYPUFF3 + db CHANSEY + db TAUROS + db MAGMAR1 + db JIGGLYPUFF1 + db GROWLITHE + db $00 + +Data_15266: ; 15266 (5:5266) + db JIGGLYPUFF3 + db CHANSEY + db GROWLITHE + db MAGMAR1 + db JIGGLYPUFF1 + db TAUROS + db $00 + +Data_1526e: ; 1526e (5:526e) + airetreat JIGGLYPUFF1, -1 + airetreat CHANSEY, -1 + airetreat GROWLITHE, -1 + db $00 + +Data_15274: ; 15274 (5:5274) + aienergy GROWLITHE, 3, +0 + aienergy ARCANINE2, 4, +0 + aienergy MAGMAR1, 3, +0 + aienergy JIGGLYPUFF1, 3, +0 + aienergy JIGGLYPUFF3, 2, +0 + aienergy WIGGLYTUFF, 3, +0 + aienergy CHANSEY, 4, +0 + aienergy TAUROS, 3, +0 + db $00 + +Data_1528d: ; 1528d (5:528d) + db GAMBLER + db $00 + +Func_1528f: ; 1528f (5:528f) + ld hl, wcda8 + ld de, Data_1528d + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1525f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15266 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15266 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_15274 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x152bd + +PointerTable_152bd: ; 152bd (5:52bd) + dw Func_152c9 + dw Func_152c9 + dw Func_152cd + dw Func_152de + dw Func_152e2 + dw Func_152e6 + +Func_152c9: ; 152c9 (5:52c9) + INCROM $152c9, $152cd + +Func_152cd: ; 152cd (5:52cd) + call InitAIDuelVars + call Func_1531d + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x152de + +Func_152de: ; 152de (5:52de) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e2 + +Func_152e2: ; 152e2 (5:52e2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e6 + +Func_152e6: ; 152e6 (5:52e6) + call _AIPickPrizeCards + ret +; 0x152ea + +Data_152ea: ; 152ea (5:52ea) + db LAPRAS + db SEEL + db CHARMANDER + db CUBONE + db SQUIRTLE + db GROWLITHE + db $00 + +Data_152f1: ; 152f1 (5:52f1) + db CHARMANDER + db SQUIRTLE + db SEEL + db CUBONE + db GROWLITHE + db LAPRAS + db $00 + +Data_152f8: ; 152f8 (5:52f8) + db $00 + +Data_152f9: ; 152f9 (5:52f9) + aienergy CHARMANDER, 3, +0 + aienergy CHARMELEON, 5, +0 + aienergy GROWLITHE, 2, +0 + aienergy ARCANINE2, 4, +0 + aienergy SQUIRTLE, 2, +0 + aienergy WARTORTLE, 3, +0 + aienergy SEEL, 3, +0 + aienergy DEWGONG, 4, +0 + aienergy LAPRAS, 3, +0 + aienergy CUBONE, 3, +0 + aienergy MAROWAK1, 3, +0 + db $00 + +Data_1531b: ; 1531b (5:531b) + db LAPRAS + db $00 + +Func_1531d: ; 1531d (5:531d) + ld hl, wcda8 + ld de, Data_1531b + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_152ea + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_152f1 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_152f1 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_152f9 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1534b + +PointerTable_1534b: ; 1534b (5:534b) + dw Func_15357 + dw Func_15357 + dw Func_1535b + dw Func_1536c + dw Func_15370 + dw Func_15374 + +Func_15357: ; 15357 (5:5357) + INCROM $15357, $1535b + +Func_1535b: ; 1535b (5:535b) + call InitAIDuelVars + call Func_153ba + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1536c + +Func_1536c: ; 1536c (5:536c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15370 + +Func_15370: ; 15370 (5:5370) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15374 + +Func_15374: ; 15374 (5:5374) + call _AIPickPrizeCards + ret +; 0x15378 + +Data_15378: ; 15378 (5:5378) + db KANGASKHAN + db ELECTABUZZ2 + db HITMONCHAN + db MR_MIME + db LICKITUNG + db HITMONLEE + db TAUROS + db JYNX + db MEWTWO1 + db DODUO + db $00 + +Data_15383: ; 15383 (5:5383) + db KANGASKHAN + db HITMONLEE + db HITMONCHAN + db TAUROS + db DODUO + db JYNX + db MEWTWO1 + db ELECTABUZZ2 + db MR_MIME + db LICKITUNG + db $00 + +Data_1538e: ; 1538e (5:538e) + airetreat KANGASKHAN, -1 + airetreat DODUO, -1 + airetreat DODRIO, -1 + db $00 + +Data_15395: ; 15395 (5:5395) + aienergy ELECTABUZZ2, 2, +1 + aienergy HITMONLEE, 3, +1 + aienergy HITMONCHAN, 3, +1 + aienergy MR_MIME, 2, +0 + aienergy JYNX, 3, +0 + aienergy MEWTWO1, 2, +0 + aienergy DODUO, 3, -1 + aienergy DODRIO, 3, -1 + aienergy LICKITUNG, 2, +0 + aienergy KANGASKHAN, 4, -1 + aienergy TAUROS, 3, +0 + db $00 + +Data_153b7: ; 153b7 (5:53b7) + db GAMBLER + db ENERGY_REMOVAL + db $00 + +Func_153ba: ; 153ba (5:53ba) + ld hl, wcda8 + ld de, Data_153b7 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15378 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_15383 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_15383 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_15395 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x153e8 + +PointerTable_153e8: ; 153e8 (5:53e8) + dw Func_153f4 + dw Func_153f4 + dw Func_153f8 + dw Func_15409 + dw Func_1540d + dw Func_15411 + +Func_153f4: ; 153f4 (5:53f4) + INCROM $153f4, $153f8 + +Func_153f8: ; 153f8 (5:53f8) + call InitAIDuelVars + call Func_15441 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15409 + +Func_15409: ; 15409 (5:5409) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1540d + +Func_1540d: ; 1540d (5:540d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15411 + +Func_15411: ; 15411 (5:5411) + call _AIPickPrizeCards + ret +; 0x15415 + +Data_15415: ; 15415 (5:5415) + db KANGASKHAN + db MAGMAR2 + db CHANSEY + db GEODUDE + db SCYTHER + db GRIMER + db $00 + +Data_1541c: ; 1541c (5:541c) + db GRIMER + db SCYTHER + db GEODUDE + db CHANSEY + db MAGMAR2 + db KANGASKHAN + db $00 + +Data_15423: ; 15423 (5:5423) + airetreat GRIMER, -1 + db $00 + +Data_15426: ; 15426 (5:5426) + aienergy GRIMER, 1, -1 + aienergy MUK, 3, -1 + aienergy SCYTHER, 4, +1 + aienergy MAGMAR2, 2, +0 + aienergy GEODUDE, 2, +0 + aienergy GRAVELER, 3, +0 + aienergy CHANSEY, 4, +0 + aienergy KANGASKHAN, 4, -1 + db $00 + +Data_1543f: ; 1543f (5:543f) + db GAMBLER + db $00 + +Func_15441: ; 15441 (5:5441) + ld hl, wcda8 + ld de, Data_1543f + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_15415 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_1541c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_1541c + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_15426 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x1546f + +PointerTable_1546f: ; 1546f (5:546f) + dw Func_1547b + dw Func_1547b + dw Func_1547f + dw Func_15490 + dw Func_15494 + dw Func_15498 + +Func_1547b: ; 1547b (5:547b) + INCROM $1547b, $1547f + +Func_1547f: ; 1547f (5:547f) + call InitAIDuelVars + call Func_154d9 + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15490 + +Func_15490: ; 15490 (5:5490) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15494 + +Func_15494: ; 15494 (5:5494) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15498 + +Func_15498: ; 15498 (5:5498) + call _AIPickPrizeCards + ret +; 0x1549c + +Data_1549c: ; 1549c (5:549c) + db KANGASKHAN + db DRATINI + db EEVEE + db ZAPDOS3 + db ARTICUNO2 + db MOLTRES2 + db $00 + +Data_154a3: ; 154a3 (5:54a3) + db KANGASKHAN + db DRATINI + db EEVEE + db $00 + +Data_154a7: ; 154a7 (5:54a7) + db MOLTRES2 + db ZAPDOS3 + db KANGASKHAN + db DRATINI + db EEVEE + db ARTICUNO2 + db $00 + +Data_154ae: ; 154ae (5:54ae) + airetreat EEVEE, -2 + db $00 + +Data_154b1: ; 154b1 (5:54b1) + aienergy FLAREON1, 3, +0 + aienergy MOLTRES2, 3, +0 + aienergy VAPOREON1, 3, +0 + aienergy ARTICUNO2, 0, -8 + aienergy JOLTEON1, 4, +0 + aienergy ZAPDOS3, 0, -8 + aienergy KANGASKHAN, 4, -1 + aienergy EEVEE, 3, +0 + aienergy DRATINI, 3, +0 + aienergy DRAGONAIR, 4, +0 + aienergy DRAGONITE1, 3, +0 + db $00 + +Data_154d3: ; 154d3 (5:54d3) + db MOLTRES2 + db ARTICUNO2 + db ZAPDOS3 + db DRAGONITE1 + db GAMBLER + db $00 + +Func_154d9: ; 154d9 (5:54d9) + ld hl, wcda8 + ld de, Data_154d3 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdaa + ld de, Data_1549c + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdac + ld de, Data_154a3 + ld [hl], e + inc hl + ld [hl], d + + ld hl, wcdae + ld de, Data_154a7 + ld [hl], e + inc hl + ld [hl], d + +; missing wcdb0 + + ld hl, wcdb2 + ld de, Data_154b1 + ld [hl], e + inc hl + ld [hl], d + + ret +; 0x15507 -- cgit v1.2.3 From 8c1acff885f6c0292a50efecb966f52732836cb9 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 1 May 2020 11:29:17 +0100 Subject: Unpack common turn routines --- src/engine/bank05.asm | 3 - src/engine/deck_ai.asm | 430 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 410 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 96ebe50..989225e 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1605,9 +1605,6 @@ AIPerformSciptedTurn: ; 1483a (5:483a) INCLUDE "engine/deck_ai.asm" -Func_15507: ; 15507 (5:5507) - INCROM $15507, $155d2 - ; 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 diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index f62239e..e4edfdf 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -29,7 +29,9 @@ PointerTable_148dc: ; 148dc (5:48dc) dw Func_148fb Func_148e8: ; 148e8 (5:48e8) - INCROM $148e8, $148ec + call Func_148ff + ret +; 0x148ec Func_148ec: ; 148ec (5:48ec) call InitAIDuelVars @@ -53,7 +55,100 @@ Func_148fb: ; 148fb (5:48fb) ; 0x148ff Func_148ff: ; 148ff (5:48ff) - INCROM $148ff, $149e8 + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall Func_227d3 + jp nc, .asm_149de + farcall HandleAIGoGoRainDanceEnergy + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c + farcall HandleAICowardice + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_1495e + call AIProcessAndTryToPlayEnergy +.asm_1495e + call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c + farcall HandleAIGoGoRainDanceEnergy + ld a, $0d + farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .asm_149de + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_149c9 + call AIProcessAndTryToPlayEnergy +.asm_149c9 + call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c + farcall HandleAIGoGoRainDanceEnergy + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards +.asm_149de + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x149e8 PointerTable_149e8: ; 149e8 (05:49e8) dw Func_149f4 @@ -273,7 +368,9 @@ PointerTable_14b0f: ; 14b0f (05:4b0f) dw Func_14b38 Func_14b1b: ; 14b1b (5:4b1b) - INCROM $14b1b, $14b1f + call Func_14b9a + ret +; 0x14b1f Func_14b1f: ; 14b1f (5:4b1f) call InitAIDuelVars @@ -376,7 +473,62 @@ Func_14b6c: ; 14b6c (5:4b6c) ; 0x14b9a Func_14b9a: ; 14b9a (5:4b9a) - INCROM $14b9a, $14c0b + call InitAITurnVars + farcall Func_227d3 + jp nc, .asm_14c01 + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_14bf8 + ld a, $bb + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, $6d + cp e + jr nz, .asm_14bdb + ld a, $6e + call LookForCardIDInHandList_Bank5 + jr nc, .asm_14bf5 + jr .asm_14be0 +.asm_14bdb + ld a, $71 + cp e + jr nz, .asm_14bf5 +.asm_14be0 + call CreateEnergyCardListFromHand + jr c, .asm_14bf8 + ld e, $00 + call CountNumberOfEnergyCardsAttached + or a + jr nz, .asm_14bf5 + xor a + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .asm_14bf8 +.asm_14bf5 + call AIProcessAndTryToPlayEnergy +.asm_14bf8 + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards +.asm_14c01 + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14c0b PointerTable_14c0b: ; 14c0b (5:4c0b) dw Func_14c17 @@ -387,7 +539,9 @@ PointerTable_14c0b: ; 14c0b (5:4c0b) dw Func_14c34 Func_14c17: ; 14c17 (5:4c17) - INCROM $14c17, $14c1b + call Func_14cf7 + ret +; 0x14c1b Func_14c1b: ; 14c1b (5:4c1b) call InitAIDuelVars @@ -563,7 +717,53 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) ; 0x14cf7 Func_14cf7: ; 14cf7 (5:4cf7) - INCROM $14cf7, $14d60 + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall Func_227d3 + jp nc, .asm_14d56 + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_14d20 + call AIProcessAndTryToPlayEnergy +.asm_14d20 + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .asm_14d56 + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_14d53 + call AIProcessAndTryToPlayEnergy +.asm_14d53 + call AIDecidePlayPokemonCard +.asm_14d56 + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14d60 PointerTable_14d60: ; 14d60 (05:4d60) dw Func_14d6c @@ -574,7 +774,9 @@ PointerTable_14d60: ; 14d60 (05:4d60) dw Func_14d89 Func_14d6c: ; 14d6c (5:4d6c) - INCROM $14d6c, $14d70 + call Func_14def + ret +; 0x14d70 Func_14d70: ; 14d70 (5:4d70) call InitAIDuelVars @@ -678,7 +880,76 @@ Func_14dc1: ; 14dc1 (5:4dc1) ; 0x14def Func_14def: ; 14def (5:4def) - INCROM $14def, $14e89 + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall Func_227d3 + jp nc, .asm_14e7f + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_14e44 + ld a, $bb + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, $b9 + cp e + jr nz, .asm_14e41 + call CreateEnergyCardListFromHand + jr c, .asm_14e44 + ld e, $00 + call CountNumberOfEnergyCardsAttached + or a + jr nz, .asm_14e41 + xor a + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .asm_14e44 +.asm_14e41 + call AIProcessAndTryToPlayEnergy +.asm_14e44 + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .asm_14e7f + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_14e7c + call AIProcessAndTryToPlayEnergy +.asm_14e7c + call AIDecidePlayPokemonCard +.asm_14e7f + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14e89 PointerTable_14e89: ; 14e89 (5:4e89) dw Func_14e95 @@ -689,7 +960,9 @@ PointerTable_14e89: ; 14e89 (5:4e89) dw Func_14eb2 Func_14e95: ; 14e95 (5:4e95) - INCROM $14e95, $14e99 + call _AIMainTurnLogic + ret +; 0x14e99 Func_14e99: ; 14e99 (5:4e99) call InitAIDuelVars @@ -796,7 +1069,9 @@ PointerTable_14f0e: ; 14f0e (5:4f0e) dw Func_14f37 Func_14f1a: ; 14f1a (5:4f1a) - INCROM $14f1a, $14f1e + call _AIMainTurnLogic + ret +; 0x14f1e Func_14f1e: ; 14f1e (5:4f1e) call InitAIDuelVars @@ -901,7 +1176,9 @@ PointerTable_14f8f: ; 14f8f (5:4f8f) dw Func_14fb8 Func_14f9b: ; 14f9b (5:4f9b) - INCROM $14f9b, $14f9f + call _AIMainTurnLogic + ret +; 0x14f9f Func_14f9f: ; 14f9f (5:4f9f) call InitAIDuelVars @@ -1011,7 +1288,9 @@ PointerTable_15019: ; 15019 (5:5019) dw Func_15042 Func_15025: ; 15025 (5:5025) - INCROM $15025, $15029 + call _AIMainTurnLogic + ret +; 0x15029 Func_15029: ; 15029 (5:5029) call InitAIDuelVars @@ -1117,7 +1396,9 @@ PointerTable_1509b: ; 1509b (5:509b) dw Func_150c4 Func_150a7: ; 150a7 (5:50a7) - INCROM $150a7, $150ab + call _AIMainTurnLogic + ret +; 0x150ab Func_150ab: ; 150ab (5:50ab) call InitAIDuelVars @@ -1223,7 +1504,9 @@ PointerTable_15122: ; 15122 (5:5122) dw Func_1514b Func_1512e: ; 1512e (5:512e) - INCROM $1512e, $15132 + call _AIMainTurnLogic + ret +; 0x15132 Func_15132: ; 15132 (5:5132) call InitAIDuelVars @@ -1335,7 +1618,9 @@ PointerTable_151ad: ; 151ad (5:51ad) dw Func_151d6 Func_151b9: ; 151b9 (5:51b9) - INCROM $151b9, $151bd + call _AIMainTurnLogic + ret +; 0x151bd Func_151bd: ; 151bd (5:51bd) call InitAIDuelVars @@ -1443,7 +1728,9 @@ PointerTable_15232: ; 15232 (5:52PointerTable_12) dw Func_1525b Func_1523e: ; 1523e (5:523e) - INCROM $1523e, $15242 + call _AIMainTurnLogic + ret +; 0x15242 Func_15242: ; 15242 (5:5242) call InitAIDuelVars @@ -1554,7 +1841,9 @@ PointerTable_152bd: ; 152bd (5:52bd) dw Func_152e6 Func_152c9: ; 152c9 (5:52c9) - INCROM $152c9, $152cd + call _AIMainTurnLogic + ret +; 0x152cd Func_152cd: ; 152cd (5:52cd) call InitAIDuelVars @@ -1665,7 +1954,9 @@ PointerTable_1534b: ; 1534b (5:534b) dw Func_15374 Func_15357: ; 15357 (5:5357) - INCROM $15357, $1535b + call _AIMainTurnLogic + ret +; 0x1535b Func_1535b: ; 1535b (5:535b) call InitAIDuelVars @@ -1788,7 +2079,9 @@ PointerTable_153e8: ; 153e8 (5:53e8) dw Func_15411 Func_153f4: ; 153f4 (5:53f4) - INCROM $153f4, $153f8 + call _AIMainTurnLogic + ret +; 0x153f8 Func_153f8: ; 153f8 (5:53f8) call InitAIDuelVars @@ -1897,7 +2190,9 @@ PointerTable_1546f: ; 1546f (5:546f) dw Func_15498 Func_1547b: ; 1547b (5:547b) - INCROM $1547b, $1547f + call Func_15507 + ret +; 0x1547f Func_1547f: ; 1547f (5:547f) call InitAIDuelVars @@ -2009,3 +2304,98 @@ Func_154d9: ; 154d9 (5:54d9) ret ; 0x15507 + +Func_15507: ; 15507 (5:5507) + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + ld a, $ef + call GetTurnDuelistVariable + cp $06 + jr nc, .asm_15540 + ld a, $ba + call GetTurnDuelistVariable + cp $33 + jr nc, .asm_15540 + ld a, $27 + call CountPokemonIDInBothPlayAreas + jr c, .asm_15540 + ld a, $40 + call LookForCardIDInHandList_Bank5 + jr nc, .asm_15540 + ldh [hTemp_ffa0], a + ld a, $01 + bank1call AIMakeDecision +.asm_15540 + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_1555f + call AIProcessAndTryToPlayEnergy +.asm_1555f + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .asm_155c8 + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + ld a, $ef + call GetTurnDuelistVariable + cp $06 + jr nc, .asm_155a5 + ld a, $ba + call GetTurnDuelistVariable + cp $33 + jr nc, .asm_155a5 + ld a, $27 + call CountPokemonIDInBothPlayAreas + jr c, .asm_155a5 + ld a, $40 + call LookForCardIDInHandList_Bank5 + jr nc, .asm_155a5 + ldh [hTemp_ffa0], a + ld a, $01 + bank1call AIMakeDecision +.asm_155a5 + call AIDecidePlayPokemonCard + ret c + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call Func_14786 + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .asm_155c4 + call AIProcessAndTryToPlayEnergy +.asm_155c4 + call AIDecidePlayPokemonCard + ret c +.asm_155c8 + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x155d2 -- cgit v1.2.3 From 17b8a2fdc29ff221b18533f06966b02ad0883fb2 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 1 May 2020 17:28:57 +0100 Subject: Document AI Anti Mill strategy --- src/constants/duel_constants.asm | 5 +++ src/engine/bank05.asm | 83 ++++++++++++++++++++++++---------------- src/engine/bank08.asm | 44 +++++++++++++-------- src/engine/deck_ai.asm | 40 +++++++++---------- src/wram.asm | 8 +++- 5 files changed, 112 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index 9cdc73b..47ca1ad 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -263,3 +263,8 @@ AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in det const AI_TRAINER_CARD_PHASE_13 ; $d const AI_TRAINER_CARD_PHASE_14 ; $e const AI_TRAINER_CARD_PHASE_15 ; $f + +; used by wAIBarrierFlagCounter to determine +; whether Player is running Mewtwo1 mill deck. +; flag set means true, flag not set means false. +AI_FLAG_MEWTWO_MILL EQU 1 << 7 diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 989225e..7162983 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1233,7 +1233,7 @@ _AIMainTurnLogic: ; 1468b (5:468b) ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - farcall Func_227d3 + farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack farcall HandleAIGoGoRainDanceEnergy @@ -1719,10 +1719,11 @@ InitAIDuelVars: ; 15636 (5:5636) ld [wcda5], a ret -; initializes some variables and -; sets value of wcda7. +; initializes some variables and sets value of wAIBarrierFlagCounter. +; if Player uses Barrier 3 times in a row, AI checks if Player's deck +; has only Mewtwo1 Pokemon cards (running a Mewtwo1 mill deck). InitAITurnVars: ; 15649 (5:5649) -; increase Pokedex counter by one +; increase Pokedex counter by 1 ld a, [wAIPokedexCounter] inc a ld [wAIPokedexCounter], a @@ -1733,30 +1734,43 @@ InitAITurnVars: ; 15649 (5:5649) ld [wcddc], a ld [wce03], a +; checks if the Player used an attack last turn +; and if it was the second attack of their card. ld a, [wPlayerAttackingMoveIndex] cp $ff - jr z, .asm_156b1 + jr z, .check_flag or a - jr z, .asm_156b1 + jr z, .check_flag ld a, [wPlayerAttackingCardIndex] cp $ff - jr z, .asm_156b1 + jr z, .check_flag +; if the card is Mewtwo1, it means the Player +; used its second attack, Barrier. call SwapTurn call GetCardIDFromDeckIndex call SwapTurn ld a, e cp MEWTWO1 - jr nz, .asm_156b1 + jr nz, .check_flag + ; Player used Barrier last turn -; handle Mewtwo1-only deck - ld a, [wcda7] +; check if flag was already set, if so, +; reset wAIBarrierFlagCounter to $80. + ld a, [wAIBarrierFlagCounter] bit 7, a - jr nz, .asm_156aa + jr nz, .set_flag + +; if not, increase it by 1 and check if it exceeds 2. inc a - ld [wcda7], a - cp $03 + ld [wAIBarrierFlagCounter], a + cp 3 jr c, .done + +; this means that the Player used Barrier +; at least 3 turns in a row. +; check if Player is running Mewtwo1-only deck, +; if so, set wAIBarrierFlagCounter flag. ld a, DUELVARS_ARENA_CARD call GetNonTurnDuelistVariable call SwapTurn @@ -1764,31 +1778,33 @@ InitAITurnVars: ; 15649 (5:5649) call SwapTurn ld a, e cp MEWTWO1 - jr nz, .asm_156a4 + jr nz, .reset_1 farcall CheckIfPlayerHasPokemonOtherThanMewtwo1 - jr nc, .asm_156aa -.asm_156a4 -; reset wcda7 + jr nc, .set_flag +.reset_1 +; reset wAIBarrierFlagCounter xor a - ld [wcda7], a + ld [wAIBarrierFlagCounter], a jr .done -.asm_156aa - ld a, $80 - ld [wcda7], a + +.set_flag + ld a, AI_FLAG_MEWTWO_MILL + 0 + ld [wAIBarrierFlagCounter], a jr .done -.asm_156b1 - ld a, [wcda7] +.check_flag +; increase counter by 1 if flag is set + ld a, [wAIBarrierFlagCounter] bit 7, a - jr z, .asm_156be + jr z, .reset_2 inc a - ld [wcda7], a + ld [wAIBarrierFlagCounter], a jr .done -.asm_156be -; reset wcda7 +.reset_2 +; reset wAIBarrierFlagCounter xor a - ld [wcda7], a + ld [wAIBarrierFlagCounter], a .done ret ; 0x156c3 @@ -4520,11 +4536,12 @@ AIProcessEnergyCards: ; 164fc (5:64fc) jr nz, .bench ; arena - ld a, [wcda7] + ld a, [wAIBarrierFlagCounter] bit 7, a jr z, .add_to_score -; subtract from score +; subtract from score instead +; if Player is running Mewtwo1 mill deck. ld a, 5 call SubFromAIScore jr .check_defending_can_ko @@ -5455,8 +5472,10 @@ AIProcessAttacks: ; 169fc (5:69fc) jr .attack_chosen .no_pluspower - ld a, [wcda7] - cp $80 +; if Player is running Mewtwo1 mill deck, +; skip attack if Barrier counter is 0. + ld a, [wAIBarrierFlagCounter] + cp AI_FLAG_MEWTWO_MILL + 0 jp z, .dont_attack ; determine AI score of both attacks. diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 1c6f82a..8d6d462 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -4698,19 +4698,22 @@ AIPlay_Gambler: ; 2182d (8:582d) ; 0x21875 ; checks whether to play Gambler. -; aside from Imakuni, all other opponents only -; play if there's less than 4 cards in the deck. +; 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 - ld a, [wcda7] - and $80 +; check if flag is set for Player using Mewtwo1 only deck + ld a, [wAIBarrierFlagCounter] + and AI_FLAG_MEWTWO_MILL jr z, .no_carry -; set carry if number of cards in deck <= 4 +; 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 @@ -7487,26 +7490,37 @@ CheckIfPlayerHasPokemonOtherThanMewtwo1: ; 227a9 (8:67a9) ret ; 0x227d3 -; checks wcda7 and Pokemon in Play Area that are set up. -; if there's at least 4, goes to AI_TRAINER_CARD_PHASE_05. -; else, returns carry. -Func_227d3: ; 227d3 (8:67d3) - ld a, [wcda7] +; returns no carry if, given the Player is using a Mewtwo1 mill deck, +; the AI already has a Bench fully set up, in which case it +; will process some Trainer cards in hand (namely Energy Removals). +; this is used to check whether to skip some normal AI routines +; this turn and jump right to the attacking phase. +HandleAIAntiMewtwoDeckStrategy: ; 227d3 (8:67d3) +; return carry if Player is not playing Mewtwo1 mill deck + ld a, [wAIBarrierFlagCounter] bit 7, a jr z, .set_carry - cp %10000010 - jr c, .asm_227e4 -; reset wcda7 +; else, check if there's been less than 2 turns +; without the Player using Barrier. + cp AI_FLAG_MEWTWO_MILL + 2 + jr c, .count_bench + +; if there has been, reset wAIBarrierFlagCounter +; and return carry. xor a - ld [wcda7], a + ld [wAIBarrierFlagCounter], a jr .set_carry -.asm_227e4 +; else, check number of Pokemon that are set up in Bench +; if less than 4, return carry. +.count_bench farcall CountNumberOfSetUpBenchPokemon cp 4 jr c, .set_carry +; if there's at least 4 Pokemon in the Bench set up, +; process Trainer hand cards of AI_TRAINER_CARD_PHASE_05 ld a, AI_TRAINER_CARD_PHASE_05 farcall AIProcessHandTrainerCards or a diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index e4edfdf..c93b8ce 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -58,8 +58,8 @@ Func_148ff: ; 148ff (5:48ff) call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - farcall Func_227d3 - jp nc, .asm_149de + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack farcall HandleAIGoGoRainDanceEnergy farcall HandleAIDamageSwap farcall HandleAIPkmnPowers @@ -105,7 +105,7 @@ Func_148ff: ; 148ff (5:48ff) call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK - jr z, .asm_149de + jr z, .try_attack ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -142,7 +142,7 @@ Func_148ff: ; 148ff (5:48ff) farcall HandleAIGoGoRainDanceEnergy ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards -.asm_149de +.try_attack call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK @@ -277,7 +277,7 @@ Func_14a4a: ; 14a4a (5:4a4a) Func_14a81: ; 14a81 (5:4a81) call InitAITurnVars - farcall Func_227d3 + farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack ld a, AI_TRAINER_CARD_PHASE_02 @@ -474,8 +474,8 @@ Func_14b6c: ; 14b6c (5:4b6c) Func_14b9a: ; 14b9a (5:4b9a) call InitAITurnVars - farcall Func_227d3 - jp nc, .asm_14c01 + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 @@ -522,7 +522,7 @@ Func_14b9a: ; 14b9a (5:4b9a) ret c ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards -.asm_14c01 +.try_attack call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK @@ -720,8 +720,8 @@ Func_14cf7: ; 14cf7 (5:4cf7) call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - farcall Func_227d3 - jp nc, .asm_14d56 + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard @@ -741,7 +741,7 @@ Func_14cf7: ; 14cf7 (5:4cf7) call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK - jr z, .asm_14d56 + jr z, .try_attack ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -757,7 +757,7 @@ Func_14cf7: ; 14cf7 (5:4cf7) call AIProcessAndTryToPlayEnergy .asm_14d53 call AIDecidePlayPokemonCard -.asm_14d56 +.try_attack call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK @@ -883,8 +883,8 @@ Func_14def: ; 14def (5:4def) call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards - farcall Func_227d3 - jp nc, .asm_14e7f + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard @@ -923,7 +923,7 @@ Func_14def: ; 14def (5:4def) call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK - jr z, .asm_14e7f + jr z, .try_attack ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -943,7 +943,7 @@ Func_14def: ; 14def (5:4def) call AIProcessAndTryToPlayEnergy .asm_14e7c call AIDecidePlayPokemonCard -.asm_14e7f +.try_attack call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK @@ -2328,7 +2328,7 @@ Func_15507: ; 15507 (5:5507) call LookForCardIDInHandList_Bank5 jr nc, .asm_15540 ldh [hTemp_ffa0], a - ld a, $01 + ld a, OPPACTION_PLAY_BASIC_PKMN bank1call AIMakeDecision .asm_15540 call AIDecidePlayPokemonCard @@ -2351,7 +2351,7 @@ Func_15507: ; 15507 (5:5507) call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK - jr z, .asm_155c8 + jr z, .try_attack ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -2373,7 +2373,7 @@ Func_15507: ; 15507 (5:5507) call LookForCardIDInHandList_Bank5 jr nc, .asm_155a5 ldh [hTemp_ffa0], a - ld a, $01 + ld a, OPPACTION_PLAY_BASIC_PKMN bank1call AIMakeDecision .asm_155a5 call AIDecidePlayPokemonCard @@ -2392,7 +2392,7 @@ Func_15507: ; 15507 (5:5507) .asm_155c4 call AIDecidePlayPokemonCard ret c -.asm_155c8 +.try_attack call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK diff --git a/src/wram.asm b/src/wram.asm index cae7f88..5614b54 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1192,7 +1192,13 @@ wcda5:: ; cda5 wAIPokedexCounter:: ; cda6 ds $1 -wcda7:: ; cda7 +; variable to keep track of Mewtwo1's Barrier usage during Player' turn. +; AI_FLAG_MEWTWO_MILL set means Player is running Mewtwo1 mill deck. +; - when flag is not set, this counts how many turns in a row +; Player used Mewtwo1's Barrier attack; +; - when flag is set, this counts how many turns in a row +; Player has NOT used Barrier attack. +wAIBarrierFlagCounter:: ; cda7 ds $1 wcda8:: ; cda8 -- cgit v1.2.3 From c4183f69cd8cb0fe1482cac8487efaf68160a411 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 7 May 2020 15:42:13 +0100 Subject: Deck AI macros and tidying --- src/constants/duel_constants.asm | 17 +- src/data/deck_ai_pointers.asm | 106 +-- src/engine/bank05.asm | 238 ++--- src/engine/bank08.asm | 15 +- src/engine/deck_ai.asm | 1956 ++++++++++++++++---------------------- src/wram.asm | 9 +- 6 files changed, 1028 insertions(+), 1313 deletions(-) (limited to 'src') diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index 47ca1ad..dd692d0 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -246,7 +246,11 @@ AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in det ; used to determine which Trainer cards for AI ; to process in AIProcessHandTrainerCards. -; aside from a few exceptions, these go in chronological order. +; these go in chronological order, except for +; AI_TRAINER_CARD_PHASE_14 which happens just before AI attacks. +; AI_TRAINER_CARD_PHASE_15 is reserved for Professor Oak card. +; if Professor Oak is played, all other Trainer card phases +; are processed again except AI_TRAINER_CARD_PHASE_15. const_def 1 const AI_TRAINER_CARD_PHASE_01 ; $1 const AI_TRAINER_CARD_PHASE_02 ; $2 @@ -261,10 +265,17 @@ AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in det const AI_TRAINER_CARD_PHASE_11 ; $b const AI_TRAINER_CARD_PHASE_12 ; $c const AI_TRAINER_CARD_PHASE_13 ; $d - const AI_TRAINER_CARD_PHASE_14 ; $e - const AI_TRAINER_CARD_PHASE_15 ; $f + const AI_TRAINER_CARD_PHASE_14 ; $e, just before attack + const AI_TRAINER_CARD_PHASE_15 ; $f, for Professor Oak ; used by wAIBarrierFlagCounter to determine ; whether Player is running Mewtwo1 mill deck. ; flag set means true, flag not set means false. AI_FLAG_MEWTWO_MILL EQU 1 << 7 + +; defines the behaviour of HandleAIEnergyTrans, for determining +; whether to move energy cards from the Bench to the Arena or vice-versa +; and the number of energy cards needed for achieving that. +AI_ENERGY_TRANS_RETREAT EQU $9 ; moves energy cards needed for Retreat Cost +AI_ENERGY_TRANS_ATTACK EQU $d ; moves energy cards needed for second attack +AI_ENERGY_TRANS_TO_BENCH EQU $e ; moves energy cards away from Arena card diff --git a/src/data/deck_ai_pointers.asm b/src/data/deck_ai_pointers.asm index 13f148b..72cbfb0 100644 --- a/src/data/deck_ai_pointers.asm +++ b/src/data/deck_ai_pointers.asm @@ -1,55 +1,55 @@ PointerTable_14000: ; 14000 (05:4000) - dw PointerTable_147bd ; SAMS_PRACTICE_DECK - dw PointerTable_14668 ; PRACTICE_PLAYER_DECK - dw PointerTable_14668 ; SAMS_NORMAL_DECK - dw PointerTable_14668 ; CHARMANDER_AND_FRIENDS_DECK - dw PointerTable_14668 ; CHARMANDER_EXTRA_DECK - dw PointerTable_14668 ; SQUIRTLE_AND_FRIENDS_DECK - dw PointerTable_14668 ; SQUIRTLE_EXTRA_DECK - dw PointerTable_14668 ; BULBASAUR_AND_FRIENDS_DECK - dw PointerTable_14668 ; BULBASAUR_EXTRA_DECK - dw PointerTable_14668 ; LIGHTNING_AND_FIRE_DECK - dw PointerTable_14668 ; WATER_AND_FIGHTING_DECK - dw PointerTable_14668 ; GRASS_AND_PSYCHIC_DECK - dw PointerTable_149e8 ; LEGENDARY_MOLTRES_DECK - dw PointerTable_14b0f ; LEGENDARY_ZAPDOS_DECK - dw PointerTable_14c0b ; LEGENDARY_ARTICUNO_DECK - dw PointerTable_14d60 ; LEGENDARY_DRAGONITE_DECK - dw PointerTable_14e89 ; FIRST_STRIKE_DECK - dw PointerTable_14f0e ; ROCK_CRUSHER_DECK - dw PointerTable_14f8f ; GO_GO_RAIN_DANCE_DECK - dw PointerTable_15019 ; ZAPPING_SELFDESTRUCT_DECK - dw PointerTable_1509b ; FLOWER_POWER_DECK - dw PointerTable_15122 ; STRANGE_PSYSHOCK_DECK - dw PointerTable_151ad ; WONDERS_OF_SCIENCE_DECK - dw PointerTable_15232 ; FIRE_CHARGE_DECK - dw PointerTable_152bd ; IM_RONALD_DECK - dw PointerTable_1534b ; POWERFUL_RONALD_DECK - dw PointerTable_153e8 ; INVINCIBLE_RONALD_DECK - dw PointerTable_1546f ; LEGENDARY_RONALD_DECK - dw PointerTable_148dc ; MUSCLES_FOR_BRAINS_DECK - dw PointerTable_14668 ; HEATED_BATTLE_DECK - dw PointerTable_14668 ; LOVE_TO_BATTLE_DECK - dw PointerTable_14668 ; EXCAVATION_DECK - dw PointerTable_14668 ; BLISTERING_POKEMON_DECK - dw PointerTable_14668 ; HARD_POKEMON_DECK - dw PointerTable_14668 ; WATERFRONT_POKEMON_DECK - dw PointerTable_14668 ; LONELY_FRIENDS_DECK - dw PointerTable_14668 ; SOUND_OF_THE_WAVES_DECK - dw PointerTable_14668 ; PIKACHU_DECK - dw PointerTable_14668 ; BOOM_BOOM_SELFDESTRUCT_DECK - dw PointerTable_14668 ; POWER_GENERATOR_DECK - dw PointerTable_14668 ; ETCETERA_DECK - dw PointerTable_14668 ; FLOWER_GARDEN_DECK - dw PointerTable_14668 ; KALEIDOSCOPE_DECK - dw PointerTable_14668 ; GHOST_DECK - dw PointerTable_14668 ; NAP_TIME_DECK - dw PointerTable_14668 ; STRANGE_POWER_DECK - dw PointerTable_14668 ; FLYIN_POKEMON_DECK - dw PointerTable_14668 ; LOVELY_NIDORAN_DECK - dw PointerTable_14668 ; POISON_DECK - dw PointerTable_14668 ; ANGER_DECK - dw PointerTable_14668 ; FLAMETHROWER_DECK - dw PointerTable_14668 ; RESHUFFLE_DECK - dw PointerTable_148dc ; IMAKUNI_DECK + dw AIActionTable_SamPractice ; SAMS_PRACTICE_DECK + dw AIActionTable_GeneralDecks ; PRACTICE_PLAYER_DECK + dw AIActionTable_GeneralDecks ; SAMS_NORMAL_DECK + dw AIActionTable_GeneralDecks ; CHARMANDER_AND_FRIENDS_DECK + dw AIActionTable_GeneralDecks ; CHARMANDER_EXTRA_DECK + dw AIActionTable_GeneralDecks ; SQUIRTLE_AND_FRIENDS_DECK + dw AIActionTable_GeneralDecks ; SQUIRTLE_EXTRA_DECK + dw AIActionTable_GeneralDecks ; BULBASAUR_AND_FRIENDS_DECK + dw AIActionTable_GeneralDecks ; BULBASAUR_EXTRA_DECK + dw AIActionTable_GeneralDecks ; LIGHTNING_AND_FIRE_DECK + dw AIActionTable_GeneralDecks ; WATER_AND_FIGHTING_DECK + dw AIActionTable_GeneralDecks ; GRASS_AND_PSYCHIC_DECK + dw AIActionTable_LegendaryMoltres ; LEGENDARY_MOLTRES_DECK + dw AIActionTable_LegendaryZapdos ; LEGENDARY_ZAPDOS_DECK + dw AIActionTable_LegendaryArticuno ; LEGENDARY_ARTICUNO_DECK + dw AIActionTable_LegendaryDragonite ; LEGENDARY_DRAGONITE_DECK + dw AIActionTable_FirstStrike ; FIRST_STRIKE_DECK + dw AIActionTable_RockCrusher ; ROCK_CRUSHER_DECK + dw AIActionTable_GoGoRainDance ; GO_GO_RAIN_DANCE_DECK + dw AIActionTable_ZappingSelfdestruct ; ZAPPING_SELFDESTRUCT_DECK + dw AIActionTable_FlowerPower ; FLOWER_POWER_DECK + dw AIActionTable_StrangePsyshock ; STRANGE_PSYSHOCK_DECK + dw AIActionTable_WondersOfScience ; WONDERS_OF_SCIENCE_DECK + dw AIActionTable_FireCharge ; FIRE_CHARGE_DECK + dw AIActionTable_ImRonald ; IM_RONALD_DECK + dw AIActionTable_PowerfulRonald ; POWERFUL_RONALD_DECK + dw AIActionTable_InvincibleRonald ; INVINCIBLE_RONALD_DECK + dw AIActionTable_LegendaryRonald ; LEGENDARY_RONALD_DECK + dw AIActionTable_GeneralNoRetreat ; MUSCLES_FOR_BRAINS_DECK + dw AIActionTable_GeneralDecks ; HEATED_BATTLE_DECK + dw AIActionTable_GeneralDecks ; LOVE_TO_BATTLE_DECK + dw AIActionTable_GeneralDecks ; EXCAVATION_DECK + dw AIActionTable_GeneralDecks ; BLISTERING_POKEMON_DECK + dw AIActionTable_GeneralDecks ; HARD_POKEMON_DECK + dw AIActionTable_GeneralDecks ; WATERFRONT_POKEMON_DECK + dw AIActionTable_GeneralDecks ; LONELY_FRIENDS_DECK + dw AIActionTable_GeneralDecks ; SOUND_OF_THE_WAVES_DECK + dw AIActionTable_GeneralDecks ; PIKACHU_DECK + dw AIActionTable_GeneralDecks ; BOOM_BOOM_SELFDESTRUCT_DECK + dw AIActionTable_GeneralDecks ; POWER_GENERATOR_DECK + dw AIActionTable_GeneralDecks ; ETCETERA_DECK + dw AIActionTable_GeneralDecks ; FLOWER_GARDEN_DECK + dw AIActionTable_GeneralDecks ; KALEIDOSCOPE_DECK + dw AIActionTable_GeneralDecks ; GHOST_DECK + dw AIActionTable_GeneralDecks ; NAP_TIME_DECK + dw AIActionTable_GeneralDecks ; STRANGE_POWER_DECK + dw AIActionTable_GeneralDecks ; FLYIN_POKEMON_DECK + dw AIActionTable_GeneralDecks ; LOVELY_NIDORAN_DECK + dw AIActionTable_GeneralDecks ; POISON_DECK + dw AIActionTable_GeneralDecks ; ANGER_DECK + dw AIActionTable_GeneralDecks ; FLAMETHROWER_DECK + dw AIActionTable_GeneralDecks ; RESHUFFLE_DECK + dw AIActionTable_GeneralNoRetreat ; IMAKUNI_DECK ; 1406a diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 7162983..8943187 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1,25 +1,25 @@ INCLUDE "data/deck_ai_pointers.asm" -PointerTable_1406a: ; 1406a (5:406a) +AIActionTable_Unreferenced: ; 1406a (5:406a) dw $406c - dw Func_14078 - dw Func_14078 - dw Func_1409e - dw $40a2 - dw $40a6 - dw $40aa - -Func_14078: ; 14078 (5:4078) + dw .do_turn + dw .do_turn + dw .star_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14078 (5:4078) call AIDecidePlayPokemonCard call AIDecideWhetherToRetreat - jr nc, .asm_14091 + jr nc, .try_attack call AIDecideBenchPokemonToSwitchTo - call AIChooseEnergyToDiscardForRetreatCost + call AITryToRetreat call AIDecideWhetherToRetreat - jr nc, .asm_14091 + jr nc, .try_attack call AIDecideBenchPokemonToSwitchTo - call AIChooseEnergyToDiscardForRetreatCost -.asm_14091 + call AITryToRetreat +.try_attack call AIProcessAndTryToPlayEnergy call AIProcessAndTryToUseAttack ret c @@ -28,8 +28,25 @@ Func_14078: ; 14078 (5:4078) ret ; 0x1409e -Func_1409e: ; 1409e (5:409e) - INCROM $1409e, $140ae +.star_duel ; 1409e (5:409e) + call AIPlayInitialBasicCards + ret +; 0x140a2 + +.forced_switch ; 140a2 (5:40a2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x140a6 + +.ko_switch ; 140a6 (5:40a6) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x140aa + +.take_prize ; 140aa (5:40aa) + call AIPickPrizeCards + ret +; 0x140ae ; returns carry if damage dealt from any of ; a card's moves KOs defending Pokémon @@ -290,7 +307,7 @@ PickRandomBenchPokemon: ; 141da (5:41da) ret ; 0x141e5 -_AIPickPrizeCards: ; 141e5 (5:41e5) +AIPickPrizeCards: ; 141e5 (5:41e5) ld a, [wNumberPrizeCardsToTake] ld b, a .loop @@ -578,7 +595,7 @@ ConvertColorToEnergyCardID: ; 1430f (5:430f) db FIGHTING_ENERGY db PSYCHIC_ENERGY db DOUBLE_COLORLESS_ENERGY - + Func_14323: ; 14323 (5:4323) INCROM $14323, $1433d @@ -1060,13 +1077,13 @@ EstimateDamage_FromDefendingPokemon: ; 1450b (5:450b) ; damage as the receiver CalculateDamage_FromDefendingPokemon: ; 1458c (5:458c) ld hl, wAIMinDamage - call _CalculateDamage_FromDefendingPokemon + call .CalculateDamage ld hl, wAIMaxDamage - call _CalculateDamage_FromDefendingPokemon + call .CalculateDamage ld hl, wDamage -; fallthrough + ; fallthrough -_CalculateDamage_FromDefendingPokemon: ; 1459b (5:459b) +.CalculateDamage ; 1459b (5:459b) ld e, [hl] ld d, $00 push hl @@ -1196,62 +1213,62 @@ AIProcessHandTrainerCards: ; 14663 (5:4663) farcall _AIProcessHandTrainerCards ret -; GENERAL DECK POINTER LIST - Not sure on all of these. -; This is an example of an AI pointer table, there's one for each AI type. -PointerTable_14668: ; 14668 (05:4668) - dw AIMainTurnLogic ; not used - dw AIMainTurnLogic ; general AI for battles - dw AIDuelStart ; basic pokemon placement / cheater shuffling on better AI - dw AIRetreatLogic ; deciding which Bench Pokemon to switch to - dw Func_14683 - dw AIPickPrizeCards +AIActionTable_GeneralDecks: ; 14668 (05:4668) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -AIMainTurnLogic: ; 14674 (5:4674) - call _AIMainTurnLogic +.do_turn ; 14674 (5:4674) + call AIMainTurnLogic ret -AIDuelStart: ; 14678 (5:4678) +.start_duel ; 14678 (5:4678) call InitAIDuelVars call AIPlayInitialBasicCards ret -AIRetreatLogic: ; 1467f (5:467f) +.forced_switch ; 1467f (5:467f) call AIDecideBenchPokemonToSwitchTo ret -Func_14683: ; 14683 (5:4683) +.ko_switch ; 14683 (5:4683) call AIDecideBenchPokemonToSwitchTo ret -AIPickPrizeCards: ; 14687 (5:4687) - call _AIPickPrizeCards +.take_prize: ; 14687 (5:4687) + call AIPickPrizeCards ret ; handle AI routines for a whole turn -_AIMainTurnLogic: ; 1468b (5:468b) +AIMainTurnLogic: ; 1468b (5:468b) +; initialize variables call InitAITurnVars - ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack - +; handle Pkmn Powers farcall HandleAIGoGoRainDanceEnergy farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c - + ret c ; return if turn ended farcall HandleAICowardice - +; process Trainer cards +; phase 2 through 4. ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_03 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c - + ret c ; return if turn ended +; process Trainer cards +; phase 5 through 12. ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_06 @@ -1260,39 +1277,38 @@ _AIMainTurnLogic: ; 1468b (5:468b) call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_08 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_12 call AIProcessHandTrainerCards - +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a - jr nz, .already_played_energy_1 + jr nz, .skip_energy_attach_1 call AIProcessAndTryToPlayEnergy - -.already_played_energy_1 +.skip_energy_attach_1 +; play Pokemon from hand again call AIDecidePlayPokemonCard - +; handle Pkmn Powers again farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c + ret c ; return if turn ended farcall HandleAIGoGoRainDanceEnergy - ld a, $0d ; attack + ld a, AI_ENERGY_TRANS_ATTACK farcall HandleAIEnergyTrans - +; process Trainer cards phases 13 and 15 ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards - +; if used Professor Oak, process new hand +; if not, then proceed to attack. ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK jr z, .try_attack - -; used Professor Oak ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 @@ -1302,8 +1318,7 @@ _AIMainTurnLogic: ; 1468b (5:468b) ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard - ret c - + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_06 @@ -1312,35 +1327,33 @@ _AIMainTurnLogic: ; 1468b (5:468b) call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_08 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_12 - call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .already_played_energy_2 + jr nz, .skip_energy_attach_2 call AIProcessAndTryToPlayEnergy -.already_played_energy_2 +.skip_energy_attach_2 call AIDecidePlayPokemonCard - farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c + ret c ; return if turn ended farcall HandleAIGoGoRainDanceEnergy - ld a, $0d ; attack + ld a, AI_ENERGY_TRANS_ATTACK farcall HandleAIEnergyTrans - ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards - + ; skip AI_TRAINER_CARD_PHASE_15 .try_attack - ld a, $0e + ld a, AI_ENERGY_TRANS_TO_BENCH farcall HandleAIEnergyTrans - +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack ret c ; return if AI attacked ld a, OPPACTION_FINISH_NO_ATTACK @@ -1348,11 +1361,11 @@ _AIMainTurnLogic: ; 1468b (5:468b) ret ; 0x14786 -; handles retreating -Func_14786: ; 14786 (5:4786) - ld a, [wce03] +; handles AI retreating logic +AIProcessRetreat: ; 14786 (5:4786) + ld a, [wAIRetreatedThisTurn] or a - ret nz + ret nz ; return, already retreated this turn call AIDecideWhetherToRetreat ret nc ; return if not retreating @@ -1360,74 +1373,88 @@ Func_14786: ; 14786 (5:4786) call AIDecideBenchPokemonToSwitchTo ret c ; return if no Bench Pokemon - ld [wcdd5], a +; store Play Area to retreat to and +; set wAIRetreatedThisTurn to true + ld [wAIPlayAreaCardToSwitch], a ld a, $01 - ld [wce03], a + ld [wAIRetreatedThisTurn], a +; if AI can use Switch from hand, use it instead... ld a, AI_TRAINER_CARD_PHASE_09 call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_SWITCH jr nz, .used_switch - ld a, [wcdd5] - call AIChooseEnergyToDiscardForRetreatCost +; ... else try retreating normally. + ld a, [wAIPlayAreaCardToSwitch] + call AITryToRetreat ret .used_switch +; if AI used switch, unset its AI flag ld a, [wPreviousAIFlags] and ~AI_FLAG_USED_SWITCH ; clear Switch flag ld [wPreviousAIFlags], a - ld a, $09 ; retreat + +; bug, this doesn't make sense being here, since at this point +; Switch Trainer card was already used to retreat the Pokemon. +; what the routine will do is just transfer Energy cards to +; the Arena Pokemon for the purpose of retreating, and +; then not actually retreat, resulting in unusual behaviour. +; this would only work placed right after the AI checks whether +; they have Switch card in hand to use and doesn't have one. +; (and probably that was the original intention.) + ld a, AI_ENERGY_TRANS_RETREAT ; retreat farcall HandleAIEnergyTrans ret ; 0x147bd -PointerTable_147bd: ; 147bd (05:47bd) - dw Func_147c9 - dw Func_147c9 - dw Func_147d6 - dw Func_147da - dw Func_147e7 - dw Func_147f4 +AIActionTable_SamPractice: ; 147bd (05:47bd) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_147c9: ; 147c9 (5:47c9) +.do_turn ; 147c9 (5:47c9) call IsAIPracticeScriptedTurn - jr nc, .scripted + jr nc, .scripted_1 ; not scripted, use AI main turn logic - call _AIMainTurnLogic + call AIMainTurnLogic ret -.scripted ; use scripted actions instead +.scripted_1 ; use scripted actions instead call AIPerformSciptedTurn ret ; 0x147d6 -Func_147d6: ; 147d6 (5:47d6) +.start_duel ; 147d6 (5:47d6) call Func_14801 ret ; 0x147da -Func_147da: ; 147da (5:47da) +.forced_switch ; 147da (5:47da) call IsAIPracticeScriptedTurn - jr nc, .scripted + jr nc, .scripted_2 call AIDecideBenchPokemonToSwitchTo ret -.scripted +.scripted_2 call PickRandomBenchPokemon ret ; 0x147e7 -Func_147e7: ; 147e7 (5:47e7) +.ko_switch: ; 147e7 (5:47e7) call IsAIPracticeScriptedTurn - jr nc, .scripted + jr nc, .scripted_3 call AIDecideBenchPokemonToSwitchTo ret -.scripted +.scripted_3 call GetPlayAreaLocationOfRaticateOrRattata ret ; 0x147f4 -Func_147f4: ; 147f4 (5:47f4) - call _AIPickPrizeCards +.take_prize: ; 147f4 (5:47f4) + call AIPickPrizeCards ret ; 0x147f8 @@ -1585,7 +1612,7 @@ AIPerformSciptedTurn: ; 1483a (5:483a) inc a ; PLAY_AREA_BENCH_2 .retreat - call AIChooseEnergyToDiscardForRetreatCost + call AITryToRetreat ret ; 0x148cc @@ -1732,7 +1759,7 @@ InitAITurnVars: ; 15649 (5:5649) ld [wPreviousAIFlags], a ld [wcddb], a ld [wcddc], a - ld [wce03], a + ld [wAIRetreatedThisTurn], a ; checks if the Player used an attack last turn ; and if it was the second attack of their card. @@ -2994,7 +3021,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; handle its effect to discard itself instead of retreating. ; input: ; - a = Play Area location (PLAY_AREA_*) of card to retreat to. -AIChooseEnergyToDiscardForRetreatCost: ; 15d4f (5:5d4f) +AITryToRetreat: ; 15d4f (5:5d4f) push af ld a, [wAIPlayEnergyCardForRetreat] or a @@ -7104,8 +7131,7 @@ CheckCardEvolutionInHandOrDeck: ; 17274 (5:7274) ; sets up the inital hand of boss deck. ; always draws at least 2 Basic Pokemon cards and 2 Energy cards. ; also sets up so that the next cards to be drawn have -; some minimum number of Basic Pokemon and Energy cards -; and avoids deck-specific list of cards. +; some minimum number of Basic Pokemon and Energy cards. SetUpBossStartingHandAndDeck: ; 172af (5:72af) ; shuffle all hand cards in deck ld a, DUELVARS_HAND @@ -7170,7 +7196,7 @@ SetUpBossStartingHandAndDeck: ; 172af (5:72af) cp 2 jr c, .shuffle_deck -; now check the following 6 cards. +; now check the following 6 cards (prize cards). ; re-shuffle deck if any of these cards is listed in wcda8. ld b, 6 .check_card_ids diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 8d6d462..df8d7c5 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6223,9 +6223,13 @@ AIDecide_PokemonTrader_Flamethrower: ; 22133 (8:6133) ; 0x2219b ; handle AI routines for Energy Trans. -; depending on input, AI can use Energy Trans to -; give Arena or Bench cards some Grass energy cards, -; depending whether it's for attack, retreat, etc. +; uses AI_ENERGY_TRANS_* constants as input: +; - AI_ENERGY_TRANS_RETREAT: transfers enough Grass Energy cards to +; Arena Pokemon for it to be able to pay the Retreat Cost; +; - AI_ENERGY_TRANS_ATTACK: transfers enough Grass Energy cards to +; Arena Pokemon for it to be able to use its second attack; +; - AI_ENERGY_TRANS_TO_BENCH: transfers all Grass Energy cards from +; Arena Pokemon to Bench in case Arena card will be KO'd. HandleAIEnergyTrans: ; 2219b (8:619b) ld [wce06], a @@ -6247,12 +6251,13 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ret c ; return if Muk found in any Play Area ld a, [wce06] - cp $09 + cp AI_ENERGY_TRANS_RETREAT jr z, .check_retreat - cp $0e + cp AI_ENERGY_TRANS_TO_BENCH jp z, .TransferEnergyToBench + ; AI_ENERGY_TRANS_ATTACK call .CheckEnoughGrassEnergyCardsForAttack ret nc jr .TransferEnergyToArena diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index c93b8ce..2a78848 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -3,76 +3,93 @@ ; a Pokemon to switch to, it looks up in this list and if ; a card ID matches, applies a retreat score bonus to this card. ; positive (negative) means more (less) likely to switch to this card. -airetreat: MACRO +ai_retreat: MACRO db \1 ; card ID db $80 + \2 ; retreat score (ranges between -128 and 127) ENDM ; AI card energy attach score bonus -; when the AI energy attachment run through the Play Area to choose +; when the AI energy attachment routine runs through the Play Area to choose ; a Pokemon to attach an energy card, it looks up in this list and if ; a card ID matches, skips this card if the maximum number of energy ; cards attached has been reached. If it hasn't been reached, additionally ; applies a positive (or negative) AI score to attach energy to this card. -aienergy: MACRO +ai_energy: MACRO db \1 ; card ID db \2 ; maximum number of attached cards db $80 + \3 ; energy score (ranges between -128 and 127) ENDM -PointerTable_148dc: ; 148dc (5:48dc) - dw Func_148e8 - dw Func_148e8 - dw Func_148ec - dw Func_148f3 - dw Func_148f7 - dw Func_148fb +; stores in WRAM pointer to data in argument +; e.g. store_list_pointer wSomeListPointer, SomeData +store_list_pointer: MACRO + ld hl, \1 + ld de, \2 + ld [hl], e + inc hl + ld [hl], d +ENDM -Func_148e8: ; 148e8 (5:48e8) - call Func_148ff +AIActionTable_GeneralNoRetreat: ; 148dc (5:48dc) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 148e8 (5:48e8) + call AIDoTurn_GeneralNoRetreat ret ; 0x148ec -Func_148ec: ; 148ec (5:48ec) +.start_duel ; 148ec (5:48ec) call InitAIDuelVars call AIPlayInitialBasicCards ret ; 0x148f3 -Func_148f3: ; 148f3 (5:48f3) +.forced_switch ; 148f3 (5:48f3) call AIDecideBenchPokemonToSwitchTo ret ; 0x148f7 -Func_148f7: ; 148f7 (5:48f7) +.ko_switch ; 148f7 (5:48f7) call AIDecideBenchPokemonToSwitchTo ret ; 0x148fb -Func_148fb: ; 148fb (5:48fb) - call _AIPickPrizeCards +.take_prize ; 148fb (5:48fb) + call AIPickPrizeCards ret ; 0x148ff -Func_148ff: ; 148ff (5:48ff) +AIDoTurn_GeneralNoRetreat: ; 148ff (5:48ff) +; initialize variables call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack +; handle Pkmn Powers farcall HandleAIGoGoRainDanceEnergy farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c + ret c ; return if turn ended farcall HandleAICowardice +; process Trainer cards +; phase 2 through 4. ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_03 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended +; process Trainer cards +; phase 5 through 12. ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_06 @@ -87,22 +104,28 @@ Func_148ff: ; 148ff (5:48ff) call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_12 call AIProcessHandTrainerCards +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_1495e + jr nz, .skip_energy_attach_1 call AIProcessAndTryToPlayEnergy -.asm_1495e +.skip_energy_attach_1 +; play Pokemon from hand again call AIDecidePlayPokemonCard +; handle Pkmn Powers again farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c + ret c ; return if turn ended farcall HandleAIGoGoRainDanceEnergy - ld a, $0d + ld a, AI_ENERGY_TRANS_ATTACK farcall HandleAIEnergyTrans +; process Trainer cards phases 13 and 15 ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards +; if used Professor Oak, process new hand +; if not, then proceed to attack. ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK jr z, .try_attack @@ -115,7 +138,7 @@ Func_148ff: ; 148ff (5:48ff) ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_06 @@ -132,40 +155,43 @@ Func_148ff: ; 148ff (5:48ff) call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_149c9 + jr nz, .skip_energy_attach_2 call AIProcessAndTryToPlayEnergy -.asm_149c9 +.skip_energy_attach_2 call AIDecidePlayPokemonCard farcall HandleAIDamageSwap farcall HandleAIPkmnPowers - ret c + ret c ; return if turn ended farcall HandleAIGoGoRainDanceEnergy ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards + ; skip AI_TRAINER_CARD_PHASE_15 .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack - ret c + ret c ; return if turn ended ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x149e8 -PointerTable_149e8: ; 149e8 (05:49e8) - dw Func_149f4 - dw Func_149f4 - dw Func_149f8 - dw Func_14a09 - dw Func_14a0d - dw Func_14a11 +AIActionTable_LegendaryMoltres: ; 149e8 (05:49e8) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_149f4: ; 149f4 (5:49f4) - call Func_14a81 +.do_turn ; 149f4 (5:49f4) + call AIDoTurn_LegendaryMoltres ret ; 0x149f8 -Func_149f8: ; 149f8 (5:49f8) +.start_duel ; 149f8 (5:49f8) call InitAIDuelVars - call Func_14a4a + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc ; Play Area set up was successful @@ -173,22 +199,22 @@ Func_149f8: ; 149f8 (5:49f8) ret ; 0x14a09 -Func_14a09: ; 14a09 (5:4a09) +.forced_switch ; 14a09 (5:4a09) call AIDecideBenchPokemonToSwitchTo ret ; 0x14a0d -Func_14a0d: ; 14a0d (5:4a0d) +.ko_switch ; 14a0d (5:4a0d) call AIDecideBenchPokemonToSwitchTo ret ; 0x14a11 -Func_14a11: ; 14a11 (5:4a11) - call _AIPickPrizeCards +.take_prize ; 14a11 (5:4a11) + call AIPickPrizeCards ret ; 0x14a15 -Data_14a15: ; 14a15 (5:4a15) +.list_arena ; 14a15 (5:4a15) db MAGMAR2 db GROWLITHE db VULPIX @@ -197,7 +223,7 @@ Data_14a15: ; 14a15 (5:4a15) db MOLTRES2 db $00 -Data_14a1c: ; 14a1c (5:4a1c) +.list_bench ; 14a1c (5:4a1c) db MOLTRES1 db VULPIX db GROWLITHE @@ -205,7 +231,7 @@ Data_14a1c: ; 14a1c (5:4a1c) db MAGMAR1 db $00 -Data_14a22: ; 14a22 (5:4a22) +.list_play_hand ; 14a22 (5:4a22) db MOLTRES2 db MOLTRES1 db VULPIX @@ -214,79 +240,51 @@ Data_14a22: ; 14a22 (5:4a22) db MAGMAR1 db $00 -Data_14a29: ; 14a29 (5:4a29) - airetreat GROWLITHE, -5 - airetreat VULPIX, -5 +.list_retreat ; 14a29 (5:4a29) + ai_retreat GROWLITHE, -5 + ai_retreat VULPIX, -5 db $00 -Data_14a2e: ; 14a2e (5:4a2e) - aienergy VULPIX, 3, +0 - aienergy NINETAILS2, 3, +1 - aienergy GROWLITHE, 3, +1 - aienergy ARCANINE2, 4, +1 - aienergy MAGMAR1, 4, -1 - aienergy MAGMAR2, 1, -1 - aienergy MOLTRES2, 3, +2 - aienergy MOLTRES1, 4, +2 +.list_energy ; 14a2e (5:4a2e) + ai_energy VULPIX, 3, +0 + ai_energy NINETAILS2, 3, +1 + ai_energy GROWLITHE, 3, +1 + ai_energy ARCANINE2, 4, +1 + ai_energy MAGMAR1, 4, -1 + ai_energy MAGMAR2, 1, -1 + ai_energy MOLTRES2, 3, +2 + ai_energy MOLTRES1, 4, +2 db $00 -Data_14a47: ; 14a47 (5:4a47) +.list_prize ; 14a47 (5:4a47) db ENERGY_REMOVAL db MOLTRES2 db $00 -Func_14a4a: ; 14a4a (5:4a4a) - ld hl, wcda8 - ld de, Data_14a47 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14a15 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14a1c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14a22 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb0 - ld de, Data_14a29 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdb2 - ld de, Data_14a2e - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14a4a (5:4a4a) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_play_hand + store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14a81 -Func_14a81: ; 14a81 (5:4a81) +AIDoTurn_LegendaryMoltres: ; 14a81 (5:4a81) +; initialize variables call InitAITurnVars farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack - +; process Trainer cards +; phase 2 through 4. ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards -; check if AI can play Moltres2 from hand -; if so, play it. +; check if AI can play Moltres2 +; from hand and if so, play it. ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable cp MAX_PLAY_AREA_POKEMON @@ -306,17 +304,18 @@ Func_14a81: ; 14a81 (5:4a81) bank1call AIMakeDecision .skip_moltres +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards - -; handle attaching energy from hand +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a jr nz, .skip_attach_energy @@ -343,8 +342,8 @@ Func_14a81: ; 14a81 (5:4a81) jr c, .skip_attach_energy .attach_normally +; play Energy card if possible call AIProcessAndTryToPlayEnergy - .skip_attach_energy ; try playing Pokemon cards from hand again call AIDecidePlayPokemonCard @@ -352,6 +351,8 @@ Func_14a81: ; 14a81 (5:4a81) call AIProcessHandTrainerCards .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack ret c ld a, OPPACTION_FINISH_NO_ATTACK @@ -359,22 +360,22 @@ Func_14a81: ; 14a81 (5:4a81) ret ; 0x14b0f -PointerTable_14b0f: ; 14b0f (05:4b0f) - dw Func_14b1b - dw Func_14b1b - dw Func_14b1f - dw Func_14b30 - dw Func_14b34 - dw Func_14b38 +AIActionTable_LegendaryZapdos: ; 14b0f (05:4b0f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14b1b: ; 14b1b (5:4b1b) - call Func_14b9a +.do_turn ; 14b1b (5:4b1b) + call AIDoTurn_LegendaryZapdos ret ; 0x14b1f -Func_14b1f: ; 14b1f (5:4b1f) +.start_duel ; 14b1f (5:4b1f) call InitAIDuelVars - call Func_14b6c + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -382,22 +383,22 @@ Func_14b1f: ; 14b1f (5:4b1f) ret ; 0x14b30 -Func_14b30: ; 14b30 (5:4b30) +.forced_switch ; 14b30 (5:4b30) call AIDecideBenchPokemonToSwitchTo ret ; 0x14b34 -Func_14b34: ; 14b34 (5:4b34) +.ko_switch ; 14b34 (5:4b34) call AIDecideBenchPokemonToSwitchTo ret ; 0x14b38 -Func_14b38: ; 14b38 (5:4b38) - call _AIPickPrizeCards +.take_prize ; 14b38 (5:4b38) + call AIPickPrizeCards ret ; 0x14b3c -Data_14b3c: ; 14b3c (5:4b3c) +.list_arena ; 14b3c (5:4b3c) db ELECTABUZZ2 db VOLTORB db EEVEE @@ -406,7 +407,7 @@ Data_14b3c: ; 14b3c (5:4b3c) db ZAPDOS3 db $00 -Data_14b43: ; 14b43 (5:4b43) +.list_bench ; 14b43 (5:4b43) db ZAPDOS2 db ZAPDOS1 db EEVEE @@ -414,138 +415,128 @@ Data_14b43: ; 14b43 (5:4b43) db ELECTABUZZ2 db $00 -Data_14b49: ; 14b49 (5:4b49) - airetreat EEVEE, -5 - airetreat VOLTORB, -5 - airetreat ELECTABUZZ2, -5 +.list_retreat ; 14b49 (5:4b49) + ai_retreat EEVEE, -5 + ai_retreat VOLTORB, -5 + ai_retreat ELECTABUZZ2, -5 db $00 -Data_14b50: ; 14b50 (5:4b50) - aienergy VOLTORB, 1, -1 - aienergy ELECTRODE1, 3, +0 - aienergy ELECTABUZZ2, 2, -1 - aienergy JOLTEON2, 3, +1 - aienergy ZAPDOS1, 4, +2 - aienergy ZAPDOS2, 4, +2 - aienergy ZAPDOS3, 3, +1 - aienergy EEVEE, 3, +0 +.list_energy ; 14b50 (5:4b50) + ai_energy VOLTORB, 1, -1 + ai_energy ELECTRODE1, 3, +0 + ai_energy ELECTABUZZ2, 2, -1 + ai_energy JOLTEON2, 3, +1 + ai_energy ZAPDOS1, 4, +2 + ai_energy ZAPDOS2, 4, +2 + ai_energy ZAPDOS3, 3, +1 + ai_energy EEVEE, 3, +0 db $00 -Data_14b69: ; 14b69 (5:4b69) +.list_prize ; 14b69 (5:4b69) db GAMBLER db ZAPDOS3 db $00 -Func_14b6c: ; 14b6c (5:4b6c) - ld hl, wcda8 - ld de, Data_14b69 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14b3c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14b43 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14b43 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14b50 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14b6c (5:4b6c) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14b9a -Func_14b9a: ; 14b9a (5:4b9a) +AIDoTurn_LegendaryZapdos: ; 14b9a (5:4b9a) +; initialize variables call InitAITurnVars farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards +; play Energy card if possible. ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_14bf8 - ld a, $bb + jr nz, .skip_energy_attach + +; if Arena card is Voltorb and there's Electrode1 in hand, +; or if it's Electabuzz, try attaching Energy card +; to the Arena card if it doesn't have any energy attached. +; Otherwise if Energy card is not needed, +; go through normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable call GetCardIDFromDeckIndex - ld a, $6d + ld a, VOLTORB cp e - jr nz, .asm_14bdb - ld a, $6e + jr nz, .check_electabuzz + ld a, ELECTRODE1 call LookForCardIDInHandList_Bank5 - jr nc, .asm_14bf5 - jr .asm_14be0 -.asm_14bdb - ld a, $71 + jr nc, .attach_normally + jr .voltorb_or_electabuzz +.check_electabuzz + ld a, ELECTABUZZ2 cp e - jr nz, .asm_14bf5 -.asm_14be0 + jr nz, .attach_normally + +.voltorb_or_electabuzz call CreateEnergyCardListFromHand - jr c, .asm_14bf8 - ld e, $00 + jr c, .skip_energy_attach + ld e, PLAY_AREA_ARENA call CountNumberOfEnergyCardsAttached or a - jr nz, .asm_14bf5 - xor a + jr nz, .attach_normally + xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a call AITryToPlayEnergyCard - jr c, .asm_14bf8 -.asm_14bf5 + jr c, .skip_energy_attach + +.attach_normally call AIProcessAndTryToPlayEnergy -.asm_14bf8 + +.skip_energy_attach +; play Pokemon from hand again call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack - ret c + ret c ; return if turn ended ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x14c0b -PointerTable_14c0b: ; 14c0b (5:4c0b) - dw Func_14c17 - dw Func_14c17 - dw Func_14c1b - dw Func_14c2c - dw Func_14c30 - dw Func_14c34 +AIActionTable_LegendaryArticuno: ; 14c0b (5:4c0b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14c17: ; 14c17 (5:4c17) - call Func_14cf7 +.do_turn ; 14c17 (5:4c17) + call AIDoTurn_LegendaryArticuno ret ; 0x14c1b -Func_14c1b: ; 14c1b (5:4c1b) +.start_duel ; 14c1b (5:4c1b) call InitAIDuelVars - call Func_14c63 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -553,22 +544,22 @@ Func_14c1b: ; 14c1b (5:4c1b) ret ; 0x14c2c -Func_14c2c: ; 14c2c (5:4c2c) +.forced_switch ; 14c2c (5:4c2c) call AIDecideBenchPokemonToSwitchTo ret ; 0x14c30 -Func_14c30: ; 14c30 (5:4c30) +.ko_switch ; 14c30 (5:4c30) call AIDecideBenchPokemonToSwitchTo ret ; 0x14c34 -Func_14c34: ; 14c34 (5:4c34) - call _AIPickPrizeCards +.take_prize ; 14c34 (5:4c34) + call AIPickPrizeCards ret ; 0x14c38 -Data_14c38: ; 14c38 (5:4c38) +.list_arena ; 14c38 (5:4c38) db CHANSEY db LAPRAS db DITTO @@ -577,7 +568,7 @@ Data_14c38: ; 14c38 (5:4c38) db ARTICUNO2 db $00 -Data_14c3f: ; 14c3f (5:4c3f) +.list_bench ; 14c3f (5:4c3f) db ARTICUNO1 db SEEL db LAPRAS @@ -585,59 +576,33 @@ Data_14c3f: ; 14c3f (5:4c3f) db DITTO db $00 -Data_14c45: ; 14c45 (5:4c45) - airetreat SEEL, -3 - airetreat DITTO, -3 +.list_retreat ; 14c45 (5:4c45) + ai_retreat SEEL, -3 + ai_retreat DITTO, -3 db $00 -Data_14c4a: ; 14c4a (5:4c4a) - aienergy SEEL, 3, +1 - aienergy DEWGONG, 4, +0 - aienergy LAPRAS, 3, +0 - aienergy ARTICUNO1, 4, +1 - aienergy ARTICUNO2, 3, +0 - aienergy CHANSEY, 0, -8 - aienergy DITTO, 3, +0 +.list_energy ; 14c4a (5:4c4a) + ai_energy SEEL, 3, +1 + ai_energy DEWGONG, 4, +0 + ai_energy LAPRAS, 3, +0 + ai_energy ARTICUNO1, 4, +1 + ai_energy ARTICUNO2, 3, +0 + ai_energy CHANSEY, 0, -8 + ai_energy DITTO, 3, +0 db $00 -Data_14c60: ; 14c60 (5:4c60) +.list_prize ; 14c60 (5:4c60) db GAMBLER db ARTICUNO2 db $00 -Func_14c63: ; 14c63 (5:4c63) - ld hl, wcda8 - ld de, Data_14c60 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14c38 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14c3f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14c3f - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14c4a - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14c63 (5:4c63) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14c91 @@ -716,29 +681,36 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) ret ; 0x14cf7 -Func_14cf7: ; 14cf7 (5:4cf7) +AIDoTurn_LegendaryArticuno: ; 14cf7 (5:4cf7) +; initialize variables call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c - call Func_14786 + ret c ; return if turn ended + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_14d20 + jr nz, .skip_energy_attach_1 call AIProcessAndTryToPlayEnergy -.asm_14d20 +.skip_energy_attach_1 +; play Pokemon from hand again call AIDecidePlayPokemonCard +; process Trainer cards phases 13 and 15 ld a, AI_TRAINER_CARD_PHASE_13 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards +; if used Professor Oak, process new hand ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK jr z, .try_attack @@ -747,40 +719,42 @@ Func_14cf7: ; 14cf7 (5:4cf7) ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard - ret c - call Func_14786 + ret c ; return if turn ended + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_14d53 + jr nz, .skip_energy_attach_2 call AIProcessAndTryToPlayEnergy -.asm_14d53 +.skip_energy_attach_2 call AIDecidePlayPokemonCard .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack - ret c + ret c ; return if turn ended ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x14d60 -PointerTable_14d60: ; 14d60 (05:4d60) - dw Func_14d6c - dw Func_14d6c - dw Func_14d70 - dw Func_14d81 - dw Func_14d85 - dw Func_14d89 +AIActionTable_LegendaryDragonite: ; 14d60 (05:4d60) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14d6c: ; 14d6c (5:4d6c) - call Func_14def +.do_turn ; 14d6c (5:4d6c) + call AIDoTurn_LegendaryDragonite ret ; 0x14d70 -Func_14d70: ; 14d70 (5:4d70) +.start_duel ; 14d70 (5:4d70) call InitAIDuelVars - call Func_14dc1 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -788,22 +762,22 @@ Func_14d70: ; 14d70 (5:4d70) ret ; 0x14d81 -Func_14d81: ; 14d81 (5:4d81) +.forced_switch ; 14d81 (5:4d81) call AIDecideBenchPokemonToSwitchTo ret ; 0x14d85 -Func_14d85: ; 14d85 (5:4d85) +.ko_switch ; 14d85 (5:4d85) call AIDecideBenchPokemonToSwitchTo ret ; 0x14d89 -Func_14d89: ; 14d89 (5:4d89) - call _AIPickPrizeCards +.take_prize ; 14d89 (5:4d89) + call AIPickPrizeCards ret ; 0x14d8d -Data_14d8d: ; 14d8d (5:4d8d) +.list_arena ; 14d8d (5:4d8d) db KANGASKHAN db LAPRAS db CHARMANDER @@ -811,7 +785,7 @@ Data_14d8d: ; 14d8d (5:4d8d) db MAGIKARP db $00 -Data_14d93: ; 14d93 (5:4d93) +.list_bench ; 14d93 (5:4d93) db CHARMANDER db MAGIKARP db DRATINI @@ -819,108 +793,94 @@ Data_14d93: ; 14d93 (5:4d93) db KANGASKHAN db $00 -Data_14d99: ; 14d99 (5:4d99) - airetreat CHARMANDER, -1 - airetreat MAGIKARP, -5 +.list_retreat ; 14d99 (5:4d99) + ai_retreat CHARMANDER, -1 + ai_retreat MAGIKARP, -5 db $00 -Data_14d9e: ; 14d9e (5:4d9e) - aienergy CHARMANDER, 3, +1 - aienergy CHARMELEON, 4, +1 - aienergy CHARIZARD, 5, +0 - aienergy MAGIKARP, 3, +1 - aienergy GYARADOS, 4, -1 - aienergy DRATINI, 2, +0 - aienergy DRAGONAIR, 4, +0 - aienergy DRAGONITE1, 3, -1 - aienergy KANGASKHAN, 2, -2 - aienergy LAPRAS, 3, +0 +.list_energy ; 14d9e (5:4d9e) + ai_energy CHARMANDER, 3, +1 + ai_energy CHARMELEON, 4, +1 + ai_energy CHARIZARD, 5, +0 + ai_energy MAGIKARP, 3, +1 + ai_energy GYARADOS, 4, -1 + ai_energy DRATINI, 2, +0 + ai_energy DRAGONAIR, 4, +0 + ai_energy DRAGONITE1, 3, -1 + ai_energy KANGASKHAN, 2, -2 + ai_energy LAPRAS, 3, +0 db $00 -Data_14dbd: ; 14dbd (5:4dbd) +.list_prize ; 14dbd (5:4dbd) db GAMBLER db DRAGONITE1 db KANGASKHAN db $00 -Func_14dc1: ; 14dc1 (5:4dc1) - ld hl, wcda8 - ld de, Data_14dbd - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14d8d - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14d93 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14d93 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14d9e - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14dc1 (5:4dc1) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14def -Func_14def: ; 14def (5:4def) +AIDoTurn_LegendaryDragonite: ; 14def (5:4def) +; initialize variables call InitAITurnVars ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards farcall HandleAIAntiMewtwoDeckStrategy jp nc, .try_attack +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_14e44 - ld a, $bb + jr nz, .skip_energy_attach_1 + +; if Arena card is Kangaskhan and doens't +; have Energy cards attached, try attaching from hand. +; otherwise run normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable call GetCardIDFromDeckIndex - ld a, $b9 + ld a, KANGASKHAN cp e - jr nz, .asm_14e41 + jr nz, .attach_normally call CreateEnergyCardListFromHand - jr c, .asm_14e44 - ld e, $00 + jr c, .skip_energy_attach_1 + ld e, PLAY_AREA_ARENA call CountNumberOfEnergyCardsAttached or a - jr nz, .asm_14e41 + jr nz, .attach_normally xor a ldh [hTempPlayAreaLocation_ff9d], a call AITryToPlayEnergyCard - jr c, .asm_14e44 -.asm_14e41 + jr c, .skip_energy_attach_1 +.attach_normally call AIProcessAndTryToPlayEnergy -.asm_14e44 + +.skip_energy_attach_1 +; play Pokemon from hand again call AIDecidePlayPokemonCard ld a, AI_TRAINER_CARD_PHASE_15 call AIProcessHandTrainerCards +; if used Professor Oak, process new hand +; if not, then proceed to attack. ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK jr z, .try_attack @@ -929,44 +889,46 @@ Func_14def: ; 14def (5:4def) ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_11 call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_14e7c + jr nz, .skip_energy_attach_2 call AIProcessAndTryToPlayEnergy -.asm_14e7c +.skip_energy_attach_2 call AIDecidePlayPokemonCard .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack - ret c + ret c ; return if turn ended ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret ; 0x14e89 -PointerTable_14e89: ; 14e89 (5:4e89) - dw Func_14e95 - dw Func_14e95 - dw Func_14e99 - dw Func_14eaa - dw Func_14eae - dw Func_14eb2 +AIActionTable_FirstStrike: ; 14e89 (5:4e89) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14e95: ; 14e95 (5:4e95) - call _AIMainTurnLogic +.do_turn ; 14e95 (5:4e95) + call AIMainTurnLogic ret ; 0x14e99 -Func_14e99: ; 14e99 (5:4e99) +.start_duel ; 14e99 (5:4e99) call InitAIDuelVars - call Func_14ee0 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -974,108 +936,82 @@ Func_14e99: ; 14e99 (5:4e99) ret ; 0x14eaa -Func_14eaa: ; 14eaa (5:4eaa) +.forced_switch ; 14eaa (5:4eaa) call AIDecideBenchPokemonToSwitchTo ret ; 0x14eae -Func_14eae: ; 14eae (5:4eae) +.ko_switch ; 14eae (5:4eae) call AIDecideBenchPokemonToSwitchTo ret ; 0x14eb2 -Func_14eb2: ; 14eb2 (5:4eb2) - call _AIPickPrizeCards +.take_prize ; 14eb2 (5:4eb2) + call AIPickPrizeCards ret ; 0x14eb6 -Data_14eb6: ; 14eb6 (5:1eb6) +.list_arena ; 14eb6 (5:1eb6) db HITMONCHAN db MACHOP db HITMONLEE db MANKEY db $00 -Data_14ebb: ; 14ebb (5:1ebb) +.list_bench ; 14ebb (5:1ebb) db MACHOP db HITMONLEE db HITMONCHAN db MANKEY db $00 -Data_14ec0: ; 14ec0 (5:1ec0) - airetreat MACHOP, - 1 - airetreat MACHOKE, - 1 - airetreat MANKEY, - 2 +.list_retreat ; 14ec0 (5:1ec0) + ai_retreat MACHOP, - 1 + ai_retreat MACHOKE, - 1 + ai_retreat MANKEY, - 2 db $00 -Data_14ec7: ; 14ec7 (5:1ec7) - aienergy MACHOP, 3, +0 - aienergy MACHOKE, 4, +0 - aienergy MACHAMP, 4, -1 - aienergy HITMONCHAN, 3, +0 - aienergy HITMONLEE, 3, +0 - aienergy MANKEY, 2, -1 - aienergy PRIMEAPE, 3, -1 +.list_energy ; 14ec7 (5:1ec7) + ai_energy MACHOP, 3, +0 + ai_energy MACHOKE, 4, +0 + ai_energy MACHAMP, 4, -1 + ai_energy HITMONCHAN, 3, +0 + ai_energy HITMONLEE, 3, +0 + ai_energy MANKEY, 2, -1 + ai_energy PRIMEAPE, 3, -1 db $00 -Data_14edd: ; 14edd (5:1edd) +.list_prize ; 14edd (5:1edd) db HITMONLEE db HITMONCHAN db $00 -Func_14ee0: ; 14ee0 (5:4ee0) - ld hl, wcda8 - ld de, Data_14edd - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14eb6 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14ebb - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14ebb - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14ec7 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14ee0 (5:4ee0) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14f0e -PointerTable_14f0e: ; 14f0e (5:4f0e) - dw Func_14f1a - dw Func_14f1a - dw Func_14f1e - dw Func_14f2f - dw Func_14f33 - dw Func_14f37 +AIActionTable_RockCrusher: ; 14f0e (5:4f0e) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14f1a: ; 14f1a (5:4f1a) - call _AIMainTurnLogic +.do_turn ; 14f1a (5:4f1a) + call AIMainTurnLogic ret ; 0x14f1e -Func_14f1e: ; 14f1e (5:4f1e) +.start_duel ; 14f1e (5:4f1e) call InitAIDuelVars - call Func_14f61 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1083,106 +1019,80 @@ Func_14f1e: ; 14f1e (5:4f1e) ret ; 0x14f2f -Func_14f2f: ; 14f2f (5:4f2f) +.forced_switch ; 14f2f (5:4f2f) call AIDecideBenchPokemonToSwitchTo ret ; 0x14f33 -Func_14f33: ; 14f33 (5:4f33) +.ko_switch ; 14f33 (5:4f33) call AIDecideBenchPokemonToSwitchTo ret ; 0x14f37 -Func_14f37: ; 14f37 (5:4f37) - call _AIPickPrizeCards +.take_prize ; 14f37 (5:4f37) + call AIPickPrizeCards ret ; 0x14f3b -Data_14f3b: ; 14f3b (5:4f3b) +.list_arena ; 14f3b (5:4f3b) db RHYHORN db ONIX db GEODUDE db DIGLETT db $00 -Data_14f40: ; 14f40 (5:4f40) +.list_bench ; 14f40 (5:4f40) db DIGLETT db GEODUDE db RHYHORN db ONIX db $00 -Data_14f45: ; 14f45 (5:4f45) - airetreat DIGLETT, -1 +.list_retreat ; 14f45 (5:4f45) + ai_retreat DIGLETT, -1 db $00 -Data_14f48: ; 14f48 (5:4f48) - aienergy DIGLETT, 3, +1 - aienergy DUGTRIO, 4, +0 - aienergy GEODUDE, 2, +1 - aienergy GRAVELER, 3, +0 - aienergy GOLEM, 4, +0 - aienergy ONIX, 2, -1 - aienergy RHYHORN, 3, +0 +.list_energy ; 14f48 (5:4f48) + ai_energy DIGLETT, 3, +1 + ai_energy DUGTRIO, 4, +0 + ai_energy GEODUDE, 2, +1 + ai_energy GRAVELER, 3, +0 + ai_energy GOLEM, 4, +0 + ai_energy ONIX, 2, -1 + ai_energy RHYHORN, 3, +0 db $00 -Data_14f5e: ; 14f5e (5:4f5e) +.list_prize ; 14f5e (5:4f5e) db ENERGY_REMOVAL db RHYHORN db $00 -Func_14f61: ; 14f61 (5:4f61) - ld hl, wcda8 - ld de, Data_14f5e - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14f3b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14f40 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14f40 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14f48 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14f61 (5:4f61) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x14f8f -PointerTable_14f8f: ; 14f8f (5:4f8f) - dw Func_14f9b - dw Func_14f9b - dw Func_14f9f - dw Func_14fb0 - dw Func_14fb4 - dw Func_14fb8 +AIActionTable_GoGoRainDance: ; 14f8f (5:4f8f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_14f9b: ; 14f9b (5:4f9b) - call _AIMainTurnLogic +.do_turn ; 14f9b (5:4f9b) + call AIMainTurnLogic ret ; 0x14f9f -Func_14f9f: ; 14f9f (5:4f9f) +.start_duel ; 14f9f (5:4f9f) call InitAIDuelVars - call Func_14feb + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1190,111 +1100,85 @@ Func_14f9f: ; 14f9f (5:4f9f) ret ; 0x14fb0 -Func_14fb0: ; 14fb0 (5:4fb0) +.forced_switch ; 14fb0 (5:4fb0) call AIDecideBenchPokemonToSwitchTo ret ; 0x14fb4 -Func_14fb4: ; 14fb4 (5:4fb4) +.ko_switch ; 14fb4 (5:4fb4) call AIDecideBenchPokemonToSwitchTo ret ; 0x14fb8 -Func_14fb8: ; 14fb8 (5:4fb8) - call _AIPickPrizeCards +.take_prize ; 14fb8 (5:4fb8) + call AIPickPrizeCards ret ; 0x14fbc -Data_14fbc: ; 14fbc (5:4fbc) +.list_arena ; 14fbc (5:4fbc) db LAPRAS db HORSEA db GOLDEEN db SQUIRTLE db $00 -Data_14fc1: ; 14fc1 (5:4fc1) +.list_bench ; 14fc1 (5:4fc1) db SQUIRTLE db HORSEA db GOLDEEN db LAPRAS db $00 -Data_14fc6: ; 14fc6 (5:4fc6) - airetreat SQUIRTLE, -3 - airetreat WARTORTLE, -2 - airetreat HORSEA, -1 +.list_retreat ; 14fc6 (5:4fc6) + ai_retreat SQUIRTLE, -3 + ai_retreat WARTORTLE, -2 + ai_retreat HORSEA, -1 db $00 -Data_14fcd: ; 14fcd (5:4fcd) - aienergy SQUIRTLE, 2, +0 - aienergy WARTORTLE, 3, +0 - aienergy BLASTOISE, 5, +0 - aienergy GOLDEEN, 1, +0 - aienergy SEAKING, 2, +0 - aienergy HORSEA, 2, +0 - aienergy SEADRA, 3, +0 - aienergy LAPRAS, 3, +0 +.list_energy ; 14fcd (5:4fcd) + ai_energy SQUIRTLE, 2, +0 + ai_energy WARTORTLE, 3, +0 + ai_energy BLASTOISE, 5, +0 + ai_energy GOLDEEN, 1, +0 + ai_energy SEAKING, 2, +0 + ai_energy HORSEA, 2, +0 + ai_energy SEADRA, 3, +0 + ai_energy LAPRAS, 3, +0 db $00 -Data_14fe6: ; 14fe6 (5:4fe6) +.list_prize ; 14fe6 (5:4fe6) db GAMBLER db ENERGY_RETRIEVAL db SUPER_ENERGY_RETRIEVAL db BLASTOISE db $00 -Func_14feb: ; 14feb (5:4feb) - ld hl, wcda8 - ld de, Data_14fe6 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_14fbc - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_14fc1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_14fc1 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_14fcd - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 14feb (5:4feb) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x15019 -PointerTable_15019: ; 15019 (5:5019) - dw Func_15025 - dw Func_15025 - dw Func_15029 - dw Func_1503a - dw Func_1503e - dw Func_15042 +AIActionTable_ZappingSelfdestruct: ; 15019 (5:5019) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_15025: ; 15025 (5:5025) - call _AIMainTurnLogic +.do_turn ; 15025 (5:5025) + call AIMainTurnLogic ret ; 0x15029 -Func_15029: ; 15029 (5:5029) +.start_duel ; 15029 (5:5029) call InitAIDuelVars - call Func_1506d + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1302,22 +1186,22 @@ Func_15029: ; 15029 (5:5029) ret ; 0x1503a -Func_1503a: ; 1503a (5:503a) +.forced_switch ; 1503a (5:503a) call AIDecideBenchPokemonToSwitchTo ret ; 0x1503e -Func_1503e: ; 1503e (5:503e) +.ko_switch ; 1503e (5:503e) call AIDecideBenchPokemonToSwitchTo ret ; 0x15042 -Func_15042: ; 15042 (5:5042) - call _AIPickPrizeCards +.take_prize ; 15042 (5:5042) + call AIPickPrizeCards ret ; 0x15046 -Data_15046: ; 15046 (5:5046) +.list_arena ; 15046 (5:5046) db KANGASKHAN db ELECTABUZZ2 db TAUROS @@ -1325,7 +1209,7 @@ Data_15046: ; 15046 (5:5046) db VOLTORB db $00 -Data_1504c: ; 1504c (5:504c) +.list_bench ; 1504c (5:504c) db MAGNEMITE1 db VOLTORB db ELECTABUZZ2 @@ -1333,76 +1217,50 @@ Data_1504c: ; 1504c (5:504c) db KANGASKHAN db $00 -Data_15052: ; 15052 (5:5052) - airetreat VOLTORB, -1 +.list_retreat ; 15052 (5:5052) + ai_retreat VOLTORB, -1 db $00 -Data_15055: ; 15055 (5:5055) - aienergy MAGNEMITE1, 3, +1 - aienergy MAGNETON1, 4, +0 - aienergy VOLTORB, 3, +1 - aienergy ELECTRODE1, 3, +0 - aienergy ELECTABUZZ2, 1, +0 - aienergy KANGASKHAN, 2, -2 - aienergy TAUROS, 3, +0 +.list_energy ; 15055 (5:5055) + ai_energy MAGNEMITE1, 3, +1 + ai_energy MAGNETON1, 4, +0 + ai_energy VOLTORB, 3, +1 + ai_energy ELECTRODE1, 3, +0 + ai_energy ELECTABUZZ2, 1, +0 + ai_energy KANGASKHAN, 2, -2 + ai_energy TAUROS, 3, +0 db $00 -Data_1506b: ; 1506b (5:506b) +.list_prize ; 1506b (5:506b) db KANGASKHAN db $00 -Func_1506d: ; 1506d (5:506d) - ld hl, wcda8 - ld de, Data_1506b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15046 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_1504c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_1504c - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_15055 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 1506d (5:506d) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x1509b -PointerTable_1509b: ; 1509b (5:509b) - dw Func_150a7 - dw Func_150a7 - dw Func_150ab - dw Func_150bc - dw Func_150c0 - dw Func_150c4 +AIActionTable_FlowerPower: ; 1509b (5:509b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_150a7: ; 150a7 (5:50a7) - call _AIMainTurnLogic +.do_turn ; 150a7 (5:50a7) + call AIMainTurnLogic ret ; 0x150ab -Func_150ab: ; 150ab (5:50ab) +.start_duel ; 150ab (5:50ab) call InitAIDuelVars - call Func_150f4 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1410,107 +1268,81 @@ Func_150ab: ; 150ab (5:50ab) ret ; 0x150bc -Func_150bc: ; 150bc (5:50bc) +.forced_switch ; 150bc (5:50bc) call AIDecideBenchPokemonToSwitchTo ret ; 0x150c0 -Func_150c0: ; 150c0 (5:50c0) +.ko_switch ; 150c0 (5:50c0) call AIDecideBenchPokemonToSwitchTo ret ; 0x150c4 -Func_150c4: ; 150c4 (5:50c4) - call _AIPickPrizeCards +.take_prize ; 150c4 (5:50c4) + call AIPickPrizeCards ret ; 0x150c8 -Data_150c8 ; 150c8 (5:50c8) +.list_arena ; 150c8 (5:50c8) db ODDISH db EXEGGCUTE db BULBASAUR db $00 -Data_150cc ; 150cc (5:50cc) +.list_bench ; 150cc (5:50cc) db BULBASAUR db EXEGGCUTE db ODDISH db $00 -Data_150cf ; 150cf (5:50cf) - airetreat GLOOM, -2 - airetreat VILEPLUME, -2 - airetreat BULBASAUR, -2 - airetreat IVYSAUR, -2 +.list_retreat ; 150cf (5:50cf) + ai_retreat GLOOM, -2 + ai_retreat VILEPLUME, -2 + ai_retreat BULBASAUR, -2 + ai_retreat IVYSAUR, -2 db $00 -Data_150d9 ; 150d9 (5:50d9) - aienergy BULBASAUR, 3, +0 - aienergy IVYSAUR, 4, +0 - aienergy VENUSAUR2, 4, +0 - aienergy ODDISH, 2, +0 - aienergy GLOOM, 3, -1 - aienergy VILEPLUME, 3, -1 - aienergy EXEGGCUTE, 3, +0 - aienergy EXEGGUTOR, 22, +0 +.list_energy ; 150d9 (5:50d9) + ai_energy BULBASAUR, 3, +0 + ai_energy IVYSAUR, 4, +0 + ai_energy VENUSAUR2, 4, +0 + ai_energy ODDISH, 2, +0 + ai_energy GLOOM, 3, -1 + ai_energy VILEPLUME, 3, -1 + ai_energy EXEGGCUTE, 3, +0 + ai_energy EXEGGUTOR, 22, +0 db $00 -Data_150f2 ; 150f2 (5:50f2) +.list_prize ; 150f2 (5:50f2) db VENUSAUR2 db $00 -Func_150f4: ; 150f4 (5:50f4) - ld hl, wcda8 - ld de, Data_150f2 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_150c8 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_150cc - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_150cc - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_150d9 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 150f4 (5:50f4) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x15122 -PointerTable_15122: ; 15122 (5:5122) - dw Func_1512e - dw Func_1512e - dw Func_15132 - dw Func_15143 - dw Func_15147 - dw Func_1514b +AIActionTable_StrangePsyshock: ; 15122 (5:5122) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_1512e: ; 1512e (5:512e) - call _AIMainTurnLogic +.do_turn ; 1512e (5:512e) + call AIMainTurnLogic ret ; 0x15132 -Func_15132: ; 15132 (5:5132) +.start_duel ; 15132 (5:5132) call InitAIDuelVars - call Func_1517f + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1518,22 +1350,22 @@ Func_15132: ; 15132 (5:5132) ret ; 0x15143 -Func_15143: ; 15143 (5:5143) +.forced_switch ; 15143 (5:5143) call AIDecideBenchPokemonToSwitchTo ret ; 0x15147 -Func_15147: ; 15147 (5:5147) +.ko_switch ; 15147 (5:5147) call AIDecideBenchPokemonToSwitchTo ret ; 0x1514b -Func_1514b: ; 1514b (5:514b) - call _AIPickPrizeCards +.take_prize ; 1514b (5:514b) + call AIPickPrizeCards ret ; 0x1514f -Data_1514f: ; 1514f (5:514f) +.list_arena ; 1514f (5:514f) db KANGASKHAN db CHANSEY db SNORLAX @@ -1541,7 +1373,7 @@ Data_1514f: ; 1514f (5:514f) db ABRA db $00 -Data_15155: ; 15155 (5:5155) +.list_bench ; 15155 (5:5155) db ABRA db MR_MIME db KANGASKHAN @@ -1549,82 +1381,56 @@ Data_15155: ; 15155 (5:5155) db CHANSEY db $00 -Data_1515b: ; 1515b (5:515b) - airetreat ABRA, -3 - airetreat SNORLAX, -3 - airetreat KANGASKHAN, -1 - airetreat CHANSEY, -1 +.list_retreat ; 1515b (5:515b) + ai_retreat ABRA, -3 + ai_retreat SNORLAX, -3 + ai_retreat KANGASKHAN, -1 + ai_retreat CHANSEY, -1 db $00 -Data_15164 ; 15164 (5:5164) - aienergy ABRA, 3, +1 - aienergy KADABRA, 3, +0 - aienergy ALAKAZAM, 3, +0 - aienergy MR_MIME, 2, +0 - aienergy CHANSEY, 2, -2 - aienergy KANGASKHAN, 4, -2 - aienergy SNORLAX, 0, -8 +.list_energy ; 15164 (5:5164) + ai_energy ABRA, 3, +1 + ai_energy KADABRA, 3, +0 + ai_energy ALAKAZAM, 3, +0 + ai_energy MR_MIME, 2, +0 + ai_energy CHANSEY, 2, -2 + ai_energy KANGASKHAN, 4, -2 + ai_energy SNORLAX, 0, -8 db $00 -Data_1517a ; 1517a (5:517a) +.list_prize ; 1517a (5:517a) db GAMBLER db MR_MIME db ALAKAZAM db SWITCH db $00 -Func_1517f: ; 1517f (5:517f) - ld hl, wcda8 - ld de, Data_1517a - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1514f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15155 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15155 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_15164 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 1517f (5:517f) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x151ad -PointerTable_151ad: ; 151ad (5:51ad) - dw Func_151b9 - dw Func_151b9 - dw Func_151bd - dw Func_151ce - dw Func_151d2 - dw Func_151d6 +AIActionTable_WondersOfScience: ; 151ad (5:51ad) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_151b9: ; 151b9 (5:51b9) - call _AIMainTurnLogic +.do_turn ; 151b9 (5:51b9) + call AIMainTurnLogic ret ; 0x151bd -Func_151bd: ; 151bd (5:51bd) +.start_duel ; 151bd (5:51bd) call InitAIDuelVars - call Func_15204 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1632,22 +1438,22 @@ Func_151bd: ; 151bd (5:51bd) ret ; 0x151ce -Func_151ce: ; 151ce (5:51ce) +.forced_switch ; 151ce (5:51ce) call AIDecideBenchPokemonToSwitchTo ret ; 0x151d2 -Func_151d2: ; 151d2 (5:51d2) +.ko_switch ; 151d2 (5:51d2) call AIDecideBenchPokemonToSwitchTo ret ; 0x151d6 -Func_151d6: ; 151d6 (5:51d6) - call _AIPickPrizeCards +.take_prize ; 151d6 (5:51d6) + call AIPickPrizeCards ret ; 0x151da -Data_151da: ; 151da (5:51da) +.list_arena ; 151da (5:51da) db MEWTWO1 db MEWTWO3 db MEWTWO2 @@ -1656,7 +1462,7 @@ Data_151da: ; 151da (5:51da) db PORYGON db $00 -Data_151e1: ; 151e1 (5:51e1) +.list_bench ; 151e1 (5:51e1) db GRIMER db KOFFING db MEWTWO3 @@ -1665,76 +1471,50 @@ Data_151e1: ; 151e1 (5:51e1) db PORYGON db $00 -Data_151e8: ; 151e8 (5:51e8) +.list_retreat ; 151e8 (5:51e8) db $00 -Data_151e9: ; 151e9 (5:51e9) - aienergy GRIMER, 3, +0 - aienergy MUK, 4, +0 - aienergy KOFFING, 2, +0 - aienergy WEEZING, 3, +0 - aienergy MEWTWO1, 2, -1 - aienergy MEWTWO3, 2, -1 - aienergy MEWTWO2, 2, -1 - aienergy PORYGON, 2, -1 +.list_energy ; 151e9 (5:51e9) + ai_energy GRIMER, 3, +0 + ai_energy MUK, 4, +0 + ai_energy KOFFING, 2, +0 + ai_energy WEEZING, 3, +0 + ai_energy MEWTWO1, 2, -1 + ai_energy MEWTWO3, 2, -1 + ai_energy MEWTWO2, 2, -1 + ai_energy PORYGON, 2, -1 db $00 -Data_15202: ; 15202 (5:5202) +.list_prize ; 15202 (5:5202) db MUK db $00 -Func_15204: ; 15204 (5:5204) - ld hl, wcda8 - ld de, Data_15202 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_151da - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_151e1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_151e1 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_151e9 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 15204 (5:5204) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x15232 -PointerTable_15232: ; 15232 (5:52PointerTable_12) - dw Func_1523e - dw Func_1523e - dw Func_15242 - dw Func_15253 - dw Func_15257 - dw Func_1525b +AIActionTable_FireCharge: ; 15232 (5:5232) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_1523e: ; 1523e (5:523e) - call _AIMainTurnLogic +.do_turn ; 1523e (5:523e) + call AIMainTurnLogic ret ; 0x15242 -Func_15242: ; 15242 (5:5242) +.start_duel ; 15242 (5:5242) call InitAIDuelVars - call Func_1528f + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1742,22 +1522,22 @@ Func_15242: ; 15242 (5:5242) ret ; 0x15253 -Func_15253: ; 15253 (5:5253) +.forced_switch ; 15253 (5:5253) call AIDecideBenchPokemonToSwitchTo ret ; 0x15257 -Func_15257: ; 15257 (5:5257) +.ko_switch ; 15257 (5:5257) call AIDecideBenchPokemonToSwitchTo ret ; 0x1525b -Func_1525b: ; 1525b (5:525b) - call _AIPickPrizeCards +.take_prize ; 1525b (5:525b) + call AIPickPrizeCards ret ; 0x1525f -Data_1525f: ; 1525f (5:525f) +.list_arena ; 1525f (5:525f) db JIGGLYPUFF3 db CHANSEY db TAUROS @@ -1766,7 +1546,7 @@ Data_1525f: ; 1525f (5:525f) db GROWLITHE db $00 -Data_15266: ; 15266 (5:5266) +.list_bench ; 15266 (5:5266) db JIGGLYPUFF3 db CHANSEY db GROWLITHE @@ -1775,79 +1555,53 @@ Data_15266: ; 15266 (5:5266) db TAUROS db $00 -Data_1526e: ; 1526e (5:526e) - airetreat JIGGLYPUFF1, -1 - airetreat CHANSEY, -1 - airetreat GROWLITHE, -1 +.list_retreat ; 1526e (5:526e) + ai_retreat JIGGLYPUFF1, -1 + ai_retreat CHANSEY, -1 + ai_retreat GROWLITHE, -1 db $00 -Data_15274: ; 15274 (5:5274) - aienergy GROWLITHE, 3, +0 - aienergy ARCANINE2, 4, +0 - aienergy MAGMAR1, 3, +0 - aienergy JIGGLYPUFF1, 3, +0 - aienergy JIGGLYPUFF3, 2, +0 - aienergy WIGGLYTUFF, 3, +0 - aienergy CHANSEY, 4, +0 - aienergy TAUROS, 3, +0 +.list_energy ; 15274 (5:5274) + ai_energy GROWLITHE, 3, +0 + ai_energy ARCANINE2, 4, +0 + ai_energy MAGMAR1, 3, +0 + ai_energy JIGGLYPUFF1, 3, +0 + ai_energy JIGGLYPUFF3, 2, +0 + ai_energy WIGGLYTUFF, 3, +0 + ai_energy CHANSEY, 4, +0 + ai_energy TAUROS, 3, +0 db $00 -Data_1528d: ; 1528d (5:528d) +.list_prize ; 1528d (5:528d) db GAMBLER db $00 -Func_1528f: ; 1528f (5:528f) - ld hl, wcda8 - ld de, Data_1528d - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1525f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15266 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15266 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_15274 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 1528f (5:528f) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x152bd -PointerTable_152bd: ; 152bd (5:52bd) - dw Func_152c9 - dw Func_152c9 - dw Func_152cd - dw Func_152de - dw Func_152e2 - dw Func_152e6 +AIActionTable_ImRonald: ; 152bd (5:52bd) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_152c9: ; 152c9 (5:52c9) - call _AIMainTurnLogic +.do_turn ; 152c9 (5:52c9) + call AIMainTurnLogic ret ; 0x152cd -Func_152cd: ; 152cd (5:52cd) +.start_duel ; 152cd (5:52cd) call InitAIDuelVars - call Func_1531d + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1855,22 +1609,22 @@ Func_152cd: ; 152cd (5:52cd) ret ; 0x152de -Func_152de: ; 152de (5:52de) +.forced_switch ; 152de (5:52de) call AIDecideBenchPokemonToSwitchTo ret ; 0x152e2 -Func_152e2: ; 152e2 (5:52e2) +.ko_switch ; 152e2 (5:52e2) call AIDecideBenchPokemonToSwitchTo ret ; 0x152e6 -Func_152e6: ; 152e6 (5:52e6) - call _AIPickPrizeCards +.take_prize ; 152e6 (5:52e6) + call AIPickPrizeCards ret ; 0x152ea -Data_152ea: ; 152ea (5:52ea) +.list_arena ; 152ea (5:52ea) db LAPRAS db SEEL db CHARMANDER @@ -1879,7 +1633,7 @@ Data_152ea: ; 152ea (5:52ea) db GROWLITHE db $00 -Data_152f1: ; 152f1 (5:52f1) +.list_bench ; 152f1 (5:52f1) db CHARMANDER db SQUIRTLE db SEEL @@ -1888,79 +1642,53 @@ Data_152f1: ; 152f1 (5:52f1) db LAPRAS db $00 -Data_152f8: ; 152f8 (5:52f8) +.list_retreat ; 152f8 (5:52f8) db $00 -Data_152f9: ; 152f9 (5:52f9) - aienergy CHARMANDER, 3, +0 - aienergy CHARMELEON, 5, +0 - aienergy GROWLITHE, 2, +0 - aienergy ARCANINE2, 4, +0 - aienergy SQUIRTLE, 2, +0 - aienergy WARTORTLE, 3, +0 - aienergy SEEL, 3, +0 - aienergy DEWGONG, 4, +0 - aienergy LAPRAS, 3, +0 - aienergy CUBONE, 3, +0 - aienergy MAROWAK1, 3, +0 +.list_energy ; 152f9 (5:52f9) + ai_energy CHARMANDER, 3, +0 + ai_energy CHARMELEON, 5, +0 + ai_energy GROWLITHE, 2, +0 + ai_energy ARCANINE2, 4, +0 + ai_energy SQUIRTLE, 2, +0 + ai_energy WARTORTLE, 3, +0 + ai_energy SEEL, 3, +0 + ai_energy DEWGONG, 4, +0 + ai_energy LAPRAS, 3, +0 + ai_energy CUBONE, 3, +0 + ai_energy MAROWAK1, 3, +0 db $00 -Data_1531b: ; 1531b (5:531b) +.list_prize ; 1531b (5:531b) db LAPRAS db $00 -Func_1531d: ; 1531d (5:531d) - ld hl, wcda8 - ld de, Data_1531b - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_152ea - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_152f1 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_152f1 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_152f9 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 1531d (5:531d) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x1534b -PointerTable_1534b: ; 1534b (5:534b) - dw Func_15357 - dw Func_15357 - dw Func_1535b - dw Func_1536c - dw Func_15370 - dw Func_15374 +AIActionTable_PowerfulRonald: ; 1534b (5:534b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_15357: ; 15357 (5:5357) - call _AIMainTurnLogic +.do_turn ; 15357 (5:5357) + call AIMainTurnLogic ret ; 0x1535b -Func_1535b: ; 1535b (5:535b) +.start_duel ; 1535b (5:535b) call InitAIDuelVars - call Func_153ba + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -1968,22 +1696,22 @@ Func_1535b: ; 1535b (5:535b) ret ; 0x1536c -Func_1536c: ; 1536c (5:536c) +.forced_switch ; 1536c (5:536c) call AIDecideBenchPokemonToSwitchTo ret ; 0x15370 -Func_15370: ; 15370 (5:5370) +.ko_switch ; 15370 (5:5370) call AIDecideBenchPokemonToSwitchTo ret ; 0x15374 -Func_15374: ; 15374 (5:5374) - call _AIPickPrizeCards +.take_prize ; 15374 (5:5374) + call AIPickPrizeCards ret ; 0x15378 -Data_15378: ; 15378 (5:5378) +.list_arena ; 15378 (5:5378) db KANGASKHAN db ELECTABUZZ2 db HITMONCHAN @@ -1996,7 +1724,7 @@ Data_15378: ; 15378 (5:5378) db DODUO db $00 -Data_15383: ; 15383 (5:5383) +.list_bench ; 15383 (5:5383) db KANGASKHAN db HITMONLEE db HITMONCHAN @@ -2009,83 +1737,57 @@ Data_15383: ; 15383 (5:5383) db LICKITUNG db $00 -Data_1538e: ; 1538e (5:538e) - airetreat KANGASKHAN, -1 - airetreat DODUO, -1 - airetreat DODRIO, -1 +.list_retreat ; 1538e (5:538e) + ai_retreat KANGASKHAN, -1 + ai_retreat DODUO, -1 + ai_retreat DODRIO, -1 db $00 -Data_15395: ; 15395 (5:5395) - aienergy ELECTABUZZ2, 2, +1 - aienergy HITMONLEE, 3, +1 - aienergy HITMONCHAN, 3, +1 - aienergy MR_MIME, 2, +0 - aienergy JYNX, 3, +0 - aienergy MEWTWO1, 2, +0 - aienergy DODUO, 3, -1 - aienergy DODRIO, 3, -1 - aienergy LICKITUNG, 2, +0 - aienergy KANGASKHAN, 4, -1 - aienergy TAUROS, 3, +0 +.list_energy ; 15395 (5:5395) + ai_energy ELECTABUZZ2, 2, +1 + ai_energy HITMONLEE, 3, +1 + ai_energy HITMONCHAN, 3, +1 + ai_energy MR_MIME, 2, +0 + ai_energy JYNX, 3, +0 + ai_energy MEWTWO1, 2, +0 + ai_energy DODUO, 3, -1 + ai_energy DODRIO, 3, -1 + ai_energy LICKITUNG, 2, +0 + ai_energy KANGASKHAN, 4, -1 + ai_energy TAUROS, 3, +0 db $00 -Data_153b7: ; 153b7 (5:53b7) +.list_prize ; 153b7 (5:53b7) db GAMBLER db ENERGY_REMOVAL db $00 -Func_153ba: ; 153ba (5:53ba) - ld hl, wcda8 - ld de, Data_153b7 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15378 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_15383 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_15383 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_15395 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 153ba (5:53ba) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x153e8 -PointerTable_153e8: ; 153e8 (5:53e8) - dw Func_153f4 - dw Func_153f4 - dw Func_153f8 - dw Func_15409 - dw Func_1540d - dw Func_15411 +AIActionTable_InvincibleRonald: ; 153e8 (5:53e8) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_153f4: ; 153f4 (5:53f4) - call _AIMainTurnLogic +.do_turn ; 153f4 (5:53f4) + call AIMainTurnLogic ret ; 0x153f8 -Func_153f8: ; 153f8 (5:53f8) +.start_duel ; 153f8 (5:53f8) call InitAIDuelVars - call Func_15441 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -2093,22 +1795,22 @@ Func_153f8: ; 153f8 (5:53f8) ret ; 0x15409 -Func_15409: ; 15409 (5:5409) +.forced_switch ; 15409 (5:5409) call AIDecideBenchPokemonToSwitchTo ret ; 0x1540d -Func_1540d: ; 1540d (5:540d) +.ko_switch ; 1540d (5:540d) call AIDecideBenchPokemonToSwitchTo ret ; 0x15411 -Func_15411: ; 15411 (5:5411) - call _AIPickPrizeCards +.take_prize ; 15411 (5:5411) + call AIPickPrizeCards ret ; 0x15415 -Data_15415: ; 15415 (5:5415) +.list_arena ; 15415 (5:5415) db KANGASKHAN db MAGMAR2 db CHANSEY @@ -2117,7 +1819,7 @@ Data_15415: ; 15415 (5:5415) db GRIMER db $00 -Data_1541c: ; 1541c (5:541c) +.list_bench ; 1541c (5:541c) db GRIMER db SCYTHER db GEODUDE @@ -2126,77 +1828,51 @@ Data_1541c: ; 1541c (5:541c) db KANGASKHAN db $00 -Data_15423: ; 15423 (5:5423) - airetreat GRIMER, -1 +.list_retreat ; 15423 (5:5423) + ai_retreat GRIMER, -1 db $00 -Data_15426: ; 15426 (5:5426) - aienergy GRIMER, 1, -1 - aienergy MUK, 3, -1 - aienergy SCYTHER, 4, +1 - aienergy MAGMAR2, 2, +0 - aienergy GEODUDE, 2, +0 - aienergy GRAVELER, 3, +0 - aienergy CHANSEY, 4, +0 - aienergy KANGASKHAN, 4, -1 +.list_energy ; 15426 (5:5426) + ai_energy GRIMER, 1, -1 + ai_energy MUK, 3, -1 + ai_energy SCYTHER, 4, +1 + ai_energy MAGMAR2, 2, +0 + ai_energy GEODUDE, 2, +0 + ai_energy GRAVELER, 3, +0 + ai_energy CHANSEY, 4, +0 + ai_energy KANGASKHAN, 4, -1 db $00 -Data_1543f: ; 1543f (5:543f) +.list_prize ; 1543f (5:543f) db GAMBLER db $00 -Func_15441: ; 15441 (5:5441) - ld hl, wcda8 - ld de, Data_1543f - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_15415 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_1541c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_1541c - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_15426 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 15441 (5:5441) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_bench + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x1546f -PointerTable_1546f: ; 1546f (5:546f) - dw Func_1547b - dw Func_1547b - dw Func_1547f - dw Func_15490 - dw Func_15494 - dw Func_15498 +AIActionTable_LegendaryRonald: ; 1546f (5:546f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize -Func_1547b: ; 1547b (5:547b) - call Func_15507 +.do_turn ; 1547b (5:547b) + call AIDoTurn_LegendaryRonald ret ; 0x1547f -Func_1547f: ; 1547f (5:547f) +.start_duel ; 1547f (5:547f) call InitAIDuelVars - call Func_154d9 + call .store_list_pointers call SetUpBossStartingHandAndDeck call TrySetUpBossStartingPlayArea ret nc @@ -2204,22 +1880,22 @@ Func_1547f: ; 1547f (5:547f) ret ; 0x15490 -Func_15490: ; 15490 (5:5490) +.forced_switch ; 15490 (5:5490) call AIDecideBenchPokemonToSwitchTo ret ; 0x15494 -Func_15494: ; 15494 (5:5494) +.ko_switch ; 15494 (5:5494) call AIDecideBenchPokemonToSwitchTo ret ; 0x15498 -Func_15498: ; 15498 (5:5498) - call _AIPickPrizeCards +.take_prize ; 15498 (5:5498) + call AIPickPrizeCards ret ; 0x1549c -Data_1549c: ; 1549c (5:549c) +.list_arena ; 1549c (5:549c) db KANGASKHAN db DRATINI db EEVEE @@ -2228,13 +1904,13 @@ Data_1549c: ; 1549c (5:549c) db MOLTRES2 db $00 -Data_154a3: ; 154a3 (5:54a3) +.list_bench ; 154a3 (5:54a3) db KANGASKHAN db DRATINI db EEVEE db $00 -Data_154a7: ; 154a7 (5:54a7) +.list_play_hand ; 154a7 (5:54a7) db MOLTRES2 db ZAPDOS3 db KANGASKHAN @@ -2243,25 +1919,25 @@ Data_154a7: ; 154a7 (5:54a7) db ARTICUNO2 db $00 -Data_154ae: ; 154ae (5:54ae) - airetreat EEVEE, -2 +.list_retreat ; 154ae (5:54ae) + ai_retreat EEVEE, -2 db $00 -Data_154b1: ; 154b1 (5:54b1) - aienergy FLAREON1, 3, +0 - aienergy MOLTRES2, 3, +0 - aienergy VAPOREON1, 3, +0 - aienergy ARTICUNO2, 0, -8 - aienergy JOLTEON1, 4, +0 - aienergy ZAPDOS3, 0, -8 - aienergy KANGASKHAN, 4, -1 - aienergy EEVEE, 3, +0 - aienergy DRATINI, 3, +0 - aienergy DRAGONAIR, 4, +0 - aienergy DRAGONITE1, 3, +0 +.list_energy ; 154b1 (5:54b1) + ai_energy FLAREON1, 3, +0 + ai_energy MOLTRES2, 3, +0 + ai_energy VAPOREON1, 3, +0 + ai_energy ARTICUNO2, 0, -8 + ai_energy JOLTEON1, 4, +0 + ai_energy ZAPDOS3, 0, -8 + ai_energy KANGASKHAN, 4, -1 + ai_energy EEVEE, 3, +0 + ai_energy DRATINI, 3, +0 + ai_energy DRAGONAIR, 4, +0 + ai_energy DRAGONITE1, 3, +0 db $00 -Data_154d3: ; 154d3 (5:54d3) +.list_prize ; 154d3 (5:54d3) db MOLTRES2 db ARTICUNO2 db ZAPDOS3 @@ -2269,85 +1945,71 @@ Data_154d3: ; 154d3 (5:54d3) db GAMBLER db $00 -Func_154d9: ; 154d9 (5:54d9) - ld hl, wcda8 - ld de, Data_154d3 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdaa - ld de, Data_1549c - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdac - ld de, Data_154a3 - ld [hl], e - inc hl - ld [hl], d - - ld hl, wcdae - ld de, Data_154a7 - ld [hl], e - inc hl - ld [hl], d - -; missing wcdb0 - - ld hl, wcdb2 - ld de, Data_154b1 - ld [hl], e - inc hl - ld [hl], d - +.store_list_pointers ; 154d9 (5:54d9) + store_list_pointer wcda8, .list_prize + store_list_pointer wcdaa, .list_arena + store_list_pointer wcdac, .list_bench + store_list_pointer wcdae, .list_play_hand + ; missing store_list_pointer wcdb0, .list_retreat + store_list_pointer wcdb2, .list_energy ret ; 0x15507 -Func_15507: ; 15507 (5:5507) +AIDoTurn_LegendaryRonald: ; 15507 (5:5507) +; initialize variables call InitAITurnVars +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_01 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_02 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards - ld a, $ef + +; check if AI can play Moltres2 +; from hand and if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable - cp $06 - jr nc, .asm_15540 - ld a, $ba + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres_1 ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable - cp $33 - jr nc, .asm_15540 - ld a, $27 + cp DECK_SIZE - 9 + jr nc, .skip_moltres_1 ; skip if cards in deck <= 9 + ld a, MUK call CountPokemonIDInBothPlayAreas - jr c, .asm_15540 - ld a, $40 + jr c, .skip_moltres_1 ; skip if Muk in play + ld a, MOLTRES2 call LookForCardIDInHandList_Bank5 - jr nc, .asm_15540 + jr nc, .skip_moltres_1 ; skip if no Moltres2 in hand ldh [hTemp_ffa0], a ld a, OPPACTION_PLAY_BASIC_PKMN bank1call AIMakeDecision -.asm_15540 + +.skip_moltres_1 +; play Pokemon from hand call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended +; process Trainer cards ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards +; play Energy card if possible ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_1555f + jr nz, .skip_attach_energy_1 call AIProcessAndTryToPlayEnergy -.asm_1555f +.skip_attach_energy_1 +; try playing Pokemon cards from hand again call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_15 +; if used Professor Oak, process new hand +; if not, then proceed to attack. call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK @@ -2358,43 +2020,49 @@ Func_15507: ; 15507 (5:5507) call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_04 call AIProcessHandTrainerCards - ld a, $ef + +; check if AI can play Moltres2 +; from hand and if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable - cp $06 - jr nc, .asm_155a5 - ld a, $ba + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres_2 ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable - cp $33 - jr nc, .asm_155a5 - ld a, $27 + cp DECK_SIZE - 9 + jr nc, .skip_moltres_2 ; skip if cards in deck <= 9 + ld a, MUK call CountPokemonIDInBothPlayAreas - jr c, .asm_155a5 - ld a, $40 + jr c, .skip_moltres_2 ; skip if Muk in play + ld a, MOLTRES2 call LookForCardIDInHandList_Bank5 - jr nc, .asm_155a5 + jr nc, .skip_moltres_2 ; skip if no Moltres2 in hand ldh [hTemp_ffa0], a ld a, OPPACTION_PLAY_BASIC_PKMN bank1call AIMakeDecision -.asm_155a5 + +.skip_moltres_2 call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended ld a, AI_TRAINER_CARD_PHASE_05 call AIProcessHandTrainerCards ld a, AI_TRAINER_CARD_PHASE_07 call AIProcessHandTrainerCards - call Func_14786 + call AIProcessRetreat ld a, AI_TRAINER_CARD_PHASE_10 call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a - jr nz, .asm_155c4 + jr nz, .skip_attach_energy_2 call AIProcessAndTryToPlayEnergy -.asm_155c4 +.skip_attach_energy_2 call AIDecidePlayPokemonCard - ret c + ret c ; return if turn ended .try_attack +; attack if possible, if not, +; finish turn without attacking. call AIProcessAndTryToUseAttack - ret c + ret c ; return if turn ended ld a, OPPACTION_FINISH_NO_ATTACK bank1call AIMakeDecision ret diff --git a/src/wram.asm b/src/wram.asm index 5614b54..e4bf0b2 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1290,7 +1290,9 @@ wAIOpponentPrizeCount:: ; cdd3 wTempCardIDToLook:: ; cdd4 ds $1 -wcdd5:: ; cdd5 +; when AI decides which Bench Pokemon to switch to +; it stores it Play Area location here. +wAIPlayAreaCardToSwitch:: ; cdd5 ds $1 ; the index of attack chosen by AI @@ -1391,7 +1393,10 @@ wce01:: ; ce01 wAIMoveIsNonDamaging:: ; ce02 ds $1 -wce03:: ; ce03 +; whether AI already retreated this turn or not. +; - $0 has not retreated; +; - $1 has retreated. +wAIRetreatedThisTurn:: ; ce03 ds $1 ; used by AI to store information of Venusaur2 -- cgit v1.2.3 From 81191863b354193fcefbd6cd2919b362c390a5bd Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 7 May 2020 21:32:45 +0100 Subject: Document AI WRAM pointers --- src/engine/bank05.asm | 56 +++++++-------- src/engine/deck_ai.asm | 192 ++++++++++++++++++++++++------------------------- src/wram.asm | 49 +++++++++---- 3 files changed, 158 insertions(+), 139 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 8943187..5417ecc 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -2177,7 +2177,7 @@ RemoveCardIDInList: ; 157f3 (5:57f3) ; 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, wcdaa + ld de, wAICardListArenaPriority ld a, d or a jr z, .set_carry ; return if null @@ -2185,14 +2185,14 @@ TrySetUpBossStartingPlayArea: ; 1581b (5:581b) ; pick Arena card call CreateHandCardList ld hl, wDuelTempList - ld de, wcdaa + 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, wcdac + ld de, wAICardListBenchPriority call .PlayPokemonCardInOrder jr c, .done cp 3 @@ -2960,18 +2960,18 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) cp MYSTERIOUS_FOSSIL jr z, .lower_score_2 cp CLEFAIRY_DOLL - jr nz, .asm_15d0c + jr nz, .ai_score_bonus .lower_score_2 ld a, 10 call SubFromAIScore -.asm_15d0c +.ai_score_bonus ld b, a - ld a, [wcdb0 + 1] + ld a, [wAICardListRetreatBonus + 1] or a jr z, .store_score ld h, a - ld a, [wcdb0] + ld a, [wAICardListRetreatBonus] ld l, a .loop_ids @@ -2982,11 +2982,11 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) jr nz, .next_id ld a, [hl] cp $80 - jr c, .asm_15d2b + jr c, .subtract_score sub $80 call AddToAIScore jr .next_id -.asm_15d2b +.subtract_score ld c, a ld a, $80 sub c @@ -4085,17 +4085,17 @@ LookForEnergyNeededForMoveInHand: ; 16311 (5:6311) ; 0x1633f ; goes through $00 terminated list pointed -; by wcdae and compares it to each card in hand. +; 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, [wcdae+1] + ld a, [wAICardListPlayFromHandPriority+1] or a ret z ; return if list is empty ; start going down the ID list ld d, a - ld a, [wcdae] + ld a, [wAICardListPlayFromHandPriority] ld e, a ld c, 0 .loop_list_id @@ -4605,7 +4605,7 @@ AIProcessEnergyCards: ; 164fc (5:64fc) jr .check_bench .check_defending_can_ko call CheckIfDefendingPokemonCanKnockOut - jr nc, .asm_165e1 + jr nc, .ai_score_bonus ld a, 10 call SubFromAIScore @@ -4616,10 +4616,10 @@ AIProcessEnergyCards: ; 164fc (5:64fc) ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable dec a - jr nz, .asm_165e1 + jr nz, .ai_score_bonus ld a, 6 call AddToAIScore - jr .asm_165e1 + jr .ai_score_bonus ; lower AI score by 3 - (bench HP)/10 ; if bench HP < 30 @@ -4628,20 +4628,20 @@ AIProcessEnergyCards: ; 164fc (5:64fc) call GetTurnDuelistVariable call CalculateByteTensDigit cp 3 - jr nc, .asm_165e1 + jr nc, .ai_score_bonus ; hp < 30 ld b, a ld a, 3 sub b call SubFromAIScore -; check list in wcdb2 -.asm_165e1 - ld a, [wcdb3] +; check list in wAICardListEnergyBonus +.ai_score_bonus + ld a, [wAICardListEnergyBonus + 1] or a - jr z, .check_boss_deck + jr z, .check_boss_deck ; is null ld h, a - ld a, [wcdb2] + ld a, [wAICardListEnergyBonus] ld l, a push hl @@ -7137,12 +7137,12 @@ SetUpBossStartingHandAndDeck: ; 172af (5:72af) ld a, DUELVARS_HAND call GetTurnDuelistVariable ld b, STARTING_HAND_SIZE -.asm_172b6 +.loop_hand ld a, [hl] call RemoveCardFromHand call ReturnCardToDeck dec b - jr nz, .asm_172b6 + jr nz, .loop_hand jr .count_energy_basic .shuffle_deck @@ -7197,7 +7197,7 @@ SetUpBossStartingHandAndDeck: ; 172af (5:72af) jr c, .shuffle_deck ; now check the following 6 cards (prize cards). -; re-shuffle deck if any of these cards is listed in wcda8. +; re-shuffle deck if any of these cards is listed in wAICardListAvoidPrize. ld b, 6 .check_card_ids ld a, [hli] @@ -7263,20 +7263,20 @@ SetUpBossStartingHandAndDeck: ; 172af (5:72af) ; 0x17366 ; expectation: return carry if card ID corresponding -; to the input deck index is listed in wcda8; +; to the input deck index is listed in wAICardListAvoidPrize; ; reality: always returns no carry because when checking terminating -; byte in wcda8 ($00), it wrongfully uses 'cp a' instead of 'or a', +; byte in wAICardListAvoidPrize ($00), it wrongfully uses 'cp a' instead of 'or a', ; so it always ends up returning in the first item in list. ; input: ; - a = deck index of card to check .CheckIfIDIsInList ; 17366 (5:7366) ld b, a - ld a, [wcda8 + 1] + ld a, [wAICardListAvoidPrize + 1] or a ret z ; null push hl ld h, a - ld a, [wcda8] + ld a, [wAICardListAvoidPrize] ld l, a ld a, b diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index 2a78848..dfa6820 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -262,12 +262,12 @@ AIActionTable_LegendaryMoltres: ; 149e8 (05:49e8) db $00 .store_list_pointers ; 14a4a (5:4a4a) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_play_hand - store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand + store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14a81 @@ -438,12 +438,12 @@ AIActionTable_LegendaryZapdos: ; 14b0f (05:4b0f) db $00 .store_list_pointers ; 14b6c (5:4b6c) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14b9a @@ -597,12 +597,12 @@ AIActionTable_LegendaryArticuno: ; 14c0b (5:4c0b) db $00 .store_list_pointers ; 14c63 (5:4c63) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14c91 @@ -818,12 +818,12 @@ AIActionTable_LegendaryDragonite: ; 14d60 (05:4d60) db $00 .store_list_pointers ; 14dc1 (5:4dc1) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14def @@ -987,12 +987,12 @@ AIActionTable_FirstStrike: ; 14e89 (5:4e89) db $00 .store_list_pointers ; 14ee0 (5:4ee0) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14f0e @@ -1068,12 +1068,12 @@ AIActionTable_RockCrusher: ; 14f0e (5:4f0e) db $00 .store_list_pointers ; 14f61 (5:4f61) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x14f8f @@ -1154,12 +1154,12 @@ AIActionTable_GoGoRainDance: ; 14f8f (5:4f8f) db $00 .store_list_pointers ; 14feb (5:4feb) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x15019 @@ -1236,12 +1236,12 @@ AIActionTable_ZappingSelfdestruct: ; 15019 (5:5019) db $00 .store_list_pointers ; 1506d (5:506d) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x1509b @@ -1318,12 +1318,12 @@ AIActionTable_FlowerPower: ; 1509b (5:509b) db $00 .store_list_pointers ; 150f4 (5:50f4) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x15122 @@ -1406,12 +1406,12 @@ AIActionTable_StrangePsyshock: ; 15122 (5:5122) db $00 .store_list_pointers ; 1517f (5:517f) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x151ad @@ -1490,12 +1490,12 @@ AIActionTable_WondersOfScience: ; 151ad (5:51ad) db $00 .store_list_pointers ; 15204 (5:5204) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x15232 @@ -1577,12 +1577,12 @@ AIActionTable_FireCharge: ; 15232 (5:5232) db $00 .store_list_pointers ; 1528f (5:528f) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x152bd @@ -1664,12 +1664,12 @@ AIActionTable_ImRonald: ; 152bd (5:52bd) db $00 .store_list_pointers ; 1531d (5:531d) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x1534b @@ -1763,12 +1763,12 @@ AIActionTable_PowerfulRonald: ; 1534b (5:534b) db $00 .store_list_pointers ; 153ba (5:53ba) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x153e8 @@ -1848,12 +1848,12 @@ AIActionTable_InvincibleRonald: ; 153e8 (5:53e8) db $00 .store_list_pointers ; 15441 (5:5441) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_bench - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x1546f @@ -1946,12 +1946,12 @@ AIActionTable_LegendaryRonald: ; 1546f (5:546f) db $00 .store_list_pointers ; 154d9 (5:54d9) - store_list_pointer wcda8, .list_prize - store_list_pointer wcdaa, .list_arena - store_list_pointer wcdac, .list_bench - store_list_pointer wcdae, .list_play_hand - ; missing store_list_pointer wcdb0, .list_retreat - store_list_pointer wcdb2, .list_energy + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy ret ; 0x15507 diff --git a/src/wram.asm b/src/wram.asm index e4bf0b2..71830dd 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1184,9 +1184,9 @@ wcda5:: ; cda5 ; this is used by AI in order to determine whether ; it should use Pokedex Trainer card. -; duel starts at 5 and counts up by one every turn. +; starts with 5 when Duel starts and counts up by 1 every turn. ; only when it's higher than 5 is AI allowed to use Pokedex, -; in which case it set the counter to 0. +; in which case it sets the counter to 0. ; this stops the AI from using Pokedex right after using another one ; while still drawing cards that were ordered. wAIPokedexCounter:: ; cda6 @@ -1201,28 +1201,47 @@ wAIPokedexCounter:: ; cda6 wAIBarrierFlagCounter:: ; cda7 ds $1 -wcda8:: ; cda8 +; pointer to $00-terminated list of card IDs +; to avoid being placed as prize cards +; when setting up AI duelist's cards at duel start. +; (see SetUpBossStartingHandAndDeck) +wAICardListAvoidPrize:: ; cda8 ds $2 -wcdaa:: ; cdaa +; pointer to $00-terminated list of card IDs +; sorted by priority of AI placing in the Arena +; at duel start (see TrySetUpBossStartingPlayArea) +wAICardListArenaPriority:: ; cdaa ds $2 -wcdac:: ; cdac +; pointer to $00-terminated list of card IDs +; sorted by priority of AI placing in the Bench +; at duel start (see TrySetUpBossStartingPlayArea) +wAICardListBenchPriority:: ; cdac ds $2 -; pointer to a list of card IDs for sorting AI hand -wcdae:: ; cdae +; pointer to $00-terminated list of card IDs +; sorted by priority of AI playing it from Hand +; to the Bench (see AIDecidePlayPokemonCard) +wAICardListPlayFromHandPriority:: ; cdae ds $2 -wcdb0:: ; cdb0 +; pointer to $00-terminated list of card IDs and AI scores. +; these are for giving certain cards more or less +; likelihood of being picked by AI to switch to. +; (see AIDecideBenchPokemonToSwitchTo) +wAICardListRetreatBonus:: ; cdb0 ds $2 -; these seem to hold pointer to some kind of -; card ID list with attached energy and score -wcdb2:: ; cdb2 - ds $1 -wcdb3:: ; cdb3 - ds $1 +; pointer to $00-terminated list of card IDs, +; number of energy cards and AI score. +; these are for giving certain cards more or less +; likelihood of being picked for AI to attach energy. +; also has the maximum number of energy cards that +; the AI is willing to provide for it. +; (see AIProcessEnergyCards) +wAICardListEnergyBonus:: ; cdb2 + ds $2 wcdb4:: ; cdb4 ds $1 @@ -1266,7 +1285,7 @@ wFirstAttackAIScore:: ; cdbf ENDU - ds $0a + ds $a ; information about the defending Pokémon and ; the prize card count on both sides for AI: -- cgit v1.2.3 From bf4cc80aa71c401f489cee3027fba09e975a64cd Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 8 May 2020 01:09:47 +0100 Subject: Document Deck AI data structures --- src/engine/deck_ai.asm | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src') diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index dfa6820..15a1025 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -30,6 +30,36 @@ store_list_pointer: MACRO ld [hl], d ENDM +; deck AIs are specialized to work on a given deck ID. +; they decide what happens during a turn, what Pokemon cards +; to pick during the start of the duel, etc. +; each of these have a pointer table with the following structure: +; dw .do_turn : never called; +; +; dw .do_turn : called to handle the main turn logic, from the beginning +; of the turn up to the attack (or lack thereof); +; +; dw .start_duel : called at the start of the duel to initialize some +; variables and optionally set up CPU hand and deck; +; +; dw .forced_switch : logic to determine what Pokemon to pick when there's +; an effect that forces AI to switch to Bench card; +; +; dw .ko_switch : logic for picking which card to use after a KO; +; +; dw .take_prize : logic to decide which prize card to pick. + +; optionally, decks can also declare card lists that will add +; more specialized logic during various generic AI routines, +; and read during the .start_duel routines. +; the pointers to these lists are stored in memory: +; wAICardListAvoidPrize : list of cards to avoid being placed as prize; +; wAICardListArenaPriority : priority list of Arena card at duel start; +; wAICardListBenchPriority : priority list of Bench cards at duel start; +; wAICardListPlayFromHandPriority : priority list of cards to play from hand; +; wAICardListRetreatBonus : scores given to certain cards for retreat; +; wAICardListEnergyBonus : max number of energy cards and card scores. + AIActionTable_GeneralNoRetreat: ; 148dc (5:48dc) dw .do_turn ; unused dw .do_turn -- cgit v1.2.3 From 1a1cff966e82ada49585bbc721247c7c8c8cf3a1 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 8 May 2020 09:28:28 +0100 Subject: Add corrections --- src/engine/bank08.asm | 86 ++++++++++++++++++++--------------------- src/engine/deck_ai.asm | 6 +-- src/engine/effect_functions.asm | 2 +- 3 files changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index df8d7c5..1bb06a3 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6255,7 +6255,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) jr z, .check_retreat cp AI_ENERGY_TRANS_TO_BENCH - jp z, .TransferEnergyToBench + jp z, AIEnergyTransTransferEnergyToBench ; AI_ENERGY_TRANS_ATTACK call .CheckEnoughGrassEnergyCardsForAttack @@ -6277,7 +6277,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) call GetTurnDuelistVariable dec a ld b, a -.loop_play_area_1 +.loop_play_area ld a, DUELVARS_ARENA_CARD add b call GetTurnDuelistVariable @@ -6285,17 +6285,17 @@ HandleAIEnergyTrans: ; 2219b (8:619b) call GetCardIDFromDeckIndex ld a, e cp VENUSAUR2 - jr z, .use_pkmn_power_1 + jr z, .use_pkmn_power ld a, b or a ret z ; return when finished Play Area loop dec b - jr .loop_play_area_1 + jr .loop_play_area ; use Energy Trans Pkmn Power -.use_pkmn_power_1 +.use_pkmn_power ld a, b ldh [hTemp_ffa0], a ld a, OPPACTION_USE_PKMN_POWER @@ -6311,13 +6311,13 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; look for Grass energy cards that ; are currently attached to a Bench card. ld e, 0 -.loop_deck_locations_1 +.loop_deck_locations ld a, DUELVARS_CARD_LOCATIONS add e call GetTurnDuelistVariable and %00011111 cp CARD_LOCATION_BENCH_1 - jr c, .next_card_1 + jr c, .next_card and %00001111 ldh [hTempPlayAreaLocation_ffa1], a @@ -6328,7 +6328,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ld a, e pop de cp GRASS_ENERGY - jr nz, .next_card_1 + jr nz, .next_card ; store the deck index of energy card ld a, e @@ -6336,39 +6336,39 @@ HandleAIEnergyTrans: ; 2219b (8:619b) push de ld d, 30 -.small_delay_loop_1 +.small_delay_loop call DoFrame dec d - jr nz, .small_delay_loop_1 + jr nz, .small_delay_loop ld a, OPPACTION_6B15 bank1call AIMakeDecision pop de dec d - jr z, .done_transfer_1 + jr z, .done_transfer -.next_card_1 +.next_card inc e ld a, DECK_SIZE cp e - jr nz, .loop_deck_locations_1 + jr nz, .loop_deck_locations ; transfer is done, perform delay ; and return to main scene. -.done_transfer_1 +.done_transfer ld d, 60 -.big_delay_loop_1 +.big_delay_loop call DoFrame dec d - jr nz, .big_delay_loop_1 + jr nz, .big_delay_loop ld a, OPPACTION_DUEL_MAIN_SCENE bank1call AIMakeDecision ret ; 0x22246 -; checks if the Arena card has not enough energy for second attack, -; and if not, return carry if transferring Grass energy from Bench -; would be enough to use it and outputs number of energy cards needed in a. +; checks if the Arena card needs energy for its second attack, +; and if it does, return carry if transferring Grass energy from Bench +; would be enough to use it. Outputs number of energy cards needed in a. .CheckEnoughGrassEnergyCardsForAttack ; 22246 (8:6246) ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable @@ -6494,7 +6494,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; AI logic to determine whether to use Energy Trans Pkmn Power ; to transfer energy cards attached from the Arena Pokemon to ; some card in the Bench. -.TransferEnergyToBench ; 222ca (8:62ca) +AIEnergyTransTransferEnergyToBench: ; 222ca (8:62ca) xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfDefendingPokemonCanKnockOut @@ -6523,7 +6523,7 @@ HandleAIEnergyTrans: ; 2219b (8:619b) call GetTurnDuelistVariable dec a ld b, a -.loop_play_area_2 +.loop_play_area ld a, DUELVARS_ARENA_CARD add b call GetTurnDuelistVariable @@ -6532,17 +6532,17 @@ HandleAIEnergyTrans: ; 2219b (8:619b) call GetCardIDFromDeckIndex ld a, e cp VENUSAUR2 - jr z, .use_pkmn_power_2 + jr z, .use_pkmn_power ld a, b or a ret z ; return when Play Area loop is ended dec b - jr .loop_play_area_2 + jr .loop_play_area ; use Energy Trans Pkmn Power -.use_pkmn_power_2 +.use_pkmn_power ld a, b ldh [hTemp_ffa0], a ld [wAIVenusaur2PlayAreaLocation], a @@ -6563,17 +6563,17 @@ HandleAIEnergyTrans: ; 2219b (8:619b) call GetPlayAreaCardAttachedEnergies ld a, [wAttachedEnergies + GRASS] or a - jr z, .done_transfer_2 + jr z, .done_transfer ; look for Grass energy cards that ; are currently attached to Arena card. ld e, 0 -.loop_deck_locations_2 +.loop_deck_locations ld a, DUELVARS_CARD_LOCATIONS add e call GetTurnDuelistVariable cp CARD_LOCATION_ARENA - jr nz, .next_card_2 + jr nz, .next_card ld a, e push de @@ -6581,32 +6581,32 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ld a, e pop de cp GRASS_ENERGY - jr nz, .next_card_2 + jr nz, .next_card ; store the deck index of energy card ld a, e ldh [hAIEnergyTransEnergyCard], a jr .transfer -.next_card_2 +.next_card inc e ld a, DECK_SIZE cp e - jr nz, .loop_deck_locations_2 - jr .done_transfer_2 + jr nz, .loop_deck_locations + jr .done_transfer .transfer ; get the Bench card location to transfer Grass energy card to. farcall AIProcessButDontPlayEnergy_SkipEvolutionAndArena - jr nc, .done_transfer_2 + jr nc, .done_transfer ldh a, [hTempPlayAreaLocation_ff9d] ldh [hAIEnergyTransPlayAreaLocation], a ld d, 30 -.small_delay_loop_2 +.small_delay_loop call DoFrame dec d - jr nz, .small_delay_loop_2 + jr nz, .small_delay_loop ld a, [wAIVenusaur2DeckIndex] ldh [hTempCardIndex_ff9f], a @@ -6619,12 +6619,12 @@ HandleAIEnergyTrans: ; 2219b (8:619b) ; transfer is done, perform delay ; and return to main scene. -.done_transfer_2 +.done_transfer ld d, 60 -.big_delay_loop_2 +.big_delay_loop call DoFrame dec d - jr nz, .big_delay_loop_2 + jr nz, .big_delay_loop ld a, OPPACTION_DUEL_MAIN_SCENE bank1call AIMakeDecision ret @@ -6934,7 +6934,7 @@ HandleAIPeek: ; 224e6 (8:64e6) cp 3 ret nc ; return 47 out of 50 times -; check what to use Peek on at random +; choose what to use Peek on at random ld a, 3 call Random or a @@ -7242,12 +7242,12 @@ HandleAICowardice: ; 2262d (8:662d) ldh a, [hTemp_ffa0] or a jr nz, .is_benched + + ; this part is buggy if AIDecideBenchPokemonToSwitchTo returns carry + ; but since this was already checked beforehand, this never happens. + ; so jr c, .asm_22678 can be safely removed. farcall AIDecideBenchPokemonToSwitchTo -; in case this routine is called with no Bench Pokemon, -; this introduces a bug. -; since it's only called in HandleAICowardice in case -; there's more than 1 Pokemon in Play Area, this never sets carry. - jr c, .asm_22678 + jr c, .asm_22678 ; bug, this jumps in the middle of damage checking jr .use_cowardice .is_benched ld a, $ff diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm index 15a1025..0bdbd5a 100644 --- a/src/engine/deck_ai.asm +++ b/src/engine/deck_ai.asm @@ -996,9 +996,9 @@ AIActionTable_FirstStrike: ; 14e89 (5:4e89) db $00 .list_retreat ; 14ec0 (5:1ec0) - ai_retreat MACHOP, - 1 - ai_retreat MACHOKE, - 1 - ai_retreat MANKEY, - 2 + ai_retreat MACHOP, -1 + ai_retreat MACHOKE, -1 + ai_retreat MANKEY, -2 db $00 .list_energy ; 14ec7 (5:1ec7) diff --git a/src/engine/effect_functions.asm b/src/engine/effect_functions.asm index dbda9ad..762e82d 100644 --- a/src/engine/effect_functions.asm +++ b/src/engine/effect_functions.asm @@ -763,4 +763,4 @@ Func_2cbfb: ; 2cbfb (b:4bfb) ret ; 0x2cc0a - INCROM $2cc0a, $30000 \ No newline at end of file + INCROM $2cc0a, $30000 -- cgit v1.2.3 From d20d490df325c1671357acd894ec14ed36599797 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Sat, 9 May 2020 11:47:04 +0100 Subject: Give each deck AI its own file --- src/engine/bank05.asm | 419 +--- src/engine/deck_ai.asm | 2099 --------------------- src/engine/deck_ai/deck_ai.asm | 81 + src/engine/deck_ai/decks/fire_charge.asm | 86 + src/engine/deck_ai/decks/first_strike.asm | 82 + src/engine/deck_ai/decks/flower_power.asm | 81 + src/engine/deck_ai/decks/general.asm | 196 ++ src/engine/deck_ai/decks/general_no_retreat.asm | 146 ++ src/engine/deck_ai/decks/go_go_rain_dance.asm | 85 + src/engine/deck_ai/decks/im_ronald.asm | 86 + src/engine/deck_ai/decks/invincible_ronald.asm | 84 + src/engine/deck_ai/decks/legendary_articuno.asm | 217 +++ src/engine/deck_ai/decks/legendary_dragonite.asm | 173 ++ src/engine/deck_ai/decks/legendary_moltres.asm | 183 ++ src/engine/deck_ai/decks/legendary_ronald.asm | 210 +++ src/engine/deck_ai/decks/legendary_zapdos.asm | 160 ++ src/engine/deck_ai/decks/powerful_ronald.asm | 98 + src/engine/deck_ai/decks/rock_crusher.asm | 80 + src/engine/deck_ai/decks/sams_practice.asm | 222 +++ src/engine/deck_ai/decks/strange_psyshock.asm | 87 + src/engine/deck_ai/decks/wonders_of_science.asm | 83 + src/engine/deck_ai/decks/zapping_selfdestruct.asm | 81 + 22 files changed, 2522 insertions(+), 2517 deletions(-) delete mode 100644 src/engine/deck_ai.asm create mode 100644 src/engine/deck_ai/deck_ai.asm create mode 100644 src/engine/deck_ai/decks/fire_charge.asm create mode 100644 src/engine/deck_ai/decks/first_strike.asm create mode 100644 src/engine/deck_ai/decks/flower_power.asm create mode 100644 src/engine/deck_ai/decks/general.asm create mode 100644 src/engine/deck_ai/decks/general_no_retreat.asm create mode 100644 src/engine/deck_ai/decks/go_go_rain_dance.asm create mode 100644 src/engine/deck_ai/decks/im_ronald.asm create mode 100644 src/engine/deck_ai/decks/invincible_ronald.asm create mode 100644 src/engine/deck_ai/decks/legendary_articuno.asm create mode 100644 src/engine/deck_ai/decks/legendary_dragonite.asm create mode 100644 src/engine/deck_ai/decks/legendary_moltres.asm create mode 100644 src/engine/deck_ai/decks/legendary_ronald.asm create mode 100644 src/engine/deck_ai/decks/legendary_zapdos.asm create mode 100644 src/engine/deck_ai/decks/powerful_ronald.asm create mode 100644 src/engine/deck_ai/decks/rock_crusher.asm create mode 100644 src/engine/deck_ai/decks/sams_practice.asm create mode 100644 src/engine/deck_ai/decks/strange_psyshock.asm create mode 100644 src/engine/deck_ai/decks/wonders_of_science.asm create mode 100644 src/engine/deck_ai/decks/zapping_selfdestruct.asm (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 5417ecc..762d5c8 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1213,424 +1213,7 @@ AIProcessHandTrainerCards: ; 14663 (5:4663) farcall _AIProcessHandTrainerCards ret -AIActionTable_GeneralDecks: ; 14668 (05:4668) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14674 (5:4674) - call AIMainTurnLogic - ret - -.start_duel ; 14678 (5:4678) - call InitAIDuelVars - call AIPlayInitialBasicCards - ret - -.forced_switch ; 1467f (5:467f) - call AIDecideBenchPokemonToSwitchTo - ret - -.ko_switch ; 14683 (5:4683) - call AIDecideBenchPokemonToSwitchTo - ret - -.take_prize: ; 14687 (5:4687) - call AIPickPrizeCards - ret - -; handle AI routines for a whole turn -AIMainTurnLogic: ; 1468b (5:468b) -; initialize variables - call InitAITurnVars - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; handle Pkmn Powers - farcall HandleAIGoGoRainDanceEnergy - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAICowardice -; process Trainer cards -; phase 2 through 4. - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_03 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended -; process Trainer cards -; phase 5 through 12. - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_06 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_08 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_12 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_1 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_1 -; play Pokemon from hand again - call AIDecidePlayPokemonCard -; handle Pkmn Powers again - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAIGoGoRainDanceEnergy - ld a, AI_ENERGY_TRANS_ATTACK - farcall HandleAIEnergyTrans -; process Trainer cards phases 13 and 15 - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_15 - call AIProcessHandTrainerCards -; if used Professor Oak, process new hand -; if not, then proceed to attack. - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK - jr z, .try_attack - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_03 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_06 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_08 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_12 - call AIProcessHandTrainerCards - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_2 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_2 - call AIDecidePlayPokemonCard - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAIGoGoRainDanceEnergy - ld a, AI_ENERGY_TRANS_ATTACK - farcall HandleAIEnergyTrans - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - ; skip AI_TRAINER_CARD_PHASE_15 -.try_attack - ld a, AI_ENERGY_TRANS_TO_BENCH - farcall HandleAIEnergyTrans -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if AI attacked - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14786 - -; handles AI retreating logic -AIProcessRetreat: ; 14786 (5:4786) - ld a, [wAIRetreatedThisTurn] - or a - ret nz ; return, already retreated this turn - - call AIDecideWhetherToRetreat - ret nc ; return if not retreating - - call AIDecideBenchPokemonToSwitchTo - ret c ; return if no Bench Pokemon - -; store Play Area to retreat to and -; set wAIRetreatedThisTurn to true - ld [wAIPlayAreaCardToSwitch], a - ld a, $01 - ld [wAIRetreatedThisTurn], a - -; if AI can use Switch from hand, use it instead... - ld a, AI_TRAINER_CARD_PHASE_09 - call AIProcessHandTrainerCards - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_SWITCH - jr nz, .used_switch -; ... else try retreating normally. - ld a, [wAIPlayAreaCardToSwitch] - call AITryToRetreat - ret - -.used_switch -; if AI used switch, unset its AI flag - ld a, [wPreviousAIFlags] - and ~AI_FLAG_USED_SWITCH ; clear Switch flag - ld [wPreviousAIFlags], a - -; bug, this doesn't make sense being here, since at this point -; Switch Trainer card was already used to retreat the Pokemon. -; what the routine will do is just transfer Energy cards to -; the Arena Pokemon for the purpose of retreating, and -; then not actually retreat, resulting in unusual behaviour. -; this would only work placed right after the AI checks whether -; they have Switch card in hand to use and doesn't have one. -; (and probably that was the original intention.) - ld a, AI_ENERGY_TRANS_RETREAT ; retreat - farcall HandleAIEnergyTrans - ret -; 0x147bd - -AIActionTable_SamPractice: ; 147bd (05:47bd) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 147c9 (5:47c9) - call IsAIPracticeScriptedTurn - jr nc, .scripted_1 -; not scripted, use AI main turn logic - call AIMainTurnLogic - ret -.scripted_1 ; use scripted actions instead - call AIPerformSciptedTurn - ret -; 0x147d6 - -.start_duel ; 147d6 (5:47d6) - call Func_14801 - ret -; 0x147da - -.forced_switch ; 147da (5:47da) - call IsAIPracticeScriptedTurn - jr nc, .scripted_2 - call AIDecideBenchPokemonToSwitchTo - ret -.scripted_2 - call PickRandomBenchPokemon - ret -; 0x147e7 - -.ko_switch: ; 147e7 (5:47e7) - call IsAIPracticeScriptedTurn - jr nc, .scripted_3 - call AIDecideBenchPokemonToSwitchTo - ret -.scripted_3 - call GetPlayAreaLocationOfRaticateOrRattata - ret -; 0x147f4 - -.take_prize: ; 147f4 (5:47f4) - call AIPickPrizeCards - ret -; 0x147f8 - -; returns carry if number of turns -; the AI has taken >= 7. -; used to know whether AI Sam is still -; doing scripted turns. -IsAIPracticeScriptedTurn: ; 147f8 (5:47f8) - ld a, [wDuelTurns] - srl a - cp 7 - ccf - ret -; 0x14801 - -; places one Machop from the hand to the Play Area -; and sets the number of prizes to 2. -Func_14801: ; 14801 (5:4801) - call CreateHandCardList - ld hl, wDuelTempList -.loop_hand - ld a, [hli] - ldh [hTempCardIndex_ff98], a - cp $ff - ret z - call LoadCardDataToBuffer1_FromDeckIndex - cp MACHOP - jr nz, .loop_hand - ldh a, [hTempCardIndex_ff98] - call PutHandPokemonCardInPlayArea - ld a, 2 - ld [wDuelInitialPrizes], a - ret -; 0x1481f - -; outputs in a Play Area location of Raticate or Rattata -; in the Bench. If neither is found, just output PLAY_AREA_BENCH_1. -GetPlayAreaLocationOfRaticateOrRattata: ; 1481f (5:481f) - ld a, RATICATE - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - cp $ff - jr nz, .found - ld a, RATTATA - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - cp $ff - jr nz, .found - ld a, PLAY_AREA_BENCH_1 -.found - ldh [hTempPlayAreaLocation_ff9d], a - ret -; 0x1483a - -; has AI execute some scripted actions depending on Duel turn. -AIPerformSciptedTurn: ; 1483a (5:483a) - ld a, [wDuelTurns] - srl a - ld hl, .scripted_actions_list - call JumpToFunctionInTable - -; always attack with Arena card's first attack. -; if it's unusable end turn without attacking. - xor a - ldh [hTempPlayAreaLocation_ff9d], a - ld [wSelectedAttack], a - call CheckIfSelectedMoveIsUnusable - jr c, .unusable - call AITryUseAttack - ret - -.unusable - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x1485a - -.scripted_actions_list ; 1485a (05:485a) - dw .turn_1 - dw .turn_2 - dw .turn_3 - dw .turn_4 - dw .turn_5 - dw .turn_6 - dw .turn_7 -; 0x14868 - -.turn_1 ; 14868 (5:4868) - ld d, MACHOP - ld e, FIGHTING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x14870 - -.turn_2 ; 14870 (5:4870) - ld a, RATTATA - call LookForCardIDInHandList_Bank5 - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - ld d, RATTATA - ld e, FIGHTING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x14884 - -.turn_3 ; 14884 (5:4884) - ld a, RATTATA - ld b, PLAY_AREA_ARENA - call LookForCardIDInPlayArea_Bank5 - ldh [hTempPlayAreaLocation_ffa1], a - ld a, RATICATE - call LookForCardIDInHandList_Bank5 - ldh [hTemp_ffa0], a - ld a, OPPACTION_EVOLVE_PKMN - bank1call AIMakeDecision - ld d, RATICATE - ld e, LIGHTNING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x148a1 - -.turn_4 ; 148a1 (5:48a1) - ld d, RATICATE - ld e, LIGHTNING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x148a9 - -.turn_5 ; 148a9 (5:48a9) - ld a, MACHOP - call LookForCardIDInHandList_Bank5 - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - ld d, MACHOP - ld e, FIGHTING_ENERGY - call AIAttachEnergyInHandToCardInBench - -; this is a bug, it's attempting to compare a card ID with a deck index. -; the intention was to change the card to switch to depending on whether -; the first Machop was KO'd at this point in the Duel or not. -; because of the buggy comparison, this will always jump the -; 'inc a' instruction and switch to PLAY_AREA_BENCH_1. -; in a normal Practice Duel following Dr. Mason's instructions, -; this will always lead to the AI correctly switching Raticate with Machop, -; but in case of a "Free" Duel where the first Machop is not KO'd, -; the intention was to switch to PLAY_AREA_BENCH_2 instead. -; but due to 'inc a' always being skipped, it will switch to Raticate. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - cp MACHOP ; wrong - ld a, PLAY_AREA_BENCH_1 - jr nz, .retreat - inc a ; PLAY_AREA_BENCH_2 - -.retreat - call AITryToRetreat - ret -; 0x148cc - -.turn_6 ; 148cc (5:48cc) - ld d, MACHOP - ld e, FIGHTING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x148d4 - -.turn_7 ; 148d4 (5:48d4) - ld d, MACHOP - ld e, FIGHTING_ENERGY - call AIAttachEnergyInHandToCardInPlayArea - ret -; 0x148dc - -INCLUDE "engine/deck_ai.asm" +INCLUDE "engine/deck_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 diff --git a/src/engine/deck_ai.asm b/src/engine/deck_ai.asm deleted file mode 100644 index 0bdbd5a..0000000 --- a/src/engine/deck_ai.asm +++ /dev/null @@ -1,2099 +0,0 @@ -; AI card retreat score bonus -; when the AI retreat routine runs through the Bench to choose -; a Pokemon to switch to, it looks up in this list and if -; a card ID matches, applies a retreat score bonus to this card. -; positive (negative) means more (less) likely to switch to this card. -ai_retreat: MACRO - db \1 ; card ID - db $80 + \2 ; retreat score (ranges between -128 and 127) -ENDM - -; AI card energy attach score bonus -; when the AI energy attachment routine runs through the Play Area to choose -; a Pokemon to attach an energy card, it looks up in this list and if -; a card ID matches, skips this card if the maximum number of energy -; cards attached has been reached. If it hasn't been reached, additionally -; applies a positive (or negative) AI score to attach energy to this card. -ai_energy: MACRO - db \1 ; card ID - db \2 ; maximum number of attached cards - db $80 + \3 ; energy score (ranges between -128 and 127) -ENDM - -; stores in WRAM pointer to data in argument -; e.g. store_list_pointer wSomeListPointer, SomeData -store_list_pointer: MACRO - ld hl, \1 - ld de, \2 - ld [hl], e - inc hl - ld [hl], d -ENDM - -; deck AIs are specialized to work on a given deck ID. -; they decide what happens during a turn, what Pokemon cards -; to pick during the start of the duel, etc. -; each of these have a pointer table with the following structure: -; dw .do_turn : never called; -; -; dw .do_turn : called to handle the main turn logic, from the beginning -; of the turn up to the attack (or lack thereof); -; -; dw .start_duel : called at the start of the duel to initialize some -; variables and optionally set up CPU hand and deck; -; -; dw .forced_switch : logic to determine what Pokemon to pick when there's -; an effect that forces AI to switch to Bench card; -; -; dw .ko_switch : logic for picking which card to use after a KO; -; -; dw .take_prize : logic to decide which prize card to pick. - -; optionally, decks can also declare card lists that will add -; more specialized logic during various generic AI routines, -; and read during the .start_duel routines. -; the pointers to these lists are stored in memory: -; wAICardListAvoidPrize : list of cards to avoid being placed as prize; -; wAICardListArenaPriority : priority list of Arena card at duel start; -; wAICardListBenchPriority : priority list of Bench cards at duel start; -; wAICardListPlayFromHandPriority : priority list of cards to play from hand; -; wAICardListRetreatBonus : scores given to certain cards for retreat; -; wAICardListEnergyBonus : max number of energy cards and card scores. - -AIActionTable_GeneralNoRetreat: ; 148dc (5:48dc) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 148e8 (5:48e8) - call AIDoTurn_GeneralNoRetreat - ret -; 0x148ec - -.start_duel ; 148ec (5:48ec) - call InitAIDuelVars - call AIPlayInitialBasicCards - ret -; 0x148f3 - -.forced_switch ; 148f3 (5:48f3) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x148f7 - -.ko_switch ; 148f7 (5:48f7) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x148fb - -.take_prize ; 148fb (5:48fb) - call AIPickPrizeCards - ret -; 0x148ff - -AIDoTurn_GeneralNoRetreat: ; 148ff (5:48ff) -; initialize variables - call InitAITurnVars - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; handle Pkmn Powers - farcall HandleAIGoGoRainDanceEnergy - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAICowardice -; process Trainer cards -; phase 2 through 4. - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_03 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended -; process Trainer cards -; phase 5 through 12. - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_06 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_08 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_12 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_1 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_1 -; play Pokemon from hand again - call AIDecidePlayPokemonCard -; handle Pkmn Powers again - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAIGoGoRainDanceEnergy - ld a, AI_ENERGY_TRANS_ATTACK - farcall HandleAIEnergyTrans -; process Trainer cards phases 13 and 15 - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_15 - call AIProcessHandTrainerCards -; if used Professor Oak, process new hand -; if not, then proceed to attack. - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK - jr z, .try_attack - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_03 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_06 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_08 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_12 - call AIProcessHandTrainerCards - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_2 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_2 - call AIDecidePlayPokemonCard - farcall HandleAIDamageSwap - farcall HandleAIPkmnPowers - ret c ; return if turn ended - farcall HandleAIGoGoRainDanceEnergy - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - ; skip AI_TRAINER_CARD_PHASE_15 -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if turn ended - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x149e8 - -AIActionTable_LegendaryMoltres: ; 149e8 (05:49e8) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 149f4 (5:49f4) - call AIDoTurn_LegendaryMoltres - ret -; 0x149f8 - -.start_duel ; 149f8 (5:49f8) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc ; Play Area set up was successful - call AIPlayInitialBasicCards - ret -; 0x14a09 - -.forced_switch ; 14a09 (5:4a09) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14a0d - -.ko_switch ; 14a0d (5:4a0d) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14a11 - -.take_prize ; 14a11 (5:4a11) - call AIPickPrizeCards - ret -; 0x14a15 - -.list_arena ; 14a15 (5:4a15) - db MAGMAR2 - db GROWLITHE - db VULPIX - db MAGMAR1 - db MOLTRES1 - db MOLTRES2 - db $00 - -.list_bench ; 14a1c (5:4a1c) - db MOLTRES1 - db VULPIX - db GROWLITHE - db MAGMAR2 - db MAGMAR1 - db $00 - -.list_play_hand ; 14a22 (5:4a22) - db MOLTRES2 - db MOLTRES1 - db VULPIX - db GROWLITHE - db MAGMAR2 - db MAGMAR1 - db $00 - -.list_retreat ; 14a29 (5:4a29) - ai_retreat GROWLITHE, -5 - ai_retreat VULPIX, -5 - db $00 - -.list_energy ; 14a2e (5:4a2e) - ai_energy VULPIX, 3, +0 - ai_energy NINETAILS2, 3, +1 - ai_energy GROWLITHE, 3, +1 - ai_energy ARCANINE2, 4, +1 - ai_energy MAGMAR1, 4, -1 - ai_energy MAGMAR2, 1, -1 - ai_energy MOLTRES2, 3, +2 - ai_energy MOLTRES1, 4, +2 - db $00 - -.list_prize ; 14a47 (5:4a47) - db ENERGY_REMOVAL - db MOLTRES2 - db $00 - -.store_list_pointers ; 14a4a (5:4a4a) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand - store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14a81 - -AIDoTurn_LegendaryMoltres: ; 14a81 (5:4a81) -; initialize variables - call InitAITurnVars - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; process Trainer cards -; phase 2 through 4. - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - -; check if AI can play Moltres2 -; from hand and if so, play it. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .skip_moltres ; skip if bench is full - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 9 - jr nc, .skip_moltres ; skip if cards in deck <= 9 - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .skip_moltres ; skip if Muk in play - ld a, MOLTRES2 - call LookForCardIDInHandList_Bank5 - jr nc, .skip_moltres ; skip if no Moltres2 in hand - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - -.skip_moltres -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_attach_energy - -; if Magmar2 is the Arena card and has no energy attached, -; try attaching an energy card to it from the hand. -; otherwise, run normal AI energy attach routine. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, MAGMAR2 - cp e - jr nz, .attach_normally - ; Magmar2 is the Arena card - call CreateEnergyCardListFromHand - jr c, .skip_attach_energy - ld e, PLAY_AREA_ARENA - call CountNumberOfEnergyCardsAttached - or a - jr nz, .attach_normally - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call AITryToPlayEnergyCard - jr c, .skip_attach_energy - -.attach_normally -; play Energy card if possible - call AIProcessAndTryToPlayEnergy -.skip_attach_energy -; try playing Pokemon cards from hand again - call AIDecidePlayPokemonCard - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14b0f - -AIActionTable_LegendaryZapdos: ; 14b0f (05:4b0f) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14b1b (5:4b1b) - call AIDoTurn_LegendaryZapdos - ret -; 0x14b1f - -.start_duel ; 14b1f (5:4b1f) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14b30 - -.forced_switch ; 14b30 (5:4b30) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14b34 - -.ko_switch ; 14b34 (5:4b34) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14b38 - -.take_prize ; 14b38 (5:4b38) - call AIPickPrizeCards - ret -; 0x14b3c - -.list_arena ; 14b3c (5:4b3c) - db ELECTABUZZ2 - db VOLTORB - db EEVEE - db ZAPDOS1 - db ZAPDOS2 - db ZAPDOS3 - db $00 - -.list_bench ; 14b43 (5:4b43) - db ZAPDOS2 - db ZAPDOS1 - db EEVEE - db VOLTORB - db ELECTABUZZ2 - db $00 - -.list_retreat ; 14b49 (5:4b49) - ai_retreat EEVEE, -5 - ai_retreat VOLTORB, -5 - ai_retreat ELECTABUZZ2, -5 - db $00 - -.list_energy ; 14b50 (5:4b50) - ai_energy VOLTORB, 1, -1 - ai_energy ELECTRODE1, 3, +0 - ai_energy ELECTABUZZ2, 2, -1 - ai_energy JOLTEON2, 3, +1 - ai_energy ZAPDOS1, 4, +2 - ai_energy ZAPDOS2, 4, +2 - ai_energy ZAPDOS3, 3, +1 - ai_energy EEVEE, 3, +0 - db $00 - -.list_prize ; 14b69 (5:4b69) - db GAMBLER - db ZAPDOS3 - db $00 - -.store_list_pointers ; 14b6c (5:4b6c) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14b9a - -AIDoTurn_LegendaryZapdos: ; 14b9a (5:4b9a) -; initialize variables - call InitAITurnVars - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards -; play Energy card if possible. - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach - -; if Arena card is Voltorb and there's Electrode1 in hand, -; or if it's Electabuzz, try attaching Energy card -; to the Arena card if it doesn't have any energy attached. -; Otherwise if Energy card is not needed, -; go through normal AI energy attach routine. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, VOLTORB - cp e - jr nz, .check_electabuzz - ld a, ELECTRODE1 - call LookForCardIDInHandList_Bank5 - jr nc, .attach_normally - jr .voltorb_or_electabuzz -.check_electabuzz - ld a, ELECTABUZZ2 - cp e - jr nz, .attach_normally - -.voltorb_or_electabuzz - call CreateEnergyCardListFromHand - jr c, .skip_energy_attach - ld e, PLAY_AREA_ARENA - call CountNumberOfEnergyCardsAttached - or a - jr nz, .attach_normally - xor a ; PLAY_AREA_ARENA - ldh [hTempPlayAreaLocation_ff9d], a - call AITryToPlayEnergyCard - jr c, .skip_energy_attach - -.attach_normally - call AIProcessAndTryToPlayEnergy - -.skip_energy_attach -; play Pokemon from hand again - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if turn ended - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14c0b - -AIActionTable_LegendaryArticuno: ; 14c0b (5:4c0b) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14c17 (5:4c17) - call AIDoTurn_LegendaryArticuno - ret -; 0x14c1b - -.start_duel ; 14c1b (5:4c1b) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14c2c - -.forced_switch ; 14c2c (5:4c2c) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14c30 - -.ko_switch ; 14c30 (5:4c30) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14c34 - -.take_prize ; 14c34 (5:4c34) - call AIPickPrizeCards - ret -; 0x14c38 - -.list_arena ; 14c38 (5:4c38) - db CHANSEY - db LAPRAS - db DITTO - db SEEL - db ARTICUNO1 - db ARTICUNO2 - db $00 - -.list_bench ; 14c3f (5:4c3f) - db ARTICUNO1 - db SEEL - db LAPRAS - db CHANSEY - db DITTO - db $00 - -.list_retreat ; 14c45 (5:4c45) - ai_retreat SEEL, -3 - ai_retreat DITTO, -3 - db $00 - -.list_energy ; 14c4a (5:4c4a) - ai_energy SEEL, 3, +1 - ai_energy DEWGONG, 4, +0 - ai_energy LAPRAS, 3, +0 - ai_energy ARTICUNO1, 4, +1 - ai_energy ARTICUNO2, 3, +0 - ai_energy CHANSEY, 0, -8 - ai_energy DITTO, 3, +0 - db $00 - -.list_prize ; 14c60 (5:4c60) - db GAMBLER - db ARTICUNO2 - db $00 - -.store_list_pointers ; 14c63 (5:4c63) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14c91 - -; this routine handles how Legendary Articuno -; prioritises playing energy cards to each Pokémon. -; first, it makes sure that all Lapras have at least -; 3 energy cards before moving on to Articuno, -; and then to Dewgong and Seel -ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) - call SwapTurn - call CountPrizes - call SwapTurn - cp 3 - ret c - -; player prizes >= 3 -; if Lapras has more than half HP and -; can use second move, check next for Articuno -; otherwise, check if Articuno or Dewgong -; have more than half HP and can use second move -; and if so, the next Pokémon to check is Lapras - ld a, LAPRAS - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .articuno - ld a, ARTICUNO1 - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .lapras - ld a, DEWGONG - call CheckForBenchIDAtHalfHPAndCanUseSecondMove - jr c, .lapras - jr .articuno - -; the following routines check for certain card IDs in bench -; and call RaiseAIScoreToAllMatchingIDsInBench if these are found. -; for Lapras, an additional check is made to its -; attached energy count, which skips calling the routine -; if this count is >= 3 -.lapras - ld a, LAPRAS - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .articuno - ld e, a - call CountNumberOfEnergyCardsAttached - cp 3 - jr nc, .articuno - ld a, LAPRAS - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.articuno - ld a, ARTICUNO1 - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .dewgong - ld a, ARTICUNO1 - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.dewgong - ld a, DEWGONG - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - jr nc, .seel - ld a, DEWGONG - call RaiseAIScoreToAllMatchingIDsInBench - ret - -.seel - ld a, SEEL - ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInPlayArea_Bank5 - ret nc - ld a, SEEL - call RaiseAIScoreToAllMatchingIDsInBench - ret -; 0x14cf7 - -AIDoTurn_LegendaryArticuno: ; 14cf7 (5:4cf7) -; initialize variables - call InitAITurnVars - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_1 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_1 -; play Pokemon from hand again - call AIDecidePlayPokemonCard -; process Trainer cards phases 13 and 15 - ld a, AI_TRAINER_CARD_PHASE_13 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_15 - call AIProcessHandTrainerCards -; if used Professor Oak, process new hand - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK - jr z, .try_attack - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - call AIDecidePlayPokemonCard - ret c ; return if turn ended - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_2 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_2 - call AIDecidePlayPokemonCard -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if turn ended - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14d60 - -AIActionTable_LegendaryDragonite: ; 14d60 (05:4d60) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14d6c (5:4d6c) - call AIDoTurn_LegendaryDragonite - ret -; 0x14d70 - -.start_duel ; 14d70 (5:4d70) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14d81 - -.forced_switch ; 14d81 (5:4d81) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14d85 - -.ko_switch ; 14d85 (5:4d85) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14d89 - -.take_prize ; 14d89 (5:4d89) - call AIPickPrizeCards - ret -; 0x14d8d - -.list_arena ; 14d8d (5:4d8d) - db KANGASKHAN - db LAPRAS - db CHARMANDER - db DRATINI - db MAGIKARP - db $00 - -.list_bench ; 14d93 (5:4d93) - db CHARMANDER - db MAGIKARP - db DRATINI - db LAPRAS - db KANGASKHAN - db $00 - -.list_retreat ; 14d99 (5:4d99) - ai_retreat CHARMANDER, -1 - ai_retreat MAGIKARP, -5 - db $00 - -.list_energy ; 14d9e (5:4d9e) - ai_energy CHARMANDER, 3, +1 - ai_energy CHARMELEON, 4, +1 - ai_energy CHARIZARD, 5, +0 - ai_energy MAGIKARP, 3, +1 - ai_energy GYARADOS, 4, -1 - ai_energy DRATINI, 2, +0 - ai_energy DRAGONAIR, 4, +0 - ai_energy DRAGONITE1, 3, -1 - ai_energy KANGASKHAN, 2, -2 - ai_energy LAPRAS, 3, +0 - db $00 - -.list_prize ; 14dbd (5:4dbd) - db GAMBLER - db DRAGONITE1 - db KANGASKHAN - db $00 - -.store_list_pointers ; 14dc1 (5:4dc1) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14def - -AIDoTurn_LegendaryDragonite: ; 14def (5:4def) -; initialize variables - call InitAITurnVars - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - farcall HandleAIAntiMewtwoDeckStrategy - jp nc, .try_attack -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_1 - -; if Arena card is Kangaskhan and doens't -; have Energy cards attached, try attaching from hand. -; otherwise run normal AI energy attach routine. - ld a, DUELVARS_ARENA_CARD - call GetTurnDuelistVariable - call GetCardIDFromDeckIndex - ld a, KANGASKHAN - cp e - jr nz, .attach_normally - call CreateEnergyCardListFromHand - jr c, .skip_energy_attach_1 - ld e, PLAY_AREA_ARENA - call CountNumberOfEnergyCardsAttached - or a - jr nz, .attach_normally - xor a - ldh [hTempPlayAreaLocation_ff9d], a - call AITryToPlayEnergyCard - jr c, .skip_energy_attach_1 -.attach_normally - call AIProcessAndTryToPlayEnergy - -.skip_energy_attach_1 -; play Pokemon from hand again - call AIDecidePlayPokemonCard - ld a, AI_TRAINER_CARD_PHASE_15 - call AIProcessHandTrainerCards -; if used Professor Oak, process new hand -; if not, then proceed to attack. - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK - jr z, .try_attack - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_11 - call AIProcessHandTrainerCards - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_energy_attach_2 - call AIProcessAndTryToPlayEnergy -.skip_energy_attach_2 - call AIDecidePlayPokemonCard -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if turn ended - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x14e89 - -AIActionTable_FirstStrike: ; 14e89 (5:4e89) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14e95 (5:4e95) - call AIMainTurnLogic - ret -; 0x14e99 - -.start_duel ; 14e99 (5:4e99) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14eaa - -.forced_switch ; 14eaa (5:4eaa) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14eae - -.ko_switch ; 14eae (5:4eae) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14eb2 - -.take_prize ; 14eb2 (5:4eb2) - call AIPickPrizeCards - ret -; 0x14eb6 - -.list_arena ; 14eb6 (5:1eb6) - db HITMONCHAN - db MACHOP - db HITMONLEE - db MANKEY - db $00 - -.list_bench ; 14ebb (5:1ebb) - db MACHOP - db HITMONLEE - db HITMONCHAN - db MANKEY - db $00 - -.list_retreat ; 14ec0 (5:1ec0) - ai_retreat MACHOP, -1 - ai_retreat MACHOKE, -1 - ai_retreat MANKEY, -2 - db $00 - -.list_energy ; 14ec7 (5:1ec7) - ai_energy MACHOP, 3, +0 - ai_energy MACHOKE, 4, +0 - ai_energy MACHAMP, 4, -1 - ai_energy HITMONCHAN, 3, +0 - ai_energy HITMONLEE, 3, +0 - ai_energy MANKEY, 2, -1 - ai_energy PRIMEAPE, 3, -1 - db $00 - -.list_prize ; 14edd (5:1edd) - db HITMONLEE - db HITMONCHAN - db $00 - -.store_list_pointers ; 14ee0 (5:4ee0) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14f0e - -AIActionTable_RockCrusher: ; 14f0e (5:4f0e) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14f1a (5:4f1a) - call AIMainTurnLogic - ret -; 0x14f1e - -.start_duel ; 14f1e (5:4f1e) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14f2f - -.forced_switch ; 14f2f (5:4f2f) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14f33 - -.ko_switch ; 14f33 (5:4f33) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14f37 - -.take_prize ; 14f37 (5:4f37) - call AIPickPrizeCards - ret -; 0x14f3b - -.list_arena ; 14f3b (5:4f3b) - db RHYHORN - db ONIX - db GEODUDE - db DIGLETT - db $00 - -.list_bench ; 14f40 (5:4f40) - db DIGLETT - db GEODUDE - db RHYHORN - db ONIX - db $00 - -.list_retreat ; 14f45 (5:4f45) - ai_retreat DIGLETT, -1 - db $00 - -.list_energy ; 14f48 (5:4f48) - ai_energy DIGLETT, 3, +1 - ai_energy DUGTRIO, 4, +0 - ai_energy GEODUDE, 2, +1 - ai_energy GRAVELER, 3, +0 - ai_energy GOLEM, 4, +0 - ai_energy ONIX, 2, -1 - ai_energy RHYHORN, 3, +0 - db $00 - -.list_prize ; 14f5e (5:4f5e) - db ENERGY_REMOVAL - db RHYHORN - db $00 - -.store_list_pointers ; 14f61 (5:4f61) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x14f8f - -AIActionTable_GoGoRainDance: ; 14f8f (5:4f8f) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 14f9b (5:4f9b) - call AIMainTurnLogic - ret -; 0x14f9f - -.start_duel ; 14f9f (5:4f9f) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x14fb0 - -.forced_switch ; 14fb0 (5:4fb0) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14fb4 - -.ko_switch ; 14fb4 (5:4fb4) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x14fb8 - -.take_prize ; 14fb8 (5:4fb8) - call AIPickPrizeCards - ret -; 0x14fbc - -.list_arena ; 14fbc (5:4fbc) - db LAPRAS - db HORSEA - db GOLDEEN - db SQUIRTLE - db $00 - -.list_bench ; 14fc1 (5:4fc1) - db SQUIRTLE - db HORSEA - db GOLDEEN - db LAPRAS - db $00 - -.list_retreat ; 14fc6 (5:4fc6) - ai_retreat SQUIRTLE, -3 - ai_retreat WARTORTLE, -2 - ai_retreat HORSEA, -1 - db $00 - -.list_energy ; 14fcd (5:4fcd) - ai_energy SQUIRTLE, 2, +0 - ai_energy WARTORTLE, 3, +0 - ai_energy BLASTOISE, 5, +0 - ai_energy GOLDEEN, 1, +0 - ai_energy SEAKING, 2, +0 - ai_energy HORSEA, 2, +0 - ai_energy SEADRA, 3, +0 - ai_energy LAPRAS, 3, +0 - db $00 - -.list_prize ; 14fe6 (5:4fe6) - db GAMBLER - db ENERGY_RETRIEVAL - db SUPER_ENERGY_RETRIEVAL - db BLASTOISE - db $00 - -.store_list_pointers ; 14feb (5:4feb) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x15019 - -AIActionTable_ZappingSelfdestruct: ; 15019 (5:5019) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 15025 (5:5025) - call AIMainTurnLogic - ret -; 0x15029 - -.start_duel ; 15029 (5:5029) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x1503a - -.forced_switch ; 1503a (5:503a) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1503e - -.ko_switch ; 1503e (5:503e) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15042 - -.take_prize ; 15042 (5:5042) - call AIPickPrizeCards - ret -; 0x15046 - -.list_arena ; 15046 (5:5046) - db KANGASKHAN - db ELECTABUZZ2 - db TAUROS - db MAGNEMITE1 - db VOLTORB - db $00 - -.list_bench ; 1504c (5:504c) - db MAGNEMITE1 - db VOLTORB - db ELECTABUZZ2 - db TAUROS - db KANGASKHAN - db $00 - -.list_retreat ; 15052 (5:5052) - ai_retreat VOLTORB, -1 - db $00 - -.list_energy ; 15055 (5:5055) - ai_energy MAGNEMITE1, 3, +1 - ai_energy MAGNETON1, 4, +0 - ai_energy VOLTORB, 3, +1 - ai_energy ELECTRODE1, 3, +0 - ai_energy ELECTABUZZ2, 1, +0 - ai_energy KANGASKHAN, 2, -2 - ai_energy TAUROS, 3, +0 - db $00 - -.list_prize ; 1506b (5:506b) - db KANGASKHAN - db $00 - -.store_list_pointers ; 1506d (5:506d) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x1509b - -AIActionTable_FlowerPower: ; 1509b (5:509b) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 150a7 (5:50a7) - call AIMainTurnLogic - ret -; 0x150ab - -.start_duel ; 150ab (5:50ab) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x150bc - -.forced_switch ; 150bc (5:50bc) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x150c0 - -.ko_switch ; 150c0 (5:50c0) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x150c4 - -.take_prize ; 150c4 (5:50c4) - call AIPickPrizeCards - ret -; 0x150c8 - -.list_arena ; 150c8 (5:50c8) - db ODDISH - db EXEGGCUTE - db BULBASAUR - db $00 - -.list_bench ; 150cc (5:50cc) - db BULBASAUR - db EXEGGCUTE - db ODDISH - db $00 - -.list_retreat ; 150cf (5:50cf) - ai_retreat GLOOM, -2 - ai_retreat VILEPLUME, -2 - ai_retreat BULBASAUR, -2 - ai_retreat IVYSAUR, -2 - db $00 - -.list_energy ; 150d9 (5:50d9) - ai_energy BULBASAUR, 3, +0 - ai_energy IVYSAUR, 4, +0 - ai_energy VENUSAUR2, 4, +0 - ai_energy ODDISH, 2, +0 - ai_energy GLOOM, 3, -1 - ai_energy VILEPLUME, 3, -1 - ai_energy EXEGGCUTE, 3, +0 - ai_energy EXEGGUTOR, 22, +0 - db $00 - -.list_prize ; 150f2 (5:50f2) - db VENUSAUR2 - db $00 - -.store_list_pointers ; 150f4 (5:50f4) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x15122 - -AIActionTable_StrangePsyshock: ; 15122 (5:5122) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 1512e (5:512e) - call AIMainTurnLogic - ret -; 0x15132 - -.start_duel ; 15132 (5:5132) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15143 - -.forced_switch ; 15143 (5:5143) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15147 - -.ko_switch ; 15147 (5:5147) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1514b - -.take_prize ; 1514b (5:514b) - call AIPickPrizeCards - ret -; 0x1514f - -.list_arena ; 1514f (5:514f) - db KANGASKHAN - db CHANSEY - db SNORLAX - db MR_MIME - db ABRA - db $00 - -.list_bench ; 15155 (5:5155) - db ABRA - db MR_MIME - db KANGASKHAN - db SNORLAX - db CHANSEY - db $00 - -.list_retreat ; 1515b (5:515b) - ai_retreat ABRA, -3 - ai_retreat SNORLAX, -3 - ai_retreat KANGASKHAN, -1 - ai_retreat CHANSEY, -1 - db $00 - -.list_energy ; 15164 (5:5164) - ai_energy ABRA, 3, +1 - ai_energy KADABRA, 3, +0 - ai_energy ALAKAZAM, 3, +0 - ai_energy MR_MIME, 2, +0 - ai_energy CHANSEY, 2, -2 - ai_energy KANGASKHAN, 4, -2 - ai_energy SNORLAX, 0, -8 - db $00 - -.list_prize ; 1517a (5:517a) - db GAMBLER - db MR_MIME - db ALAKAZAM - db SWITCH - db $00 - -.store_list_pointers ; 1517f (5:517f) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x151ad - -AIActionTable_WondersOfScience: ; 151ad (5:51ad) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 151b9 (5:51b9) - call AIMainTurnLogic - ret -; 0x151bd - -.start_duel ; 151bd (5:51bd) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x151ce - -.forced_switch ; 151ce (5:51ce) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x151d2 - -.ko_switch ; 151d2 (5:51d2) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x151d6 - -.take_prize ; 151d6 (5:51d6) - call AIPickPrizeCards - ret -; 0x151da - -.list_arena ; 151da (5:51da) - db MEWTWO1 - db MEWTWO3 - db MEWTWO2 - db GRIMER - db KOFFING - db PORYGON - db $00 - -.list_bench ; 151e1 (5:51e1) - db GRIMER - db KOFFING - db MEWTWO3 - db MEWTWO2 - db MEWTWO1 - db PORYGON - db $00 - -.list_retreat ; 151e8 (5:51e8) - db $00 - -.list_energy ; 151e9 (5:51e9) - ai_energy GRIMER, 3, +0 - ai_energy MUK, 4, +0 - ai_energy KOFFING, 2, +0 - ai_energy WEEZING, 3, +0 - ai_energy MEWTWO1, 2, -1 - ai_energy MEWTWO3, 2, -1 - ai_energy MEWTWO2, 2, -1 - ai_energy PORYGON, 2, -1 - db $00 - -.list_prize ; 15202 (5:5202) - db MUK - db $00 - -.store_list_pointers ; 15204 (5:5204) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x15232 - -AIActionTable_FireCharge: ; 15232 (5:5232) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 1523e (5:523e) - call AIMainTurnLogic - ret -; 0x15242 - -.start_duel ; 15242 (5:5242) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15253 - -.forced_switch ; 15253 (5:5253) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15257 - -.ko_switch ; 15257 (5:5257) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1525b - -.take_prize ; 1525b (5:525b) - call AIPickPrizeCards - ret -; 0x1525f - -.list_arena ; 1525f (5:525f) - db JIGGLYPUFF3 - db CHANSEY - db TAUROS - db MAGMAR1 - db JIGGLYPUFF1 - db GROWLITHE - db $00 - -.list_bench ; 15266 (5:5266) - db JIGGLYPUFF3 - db CHANSEY - db GROWLITHE - db MAGMAR1 - db JIGGLYPUFF1 - db TAUROS - db $00 - -.list_retreat ; 1526e (5:526e) - ai_retreat JIGGLYPUFF1, -1 - ai_retreat CHANSEY, -1 - ai_retreat GROWLITHE, -1 - db $00 - -.list_energy ; 15274 (5:5274) - ai_energy GROWLITHE, 3, +0 - ai_energy ARCANINE2, 4, +0 - ai_energy MAGMAR1, 3, +0 - ai_energy JIGGLYPUFF1, 3, +0 - ai_energy JIGGLYPUFF3, 2, +0 - ai_energy WIGGLYTUFF, 3, +0 - ai_energy CHANSEY, 4, +0 - ai_energy TAUROS, 3, +0 - db $00 - -.list_prize ; 1528d (5:528d) - db GAMBLER - db $00 - -.store_list_pointers ; 1528f (5:528f) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x152bd - -AIActionTable_ImRonald: ; 152bd (5:52bd) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 152c9 (5:52c9) - call AIMainTurnLogic - ret -; 0x152cd - -.start_duel ; 152cd (5:52cd) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x152de - -.forced_switch ; 152de (5:52de) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x152e2 - -.ko_switch ; 152e2 (5:52e2) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x152e6 - -.take_prize ; 152e6 (5:52e6) - call AIPickPrizeCards - ret -; 0x152ea - -.list_arena ; 152ea (5:52ea) - db LAPRAS - db SEEL - db CHARMANDER - db CUBONE - db SQUIRTLE - db GROWLITHE - db $00 - -.list_bench ; 152f1 (5:52f1) - db CHARMANDER - db SQUIRTLE - db SEEL - db CUBONE - db GROWLITHE - db LAPRAS - db $00 - -.list_retreat ; 152f8 (5:52f8) - db $00 - -.list_energy ; 152f9 (5:52f9) - ai_energy CHARMANDER, 3, +0 - ai_energy CHARMELEON, 5, +0 - ai_energy GROWLITHE, 2, +0 - ai_energy ARCANINE2, 4, +0 - ai_energy SQUIRTLE, 2, +0 - ai_energy WARTORTLE, 3, +0 - ai_energy SEEL, 3, +0 - ai_energy DEWGONG, 4, +0 - ai_energy LAPRAS, 3, +0 - ai_energy CUBONE, 3, +0 - ai_energy MAROWAK1, 3, +0 - db $00 - -.list_prize ; 1531b (5:531b) - db LAPRAS - db $00 - -.store_list_pointers ; 1531d (5:531d) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x1534b - -AIActionTable_PowerfulRonald: ; 1534b (5:534b) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 15357 (5:5357) - call AIMainTurnLogic - ret -; 0x1535b - -.start_duel ; 1535b (5:535b) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x1536c - -.forced_switch ; 1536c (5:536c) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15370 - -.ko_switch ; 15370 (5:5370) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15374 - -.take_prize ; 15374 (5:5374) - call AIPickPrizeCards - ret -; 0x15378 - -.list_arena ; 15378 (5:5378) - db KANGASKHAN - db ELECTABUZZ2 - db HITMONCHAN - db MR_MIME - db LICKITUNG - db HITMONLEE - db TAUROS - db JYNX - db MEWTWO1 - db DODUO - db $00 - -.list_bench ; 15383 (5:5383) - db KANGASKHAN - db HITMONLEE - db HITMONCHAN - db TAUROS - db DODUO - db JYNX - db MEWTWO1 - db ELECTABUZZ2 - db MR_MIME - db LICKITUNG - db $00 - -.list_retreat ; 1538e (5:538e) - ai_retreat KANGASKHAN, -1 - ai_retreat DODUO, -1 - ai_retreat DODRIO, -1 - db $00 - -.list_energy ; 15395 (5:5395) - ai_energy ELECTABUZZ2, 2, +1 - ai_energy HITMONLEE, 3, +1 - ai_energy HITMONCHAN, 3, +1 - ai_energy MR_MIME, 2, +0 - ai_energy JYNX, 3, +0 - ai_energy MEWTWO1, 2, +0 - ai_energy DODUO, 3, -1 - ai_energy DODRIO, 3, -1 - ai_energy LICKITUNG, 2, +0 - ai_energy KANGASKHAN, 4, -1 - ai_energy TAUROS, 3, +0 - db $00 - -.list_prize ; 153b7 (5:53b7) - db GAMBLER - db ENERGY_REMOVAL - db $00 - -.store_list_pointers ; 153ba (5:53ba) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x153e8 - -AIActionTable_InvincibleRonald: ; 153e8 (5:53e8) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 153f4 (5:53f4) - call AIMainTurnLogic - ret -; 0x153f8 - -.start_duel ; 153f8 (5:53f8) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15409 - -.forced_switch ; 15409 (5:5409) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x1540d - -.ko_switch ; 1540d (5:540d) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15411 - -.take_prize ; 15411 (5:5411) - call AIPickPrizeCards - ret -; 0x15415 - -.list_arena ; 15415 (5:5415) - db KANGASKHAN - db MAGMAR2 - db CHANSEY - db GEODUDE - db SCYTHER - db GRIMER - db $00 - -.list_bench ; 1541c (5:541c) - db GRIMER - db SCYTHER - db GEODUDE - db CHANSEY - db MAGMAR2 - db KANGASKHAN - db $00 - -.list_retreat ; 15423 (5:5423) - ai_retreat GRIMER, -1 - db $00 - -.list_energy ; 15426 (5:5426) - ai_energy GRIMER, 1, -1 - ai_energy MUK, 3, -1 - ai_energy SCYTHER, 4, +1 - ai_energy MAGMAR2, 2, +0 - ai_energy GEODUDE, 2, +0 - ai_energy GRAVELER, 3, +0 - ai_energy CHANSEY, 4, +0 - ai_energy KANGASKHAN, 4, -1 - db $00 - -.list_prize ; 1543f (5:543f) - db GAMBLER - db $00 - -.store_list_pointers ; 15441 (5:5441) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_bench - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x1546f - -AIActionTable_LegendaryRonald: ; 1546f (5:546f) - dw .do_turn ; unused - dw .do_turn - dw .start_duel - dw .forced_switch - dw .ko_switch - dw .take_prize - -.do_turn ; 1547b (5:547b) - call AIDoTurn_LegendaryRonald - ret -; 0x1547f - -.start_duel ; 1547f (5:547f) - call InitAIDuelVars - call .store_list_pointers - call SetUpBossStartingHandAndDeck - call TrySetUpBossStartingPlayArea - ret nc - call AIPlayInitialBasicCards - ret -; 0x15490 - -.forced_switch ; 15490 (5:5490) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15494 - -.ko_switch ; 15494 (5:5494) - call AIDecideBenchPokemonToSwitchTo - ret -; 0x15498 - -.take_prize ; 15498 (5:5498) - call AIPickPrizeCards - ret -; 0x1549c - -.list_arena ; 1549c (5:549c) - db KANGASKHAN - db DRATINI - db EEVEE - db ZAPDOS3 - db ARTICUNO2 - db MOLTRES2 - db $00 - -.list_bench ; 154a3 (5:54a3) - db KANGASKHAN - db DRATINI - db EEVEE - db $00 - -.list_play_hand ; 154a7 (5:54a7) - db MOLTRES2 - db ZAPDOS3 - db KANGASKHAN - db DRATINI - db EEVEE - db ARTICUNO2 - db $00 - -.list_retreat ; 154ae (5:54ae) - ai_retreat EEVEE, -2 - db $00 - -.list_energy ; 154b1 (5:54b1) - ai_energy FLAREON1, 3, +0 - ai_energy MOLTRES2, 3, +0 - ai_energy VAPOREON1, 3, +0 - ai_energy ARTICUNO2, 0, -8 - ai_energy JOLTEON1, 4, +0 - ai_energy ZAPDOS3, 0, -8 - ai_energy KANGASKHAN, 4, -1 - ai_energy EEVEE, 3, +0 - ai_energy DRATINI, 3, +0 - ai_energy DRAGONAIR, 4, +0 - ai_energy DRAGONITE1, 3, +0 - db $00 - -.list_prize ; 154d3 (5:54d3) - db MOLTRES2 - db ARTICUNO2 - db ZAPDOS3 - db DRAGONITE1 - db GAMBLER - db $00 - -.store_list_pointers ; 154d9 (5:54d9) - store_list_pointer wAICardListAvoidPrize, .list_prize - store_list_pointer wAICardListArenaPriority, .list_arena - store_list_pointer wAICardListBenchPriority, .list_bench - store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand - ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat - store_list_pointer wAICardListEnergyBonus, .list_energy - ret -; 0x15507 - -AIDoTurn_LegendaryRonald: ; 15507 (5:5507) -; initialize variables - call InitAITurnVars -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - -; check if AI can play Moltres2 -; from hand and if so, play it. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .skip_moltres_1 ; skip if bench is full - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 9 - jr nc, .skip_moltres_1 ; skip if cards in deck <= 9 - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .skip_moltres_1 ; skip if Muk in play - ld a, MOLTRES2 - call LookForCardIDInHandList_Bank5 - jr nc, .skip_moltres_1 ; skip if no Moltres2 in hand - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - -.skip_moltres_1 -; play Pokemon from hand - call AIDecidePlayPokemonCard - ret c ; return if turn ended -; process Trainer cards - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards -; play Energy card if possible - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_attach_energy_1 - call AIProcessAndTryToPlayEnergy -.skip_attach_energy_1 -; try playing Pokemon cards from hand again - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_15 -; if used Professor Oak, process new hand -; if not, then proceed to attack. - call AIProcessHandTrainerCards - ld a, [wPreviousAIFlags] - and AI_FLAG_USED_PROFESSOR_OAK - jr z, .try_attack - ld a, AI_TRAINER_CARD_PHASE_01 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_02 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_04 - call AIProcessHandTrainerCards - -; check if AI can play Moltres2 -; from hand and if so, play it. - ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA - call GetTurnDuelistVariable - cp MAX_PLAY_AREA_POKEMON - jr nc, .skip_moltres_2 ; skip if bench is full - ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK - call GetTurnDuelistVariable - cp DECK_SIZE - 9 - jr nc, .skip_moltres_2 ; skip if cards in deck <= 9 - ld a, MUK - call CountPokemonIDInBothPlayAreas - jr c, .skip_moltres_2 ; skip if Muk in play - ld a, MOLTRES2 - call LookForCardIDInHandList_Bank5 - jr nc, .skip_moltres_2 ; skip if no Moltres2 in hand - ldh [hTemp_ffa0], a - ld a, OPPACTION_PLAY_BASIC_PKMN - bank1call AIMakeDecision - -.skip_moltres_2 - call AIDecidePlayPokemonCard - ret c ; return if turn ended - ld a, AI_TRAINER_CARD_PHASE_05 - call AIProcessHandTrainerCards - ld a, AI_TRAINER_CARD_PHASE_07 - call AIProcessHandTrainerCards - call AIProcessRetreat - ld a, AI_TRAINER_CARD_PHASE_10 - call AIProcessHandTrainerCards - ld a, [wAlreadyPlayedEnergy] - or a - jr nz, .skip_attach_energy_2 - call AIProcessAndTryToPlayEnergy -.skip_attach_energy_2 - call AIDecidePlayPokemonCard - ret c ; return if turn ended -.try_attack -; attack if possible, if not, -; finish turn without attacking. - call AIProcessAndTryToUseAttack - ret c ; return if turn ended - ld a, OPPACTION_FINISH_NO_ATTACK - bank1call AIMakeDecision - ret -; 0x155d2 diff --git a/src/engine/deck_ai/deck_ai.asm b/src/engine/deck_ai/deck_ai.asm new file mode 100644 index 0000000..a906472 --- /dev/null +++ b/src/engine/deck_ai/deck_ai.asm @@ -0,0 +1,81 @@ +; AI card retreat score bonus +; when the AI retreat routine runs through the Bench to choose +; a Pokemon to switch to, it looks up in this list and if +; a card ID matches, applies a retreat score bonus to this card. +; positive (negative) means more (less) likely to switch to this card. +ai_retreat: MACRO + db \1 ; card ID + db $80 + \2 ; retreat score (ranges between -128 and 127) +ENDM + +; AI card energy attach score bonus +; when the AI energy attachment routine runs through the Play Area to choose +; a Pokemon to attach an energy card, it looks up in this list and if +; a card ID matches, skips this card if the maximum number of energy +; cards attached has been reached. If it hasn't been reached, additionally +; applies a positive (or negative) AI score to attach energy to this card. +ai_energy: MACRO + db \1 ; card ID + db \2 ; maximum number of attached cards + db $80 + \3 ; energy score (ranges between -128 and 127) +ENDM + +; stores in WRAM pointer to data in argument +; e.g. store_list_pointer wSomeListPointer, SomeData +store_list_pointer: MACRO + ld hl, \1 + ld de, \2 + ld [hl], e + inc hl + ld [hl], d +ENDM + +; deck AIs are specialized to work on a given deck ID. +; they decide what happens during a turn, what Pokemon cards +; to pick during the start of the duel, etc. +; each of these have a pointer table with the following structure: +; dw .do_turn : never called; +; +; dw .do_turn : called to handle the main turn logic, from the beginning +; of the turn up to the attack (or lack thereof); +; +; dw .start_duel : called at the start of the duel to initialize some +; variables and optionally set up CPU hand and deck; +; +; dw .forced_switch : logic to determine what Pokemon to pick when there's +; an effect that forces AI to switch to Bench card; +; +; dw .ko_switch : logic for picking which card to use after a KO; +; +; dw .take_prize : logic to decide which prize card to pick. + +; optionally, decks can also declare card lists that will add +; more specialized logic during various generic AI routines, +; and read during the .start_duel routines. +; the pointers to these lists are stored in memory: +; wAICardListAvoidPrize : list of cards to avoid being placed as prize; +; wAICardListArenaPriority : priority list of Arena card at duel start; +; wAICardListBenchPriority : priority list of Bench cards at duel start; +; wAICardListPlayFromHandPriority : priority list of cards to play from hand; +; wAICardListRetreatBonus : scores given to certain cards for retreat; +; wAICardListEnergyBonus : max number of energy cards and card scores. + +INCLUDE "engine/deck_ai/decks/general.asm" +INCLUDE "engine/deck_ai/decks/sams_practice.asm" +INCLUDE "engine/deck_ai/decks/general_no_retreat.asm" +INCLUDE "engine/deck_ai/decks/legendary_moltres.asm" +INCLUDE "engine/deck_ai/decks/legendary_zapdos.asm" +INCLUDE "engine/deck_ai/decks/legendary_articuno.asm" +INCLUDE "engine/deck_ai/decks/legendary_dragonite.asm" +INCLUDE "engine/deck_ai/decks/first_strike.asm" +INCLUDE "engine/deck_ai/decks/rock_crusher.asm" +INCLUDE "engine/deck_ai/decks/go_go_rain_dance.asm" +INCLUDE "engine/deck_ai/decks/zapping_selfdestruct.asm" +INCLUDE "engine/deck_ai/decks/flower_power.asm" +INCLUDE "engine/deck_ai/decks/strange_psyshock.asm" +INCLUDE "engine/deck_ai/decks/wonders_of_science.asm" +INCLUDE "engine/deck_ai/decks/fire_charge.asm" +INCLUDE "engine/deck_ai/decks/im_ronald.asm" +INCLUDE "engine/deck_ai/decks/powerful_ronald.asm" +INCLUDE "engine/deck_ai/decks/invincible_ronald.asm" +INCLUDE "engine/deck_ai/decks/legendary_ronald.asm" diff --git a/src/engine/deck_ai/decks/fire_charge.asm b/src/engine/deck_ai/decks/fire_charge.asm new file mode 100644 index 0000000..454f731 --- /dev/null +++ b/src/engine/deck_ai/decks/fire_charge.asm @@ -0,0 +1,86 @@ +AIActionTable_FireCharge: ; 15232 (5:5232) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 1523e (5:523e) + call AIMainTurnLogic + ret +; 0x15242 + +.start_duel ; 15242 (5:5242) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15253 + +.forced_switch ; 15253 (5:5253) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15257 + +.ko_switch ; 15257 (5:5257) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1525b + +.take_prize ; 1525b (5:525b) + call AIPickPrizeCards + ret +; 0x1525f + +.list_arena ; 1525f (5:525f) + db JIGGLYPUFF3 + db CHANSEY + db TAUROS + db MAGMAR1 + db JIGGLYPUFF1 + db GROWLITHE + db $00 + +.list_bench ; 15266 (5:5266) + db JIGGLYPUFF3 + db CHANSEY + db GROWLITHE + db MAGMAR1 + db JIGGLYPUFF1 + db TAUROS + db $00 + +.list_retreat ; 1526e (5:526e) + ai_retreat JIGGLYPUFF1, -1 + ai_retreat CHANSEY, -1 + ai_retreat GROWLITHE, -1 + db $00 + +.list_energy ; 15274 (5:5274) + ai_energy GROWLITHE, 3, +0 + ai_energy ARCANINE2, 4, +0 + ai_energy MAGMAR1, 3, +0 + ai_energy JIGGLYPUFF1, 3, +0 + ai_energy JIGGLYPUFF3, 2, +0 + ai_energy WIGGLYTUFF, 3, +0 + ai_energy CHANSEY, 4, +0 + ai_energy TAUROS, 3, +0 + db $00 + +.list_prize ; 1528d (5:528d) + db GAMBLER + db $00 + +.store_list_pointers ; 1528f (5:528f) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x152bd diff --git a/src/engine/deck_ai/decks/first_strike.asm b/src/engine/deck_ai/decks/first_strike.asm new file mode 100644 index 0000000..6d2906c --- /dev/null +++ b/src/engine/deck_ai/decks/first_strike.asm @@ -0,0 +1,82 @@ +AIActionTable_FirstStrike: ; 14e89 (5:4e89) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14e95 (5:4e95) + call AIMainTurnLogic + ret +; 0x14e99 + +.start_duel ; 14e99 (5:4e99) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14eaa + +.forced_switch ; 14eaa (5:4eaa) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eae + +.ko_switch ; 14eae (5:4eae) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14eb2 + +.take_prize ; 14eb2 (5:4eb2) + call AIPickPrizeCards + ret +; 0x14eb6 + +.list_arena ; 14eb6 (5:1eb6) + db HITMONCHAN + db MACHOP + db HITMONLEE + db MANKEY + db $00 + +.list_bench ; 14ebb (5:1ebb) + db MACHOP + db HITMONLEE + db HITMONCHAN + db MANKEY + db $00 + +.list_retreat ; 14ec0 (5:1ec0) + ai_retreat MACHOP, -1 + ai_retreat MACHOKE, -1 + ai_retreat MANKEY, -2 + db $00 + +.list_energy ; 14ec7 (5:1ec7) + ai_energy MACHOP, 3, +0 + ai_energy MACHOKE, 4, +0 + ai_energy MACHAMP, 4, -1 + ai_energy HITMONCHAN, 3, +0 + ai_energy HITMONLEE, 3, +0 + ai_energy MANKEY, 2, -1 + ai_energy PRIMEAPE, 3, -1 + db $00 + +.list_prize ; 14edd (5:1edd) + db HITMONLEE + db HITMONCHAN + db $00 + +.store_list_pointers ; 14ee0 (5:4ee0) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14f0e diff --git a/src/engine/deck_ai/decks/flower_power.asm b/src/engine/deck_ai/decks/flower_power.asm new file mode 100644 index 0000000..566d064 --- /dev/null +++ b/src/engine/deck_ai/decks/flower_power.asm @@ -0,0 +1,81 @@ +AIActionTable_FlowerPower: ; 1509b (5:509b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 150a7 (5:50a7) + call AIMainTurnLogic + ret +; 0x150ab + +.start_duel ; 150ab (5:50ab) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x150bc + +.forced_switch ; 150bc (5:50bc) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c0 + +.ko_switch ; 150c0 (5:50c0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x150c4 + +.take_prize ; 150c4 (5:50c4) + call AIPickPrizeCards + ret +; 0x150c8 + +.list_arena ; 150c8 (5:50c8) + db ODDISH + db EXEGGCUTE + db BULBASAUR + db $00 + +.list_bench ; 150cc (5:50cc) + db BULBASAUR + db EXEGGCUTE + db ODDISH + db $00 + +.list_retreat ; 150cf (5:50cf) + ai_retreat GLOOM, -2 + ai_retreat VILEPLUME, -2 + ai_retreat BULBASAUR, -2 + ai_retreat IVYSAUR, -2 + db $00 + +.list_energy ; 150d9 (5:50d9) + ai_energy BULBASAUR, 3, +0 + ai_energy IVYSAUR, 4, +0 + ai_energy VENUSAUR2, 4, +0 + ai_energy ODDISH, 2, +0 + ai_energy GLOOM, 3, -1 + ai_energy VILEPLUME, 3, -1 + ai_energy EXEGGCUTE, 3, +0 + ai_energy EXEGGUTOR, 22, +0 + db $00 + +.list_prize ; 150f2 (5:50f2) + db VENUSAUR2 + db $00 + +.store_list_pointers ; 150f4 (5:50f4) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x15122 diff --git a/src/engine/deck_ai/decks/general.asm b/src/engine/deck_ai/decks/general.asm new file mode 100644 index 0000000..1bfc3e0 --- /dev/null +++ b/src/engine/deck_ai/decks/general.asm @@ -0,0 +1,196 @@ +; AI logic used by general decks +AIActionTable_GeneralDecks: ; 14668 (05:4668) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14674 (5:4674) + call AIMainTurnLogic + ret + +.start_duel ; 14678 (5:4678) + call InitAIDuelVars + call AIPlayInitialBasicCards + ret + +.forced_switch ; 1467f (5:467f) + call AIDecideBenchPokemonToSwitchTo + ret + +.ko_switch ; 14683 (5:4683) + call AIDecideBenchPokemonToSwitchTo + ret + +.take_prize: ; 14687 (5:4687) + call AIPickPrizeCards + ret + +; handle AI routines for a whole turn +AIMainTurnLogic: ; 1468b (5:468b) +; initialize variables + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; handle Pkmn Powers + farcall HandleAIGoGoRainDanceEnergy + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAICowardice +; process Trainer cards +; phase 2 through 4. + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended +; process Trainer cards +; phase 5 through 12. + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_1 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_1 +; play Pokemon from hand again + call AIDecidePlayPokemonCard +; handle Pkmn Powers again + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAIGoGoRainDanceEnergy + ld a, AI_ENERGY_TRANS_ATTACK + farcall HandleAIEnergyTrans +; process Trainer cards phases 13 and 15 + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards +; if used Professor Oak, process new hand +; if not, then proceed to attack. + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_2 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_2 + call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAIGoGoRainDanceEnergy + ld a, AI_ENERGY_TRANS_ATTACK + farcall HandleAIEnergyTrans + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ; skip AI_TRAINER_CARD_PHASE_15 +.try_attack + ld a, AI_ENERGY_TRANS_TO_BENCH + farcall HandleAIEnergyTrans +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if AI attacked + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14786 + +; handles AI retreating logic +AIProcessRetreat: ; 14786 (5:4786) + ld a, [wAIRetreatedThisTurn] + or a + ret nz ; return, already retreated this turn + + call AIDecideWhetherToRetreat + ret nc ; return if not retreating + + call AIDecideBenchPokemonToSwitchTo + ret c ; return if no Bench Pokemon + +; store Play Area to retreat to and +; set wAIRetreatedThisTurn to true + ld [wAIPlayAreaCardToSwitch], a + ld a, $01 + ld [wAIRetreatedThisTurn], a + +; if AI can use Switch from hand, use it instead... + ld a, AI_TRAINER_CARD_PHASE_09 + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_SWITCH + jr nz, .used_switch +; ... else try retreating normally. + ld a, [wAIPlayAreaCardToSwitch] + call AITryToRetreat + ret + +.used_switch +; if AI used switch, unset its AI flag + ld a, [wPreviousAIFlags] + and ~AI_FLAG_USED_SWITCH ; clear Switch flag + ld [wPreviousAIFlags], a + +; bug, this doesn't make sense being here, since at this point +; Switch Trainer card was already used to retreat the Pokemon. +; what the routine will do is just transfer Energy cards to +; the Arena Pokemon for the purpose of retreating, and +; then not actually retreat, resulting in unusual behaviour. +; this would only work placed right after the AI checks whether +; they have Switch card in hand to use and doesn't have one. +; (and probably that was the original intention.) + ld a, AI_ENERGY_TRANS_RETREAT ; retreat + farcall HandleAIEnergyTrans + ret +; 0x147bd diff --git a/src/engine/deck_ai/decks/general_no_retreat.asm b/src/engine/deck_ai/decks/general_no_retreat.asm new file mode 100644 index 0000000..e735076 --- /dev/null +++ b/src/engine/deck_ai/decks/general_no_retreat.asm @@ -0,0 +1,146 @@ +; acts just like a general deck AI except never retreats +AIActionTable_GeneralNoRetreat: ; 148dc (5:48dc) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 148e8 (5:48e8) + call AIDoTurn_GeneralNoRetreat + ret +; 0x148ec + +.start_duel ; 148ec (5:48ec) + call InitAIDuelVars + call AIPlayInitialBasicCards + ret +; 0x148f3 + +.forced_switch ; 148f3 (5:48f3) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148f7 + +.ko_switch ; 148f7 (5:48f7) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x148fb + +.take_prize ; 148fb (5:48fb) + call AIPickPrizeCards + ret +; 0x148ff + +AIDoTurn_GeneralNoRetreat: ; 148ff (5:48ff) +; initialize variables + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; handle Pkmn Powers + farcall HandleAIGoGoRainDanceEnergy + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAICowardice +; process Trainer cards +; phase 2 through 4. + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended +; process Trainer cards +; phase 5 through 12. + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_1 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_1 +; play Pokemon from hand again + call AIDecidePlayPokemonCard +; handle Pkmn Powers again + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAIGoGoRainDanceEnergy + ld a, AI_ENERGY_TRANS_ATTACK + farcall HandleAIEnergyTrans +; process Trainer cards phases 13 and 15 + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards +; if used Professor Oak, process new hand +; if not, then proceed to attack. + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_03 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_06 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_08 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_12 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_2 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_2 + call AIDecidePlayPokemonCard + farcall HandleAIDamageSwap + farcall HandleAIPkmnPowers + ret c ; return if turn ended + farcall HandleAIGoGoRainDanceEnergy + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ; skip AI_TRAINER_CARD_PHASE_15 +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if turn ended + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x149e8 diff --git a/src/engine/deck_ai/decks/go_go_rain_dance.asm b/src/engine/deck_ai/decks/go_go_rain_dance.asm new file mode 100644 index 0000000..006bbdc --- /dev/null +++ b/src/engine/deck_ai/decks/go_go_rain_dance.asm @@ -0,0 +1,85 @@ +AIActionTable_GoGoRainDance: ; 14f8f (5:4f8f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14f9b (5:4f9b) + call AIMainTurnLogic + ret +; 0x14f9f + +.start_duel ; 14f9f (5:4f9f) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14fb0 + +.forced_switch ; 14fb0 (5:4fb0) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb4 + +.ko_switch ; 14fb4 (5:4fb4) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14fb8 + +.take_prize ; 14fb8 (5:4fb8) + call AIPickPrizeCards + ret +; 0x14fbc + +.list_arena ; 14fbc (5:4fbc) + db LAPRAS + db HORSEA + db GOLDEEN + db SQUIRTLE + db $00 + +.list_bench ; 14fc1 (5:4fc1) + db SQUIRTLE + db HORSEA + db GOLDEEN + db LAPRAS + db $00 + +.list_retreat ; 14fc6 (5:4fc6) + ai_retreat SQUIRTLE, -3 + ai_retreat WARTORTLE, -2 + ai_retreat HORSEA, -1 + db $00 + +.list_energy ; 14fcd (5:4fcd) + ai_energy SQUIRTLE, 2, +0 + ai_energy WARTORTLE, 3, +0 + ai_energy BLASTOISE, 5, +0 + ai_energy GOLDEEN, 1, +0 + ai_energy SEAKING, 2, +0 + ai_energy HORSEA, 2, +0 + ai_energy SEADRA, 3, +0 + ai_energy LAPRAS, 3, +0 + db $00 + +.list_prize ; 14fe6 (5:4fe6) + db GAMBLER + db ENERGY_RETRIEVAL + db SUPER_ENERGY_RETRIEVAL + db BLASTOISE + db $00 + +.store_list_pointers ; 14feb (5:4feb) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x15019 diff --git a/src/engine/deck_ai/decks/im_ronald.asm b/src/engine/deck_ai/decks/im_ronald.asm new file mode 100644 index 0000000..c140f1d --- /dev/null +++ b/src/engine/deck_ai/decks/im_ronald.asm @@ -0,0 +1,86 @@ +AIActionTable_ImRonald: ; 152bd (5:52bd) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 152c9 (5:52c9) + call AIMainTurnLogic + ret +; 0x152cd + +.start_duel ; 152cd (5:52cd) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x152de + +.forced_switch ; 152de (5:52de) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e2 + +.ko_switch ; 152e2 (5:52e2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x152e6 + +.take_prize ; 152e6 (5:52e6) + call AIPickPrizeCards + ret +; 0x152ea + +.list_arena ; 152ea (5:52ea) + db LAPRAS + db SEEL + db CHARMANDER + db CUBONE + db SQUIRTLE + db GROWLITHE + db $00 + +.list_bench ; 152f1 (5:52f1) + db CHARMANDER + db SQUIRTLE + db SEEL + db CUBONE + db GROWLITHE + db LAPRAS + db $00 + +.list_retreat ; 152f8 (5:52f8) + db $00 + +.list_energy ; 152f9 (5:52f9) + ai_energy CHARMANDER, 3, +0 + ai_energy CHARMELEON, 5, +0 + ai_energy GROWLITHE, 2, +0 + ai_energy ARCANINE2, 4, +0 + ai_energy SQUIRTLE, 2, +0 + ai_energy WARTORTLE, 3, +0 + ai_energy SEEL, 3, +0 + ai_energy DEWGONG, 4, +0 + ai_energy LAPRAS, 3, +0 + ai_energy CUBONE, 3, +0 + ai_energy MAROWAK1, 3, +0 + db $00 + +.list_prize ; 1531b (5:531b) + db LAPRAS + db $00 + +.store_list_pointers ; 1531d (5:531d) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x1534b diff --git a/src/engine/deck_ai/decks/invincible_ronald.asm b/src/engine/deck_ai/decks/invincible_ronald.asm new file mode 100644 index 0000000..0a55461 --- /dev/null +++ b/src/engine/deck_ai/decks/invincible_ronald.asm @@ -0,0 +1,84 @@ +AIActionTable_InvincibleRonald: ; 153e8 (5:53e8) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 153f4 (5:53f4) + call AIMainTurnLogic + ret +; 0x153f8 + +.start_duel ; 153f8 (5:53f8) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15409 + +.forced_switch ; 15409 (5:5409) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1540d + +.ko_switch ; 1540d (5:540d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15411 + +.take_prize ; 15411 (5:5411) + call AIPickPrizeCards + ret +; 0x15415 + +.list_arena ; 15415 (5:5415) + db KANGASKHAN + db MAGMAR2 + db CHANSEY + db GEODUDE + db SCYTHER + db GRIMER + db $00 + +.list_bench ; 1541c (5:541c) + db GRIMER + db SCYTHER + db GEODUDE + db CHANSEY + db MAGMAR2 + db KANGASKHAN + db $00 + +.list_retreat ; 15423 (5:5423) + ai_retreat GRIMER, -1 + db $00 + +.list_energy ; 15426 (5:5426) + ai_energy GRIMER, 1, -1 + ai_energy MUK, 3, -1 + ai_energy SCYTHER, 4, +1 + ai_energy MAGMAR2, 2, +0 + ai_energy GEODUDE, 2, +0 + ai_energy GRAVELER, 3, +0 + ai_energy CHANSEY, 4, +0 + ai_energy KANGASKHAN, 4, -1 + db $00 + +.list_prize ; 1543f (5:543f) + db GAMBLER + db $00 + +.store_list_pointers ; 15441 (5:5441) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x1546f diff --git a/src/engine/deck_ai/decks/legendary_articuno.asm b/src/engine/deck_ai/decks/legendary_articuno.asm new file mode 100644 index 0000000..183ab62 --- /dev/null +++ b/src/engine/deck_ai/decks/legendary_articuno.asm @@ -0,0 +1,217 @@ +AIActionTable_LegendaryArticuno: ; 14c0b (5:4c0b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14c17 (5:4c17) + call AIDoTurn_LegendaryArticuno + ret +; 0x14c1b + +.start_duel ; 14c1b (5:4c1b) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14c2c + +.forced_switch ; 14c2c (5:4c2c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c30 + +.ko_switch ; 14c30 (5:4c30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14c34 + +.take_prize ; 14c34 (5:4c34) + call AIPickPrizeCards + ret +; 0x14c38 + +.list_arena ; 14c38 (5:4c38) + db CHANSEY + db LAPRAS + db DITTO + db SEEL + db ARTICUNO1 + db ARTICUNO2 + db $00 + +.list_bench ; 14c3f (5:4c3f) + db ARTICUNO1 + db SEEL + db LAPRAS + db CHANSEY + db DITTO + db $00 + +.list_retreat ; 14c45 (5:4c45) + ai_retreat SEEL, -3 + ai_retreat DITTO, -3 + db $00 + +.list_energy ; 14c4a (5:4c4a) + ai_energy SEEL, 3, +1 + ai_energy DEWGONG, 4, +0 + ai_energy LAPRAS, 3, +0 + ai_energy ARTICUNO1, 4, +1 + ai_energy ARTICUNO2, 3, +0 + ai_energy CHANSEY, 0, -8 + ai_energy DITTO, 3, +0 + db $00 + +.list_prize ; 14c60 (5:4c60) + db GAMBLER + db ARTICUNO2 + db $00 + +.store_list_pointers ; 14c63 (5:4c63) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14c91 + +; this routine handles how Legendary Articuno +; prioritises playing energy cards to each Pokémon. +; first, it makes sure that all Lapras have at least +; 3 energy cards before moving on to Articuno, +; and then to Dewgong and Seel +ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) + call SwapTurn + call CountPrizes + call SwapTurn + cp 3 + ret c + +; player prizes >= 3 +; if Lapras has more than half HP and +; can use second move, check next for Articuno +; otherwise, check if Articuno or Dewgong +; have more than half HP and can use second move +; and if so, the next Pokémon to check is Lapras + ld a, LAPRAS + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .articuno + ld a, ARTICUNO1 + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .lapras + ld a, DEWGONG + call CheckForBenchIDAtHalfHPAndCanUseSecondMove + jr c, .lapras + jr .articuno + +; the following routines check for certain card IDs in bench +; and call RaiseAIScoreToAllMatchingIDsInBench if these are found. +; for Lapras, an additional check is made to its +; attached energy count, which skips calling the routine +; if this count is >= 3 +.lapras + ld a, LAPRAS + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .articuno + ld e, a + call CountNumberOfEnergyCardsAttached + cp 3 + jr nc, .articuno + ld a, LAPRAS + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.articuno + ld a, ARTICUNO1 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .dewgong + ld a, ARTICUNO1 + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.dewgong + ld a, DEWGONG + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + jr nc, .seel + ld a, DEWGONG + call RaiseAIScoreToAllMatchingIDsInBench + ret + +.seel + ld a, SEEL + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + ret nc + ld a, SEEL + call RaiseAIScoreToAllMatchingIDsInBench + ret +; 0x14cf7 + +AIDoTurn_LegendaryArticuno: ; 14cf7 (5:4cf7) +; initialize variables + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_1 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_1 +; play Pokemon from hand again + call AIDecidePlayPokemonCard +; process Trainer cards phases 13 and 15 + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards +; if used Professor Oak, process new hand + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c ; return if turn ended + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_2 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_2 + call AIDecidePlayPokemonCard +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if turn ended + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14d60 diff --git a/src/engine/deck_ai/decks/legendary_dragonite.asm b/src/engine/deck_ai/decks/legendary_dragonite.asm new file mode 100644 index 0000000..d320440 --- /dev/null +++ b/src/engine/deck_ai/decks/legendary_dragonite.asm @@ -0,0 +1,173 @@ +AIActionTable_LegendaryDragonite: ; 14d60 (05:4d60) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14d6c (5:4d6c) + call AIDoTurn_LegendaryDragonite + ret +; 0x14d70 + +.start_duel ; 14d70 (5:4d70) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14d81 + +.forced_switch ; 14d81 (5:4d81) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d85 + +.ko_switch ; 14d85 (5:4d85) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14d89 + +.take_prize ; 14d89 (5:4d89) + call AIPickPrizeCards + ret +; 0x14d8d + +.list_arena ; 14d8d (5:4d8d) + db KANGASKHAN + db LAPRAS + db CHARMANDER + db DRATINI + db MAGIKARP + db $00 + +.list_bench ; 14d93 (5:4d93) + db CHARMANDER + db MAGIKARP + db DRATINI + db LAPRAS + db KANGASKHAN + db $00 + +.list_retreat ; 14d99 (5:4d99) + ai_retreat CHARMANDER, -1 + ai_retreat MAGIKARP, -5 + db $00 + +.list_energy ; 14d9e (5:4d9e) + ai_energy CHARMANDER, 3, +1 + ai_energy CHARMELEON, 4, +1 + ai_energy CHARIZARD, 5, +0 + ai_energy MAGIKARP, 3, +1 + ai_energy GYARADOS, 4, -1 + ai_energy DRATINI, 2, +0 + ai_energy DRAGONAIR, 4, +0 + ai_energy DRAGONITE1, 3, -1 + ai_energy KANGASKHAN, 2, -2 + ai_energy LAPRAS, 3, +0 + db $00 + +.list_prize ; 14dbd (5:4dbd) + db GAMBLER + db DRAGONITE1 + db KANGASKHAN + db $00 + +.store_list_pointers ; 14dc1 (5:4dc1) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14def + +AIDoTurn_LegendaryDragonite: ; 14def (5:4def) +; initialize variables + call InitAITurnVars + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_1 + +; if Arena card is Kangaskhan and doens't +; have Energy cards attached, try attaching from hand. +; otherwise run normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, KANGASKHAN + cp e + jr nz, .attach_normally + call CreateEnergyCardListFromHand + jr c, .skip_energy_attach_1 + ld e, PLAY_AREA_ARENA + call CountNumberOfEnergyCardsAttached + or a + jr nz, .attach_normally + xor a + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .skip_energy_attach_1 +.attach_normally + call AIProcessAndTryToPlayEnergy + +.skip_energy_attach_1 +; play Pokemon from hand again + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_15 + call AIProcessHandTrainerCards +; if used Professor Oak, process new hand +; if not, then proceed to attack. + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach_2 + call AIProcessAndTryToPlayEnergy +.skip_energy_attach_2 + call AIDecidePlayPokemonCard +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if turn ended + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14e89 diff --git a/src/engine/deck_ai/decks/legendary_moltres.asm b/src/engine/deck_ai/decks/legendary_moltres.asm new file mode 100644 index 0000000..cb38668 --- /dev/null +++ b/src/engine/deck_ai/decks/legendary_moltres.asm @@ -0,0 +1,183 @@ +AIActionTable_LegendaryMoltres: ; 149e8 (05:49e8) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 149f4 (5:49f4) + call AIDoTurn_LegendaryMoltres + ret +; 0x149f8 + +.start_duel ; 149f8 (5:49f8) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc ; Play Area set up was successful + call AIPlayInitialBasicCards + ret +; 0x14a09 + +.forced_switch ; 14a09 (5:4a09) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a0d + +.ko_switch ; 14a0d (5:4a0d) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14a11 + +.take_prize ; 14a11 (5:4a11) + call AIPickPrizeCards + ret +; 0x14a15 + +.list_arena ; 14a15 (5:4a15) + db MAGMAR2 + db GROWLITHE + db VULPIX + db MAGMAR1 + db MOLTRES1 + db MOLTRES2 + db $00 + +.list_bench ; 14a1c (5:4a1c) + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +.list_play_hand ; 14a22 (5:4a22) + db MOLTRES2 + db MOLTRES1 + db VULPIX + db GROWLITHE + db MAGMAR2 + db MAGMAR1 + db $00 + +.list_retreat ; 14a29 (5:4a29) + ai_retreat GROWLITHE, -5 + ai_retreat VULPIX, -5 + db $00 + +.list_energy ; 14a2e (5:4a2e) + ai_energy VULPIX, 3, +0 + ai_energy NINETAILS2, 3, +1 + ai_energy GROWLITHE, 3, +1 + ai_energy ARCANINE2, 4, +1 + ai_energy MAGMAR1, 4, -1 + ai_energy MAGMAR2, 1, -1 + ai_energy MOLTRES2, 3, +2 + ai_energy MOLTRES1, 4, +2 + db $00 + +.list_prize ; 14a47 (5:4a47) + db ENERGY_REMOVAL + db MOLTRES2 + db $00 + +.store_list_pointers ; 14a4a (5:4a4a) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand + store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14a81 + +AIDoTurn_LegendaryMoltres: ; 14a81 (5:4a81) +; initialize variables + call InitAITurnVars + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; process Trainer cards +; phase 2 through 4. + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + +; check if AI can play Moltres2 +; from hand and if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 9 + jr nc, .skip_moltres ; skip if cards in deck <= 9 + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .skip_moltres ; skip if Muk in play + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank5 + jr nc, .skip_moltres ; skip if no Moltres2 in hand + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + +.skip_moltres +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_11 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_attach_energy + +; if Magmar2 is the Arena card and has no energy attached, +; try attaching an energy card to it from the hand. +; otherwise, run normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, MAGMAR2 + cp e + jr nz, .attach_normally + ; Magmar2 is the Arena card + call CreateEnergyCardListFromHand + jr c, .skip_attach_energy + ld e, PLAY_AREA_ARENA + call CountNumberOfEnergyCardsAttached + or a + jr nz, .attach_normally + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .skip_attach_energy + +.attach_normally +; play Energy card if possible + call AIProcessAndTryToPlayEnergy +.skip_attach_energy +; try playing Pokemon cards from hand again + call AIDecidePlayPokemonCard + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards + +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14b0f diff --git a/src/engine/deck_ai/decks/legendary_ronald.asm b/src/engine/deck_ai/decks/legendary_ronald.asm new file mode 100644 index 0000000..2721ba9 --- /dev/null +++ b/src/engine/deck_ai/decks/legendary_ronald.asm @@ -0,0 +1,210 @@ +AIActionTable_LegendaryRonald: ; 1546f (5:546f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 1547b (5:547b) + call AIDoTurn_LegendaryRonald + ret +; 0x1547f + +.start_duel ; 1547f (5:547f) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15490 + +.forced_switch ; 15490 (5:5490) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15494 + +.ko_switch ; 15494 (5:5494) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15498 + +.take_prize ; 15498 (5:5498) + call AIPickPrizeCards + ret +; 0x1549c + +.list_arena ; 1549c (5:549c) + db KANGASKHAN + db DRATINI + db EEVEE + db ZAPDOS3 + db ARTICUNO2 + db MOLTRES2 + db $00 + +.list_bench ; 154a3 (5:54a3) + db KANGASKHAN + db DRATINI + db EEVEE + db $00 + +.list_play_hand ; 154a7 (5:54a7) + db MOLTRES2 + db ZAPDOS3 + db KANGASKHAN + db DRATINI + db EEVEE + db ARTICUNO2 + db $00 + +.list_retreat ; 154ae (5:54ae) + ai_retreat EEVEE, -2 + db $00 + +.list_energy ; 154b1 (5:54b1) + ai_energy FLAREON1, 3, +0 + ai_energy MOLTRES2, 3, +0 + ai_energy VAPOREON1, 3, +0 + ai_energy ARTICUNO2, 0, -8 + ai_energy JOLTEON1, 4, +0 + ai_energy ZAPDOS3, 0, -8 + ai_energy KANGASKHAN, 4, -1 + ai_energy EEVEE, 3, +0 + ai_energy DRATINI, 3, +0 + ai_energy DRAGONAIR, 4, +0 + ai_energy DRAGONITE1, 3, +0 + db $00 + +.list_prize ; 154d3 (5:54d3) + db MOLTRES2 + db ARTICUNO2 + db ZAPDOS3 + db DRAGONITE1 + db GAMBLER + db $00 + +.store_list_pointers ; 154d9 (5:54d9) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_play_hand + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x15507 + +AIDoTurn_LegendaryRonald: ; 15507 (5:5507) +; initialize variables + call InitAITurnVars +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + +; check if AI can play Moltres2 +; from hand and if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres_1 ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 9 + jr nc, .skip_moltres_1 ; skip if cards in deck <= 9 + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .skip_moltres_1 ; skip if Muk in play + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank5 + jr nc, .skip_moltres_1 ; skip if no Moltres2 in hand + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + +.skip_moltres_1 +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards +; play Energy card if possible + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_attach_energy_1 + call AIProcessAndTryToPlayEnergy +.skip_attach_energy_1 +; try playing Pokemon cards from hand again + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_15 +; if used Professor Oak, process new hand +; if not, then proceed to attack. + call AIProcessHandTrainerCards + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK + jr z, .try_attack + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_02 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards + +; check if AI can play Moltres2 +; from hand and if so, play it. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .skip_moltres_2 ; skip if bench is full + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 9 + jr nc, .skip_moltres_2 ; skip if cards in deck <= 9 + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .skip_moltres_2 ; skip if Muk in play + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank5 + jr nc, .skip_moltres_2 ; skip if no Moltres2 in hand + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + +.skip_moltres_2 + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_05 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_attach_energy_2 + call AIProcessAndTryToPlayEnergy +.skip_attach_energy_2 + call AIDecidePlayPokemonCard + ret c ; return if turn ended +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if turn ended + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x155d2 diff --git a/src/engine/deck_ai/decks/legendary_zapdos.asm b/src/engine/deck_ai/decks/legendary_zapdos.asm new file mode 100644 index 0000000..cfa60be --- /dev/null +++ b/src/engine/deck_ai/decks/legendary_zapdos.asm @@ -0,0 +1,160 @@ +AIActionTable_LegendaryZapdos: ; 14b0f (05:4b0f) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14b1b (5:4b1b) + call AIDoTurn_LegendaryZapdos + ret +; 0x14b1f + +.start_duel ; 14b1f (5:4b1f) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14b30 + +.forced_switch ; 14b30 (5:4b30) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b34 + +.ko_switch ; 14b34 (5:4b34) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14b38 + +.take_prize ; 14b38 (5:4b38) + call AIPickPrizeCards + ret +; 0x14b3c + +.list_arena ; 14b3c (5:4b3c) + db ELECTABUZZ2 + db VOLTORB + db EEVEE + db ZAPDOS1 + db ZAPDOS2 + db ZAPDOS3 + db $00 + +.list_bench ; 14b43 (5:4b43) + db ZAPDOS2 + db ZAPDOS1 + db EEVEE + db VOLTORB + db ELECTABUZZ2 + db $00 + +.list_retreat ; 14b49 (5:4b49) + ai_retreat EEVEE, -5 + ai_retreat VOLTORB, -5 + ai_retreat ELECTABUZZ2, -5 + db $00 + +.list_energy ; 14b50 (5:4b50) + ai_energy VOLTORB, 1, -1 + ai_energy ELECTRODE1, 3, +0 + ai_energy ELECTABUZZ2, 2, -1 + ai_energy JOLTEON2, 3, +1 + ai_energy ZAPDOS1, 4, +2 + ai_energy ZAPDOS2, 4, +2 + ai_energy ZAPDOS3, 3, +1 + ai_energy EEVEE, 3, +0 + db $00 + +.list_prize ; 14b69 (5:4b69) + db GAMBLER + db ZAPDOS3 + db $00 + +.store_list_pointers ; 14b6c (5:4b6c) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14b9a + +AIDoTurn_LegendaryZapdos: ; 14b9a (5:4b9a) +; initialize variables + call InitAITurnVars + farcall HandleAIAntiMewtwoDeckStrategy + jp nc, .try_attack +; process Trainer cards + ld a, AI_TRAINER_CARD_PHASE_01 + call AIProcessHandTrainerCards + ld a, AI_TRAINER_CARD_PHASE_04 + call AIProcessHandTrainerCards +; play Pokemon from hand + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_07 + call AIProcessHandTrainerCards + call AIProcessRetreat + ld a, AI_TRAINER_CARD_PHASE_10 + call AIProcessHandTrainerCards +; play Energy card if possible. + ld a, [wAlreadyPlayedEnergy] + or a + jr nz, .skip_energy_attach + +; if Arena card is Voltorb and there's Electrode1 in hand, +; or if it's Electabuzz, try attaching Energy card +; to the Arena card if it doesn't have any energy attached. +; Otherwise if Energy card is not needed, +; go through normal AI energy attach routine. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, VOLTORB + cp e + jr nz, .check_electabuzz + ld a, ELECTRODE1 + call LookForCardIDInHandList_Bank5 + jr nc, .attach_normally + jr .voltorb_or_electabuzz +.check_electabuzz + ld a, ELECTABUZZ2 + cp e + jr nz, .attach_normally + +.voltorb_or_electabuzz + call CreateEnergyCardListFromHand + jr c, .skip_energy_attach + ld e, PLAY_AREA_ARENA + call CountNumberOfEnergyCardsAttached + or a + jr nz, .attach_normally + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call AITryToPlayEnergyCard + jr c, .skip_energy_attach + +.attach_normally + call AIProcessAndTryToPlayEnergy + +.skip_energy_attach +; play Pokemon from hand again + call AIDecidePlayPokemonCard + ret c ; return if turn ended + ld a, AI_TRAINER_CARD_PHASE_13 + call AIProcessHandTrainerCards +.try_attack +; attack if possible, if not, +; finish turn without attacking. + call AIProcessAndTryToUseAttack + ret c ; return if turn ended + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x14c0b diff --git a/src/engine/deck_ai/decks/powerful_ronald.asm b/src/engine/deck_ai/decks/powerful_ronald.asm new file mode 100644 index 0000000..d99f87f --- /dev/null +++ b/src/engine/deck_ai/decks/powerful_ronald.asm @@ -0,0 +1,98 @@ +AIActionTable_PowerfulRonald: ; 1534b (5:534b) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 15357 (5:5357) + call AIMainTurnLogic + ret +; 0x1535b + +.start_duel ; 1535b (5:535b) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1536c + +.forced_switch ; 1536c (5:536c) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15370 + +.ko_switch ; 15370 (5:5370) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15374 + +.take_prize ; 15374 (5:5374) + call AIPickPrizeCards + ret +; 0x15378 + +.list_arena ; 15378 (5:5378) + db KANGASKHAN + db ELECTABUZZ2 + db HITMONCHAN + db MR_MIME + db LICKITUNG + db HITMONLEE + db TAUROS + db JYNX + db MEWTWO1 + db DODUO + db $00 + +.list_bench ; 15383 (5:5383) + db KANGASKHAN + db HITMONLEE + db HITMONCHAN + db TAUROS + db DODUO + db JYNX + db MEWTWO1 + db ELECTABUZZ2 + db MR_MIME + db LICKITUNG + db $00 + +.list_retreat ; 1538e (5:538e) + ai_retreat KANGASKHAN, -1 + ai_retreat DODUO, -1 + ai_retreat DODRIO, -1 + db $00 + +.list_energy ; 15395 (5:5395) + ai_energy ELECTABUZZ2, 2, +1 + ai_energy HITMONLEE, 3, +1 + ai_energy HITMONCHAN, 3, +1 + ai_energy MR_MIME, 2, +0 + ai_energy JYNX, 3, +0 + ai_energy MEWTWO1, 2, +0 + ai_energy DODUO, 3, -1 + ai_energy DODRIO, 3, -1 + ai_energy LICKITUNG, 2, +0 + ai_energy KANGASKHAN, 4, -1 + ai_energy TAUROS, 3, +0 + db $00 + +.list_prize ; 153b7 (5:53b7) + db GAMBLER + db ENERGY_REMOVAL + db $00 + +.store_list_pointers ; 153ba (5:53ba) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x153e8 diff --git a/src/engine/deck_ai/decks/rock_crusher.asm b/src/engine/deck_ai/decks/rock_crusher.asm new file mode 100644 index 0000000..f4e79d8 --- /dev/null +++ b/src/engine/deck_ai/decks/rock_crusher.asm @@ -0,0 +1,80 @@ +AIActionTable_RockCrusher: ; 14f0e (5:4f0e) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 14f1a (5:4f1a) + call AIMainTurnLogic + ret +; 0x14f1e + +.start_duel ; 14f1e (5:4f1e) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x14f2f + +.forced_switch ; 14f2f (5:4f2f) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f33 + +.ko_switch ; 14f33 (5:4f33) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x14f37 + +.take_prize ; 14f37 (5:4f37) + call AIPickPrizeCards + ret +; 0x14f3b + +.list_arena ; 14f3b (5:4f3b) + db RHYHORN + db ONIX + db GEODUDE + db DIGLETT + db $00 + +.list_bench ; 14f40 (5:4f40) + db DIGLETT + db GEODUDE + db RHYHORN + db ONIX + db $00 + +.list_retreat ; 14f45 (5:4f45) + ai_retreat DIGLETT, -1 + db $00 + +.list_energy ; 14f48 (5:4f48) + ai_energy DIGLETT, 3, +1 + ai_energy DUGTRIO, 4, +0 + ai_energy GEODUDE, 2, +1 + ai_energy GRAVELER, 3, +0 + ai_energy GOLEM, 4, +0 + ai_energy ONIX, 2, -1 + ai_energy RHYHORN, 3, +0 + db $00 + +.list_prize ; 14f5e (5:4f5e) + db ENERGY_REMOVAL + db RHYHORN + db $00 + +.store_list_pointers ; 14f61 (5:4f61) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x14f8f diff --git a/src/engine/deck_ai/decks/sams_practice.asm b/src/engine/deck_ai/decks/sams_practice.asm new file mode 100644 index 0000000..2ce0060 --- /dev/null +++ b/src/engine/deck_ai/decks/sams_practice.asm @@ -0,0 +1,222 @@ +; AI for Sam's practice duel, which handles his scripted actions. +; will act as a normal duelist AI after turn 7. +AIActionTable_SamPractice: ; 147bd (05:47bd) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 147c9 (5:47c9) + call IsAIPracticeScriptedTurn + jr nc, .scripted_1 +; not scripted, use AI main turn logic + call AIMainTurnLogic + ret +.scripted_1 ; use scripted actions instead + call AIPerformSciptedTurn + ret +; 0x147d6 + +.start_duel ; 147d6 (5:47d6) + call SetSamsStartingPlayArea + ret +; 0x147da + +.forced_switch ; 147da (5:47da) + call IsAIPracticeScriptedTurn + jr nc, .scripted_2 + call AIDecideBenchPokemonToSwitchTo + ret +.scripted_2 + call PickRandomBenchPokemon + ret +; 0x147e7 + +.ko_switch: ; 147e7 (5:47e7) + call IsAIPracticeScriptedTurn + jr nc, .scripted_3 + call AIDecideBenchPokemonToSwitchTo + ret +.scripted_3 + call GetPlayAreaLocationOfRaticateOrRattata + ret +; 0x147f4 + +.take_prize: ; 147f4 (5:47f4) + call AIPickPrizeCards + ret +; 0x147f8 + +; returns carry if number of turns +; the AI has taken >= 7. +; used to know whether AI Sam is still +; doing scripted turns. +IsAIPracticeScriptedTurn: ; 147f8 (5:47f8) + ld a, [wDuelTurns] + srl a + cp 7 + ccf + ret +; 0x14801 + +; places one Machop from the hand to the Play Area +; and sets the number of prizes to 2. +SetSamsStartingPlayArea: ; 14801 (5:4801) + call CreateHandCardList + ld hl, wDuelTempList +.loop_hand + ld a, [hli] + ldh [hTempCardIndex_ff98], a + cp $ff + ret z + call LoadCardDataToBuffer1_FromDeckIndex + cp MACHOP + jr nz, .loop_hand + ldh a, [hTempCardIndex_ff98] + call PutHandPokemonCardInPlayArea + ld a, 2 + ld [wDuelInitialPrizes], a + ret +; 0x1481f + +; outputs in a Play Area location of Raticate or Rattata +; in the Bench. If neither is found, just output PLAY_AREA_BENCH_1. +GetPlayAreaLocationOfRaticateOrRattata: ; 1481f (5:481f) + ld a, RATICATE + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + cp $ff + jr nz, .found + ld a, RATTATA + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank5 + cp $ff + jr nz, .found + ld a, PLAY_AREA_BENCH_1 +.found + ldh [hTempPlayAreaLocation_ff9d], a + ret +; 0x1483a + +; has AI execute some scripted actions depending on Duel turn. +AIPerformSciptedTurn: ; 1483a (5:483a) + ld a, [wDuelTurns] + srl a + ld hl, .scripted_actions_list + call JumpToFunctionInTable + +; always attack with Arena card's first attack. +; if it's unusable end turn without attacking. + xor a + ldh [hTempPlayAreaLocation_ff9d], a + ld [wSelectedAttack], a + call CheckIfSelectedMoveIsUnusable + jr c, .unusable + call AITryUseAttack + ret + +.unusable + ld a, OPPACTION_FINISH_NO_ATTACK + bank1call AIMakeDecision + ret +; 0x1485a + +.scripted_actions_list ; 1485a (05:485a) + dw .turn_1 + dw .turn_2 + dw .turn_3 + dw .turn_4 + dw .turn_5 + dw .turn_6 + dw .turn_7 +; 0x14868 + +.turn_1 ; 14868 (5:4868) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x14870 + +.turn_2 ; 14870 (5:4870) + ld a, RATTATA + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + ld d, RATTATA + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x14884 + +.turn_3 ; 14884 (5:4884) + ld a, RATTATA + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank5 + ldh [hTempPlayAreaLocation_ffa1], a + ld a, RATICATE + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_EVOLVE_PKMN + bank1call AIMakeDecision + ld d, RATICATE + ld e, LIGHTNING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148a1 + +.turn_4 ; 148a1 (5:48a1) + ld d, RATICATE + ld e, LIGHTNING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148a9 + +.turn_5 ; 148a9 (5:48a9) + ld a, MACHOP + call LookForCardIDInHandList_Bank5 + ldh [hTemp_ffa0], a + ld a, OPPACTION_PLAY_BASIC_PKMN + bank1call AIMakeDecision + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInBench + +; this is a bug, it's attempting to compare a card ID with a deck index. +; the intention was to change the card to switch to depending on whether +; the first Machop was KO'd at this point in the Duel or not. +; because of the buggy comparison, this will always jump the +; 'inc a' instruction and switch to PLAY_AREA_BENCH_1. +; in a normal Practice Duel following Dr. Mason's instructions, +; this will always lead to the AI correctly switching Raticate with Machop, +; but in case of a "Free" Duel where the first Machop is not KO'd, +; the intention was to switch to PLAY_AREA_BENCH_2 instead. +; but due to 'inc a' always being skipped, it will switch to Raticate. + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + cp MACHOP ; wrong + ld a, PLAY_AREA_BENCH_1 + jr nz, .retreat + inc a ; PLAY_AREA_BENCH_2 + +.retreat + call AITryToRetreat + ret +; 0x148cc + +.turn_6 ; 148cc (5:48cc) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148d4 + +.turn_7 ; 148d4 (5:48d4) + ld d, MACHOP + ld e, FIGHTING_ENERGY + call AIAttachEnergyInHandToCardInPlayArea + ret +; 0x148dc diff --git a/src/engine/deck_ai/decks/strange_psyshock.asm b/src/engine/deck_ai/decks/strange_psyshock.asm new file mode 100644 index 0000000..309ef11 --- /dev/null +++ b/src/engine/deck_ai/decks/strange_psyshock.asm @@ -0,0 +1,87 @@ +AIActionTable_StrangePsyshock: ; 15122 (5:5122) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 1512e (5:512e) + call AIMainTurnLogic + ret +; 0x15132 + +.start_duel ; 15132 (5:5132) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x15143 + +.forced_switch ; 15143 (5:5143) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15147 + +.ko_switch ; 15147 (5:5147) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1514b + +.take_prize ; 1514b (5:514b) + call AIPickPrizeCards + ret +; 0x1514f + +.list_arena ; 1514f (5:514f) + db KANGASKHAN + db CHANSEY + db SNORLAX + db MR_MIME + db ABRA + db $00 + +.list_bench ; 15155 (5:5155) + db ABRA + db MR_MIME + db KANGASKHAN + db SNORLAX + db CHANSEY + db $00 + +.list_retreat ; 1515b (5:515b) + ai_retreat ABRA, -3 + ai_retreat SNORLAX, -3 + ai_retreat KANGASKHAN, -1 + ai_retreat CHANSEY, -1 + db $00 + +.list_energy ; 15164 (5:5164) + ai_energy ABRA, 3, +1 + ai_energy KADABRA, 3, +0 + ai_energy ALAKAZAM, 3, +0 + ai_energy MR_MIME, 2, +0 + ai_energy CHANSEY, 2, -2 + ai_energy KANGASKHAN, 4, -2 + ai_energy SNORLAX, 0, -8 + db $00 + +.list_prize ; 1517a (5:517a) + db GAMBLER + db MR_MIME + db ALAKAZAM + db SWITCH + db $00 + +.store_list_pointers ; 1517f (5:517f) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x151ad diff --git a/src/engine/deck_ai/decks/wonders_of_science.asm b/src/engine/deck_ai/decks/wonders_of_science.asm new file mode 100644 index 0000000..e11a829 --- /dev/null +++ b/src/engine/deck_ai/decks/wonders_of_science.asm @@ -0,0 +1,83 @@ +AIActionTable_WondersOfScience: ; 151ad (5:51ad) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 151b9 (5:51b9) + call AIMainTurnLogic + ret +; 0x151bd + +.start_duel ; 151bd (5:51bd) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x151ce + +.forced_switch ; 151ce (5:51ce) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d2 + +.ko_switch ; 151d2 (5:51d2) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x151d6 + +.take_prize ; 151d6 (5:51d6) + call AIPickPrizeCards + ret +; 0x151da + +.list_arena ; 151da (5:51da) + db MEWTWO1 + db MEWTWO3 + db MEWTWO2 + db GRIMER + db KOFFING + db PORYGON + db $00 + +.list_bench ; 151e1 (5:51e1) + db GRIMER + db KOFFING + db MEWTWO3 + db MEWTWO2 + db MEWTWO1 + db PORYGON + db $00 + +.list_retreat ; 151e8 (5:51e8) + db $00 + +.list_energy ; 151e9 (5:51e9) + ai_energy GRIMER, 3, +0 + ai_energy MUK, 4, +0 + ai_energy KOFFING, 2, +0 + ai_energy WEEZING, 3, +0 + ai_energy MEWTWO1, 2, -1 + ai_energy MEWTWO3, 2, -1 + ai_energy MEWTWO2, 2, -1 + ai_energy PORYGON, 2, -1 + db $00 + +.list_prize ; 15202 (5:5202) + db MUK + db $00 + +.store_list_pointers ; 15204 (5:5204) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x15232 diff --git a/src/engine/deck_ai/decks/zapping_selfdestruct.asm b/src/engine/deck_ai/decks/zapping_selfdestruct.asm new file mode 100644 index 0000000..6675c52 --- /dev/null +++ b/src/engine/deck_ai/decks/zapping_selfdestruct.asm @@ -0,0 +1,81 @@ +AIActionTable_ZappingSelfdestruct: ; 15019 (5:5019) + dw .do_turn ; unused + dw .do_turn + dw .start_duel + dw .forced_switch + dw .ko_switch + dw .take_prize + +.do_turn ; 15025 (5:5025) + call AIMainTurnLogic + ret +; 0x15029 + +.start_duel ; 15029 (5:5029) + call InitAIDuelVars + call .store_list_pointers + call SetUpBossStartingHandAndDeck + call TrySetUpBossStartingPlayArea + ret nc + call AIPlayInitialBasicCards + ret +; 0x1503a + +.forced_switch ; 1503a (5:503a) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x1503e + +.ko_switch ; 1503e (5:503e) + call AIDecideBenchPokemonToSwitchTo + ret +; 0x15042 + +.take_prize ; 15042 (5:5042) + call AIPickPrizeCards + ret +; 0x15046 + +.list_arena ; 15046 (5:5046) + db KANGASKHAN + db ELECTABUZZ2 + db TAUROS + db MAGNEMITE1 + db VOLTORB + db $00 + +.list_bench ; 1504c (5:504c) + db MAGNEMITE1 + db VOLTORB + db ELECTABUZZ2 + db TAUROS + db KANGASKHAN + db $00 + +.list_retreat ; 15052 (5:5052) + ai_retreat VOLTORB, -1 + db $00 + +.list_energy ; 15055 (5:5055) + ai_energy MAGNEMITE1, 3, +1 + ai_energy MAGNETON1, 4, +0 + ai_energy VOLTORB, 3, +1 + ai_energy ELECTRODE1, 3, +0 + ai_energy ELECTABUZZ2, 1, +0 + ai_energy KANGASKHAN, 2, -2 + ai_energy TAUROS, 3, +0 + db $00 + +.list_prize ; 1506b (5:506b) + db KANGASKHAN + db $00 + +.store_list_pointers ; 1506d (5:506d) + store_list_pointer wAICardListAvoidPrize, .list_prize + store_list_pointer wAICardListArenaPriority, .list_arena + store_list_pointer wAICardListBenchPriority, .list_bench + store_list_pointer wAICardListPlayFromHandPriority, .list_bench + ; missing store_list_pointer wAICardListRetreatBonus, .list_retreat + store_list_pointer wAICardListEnergyBonus, .list_energy + ret +; 0x1509b -- cgit v1.2.3 From 86d8cfb0fd86326e4534fc33c7bb384d515bbe0e Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Sat, 9 May 2020 12:11:05 +0100 Subject: Separate AI constants and new AIACTION_* --- src/constants.asm | 1 + src/constants/deck_ai_constants.asm | 61 +++++++++++++++++++++++++++++++++++++ src/constants/duel_constants.asm | 53 -------------------------------- src/data/deck_ai_pointers.asm | 2 +- src/engine/bank01.asm | 8 ++--- src/engine/deck_ai/deck_ai.asm | 1 + src/engine/effect_functions.asm | 2 +- src/engine/home.asm | 40 +++++++++++++----------- 8 files changed, 91 insertions(+), 77 deletions(-) create mode 100644 src/constants/deck_ai_constants.asm (limited to 'src') diff --git a/src/constants.asm b/src/constants.asm index 4e6f410..6e6f0b3 100644 --- a/src/constants.asm +++ b/src/constants.asm @@ -1,6 +1,7 @@ INCLUDE "constants/booster_constants.asm" INCLUDE "constants/card_constants.asm" INCLUDE "constants/card_data_constants.asm" +INCLUDE "constants/deck_ai_constants.asm" INCLUDE "constants/deck_constants.asm" INCLUDE "constants/duel_constants.asm" INCLUDE "constants/duel_interface_constants.asm" diff --git a/src/constants/deck_ai_constants.asm b/src/constants/deck_ai_constants.asm new file mode 100644 index 0000000..ceae8ed --- /dev/null +++ b/src/constants/deck_ai_constants.asm @@ -0,0 +1,61 @@ +; wPreviousAIFlags and wCurrentAIFlags constants +AI_FLAG_USED_PLUSPOWER EQU 1 << 0 +AI_FLAG_USED_SWITCH EQU 1 << 1 +AI_FLAG_USED_PROFESSOR_OAK EQU 1 << 2 +AI_FLAG_MODIFIED_HAND EQU 1 << 3 +AI_FLAG_USED_GUST_OF_WIND EQU 1 << 4 + +; used as input for AIProcessEnergyCards to determine what to check +; and whether to play card after the routine is over. +; I suspect AI_ENERGY_FLAG_DONT_PLAY to be a flag to signal the routine +; not to actually play the energy card after it's finished, +; but AIProcessEnergyCards checks whether ANY flag is set in order +; to decide not to play it, so it's redundant in the presence of another flag. +AI_ENERGY_FLAG_DONT_PLAY EQU 1 << 0 ; whether to play energy card (?) +AI_ENERGY_FLAG_SKIP_EVOLUTION EQU 1 << 1 ; whether to check if card has evolutions +AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in determining which card to attach energy + +; used to determine which Trainer cards for AI +; to process in AIProcessHandTrainerCards. +; these go in chronological order, except for +; AI_TRAINER_CARD_PHASE_14 which happens just before AI attacks. +; AI_TRAINER_CARD_PHASE_15 is reserved for Professor Oak card. +; if Professor Oak is played, all other Trainer card phases +; are processed again except AI_TRAINER_CARD_PHASE_15. + const_def 1 + const AI_TRAINER_CARD_PHASE_01 ; $1 + const AI_TRAINER_CARD_PHASE_02 ; $2 + const AI_TRAINER_CARD_PHASE_03 ; $3 + const AI_TRAINER_CARD_PHASE_04 ; $4 + const AI_TRAINER_CARD_PHASE_05 ; $5 + const AI_TRAINER_CARD_PHASE_06 ; $6 + const AI_TRAINER_CARD_PHASE_07 ; $7 + const AI_TRAINER_CARD_PHASE_08 ; $8 + const AI_TRAINER_CARD_PHASE_09 ; $9 + const AI_TRAINER_CARD_PHASE_10 ; $a + const AI_TRAINER_CARD_PHASE_11 ; $b + const AI_TRAINER_CARD_PHASE_12 ; $c + const AI_TRAINER_CARD_PHASE_13 ; $d + const AI_TRAINER_CARD_PHASE_14 ; $e, just before attack + const AI_TRAINER_CARD_PHASE_15 ; $f, for Professor Oak + +; used by wAIBarrierFlagCounter to determine +; whether Player is running Mewtwo1 mill deck. +; flag set means true, flag not set means false. +AI_FLAG_MEWTWO_MILL EQU 1 << 7 + +; defines the behaviour of HandleAIEnergyTrans, for determining +; whether to move energy cards from the Bench to the Arena or vice-versa +; and the number of energy cards needed for achieving that. +AI_ENERGY_TRANS_RETREAT EQU $9 ; moves energy cards needed for Retreat Cost +AI_ENERGY_TRANS_ATTACK EQU $d ; moves energy cards needed for second attack +AI_ENERGY_TRANS_TO_BENCH EQU $e ; moves energy cards away from Arena card + +; used to know which AI routine to call in +; the AIAction pointer tables in AIDoAction + const_def 1 + const AIACTION_DO_TURN ; $1 + const AIACTION_START_DUEL ; $2 + const AIACTION_FORCED_SWITCH ; $3 + const AIACTION_KO_SWITCH ; $4 + const AIACTION_TAKE_PRIZE ; $5 diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index dd692d0..d461d24 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -226,56 +226,3 @@ EFFECT_FAILED_UNSUCCESSFUL EQU $02 ; wAnimationQueue length ANIMATION_QUEUE_LENGTH EQU 7 - -; wPreviousAIFlags and wCurrentAIFlags constants -AI_FLAG_USED_PLUSPOWER EQU 1 << 0 -AI_FLAG_USED_SWITCH EQU 1 << 1 -AI_FLAG_USED_PROFESSOR_OAK EQU 1 << 2 -AI_FLAG_MODIFIED_HAND EQU 1 << 3 -AI_FLAG_USED_GUST_OF_WIND EQU 1 << 4 - -; used as input for AIProcessEnergyCards to determine what to check -; and whether to play card after the routine is over. -; I suspect AI_ENERGY_FLAG_DONT_PLAY to be a flag to signal the routine -; not to actually play the energy card after it's finished, -; but AIProcessEnergyCards checks whether ANY flag is set in order -; to decide not to play it, so it's redundant in the presence of another flag. -AI_ENERGY_FLAG_DONT_PLAY EQU 1 << 0 ; whether to play energy card (?) -AI_ENERGY_FLAG_SKIP_EVOLUTION EQU 1 << 1 ; whether to check if card has evolutions -AI_ENERGY_FLAG_SKIP_ARENA_CARD EQU 1 << 7 ; whether to include Arena card in determining which card to attach energy - -; used to determine which Trainer cards for AI -; to process in AIProcessHandTrainerCards. -; these go in chronological order, except for -; AI_TRAINER_CARD_PHASE_14 which happens just before AI attacks. -; AI_TRAINER_CARD_PHASE_15 is reserved for Professor Oak card. -; if Professor Oak is played, all other Trainer card phases -; are processed again except AI_TRAINER_CARD_PHASE_15. - const_def 1 - const AI_TRAINER_CARD_PHASE_01 ; $1 - const AI_TRAINER_CARD_PHASE_02 ; $2 - const AI_TRAINER_CARD_PHASE_03 ; $3 - const AI_TRAINER_CARD_PHASE_04 ; $4 - const AI_TRAINER_CARD_PHASE_05 ; $5 - const AI_TRAINER_CARD_PHASE_06 ; $6 - const AI_TRAINER_CARD_PHASE_07 ; $7 - const AI_TRAINER_CARD_PHASE_08 ; $8 - const AI_TRAINER_CARD_PHASE_09 ; $9 - const AI_TRAINER_CARD_PHASE_10 ; $a - const AI_TRAINER_CARD_PHASE_11 ; $b - const AI_TRAINER_CARD_PHASE_12 ; $c - const AI_TRAINER_CARD_PHASE_13 ; $d - const AI_TRAINER_CARD_PHASE_14 ; $e, just before attack - const AI_TRAINER_CARD_PHASE_15 ; $f, for Professor Oak - -; used by wAIBarrierFlagCounter to determine -; whether Player is running Mewtwo1 mill deck. -; flag set means true, flag not set means false. -AI_FLAG_MEWTWO_MILL EQU 1 << 7 - -; defines the behaviour of HandleAIEnergyTrans, for determining -; whether to move energy cards from the Bench to the Arena or vice-versa -; and the number of energy cards needed for achieving that. -AI_ENERGY_TRANS_RETREAT EQU $9 ; moves energy cards needed for Retreat Cost -AI_ENERGY_TRANS_ATTACK EQU $d ; moves energy cards needed for second attack -AI_ENERGY_TRANS_TO_BENCH EQU $e ; moves energy cards away from Arena card diff --git a/src/data/deck_ai_pointers.asm b/src/data/deck_ai_pointers.asm index 72cbfb0..4f00299 100644 --- a/src/data/deck_ai_pointers.asm +++ b/src/data/deck_ai_pointers.asm @@ -1,4 +1,4 @@ -PointerTable_14000: ; 14000 (05:4000) +DeckAIPointerTable: ; 14000 (05:4000) dw AIActionTable_SamPractice ; SAMS_PRACTICE_DECK dw AIActionTable_GeneralDecks ; PRACTICE_PLAYER_DECK dw AIActionTable_GeneralDecks ; SAMS_NORMAL_DECK diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index 7eb7340..8f780eb 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -353,7 +353,7 @@ DuelMainInterface: ; 426d (1:426d) ld [wSkipDuelistIsThinkingDelay], a ldtx hl, DuelistIsThinkingText call DrawWideTextBox_PrintTextNoDelay - call Func_2bbf + call AIDoAction_Turn ld a, $ff ld [wPlayerAttackingCardIndex], a ld [wPlayerAttackingMoveIndex], a @@ -1967,7 +1967,7 @@ ChooseInitialArenaAndBenchPokemon: ; 4cd5 (1:4cd5) ; AI opponent's turn push af push hl - call Func_2bc3 + call AIDoAction_StartDuel pop hl pop af ld [hl], a @@ -3757,7 +3757,7 @@ Func_5805: ; 5805 (1:5805) call GetTurnDuelistVariable cp DUELIST_TYPE_LINK_OPP jr z, .link_opponent - call Func_2bd7 + call AIDoAction_TakePrize ld c, DECK_SIZE .asm_5858 call DoFrame @@ -7492,7 +7492,7 @@ ReplaceKnockedOutPokemon: ; 6f23 (1:6f23) .opponent cp DUELIST_TYPE_LINK_OPP jr z, .link_opponent - call Func_2bcf + call AIDoAction_KOSwitch ldh a, [hTemp_ffa0] ldh [hTempPlayAreaLocation_ff9d], a jr .replace_pokemon diff --git a/src/engine/deck_ai/deck_ai.asm b/src/engine/deck_ai/deck_ai.asm index a906472..c8b73f3 100644 --- a/src/engine/deck_ai/deck_ai.asm +++ b/src/engine/deck_ai/deck_ai.asm @@ -33,6 +33,7 @@ ENDM ; deck AIs are specialized to work on a given deck ID. ; they decide what happens during a turn, what Pokemon cards ; to pick during the start of the duel, etc. +; the different scenarios these are used are listed in AIACTION_* constants. ; each of these have a pointer table with the following structure: ; dw .do_turn : never called; ; diff --git a/src/engine/effect_functions.asm b/src/engine/effect_functions.asm index 762e82d..75b0f76 100644 --- a/src/engine/effect_functions.asm +++ b/src/engine/effect_functions.asm @@ -437,7 +437,7 @@ DuelistSelectForcedSwitch: ; 2c487 (b:4487) ; AI opponent call SwapTurn - bank1call Func_2bc7 + bank1call AIDoAction_ForcedSwitch call SwapTurn ld a, [wPlayerAttackingMoveIndex] diff --git a/src/engine/home.asm b/src/engine/home.asm index c56e0c6..a9d28d6 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -8280,37 +8280,41 @@ LoadOpponentDeck: ; 2b78 (0:2b78) ld [hl], a ret -Func_2bbf: ; 2bbf (0:2bbf) - ld a, $1 - jr Func_2bdb +AIDoAction_Turn: ; 2bbf (0:2bbf) + ld a, AIACTION_DO_TURN + jr AIDoAction -Func_2bc3: ; 2bc3 (0:2bc3) - ld a, $2 - jr Func_2bdb +AIDoAction_StartDuel: ; 2bc3 (0:2bc3) + ld a, AIACTION_START_DUEL + jr AIDoAction -Func_2bc7: ; 2bc7 (0:2bc7) - ld a, $3 - call Func_2bdb +AIDoAction_ForcedSwitch: ; 2bc7 (0:2bc7) + ld a, AIACTION_FORCED_SWITCH + call AIDoAction ldh [hTempPlayAreaLocation_ff9d], a ret -Func_2bcf: ; 2bcf (0:2bcf) - ld a, $4 - call Func_2bdb +AIDoAction_KOSwitch: ; 2bcf (0:2bcf) + ld a, AIACTION_KO_SWITCH + call AIDoAction ldh [hTemp_ffa0], a ret -Func_2bd7: ; 2bd7 (0:2bd7) - ld a, $5 - jr Func_2bdb ; this line is not needed +AIDoAction_TakePrize: ; 2bd7 (0:2bd7) + ld a, AIACTION_TAKE_PRIZE + jr AIDoAction ; this line is not needed -Func_2bdb: ; 2bdb (0:2bdb) +; calls the appropriate AI routine to handle action, +; depending on the deck ID (see engine/deck_ai/deck_ai.asm) +; input: +; - a = AIACTION_* constant +AIDoAction: ; 2bdb (0:2bdb) ld c, a ; load bank for Opponent Deck pointer table ldh a, [hBankROM] push af - ld a, BANK(PointerTable_14000) + ld a, BANK(DeckAIPointerTable) call BankswitchROM ; load hl with the corresponding pointer @@ -8318,7 +8322,7 @@ Func_2bdb: ; 2bdb (0:2bdb) ld l, a ld h, $0 add hl, hl ; two bytes per deck - ld de, PointerTable_14000 + ld de, DeckAIPointerTable add hl, de ld a, [hli] ld h, [hl] -- cgit v1.2.3