From 3d8c853f38eb4c9c782c7984bb9905fa76dbf625 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 20 Sep 2019 00:08:55 +0100 Subject: Document Pluspower AI routines --- src/engine/bank08.asm | 138 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 103 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 48ed23f..d2e0d9c 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -12,8 +12,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0b, SUPER_POTION, FindTargetCardForSuperPotion, AIPlaySuperPotion unknown_data_20000 $0d, DEFENDER, CheckIfDefenderPreventsKnockOut, AIPlayDefender unknown_data_20000 $0e, DEFENDER, CheckIfDefenderPreventsRecoilKnockOut, AIPlayDefender - unknown_data_20000 $0d, PLUSPOWER, $4501, AIPlayPluspower - unknown_data_20000 $0e, PLUSPOWER, $45a5, AIPlayPluspower + unknown_data_20000 $0d, PLUSPOWER, CheckIfPluspowerBoostCausesKnockOut, AIPlayPluspower + unknown_data_20000 $0e, PLUSPOWER, CheckIfSelectedMoveCannotKnockOutWithoutPluspowerBoost, AIPlayPluspower unknown_data_20000 $09, SWITCH, $462e, $4612 unknown_data_20000 $07, GUST_OF_WIND, $467e, $4666 unknown_data_20000 $0a, GUST_OF_WIND, $467e, $4666 @@ -808,7 +808,9 @@ AIPlayPluspower: ; 204e8 (8:44e8) ret ; 0x20501 -Func_20501: ; 20501 (8:4501) +; returns carry if using a Pluspower can KO defending Pokémon +; if active card cannot KO without the boost. +CheckIfPluspowerBoostCausesKnockOut: ; 20501 (8:4501) ; this is mistakenly duplicated xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -848,33 +850,41 @@ Func_20501: ; 20501 (8:4501) call SwapTurn jr c, .no_carry +; check both attacks and decide which one +; can KO with Pluspower boost. +; if neither can KO, return no carry. xor a ; first attack ld [wSelectedMoveIndex], a - call .asm_20562 - jr c, .asm_20551 + call .check_ko_with_pluspower + jr c, .kos_with_pluspower_1 ld a, $01 ; second attack ld [wSelectedMoveIndex], a - call .asm_20562 - jr c, .asm_20559 + call .check_ko_with_pluspower + jr c, .kos_with_pluspower_2 .no_carry or a ret -.asm_20551 - call .asm_20589 + +; first attack can KO with Pluspower. +.kos_with_pluspower_1 + call .check_mr_mime jr nc, .no_carry xor a ; first attack scf ret -.asm_20559 - call .asm_20589 +; second attack can KO with Pluspower. +.kos_with_pluspower_2 + call .check_mr_mime jr nc, .no_carry - ld a, $01 ; first attack + ld a, $01 ; second attack scf ret ; 0x20562 -.asm_20562 ; 20562 (8:4562) +; return carry if move is useable and KOs +; defending Pokémon with Pluspower boost. +.check_ko_with_pluspower ; 20562 (8:4562) farcall CheckIfSelectedMoveIsUnusable jr c, .unusable ld a, [wSelectedMoveIndex] @@ -887,23 +897,25 @@ Func_20501: ; 20501 (8:4501) jr c, .no_carry jr z, .no_carry ld a, [hl] - add 10 + add 10 ; add Pluspower boost ld c, a ld a, b sub c - ret c - ret nz + ret c ; return carry if damage > HP left + ret nz ; does not KO scf - ret + ret ; KOs with Pluspower boost .unusable or a ret ; 0x20589 -.asm_20589 ; 20589 (8:4589) +; returns carry if Pluspower boost does +; not exceed 30 damage when facing Mr. Mime. +.check_mr_mime ; 20589 (8:4589) ld a, [wDamage] - add 10 - cp 30 + add 10 ; add Pluspower boost + cp 30 ; no danger in preventing damage ret c call SwapTurn ld a, DUELVARS_ARENA_CARD @@ -911,36 +923,92 @@ Func_20501: ; 20501 (8:4501) call GetCardIDFromDeckIndex call SwapTurn ld a, e - cp $9b + cp MR_MIME ret z +; damage is >= 30 but not Mr. Mime scf ret ; 0x205a5 -Func_205a5: ; 205a5 (8:45a5) +; returns carry 7/10 of the time +; if selected move is useable, can't KO without Pluspower boost +; can damage Mr. Mime even with Pluspower boost; +; and has a minimum damage > 0. +CheckIfSelectedMoveCannotKnockOutWithoutPluspowerBoost: ; 205a5 (8:45a5) xor a ldh [hTempPlayAreaLocation_ff9d], a - call Func_205d7 - jr nc, .asm_205b9 - call Func_205f6 - jr nc, .asm_205b9 - call Func_205bb - jr nc, .asm_205b9 + call .check_can_ko + jr nc, .no_carry + call .check_random + jr nc, .no_carry + call .check_mr_mime + jr nc, .no_carry scf ret -.asm_205b9 +.no_carry or a ret ; 0x205bb -Func_205bb: ; 205bb (8:45bb) - INCROM $205bb, $205d7 +; returns carry if Pluspower boost does +; not exceed 30 damage when facing Mr. Mime. +.check_mr_mime ; 205bb (8:45bb) + ld a, [wDamage] + add 10 ; add Pluspower boost + cp 30 ; no danger in preventing damage + ret c + call SwapTurn + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + call SwapTurn + ld a, e + cp MR_MIME + ret z +; damage is >= 30 but not Mr. Mime + scf + ret +; 0x205d7 -Func_205d7: ; 205d7 (8:45d7) - INCROM $205d7, $205f6 +; return carry if move is useable but cannot KO. +.check_can_ko ; 205d7 (8:45d7) + farcall CheckIfSelectedMoveIsUnusable + jr c, .unuseable + ld a, [wSelectedMoveIndex] + farcall EstimateDamage_VersusDefendingCard + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + ld b, a + ld hl, wDamage + sub [hl] + jr c, .no_carry + jr z, .no_carry +; can't KO. + scf + ret +.unuseable + or a + ret +; 0x205f6 + +; return carry 7/10 of the time if +; move is useable and minimum damage > 0. +.check_random ; 205f6 (8:45f6) + farcall CheckIfSelectedMoveIsUnusable + jr c, .unuseable + ld a, [wSelectedMoveIndex] + farcall EstimateDamage_VersusDefendingCard + ld a, [wAIMinDamage] + cp 10 + jr c, .unuseable + ld a, 10 + call Random + cp 3 + ret +; 0x20612 -Func_205f6: ; 205f6 (8:45f6) - INCROM $205f6, $2282e +Func_20612: ; 20612 (8:4612) + INCROM $20612, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, -- cgit v1.2.3 From a4ee5f64029e3c6dfc0a890aa0ac1b727127301b Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Mon, 30 Dec 2019 13:50:08 +0000 Subject: Disassembe Switch AI routines --- src/engine/bank05.asm | 10 ++++---- src/engine/bank08.asm | 64 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/wram.asm | 1 + 3 files changed, 68 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index c9e0b53..6e060b2 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1779,7 +1779,7 @@ AIDecideWhetherToRetreat: ; 158b2 (5:58b2) call LoadDefendingPokemonColorWRAndPrizeCards ld a, 128 ; initial retreat score ld [wAIScore], a - ld a, [$cdb4] + ld a, [wcdb4] or a jr z, .check_status srl a @@ -2530,7 +2530,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; done xor a - ld [$cdb4], a + ld [wcdb4], a jp FindHighestBenchScore ; 0x15d4f @@ -5031,13 +5031,13 @@ Func_169f8: ; 169f8 (5:69f8) jr z, .asm_16a62 .asm_16a5c xor a - ld [$cdb4], a + ld [wcdb4], a jr .asm_16a6d .asm_16a62 ld a, MOVE_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F call CheckLoadedMoveFlag jr c, .asm_16a5c - ld hl, $cdb4 + ld hl, wcdb4 inc [hl] .asm_16a6d ld a, $01 @@ -5051,7 +5051,7 @@ Func_169f8: ; 169f8 (5:69f8) jr z, .asm_16a80 jp Func_169e3 .asm_16a80 - ld hl, $cdb4 + ld hl, wcdb4 inc [hl] or a ret diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index d2e0d9c..fbb7481 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -1007,8 +1007,68 @@ CheckIfSelectedMoveCannotKnockOutWithoutPluspowerBoost: ; 205a5 (8:45a5) ret ; 0x20612 -Func_20612: ; 20612 (8:4612) - INCROM $20612, $2282e +AIPlaySwitch: ; 20612 (8:4612) + ld a, [wce21] + or $02 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + xor a + ld [wcdb4], a + ret +; 0x2062e + +Func_2062e: ; 2062e (8:462e) +; check if card already has no retreat cost + ld a, [wAIPlayEnergyCardForRetreat] + or a + jr z, .asm_2064a + +; compare number of energy cards attached to retreat cost. + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call GetPlayAreaCardRetreatCost + push af + ld e, PLAY_AREA_ARENA + farcall CountNumberOfEnergyCardsAttached + ld b, a + pop af + sub b + ; jump if cards attached > retreat cost + jr c, .asm_2064a + cp 2 + ; jump if retreat cost is 2 more energy cards + ; than the number of cards attached + jr nc, .asm_20660 + +.asm_2064a + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call GetPlayAreaCardRetreatCost + cp 3 + ; jump if retreat cost >= 3 + jr nc, .asm_20660 + + push af + ld e, PLAY_AREA_ARENA + farcall CountNumberOfEnergyCardsAttached + pop bc + cp b + ; jump if + jr c, .asm_20660 + ret +.asm_20660 + farcall AIDecideBenchPokemonToSwitchTo + ccf + ret +; 0x20666 + +Func_20666: ; 20666 (8:4666) + INCROM $20666, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, diff --git a/src/wram.asm b/src/wram.asm index 3bed41e..9b13642 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1201,6 +1201,7 @@ wcdb2:: ; cdb2 wcdb3:: ; cdb3 ds $1 +wcdb4:: ; cdb4 ds $1 ; information about various properties of -- cgit v1.2.3 From 7f1b4faea45a13fec23d41a88e1039965b70e274 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Mon, 30 Dec 2019 17:47:47 +0000 Subject: Document Switch AI routines --- src/engine/bank08.asm | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index fbb7481..3b0240a 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -13,8 +13,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0d, DEFENDER, CheckIfDefenderPreventsKnockOut, AIPlayDefender unknown_data_20000 $0e, DEFENDER, CheckIfDefenderPreventsRecoilKnockOut, AIPlayDefender unknown_data_20000 $0d, PLUSPOWER, CheckIfPluspowerBoostCausesKnockOut, AIPlayPluspower - unknown_data_20000 $0e, PLUSPOWER, CheckIfSelectedMoveCannotKnockOutWithoutPluspowerBoost, AIPlayPluspower - unknown_data_20000 $09, SWITCH, $462e, $4612 + unknown_data_20000 $0e, PLUSPOWER, CheckIfMoveNeedsPluspowerBoostToKnockOut, AIPlayPluspower + unknown_data_20000 $09, SWITCH, CheckIfActiveCardCanSwitch, AIPlaySwitch unknown_data_20000 $07, GUST_OF_WIND, $467e, $4666 unknown_data_20000 $0a, GUST_OF_WIND, $467e, $4666 unknown_data_20000 $04, BILL, $4878, $486d @@ -932,9 +932,9 @@ CheckIfPluspowerBoostCausesKnockOut: ; 20501 (8:4501) ; returns carry 7/10 of the time ; if selected move is useable, can't KO without Pluspower boost -; can damage Mr. Mime even with Pluspower boost; +; can damage Mr. Mime even with Pluspower boost ; and has a minimum damage > 0. -CheckIfSelectedMoveCannotKnockOutWithoutPluspowerBoost: ; 205a5 (8:45a5) +CheckIfMoveNeedsPluspowerBoostToKnockOut: ; 205a5 (8:45a5) xor a ldh [hTempPlayAreaLocation_ff9d], a call .check_can_ko @@ -1022,13 +1022,17 @@ AIPlaySwitch: ; 20612 (8:4612) ret ; 0x2062e -Func_2062e: ; 2062e (8:462e) -; check if card already has no retreat cost +; returns carry if the active card has less energy cards +; than the retreat cost and if AI can't play an energy +; card from the hand to fulfill the cost +CheckIfActiveCardCanSwitch: ; 2062e (8:462e) +; check if AI can already play an energy card from hand to retreat ld a, [wAIPlayEnergyCardForRetreat] or a - jr z, .asm_2064a + jr z, .check_cost_amount -; compare number of energy cards attached to retreat cost. +; can't play energy card from hand to retreat +; compare number of energy cards attached to retreat cost xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a call GetPlayAreaCardRetreatCost @@ -1039,29 +1043,30 @@ Func_2062e: ; 2062e (8:462e) pop af sub b ; jump if cards attached > retreat cost - jr c, .asm_2064a + jr c, .check_cost_amount cp 2 ; jump if retreat cost is 2 more energy cards ; than the number of cards attached - jr nc, .asm_20660 + jr nc, .switch -.asm_2064a +.check_cost_amount xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a call GetPlayAreaCardRetreatCost cp 3 ; jump if retreat cost >= 3 - jr nc, .asm_20660 + jr nc, .switch push af ld e, PLAY_AREA_ARENA farcall CountNumberOfEnergyCardsAttached pop bc cp b - ; jump if - jr c, .asm_20660 + ; jump if energy cards attached < retreat cost + jr c, .switch ret -.asm_20660 + +.switch farcall AIDecideBenchPokemonToSwitchTo ccf ret -- cgit v1.2.3 From 018978cf32ff1f2f9564f61ce77f0e71c5771d68 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Mon, 30 Dec 2019 21:57:59 +0000 Subject: Disassemble AI Gust Of Wind routines --- src/engine/bank08.asm | 393 +++++++++++++++++++++++++++++++++++++++++++++++++- src/wram.asm | 7 +- 2 files changed, 395 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 3b0240a..3e3ddbc 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -15,8 +15,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0d, PLUSPOWER, CheckIfPluspowerBoostCausesKnockOut, AIPlayPluspower unknown_data_20000 $0e, PLUSPOWER, CheckIfMoveNeedsPluspowerBoostToKnockOut, AIPlayPluspower unknown_data_20000 $09, SWITCH, CheckIfActiveCardCanSwitch, AIPlaySwitch - unknown_data_20000 $07, GUST_OF_WIND, $467e, $4666 - unknown_data_20000 $0a, GUST_OF_WIND, $467e, $4666 + unknown_data_20000 $07, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind + unknown_data_20000 $0a, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind unknown_data_20000 $04, BILL, $4878, $486d unknown_data_20000 $05, ENERGY_REMOVAL, $4895, $4880 unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, $49bc, $4994 @@ -1072,8 +1072,393 @@ CheckIfActiveCardCanSwitch: ; 2062e (8:462e) ret ; 0x20666 -Func_20666: ; 20666 (8:4666) - INCROM $20666, $2282e +AIPlayGustOfWind: ; 20666 (8:4666) + ld a, [wce21] + or $10 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x2067e + +CheckWhetherToUseGustOfWind: ; 2067e (8:467e) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + dec a + or a + ret z ; no bench cards + ld a, [wce20] + and $10 + ret nz + farcall CheckIfActivePokemonCanUseAnyNonResidualMove + ret nc ; no non-residual move can be used + + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .check_id ; if can't KO + farcall CheckIfSelectedMoveIsUnusable + jr nc, .no_carry ; if KO move is useable + farcall LookForEnergyNeededForMoveInHand + jr c, .no_carry ; if energy card is in hand + +.check_id + ; skip if current active card is MEW3 or MEWTWO1 + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp MEW3 + jr z, .no_carry + cp MEWTWO1 + jr z, .no_carry + + call .FindBenchCardToKnockOut + ret c + + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call .CheckIfNoAttackDealsDamage + jr c, .check_bench_energy + + ; skip if current arena card's color is + ; the defending card's weakness + call GetArenaCardColor + call TranslateColorToWR + ld b, a + call SwapTurn + call GetArenaCardWeakness + call SwapTurn + and b + jr nz, .no_carry + +; check weakness + call .FindBenchCardWithWeakness + ret nc ; no bench card weak to arena card + scf + ret ; found bench card weak to arena card + +.no_carry + or a + ret + +; being here means AI's arena card cannot damage player's arena card + +; first check if there is a card in player's bench that +; has no attached energy cards and that the AI can damage +.check_bench_energy + ; return carry if there's a bench card with weakness + call .FindBenchCardWithWeakness + ret c + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA +; loop through bench and check attached energy cards +.loop_1 + inc e + dec d + jr z, .check_bench_hp + call SwapTurn + call GetPlayAreaCardAttachedEnergies + call SwapTurn + ld a, [wTotalAttachedEnergies] + or a + jr nz, .loop_1 ; skip if has energy attached + call .CheckIfCanDamageBenchedCard + jr nc, .loop_1 + ld a, e + scf + ret + +.check_bench_hp + ld a, $ff + ld [wce06], a + xor a + ld [wce08], a + ld e, a + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + ld d, a + +; find bench card with least amount of available HP +.loop_2 + inc e + dec d + jr z, .check_found + ld a, e + add DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + ld b, a + ld a, [wce06] + inc b + cp b + jr c, .loop_2 + call .CheckIfCanDamageBenchedCard + jr nc, .loop_2 + dec b + ld a, b + ld [wce06], a + ld a, e + ld [wce08], a + jr .loop_2 + +.check_found + ld a, [wce08] + or a + jr z, .no_carry +; a card was found + +.set_carry + scf + ret + +.check_can_damage + push bc + push hl + xor a ; PLAY_AREA_ARENA + farcall CheckIfCanDamageDefendingPokemon + pop hl + pop bc + jr nc, .loop_3 + ld a, c + scf + ret + +; returns carry if any of the player's +; benched cards is weak to color in b +; and has a way to damage it +.FindBenchCardWithWeakness ; 2074d (8:474d) + ld a, DUELVARS_BENCH + call GetNonTurnDuelistVariable + ld c, PLAY_AREA_ARENA +.loop_3 + inc c + ld a, [hli] + cp $ff + jr z, .no_carry + call SwapTurn + call LoadCardDataToBuffer1_FromDeckIndex + call SwapTurn + ld a, [wLoadedCard1Weakness] + and b + jr nz, .check_can_damage + jr .loop_3 + +; returns carry if neither attack can deal damage +.CheckIfNoAttackDealsDamage ; 2076b (8:476b) + xor a ; first attack + ld [wSelectedMoveIndex], a + call .CheckIfAttackDealsNoDamage + jr c, .second_attack + ret +.second_attack + ld a, $01 ; second attack + ld [wSelectedMoveIndex], a + call .CheckIfAttackDealsNoDamage + jr c, .asm_20780 + ret +.asm_20780 + scf + ret + +; returns carry if attack is Pokemon Power +; or otherwise doesn't deal any damage +.CheckIfAttackDealsNoDamage ; 20782 (8:4782) + ld a, [wSelectedMoveIndex] + ld e, a + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + ld d, a + call CopyMoveDataAndDamage_FromDeckIndex + ld a, [wLoadedMoveCategory] + + ; skip if move is a Power or has 0 damage + cp POKEMON_POWER + jr z, .no_damage + ld a, [wDamage] + or a + ret z + + ; check damage against defending card + ld a, [wSelectedMoveIndex] + farcall EstimateDamage_VersusDefendingCard + ld a, [wAIMaxDamage] + or a + ret nz + +.no_damage + scf + ret + +; returns carry if there is a player's bench card that +; the opponent's current active card can KO +.FindBenchCardToKnockOut ; 207a9 (8:47a9) + ld a, DUELVARS_BENCH + call GetNonTurnDuelistVariable + ld e, PLAY_AREA_BENCH_1 + +.loop_4 + ld a, [hli] + cp $ff + ret z + +; overwrite the player's active card and its HP +; with the current bench card that is being checked + push hl + push de + ld b, a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + push af + ld [hl], b + ld a, e + add DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + ld b, a + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + push af + ld [hl], b + + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + call .CheckIfAnyMoveKnocksOut + jr nc, .next + farcall CheckIfSelectedMoveIsUnusable + jr nc, .found + farcall LookForEnergyNeededForMoveInHand + jr c, .found + +; the following two local routines can be condensed into one +; since they both revert the player's arena card +.next + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + pop af + ld [hl], a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + pop af + ld [hl], a + pop de + inc e + pop hl + jr .loop_4 + +; revert player's arena card and set carry +.found + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + pop af + ld [hl], a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + pop af + ld [hl], a + pop de + ld a, e + pop hl + scf + ret + +; returns carry if any of arena card's attacks +; KOs player card in location stored in e +.CheckIfAnyMoveKnocksOut ; 20806 (8:4806) + xor a ; first attack + call .asm_2080d + ret c + ld a, $01 ; second attack + +; returns carry if attack KOs player card +; in location stored in e +.asm_2080d + push de + farcall EstimateDamage_VersusDefendingCard + pop de + ld a, DUELVARS_ARENA_CARD_HP + add e + call GetNonTurnDuelistVariable + ld hl, wDamage + sub [hl] + ret c + ret nz + scf + ret + +; returns carry if opponent's arena card can damage +; this benched card if it were switched with +; the player's arena card +.CheckIfCanDamageBenchedCard ; 20821 (8:4821) + push bc + push de + push hl + + ; overwrite arena card data + ld a, e + add DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + ld b, a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + push af + ld [hl], b + + ; overwrite arena card HP + ld a, e + add DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + ld b, a + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + push af + ld [hl], b + + xor a ; PLAY_AREA_ARENA + farcall CheckIfCanDamageDefendingPokemon + jr c, .can_damage + +; the following two local routines can be condensed into one +; since they both revert the player's arena card + +; can't damage + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + pop af + ld [hl], a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + pop af + ld [hl], a + pop hl + pop de + pop bc + or a + ret + +.can_damage + ld a, DUELVARS_ARENA_CARD_HP + call GetNonTurnDuelistVariable + pop af + ld [hl], a + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + pop af + ld [hl], a + pop hl + pop de + pop bc + scf + ret +; 0x2086d + +Func_2086d: ; 2086d (8:486d) + INCROM $2086d, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, diff --git a/src/wram.asm b/src/wram.asm index 9e785c3..95520c7 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1356,7 +1356,12 @@ wce03:: ; ce03 wce06:: ; ce06 ds $1 - ds $0f + ds $1 + +wce08:: ; ce08 + ds $1 + + ds $0d wce16:: ; ce16 ds $1 -- cgit v1.2.3 From 205f6b87c17bcac2d204fdde9d207bf5d331566a Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Mon, 30 Dec 2019 22:04:17 +0000 Subject: Disassemble AI Bill routines --- src/engine/bank08.asm | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 3e3ddbc..8d52c23 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -17,7 +17,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $09, SWITCH, CheckIfActiveCardCanSwitch, AIPlaySwitch unknown_data_20000 $07, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind unknown_data_20000 $0a, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind - unknown_data_20000 $04, BILL, $4878, $486d + unknown_data_20000 $04, BILL, CheckDeckCardsAmount, AIPlayBill unknown_data_20000 $05, ENERGY_REMOVAL, $4895, $4880 unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, $49bc, $4994 unknown_data_20000 $07, POKEMON_BREEDER, $4b1b, $4b06 @@ -1080,7 +1080,7 @@ AIPlayGustOfWind: ; 20666 (8:4666) ldh [hTempCardIndex_ff9f], a ld a, [wce19] ldh [hTemp_ffa0], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x2067e @@ -1457,8 +1457,24 @@ CheckWhetherToUseGustOfWind: ; 2067e (8:467e) ret ; 0x2086d -Func_2086d: ; 2086d (8:486d) - INCROM $2086d, $2282e +AIPlayBill: ; 2086d (8:486d) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x20878 + +; return carry if cards not in deck < 51 +CheckDeckCardsAmount: ; 20878 (8:4878) + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp 51 + ret +; 0x20880 + +Func_20880: ; 20880 (8:4880) + INCROM $20880, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, -- cgit v1.2.3 From da1f84f7c093fb79c6af0b2ffa0dfc39f68784bb Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Tue, 31 Dec 2019 12:24:03 +0000 Subject: Disassemble AI Energy Removal routines --- src/engine/bank08.asm | 312 +++++++++++++++++++++++++++++++++++++++++++++++--- src/wram.asm | 12 +- 2 files changed, 309 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 8d52c23..81f82cc 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -18,7 +18,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $07, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind unknown_data_20000 $0a, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind unknown_data_20000 $04, BILL, CheckDeckCardsAmount, AIPlayBill - unknown_data_20000 $05, ENERGY_REMOVAL, $4895, $4880 + unknown_data_20000 $05, ENERGY_REMOVAL, CheckEnergyCardToRemoveInPlayArea, AIPlayEnergyRemoval unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, $49bc, $4994 unknown_data_20000 $07, POKEMON_BREEDER, $4b1b, $4b06 unknown_data_20000 $0f, PROFESSOR_OAK, $4cc1, $4cae @@ -641,13 +641,13 @@ CheckIfDefenderPreventsKnockOut: ; 20406 (8:4406) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfAnyMoveKnocksOutDefendingCard - jr nc, .asm_2041b + jr nc, .cannot_ko farcall CheckIfSelectedMoveIsUnusable jr nc, .no_carry farcall LookForEnergyNeededForMoveInHand jr c, .no_carry -.asm_2041b +.cannot_ko ; check if any of the defending Pokémon's attacks deal ; damage exactly equal to current HP, and if so, ; only continue if that move is useable. @@ -1261,9 +1261,9 @@ CheckWhetherToUseGustOfWind: ; 2067e (8:467e) ld a, $01 ; second attack ld [wSelectedMoveIndex], a call .CheckIfAttackDealsNoDamage - jr c, .asm_20780 + jr c, .true ret -.asm_20780 +.true scf ret @@ -1328,7 +1328,7 @@ CheckWhetherToUseGustOfWind: ; 2067e (8:467e) xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a - call .CheckIfAnyMoveKnocksOut + call .CheckIfAnyAttackKnocksOut jr nc, .next farcall CheckIfSelectedMoveIsUnusable jr nc, .found @@ -1369,15 +1369,15 @@ CheckWhetherToUseGustOfWind: ; 2067e (8:467e) ; returns carry if any of arena card's attacks ; KOs player card in location stored in e -.CheckIfAnyMoveKnocksOut ; 20806 (8:4806) +.CheckIfAnyAttackKnocksOut ; 20806 (8:4806) xor a ; first attack - call .asm_2080d + call .CheckIfAttackKnocksOut ret c ld a, $01 ; second attack ; returns carry if attack KOs player card ; in location stored in e -.asm_2080d +.CheckIfAttackKnocksOut push de farcall EstimateDamage_VersusDefendingCard pop de @@ -1473,8 +1473,218 @@ CheckDeckCardsAmount: ; 20878 (8:4878) ret ; 0x20880 -Func_20880: ; 20880 (8:4880) - INCROM $20880, $2282e +AIPlayEnergyRemoval: ; 20880 (8:4880) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x20895 + +; picks an energy card in the player's Play Area to remove +CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) +; check if the current active card can KO player's card +; if it's possible to KO, then do not consider the player's +; active card to remove its attached energy + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .cannot_ko + farcall CheckIfSelectedMoveIsUnusable + jr nc, .can_ko + farcall LookForEnergyNeededForMoveInHand + jr nc, .cannot_ko + +.can_ko + ; start checking from the bench + ld a, PLAY_AREA_BENCH_1 + ld [wce0f], a + jr .check_bench_energy + +.cannot_ko + ; start checking from the arena card + xor a ; PLAY_AREA_ARENA + ld [wce0f], a + +; loop each card and check if it has enough energy to use any attack +; if it does, then proceed to pick an energy card to remove +.check_bench_energy + call SwapTurn + ld a, [wce0f] + ld e, a +.loop_1 + ld a, DUELVARS_ARENA_CARD + add e + call GetTurnDuelistVariable + cp $ff + jr z, .default + ld d, a + call .CheckIfCardHasEnergyAttached + jr nc, .next_1 + call .CheckIfNotEnoughEnergyToAttack + jr nc, .pick_energy ; jump if enough energy to attack +.next_1 + inc e + jr .loop_1 + +.pick_energy +; a play area card was picked to remove energy +; store the picked energy card to remove in wce1a +; and set carry + ld a, e + push af + call PickAttachedEnergyCard + ld [wce1a], a + pop af + call SwapTurn + scf + ret + +; if no card in player's Play Area was found with enough energy +; to attack, just pick an energy card from player's active card +; (in case the AI cannot KO it this turn) +.default + ld a, [wce0f] + or a + jr nz, .check_bench_damage ; not active card + call .CheckIfCardHasEnergyAttached + jr c, .pick_energy + +; lastly, check what attack on player's Play Area is highest damaging +; and pick an energy card attached to that Pokemon to remove +.check_bench_damage + xor a + ld [wce06], a + ld [wce08], a + + ld e, PLAY_AREA_BENCH_1 +.loop_2 + ld a, DUELVARS_ARENA_CARD + add e + call GetTurnDuelistVariable + cp $ff + jr z, .found_damage + ld d, a + call .CheckIfCardHasEnergyAttached + jr nc, .next_2 + call .FindHighestDamagingAttack +.next_2 + inc e + jr .loop_2 + +.found_damage + ld a, [wce08] + or a + jr z, .no_carry ; skip if none found + ld e, a + jr .pick_energy +.no_carry + call SwapTurn + or a + ret + +; returns carry if this card has any energy cards attached +.CheckIfCardHasEnergyAttached ; 2091a (8:491a) + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + or a + ret z + scf + ret + +; returns carry if this card does not +; have enough energy for either of its attacks +.CheckIfNotEnoughEnergyToAttack ; 20924 (8:4924) + push de + xor a ; first attack + ld [wSelectedMoveIndex], a + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckEnergyNeededForAttack + jr nc, .enough_energy + pop de + + push de + ld a, $01 ; second attack + ld [wSelectedMoveIndex], a + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckEnergyNeededForAttack + jr nc, .check_surplus + pop de + +; neither attack has enough energy + scf + ret + +.enough_energy + pop de + or a + ret + +; first attack doesn't have enough energy (or is just a Pokemon Power) +; but second attack has enough energy to be used +; check if there's surplus energy for attack and, if so, return carry +.check_surplus + farcall CheckIfNoSurplusEnergyForMove + pop de + ccf + ret + +; stores in wce06 the highest damaging attack +; for the card in play area location in e +; and stores this card's location in wce08 +.FindHighestDamagingAttack ; 2094f (8:494f) + push de + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + xor a ; first attack + farcall EstimateDamage_VersusDefendingCard + ld a, [wDamage] + or a + jr z, .skip_1 + ld e, a + ld a, [wce06] + cp e + jr nc, .skip_1 + ld a, e + ld [wce06], a ; store this damage value + pop de + ld a, e + ld [wce08], a ; store this location + jr .second_attack +.skip_1 + pop de + +.second_attack + push de + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + ld a, $01 ; second attack + farcall EstimateDamage_VersusDefendingCard + ld a, [wDamage] + or a + jr z, .skip_2 + ld e, a + ld a, [wce06] + cp e + jr nc, .skip_2 + ld a, e + ld [wce06], a ; store this damage value + pop de + ld a, e + ld [wce08], a ; store this location + ret +.skip_2 + pop de + ret +; 0x20994 + + INCROM $20994, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, @@ -1528,8 +1738,84 @@ GetEnergyCardToDiscard: ; 2282e (8:682e) ret ; 0x22875 -Func_22875: ; 22875 (8:6875) - INCROM $22875, $2297b +; returns in a the deck index of the energy card +; attached to card in hTempPlayAreaLocation_ff9d. +; prioritises double colorless energy, then any +; useful energy, then defaults to the first energy +; card attached if neither of those are found. +; returns $ff if there are no energy cards attached. +PickAttachedEnergyCard: ; 22875 (8:6875) +; construct energy list and check if there are any energy cards attached + ldh [hTempPlayAreaLocation_ff9d], a + call CreateArenaOrBenchEnergyCardList + ldh a, [hTempPlayAreaLocation_ff9d] + ld e, a + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + or a + jr z, .no_energy + +; load card data and store its type + ldh a, [hTempPlayAreaLocation_ff9d] + ld b, a + ld a, DUELVARS_ARENA_CARD + add b + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + ld [wTempCardType], a + +; first look for any double colorless energy + ld hl, wDuelTempList +.loop_1 + ld a, [hl] + cp $ff + jr z, .check_useful + push hl + call GetCardIDFromDeckIndex + ld a, e + cp DOUBLE_COLORLESS_ENERGY + pop hl + jr z, .found + inc hl + jr .loop_1 + +; then look for any energy cards that are useful +.check_useful + ld hl, wDuelTempList +.loop_2 + ld a, [hl] + cp $ff + jr z, .default + farcall CheckIfEnergyIsUseful + jr c, .found + inc hl + jr .loop_2 + +; return the energy card that was found +.found + ld a, [hl] + ret + +; if none were found with the above criteria, +; just return the first option +.default + ld hl, wDuelTempList + ld a, [hl] + ret + +; return $ff if no energy cards attached +.no_energy + ld a, $ff + ret +; 0x228d1 + +Func_228d1: ; 228d1 (8:68d1) + INCROM $228d1, $2297b ; copies $ff terminated buffer from hl to de CopyBuffer: ; 2297b (8:697b) diff --git a/src/wram.asm b/src/wram.asm index 95520c7..f373f8e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1361,7 +1361,12 @@ wce06:: ; ce06 wce08:: ; ce08 ds $1 - ds $0d + ds $06 + +wce0f:: ; ce0f + ds $1 + + ds $06 wce16:: ; ce16 ds $1 @@ -1375,7 +1380,10 @@ wce18:: ; ce18 wce19:: ; ce19 ds $1 - ds $6 +wce1a:: ; ce1a + ds $1 + + ds $5 wce20:: ; ce20 ds $1 -- cgit v1.2.3 From 88309ea8f1840c7d309e45aa53d928762adaaf80 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Tue, 14 Apr 2020 19:27:27 +0100 Subject: Finish AI Energy Removal routines --- src/engine/bank08.asm | 437 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/wram.asm | 11 +- 2 files changed, 436 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 81f82cc..a3423f0 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -19,7 +19,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0a, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind unknown_data_20000 $04, BILL, CheckDeckCardsAmount, AIPlayBill unknown_data_20000 $05, ENERGY_REMOVAL, CheckEnergyCardToRemoveInPlayArea, AIPlayEnergyRemoval - unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, $49bc, $4994 + unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, CheckTwoEnergyCardsToRemoveInPlayArea, AIPlaySuperEnergyRemoval unknown_data_20000 $07, POKEMON_BREEDER, $4b1b, $4b06 unknown_data_20000 $0f, PROFESSOR_OAK, $4cc1, $4cae unknown_data_20000 $0a, ENERGY_RETRIEVAL, $4e6e, $4e44 @@ -1504,7 +1504,6 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) ld a, PLAY_AREA_BENCH_1 ld [wce0f], a jr .check_bench_energy - .cannot_ko ; start checking from the arena card xor a ; PLAY_AREA_ARENA @@ -1522,6 +1521,7 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) call GetTurnDuelistVariable cp $ff jr z, .default + ld d, a call .CheckIfCardHasEnergyAttached jr nc, .next_1 @@ -1568,6 +1568,7 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) call GetTurnDuelistVariable cp $ff jr z, .found_damage + ld d, a call .CheckIfCardHasEnergyAttached jr nc, .next_2 @@ -1642,6 +1643,7 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) push de ld a, e ldh [hTempPlayAreaLocation_ff9d], a + xor a ; first attack farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] @@ -1657,6 +1659,7 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) ld a, e ld [wce08], a ; store this location jr .second_attack + .skip_1 pop de @@ -1664,6 +1667,7 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) push de ld a, e ldh [hTempPlayAreaLocation_ff9d], a + ld a, $01 ; second attack farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] @@ -1684,7 +1688,296 @@ CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) ret ; 0x20994 - INCROM $20994, $2282e +AIPlaySuperEnergyRemoval: ; 20994 (8:4994) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce1b] + ldh [hTempRetreatCostCards], a + ld a, [wce1c] + ldh [hTempRetreatCostCards + 1], a + ld a, [wce1d] + ldh [hTempRetreatCostCards + 2], a + ld a, $ff + ldh [hTempRetreatCostCards + 3], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x209bc + +; picks two energy cards in the player's Play Area to remove +CheckTwoEnergyCardsToRemoveInPlayArea: ; 209bc (8:49bc) + ld e, PLAY_AREA_BENCH_1 +.loop_1 +; first find an Arena card with a color energy card +; to discard for card effect +; return immediately if no Arena cards + ld a, DUELVARS_ARENA_CARD + add e + call GetTurnDuelistVariable + cp $ff + jr z, .exit + + ld d, a + push de + call .LookForNonDoubleColorless + pop de + jr c, .not_double_colorless + inc e + jr .loop_1 + +; returns carry if an energy card other than double colorless +; is found attached to the card in play area location e +.LookForNonDoubleColorless + ld a, e + call CreateArenaOrBenchEnergyCardList + ld hl, wDuelTempList +.loop_2 + ld a, [hli] + cp $ff + ret z + call LoadCardDataToBuffer1_FromDeckIndex + cp DOUBLE_COLORLESS_ENERGY + ; any non-double colorless energy card + ; will set carry flag here + jr nc, .loop_2 + ret + +.exit + or a + ret + +; card in Play Area location e was found with +; a non-double colorless energy card +.not_double_colorless + ld a, e + ld [wce0f], a + +; check if the current active card can KO player's card +; if it's possible to KO, then do not consider the player's +; active card to remove its attached energy + xor a ; PLAY_AREA_ARENA + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .cannot_ko + farcall CheckIfSelectedMoveIsUnusable + jr nc, .can_ko + farcall LookForEnergyNeededForMoveInHand + jr nc, .cannot_ko + +.can_ko + ; start checking from the bench + call SwapTurn + ld e, PLAY_AREA_BENCH_1 + jr .loop_3 +.cannot_ko + ; start checking from the arena card + call SwapTurn + ld e, PLAY_AREA_ARENA + +; loop each card and check if it has enough energy to use any attack +; if it does, then proceed to pick energy cards to remove +.loop_3 + ld a, DUELVARS_ARENA_CARD + add e + call GetTurnDuelistVariable + cp $ff + jr z, .no_carry + + ld d, a + call .CheckIfFewerThanTwoEnergyCards + jr c, .next_1 + call .CheckIfNotEnoughEnergyToAttack + jr nc, .found_card ; jump if enough energy to attack +.next_1 + inc e + jr .loop_3 + +.found_card +; a play area card was picked to remove energy +; if this is not the Arena Card, then check +; entire bench to pick the highest damage + ld a, e + or a + jr nz, .check_bench_damage + +; store the picked energy card to remove in wce1a +; and set carry +.pick_energy + ld [wce1b], a + call PickTwoAttachedEnergyCards + ld [wce1c], a + ld a, b + ld [wce1d], a + call SwapTurn + ld a, [wce0f] + push af + call GetEnergyCardToDiscard + ld [wce1a], a + pop af + scf + ret + +; check what attack on player's Play Area is highest damaging +; and pick an energy card attached to that Pokemon to remove +.check_bench_damage + xor a + ld [wce06], a + ld [wce08], a + + ld e, PLAY_AREA_BENCH_1 +.loop_4 + ld a, DUELVARS_ARENA_CARD + add e + call GetTurnDuelistVariable + cp $ff + jr z, .found_damage + + ld d, a + call .CheckIfFewerThanTwoEnergyCards + jr c, .next_2 + call .CheckIfNotEnoughEnergyToAttack + jr c, .next_2 + call .FindHighestDamagingAttack +.next_2 + inc e + jr .loop_4 + +.found_damage + ld a, [wce08] + or a + jr z, .no_carry + jr .pick_energy +.no_carry + call SwapTurn + or a + ret + +; returns carry if the number of energy cards attached +; is fewer than 2, or if all energy combined yields +; fewer than 2 energy +.CheckIfFewerThanTwoEnergyCards ; 20a77 (8:4a77) + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + cp 2 + ret c ; return if fewer than 2 attached cards + +; count all energy attached +; i.e. colored energy card = 1 +; and double colorless energy card = 2 + xor a + ld b, NUM_COLORED_TYPES + ld hl, wAttachedEnergies +.loop_5 + add [hl] + inc hl + dec b + jr nz, .loop_5 + ld b, [hl] + srl b + add b + cp 2 + ret + +; returns carry if this card does not +; have enough energy for either of its attacks +.CheckIfNotEnoughEnergyToAttack ; 20a92 (8:4a92) + push de + xor a ; first attack + ld [wSelectedMoveIndex], a + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckEnergyNeededForAttack + jr nc, .enough_energy + pop de + + push de + ld a, $01 ; second attack + ld [wSelectedMoveIndex], a + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + farcall CheckEnergyNeededForAttack + jr nc, .check_surplus + pop de + +; neither attack has enough energy + scf + ret + +.enough_energy + pop de + or a + ret + +; first attack doesn't have enough energy (or is just a Pokemon Power) +; but second attack has enough energy to be used +; check if there's surplus energy for attack and, if so, +; return carry if this surplus energy is at least 2 +.check_surplus + farcall CheckIfNoSurplusEnergyForMove + cp 2 + jr c, .enough_energy + pop de + scf + ret +; 0x20ac1 + +; stores in wce06 the highest damaging attack +; for the card in play area location in e +; and stores this card's location in wce08 +.FindHighestDamagingAttack ; 20ac1 (8:4ac1) + push de + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + + xor a ; first attack + farcall EstimateDamage_VersusDefendingCard + ld a, [wDamage] + or a + jr z, .skip_1 + ld e, a + ld a, [wce06] + cp e + jr nc, .skip_1 + ld a, e + ld [wce06], a ; store this damage value + pop de + ld a, e + ld [wce08], a ; store this location + jr .second_attack + +.skip_1 + pop de + +.second_attack + push de + ld a, e + ldh [hTempPlayAreaLocation_ff9d], a + + ld a, $01 ; second attack + farcall EstimateDamage_VersusDefendingCard + ld a, [wDamage] + or a + jr z, .skip_2 + ld e, a + ld a, [wce06] + cp e + jr nc, .skip_2 + ld a, e + ld [wce06], a ; store this damage value + pop de + ld a, e + ld [wce08], a ; store this location + ret +.skip_2 + pop de + ret +; 0x20b06 + + INCROM $20b06, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, @@ -1738,12 +2031,16 @@ GetEnergyCardToDiscard: ; 2282e (8:682e) ret ; 0x22875 -; returns in a the deck index of the energy card -; attached to card in hTempPlayAreaLocation_ff9d. -; prioritises double colorless energy, then any -; useful energy, then defaults to the first energy -; card attached if neither of those are found. -; returns $ff if there are no energy cards attached. +; returns in a the deck index of an energy card attached to card +; in Play Area location a.. +; prioritises double colorless energy, then any useful energy, +; then defaults to the first energy card attached if neither +; of those are found. +; returns $ff in a if there are no energy cards attached. +; input: +; a = Play Area location to check +; output: +; a = deck index of attached energy card PickAttachedEnergyCard: ; 22875 (8:6875) ; construct energy list and check if there are any energy cards attached ldh [hTempPlayAreaLocation_ff9d], a @@ -1814,8 +2111,126 @@ PickAttachedEnergyCard: ; 22875 (8:6875) ret ; 0x228d1 -Func_228d1: ; 228d1 (8:68d1) - INCROM $228d1, $2297b +; stores in wTempAI and wCurCardCanAttack the deck indices +; of energy cards attached to card in Play Area location a. +; prioritises double colorless energy, then any useful energy, +; then defaults to the first two energy cards attached if neither +; of those are found. +; returns $ff in a if there are no energy cards attached. +; input: +; a = Play Area location to check +; output: +; [wTempAI] = deck index of attached energy card +; [wCurCardCanAttack] = deck index of attached energy card +PickTwoAttachedEnergyCards: ; 228d1 (8:68d1) + ldh [hTempPlayAreaLocation_ff9d], a + call CreateArenaOrBenchEnergyCardList + ldh a, [hTempPlayAreaLocation_ff9d] + ld e, a + farcall CountNumberOfEnergyCardsAttached + cp 2 + jp c, .not_enough + +; load card data and store its type + ldh a, [hTempPlayAreaLocation_ff9d] + ld b, a + ld a, DUELVARS_ARENA_CARD + add b + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + ld [wTempCardType], a + ld a, $ff + ld [wTempAI], a + ld [wCurCardCanAttack], a + +; first look for any double colorless energy + ld hl, wDuelTempList +.loop_1 + ld a, [hl] + cp $ff + jr z, .check_useful + push hl + call GetCardIDFromDeckIndex + ld a, e + cp DOUBLE_COLORLESS_ENERGY + pop hl + jr z, .found_double_colorless + inc hl + jr .loop_1 +.found_double_colorless + ld a, [wTempAI] + cp $ff + jr nz, .already_chosen_1 + ld a, [hli] + ld [wTempAI], a + jr .loop_1 +.already_chosen_1 + ld a, [hl] + ld [wCurCardCanAttack], a + jr .done + +; then look for any energy cards that are useful +.check_useful + ld hl, wDuelTempList +.loop_2 + ld a, [hl] + cp $ff + jr z, .default + farcall CheckIfEnergyIsUseful + jr c, .found_useful + inc hl + jr .loop_2 +.found_useful + ld a, [wTempAI] + cp $ff + jr nz, .already_chosen_2 + ld a, [hli] + ld [wTempAI], a + jr .loop_2 +.already_chosen_2 + ld a, [hl] + ld [wCurCardCanAttack], a + jr .done + +; if none were found with the above criteria, +; just return the first 2 options +.default + ld hl, wDuelTempList + ld a, [wTempAI] + cp $ff + jr nz, .pick_one_card + +; pick 2 cards + ld a, [hli] + ld [wTempAI], a + ld a, [hl] + ld [wCurCardCanAttack], a + jr .done +.pick_one_card + ld a, [wTempAI] + ld b, a +.loop_3 + ld a, [hli] + cp b + jr z, .loop_3 ; already picked + ld [wCurCardCanAttack], a + +.done + ld a, [wCurCardCanAttack] + ld b, a + ld a, [wTempAI] + ret + +; return $ff if no energy cards attached +.not_enough + ld a, $ff + ret +; 0x2297b ; copies $ff terminated buffer from hl to de CopyBuffer: ; 2297b (8:697b) diff --git a/src/wram.asm b/src/wram.asm index f373f8e..3ed098e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1383,7 +1383,16 @@ wce19:: ; ce19 wce1a:: ; ce1a ds $1 - ds $5 +wce1b:: ; ce1b + ds $1 + +wce1c:: ; ce1c + ds $1 + +wce1d:: ; ce1d + ds $1 + + ds $2 wce20:: ; ce20 ds $1 -- cgit v1.2.3 From 064ed473ff7a33b42e663105b94c9503021c11e4 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Tue, 14 Apr 2020 21:31:06 +0100 Subject: AI Pokemon Breeder routines --- src/engine/bank05.asm | 8 +- src/engine/bank08.asm | 401 +++++++++++++++++++++++++++++++++++++++++++++++++- src/wram.asm | 9 +- 3 files changed, 402 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 9e2734a..c01792c 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1450,7 +1450,7 @@ Func_15612: ; 15612 (5:5612) Func_15636: ; 15636 (5:5636) ld a, $10 ld hl, wcda5 - call ZeroData + call ZeroData_Bank5 ld a, $5 ld [wcda6], a ld a, $ff @@ -1642,7 +1642,7 @@ CheckEnergyNeededForAttackAfterDiscard: ; 156c3 (5:56c3) ; 0x1575e ; zeroes a bytes starting at hl -ZeroData: ; 1575e (5:575e) +ZeroData_Bank5: ; 1575e (5:575e) push af push bc push hl @@ -6752,7 +6752,7 @@ RaiseAIScoreToAllMatchingIDsInBench: ; 174cd (5:74cd) Func_174f2: ; 174f2 (5:74f2) ld a, MAX_PLAY_AREA_POKEMON ld hl, wcdfa - call ZeroData + call ZeroData_Bank5 ld a, DUELVARS_BENCH call GetTurnDuelistVariable ld e, 0 @@ -6761,7 +6761,7 @@ Func_174f2: ; 174f2 (5:74f2) push hl ld a, MAX_PLAY_AREA_POKEMON ld hl, wcdea - call ZeroData + call ZeroData_Bank5 pop hl inc e ld a, [hli] diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index a3423f0..7fd84b2 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -20,7 +20,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $04, BILL, CheckDeckCardsAmount, AIPlayBill unknown_data_20000 $05, ENERGY_REMOVAL, CheckEnergyCardToRemoveInPlayArea, AIPlayEnergyRemoval unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, CheckTwoEnergyCardsToRemoveInPlayArea, AIPlaySuperEnergyRemoval - unknown_data_20000 $07, POKEMON_BREEDER, $4b1b, $4b06 + unknown_data_20000 $07, POKEMON_BREEDER, CheckIfCanEvolve2StageFromHand, AIPlayPokemonBreeder unknown_data_20000 $0f, PROFESSOR_OAK, $4cc1, $4cae unknown_data_20000 $0a, ENERGY_RETRIEVAL, $4e6e, $4e44 unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, $4fc1, $4f80 @@ -1977,7 +1977,363 @@ CheckTwoEnergyCardsToRemoveInPlayArea: ; 209bc (8:49bc) ret ; 0x20b06 - INCROM $20b06, $2282e +AIPlayPokemonBreeder: ; 20b06 (8:4b06) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce1a] + ldh [hTemp_ffa0], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x20b1b + +CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) + call IsPrehistoricPowerActive + jp c, .done + + ld a, 7 + ld hl, wce08 + call ZeroData_Bank8 + + xor a + ld [wce06], a + call CreateHandCardList + ld hl, wDuelTempList + +.loop_hand_1 + ld a, [hli] + cp $ff + jr z, .not_found_in_hand + +; check if card in hand is any of the following +; stage 2 Pokemon cards + ld d, a + call LoadCardDataToBuffer1_FromDeckIndex + cp VENUSAUR1 + jr z, .found + cp VENUSAUR2 + jr z, .found + cp BLASTOISE + jr z, .found + cp VILEPLUME + jr z, .found + cp ALAKAZAM + jr z, .found + cp GENGAR + jr nz, .loop_hand_1 + +.found + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + push hl + call GetTurnDuelistVariable + pop hl + ld c, a + ld e, PLAY_AREA_ARENA + +; check Play Area for card that can evolve into +; the picked stage 2 Pokemon +.loop_play_area_1 + push hl + push bc + push de + call CheckIfCanEvolveInto_BasicToStage2 + pop de + call nc, .can_evolve + pop bc + pop hl + inc e + dec c + jr nz, .loop_play_area_1 + jr .loop_hand_1 + +.can_evolve + ld a, DUELVARS_ARENA_CARD_HP + add e + call GetTurnDuelistVariable + call ConvertHPToCounters + swap a + ld b, a + +; count number of energy cards attached and keep +; the lowest 4 bits (capped at $0f) + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + cp $10 + jr c, .not_maxed_out + ld a, %00001111 +.not_maxed_out + or b + +; 4 high bits of a = HP counters Pokemon still has +; 4 low bits of a = number of energy cards attached + +; store this score in wce08 + PLAY_AREA* + ld hl, wce08 + ld c, e + ld b, $00 + add hl, bc + ld [hl], a + +; store the deck index of stage 2 Pokemon in wce0f + PLAY_AREA* + ld hl, wce0f + add hl, bc + ld [hl], d + +; increase wce06 by one + ld hl, wce06 + inc [hl] + ret + +.not_found_in_hand + ld a, [wce06] + or a + jr z, .check_evolution_and_dragonite + +; an evolution has been found before + xor a + ld [wce06], a + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld c, a + ld e, $00 + ld d, $00 + +; find highest score in wce08 +.loop_score_1 + ld hl, wce08 + add hl, de + ld a, [wce06] + cp [hl] + jr nc, .not_higher + +; store this score to wce06 + ld a, [hl] + ld [wce06], a +; store this PLay Area location to wce07 + ld a, e + ld [wce07], a + +.not_higher + inc e + dec c + jr nz, .loop_score_1 + +; store the deck index of the stage 2 card +; that has been decided in wce1a, +; return the Play Area location of card +; to evolve in a and return carry + ld a, [wce07] + ld e, a + ld hl, wce0f + add hl, de + ld a, [hl] + ld [wce1a], a + ld a, [wce07] + scf + ret + +.check_evolution_and_dragonite + ld a, 7 + ld hl, wce08 + call ZeroData_Bank8 + + xor a + ld [wce06], a + call CreateHandCardList + ld hl, wDuelTempList + push hl + +.loop_hand_2 + pop hl + ld a, [hli] + cp $ff + jr z, .asm_20c0c + + push hl + ld d, a + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld c, a + ld e, PLAY_AREA_ARENA + +.loop_play_area_2 +; check if evolution is possible + push bc + push de + call CheckIfCanEvolveInto_BasicToStage2 + pop de + call nc, .HandleDragonite1Evolution + call nc, .can_evolve + +; not possible to evolve or returned carry +; when handling Dragonite1 evolution + pop bc + inc e + dec c + jr nz, .loop_play_area_2 + jr .loop_hand_2 + +.asm_20c0c + ld a, [wce06] + or a + jr nz, .asm_20c14 +; no evolution was found before + or a + ret + +.asm_20c14 + xor a + ld [wce06], a + ld a, $ff + ld [wce07], a + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld c, a + ld e, $00 + ld d, $00 + +; find highest score in wce08 with at least +; 2 energy cards attached +.loop_score_2 + ld hl, wce08 + add hl, de + ld a, [wce06] + cp [hl] + jr nc, .next_score + +; take the lower 4 bits (total energy cards) +; and skip if less than 2 + ld a, [hl] + ld b, a + and %00001111 + cp 2 + jr c, .next_score + +; has at least 2 energy cards +; store the score in wce06 + ld a, b + ld [wce06], a +; store this PLay Area location to wce07 + ld a, e + ld [wce07], a + +.next_score + inc e + dec c + jr nz, .loop_score_2 + + ld a, [wce07] + cp $ff + jr z, .done + +; a card to evolve was found +; store the deck index of the stage 2 card +; that has been decided in wce1a, +; return the Play Area location of card +; to evolve in a and return carry + ld e, a + ld hl, wce0f + add hl, de + ld a, [hl] + ld [wce1a], a + ld a, [wce07] + scf + ret + +.done + or a + ret + +; return carry if card is evolving to Dragonite1 and if +; - the card that is evolving is not Arena card and +; number of damage counters in Play Area is under 8; +; - the card that is evolving is Arena card and has under 5 +; damage counters or has less than 3 energy cards attached. +.HandleDragonite1Evolution ; 20c5c (8:4c5c) + push af + push bc + push de + push hl + push de + +; check card ID + ld a, d + call GetCardIDFromDeckIndex + ld a, e + pop de + cp DRAGONITE1 + jr nz, .no_carry + +; check card Play Area location + ld a, e + or a + jr z, .active_card_dragonite + +; the card that is evolving is not active card + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld b, a + ld c, 0 + +; count damage counters in Play Area +.loop_play_area_damage + dec b + ld e, b + push bc + call GetCardDamage + pop bc + call ConvertHPToCounters + add c + ld c, a + + ld a, b + or a + jr nz, .loop_play_area_damage + +; compare number of total damage counters +; with 7, if less or equal to that, set carry + ld a, 7 + cp c + jr c, .no_carry + jr .set_carry + +.active_card_dragonite +; the card that is evolving is active card +; compare number of this card's damage counters +; with 5, if less than that, set carry + ld e, PLAY_AREA_ARENA + call GetCardDamage + cp 5 + jr c, .set_carry + +; compare number of this card's attached energy cards +; with 3, if less than that, set carry + ld e, PLAY_AREA_ARENA + farcall CountNumberOfEnergyCardsAttached + cp 3 + jr c, .set_carry + jr .no_carry + +.no_carry + pop hl + pop de + pop bc + pop af + ret + +.set_carry + pop hl + pop de + pop bc + pop af + scf + ret +; 0x20cae + + INCROM $20cae, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, @@ -2242,8 +2598,22 @@ CopyBuffer: ; 2297b (8:697b) jr CopyBuffer ; 0x22983 -Func_22983: ; 22983 (8:6983) - INCROM $22983, $22990 +; zeroes a bytes starting at hl +ZeroData_Bank8: ; 22983 (8:6983) + push af + push bc + push hl + ld b, a + xor a +.loop + ld [hli], a + dec b + jr nz, .loop + pop hl + pop bc + pop af + ret +; 0x22990 ; counts number of energy cards found in hand ; and outputs result in a @@ -2265,8 +2635,27 @@ CountEnergyCardsInHand: ; 22990 (8:6990) ret ; 0x229a3 -Func_229a3 ; 229a3 (8:69a3) - INCROM $229a3, $22bad +; converts HP in a to number of equivalent damage counters +; input: +; a = HP +; output: +; a = number of damage counters +ConvertHPToCounters: ; 229a3 (8:69a3) + push bc + ld c, 0 +.loop + sub 10 + jr c, .carry + inc c + jr .loop +.carry + ld a, c + pop bc + ret +; 0x229b0 + +Func_229b0 ; 229b0 (8:69b0) + INCROM $229b0, $22bad ; return carry flag if move is not high recoil. Func_22bad: ; 22bad (8:6bad) diff --git a/src/wram.asm b/src/wram.asm index 3ed098e..b7f80c7 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1356,17 +1356,14 @@ wce03:: ; ce03 wce06:: ; ce06 ds $1 +wce07:: ; ce07 ds $1 wce08:: ; ce08 - ds $1 - - ds $06 + ds $7 wce0f:: ; ce0f - ds $1 - - ds $06 + ds $7 wce16:: ; ce16 ds $1 -- cgit v1.2.3 From 81c72a30d42eaccd054868f73a2ff0101ed6b5ce Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 11:42:00 +0100 Subject: AI Professor Oak routines --- src/engine/bank05.asm | 89 ++++++++-- src/engine/bank08.asm | 446 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 508 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index c01792c..7a541eb 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -634,7 +634,7 @@ CreateEnergyCardListFromHand: ; 1438c (5:438c) ; looks for card ID in hand and ; sets carry if a card wasn't found -; as opposed to LookForCardIDInHandList +; as opposed to LookForCardIDInHandList_Bank5 ; this function doesn't create a list ; and preserves hl, de and bc ; input: @@ -1317,7 +1317,7 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) .lapras ld a, LAPRAS ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInBench + call LookForCardIDInPlayArea_Bank5 jr nc, .articuno ld e, a call CountNumberOfEnergyCardsAttached @@ -1330,7 +1330,7 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) .articuno ld a, ARTICUNO1 ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInBench + call LookForCardIDInPlayArea_Bank5 jr nc, .dewgong ld a, ARTICUNO1 call RaiseAIScoreToAllMatchingIDsInBench @@ -1339,7 +1339,7 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) .dewgong ld a, DEWGONG ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInBench + call LookForCardIDInPlayArea_Bank5 jr nc, .seel ld a, DEWGONG call RaiseAIScoreToAllMatchingIDsInBench @@ -1348,7 +1348,7 @@ ScoreLegendaryArticunoCards: ; 14c91 (5:4c91) .seel ld a, SEEL ld b, PLAY_AREA_BENCH_1 - call LookForCardIDInBench + call LookForCardIDInPlayArea_Bank5 ret nc ld a, SEEL call RaiseAIScoreToAllMatchingIDsInBench @@ -1386,7 +1386,7 @@ Data_1514f: ; 1514f (5:514f) ; output: ; a = card deck index, if found ; carry set if found -LookForCardIDInHandList: ; 155d2 (5:55d2) +LookForCardIDInHandList_Bank5: ; 155d2 (5:55d2) ld [wTempCardIDToLook], a call CreateHandCardList ld hl, wDuelTempList @@ -1408,7 +1408,7 @@ LookForCardIDInHandList: ; 155d2 (5:55d2) ; 0x155ef ; returns carry if card ID in a -; is found in bench, starting with +; is found in Play Area, starting with ; location in b ; input: ; a = card ID @@ -1416,7 +1416,7 @@ LookForCardIDInHandList: ; 155d2 (5:55d2) ; ouput: ; a = PLAY_AREA_* of found card ; carry set if found -LookForCardIDInBench: ; 155ef (5:55ef) +LookForCardIDInPlayArea_Bank5: ; 155ef (5:55ef) ld [wTempCardIDToLook], a .loop @@ -1450,7 +1450,7 @@ Func_15612: ; 15612 (5:5612) Func_15636: ; 15636 (5:5636) ld a, $10 ld hl, wcda5 - call ZeroData_Bank5 + call ClearMemory_Bank5 ld a, $5 ld [wcda6], a ld a, $ff @@ -1642,7 +1642,7 @@ CheckEnergyNeededForAttackAfterDiscard: ; 156c3 (5:56c3) ; 0x1575e ; zeroes a bytes starting at hl -ZeroData_Bank5: ; 1575e (5:575e) +ClearMemory_Bank5: ; 1575e (5:575e) push af push bc push hl @@ -1766,7 +1766,62 @@ CheckIfAnyCardIDinLocation: ; 157a3 (5:57a3) ; 0x157c6 Func_157c6: ; 157c6 (5:57c6) - INCROM $157c6, $158b2 + INCROM $157c6, $157f3 + +; returns carry if any card with ID in e is found +; in the list that is pointed by hl. +; if one is found, it is removed from the list. +; input: +; e = card ID to look for. +; hl = list to look in +RemoveCardIDInList: ; 157f3 (5:57f3) + push hl + push de + push bc + ld c, e + +.loop_1 + ld a, [hli] + cp $ff + jr z, .no_carry + + ldh [hTempCardIndex_ff98], a + call GetCardIDFromDeckIndex + ld a, c + cp e + jr nz, .loop_1 + +; found + ld d, h + ld e, l + dec hl + +; remove this index from the list +; and reposition the rest of the list ahead. +.loop_2 + ld a, [de] + inc de + ld [hli], a + cp $ff + jr nz, .loop_2 + + ldh a, [hTempCardIndex_ff98] + pop bc + pop de + pop hl + scf + ret + +.no_carry + pop bc + pop de + pop hl + or a + ret +; 0x1581b + +Func_1581b: ; 1581b (5:581b) + INCROM $1581b, $158b2 ; determine AI score for retreating ; return carry if AI decides to retreat @@ -3536,7 +3591,7 @@ LookForEnergyNeededInHand: ; 162c8 (5:62c8) or a jr z, .one_colorless ld a, e - call LookForCardIDInHandList + call LookForCardIDInHandList_Bank5 ret c jr .no_carry @@ -3548,7 +3603,7 @@ LookForEnergyNeededInHand: ; 162c8 (5:62c8) .two_colorless ld a, DOUBLE_COLORLESS_ENERGY - call LookForCardIDInHandList + call LookForCardIDInHandList_Bank5 ret c jr .no_carry ; 0x16311 @@ -3583,7 +3638,7 @@ LookForEnergyNeededForMoveInHand: ; 16311 (5:6311) or a jr z, .one_colorless ld a, e - call LookForCardIDInHandList + call LookForCardIDInHandList_Bank5 ret c jr .done @@ -3595,7 +3650,7 @@ LookForEnergyNeededForMoveInHand: ; 16311 (5:6311) .two_colorless ld a, DOUBLE_COLORLESS_ENERGY - call LookForCardIDInHandList + call LookForCardIDInHandList_Bank5 ret c jr .done ; 0x1633f @@ -6752,7 +6807,7 @@ RaiseAIScoreToAllMatchingIDsInBench: ; 174cd (5:74cd) Func_174f2: ; 174f2 (5:74f2) ld a, MAX_PLAY_AREA_POKEMON ld hl, wcdfa - call ZeroData_Bank5 + call ClearMemory_Bank5 ld a, DUELVARS_BENCH call GetTurnDuelistVariable ld e, 0 @@ -6761,7 +6816,7 @@ Func_174f2: ; 174f2 (5:74f2) push hl ld a, MAX_PLAY_AREA_POKEMON ld hl, wcdea - call ZeroData_Bank5 + call ClearMemory_Bank5 pop hl inc e ld a, [hli] diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 7fd84b2..8965da1 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -21,7 +21,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $05, ENERGY_REMOVAL, CheckEnergyCardToRemoveInPlayArea, AIPlayEnergyRemoval unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, CheckTwoEnergyCardsToRemoveInPlayArea, AIPlaySuperEnergyRemoval unknown_data_20000 $07, POKEMON_BREEDER, CheckIfCanEvolve2StageFromHand, AIPlayPokemonBreeder - unknown_data_20000 $0f, PROFESSOR_OAK, $4cc1, $4cae + unknown_data_20000 $0f, PROFESSOR_OAK, CheckIfCanPlayProfessorOak, AIPlayProfessorOak unknown_data_20000 $0a, ENERGY_RETRIEVAL, $4e6e, $4e44 unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, $4fc1, $4f80 unknown_data_20000 $06, POKEMON_CENTER, $50eb, $50e0 @@ -1995,7 +1995,7 @@ CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) ld a, 7 ld hl, wce08 - call ZeroData_Bank8 + call ClearMemory_Bank8 xor a ld [wce06], a @@ -2137,7 +2137,7 @@ CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) .check_evolution_and_dragonite ld a, 7 ld hl, wce08 - call ZeroData_Bank8 + call ClearMemory_Bank8 xor a ld [wce06], a @@ -2149,7 +2149,7 @@ CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) pop hl ld a, [hli] cp $ff - jr z, .asm_20c0c + jr z, .check_evolution_found push hl ld d, a @@ -2175,15 +2175,15 @@ CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) jr nz, .loop_play_area_2 jr .loop_hand_2 -.asm_20c0c +.check_evolution_found ld a, [wce06] or a - jr nz, .asm_20c14 + jr nz, .evolution_was_found ; no evolution was found before or a ret -.asm_20c14 +.evolution_was_found xor a ld [wce06], a ld a, $ff @@ -2333,7 +2333,338 @@ CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) ret ; 0x20cae - INCROM $20cae, $2282e +AIPlayProfessorOak: ; 20cae (8:4cae) + ld a, [wce21] + or $0c + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x20cc1 + +; sets carry if AI determines a score of playing +; Professor Oak is over a certain threshold. +CheckIfCanPlayProfessorOak: ; 20cc1 (8:4cc1) +; return if cards in deck is less than 7 + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp 54 + ret nc + + ld a, [wOpponentDeckID] + cp LEGENDARY_ARTICUNO_DECK_ID + jp z, .HandleLegendaryArticunoDeck + cp EXCAVATION_DECK_ID + jp z, .HandleExcavationDeck + cp WONDERS_OF_SCIENCE_DECK_ID + jp z, .HandleWondersOfScienceDeck + +; return if cards in deck is less than 15 +.check_cards_deck + ld a, [hl] + cp 46 + ret nc + +; initialize score + ld a, $1e + ld [wce06], a + +; check number of cards in hand +.check_cards_hand + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 4 + jr nc, .more_than_3_cards + +; less than 4 cards in hand + ld a, [wce06] + add $32 + ld [wce06], a + jr .check_energy_cards + +.more_than_3_cards + cp 9 + jr c, .check_energy_cards + +; more than 8 cards + ld a, [wce06] + sub $1e + ld [wce06], a + +.check_energy_cards + farcall CreateEnergyCardListFromHand + jr nc, .handle_blastoise + +; no energy cards in hand + ld a, [wce06] + add $28 + ld [wce06], a + +.handle_blastoise + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .check_hand + +; no Muk in Play Area + ld a, BLASTOISE + call CountPokemonIDInPlayArea + jr nc, .check_hand + +; at least one Blastoise in AI Play Area + ld a, WATER_ENERGY + farcall LookForCardIDInHand + jr nc, .check_hand + +; no Water energy in hand + ld a, [wce06] + add $0a + ld [wce06], a + +; this part seems buggy +; the AI loops through all the cards in hand and checks +; if any of them is not a Pokemon card and has Basic stage. +; it seems like the intention was that if there was +; any Basic Pokemon still in hand, the AI would add to the score. +.check_hand + call CreateHandCardList + ld hl, wDuelTempList +.loop_hand + ld a, [hli] + cp $ff + jr z, .check_evolution + + call LoadCardDataToBuffer1_FromDeckIndex + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr c, .loop_hand ; bug, should be jr nc + + ld a, [wLoadedCard1Stage] + or a + jr nz, .loop_hand + + ld a, [wce06] + add $0a + ld [wce06], a + +.check_evolution + xor a + ld [wce0f], a + ld [wce0f + 1], a + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +.loop_play_area + push de + call .LookForEvolution + pop de + jr nc, .not_in_hand + +; there's a card in hand that can evolve + ld a, $01 + ld [wce0f], a + +.not_in_hand +; check if a card that can evolve was found at all +; if not, go to the next card in the Play Area + ld a, [wce08] + cp $01 + jr nz, .next_play_area + +; if it was found, set wce0f + 1 to $01 + ld a, $01 + ld [wce0f + 1], a + +.next_play_area + inc e + dec d + jr nz, .loop_play_area + +; if a card was found that evolves... + ld a, [wce0f + 1] + or a + jr z, .check_score + +; ...but that card is not in the hand... + ld a, [wce0f] + or a + jr nz, .check_score + +; ...add to the score + ld a, [wce06] + add $0a + ld [wce06], a + +; only return carry if score > $3c +.check_score + ld a, [wce06] + ld b, $3c + cp b + jr nc, .set_carry + or a + ret + +.set_carry + scf + ret +; 0x20d9d + +; return carry if there's a card in the hand that +; can evolve the card in Play Area location in e. +; sets wce08 to $01 if any card is found that can +; evolve regardless of card location. +.LookForEvolution ; 20d9d (8:4d9d) + xor a + ld [wce08], a + ld d, 0 + +; loop through the whole deck to check if there's +; a card that can evolve this Pokemon. +.loop_deck_evolution + push de + call CheckIfCanEvolveInto + pop de + jr nc, .can_evolve +.evolution_not_in_hand + inc d + ld a, DECK_SIZE + cp d + jr nz, .loop_deck_evolution + + or a + ret + +; a card was found that can evolve, set wce08 to $01 +; and if the card is in the hand, return carry. +; otherwise resume looping through deck. +.can_evolve + ld a, $01 + ld [wce08], a + ld a, DUELVARS_CARD_LOCATIONS + add d + call GetTurnDuelistVariable + cp CARD_LOCATION_HAND + jr nz, .evolution_not_in_hand + + scf + ret +; 0x20dc3 + +; handles Legendary Articuno Deck AI logic. +.HandleLegendaryArticunoDeck ; 20dc3 (8:4dc3) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 3 + jr nc, .check_playable_cards + +; has less than 3 Pokemon in Play Area. + push af + call CreateHandCardList + pop af + ld d, a + ld e, PLAY_AREA_ARENA + +; if no cards in hand evolve cards in Play Area, +; returns carry. +.loop_play_area_articuno + ld a, DUELVARS_ARENA_CARD + add e + + push de + call GetTurnDuelistVariable + farcall CheckForEvolutionInList + pop de + jr c, .check_playable_cards + + inc e + ld a, d + cp e + jr nz, .loop_play_area_articuno + +.set_carry_articuno + scf + ret + +; if there are more than 3 energy cards in hand, +; return no carry, otherwise check for playable cards. +.check_playable_cards + call CountEnergyCardsInHand + cp 4 + jr nc, .no_carry_articuno + +; remove both Professor Oak cards from list +; before checking for playable cards + call CreateHandCardList + ld hl, wDuelTempList + ld e, PROFESSOR_OAK + farcall RemoveCardIDInList + ld e, PROFESSOR_OAK + farcall RemoveCardIDInList + +; look in hand for cards that can be played. +; if a card that cannot be played is found, return no carry. +; otherwise return carry. +.loop_hand_articuno + ld a, [hli] + cp $ff + jr z, .set_carry_articuno + push hl + farcall CheckIfCardCanBePlayed + pop hl + jr c, .loop_hand_articuno + +.no_carry_articuno + or a + ret +; 0x20e11 + +; handles Excavation deck AI logic. +; sets score depending on whether there's no +; Mysterious Fossil in play and in hand. +.HandleExcavationDeck ; 20e11 (8:4e11) +; return no carry if cards in deck < 15 + ld a, [hl] + cp 46 + ret nc + +; look for Mysterious Fossil + ld a, MYSTERIOUS_FOSSIL + call LookForCardIDInHandAndPlayArea + jr c, .found_mysterious_fossil + ld a, $50 + ld [wce06], a + jp .check_cards_hand +.found_mysterious_fossil + ld a, $1e + ld [wce06], a + jp .check_cards_hand +; 0x20e2c + +; handles Wonders of Science AI logic. +; if there's either Grimer or Muk in hand, +; do not play Professor Oak. +.HandleWondersOfScienceDeck ; 20e2c (8:4e2c) + ld a, GRIMER + call LookForCardIDInHandList_Bank8 + jr c, .found_grimer_or_muk + ld a, MUK + call LookForCardIDInHandList_Bank8 + jr c, .found_grimer_or_muk + + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + jp .check_cards_deck + +.found_grimer_or_muk + or a + ret +; 0x20e44 + + INCROM $20e44, $2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, @@ -2599,7 +2930,7 @@ CopyBuffer: ; 2297b (8:697b) ; 0x22983 ; zeroes a bytes starting at hl -ZeroData_Bank8: ; 22983 (8:6983) +ClearMemory_Bank8: ; 22983 (8:6983) push af push bc push hl @@ -2655,7 +2986,102 @@ ConvertHPToCounters: ; 229a3 (8:69a3) ; 0x229b0 Func_229b0 ; 229b0 (8:69b0) - INCROM $229b0, $22bad + INCROM $229b0, $229f3 + +; return carry if card ID loaded in a is found in hand +; and outputs in a the deck index of that card +; input: +; a = card ID +; output: +; a = card deck index, if found +; carry set if found +LookForCardIDInHandList_Bank8: ; 229f3 (8:69f3) + ld [wTempCardIDToLook], a + call CreateHandCardList + ld hl, wDuelTempList + +.loop + ld a, [hli] + cp $ff + ret z + + ldh [hTempCardIndex_ff98], a + call LoadCardDataToBuffer1_FromDeckIndex + ld b, a + ld a, [wTempCardIDToLook] + cp b + jr nz, .loop + + ldh a, [hTempCardIndex_ff98] + scf + ret +; 0x22a10 + +Func_22a10 ; 22a10 (8:6a10) + INCROM $22a10, $22a39 + +; returns carry if card ID in a +; is found in Play Area or in hand +; input: +; a = card ID +LookForCardIDInHandAndPlayArea: ; 22a39 (8:6a39) + ld b, a + push bc + call LookForCardIDInHandList_Bank8 + pop bc + ret c + + ld a, b + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank8 + ret c + or a + ret +; 0x22a49 + +Func_22a49 ; 22a49 (8:6a49) + INCROM $22a49, $22a72 + +; returns carry if card ID in a +; is found in Play Area, starting with +; location in b +; input: +; a = card ID +; b = PLAY_AREA_* to start with +; ouput: +; a = PLAY_AREA_* of found card +; carry set if found +LookForCardIDInPlayArea_Bank8: ; 22a72 (8:6a72) + ld [wTempCardIDToLook], a +.loop + ld a, DUELVARS_ARENA_CARD + add b + call GetTurnDuelistVariable + cp $ff + ret z + + call LoadCardDataToBuffer1_FromDeckIndex + ld c, a + ld a, [wTempCardIDToLook] + cp c + jr z, .is_same + + inc b + ld a, MAX_PLAY_AREA_POKEMON + cp b + jr nz, .loop + ld b, $ff + or a + ret + +.is_same + ld a, b + scf + ret +; 0x22a95 + +Func_22a95 ; 22a95 (8:6a95) + INCROM $22a95, $22bad ; return carry flag if move is not high recoil. Func_22bad: ; 22bad (8:6bad) -- cgit v1.2.3 From d86d032bb65bcdfbf666a9d7185d65bbe7e74028 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 14:26:16 +0100 Subject: AI Energy Retrieval routines --- src/engine/bank08.asm | 320 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 316 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 8965da1..3f9ddd9 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -22,7 +22,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, CheckTwoEnergyCardsToRemoveInPlayArea, AIPlaySuperEnergyRemoval unknown_data_20000 $07, POKEMON_BREEDER, CheckIfCanEvolve2StageFromHand, AIPlayPokemonBreeder unknown_data_20000 $0f, PROFESSOR_OAK, CheckIfCanPlayProfessorOak, AIPlayProfessorOak - unknown_data_20000 $0a, ENERGY_RETRIEVAL, $4e6e, $4e44 + unknown_data_20000 $0a, ENERGY_RETRIEVAL, CheckEnergyRetrievalCardsToPick, AIPlayEnergyRetrieval unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, $4fc1, $4f80 unknown_data_20000 $06, POKEMON_CENTER, $50eb, $50e0 unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, $517b, $5170 @@ -1741,7 +1741,7 @@ CheckTwoEnergyCardsToRemoveInPlayArea: ; 209bc (8:49bc) ret z call LoadCardDataToBuffer1_FromDeckIndex cp DOUBLE_COLORLESS_ENERGY - ; any non-double colorless energy card + ; any basic energy card ; will set carry flag here jr nc, .loop_2 ret @@ -1751,7 +1751,7 @@ CheckTwoEnergyCardsToRemoveInPlayArea: ; 209bc (8:49bc) ret ; card in Play Area location e was found with -; a non-double colorless energy card +; a basic energy card .not_double_colorless ld a, e ld [wce0f], a @@ -2664,7 +2664,319 @@ CheckIfCanPlayProfessorOak: ; 20cc1 (8:4cc1) ret ; 0x20e44 - INCROM $20e44, $2282e +AIPlayEnergyRetrieval: ; 20e44 (8:4e44) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce1b] + ldh [hTempRetreatCostCards], a + cp $ff + jr z, .asm_20e68 + ld a, $ff + ldh [$ffa3], a +.asm_20e68 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x20e6e + +; checks whether AI can play Energy Retrieval and +; picks the energy cards from the discard pile, +; and duplicate cards in hand to discard. +CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) +; return no carry if no cards in hand + farcall CreateEnergyCardListFromHand + jp nc, .no_carry + +; handle Go Go Rain Dance deck +; return no carry if there's no Muk card in play and +; if there's no Blastoise card in Play Area +; if there's a Muk in play, continue as normal + ld a, [wOpponentDeckID] + cp GO_GO_RAIN_DANCE_DECK_ID + jr nz, .start + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .start + ld a, BLASTOISE + call CountPokemonIDInPlayArea + jp nc, .no_carry + +.start + call CreateHandCardList + ld hl, wDuelTempList + call .CheckDuplicatePokemonAndNonPokemonCards + jp c, .no_carry + + ld [wce06], a + ld a, CARD_LOCATION_DISCARD_PILE + call FindBasicEnergyCardsInLocation + jp c, .no_carry + +; some basic energy cards were found in Discard Pile + ld a, $ff + ld [wce1a], a + ld [wce1b], a + ld [wce1c], a + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +; first check if there are useful energy cards in the list +; and choose them for retrieval first +.loop_play_area + ld a, DUELVARS_ARENA_CARD + add e + push de + +; load this card's ID in wTempCardID +; and this card's Type in wTempCardType + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + pop de + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + ld [wTempCardType], a + +; loop the energy cards in the Discard Pile +; and check if they are useful for this Pokemon + ld hl, wDuelTempList +.loop_energy_cards_1 + ld a, [hli] + cp $ff + jr z, .next_play_area + + ld b, a + push hl + farcall CheckIfEnergyIsUseful + pop hl + jr nc, .loop_energy_cards_1 + + ld a, [wce1a] + cp $ff + jr nz, .second_energy_1 + +; check if there were already chosen cards, +; if this is the second chosen card, return carry + +; first energy card found + ld a, b + ld [wce1a], a + call .RemoveEnergyCardFromList + jr .next_play_area +.second_energy_1 + ld a, b + ld [wce1b], a + jr .set_carry + +.next_play_area + inc e + dec d + jr nz, .loop_play_area + +; next, if there are still energy cards left to choose, +; loop through the energy cards again and select +; them in order. + ld hl, wDuelTempList +.loop_energy_cards_2 + ld a, [hli] + cp $ff + jr z, .check_chosen + ld b, a + ld a, [wce1a] + cp $ff + jr nz, .second_energy_2 + ld a, b + ld [wce1a], a + call .RemoveEnergyCardFromList + jr .loop_energy_cards_2 + +.second_energy_2 + ld a, b + ld [wce1b], a + jr .set_carry + +; will set carry if at least one has been chosen +.check_chosen + ld a, [wce1a] + cp $ff + jr nz, .set_carry +.no_carry + or a + ret + +.set_carry + ld a, [wce06] + scf + ret +; 0x20f27 + +; function to remove an element from the list +; and shorten it accordingly +.RemoveEnergyCardFromList: ; 20f27 (8:4f27) + push de + ld d, h + ld e, l + dec hl + push hl +.loop_remove + ld a, [de] + ld [hli], a + cp $ff + jr z, .done_remove + inc de + jr .loop_remove +.done_remove + pop hl + pop de + ret +; 0x20f38 + +; returns carry if duplicate cards with found for +; at least one Pokemon card and at least one Non-Pokemon card +.CheckDuplicatePokemonAndNonPokemonCards ; 20f38 (8:4f38) + ld a, $ff + ld [wce0f], a + ld [wce0f + 1], a + push hl + +.loop_outer +; get ID of current card + pop hl + ld a, [hli] + cp $ff + jr z, .check_found + call GetCardIDFromDeckIndex + ld b, e + push hl + +; loop the rest of the list to find +; another card with the same ID +.loop_inner + ld a, [hli] + cp $ff + jr z, .loop_outer + ld c, a + call GetCardIDFromDeckIndex + ld a, e + cp b + jr nz, .loop_inner + +; found two cards with same ID + push bc + call GetCardType + pop bc + cp TYPE_ENERGY + jr c, .not_energy + +; they are energy or trainer cards +; loads wce0f+1 with this card deck index + ld a, c + ld [wce0f + 1], a + jr .loop_outer + +.not_energy +; they are Pokemon cards +; loads wce0f with this card deck index + ld a, c + ld [wce0f], a + jr .loop_outer + +.check_found + ld a, [wce0f] + cp $ff + jr nz, .no_carry_duplicate + ld a, [wce0f + 1] + cp $ff + jr nz, .no_carry_duplicate + +; only set carry if duplicate cards were found +; for both Pokemon and Non-Pokemon cards + scf + ret + +.no_carry_duplicate +; two cards with the same ID were not found +; of either Pokemon and Non-Pokemon cards + or a + ret +; 0x20f80 + + INCROM $20f80, $227f6 + +; lists in wDuelTempList all the basic energy cards +; is card location of a. +; returns carry if none were found. +; input: +; a = CARD_LOCATION_* to look +FindBasicEnergyCardsInLocation: ; 227f6 (8:67f6) + ld [wTempAI], a + lb de, 0, 0 + ld hl, wDuelTempList + +; d = number of basic energy cards found +; e = current card in deck +; loop entire deck +.loop + ld a, DUELVARS_CARD_LOCATIONS + add e + push hl + call GetTurnDuelistVariable + ld hl, wTempAI + cp [hl] + pop hl + jr nz, .next_card + +; is in the card location we're looking for + ld a, e + push de + push hl + call GetCardIDFromDeckIndex + pop hl + ld a, e + pop de + cp DOUBLE_COLORLESS_ENERGY + ; only basic energy cards + ; will set carry here + jr nc, .next_card + +; is a basic energy card +; add this card to the TempList + ld a, e + ld [hli], a + inc d +.next_card + inc e + ld a, DECK_SIZE + cp e + jr nz, .loop + +; check if any were found + ld a, d + or a + jr z, .set_carry + +; some were found, add the termination byte on TempList + ld a, $ff + ld [hl], a + ld a, d + ret + +.set_carry + scf + ret +; 0x2282e ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, -- cgit v1.2.3 From 58d836385d600515ae0a7e689e1a12db88fbdfec Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 14:58:48 +0100 Subject: AI Super Energy Retrieval routines --- src/engine/bank08.asm | 260 +++++++++++++++++++++++++++++++++++++++++++++++--- src/wram.asm | 6 +- 2 files changed, 252 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 3f9ddd9..a5f35c5 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -23,7 +23,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $07, POKEMON_BREEDER, CheckIfCanEvolve2StageFromHand, AIPlayPokemonBreeder unknown_data_20000 $0f, PROFESSOR_OAK, CheckIfCanPlayProfessorOak, AIPlayProfessorOak unknown_data_20000 $0a, ENERGY_RETRIEVAL, CheckEnergyRetrievalCardsToPick, AIPlayEnergyRetrieval - unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, $4fc1, $4f80 + unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, CheckSuperEnergyRetrievalCardsToPick, AIPlaySuperEnergyRetrieval unknown_data_20000 $06, POKEMON_CENTER, $50eb, $50e0 unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, $517b, $5170 unknown_data_20000 $0c, ENERGY_SEARCH, $51aa, $519a @@ -2709,9 +2709,10 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) jp nc, .no_carry .start +; find duplicate cards in hand call CreateHandCardList ld hl, wDuelTempList - call .CheckDuplicatePokemonAndNonPokemonCards + call CheckDuplicatePokemonAndNonPokemonCards jp c, .no_carry ld [wce06], a @@ -2773,7 +2774,7 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) ; first energy card found ld a, b ld [wce1a], a - call .RemoveEnergyCardFromList + call RemoveCardFromList jr .next_play_area .second_energy_1 ld a, b @@ -2799,7 +2800,7 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) jr nz, .second_energy_2 ld a, b ld [wce1a], a - call .RemoveEnergyCardFromList + call RemoveCardFromList jr .loop_energy_cards_2 .second_energy_2 @@ -2822,9 +2823,11 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) ret ; 0x20f27 -; function to remove an element from the list -; and shorten it accordingly -.RemoveEnergyCardFromList: ; 20f27 (8:4f27) +; remove an element from the list +; and shortens it accordingly +; input: +; hl = pointer to element to remove +RemoveCardFromList: ; 20f27 (8:4f27) push de ld d, h ld e, l @@ -2843,9 +2846,13 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) ret ; 0x20f38 -; returns carry if duplicate cards with found for +; returns carry if duplicate cards are found for ; at least one Pokemon card and at least one Non-Pokemon card -.CheckDuplicatePokemonAndNonPokemonCards ; 20f38 (8:4f38) +; input: +; hl = list to look in +; output: +; a = deck index of duplicate non-Pokemon card +CheckDuplicatePokemonAndNonPokemonCards: ; 20f38 (8:4f38) ld a, $ff ld [wce0f], a ld [wce0f + 1], a @@ -2896,24 +2903,251 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) .check_found ld a, [wce0f] cp $ff - jr nz, .no_carry_duplicate + jr nz, .no_carry ld a, [wce0f + 1] cp $ff - jr nz, .no_carry_duplicate + jr nz, .no_carry ; only set carry if duplicate cards were found ; for both Pokemon and Non-Pokemon cards scf ret -.no_carry_duplicate +.no_carry ; two cards with the same ID were not found ; of either Pokemon and Non-Pokemon cards or a ret ; 0x20f80 - INCROM $20f80, $227f6 +AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce1b] + ldh [hTempRetreatCostCards], a + ld a, [wce1c] + ldh [$ffa3], a + cp $ff + jr z, .asm_20fbb + ld a, [wce1d] + ldh [$ffa4], a + cp $ff + jr z, .asm_20fbb + ld a, [wce1e] + ldh [$ffa5], a + cp $ff + jr z, .asm_20fbb + ld a, $ff + ldh [$ffa6], a +.asm_20fbb + ld a, $07 + bank1call AIMakeDecision + ret +; 0x20fc1 + +CheckSuperEnergyRetrievalCardsToPick: ; 20fc1 (8:4fc1) +; return no carry if no cards in hand + farcall CreateEnergyCardListFromHand + jp nc, .no_carry + +; handle Go Go Rain Dance deck +; return no carry if there's no Muk card in play and +; if there's no Blastoise card in Play Area +; if there's a Muk in play, continue as normal + ld a, [wOpponentDeckID] + cp GO_GO_RAIN_DANCE_DECK_ID + jr nz, .start + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .start + ld a, BLASTOISE + call CountPokemonIDInPlayArea + jp nc, .no_carry + +.start +; find duplicate cards in hand + call CreateHandCardList + ld hl, wDuelTempList + call CheckDuplicatePokemonAndNonPokemonCards + jp c, .no_carry + +; remove the duplicate non-Pokemon card in hand +; and run the hand check again + ld [wce06], a + ld hl, wDuelTempList + call .RemoveDuplicateCardFromHandList + call CheckDuplicatePokemonAndNonPokemonCards + jp c, .no_carry + + ld [wce08], a + ld a, CARD_LOCATION_DISCARD_PILE + call FindBasicEnergyCardsInLocation + jp c, .no_carry + +; some basic energy cards were found in Discard Pile + ld a, $ff + ld [wce1b], a + ld [wce1c], a + ld [wce1d], a + ld [wce1e], a + ld [wce1f], a + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +; first check if there are useful energy cards in the list +; and choose them for retrieval first +.loop_play_area + ld a, DUELVARS_ARENA_CARD + add e + push de + +; load this card's ID in wTempCardID +; and this card's Type in wTempCardType + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + pop de + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + ld [wTempCardType], a + +; loop the energy cards in the Discard Pile +; and check if they are useful for this Pokemon + ld hl, wDuelTempList +.loop_energy_cards_1 + ld a, [hli] + cp $ff + jr z, .next_play_area + + ld b, a + push hl + farcall CheckIfEnergyIsUseful + pop hl + jr nc, .loop_energy_cards_1 + +; first energy + ld a, [wce1b] + cp $ff + jr nz, .second_energy_1 + ld a, b + ld [wce1b], a + call RemoveCardFromList + jr .next_play_area + +.second_energy_1 + ld a, [wce1c] + cp $ff + jr nz, .third_energy_1 + ld a, b + ld [wce1c], a + call RemoveCardFromList + jr .next_play_area + +.third_energy_1 + ld a, [wce1d] + cp $ff + jr nz, .fourth_energy_1 + ld a, b + ld [wce1d], a + call RemoveCardFromList + jr .next_play_area + +.fourth_energy_1 + ld a, b + ld [wce1e], a + jr .set_carry + +.next_play_area + inc e + dec d + jr nz, .loop_play_area + +; next, if there are still energy cards left to choose, +; loop through the energy cards again and select +; them in order. + ld hl, wDuelTempList +.loop_energy_cards_2 + ld a, [hli] + cp $ff + jr z, .check_chosen + ld b, a + ld a, [wce1b] + cp $ff + jr nz, .second_energy_2 + ld a, b + +; first energy + ld [wce1b], a + call RemoveCardFromList + jr .loop_energy_cards_2 + +.second_energy_2 + ld a, [wce1c] + cp $ff + jr nz, .third_energy_2 + ld a, b + ld [wce1c], a + call RemoveCardFromList + jr .loop_energy_cards_2 + +.third_energy_2 + ld a, [wce1d] + cp $ff + jr nz, .fourth_energy + ld a, b + ld [wce1d], a + call RemoveCardFromList + jr .loop_energy_cards_2 + +.fourth_energy + ld a, b + ld [wce1e], a + jr .set_carry + +; will set carry if at least one has been chosen +.check_chosen + ld a, [wce1b] + cp $ff + jr nz, .set_carry + +.no_carry + or a + ret +.set_carry + ld a, [wce08] + ld [wce1a], a + ld a, [wce06] + scf + ret +; 0x210d5 + +; finds the energy card that was found to be a duplicate +; and removes it from the hand card list. +.RemoveDuplicateCardFromHandList ; 210d5 (8:50d5) + push hl + ld b, a +.loop_duplicate + ld a, [hli] + cp b + jr nz, .loop_duplicate + call RemoveCardFromList + pop hl + ret +; 0x210e0 + + INCROM $210e0, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. diff --git a/src/wram.asm b/src/wram.asm index b7f80c7..c0ff24e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1389,7 +1389,11 @@ wce1c:: ; ce1c wce1d:: ; ce1d ds $1 - ds $2 +wce1e:: ; ce1e + ds $1 + +wce1f:: ; ce1f + ds $1 wce20:: ; ce20 ds $1 -- cgit v1.2.3 From 271372930487c67641367f644b35619f7b453368 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 15:29:38 +0100 Subject: AI Pokemon Center routines --- src/engine/bank05.asm | 26 +++++------ src/engine/bank08.asm | 126 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 135 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 7a541eb..e9191da 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1659,7 +1659,7 @@ ClearMemory_Bank5: ; 1575e (5:575e) ; 0x1576b ; returns in a the tens digit of value in a -CalculateTensDigit: ; 1576b (5:576b) +CalculateByteTensDigit: ; 1576b (5:576b) push bc ld c, 0 .loop @@ -2354,7 +2354,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ld a, [wSelectedMoveIndex] call EstimateDamage_VersusDefendingCard ld a, [wDamage] - call CalculateTensDigit + call CalculateByteTensDigit inc a call AddToAIScore ret @@ -2368,7 +2368,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ld a, [wSelectedMoveIndex] call EstimateDamage_VersusDefendingCard ld a, [wDamage] - call CalculateTensDigit + call CalculateByteTensDigit srl a call AddToAIScore @@ -2496,7 +2496,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ld b, a ld a, 4 call CalculateBDividedByA - call CalculateTensDigit + call CalculateByteTensDigit call AddToAIScore ; raise AI score if @@ -3159,7 +3159,7 @@ AIDecideEvolution: ; 15f4c (5:5f4c) jr z, .check_mysterious_fossil srl a srl a - call CalculateTensDigit + call CalculateByteTensDigit call SubFromAIScore ; if is Mysterious Fossil or @@ -4135,7 +4135,7 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ld a, DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable - call CalculateTensDigit + call CalculateByteTensDigit cp 3 jr nc, .check_defending_can_ko ; hp < 30 @@ -4179,7 +4179,7 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) .bench add DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable - call CalculateTensDigit + call CalculateByteTensDigit cp 3 jr nc, .asm_165e1 ; hp < 30 @@ -5197,7 +5197,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ld [wTempAI], a or a jr z, .no_damage - call CalculateTensDigit + call CalculateByteTensDigit call AddToAIScore jr .check_recoil .no_damage @@ -5235,7 +5235,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ld [wDamage], a call ApplyDamageModifiers_DamageToSelf ld a, e - call CalculateTensDigit + call CalculateByteTensDigit call SubFromAIScore push de @@ -5513,7 +5513,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) cp 1 jr z, .tally_heal_score ld a, [wTempAI] - call CalculateTensDigit + call CalculateByteTensDigit ld b, a ld a, [wLoadedMoveUnknown1] cp 3 @@ -5524,7 +5524,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) .asm_16cec ld a, DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable - call CalculateTensDigit + call CalculateByteTensDigit cp b jr c, .tally_heal_score ld a, b @@ -5532,7 +5532,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) push af ld e, PLAY_AREA_ARENA call GetCardDamage - call CalculateTensDigit + call CalculateByteTensDigit pop bc cp b ; wLoadedMoveUnknown1 jr c, .add_heal_score @@ -6930,7 +6930,7 @@ Func_17583: ; 17583 (5:7583) push hl push de call GetCardDamage - call CalculateTensDigit + call CalculateByteTensDigit ld b, a push bc call CountNumberOfEnergyCardsAttached diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index a5f35c5..6d05f74 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -24,7 +24,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0f, PROFESSOR_OAK, CheckIfCanPlayProfessorOak, AIPlayProfessorOak unknown_data_20000 $0a, ENERGY_RETRIEVAL, CheckEnergyRetrievalCardsToPick, AIPlayEnergyRetrieval unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, CheckSuperEnergyRetrievalCardsToPick, AIPlaySuperEnergyRetrieval - unknown_data_20000 $06, POKEMON_CENTER, $50eb, $50e0 + unknown_data_20000 $06, POKEMON_CENTER, CheckIfCanPlayPokemonCenter, AIPlayPokemonCenter unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, $517b, $5170 unknown_data_20000 $0c, ENERGY_SEARCH, $51aa, $519a unknown_data_20000 $03, POKEDEX, $52dc, $52b4 @@ -3147,7 +3147,108 @@ CheckSuperEnergyRetrievalCardsToPick: ; 20fc1 (8:4fc1) ret ; 0x210e0 - INCROM $210e0, $227f6 +AIPlayPokemonCenter: ; 210e0 (8:50e0) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x210eb + +CheckIfCanPlayPokemonCenter: ; 210eb (8:50eb) + xor a + ldh [hTempPlayAreaLocation_ff9d], a + +; return if active Pokemon can KO player's card. + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .start + farcall CheckIfSelectedMoveIsUnusable + jr nc, .no_carry + farcall LookForEnergyNeededForMoveInHand + jr c, .no_carry + +.start + xor a + ld [wce06], a + ld [wce08], a + ld [wce0f], a + + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +.loop_play_area + ld a, DUELVARS_ARENA_CARD + add e + push de + call GetTurnDuelistVariable + call LoadCardDataToBuffer1_FromDeckIndex + ld a, e + pop de + +; get this Pokemon's current HP in number of counters +; and add it to the total. + ld a, [wLoadedCard1HP] + call ConvertHPToCounters + ld b, a + ld a, [wce06] + add b + ld [wce06], a + +; get this Pokemon's current damage counters +; and add it to the total. + call GetCardDamage + call ConvertHPToCounters + ld b, a + ld a, [wce08] + add b + ld [wce08], a + +; get this Pokemon's number of attached energy cards +; and add it to the total. +; if there's overflow, return no carry. + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + ld b, a + ld a, [wce0f] + add b + jr c, .no_carry + ld [wce0f], a + + inc e + dec d + jr nz, .loop_play_area + +; if (number of damage counters / 2) < (total energy cards attached) +; return no carry. + ld a, [wce08] + srl a + ld hl, wce0f + cp [hl] + jr c, .no_carry + +; if (number of HP counters * 6 / 10) >= (number of damage counters) +; return no carry. + ld a, [wce06] + ld l, a + ld h, 6 + call HtimesL + call CalculateWordTensDigit + ld a, l + ld hl, wce08 + cp [hl] + jr nc, .no_carry + + scf + ret + +.no_carry + or a + ret +; 0x21170 + + INCROM $21170, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. @@ -3531,8 +3632,25 @@ ConvertHPToCounters: ; 229a3 (8:69a3) ret ; 0x229b0 -Func_229b0 ; 229b0 (8:69b0) - INCROM $229b0, $229f3 +; calculates floor(hl / 10) +CalculateWordTensDigit: ; 229b0 (8:69b0) + push bc + push de + lb bc, $ff, -10 + lb de, $ff, -1 +.asm_229b8 + inc de + add hl, bc + jr c, .asm_229b8 + ld h, d + ld l, e + pop de + pop bc + ret +; 0x229c1 + +Func_229c1 ; 229c1 (8:69c1) + INCROM $229c1, $229f3 ; 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 4697f2d0e86038179dd5b1f4e03dc4d80d614615 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 16:28:45 +0100 Subject: AI Imposter Professor Oak routines --- src/engine/bank08.asm | 54 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 6d05f74..2f38c4e 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -25,7 +25,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0a, ENERGY_RETRIEVAL, CheckEnergyRetrievalCardsToPick, AIPlayEnergyRetrieval unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, CheckSuperEnergyRetrievalCardsToPick, AIPlaySuperEnergyRetrieval unknown_data_20000 $06, POKEMON_CENTER, CheckIfCanPlayPokemonCenter, AIPlayPokemonCenter - unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, $517b, $5170 + unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, CheckWhetherToPlayImposterProfessorOak, AIPlayImposterProfessorOak unknown_data_20000 $0c, ENERGY_SEARCH, $51aa, $519a unknown_data_20000 $03, POKEDEX, $52dc, $52b4 unknown_data_20000 $07, FULL_HEAL, $5428, $541d @@ -1465,11 +1465,11 @@ AIPlayBill: ; 2086d (8:486d) ret ; 0x20878 -; return carry if cards not in deck < 51 +; return carry if cards in deck > 9 CheckDeckCardsAmount: ; 20878 (8:4878) ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable - cp 51 + cp DECK_SIZE - 9 ret ; 0x20880 @@ -2347,10 +2347,10 @@ AIPlayProfessorOak: ; 20cae (8:4cae) ; sets carry if AI determines a score of playing ; Professor Oak is over a certain threshold. CheckIfCanPlayProfessorOak: ; 20cc1 (8:4cc1) -; return if cards in deck is less than 7 +; return if cards in deck <= 6 ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable - cp 54 + cp DECK_SIZE - 6 ret nc ld a, [wOpponentDeckID] @@ -2361,10 +2361,10 @@ CheckIfCanPlayProfessorOak: ; 20cc1 (8:4cc1) cp WONDERS_OF_SCIENCE_DECK_ID jp z, .HandleWondersOfScienceDeck -; return if cards in deck is less than 15 +; return if cards in deck <= 14 .check_cards_deck ld a, [hl] - cp 46 + cp DECK_SIZE - 14 ret nc ; initialize score @@ -3248,7 +3248,45 @@ CheckIfCanPlayPokemonCenter: ; 210eb (8:50eb) ret ; 0x21170 - INCROM $21170, $227f6 +AIPlayImposterProfessorOak: ; 21170 (8:5170) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x2117b + +; sets carry depending on player's number of cards +; in deck in in hand. +CheckWhetherToPlayImposterProfessorOak: ; 2117b (8:517b) + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetNonTurnDuelistVariable + cp DECK_SIZE - 14 + jr c, .more_than_14_cards + +; if player has less than 14 cards in deck, only +; set carry if number of cards in their hands < 6 + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetNonTurnDuelistVariable + cp 6 + jr c, .set_carry +.no_carry + or a + ret + +; if player has more than 14 cards in deck, only +; set carry if number of cards in their hands >= 9 +.more_than_14_cards + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetNonTurnDuelistVariable + cp 9 + jr c, .no_carry +.set_carry + scf + ret +; 0x2119a + + INCROM $2119a, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From e00e2aab1627f668a30ea423fe4be1d4d9709f23 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 18:36:01 +0100 Subject: AI Energy Search routines --- src/engine/bank08.asm | 252 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 250 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 2f38c4e..94d53a4 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -26,7 +26,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, CheckSuperEnergyRetrievalCardsToPick, AIPlaySuperEnergyRetrieval unknown_data_20000 $06, POKEMON_CENTER, CheckIfCanPlayPokemonCenter, AIPlayPokemonCenter unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, CheckWhetherToPlayImposterProfessorOak, AIPlayImposterProfessorOak - unknown_data_20000 $0c, ENERGY_SEARCH, $51aa, $519a + unknown_data_20000 $0c, ENERGY_SEARCH, CheckIfEnergySearchCanBePlayed, AIPlayEnergySearch unknown_data_20000 $03, POKEDEX, $52dc, $52b4 unknown_data_20000 $07, FULL_HEAL, $5428, $541d unknown_data_20000 $0a, MR_FUJI, $54a7, $5497 @@ -3286,7 +3286,255 @@ CheckWhetherToPlayImposterProfessorOak: ; 2117b (8:517b) ret ; 0x2119a - INCROM $2119a, $227f6 +AIPlayEnergySearch: ; 2119a (8:519a) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x211aa + +; AI checks for playing Energy Search +CheckIfEnergySearchCanBePlayed: ; 211aa (8:51aa) + farcall CreateEnergyCardListFromHand + jr c, .start + call .CheckForUsefulEnergyCards + jr c, .start + +; there are energy cards in hand and at least +; one of them is useful to a card in Play Area +.no_carry + or a + ret + +.start + ld a, [wOpponentDeckID] + cp HEATED_BATTLE_DECK_ID + jr z, .heated_battle + cp WONDERS_OF_SCIENCE_DECK_ID + jr z, .wonders_of_science + +; if no energy cards in deck, return no carry + ld a, CARD_LOCATION_DECK + call FindBasicEnergyCardsInLocation + jr c, .no_carry + +; if any of the energy cards in deck is useful +; return carry right away... + call .CheckForUsefulEnergyCards + jr c, .no_useful + scf + ret + +; ...otherwise save the list in a before return carry. +.no_useful + ld a, [wDuelTempList] + scf + ret + +; Heated Battle deck only searches for Fire and Lightning +; if they are found to be useful to some card in Play Area +.heated_battle + ld a, CARD_LOCATION_DECK + call FindBasicEnergyCardsInLocation + jr c, .no_carry + call .CheckUsefulFireOrLightningEnergy + jr c, .no_carry + scf + ret + +; this subroutine has a bug. +; it was supposed to use the .CheckUsefulGrassEnergy subroutine +; but uses .CheckUsefulFireOrLightningEnergy instead. +.wonders_of_science + ld a, CARD_LOCATION_DECK + call FindBasicEnergyCardsInLocation + jr c, .no_carry + call .CheckUsefulFireOrLightningEnergy + jr c, .no_carry + scf + ret +; 0x211f1 + +; return carry if cards in wDuelTempList are not +; useful to any of the Play Area Pokemon +.CheckForUsefulEnergyCards ; 211f1 (8:51f1) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +.loop_play_area_1 + ld a, DUELVARS_ARENA_CARD + add e + push de + call GetTurnDuelistVariable + +; store ID and type of card + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + pop de + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + ld [wTempCardType], a + +; look in list for a useful energy, +; is any is found return no carry. + ld hl, wDuelTempList +.loop_energy_1 + ld a, [hli] + cp $ff + jr z, .none_found + ld b, a + push hl + farcall CheckIfEnergyIsUseful + pop hl + jr nc, .loop_energy_1 + + ld a, b + or a + ret + +.none_found + inc e + ld a, e + cp d + jr nz, .loop_play_area_1 + + scf + ret +; 0x2122e + +; checks whether there are useful energies +; only for Fire and Lightning type Pokemon cards +; in Play Area. If none found, return carry. +.CheckUsefulFireOrLightningEnergy ; 2122e (8:522e) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +.loop_play_area_2 + ld a, DUELVARS_ARENA_CARD + add e + push de + call GetTurnDuelistVariable + +; get card's ID and Type + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + pop de + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + +; only do check if the Pokemon's type +; is either Fire or Lightning + cp TYPE_ENERGY_FIRE + jr z, .fire_or_lightning + cp TYPE_ENERGY_LIGHTNING + jr nz, .next_play_area + +; loop each energy card in list +.fire_or_lightning + ld [wTempCardType], a + ld hl, wDuelTempList +.loop_energy_2 + ld a, [hli] + cp $ff + jr z, .next_play_area + +; if this energy card is useful, +; return no carry. + ld b, a + push hl + farcall CheckIfEnergyIsUseful + pop hl + jr nc, .loop_energy_2 + + ld a, b + or a + ret + +.next_play_area + inc e + ld a, e + cp d + jr nz, .loop_play_area_2 + +; no card was found to be useful +; for Fire/Lightning type Pokemon card. + scf + ret +; 0x21273 + +; checks whether there are useful energies +; only for Grass type Pokemon cards +; in Play Area. If none found, return carry. +.CheckUsefulGrassEnergy ; 21273 (8:5273) +; unreferenced + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA + +.loop_play_area_3 + ld a, DUELVARS_ARENA_CARD + add e + push de + call GetTurnDuelistVariable + +; get card's ID and Type + call GetCardIDFromDeckIndex + ld a, e + ld [wTempCardID], a + call LoadCardDataToBuffer1_FromCardID + pop de + ld a, [wLoadedCard1Type] + or TYPE_ENERGY + +; only do check if the Pokemon's type is Grass + cp TYPE_ENERGY_GRASS + jr nz, .next_play_area_3 + +; loop each energy card in list + ld [wTempCardType], a + ld hl, wDuelTempList +.loop_energy_3 + ld a, [hli] + cp $ff + jr z, .next_play_area_3 + +; if this energy card is useful, +; return no carry. + ld b, a + push hl + farcall CheckIfEnergyIsUseful + pop hl + jr nc, .loop_energy_3 + + ld a, b + or a + ret + +.next_play_area_3 + inc e + ld a, e + cp d + jr nz, .loop_play_area_3 + +; no card was found to be useful +; for Grass type Pokemon card. + scf + ret +; 0x212b4 + + INCROM $212b4, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From afdbd70def59e1be6584d41a4ba8c5e08d8f749f Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 21:39:25 +0100 Subject: AI Pokedex routines --- src/engine/bank08.asm | 319 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 318 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 94d53a4..fbf59c5 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -3534,7 +3534,324 @@ CheckIfEnergySearchCanBePlayed: ; 211aa (8:51aa) ret ; 0x212b4 - INCROM $212b4, $227f6 +AIPlayPokedex: ; 212b4 (8:52b4) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce1a] + ldh [hTemp_ffa0], a + ld a, [wce1b] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce1c] + ldh [hTempRetreatCostCards], a + ld a, [wce1d] + ldh [$ffa3], a + ld a, [wce1e] + ldh [$ffa4], a + ld a, $ff + ldh [$ffa5], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x212dc + +Func_212dc: ; 212dc (8:52dc) + ld a, [wcda6] + cp $06 + jr c, .no_carry + +; return no carry if number of cards in deck <= 4 + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 4 + jr nc, .no_carry + +; has a 3 in 10 chance of actually playing card + ld a, 10 + call Random + cp 3 + jr c, .pick_cards + +.no_carry + or a + ret + +.pick_cards +; the following comparison is disregarded +; the Wonders of Science deck was probably intended +; to use PickPokedexCards_Unreferenced instead + ld a, [wOpponentDeckID] + cp WONDERS_OF_SCIENCE_DECK_ID + jp PickPokedexCards ; bug, should be jp nz +; 0x212ff + +; picks order of the cards in deck from the effects of Pokedex. +; prioritises Pokemon cards, then Trainer cards, then energy cards. +; stores the resulting order in wce1a. +PickPokedexCards_Unreferenced: ; 212ff (8:52ff) +; unreferenced + xor a + ld [wcda6], a + + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + add DUELVARS_DECK_CARDS + ld l, a + lb de, $00, $00 + ld b, 5 + +; run through 5 of the remaining cards in deck +.next_card + ld a, [hli] + ld c, a + call .GetCardType + +; load this card's deck index and type in memory +; wce08 = card types +; wce0f = card deck indices + push hl + ld hl, wce08 + add hl, de + ld [hl], a + ld hl, wce0f + add hl, de + ld [hl], c + pop hl + + inc e + dec b + jr nz, .next_card + +; terminate the wce08 list + ld a, $ff + ld [wce08 + 5], a + + ld de, wce1a + +; find Pokemon + ld hl, wce08 + ld c, -1 + ld b, $00 + +; run through the stored cards +; and look for any Pokemon cards. +.loop_pokemon + inc c + ld a, [hli] + cp $ff + jr z, .find_trainers + cp TYPE_ENERGY + jr nc, .loop_pokemon +; found a Pokemon card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_pokemon + +; run through the stored cards +; and look for any Trainer cards. +.find_trainers + ld hl, wce08 + ld c, -1 + ld b, $00 + +.loop_trainers + inc c + ld a, [hli] + cp $ff + jr z, .find_energy + cp TYPE_TRAINER + jr nz, .loop_trainers +; found a Trainer card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_trainers + +.find_energy + ld hl, wce08 + ld c, -1 + ld b, $00 + +; run through the stored cards +; and look for any energy cards. +.loop_energy + inc c + ld a, [hli] + cp $ff + jr z, .done + and TYPE_ENERGY + jr z, .loop_energy +; found an energy card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_energy + +.done + scf + ret +; 0x21383 + +.GetCardType ; 21383 (8:5383) + push bc + push de + call GetCardIDFromDeckIndex + call GetCardType + pop de + pop bc + ret +; 0x2138e + +; picks order of the cards in deck from the effects of Pokedex. +; prioritises energy cards, then Pokemon cards, then Trainer cards. +; stores the resulting order in wce1a. +PickPokedexCards: ; 2138e (8:538e) + xor a + ld [wcda6], a + + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + add DUELVARS_DECK_CARDS + ld l, a + lb de, $00, $00 + ld b, 5 + +; run through 5 of the remaining cards in deck +.next_card + ld a, [hli] + ld c, a + call .GetCardType + +; load this card's deck index and type in memory +; wce08 = card types +; wce0f = card deck indices + push hl + ld hl, wce08 + add hl, de + ld [hl], a + ld hl, wce0f + add hl, de + ld [hl], c + pop hl + + inc e + dec b + jr nz, .next_card + +; terminate the wce08 list + ld a, $ff + ld [wce08 + 5], a + + ld de, wce1a + +; find energy + ld hl, wce08 + ld c, -1 + ld b, $00 + +; run through the stored cards +; and look for any energy cards. +.loop_energy + inc c + ld a, [hli] + cp $ff + jr z, .find_pokemon + and TYPE_ENERGY + jr z, .loop_energy +; found an energy card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_energy + +.find_pokemon + ld hl, wce08 + ld c, -1 + ld b, $00 + +; run through the stored cards +; and look for any Pokemon cards. +.loop_pokemon + inc c + ld a, [hli] + cp $ff + jr z, .find_trainers + cp TYPE_ENERGY + jr nc, .loop_pokemon +; found a Pokemon card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_pokemon + +; run through the stored cards +; and look for any Trainer cards. +.find_trainers + ld hl, wce08 + ld c, -1 + ld b, $00 + +.loop_trainers + inc c + ld a, [hli] + cp $ff + jr z, .done + cp TYPE_TRAINER + jr nz, .loop_trainers +; found a Trainer card +; store it in wce1a list + push hl + ld hl, wce0f + add hl, bc + ld a, [hl] + pop hl + ld [de], a + inc de + jr .loop_trainers + +.done + scf + ret +; 0x21412 + +.GetCardType ; 21412 (8:5412) + push bc + push de + call GetCardIDFromDeckIndex + call GetCardType + pop de + pop bc + ret +; 0x2141d + + INCROM $2141d, $227f6 + + ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From 6c503f1c03ac70e7098580924166bd37c48a95cb Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 15 Apr 2020 22:57:47 +0100 Subject: AI Full Heal routines --- src/engine/bank08.asm | 104 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index fbf59c5..0625fa3 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -27,8 +27,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $06, POKEMON_CENTER, CheckIfCanPlayPokemonCenter, AIPlayPokemonCenter unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, CheckWhetherToPlayImposterProfessorOak, AIPlayImposterProfessorOak unknown_data_20000 $0c, ENERGY_SEARCH, CheckIfEnergySearchCanBePlayed, AIPlayEnergySearch - unknown_data_20000 $03, POKEDEX, $52dc, $52b4 - unknown_data_20000 $07, FULL_HEAL, $5428, $541d + unknown_data_20000 $03, POKEDEX, CheckWhetherToPlayPokedex, AIPlayPokedex + unknown_data_20000 $07, FULL_HEAL, CheckWhetherToPlayFullHeal, AIPlayFullHeal unknown_data_20000 $0a, MR_FUJI, $54a7, $5497 unknown_data_20000 $0a, SCOOP_UP, $5506, $54f1 unknown_data_20000 $02, MAINTENANCE, $562c, $560f @@ -3554,7 +3554,7 @@ AIPlayPokedex: ; 212b4 (8:52b4) ret ; 0x212dc -Func_212dc: ; 212dc (8:52dc) +CheckWhetherToPlayPokedex: ; 212dc (8:52dc) ld a, [wcda6] cp $06 jr c, .no_carry @@ -3849,9 +3849,105 @@ PickPokedexCards: ; 2138e (8:538e) ret ; 0x2141d - INCROM $2141d, $227f6 +AIPlayFullHeal: ; 2141d (8:541d) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x21428 + +CheckWhetherToPlayFullHeal: ; 21428 (8:5428) + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + +; skip if no status on arena card + or a ; NO_STATUS + jr z, .no_carry + + and CNF_SLP_PRZ + cp PARALYZED + jr z, .paralyzed + cp ASLEEP + jr z, .asleep + cp CONFUSED + jr z, .confused + ; if either PSN or DBLPSN, fallthrough + +.set_carry + scf + ret + +.asleep +; set carry if any of the following +; cards are in the Play Area. + ld a, GASTLY1 + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank8 + jr c, .set_carry + ld a, GASTLY2 + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank8 + jr c, .set_carry + ld a, HAUNTER2 + ld b, PLAY_AREA_ARENA + call LookForCardIDInPlayArea_Bank8 + jr c, .set_carry + +; otherwise fallthrough + +.paralyzed +; if Scoop Up is in hand and decided to be played, skip. + ld a, SCOOP_UP + call LookForCardIDInHandList_Bank8 + jr nc, .no_scoop_up_prz + call Func_21506 + jr c, .no_carry + +.no_scoop_up_prz +; if card can damage defending Pokemon... + xor a ; PLAY_AREA_ARENA + farcall CheckIfCanDamageDefendingPokemon + jr nc, .no_carry +; ...and can play an energy card to retreat, set carry. + ld a, [wAIPlayEnergyCardForRetreat] + or a + jr nz, .set_carry + +; if not, check whether it's a card it would rather retreat, +; and if it isn't, set carry. + farcall AIDecideWhetherToRetreat + jr nc, .set_carry + +.no_carry + or a + ret + +.confused +; if Scoop Up is in hand and decided to be played, skip. + ld a, SCOOP_UP + call LookForCardIDInHandList_Bank8 + jr nc, .no_scoop_up_cnf + call Func_21506 + jr c, .no_carry + +.no_scoop_up_cnf +; if card can damage defending Pokemon... + xor a ; PLAY_AREA_ARENA + farcall CheckIfCanDamageDefendingPokemon + jr nc, .no_carry +; ...and can play an energy card to retreat, set carry. + ld a, [wAIPlayEnergyCardForRetreat] + or a + jr nz, .set_carry +; if not, return no carry. + jr .no_carry +; 0x21497 + INCROM $21497, $21506 +Func_21506: ; 21506 (8:5506) + INCROM $21506, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From 812436465f010c3e64b93f2ff72e5401f82861e8 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 16 Apr 2020 00:28:06 +0100 Subject: AI Mr Fuji routines --- src/engine/bank05.asm | 4 +-- src/engine/bank08.asm | 99 ++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 97 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index e9191da..62529a4 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1678,7 +1678,7 @@ CalculateByteTensDigit: ; 1576b (5:576b) ; input: ; a = divisor ; b = dividend -CalculateBDividedByA: ; 15778 (5:5778) +CalculateBDividedByA_Bank5: ; 15778 (5:5778) push bc ld c, a ld a, b @@ -2495,7 +2495,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) .add_hp_score ld b, a ld a, 4 - call CalculateBDividedByA + call CalculateBDividedByA_Bank5 call CalculateByteTensDigit call AddToAIScore diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 0625fa3..b9ff561 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -29,7 +29,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0c, ENERGY_SEARCH, CheckIfEnergySearchCanBePlayed, AIPlayEnergySearch unknown_data_20000 $03, POKEDEX, CheckWhetherToPlayPokedex, AIPlayPokedex unknown_data_20000 $07, FULL_HEAL, CheckWhetherToPlayFullHeal, AIPlayFullHeal - unknown_data_20000 $0a, MR_FUJI, $54a7, $5497 + unknown_data_20000 $0a, MR_FUJI, CheckWetherToPlayMrFuji, AIPlayMrFuji unknown_data_20000 $0a, SCOOP_UP, $5506, $54f1 unknown_data_20000 $02, MAINTENANCE, $562c, $560f unknown_data_20000 $03, RECYCLE, $56b8, $569a @@ -3944,7 +3944,81 @@ CheckWhetherToPlayFullHeal: ; 21428 (8:5428) jr .no_carry ; 0x21497 - INCROM $21497, $21506 +AIPlayMrFuji: ; 21497 (8:5497) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x214a7 + +; AI logic for playing Mr Fuji +CheckWetherToPlayMrFuji: ; 214a7 (8:54a7) + ld a, $ff + ld [wce06], a + ld [wce08], a + +; if just one Pokemon in Play Area, skip. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 1 + ret z + + dec a + ld d, a + ld e, PLAY_AREA_BENCH_1 + +; find a Pokemon in the bench that has damage counters. +.loop_bench + ld a, DUELVARS_ARENA_CARD + add e + push de + call GetTurnDuelistVariable + call LoadCardDataToBuffer1_FromDeckIndex + pop de + + ld a, [wLoadedCard1HP] + ld b, a + + ; skip if zero damage counters + call GetCardDamage + call ConvertHPToCounters + or a + jr z, .next + +; a = damage counters +; b = hp left + call CalculateBDividedByA_Bank8 + cp 20 + jr nc, .next + +; here, HP left in counters is less than twice +; the number of damage counters, that is: +; HP < 1/3 max HP + +; if value is less than the one found before, store this one. + ld hl, wce08 + cp [hl] + jr nc, .next + ld [hl], a + ld a, e + ld [wce06], a +.next + inc e + dec d + jr nz, .loop_bench + + ld a, [wce06] + cp $ff + ret z + + scf + ret +; 0x214f1 + + INCROM $214f1, $21506 Func_21506: ; 21506 (8:5506) INCROM $21506, $227f6 @@ -4348,8 +4422,25 @@ CalculateWordTensDigit: ; 229b0 (8:69b0) ret ; 0x229c1 -Func_229c1 ; 229c1 (8:69c1) - INCROM $229c1, $229f3 +CalculateBDividedByA_Bank8: ; 229c1 (8:69c1) + push bc + ld c, a + ld a, b + ld b, c + ld c, 0 +.loop + sub b + jr c, .done + inc c + jr .loop +.done + ld a, c + pop bc + ret +; 0x229d0 + +Func_229d0 ; 229d0 (8:69d0) + INCROM $229d0, $229f3 ; 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 2a5c23582fe5f4e83987fd5271c5a965286ff679 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 16 Apr 2020 09:42:40 +0100 Subject: AI Scoop Up routines --- src/engine/bank08.asm | 224 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 216 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index b9ff561..f9ab262 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -29,8 +29,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0c, ENERGY_SEARCH, CheckIfEnergySearchCanBePlayed, AIPlayEnergySearch unknown_data_20000 $03, POKEDEX, CheckWhetherToPlayPokedex, AIPlayPokedex unknown_data_20000 $07, FULL_HEAL, CheckWhetherToPlayFullHeal, AIPlayFullHeal - unknown_data_20000 $0a, MR_FUJI, CheckWetherToPlayMrFuji, AIPlayMrFuji - unknown_data_20000 $0a, SCOOP_UP, $5506, $54f1 + unknown_data_20000 $0a, MR_FUJI, CheckWhetherToPlayMrFuji, AIPlayMrFuji + unknown_data_20000 $0a, SCOOP_UP, CheckWhetherToPlayScoopUp, AIPlayScoopUp unknown_data_20000 $02, MAINTENANCE, $562c, $560f unknown_data_20000 $03, RECYCLE, $56b8, $569a unknown_data_20000 $0d, LASS, $5768, $5755 @@ -3901,7 +3901,7 @@ CheckWhetherToPlayFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_prz - call Func_21506 + call CheckWhetherToPlayScoopUp jr c, .no_carry .no_scoop_up_prz @@ -3928,7 +3928,7 @@ CheckWhetherToPlayFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_cnf - call Func_21506 + call CheckWhetherToPlayScoopUp jr c, .no_carry .no_scoop_up_cnf @@ -3955,7 +3955,7 @@ AIPlayMrFuji: ; 21497 (8:5497) ; 0x214a7 ; AI logic for playing Mr Fuji -CheckWetherToPlayMrFuji: ; 214a7 (8:54a7) +CheckWhetherToPlayMrFuji: ; 214a7 (8:54a7) ld a, $ff ld [wce06], a ld [wce08], a @@ -4018,10 +4018,218 @@ CheckWetherToPlayMrFuji: ; 214a7 (8:54a7) ret ; 0x214f1 - INCROM $214f1, $21506 +AIPlayScoopUp: ; 214f1 (8:54f1) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x21506 + +CheckWhetherToPlayScoopUp: ; 21506 (8:5506) + xor a + ldh [hTempPlayAreaLocation_ff9d], a + +; if only one Pokemon in Play Area, skip. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 2 + jr c, .no_carry + +; handle some decks differently + ld a, [wOpponentDeckID] + cp LEGENDARY_ARTICUNO_DECK_ID + jr z, .HandleLegendaryArticuno + cp LEGENDARY_RONALD_DECK_ID + jp z, .HandleLegendaryRonald + +; if can't KO defending Pokemon, check if defending Pokemon +; can KO this card. If so, then continue. +; If not, return no carry. + +; if it can KO the defending Pokemon this turn, +; return no carry. + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .cannot_ko + farcall CheckIfSelectedMoveIsUnusable + jr nc, .no_carry + farcall LookForEnergyNeededForMoveInHand + jr c, .no_carry + +.cannot_ko + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and CNF_SLP_PRZ + cp PARALYZED + jr z, .cannot_retreat + cp ASLEEP + jr z, .cannot_retreat + +; doesn't have a status that prevents retreat. +; so check if it has enough energy to retreat. +; if not, return no carry. + xor a + ldh [hTempPlayAreaLocation_ff9d], a + call GetPlayAreaCardRetreatCost + ld b, a + ld e, PLAY_AREA_ARENA + farcall CountNumberOfEnergyCardsAttached + cp b + jr c, .cannot_retreat + +.no_carry + or a + ret + +.cannot_retreat +; store damage and total HP left + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call LoadCardDataToBuffer1_FromDeckIndex + ld a, [wLoadedCard1HP] + call ConvertHPToCounters + ld d, a + +; skip if card has no damage counters. + ld e, PLAY_AREA_ARENA + call GetCardDamage + or a + jr z, .no_carry + +; if (total damage / total HP counters) < 7 +; return carry. +; (this corresponds to damage counters +; being under 70% of the max HP) + ld b, a + ld a, d + call CalculateBDividedByA_Bank8 + cp 7 + jr c, .no_carry + +; store Pokemon to switch to in wce1a and set carry. +.decide_switch + farcall AIDecideBenchPokemonToSwitchTo + jr c, .no_carry + ld [wce1a], a + xor a + scf + ret + +; this deck will use Scoop Up on a benched Articuno2. +; it checks if the defending Pokemon is a Snorlax, +; but interestingly does not check for Muk in both Play Areas. +; will also use Scoop Up on +.HandleLegendaryArticuno +; if less than 3 Play Area Pokemon cards, skip. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 3 + jr c, .no_carry + +; look for Articuno2 in bench + ld a, ARTICUNO2 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank8 + jr c, .articuno_bench + +; check Arena card + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp ARTICUNO2 + jr z, .articuno_or_chansey + cp CHANSEY + jr nz, .no_carry + +; here either Articuno2 or Chansey +; is the Arena Card. +.articuno_or_chansey +; if can't KO defending Pokemon, check if defending Pokemon +; can KO this card. If so, then continue. +; If not, return no carry. + +; if it can KO the defending Pokemon this turn, +; return no carry. + farcall CheckIfAnyMoveKnocksOutDefendingCard + jr nc, .check_ko + farcall CheckIfSelectedMoveIsUnusable + jr nc, .no_carry + farcall LookForEnergyNeededForMoveInHand + jr c, .no_carry +.check_ko + farcall CheckIfDefendingPokemonCanKnockOut + jr nc, .no_carry + jr .decide_switch + +.articuno_bench +; skip if the defending card is Snorlax + push af + ld a, DUELVARS_ARENA_CARD + call GetNonTurnDuelistVariable + call SwapTurn + call GetCardIDFromDeckIndex + call SwapTurn + ld a, e + cp SNORLAX + pop bc + jr z, .no_carry + +; check attached energy cards. +; if it has any, return no carry. + ld a, b +.check_attached_energy + ld e, a + push af + farcall CountNumberOfEnergyCardsAttached + or a + pop bc + ld a, b + jr z, .no_energy + jp .no_carry + +.no_energy +; has decided to Scoop Up benched card, +; store $ff as the Pokemon card to switch to +; because there's no need to switch. + push af + ld a, $ff + ld [wce1a], a + pop af + scf + ret +; 0x215e7 + +; this deck will use Scoop Up on a benched Articuno2, Zapdos3 or Molres2. +; interestingly, does not check for Muk in both Play Areas. +.HandleLegendaryRonald ; 215e7 (8:55e7) +; if less than 3 Play Area Pokemon cards, skip. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 3 + jp c, .no_carry + + ld a, ARTICUNO2 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank8 + jr c, .articuno_bench + ld a, ZAPDOS3 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank8 + jr c, .check_attached_energy + ld a, MOLTRES2 + ld b, PLAY_AREA_BENCH_1 + call LookForCardIDInPlayArea_Bank8 + jr c, .check_attached_energy + jp .no_carry +; 0x2160f -Func_21506: ; 21506 (8:5506) - INCROM $21506, $227f6 +Func_2160f: ; 2160f (8:560f) + INCROM $2160f, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From fe5d55e397d9a48ed1743cde4bf2479a852ba708 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 16 Apr 2020 14:57:29 +0100 Subject: AI Maintenance and Recycle routines --- src/engine/bank08.asm | 290 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 269 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index f9ab262..82bcd01 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -31,8 +31,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $07, FULL_HEAL, CheckWhetherToPlayFullHeal, AIPlayFullHeal unknown_data_20000 $0a, MR_FUJI, CheckWhetherToPlayMrFuji, AIPlayMrFuji unknown_data_20000 $0a, SCOOP_UP, CheckWhetherToPlayScoopUp, AIPlayScoopUp - unknown_data_20000 $02, MAINTENANCE, $562c, $560f - unknown_data_20000 $03, RECYCLE, $56b8, $569a + unknown_data_20000 $02, MAINTENANCE, CheckWhetherToPlayMaintencance, AIPlayMaintenance + unknown_data_20000 $03, RECYCLE, CheckWhetherToPlayRecycle, AIPlayRecycle unknown_data_20000 $0d, LASS, $5768, $5755 unknown_data_20000 $04, ITEM_FINDER, $57b1, $578f unknown_data_20000 $01, IMAKUNI_CARD, $581e, $5813 @@ -2712,7 +2712,7 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) ; find duplicate cards in hand call CreateHandCardList ld hl, wDuelTempList - call CheckDuplicatePokemonAndNonPokemonCards + call FindDuplicateCards jp c, .no_carry ld [wce06], a @@ -2846,13 +2846,17 @@ RemoveCardFromList: ; 20f27 (8:4f27) ret ; 0x20f38 -; returns carry if duplicate cards are found for -; at least one Pokemon card and at least one Non-Pokemon card +; finds duplicates in card list in hl. +; if a duplicate of Pokemon cards are found, return in +; a the deck index of the second one. +; otherwise, if a duplicate of non-Pokemon cards are found +; return in a the deck index of the second one. +; if no duplicates found, return carry. ; input: ; hl = list to look in ; output: -; a = deck index of duplicate non-Pokemon card -CheckDuplicatePokemonAndNonPokemonCards: ; 20f38 (8:4f38) +; a = deck index of duplicate card +FindDuplicateCards: ; 20f38 (8:4f38) ld a, $ff ld [wce0f], a ld [wce0f + 1], a @@ -2908,14 +2912,13 @@ CheckDuplicatePokemonAndNonPokemonCards: ; 20f38 (8:4f38) cp $ff jr nz, .no_carry -; only set carry if duplicate cards were found -; for both Pokemon and Non-Pokemon cards +; only set carry if duplicate cards were not found scf ret .no_carry -; two cards with the same ID were not found -; of either Pokemon and Non-Pokemon cards +; two cards with the same ID were found +; of either Pokemon or Non-Pokemon cards or a ret ; 0x20f80 @@ -2975,15 +2978,15 @@ CheckSuperEnergyRetrievalCardsToPick: ; 20fc1 (8:4fc1) ; find duplicate cards in hand call CreateHandCardList ld hl, wDuelTempList - call CheckDuplicatePokemonAndNonPokemonCards + call FindDuplicateCards jp c, .no_carry -; remove the duplicate non-Pokemon card in hand +; remove the duplicate card in hand ; and run the hand check again ld [wce06], a ld hl, wDuelTempList - call .RemoveDuplicateCardFromHandList - call CheckDuplicatePokemonAndNonPokemonCards + call FindAndRemoveCardFromList + call FindDuplicateCards jp c, .no_carry ld [wce08], a @@ -3133,9 +3136,14 @@ CheckSuperEnergyRetrievalCardsToPick: ; 20fc1 (8:4fc1) ret ; 0x210d5 -; finds the energy card that was found to be a duplicate -; and removes it from the hand card list. -.RemoveDuplicateCardFromHandList ; 210d5 (8:50d5) +; finds the card with deck index a in list hl, +; and removes it from the list. +; the card HAS to exist in the list, since this +; routine does not check for the terminating byte $ff! +; input: +; a = card deck index to look +; hl = pointer to list of cards +FindAndRemoveCardFromList: ; 210d5 (8:50d5) push hl ld b, a .loop_duplicate @@ -3184,7 +3192,7 @@ CheckIfCanPlayPokemonCenter: ; 210eb (8:50eb) push de call GetTurnDuelistVariable call LoadCardDataToBuffer1_FromDeckIndex - ld a, e + ld a, e ; useless instruction pop de ; get this Pokemon's current HP in number of counters @@ -4228,8 +4236,248 @@ CheckWhetherToPlayScoopUp: ; 21506 (8:5506) jp .no_carry ; 0x2160f -Func_2160f: ; 2160f (8:560f) - INCROM $2160f, $227f6 +AIPlayMaintenance: ; 2160f (8:560f) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce1a] + ldh [hTemp_ffa0], a + ld a, [wce1b] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x2162c + +; AI logic for playing Maintenance +CheckWhetherToPlayMaintencance: ; 2162c (8:562c) +; Imakuni? has his own thing + ld a, [wOpponentDeckID] + cp IMAKUNI_DECK_ID + jr z, .imakuni + +; skip if number of cars in hand < 4. + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 4 + jr c, .no_carry + +; list out all the hand cards and remove +; the card in wce16. Then find any duplicate cards. + call CreateHandCardList + ld hl, wDuelTempList + ld a, [wce16] + call FindAndRemoveCardFromList +; if duplicates are not found, return no carry. + call FindDuplicateCards + jp c, .no_carry + +; store the first duplicate card and remove it from the list. +; run duplicate check again. + ld [wce1a], a + ld hl, wDuelTempList + call FindAndRemoveCardFromList +; if duplicates are not found, return no carry. + call FindDuplicateCards + jp c, .no_carry + +; store the second duplicate card and return carry. + ld [wce1b], a + scf + ret + +.no_carry + or a + ret + +.imakuni +; has a 2 in 10 chance of not skipping. + ld a, 10 + call Random + cp 2 + jr nc, .no_carry + +; skip if number of cards in hand < 3. + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 3 + jr c, .no_carry + +; shuffle hand cards + call CreateHandCardList + ld hl, wDuelTempList + call CountCardsInDuelTempList + call ShuffleCards + +; go through each card and find +; cards that are different from wce16. +; if found, add those cards to wce1a and wce1a+1. + ld a, [wce16] + ld b, a + ld c, 2 + ld de, wce1a + +.loop + ld a, [hli] + cp $ff + jr z, .no_carry + cp b + jr z, .loop + ld [de], a + inc de + dec c + jr nz, .loop + +; two cards were found, return carry. + scf + ret +; 0x2169a + +AIPlayRecycle: ; 2169a (8:569a) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld de, $ef + bank1call TossCoin + jr nc, .asm_216ae + ld a, [wce19] + ldh [hTemp_ffa0], a + jr .asm_216b2 +.asm_216ae + ld a, $ff + ldh [hTemp_ffa0], a +.asm_216b2 + ld a, $07 + bank1call AIMakeDecision + ret +; 0x216b8 + +; lists cards to look for in the Discard Pile. +; has priorities for Ghost Deck, and a "default" priority list +; (which is the Fire Charge deck, since it's the only other +; deck that runs a Recycle card in it.) +CheckWhetherToPlayRecycle: ; 216b8 (8:56b8) +; no use checking if no cards in Discard Pile + call CreateDiscardPileCardList + jr c, .no_carry + + ld a, $ff + ld [wce08], a + ld [wce08 + 1], a + ld [wce08 + 2], a + ld [wce08 + 3], a + ld [wce08 + 4], a + +; handle Ghost deck differently + ld hl, wDuelTempList + ld a, [wOpponentDeckID] + cp GHOST_DECK_ID + jr z, .loop_2 + +; priority list for Fire Charge deck +.loop_1 + ld a, [hli] + cp $ff + jr z, .done + + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + +; double colorless + cp DOUBLE_COLORLESS_ENERGY + jr nz, .chansey + ld a, b + ld [wce08], a + jr .loop_1 + +.chansey + cp CHANSEY + jr nz, .tauros + ld a, b + ld [wce08 + 1], a + jr .loop_1 + +.tauros + cp TAUROS + jr nz, .jigglypuff + ld a, b + ld [wce08 + 2], a + jr .loop_1 + +.jigglypuff + cp JIGGLYPUFF1 + jr nz, .loop_1 + ld a, b + ld [wce08 + 3], a + jr .loop_1 + +; loop through wce08 and set carry +; on the first that was found in Discard Pile. +; if none were found, return no carry. +.done + ld hl, wce08 + ld b, 5 +.loop_found + ld a, [hli] + cp $ff + jr nz, .set_carry + dec b + jr nz, .loop_found +.no_carry + or a + ret +.set_carry + scf + ret + +; priority list for Ghost deck +.loop_2 + ld a, [hli] + cp $ff + jr z, .done + + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + +; gastly2 + cp GASTLY2 + jr nz, .gastly1 + ld a, b + ld [wce08], a + jr .loop_2 + +.gastly1 + cp GASTLY1 + jr nz, .zubat + ld a, b + ld [wce08 + 1], a + jr .loop_2 + +.zubat + cp ZUBAT + jr nz, .ditto + ld a, b + ld [wce08 + 2], a + jr .loop_2 + +.ditto + cp DITTO + jr nz, .meowth + ld a, b + ld [wce08 + 3], a + jr .loop_2 + +.meowth + cp MEOWTH2 + jr nz, .loop_2 + ld a, b + ld [wce08 + 4], a + jr .loop_2 +; 0x21755 + +Func_21755: ; 21755 (8:5755) + INCROM $21755, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From 65239aa9e0d5277cd082c6b78120053c9a3b503e Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 16 Apr 2020 15:35:28 +0100 Subject: AI Lass and Item Finder routines --- src/engine/bank08.asm | 153 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 144 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 82bcd01..cb3ffa8 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -33,8 +33,8 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $0a, SCOOP_UP, CheckWhetherToPlayScoopUp, AIPlayScoopUp unknown_data_20000 $02, MAINTENANCE, CheckWhetherToPlayMaintencance, AIPlayMaintenance unknown_data_20000 $03, RECYCLE, CheckWhetherToPlayRecycle, AIPlayRecycle - unknown_data_20000 $0d, LASS, $5768, $5755 - unknown_data_20000 $04, ITEM_FINDER, $57b1, $578f + unknown_data_20000 $0d, LASS, CheckWhetherToPlayLass, AIPlayLass + unknown_data_20000 $04, ITEM_FINDER, CheckWhetherToPlayItemFinder, AIPlayItemFinder unknown_data_20000 $01, IMAKUNI_CARD, $581e, $5813 unknown_data_20000 $01, GAMBLER, $5875, $582d unknown_data_20000 $05, REVIVE, $58a9, $5899 @@ -2826,7 +2826,7 @@ CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) ; remove an element from the list ; and shortens it accordingly ; input: -; hl = pointer to element to remove +; hl = pointer to element after the one to remove RemoveCardFromList: ; 20f27 (8:4f27) push de ld d, h @@ -2950,7 +2950,7 @@ AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) ld a, $ff ldh [$ffa6], a .asm_20fbb - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x20fc1 @@ -3299,7 +3299,7 @@ AIPlayEnergySearch: ; 2119a (8:519a) ldh [hTempCardIndex_ff9f], a ld a, [wce19] ldh [hTemp_ffa0], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x211aa @@ -3557,7 +3557,7 @@ AIPlayPokedex: ; 212b4 (8:52b4) ldh [$ffa4], a ld a, $ff ldh [$ffa5], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x212dc @@ -4348,7 +4348,7 @@ AIPlayRecycle: ; 2169a (8:569a) ld a, $ff ldh [hTemp_ffa0], a .asm_216b2 - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x216b8 @@ -4476,8 +4476,143 @@ CheckWhetherToPlayRecycle: ; 216b8 (8:56b8) jr .loop_2 ; 0x21755 -Func_21755: ; 21755 (8:5755) - INCROM $21755, $227f6 +AIPlayLass: ; 21755 (8:5755) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x21768 + +CheckWhetherToPlayLass: ; 21768 (8:5768) +; skip if player has less than 7 cards in hand + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetNonTurnDuelistVariable + cp 7 + jr c, .no_carry + +; look for Trainer cards in hand (except for Lass) +; if any is found, return no carry. +; otherwise, return carry. + call CreateHandCardList + ld hl, wDuelTempList +.loop + ld a, [hli] + cp $ff + jr z, .set_carry + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + cp LASS + jr z, .loop + ld a, [wLoadedCard1Type] + cp TYPE_TRAINER + jr nz, .loop +.no_carry + or a + ret +.set_carry + scf + ret +; 0x2178f + +AIPlayItemFinder: ; 2178f (8:578f) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce1a] + ldh [hTemp_ffa0], a + ld a, [wce1b] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, [wce19] + ldh [hTempRetreatCostCards], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x217b1 + +; checks whether there's Energy Removal in Discard Pile. +; if so, find duplicate cards in hand to discard +; that are not Mr Mime and Pokemon Trader cards. +; this logic is suitable only for Strange Psyshock deck. +CheckWhetherToPlayItemFinder: ; 217b1 (8:57b1) +; skip if no Discard Pile. + call CreateDiscardPileCardList + jr c, .no_carry + +; look for Energy Removal in Discard Pile + ld hl, wDuelTempList +.loop_discard_pile + ld a, [hli] + cp $ff + jr z, .no_carry + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + cp ENERGY_REMOVAL + jr nz, .loop_discard_pile +; found, store this deck index + ld a, b + ld [wce06], a + +; before looking for cards to discard in hand, +; remove any Mr Mime and Pokemon Trader cards. +; this way these are guaranteed to not be discarded. + call CreateHandCardList + ld hl, wDuelTempList +.loop_hand + ld a, [hli] + cp $ff + jr z, .asm_217eb + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + cp MR_MIME + jr nz, .pkmn_trader + call RemoveCardFromList + jr .loop_hand +.pkmn_trader + cp POKEMON_TRADER + jr nz, .loop_hand + call RemoveCardFromList + jr .loop_hand + +; choose cards to discard from hand. +.asm_217eb + ld hl, wDuelTempList + +; do not discard card in wce16 + ld a, [wce16] + call FindAndRemoveCardFromList +; find any duplicates, if not found, return no carry. + call FindDuplicateCards + jp c, .no_carry + +; store the duplicate found in wce1a and +; remove it from the hand list. + ld [wce1a], a + ld hl, wDuelTempList + call FindAndRemoveCardFromList +; find duplicates again, if not found, return no carry. + call FindDuplicateCards + jp c, .no_carry + +; store the duplicate found in wce1b. +; output the card to be recovered from the Discard Pile. + ld [wce1b], a + ld a, [wce06] + scf + ret + +.no_carry + or a + ret +; 0x21813 + +Func_21813: ; 21813 (8:5813) + INCROM $21813, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. -- cgit v1.2.3 From cdf5b71ee119262a5a4c4760b88017dd1194db10 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Thu, 16 Apr 2020 19:21:11 +0100 Subject: More AI Trainer routines --- src/engine/bank08.asm | 680 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 664 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index cb3ffa8..e1c70a5 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -35,13 +35,13 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $03, RECYCLE, CheckWhetherToPlayRecycle, AIPlayRecycle unknown_data_20000 $0d, LASS, CheckWhetherToPlayLass, AIPlayLass unknown_data_20000 $04, ITEM_FINDER, CheckWhetherToPlayItemFinder, AIPlayItemFinder - unknown_data_20000 $01, IMAKUNI_CARD, $581e, $5813 - unknown_data_20000 $01, GAMBLER, $5875, $582d - unknown_data_20000 $05, REVIVE, $58a9, $5899 - unknown_data_20000 $0d, POKEMON_FLUTE, $58e8, $58d8 - unknown_data_20000 $05, CLEFAIRY_DOLL, $5982, $5977 - unknown_data_20000 $05, MYSTERIOUS_FOSSIL, $5982, $5977 - unknown_data_20000 $02, POKE_BALL, $59c6, $59a6 + unknown_data_20000 $01, IMAKUNI_CARD, CheckWhetherToPlayImakuni, AIPlayImakuni + unknown_data_20000 $01, GAMBLER, CheckWhetherToPlayGambler, AIPlayGambler + unknown_data_20000 $05, REVIVE, CheckWhetherToPlayRevive, AIPlayRevive + unknown_data_20000 $0d, POKEMON_FLUTE, CheckWhetherToPlayPokemonFlute, AIPlayPokemonFlute + unknown_data_20000 $05, CLEFAIRY_DOLL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil + unknown_data_20000 $05, MYSTERIOUS_FOSSIL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil + unknown_data_20000 $02, POKE_BALL, CheckWhetherToPlayPokeball, AIPlayPokeball unknown_data_20000 $02, COMPUTER_SEARCH, $5b34, $5b12 unknown_data_20000 $02, POKEMON_TRADER, $5d8f, $5d7a db $ff @@ -4530,7 +4530,7 @@ AIPlayItemFinder: ; 2178f (8:578f) ldh [hTempPlayAreaLocation_ffa1], a ld a, [wce19] ldh [hTempRetreatCostCards], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x217b1 @@ -4611,8 +4611,527 @@ CheckWhetherToPlayItemFinder: ; 217b1 (8:57b1) ret ; 0x21813 -Func_21813: ; 21813 (8:5813) - INCROM $21813, $227f6 +AIPlayImakuni: ; 21813 (8:5813) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x2181e + +; only sets carry if Active card is not confused. +CheckWhetherToPlayImakuni: ; 2181e (8:581e) + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and CNF_SLP_PRZ + cp CONFUSED + jr z, .confused + scf + ret +.confused + or a + ret +; 0x2182d + +AIPlayGambler: ; 2182d (8:582d) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wOpponentDeckID] + cp IMAKUNI_DECK_ID + jr z, .asm_2186a + ld hl, wRNG1 + ld a, [hli] + ld [wce06], a + ld a, [hli] + ld [wce08], a + ld a, [hl] + ld [wce0f], a + ld a, $50 + ld [hld], a + ld [hld], a + ld [hl], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ld hl, wRNG1 + ld a, [wce06] + ld [hli], a + ld a, [wce08] + ld [hli], a + ld a, [wce0f] + ld [hl], a + ret +.asm_2186a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS + bank1call AIMakeDecision + ret +; 0x21875 + +; checks whether to play Gambler. +; aside from Imakuni, all other opponents only +; play if there's less than 4 cards in the deck. +CheckWhetherToPlayGambler: ; 21875 (8:5875) +; Imakuni? has his own routine + ld a, [wOpponentDeckID] + cp IMAKUNI_DECK_ID + jr z, .imakuni + + ld a, [wcda7] + and $80 + jr z, .no_carry + +; set carry if number of cards in deck <= 4 + ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK + call GetTurnDuelistVariable + cp DECK_SIZE - 4 + jr nc, .set_carry +.no_carry + or a + ret + +.imakuni +; has a 2 in 10 chance of returning carry + ld a, 10 + call Random + cp 2 + jr nc, .no_carry +.set_carry + scf + ret +; 0x21899 + +AIPlayRevive: ; 21899 (8:5899) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x218a9 + +; checks certain cards in Discard Pile to use Revive on. +; suitable for Muscle For Brains deck only. +CheckWhetherToPlayRevive: ; 218a9 (8:58a9) +; skip if no cards in Discard Pile + call CreateDiscardPileCardList + jr c, .no_carry + +; skip if number of Pokemon cards in Play Area >= 4 + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp 4 + jr nc, .no_carry + +; look in Discard Pile for specific cards. + ld hl, wDuelTempList +.loop_discard_pile + ld a, [hli] + cp $ff + jr z, .no_carry + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + +; these checks have a bug. +; it works fine for Hitmonchan and Hitmonlee, +; but in case it's a Tauros card, the routine will fallthrough +; into the Kangaskhan check. since it will never be equal to Kangaskhan, +; it will fallthrough into the set carry branch. +; in case it's a Kangaskhan card, the check will fail in the Tauros check +; and jump back into the loop. so just by accident the Tauros check works, +; but Kangaskhan will never be correctly checked because of this. + cp HITMONCHAN + jr z, .set_carry + cp HITMONLEE + jr z, .set_carry + cp TAUROS + jr nz, .loop_discard_pile ; bug, these two lines should be swapped + cp KANGASKHAN + jr z, .set_carry ; bug, these two lines should be swapped + +.set_carry + ld a, b + scf + ret +.no_carry + or a + ret +; 0x218d8 + +AIPlayPokemonFlute: ; 218d8 (8:58d8) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x218e8 + +CheckWhetherToPlayPokemonFlute: ; 218e8 (8:58e8) +; if player has no Discard Pile, skip. + call SwapTurn + call CreateDiscardPileCardList + call SwapTurn + jr c, .no_carry + +; if player's Play Area is already full, skip. + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetNonTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .no_carry + + ld a, [wOpponentDeckID] + cp IMAKUNI_DECK_ID + jr z, .imakuni + + ld a, $ff + ld [wce06], a + ld [wce08], a + +; find Basic stage Pokemon with lowest HP in Discard Pile + ld hl, wDuelTempList +.loop_1 + ld a, [hli] + cp $ff + jr z, .done + + ld b, a + call SwapTurn + call LoadCardDataToBuffer1_FromDeckIndex + call SwapTurn +; skip this card if it's not Pokemon card + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .loop_1 +; skip this card if it's not Basic Stage + ld a, [wLoadedCard1Stage] + or a ; BASIC + jr nz, .loop_1 + +; compare this HP with one stored + ld a, [wLoadedCard1HP] + push hl + ld hl, wce06 + cp [hl] + pop hl + jr nc, .loop_1 +; if lower, store this one + ld [wce06], a + ld a, b + ld [wce08], a + jr .loop_1 + +.done +; if lowest HP found >= 50, return no carry + ld a, [wce06] + cp 50 + jr nc, .no_carry +; otherwise output its deck index in a and set carry. + ld a, [wce08] + scf + ret +.no_carry + or a + ret + +.imakuni +; has 2 in 10 chance of not skipping + ld a, 10 + call Random + cp 2 + jr nc, .no_carry + +; look for any Basic Pokemon card + ld hl, wDuelTempList +.loop_2 + ld a, [hli] + cp $ff + jr z, .no_carry + ld b, a + call SwapTurn + call LoadCardDataToBuffer1_FromDeckIndex + call SwapTurn + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .loop_2 + ld a, [wLoadedCard1Stage] + or a ; BASIC + jr nz, .loop_2 + +; a Basic stage Pokemon was found, return carry + ld a, b + scf + ret +; 0x21977 + +AIPlayClefairyDollOrMysteriousFossil: ; 21977 (8:5977) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x21982 + +; AI logic for playing Clefairy Doll +CheckWhetherToPlayClefairyDollOrMysteriousFossil: ; 21982 (8:5982) +; if has max number of Play Area Pokemon, skip + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + cp MAX_PLAY_AREA_POKEMON + jr nc, .no_carry + +; store number of Play Area Pokemon cards + ld [wce06], a + +; if the Arena card is Wigglytuff, return carry + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + ld a, e + cp WIGGLYTUFF + jr z, .set_carry + +; if number of Play Area Pokemon >= 4, return no carry + ld a, [wce06] + cp 4 + jr nc, .no_carry + +.set_carry + scf + ret +.no_carry + or a + ret +; 0x219a6 + +AIPlayPokeball: ; 219a6 (8:59a6) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld de, $ef + bank1call TossCoin + ldh [hTemp_ffa0], a + jr nc, .asm_219bc + ld a, [wce19] + ldh [hTempPlayAreaLocation_ffa1], a + jr .asm_219c0 +.asm_219bc + ld a, $ff + ldh [hTempPlayAreaLocation_ffa1], a +.asm_219c0 + ld a, $07 + bank1call AIMakeDecision + ret +; 0x219c6 + +CheckWhetherToPlayPokeball: ; 219c6 (8:59c6) +; go to the routines associated with deck ID + ld a, [wOpponentDeckID] + cp FIRE_CHARGE_DECK_ID + jr z, .fire_charge + cp HARD_POKEMON_DECK_ID + jr z, .hard_pokemon + cp PIKACHU_DECK_ID + jr z, .pikachu + cp ETCETERA_DECK_ID + jr z, .etcetera + cp LOVELY_NIDORAN_DECK_ID + jp z, .lovely_nidoran + or a + ret + +; this deck runs a deck check for specific +; card IDs in order of decreasing priority +.fire_charge + ld e, CHANSEY + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, TAUROS + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, JIGGLYPUFF1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ret + +; this deck runs a deck check for specific +; card IDs in order of decreasing priority +.hard_pokemon + ld e, RHYHORN + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, RHYDON + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, ONIX + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ret + +; this deck runs a deck check for specific +; card IDs in order of decreasing priority +.pikachu + ld e, PIKACHU2 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, PIKACHU3 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, PIKACHU4 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, PIKACHU1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, FLYING_PIKACHU + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ret + +; this deck runs a deck check for specific +; card IDs in order of decreasing priority +; given a specific energy card in hand. +; also it avoids redundancy, so if it already +; has that card ID in the hand, it is skipped. +.etcetera +; fire + ld a, FIRE_ENERGY + call LookForCardIDInHandList_Bank8 + jr nc, .lightning + ld a, CHARMANDER + call LookForCardIDInHandList_Bank8 + jr c, .lightning + ld a, MAGMAR2 + call LookForCardIDInHandList_Bank8 + jr c, .lightning + ld e, CHARMANDER + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, MAGMAR2 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + +.lightning + ld a, LIGHTNING_ENERGY + call LookForCardIDInHandList_Bank8 + jr nc, .fighting + ld a, PIKACHU1 + call LookForCardIDInHandList_Bank8 + jr c, .fighting + ld a, MAGNEMITE1 + call LookForCardIDInHandList_Bank8 + jr c, .fighting + ld e, PIKACHU1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, MAGNEMITE1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + +.fighting + ld a, FIGHTING_ENERGY + call LookForCardIDInHandList_Bank8 + jr nc, .psychic + ld a, DIGLETT + call LookForCardIDInHandList_Bank8 + jr c, .psychic + ld a, MACHOP + call LookForCardIDInHandList_Bank8 + jr c, .psychic + ld e, DIGLETT + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, MACHOP + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + +.psychic + ld a, PSYCHIC_ENERGY + call LookForCardIDInHandList_Bank8 + jr nc, .done_etcetera + ld a, GASTLY1 + call LookForCardIDInHandList_Bank8 + jr c, .done_etcetera + ld a, JYNX + call LookForCardIDInHandList_Bank8 + jr c, .done_etcetera + ld e, GASTLY1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c + ld e, JYNX + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret c +.done_etcetera + or a + ret + +; this deck looks for card evolutions if +; its pre-evolution is in hand or in Play Area. +; if none of these are found, it looks for pre-evolutions +; of cards it has in hand. +; it does this for both the NidoranM (first) +; and NidoranF (second) families. +.lovely_nidoran + ld b, NIDORANM + ld a, NIDORINO + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + ret c + ld b, NIDORINO + ld a, NIDOKING + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + ret c + ld a, NIDORANM + ld b, NIDORINO + call LookForCardIDInDeck_GivenCardIDInHand + ret c + ld a, NIDORINO + ld b, NIDOKING + call LookForCardIDInDeck_GivenCardIDInHand + ret c + ld b, NIDORANF + ld a, NIDORINA + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + ret c + ld b, NIDORINA + ld a, NIDOQUEEN + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + ret c + ld a, NIDORANF + ld b, NIDORINA + call LookForCardIDInDeck_GivenCardIDInHand + ret c + ld a, NIDORINA + ld b, NIDOQUEEN + call LookForCardIDInDeck_GivenCardIDInHand + ret c + ret +; 0x21b12 + +Func_21b12: ; 21b12 (8:5b12) + INCROM $21b12, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. @@ -5030,8 +5549,44 @@ CalculateBDividedByA_Bank8: ; 229c1 (8:69c1) ret ; 0x229d0 -Func_229d0 ; 229d0 (8:69d0) - INCROM $229d0, $229f3 +; returns in a the deck index of the first +; instance of card with ID equal to the ID in e +; in card location a. +; returns carry if found. +; input: +; a = CARD_LOCATION_* +; e = card ID to look for +LookForCardIDInLocation: ; 229d0 (8:69d0) + ld b, a + ld c, e + lb de, $00, 0 ; d is never used +.loop + ld a, DUELVARS_CARD_LOCATIONS + add e + call GetTurnDuelistVariable + cp b + jr nz, .next + ld a, e + push de + call GetCardIDFromDeckIndex + ld a, e + pop de + cp c + jr z, .found +.next + inc e + ld a, DECK_SIZE + cp e + jr nz, .loop + +; not found + or a + ret +.found + ld a, e + scf + ret +; 0x229f3 ; return carry if card ID loaded in a is found in hand ; and outputs in a the deck index of that card @@ -5062,8 +5617,55 @@ LookForCardIDInHandList_Bank8: ; 229f3 (8:69f3) ret ; 0x22a10 -Func_22a10 ; 22a10 (8:6a10) - INCROM $22a10, $22a39 +; searches in deck for card ID 1 in a, and +; if found, searches in Hand/Play Area for card ID 2 in b, and +; if found, searches for card ID 1 in Hand/Play Area, and +; if none found, return carry and output deck index +; of the card ID 1 in deck. +; input: +; a = card ID 1 +; b = card ID 2 +; output: +; a = index of card ID 1 in deck +LookForCardIDInDeck_GivenCardIDInHandAndPlayArea: ; 22a10 (8:6a10) +; store a in wCurCardCanAttack +; and b in wTempAI + ld c, a + ld a, b + ld [wTempAI], a + ld a, c + ld [wCurCardCanAttack], a + +; look for the card ID 1 in deck + ld e, a + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret nc + +; was found, store its deck index in memory + ld [wTempAIPokemonCard], a + +; look for the card ID 2 +; in Hand and Play Area, return if not found. + ld a, [wTempAI] + call LookForCardIDInHandAndPlayArea + ret nc + +; look for the card ID 1 in the Hand and Play Area +; if any card is found, return no carry. + ld a, [wCurCardCanAttack] + call LookForCardIDInHandAndPlayArea + jr c, .no_carry +; none found + + ld a, [wTempAIPokemonCard] + scf + ret + +.no_carry + or a + ret +; 0x22a39 ; returns carry if card ID in a ; is found in Play Area or in hand @@ -5084,8 +5686,54 @@ LookForCardIDInHandAndPlayArea: ; 22a39 (8:6a39) ret ; 0x22a49 -Func_22a49 ; 22a49 (8:6a49) - INCROM $22a49, $22a72 +; searches in deck for card ID 1 in a, and +; if found, searches in Hand Area for card ID 2 in b, and +; if found, searches for card ID 1 in Hand/Play Area, and +; if none found, return carry and output deck index +; of the card ID 1 in deck. +; input: +; a = card ID 1 +; b = card ID 2 +; output: +; a = index of card ID 1 in deck +LookForCardIDInDeck_GivenCardIDInHand: ; 22a49 (8:6a49) +; store a in wCurCardCanAttack +; and b in wTempAI + ld c, a + ld a, b + ld [wTempAI], a + ld a, c + ld [wCurCardCanAttack], a + +; look for the card ID 1 in deck + ld e, a + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + ret nc + +; was found, store its deck index in memory + ld [wTempAIPokemonCard], a + +; look for the card ID 2 in hand, return if not found. + ld a, [wTempAI] + call LookForCardIDInHandList_Bank8 + ret nc + +; look for the card ID 1 in the Hand and Play Area +; if any card is found, return no carry. + ld a, [wCurCardCanAttack] + call LookForCardIDInHandAndPlayArea + jr c, .no_carry +; none found + + ld a, [wTempAIPokemonCard] + scf + ret + +.no_carry + or a + ret +; 0x22a72 ; returns carry if card ID in a ; is found in Play Area, starting with -- cgit v1.2.3 From 35cdf3bde1b52b6e637a10ef81222c4f7e65f0ba Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 17 Apr 2020 01:21:55 +0100 Subject: AI Computer Search routines --- src/engine/bank08.asm | 500 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 495 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index e1c70a5..8faf31d 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -42,7 +42,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $05, CLEFAIRY_DOLL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil unknown_data_20000 $05, MYSTERIOUS_FOSSIL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil unknown_data_20000 $02, POKE_BALL, CheckWhetherToPlayPokeball, AIPlayPokeball - unknown_data_20000 $02, COMPUTER_SEARCH, $5b34, $5b12 + unknown_data_20000 $02, COMPUTER_SEARCH, AIDecideComputerSearch, AIPlayComputerSearch unknown_data_20000 $02, POKEMON_TRADER, $5d8f, $5d7a db $ff @@ -5130,8 +5130,417 @@ CheckWhetherToPlayPokeball: ; 219c6 (8:59c6) ret ; 0x21b12 -Func_21b12: ; 21b12 (8:5b12) - INCROM $21b12, $227f6 +AIPlayComputerSearch: ; 21b12 (8:5b12) + ld a, [wce21] + or $08 + ld [wce21], a + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTempRetreatCostCards], a + ld a, [wce1a] + ldh [hTemp_ffa0], a + ld a, [wce1b] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x21b34 + +; checks what Deck ID AI is playing and handle +; them in their own routine. +AIDecideComputerSearch: ; 21b34 (8:5b34) +; skip if number of cards in hand < 3 + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 3 + jr c, .no_carry + + ld a, [wOpponentDeckID] + cp ROCK_CRUSHER_DECK_ID + jr z, AIDecideComputerSearch_RockCrusher + cp WONDERS_OF_SCIENCE_DECK_ID + jp z, AIDecideComputerSearch_WondersOfScience + cp FIRE_CHARGE_DECK_ID + jp z, AIDecideComputerSearch_FireCharge + cp ANGER_DECK_ID + jp z, AIDecideComputerSearch_Anger + +.no_carry + or a + ret + +AIDecideComputerSearch_RockCrusher: ; 21b55 (8:5b55) +; if number of cards in hand is equal to 3, +; target Professor Oak in deck + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 3 + jr nz, .graveler + + ld e, PROFESSOR_OAK + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr c, .find_discard_cards_1 + ; no Professor Oak in deck, fallthrough + +.no_carry + or a + ret + +.find_discard_cards_1 + ld [wce06], a + ld a, $ff + ld [wce1a], a + ld [wce1b], a + + call CreateHandCardList + ld hl, wDuelTempList + ld de, wce1a +.loop_hand_1 + ld a, [hli] + cp $ff + jr z, .check_discard_cards + + ld c, a + call LoadCardDataToBuffer1_FromDeckIndex + +; if any of the following cards are in the hand, +; return no carry. + cp PROFESSOR_OAK + jr z, .no_carry + cp FIGHTING_ENERGY + jr z, .no_carry + cp DOUBLE_COLORLESS_ENERGY + jr z, .no_carry + cp DIGLETT + jr z, .no_carry + cp GEODUDE + jr z, .no_carry + cp ONIX + jr z, .no_carry + cp RHYHORN + jr z, .no_carry + +; if it's same as card in wce16, skip this card. + ld a, [wce16] + ld b, a + ld a, c + cp b + jr z, .loop_hand_1 + +; store this card index in memory + ld [de], a + inc de + jr .loop_hand_1 + +.check_discard_cards +; check if two cards were found +; if so, output in a the deck index +; of Professor Oak card found in deck and set carry. + ld a, [wce1b] + cp $ff + jr z, .no_carry + ld a, [wce06] + scf + ret + +; more than 3 cards in hand, so look for +; specific evolution cards. + +; checks if there is a Graveler card in the deck to target. +; if so, check if there's Geodude in hand or Play Area, +; and if there's no Graveler card in hand, proceed. +; also removes Geodude from hand list so that it is not discarded. +.graveler + ld e, GRAVELER + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .golem + ld [wce06], a + ld a, GEODUDE + call LookForCardIDInHandAndPlayArea + jr nc, .golem + ld a, GRAVELER + call LookForCardIDInHandList_Bank8 + jr c, .golem + call CreateHandCardList + ld hl, wDuelTempList + ld e, GEODUDE + farcall RemoveCardIDInList + jr .find_discard_cards_2 + +; checks if there is a Golem card in the deck to target. +; if so, check if there's Graveler in Play Area, +; and if there's no Golem card in hand, proceed. +.golem + ld e, GOLEM + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .dugtrio + ld [wce06], a + ld a, GRAVELER + call LookForCardIDInPlayArea_Bank8 + jr nc, .dugtrio + ld a, GOLEM + call LookForCardIDInHandList_Bank8 + jr c, .dugtrio + call CreateHandCardList + ld hl, wDuelTempList + jr .find_discard_cards_2 + +; checks if there is a Dugtrio card in the deck to target. +; if so, check if there's Diglett in Play Area, +; and if there's no Dugtrio card in hand, proceed. +.dugtrio + ld e, DUGTRIO + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry + ld [wce06], a + ld a, DIGLETT + call LookForCardIDInPlayArea_Bank8 + jp nc, .no_carry + ld a, DUGTRIO + call LookForCardIDInHandList_Bank8 + jp c, .no_carry + call CreateHandCardList + ld hl, wDuelTempList + jr .find_discard_cards_2 + +.find_discard_cards_2 + ld a, $ff + ld [wce1a], a + ld [wce1b], a + + ld bc, wce1a + ld d, $00 ; start considering Trainer cards only + ld a, [wce16] + ld e, a + +; this loop will store in wce1a cards to discard from hand. +; at the start it will only consider Trainer cards, +; then if there are still needed to discard, +; move on to Pokemon cards, and finally to Energy cards. +.loop_hand_2 + call RemoveFromListDifferentCardOfGivenType + jr c, .found + inc d ; move on to next type (Pokemon, then Energy) + ld a, $03 + cp d + jp z, .no_carry ; no more types to look + jr .loop_hand_2 +.found +; store this card in memory, +; and if there's still one more card to search for, +; jump back into the loop. + ld [bc], a + inc bc + ld a, [wce1b] + cp $ff + jr z, .loop_hand_2 + +; output in a Computer Search target and set carry. + ld a, [wce06] + scf + ret + +AIDecideComputerSearch_WondersOfScience: ; 21c56 (8:5c56) +; if number of cards in hand < 5, target Professor Oak in deck + ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND + call GetTurnDuelistVariable + cp 5 + jr nc, .look_in_hand + +; target Professor Oak for Computer Search + ld e, PROFESSOR_OAK + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .look_in_hand ; can be a jr + ld [wce06], a + jr .find_discard_cards + +; Professor Oak not in deck, move on to +; look for other cards instead. +; if Grimer or Muk are not in hand, +; check whether to use Computer Search on them. +.look_in_hand + ld a, GRIMER + call LookForCardIDInHandList_Bank8 + jr nc, .target_grimer + ld a, MUK + call LookForCardIDInHandList_Bank8 + jr nc, .target_muk + +.no_carry + or a + ret + +; first check Grimer +; if in deck, check cards to discard. +.target_grimer + ld e, GRIMER + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry ; can be a jr + ld [wce06], a + jr .find_discard_cards + +; first check Muk +; if in deck, check cards to discard. +.target_muk + ld e, MUK + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry ; can be a jr + ld [wce06], a + +; only discard Trainer cards from hand. +; if there are less than 2 Trainer cards to discard, +; then return with no carry. +; else, store the cards to discard and the +; target card deck index, and return carry. +.find_discard_cards + call CreateHandCardList + ld hl, wDuelTempList + ld d, $00 ; first consider Trainer cards + ld a, [wce16] + ld e, a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1a], a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1b], a + ld a, [wce06] + scf + ret + +AIDecideComputerSearch_FireCharge: ; 21cbb (8:5cbb) +; pick target card in deck from highest to lowest priority. +; if not found in hand, go to corresponding branch. + ld a, CHANSEY + call LookForCardIDInHandList_Bank8 + jr nc, .chansey + ld a, TAUROS + call LookForCardIDInHandList_Bank8 + jr nc, .tauros + ld a, JIGGLYPUFF1 + call LookForCardIDInHandList_Bank8 + jr nc, .jigglypuff + ; fallthrough + +.no_carry + or a + ret + +; for each card targeted, check if it's in deck and, +; if not, then return no carry. +; else, look for cards to discard. +.chansey + ld e, CHANSEY + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry + ld [wce06], a + jr .find_discard_cards +.tauros + ld e, TAUROS + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry + ld [wce06], a + jr .find_discard_cards +.jigglypuff + ld e, JIGGLYPUFF1 + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jp nc, .no_carry + ld [wce06], a + +; only discard Trainer cards from hand. +; if there are less than 2 Trainer cards to discard, +; then return with no carry. +; else, store the cards to discard and the +; target card deck index, and return carry. +.find_discard_cards + call CreateHandCardList + ld hl, wDuelTempList + ld d, $00 ; first consider Trainer cards + ld a, [wce16] + ld e, a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1a], a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1b], a + ld a, [wce06] + scf + ret +; 0x21d1e + +AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, search for card. +; otherwise, check if the evolution card is in +; hand and if so, search for it instead. + ld b, RATTATA + ld a, RATICATE + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_discard_cards + ld a, RATTATA + ld b, RATICATE + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_discard_cards + ld b, GROWLITHE + ld a, ARCANINE1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_discard_cards + ld a, GROWLITHE + ld b, ARCANINE1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_discard_cards + ld b, DODUO + ld a, DODRIO + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_discard_cards + ld a, DODUO + ld b, DODRIO + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_discard_cards + ; fallthrough + +.no_carry + or a + ret + +; only discard Trainer cards from hand. +; if there are less than 2 Trainer cards to discard, +; then return with no carry. +; else, store the cards to discard and the +; target card deck index, and return carry. +.find_discard_cards + ld [wce06], a + call CreateHandCardList + ld hl, wDuelTempList + ld d, $00 ; first consider Trainer cards + ld a, [wce16] + ld e, a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1a], a + call RemoveFromListDifferentCardOfGivenType + jr nc, .no_carry + ld [wce1b], a + ld a, [wce06] + scf + ret +; 0x21d7a + +Func_21d7a: ; 21d7a (8:5d7a) + INCROM $21d7a, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. @@ -5773,8 +6182,89 @@ LookForCardIDInPlayArea_Bank8: ; 22a72 (8:6a72) ret ; 0x22a95 -Func_22a95 ; 22a95 (8:6a95) - INCROM $22a95, $22bad +; runs through list avoiding card in e. +; removes first card in list not equal to e +; and that has a type allowed to be removed, in d. +; returns carry if successful in finding a card. +; input: +; d = type of card allowed to be removed +; ($00 = Trainer, $01 = Pokemon, $02 = Energy) +; e = card deck index to avoid removing +; output: +; a = card index of removed card +RemoveFromListDifferentCardOfGivenType: ; 22a95 (8:6a95) + push hl + push de + push bc + call CountCardsInDuelTempList + call ShuffleCards + +; loop list until a card with +; deck index different from e is found. +.loop_list + ld a, [hli] + cp $ff + jr z, .no_carry + cp e + jr z, .loop_list + +; get this card's type + ldh [hTempCardIndex_ff98], a + push de + call GetCardIDFromDeckIndex + call GetCardType + pop de + cp TYPE_ENERGY + jr c, .pkmn_card + cp TYPE_TRAINER + jr nz, .energy + +; only remove from list specific type. + +; trainer + ld a, d + or a + jr nz, .loop_list + jr .remove_card +.energy + ld a, d + cp $02 + jr nz, .loop_list + jr .remove_card +.pkmn_card + ld a, d + cp $01 + jr nz, .loop_list + ; fallthrough + +.remove_card + ld d, h + ld e, l + dec hl +.loop_remove + ld a, [de] + inc de + ld [hli], a + cp $ff + jr nz, .loop_remove + +; success + ldh a, [hTempCardIndex_ff98] + pop bc + pop de + pop hl + scf + ret +.no_carry + pop bc + pop de + pop hl + or a + ret +; 0x22ae0 + +Func_22ae0 ; 22ae0 (8:6ae0) + INCROM $22ae0, $22bad ; return carry flag if move is not high recoil. Func_22bad: ; 22bad (8:6bad) -- cgit v1.2.3 From 104ef4708f88d16ccf5dfde641021fb33e5d8195 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 17 Apr 2020 18:51:11 +0100 Subject: AI Pokemon Trader routines --- src/engine/bank05.asm | 38 ++- src/engine/bank08.asm | 830 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 859 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 62529a4..e6d80c3 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1765,8 +1765,42 @@ CheckIfAnyCardIDinLocation: ; 157a3 (5:57a3) ret ; 0x157c6 -Func_157c6: ; 157c6 (5:57c6) - INCROM $157c6, $157f3 +; outputs in a total number of energy cards in hand +; plus all the cards attached in Turn Duelist's Play Area. +CountEnergyCardsInHandAndAttached: ; 157c6 (5:57c6) + xor a + ld [wTempAI], a + call CreateEnergyCardListFromHand + jr c, .attached + +; counts number of energy cards in hand + ld b, -1 + ld hl, wDuelTempList +.loop_hand + inc b + ld a, [hli] + cp $ff + jr nz, .loop_hand + ld a, b + ld [wTempAI], a + +; counts number of energy cards +; that are attached in Play Area +.attached + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld d, a + ld e, PLAY_AREA_ARENA +.loop_play_area + call CountNumberOfEnergyCardsAttached + ld hl, wTempAI + add [hl] + ld [hl], a + inc e + dec d + jr nz, .loop_play_area + ret +; 0x157f3 ; returns carry if any card with ID in e is found ; in the list that is pointed by hl. diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 8faf31d..7e3127e 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -43,7 +43,7 @@ Data_20000: ; 20000 (8:4000) unknown_data_20000 $05, MYSTERIOUS_FOSSIL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil unknown_data_20000 $02, POKE_BALL, CheckWhetherToPlayPokeball, AIPlayPokeball unknown_data_20000 $02, COMPUTER_SEARCH, AIDecideComputerSearch, AIPlayComputerSearch - unknown_data_20000 $02, POKEMON_TRADER, $5d8f, $5d7a + unknown_data_20000 $02, POKEMON_TRADER, AIDecidePokemonTrader, AIPlayPokemonTrader db $ff Func_200e5: ; 200e5 (8:40e5) @@ -5483,9 +5483,9 @@ AIDecideComputerSearch_FireCharge: ; 21cbb (8:5cbb) AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) ; for each of the following cards, ; first run a check if there's a pre-evolution in -; Play Area or in the hand. If there is, search for card. +; Play Area or in the hand. If there is, choose it as target. ; otherwise, check if the evolution card is in -; hand and if so, search for it instead. +; hand and if so, choose it as target instead. ld b, RATTATA ld a, RATICATE call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea @@ -5539,8 +5539,653 @@ AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) ret ; 0x21d7a -Func_21d7a: ; 21d7a (8:5d7a) - INCROM $21d7a, $227f6 +AIPlayPokemonTrader: ; 21d7a (8:5d7a) + ld a, [wce16] + ldh [hTempCardIndex_ff9f], a + ld a, [wce19] + ldh [hTemp_ffa0], a + ld a, [wce1a] + ldh [hTempPlayAreaLocation_ffa1], a + ld a, $07 + bank1call AIMakeDecision + ret +; 0x21d8f + +AIDecidePokemonTrader: ; 21d8f (8:5d8f) +; each deck has their own routine for picking +; what Pokemon to look for. + ld a, [wOpponentDeckID] + cp LEGENDARY_MOLTRES_DECK_ID + jr z, AIDecidePokemonTrader_LegendaryMoltres + cp LEGENDARY_ARTICUNO_DECK_ID + jr z, AIDecidePokemonTrader_LegendaryArticuno + cp LEGENDARY_DRAGONITE_DECK_ID + jp z, AIDecidePokemonTrader_LegendaryDragonite + cp LEGENDARY_RONALD_DECK_ID + jp z, AIDecidePokemonTrader_LegendaryRonald + cp BLISTERING_POKEMON_DECK_ID + jp z, AIDecidePokemonTrader_BlisteringPokemon + cp SOUND_OF_THE_WAVES_DECK_ID + jp z, AIDecidePokemonTrader_SoundOfTheWaves + cp POWER_GENERATOR_DECK_ID + jp z, AIDecidePokemonTrader_PowerGenerator + cp FLOWER_GARDEN_DECK_ID + jp z, AIDecidePokemonTrader_FlowerGarden + cp STRANGE_POWER_DECK_ID + jp z, AIDecidePokemonTrader_StrangePower + cp FLAMETHROWER_DECK_ID + jp z, AIDecidePokemonTrader_Flamethrower + or a + ret + +AIDecidePokemonTrader_LegendaryMoltres: ; 21dc4 (8:5dc4) +; look for Moltres2 card in deck to trade with a +; card in hand different from Moltres1. + ld a, MOLTRES2 + ld e, MOLTRES1 + call LookForCardIDToTradeWithDifferentHandCard + jr nc, .no_carry +; success + ld [wce1a], a + ld a, e + scf + ret +.no_carry + or a + ret + +AIDecidePokemonTrader_LegendaryArticuno: ; 21dd5 (8:5dd5) +; if has none of these cards in Hand or Play Area, proceed + ld a, ARTICUNO1 + call LookForCardIDInHandAndPlayArea + jr c, .no_carry + ld a, LAPRAS + call LookForCardIDInHandAndPlayArea + jr c, .no_carry + +; if doesn't have Seel in Hand or Play Area, +; look for it in the deck. +; otherwise, look for Dewgong instead. + ld a, SEEL + call LookForCardIDInHandAndPlayArea + jr c, .dewgong + + ld e, SEEL + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .dewgong + ld [wce1a], a + jr .check_hand + +.dewgong + ld a, DEWGONG + call LookForCardIDInHandAndPlayArea + jr c, .no_carry + ld e, DEWGONG + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .no_carry + ld [wce1a], a + +; a Seel or Dewgong was found in deck, +; check hand for card to trade for +.check_hand + ld a, CHANSEY + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, DITTO + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, ARTICUNO2 + call CheckIfHasCardIDInHand + jr c, .set_carry + ; doesn't have any of the cards in hand + +.no_carry + or a + ret + +.set_carry + scf + ret +; 0x21e24 + +AIDecidePokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) +; if has less than 5 cards of energy +; and of Pokemon in hand/Play Area, +; target a Kangaskhan in deck. + farcall CountEnergyCardsInHandAndAttached + cp 5 + jr c, .kangaskhan + call CountPokemonCardsInHandAndInPlayArea + cp 5 + jr c, .kangaskhan + ; total number of energy cards >= 5 + ; total number of Pokemon cards >= 5 + +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, MAGIKARP + ld a, GYARADOS + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, MAGIKARP + ld b, GYARADOS + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, DRATINI + ld a, DRAGONAIR + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld b, DRAGONAIR + ld a, DRAGONITE1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, DRATINI + ld b, DRAGONAIR + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld a, DRAGONAIR + ld b, DRAGONITE1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, CHARMANDER + ld a, CHARMELEON + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld b, CHARMELEON + ld a, CHARIZARD + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, CHARMANDER + ld b, CHARMELEON + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld a, CHARMELEON + ld b, CHARIZARD + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + jr .no_carry + +.kangaskhan + ld e, KANGASKHAN + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .no_carry + +; card was found as target in deck, +; look for card in hand to trade with +.choose_hand + ld [wce1a], a + ld a, DRAGONAIR + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, CHARMELEON + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, GYARADOS + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, MAGIKARP + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, CHARMANDER + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, DRATINI + call CheckIfHasCardIDInHand + jr c, .set_carry + ; non found + +.no_carry + or a + ret +.set_carry + scf + ret +; 0x21ec9 + +AIDecidePokemonTrader_LegendaryRonald: ; 21ec9 (8:5ec9) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, EEVEE + ld a, FLAREON1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld b, EEVEE + ld a, VAPOREON1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld b, EEVEE + ld a, JOLTEON1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, EEVEE + ld b, FLAREON1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld a, EEVEE + ld b, VAPOREON1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld a, EEVEE + ld b, JOLTEON1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, DRATINI + ld a, DRAGONAIR + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld b, DRAGONAIR + ld a, DRAGONITE1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, DRATINI + ld b, DRAGONAIR + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld a, DRAGONAIR + ld b, DRAGONITE1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + jr .no_carry + +; card was found as target in deck, +; look for card in hand to trade with +.choose_hand + ld [wce1a], a + ld a, ZAPDOS3 + call LookForCardIDInHandList_Bank8 + jr c, .set_carry + ld a, ARTICUNO2 + call LookForCardIDInHandList_Bank8 + jr c, .set_carry + ld a, MOLTRES2 + call LookForCardIDInHandList_Bank8 + jr c, .set_carry + ; none found + +.no_carry + or a + ret +.set_carry + scf + ret +; 0x21f41 + +AIDecidePokemonTrader_BlisteringPokemon: ; 21f41 (8:5f41) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, RHYHORN + ld a, RHYDON + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, RHYHORN + ld b, RHYDON + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, CUBONE + ld a, MAROWAK1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, CUBONE + ld b, MAROWAK1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, PONYTA + ld a, RAPIDASH + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, PONYTA + ld b, RAPIDASH + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + jr .no_carry + +; a card in deck was found to look for, +; check if there are duplicates in hand to trade with. +.find_duplicates + ld [wce1a], a + call FindDuplicatePokemonCards + jr c, .set_carry +.no_carry + or a + ret +.set_carry + scf + ret +; 0x21f85 + +AIDecidePokemonTrader_SoundOfTheWaves: ; 21f85 (8:5f85) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, SEEL + ld a, DEWGONG + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, SEEL + ld b, DEWGONG + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, KRABBY + ld a, KINGLER + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, KRABBY + ld b, KINGLER + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, SHELLDER + ld a, CLOYSTER + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, SHELLDER + ld b, CLOYSTER + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, HORSEA + ld a, SEADRA + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, HORSEA + ld b, SEADRA + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + ld b, TENTACOOL + ld a, TENTACRUEL + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .choose_hand + ld a, TENTACOOL + ld b, TENTACRUEL + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .choose_hand + jr .no_carry + +; card was found as target in deck, +; look for card in hand to trade with +.choose_hand + ld [wce1a], a + ld a, SEEL + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, KRABBY + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, HORSEA + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, SHELLDER + call CheckIfHasCardIDInHand + jr c, .set_carry + ld a, TENTACOOL + call CheckIfHasCardIDInHand + jr c, .set_carry + ; none found + +.no_carry + or a + ret +.set_carry + scf + ret +; 0x2200b + +AIDecidePokemonTrader_PowerGenerator: ; 2200b (8:600b) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, PIKACHU2 + ld a, RAICHU1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jp c, .find_duplicates + ld b, PIKACHU1 + ld a, RAICHU1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, PIKACHU2 + ld b, RAICHU1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, PIKACHU1 + ld b, RAICHU1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, VOLTORB + ld a, ELECTRODE2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, VOLTORB + ld a, ELECTRODE1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, VOLTORB + ld b, ELECTRODE2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, VOLTORB + ld b, ELECTRODE1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, MAGNEMITE1 + ld a, MAGNETON2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, MAGNEMITE2 + ld a, MAGNETON2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, MAGNEMITE1 + ld a, MAGNETON1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, MAGNEMITE2 + ld a, MAGNETON1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, MAGNEMITE2 + ld b, MAGNETON2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, MAGNEMITE1 + ld b, MAGNETON2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, MAGNEMITE2 + ld b, MAGNETON1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, MAGNEMITE1 + ld b, MAGNETON1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ; bug, missing jr .no_carry + +; since this last check falls through regardless of result, +; register a might hold an invalid deck index, +; which might lead to hilarious results like Brandon +; trading a Pikachu with a Grass Energy from the deck. +; however, since it's deep in a tower of conditionals, +; reaching here is extremely unlikely. + +; a card in deck was found to look for, +; check if there are duplicates in hand to trade with. +.find_duplicates + ld [wce1a], a + call FindDuplicatePokemonCards + jr c, .set_carry + or a + ret +.set_carry + scf + ret +; 0x220a8 + +AIDecidePokemonTrader_FlowerGarden: ; 220a8 (8:60a8) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, BULBASAUR + ld a, IVYSAUR + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, IVYSAUR + ld a, VENUSAUR2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, BULBASAUR + ld b, IVYSAUR + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, IVYSAUR + ld b, VENUSAUR2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, BELLSPROUT + ld a, WEEPINBELL + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, WEEPINBELL + ld a, VICTREEBEL + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, BELLSPROUT + ld b, WEEPINBELL + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, WEEPINBELL + ld b, VICTREEBEL + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, ODDISH + ld a, GLOOM + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, GLOOM + ld a, VILEPLUME + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, ODDISH + ld b, GLOOM + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, GLOOM + ld b, VILEPLUME + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + jr .no_carry + +; a card in deck was found to look for, +; check if there are duplicates in hand to trade with. +.find_duplicates + ld [wce1a], a + call FindDuplicatePokemonCards + jr c, .asm_22120 +.no_carry + or a + ret +.asm_22120 + scf + ret +; 0x22122 + +AIDecidePokemonTrader_StrangePower: ; 22122 (8:6122) +; looks for a Pokemon in hand to trade with Mr Mime in deck. +; inputing Mr Mime in register e for the function is redundant +; since it already checks whether a Mr Mime exists in the hand. + ld a, MR_MIME + ld e, MR_MIME + call LookForCardIDToTradeWithDifferentHandCard + jr nc, .no_carry +; found + ld [wce1a], a + ld a, e + scf + ret +.no_carry + or a + ret +; 0x22133 + +AIDecidePokemonTrader_Flamethrower: ; 22133 (8:6133) +; for each of the following cards, +; first run a check if there's a pre-evolution in +; Play Area or in the hand. If there is, choose it as target. +; otherwise, check if the evolution card is in +; hand and if so, choose it as target instead. + ld b, CHARMANDER + ld a, CHARMELEON + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld b, CHARMELEON + ld a, CHARIZARD + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, CHARMANDER + ld b, CHARMELEON + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld a, CHARMELEON + ld b, CHARIZARD + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, VULPIX + ld a, NINETAILS1 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, VULPIX + ld b, NINETAILS1 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, GROWLITHE + ld a, ARCANINE2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, GROWLITHE + ld b, ARCANINE2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + ld b, EEVEE + ld a, FLAREON2 + call LookForCardIDInDeck_GivenCardIDInHandAndPlayArea + jr c, .find_duplicates + ld a, EEVEE + ld b, FLAREON2 + call LookForCardIDInDeck_GivenCardIDInHand + jr c, .find_duplicates + jr .no_carry + +; a card in deck was found to look for, +; check if there are duplicates in hand to trade with. +.find_duplicates + ld [wce1a], a + call FindDuplicatePokemonCards + jr c, .set_carry +.no_carry + or a + ret +.set_carry + scf + ret +; 0x2219b + +Func_2219b: ; 2219b (8:219b) + INCROM $2219b, $227f6 ; lists in wDuelTempList all the basic energy cards ; is card location of a. @@ -6263,8 +6908,179 @@ RemoveFromListDifferentCardOfGivenType: ; 22a95 (8:6a95) ret ; 0x22ae0 -Func_22ae0 ; 22ae0 (8:6ae0) - INCROM $22ae0, $22bad +; used in Pokemon Trader checks to look for a specific +; card in the deck to trade with a card in hand that +; has a card ID different from e. +; returns carry if successful. +; input: +; a = card ID 1 +; e = card ID 2 +; output: +; a = deck index of card ID 1 found in deck +; e = deck index of Pokemon card in hand dfferent than card ID 2 +LookForCardIDToTradeWithDifferentHandCard: ; 22ae0 (8:6ae0) + ld hl, wCurCardCanAttack + ld [hl], e + ld [wTempAI], a + +; if card ID 1 is in hand, return no carry. + call LookForCardIDInHandList_Bank8 + jr c, .no_carry + +; if card ID 1 is not in deck, return no carry. + ld a, [wTempAI] + ld e, a + ld a, CARD_LOCATION_DECK + call LookForCardIDInLocation + jr nc, .no_carry + +; store its deck index + ld [wTempAI], a + +; look in hand for Pokemon card ID that +; is different from card ID 2. + ld a, [wCurCardCanAttack] + ld c, a + call CreateHandCardList + ld hl, wDuelTempList + +.loop_hand + ld a, [hli] + cp $ff + jr z, .no_carry + ld b, a + call LoadCardDataToBuffer1_FromDeckIndex + cp c + jr z, .loop_hand + ld a, [wLoadedCard1Type] + cp TYPE_ENERGY + jr nc, .loop_hand + +; found, output deck index of card ID 1 in deck +; and deck index of card found in hand, and set carry + ld e, b + ld a, [wTempAI] + scf + ret + +.no_carry + or a + ret +; 0x22b1f + +; returns carry if at least one card in the hand +; has the card ID of input. Outputs its index. +; input: +; a = card ID to look for +; output: +; a = deck index of card in hand found +CheckIfHasCardIDInHand: ; 22b1f (8:6b1f) + ld [wTempCardIDToLook], a + call CreateHandCardList + ld hl, wDuelTempList + ld c, 0 + +.loop_hand + ld a, [hli] + cp $ff + ret z + ldh [hTempCardIndex_ff98], a + call LoadCardDataToBuffer1_FromDeckIndex + ld b, a + ld a, [wTempCardIDToLook] + cp b + jr nz, .loop_hand + ld a, c + or a + jr nz, .set_carry + inc c + jr nz, .loop_hand + +.set_carry + ldh a, [hTempCardIndex_ff98] + scf + ret +; 0x22b45 + +; outputs in a total number of Pokemon cards in hand +; plus Pokemon in Turn Duelist's Play Area. +CountPokemonCardsInHandAndInPlayArea: ; 22b45 (8:6b45) + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld [wTempAI], a + call CreateHandCardList + ld hl, wDuelTempList +.loop_hand + ld a, [hli] + cp $ff + jr z, .done + call GetCardIDFromDeckIndex + call GetCardType + cp TYPE_ENERGY + jr nc, .loop_hand + ld a, [wTempAI] + inc a + ld [wTempAI], a + jr .loop_hand +.done + ld a, [wTempAI] + ret +; 0x22b6f + +; returns carry if a duplicate Pokemon card is found in hand. +; outputs in a the deck index of one of them. +FindDuplicatePokemonCards: ; 22b6f (8:6b6f) + ld a, $ff + ld [wTempAI], a + call CreateHandCardList + ld hl, wDuelTempList + push hl + +.loop_hand_outer + pop hl + ld a, [hli] + cp $ff + jr z, .done + call GetCardIDFromDeckIndex + ld b, e + push hl + +.loop_hand_inner + ld a, [hli] + cp $ff + jr z, .loop_hand_outer + ld c, a + call GetCardIDFromDeckIndex + ld a, e + cp b + jr nz, .loop_hand_inner + +; found two cards with same ID, +; if they are Pokemon cards, store its deck index. + push bc + call GetCardType + pop bc + cp TYPE_ENERGY + jr nc, .loop_hand_outer + ld a, c + ld [wTempAI], a + ; for some reason loop still continues + ; even though if some other duplicate + ; cards are found, it overwrites the result. + jr .loop_hand_outer + +.done + ld a, [wTempAI] + cp $ff + jr z, .no_carry + +; found + scf + ret +.no_carry + or a + ret +; 0x22bad ; return carry flag if move is not high recoil. Func_22bad: ; 22bad (8:6bad) -- cgit v1.2.3 From 4e2bb488d2a62087ebd9514ca69cbdd2566067d5 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Fri, 17 Apr 2020 19:02:23 +0100 Subject: Standardise AI routine names --- src/engine/bank08.asm | 148 +++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index 7e3127e..af95853 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6,44 +6,44 @@ unknown_data_20000: MACRO ENDM Data_20000: ; 20000 (8:4000) - unknown_data_20000 $07, POTION, CheckIfPotionPreventsKnockOut, AIPlayPotion - unknown_data_20000 $0a, POTION, FindTargetCardForPotion, AIPlayPotion - unknown_data_20000 $08, SUPER_POTION, CheckIfSuperPotionPreventsKnockOut, AIPlaySuperPotion - unknown_data_20000 $0b, SUPER_POTION, FindTargetCardForSuperPotion, AIPlaySuperPotion - unknown_data_20000 $0d, DEFENDER, CheckIfDefenderPreventsKnockOut, AIPlayDefender - unknown_data_20000 $0e, DEFENDER, CheckIfDefenderPreventsRecoilKnockOut, AIPlayDefender - unknown_data_20000 $0d, PLUSPOWER, CheckIfPluspowerBoostCausesKnockOut, AIPlayPluspower - unknown_data_20000 $0e, PLUSPOWER, CheckIfMoveNeedsPluspowerBoostToKnockOut, AIPlayPluspower - unknown_data_20000 $09, SWITCH, CheckIfActiveCardCanSwitch, AIPlaySwitch - unknown_data_20000 $07, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind - unknown_data_20000 $0a, GUST_OF_WIND, CheckWhetherToUseGustOfWind, AIPlayGustOfWind - unknown_data_20000 $04, BILL, CheckDeckCardsAmount, AIPlayBill - unknown_data_20000 $05, ENERGY_REMOVAL, CheckEnergyCardToRemoveInPlayArea, AIPlayEnergyRemoval - unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, CheckTwoEnergyCardsToRemoveInPlayArea, AIPlaySuperEnergyRemoval - unknown_data_20000 $07, POKEMON_BREEDER, CheckIfCanEvolve2StageFromHand, AIPlayPokemonBreeder - unknown_data_20000 $0f, PROFESSOR_OAK, CheckIfCanPlayProfessorOak, AIPlayProfessorOak - unknown_data_20000 $0a, ENERGY_RETRIEVAL, CheckEnergyRetrievalCardsToPick, AIPlayEnergyRetrieval - unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, CheckSuperEnergyRetrievalCardsToPick, AIPlaySuperEnergyRetrieval - unknown_data_20000 $06, POKEMON_CENTER, CheckIfCanPlayPokemonCenter, AIPlayPokemonCenter - unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, CheckWhetherToPlayImposterProfessorOak, AIPlayImposterProfessorOak - unknown_data_20000 $0c, ENERGY_SEARCH, CheckIfEnergySearchCanBePlayed, AIPlayEnergySearch - unknown_data_20000 $03, POKEDEX, CheckWhetherToPlayPokedex, AIPlayPokedex - unknown_data_20000 $07, FULL_HEAL, CheckWhetherToPlayFullHeal, AIPlayFullHeal - unknown_data_20000 $0a, MR_FUJI, CheckWhetherToPlayMrFuji, AIPlayMrFuji - unknown_data_20000 $0a, SCOOP_UP, CheckWhetherToPlayScoopUp, AIPlayScoopUp - unknown_data_20000 $02, MAINTENANCE, CheckWhetherToPlayMaintencance, AIPlayMaintenance - unknown_data_20000 $03, RECYCLE, CheckWhetherToPlayRecycle, AIPlayRecycle - unknown_data_20000 $0d, LASS, CheckWhetherToPlayLass, AIPlayLass - unknown_data_20000 $04, ITEM_FINDER, CheckWhetherToPlayItemFinder, AIPlayItemFinder - unknown_data_20000 $01, IMAKUNI_CARD, CheckWhetherToPlayImakuni, AIPlayImakuni - unknown_data_20000 $01, GAMBLER, CheckWhetherToPlayGambler, AIPlayGambler - unknown_data_20000 $05, REVIVE, CheckWhetherToPlayRevive, AIPlayRevive - unknown_data_20000 $0d, POKEMON_FLUTE, CheckWhetherToPlayPokemonFlute, AIPlayPokemonFlute - unknown_data_20000 $05, CLEFAIRY_DOLL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil - unknown_data_20000 $05, MYSTERIOUS_FOSSIL, CheckWhetherToPlayClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil - unknown_data_20000 $02, POKE_BALL, CheckWhetherToPlayPokeball, AIPlayPokeball - unknown_data_20000 $02, COMPUTER_SEARCH, AIDecideComputerSearch, AIPlayComputerSearch - unknown_data_20000 $02, POKEMON_TRADER, AIDecidePokemonTrader, AIPlayPokemonTrader + unknown_data_20000 $07, POTION, AIDecidePotion1, AIPlayPotion + unknown_data_20000 $0a, POTION, AIDecidePotion2, AIPlayPotion + unknown_data_20000 $08, SUPER_POTION, AIDecideSuperPotion1, AIPlaySuperPotion + unknown_data_20000 $0b, SUPER_POTION, AIDecideSuperPotion2, AIPlaySuperPotion + unknown_data_20000 $0d, DEFENDER, AIDecideDefender1, AIPlayDefender + unknown_data_20000 $0e, DEFENDER, AIDecideDefender2, AIPlayDefender + unknown_data_20000 $0d, PLUSPOWER, AIDecidePluspower1, AIPlayPluspower + unknown_data_20000 $0e, PLUSPOWER, AIDecidePluspower2, AIPlayPluspower + unknown_data_20000 $09, SWITCH, AIDecideSwitch, AIPlaySwitch + unknown_data_20000 $07, GUST_OF_WIND, AIDecideGustOfWind, AIPlayGustOfWind + unknown_data_20000 $0a, GUST_OF_WIND, AIDecideGustOfWind, AIPlayGustOfWind + unknown_data_20000 $04, BILL, AIDecideBill, AIPlayBill + unknown_data_20000 $05, ENERGY_REMOVAL, AIDecideEnergyRemoval, AIPlayEnergyRemoval + unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, AIDecideSuperEnergyRemoval, AIPlaySuperEnergyRemoval + unknown_data_20000 $07, POKEMON_BREEDER, AIDecidePokemonBreeder, AIPlayPokemonBreeder + unknown_data_20000 $0f, PROFESSOR_OAK, AIDecideProfessorOak, AIPlayProfessorOak + unknown_data_20000 $0a, ENERGY_RETRIEVAL, AIDecideEnergyRetrieval, AIPlayEnergyRetrieval + unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, AIDecideSuperEnergyRetrieval, AIPlaySuperEnergyRetrieval + unknown_data_20000 $06, POKEMON_CENTER, AIDecidePokemonCenter, AIPlayPokemonCenter + unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, AIDecideImposterProfessorOak, AIPlayImposterProfessorOak + unknown_data_20000 $0c, ENERGY_SEARCH, AIDecideEnergySearch, AIPlayEnergySearch + unknown_data_20000 $03, POKEDEX, AIDecidePokedex, AIPlayPokedex + unknown_data_20000 $07, FULL_HEAL, AIDecideFullHeal, AIPlayFullHeal + unknown_data_20000 $0a, MR_FUJI, AIDecideMrFuji, AIPlayMrFuji + unknown_data_20000 $0a, SCOOP_UP, AIDecideScoopUp, AIPlayScoopUp + unknown_data_20000 $02, MAINTENANCE, AIDecideMaintenance, AIPlayMaintenance + unknown_data_20000 $03, RECYCLE, AIDecideRecycle, AIPlayRecycle + unknown_data_20000 $0d, LASS, AIDecideLass, AIPlayLass + unknown_data_20000 $04, ITEM_FINDER, AIDecideItemFinder, AIPlayItemFinder + unknown_data_20000 $01, IMAKUNI_CARD, AIDecideImakuni, AIPlayImakuni + unknown_data_20000 $01, GAMBLER, AIDecideGambler, AIPlayGambler + unknown_data_20000 $05, REVIVE, AIDecideRevive, AIPlayRevive + unknown_data_20000 $0d, POKEMON_FLUTE, AIDecidePokemonFlute, AIPlayPokemonFlute + unknown_data_20000 $05, CLEFAIRY_DOLL, AIDecideClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil + unknown_data_20000 $05, MYSTERIOUS_FOSSIL, AIDecideClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil + unknown_data_20000 $02, POKE_BALL, AIDecidePokeball, AIPlayPokeball + unknown_data_20000 $02, COMPUTER_SEARCH, AIDecideComputerSearch, AIPlayComputerSearch + unknown_data_20000 $02, POKEMON_TRADER, AIDecidePokemonTrader, AIPlayPokemonTrader db $ff Func_200e5: ; 200e5 (8:40e5) @@ -199,7 +199,7 @@ AIPlayPotion: ; 201b5 (8:41b5) ; next turn after using Potion. ; if it cannot, return carry. ; also take into account whether move is high recoil. -CheckIfPotionPreventsKnockOut: ; 201d1 (8:41d1) +AIDecidePotion1: ; 201d1 (8:41d1) farcall AIDecideWhetherToRetreat jr c, .no_carry call Func_22bad @@ -242,7 +242,7 @@ CheckIfPotionPreventsKnockOut: ; 201d1 (8:41d1) ; output: ; a = card to use Potion on; ; carry set if Potion should be used. -FindTargetCardForPotion: ; 20204 (8:4204) +AIDecidePotion2: ; 20204 (8:4204) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfDefendingPokemonCanKnockOut @@ -393,7 +393,7 @@ AIPlaySuperPotion: ; 202a8 (8:42a8) ; active card next turn after using Super Potion. ; if it cannot, return carry. ; also take into account whether move is high recoil. -CheckIfSuperPotionPreventsKnockOut: ; 202cc (8:42cc) +AIDecideSuperPotion1: ; 202cc (8:42cc) farcall AIDecideWhetherToRetreat jr c, .no_carry call Func_22bad @@ -447,7 +447,7 @@ CheckIfSuperPotionPreventsKnockOut: ; 202cc (8:42cc) ; output: ; a = card to use Super Potion on; ; carry set if Super Potion should be used. -FindTargetCardForSuperPotion: ; 2030f (8:430f) +AIDecideSuperPotion2: ; 2030f (8:430f) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfDefendingPokemonCanKnockOut @@ -637,7 +637,7 @@ AIPlayDefender: ; 203f8 (8:43f8) ; returns carry if using Defender can prevent a KO ; by the defending Pokémon. ; this takes into account both attacks and whether they're useable. -CheckIfDefenderPreventsKnockOut: ; 20406 (8:4406) +AIDecideDefender1: ; 20406 (8:4406) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfAnyMoveKnocksOutDefendingCard @@ -722,7 +722,7 @@ CheckIfDefenderPreventsKnockOut: ; 20406 (8:4406) ; return carry if using Defender prevents Pokémon ; from being knocked out by an attack with recoil. -CheckIfDefenderPreventsRecoilKnockOut: ; 20486 (8:4486) +AIDecideDefender2: ; 20486 (8:4486) ld a, MOVE_FLAG1_ADDRESS | HIGH_RECOIL_F call CheckLoadedMoveFlag jr c, .recoil @@ -810,7 +810,7 @@ AIPlayPluspower: ; 204e8 (8:44e8) ; returns carry if using a Pluspower can KO defending Pokémon ; if active card cannot KO without the boost. -CheckIfPluspowerBoostCausesKnockOut: ; 20501 (8:4501) +AIDecidePluspower1: ; 20501 (8:4501) ; this is mistakenly duplicated xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -934,7 +934,7 @@ CheckIfPluspowerBoostCausesKnockOut: ; 20501 (8:4501) ; if selected move is useable, can't KO without Pluspower boost ; can damage Mr. Mime even with Pluspower boost ; and has a minimum damage > 0. -CheckIfMoveNeedsPluspowerBoostToKnockOut: ; 205a5 (8:45a5) +AIDecidePluspower2: ; 205a5 (8:45a5) xor a ldh [hTempPlayAreaLocation_ff9d], a call .check_can_ko @@ -1025,7 +1025,7 @@ AIPlaySwitch: ; 20612 (8:4612) ; returns carry if the active card has less energy cards ; than the retreat cost and if AI can't play an energy ; card from the hand to fulfill the cost -CheckIfActiveCardCanSwitch: ; 2062e (8:462e) +AIDecideSwitch: ; 2062e (8:462e) ; check if AI can already play an energy card from hand to retreat ld a, [wAIPlayEnergyCardForRetreat] or a @@ -1085,7 +1085,7 @@ AIPlayGustOfWind: ; 20666 (8:4666) ret ; 0x2067e -CheckWhetherToUseGustOfWind: ; 2067e (8:467e) +AIDecideGustOfWind: ; 2067e (8:467e) ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetNonTurnDuelistVariable dec a @@ -1466,7 +1466,7 @@ AIPlayBill: ; 2086d (8:486d) ; 0x20878 ; return carry if cards in deck > 9 -CheckDeckCardsAmount: ; 20878 (8:4878) +AIDecideBill: ; 20878 (8:4878) ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable cp DECK_SIZE - 9 @@ -1486,7 +1486,7 @@ AIPlayEnergyRemoval: ; 20880 (8:4880) ; 0x20895 ; picks an energy card in the player's Play Area to remove -CheckEnergyCardToRemoveInPlayArea: ; 20895 (8:4895) +AIDecideEnergyRemoval: ; 20895 (8:4895) ; check if the current active card can KO player's card ; if it's possible to KO, then do not consider the player's ; active card to remove its attached energy @@ -1709,7 +1709,7 @@ AIPlaySuperEnergyRemoval: ; 20994 (8:4994) ; 0x209bc ; picks two energy cards in the player's Play Area to remove -CheckTwoEnergyCardsToRemoveInPlayArea: ; 209bc (8:49bc) +AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ld e, PLAY_AREA_BENCH_1 .loop_1 ; first find an Arena card with a color energy card @@ -1989,7 +1989,7 @@ AIPlayPokemonBreeder: ; 20b06 (8:4b06) ret ; 0x20b1b -CheckIfCanEvolve2StageFromHand: ; 20b1b (8:4b1b) +AIDecidePokemonBreeder: ; 20b1b (8:4b1b) call IsPrehistoricPowerActive jp c, .done @@ -2346,7 +2346,7 @@ AIPlayProfessorOak: ; 20cae (8:4cae) ; sets carry if AI determines a score of playing ; Professor Oak is over a certain threshold. -CheckIfCanPlayProfessorOak: ; 20cc1 (8:4cc1) +AIDecideProfessorOak: ; 20cc1 (8:4cc1) ; return if cards in deck <= 6 ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable @@ -2689,7 +2689,7 @@ AIPlayEnergyRetrieval: ; 20e44 (8:4e44) ; checks whether AI can play Energy Retrieval and ; picks the energy cards from the discard pile, ; and duplicate cards in hand to discard. -CheckEnergyRetrievalCardsToPick: ; 20e6e (8:4e6e) +AIDecideEnergyRetrieval: ; 20e6e (8:4e6e) ; return no carry if no cards in hand farcall CreateEnergyCardListFromHand jp nc, .no_carry @@ -2955,7 +2955,7 @@ AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) ret ; 0x20fc1 -CheckSuperEnergyRetrievalCardsToPick: ; 20fc1 (8:4fc1) +AIDecideSuperEnergyRetrieval: ; 20fc1 (8:4fc1) ; return no carry if no cards in hand farcall CreateEnergyCardListFromHand jp nc, .no_carry @@ -3163,7 +3163,7 @@ AIPlayPokemonCenter: ; 210e0 (8:50e0) ret ; 0x210eb -CheckIfCanPlayPokemonCenter: ; 210eb (8:50eb) +AIDecidePokemonCenter: ; 210eb (8:50eb) xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -3266,7 +3266,7 @@ AIPlayImposterProfessorOak: ; 21170 (8:5170) ; sets carry depending on player's number of cards ; in deck in in hand. -CheckWhetherToPlayImposterProfessorOak: ; 2117b (8:517b) +AIDecideImposterProfessorOak: ; 2117b (8:517b) ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetNonTurnDuelistVariable cp DECK_SIZE - 14 @@ -3305,7 +3305,7 @@ AIPlayEnergySearch: ; 2119a (8:519a) ; 0x211aa ; AI checks for playing Energy Search -CheckIfEnergySearchCanBePlayed: ; 211aa (8:51aa) +AIDecideEnergySearch: ; 211aa (8:51aa) farcall CreateEnergyCardListFromHand jr c, .start call .CheckForUsefulEnergyCards @@ -3562,7 +3562,7 @@ AIPlayPokedex: ; 212b4 (8:52b4) ret ; 0x212dc -CheckWhetherToPlayPokedex: ; 212dc (8:52dc) +AIDecidePokedex: ; 212dc (8:52dc) ld a, [wcda6] cp $06 jr c, .no_carry @@ -3865,7 +3865,7 @@ AIPlayFullHeal: ; 2141d (8:541d) ret ; 0x21428 -CheckWhetherToPlayFullHeal: ; 21428 (8:5428) +AIDecideFullHeal: ; 21428 (8:5428) ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable @@ -3909,7 +3909,7 @@ CheckWhetherToPlayFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_prz - call CheckWhetherToPlayScoopUp + call AIDecideScoopUp jr c, .no_carry .no_scoop_up_prz @@ -3936,7 +3936,7 @@ CheckWhetherToPlayFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_cnf - call CheckWhetherToPlayScoopUp + call AIDecideScoopUp jr c, .no_carry .no_scoop_up_cnf @@ -3963,7 +3963,7 @@ AIPlayMrFuji: ; 21497 (8:5497) ; 0x214a7 ; AI logic for playing Mr Fuji -CheckWhetherToPlayMrFuji: ; 214a7 (8:54a7) +AIDecideMrFuji: ; 214a7 (8:54a7) ld a, $ff ld [wce06], a ld [wce08], a @@ -4038,7 +4038,7 @@ AIPlayScoopUp: ; 214f1 (8:54f1) ret ; 0x21506 -CheckWhetherToPlayScoopUp: ; 21506 (8:5506) +AIDecideScoopUp: ; 21506 (8:5506) xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -4252,7 +4252,7 @@ AIPlayMaintenance: ; 2160f (8:560f) ; 0x2162c ; AI logic for playing Maintenance -CheckWhetherToPlayMaintencance: ; 2162c (8:562c) +AIDecideMaintenance: ; 2162c (8:562c) ; Imakuni? has his own thing ld a, [wOpponentDeckID] cp IMAKUNI_DECK_ID @@ -4357,7 +4357,7 @@ AIPlayRecycle: ; 2169a (8:569a) ; has priorities for Ghost Deck, and a "default" priority list ; (which is the Fire Charge deck, since it's the only other ; deck that runs a Recycle card in it.) -CheckWhetherToPlayRecycle: ; 216b8 (8:56b8) +AIDecideRecycle: ; 216b8 (8:56b8) ; no use checking if no cards in Discard Pile call CreateDiscardPileCardList jr c, .no_carry @@ -4487,7 +4487,7 @@ AIPlayLass: ; 21755 (8:5755) ret ; 0x21768 -CheckWhetherToPlayLass: ; 21768 (8:5768) +AIDecideLass: ; 21768 (8:5768) ; skip if player has less than 7 cards in hand ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND call GetNonTurnDuelistVariable @@ -4539,7 +4539,7 @@ AIPlayItemFinder: ; 2178f (8:578f) ; if so, find duplicate cards in hand to discard ; that are not Mr Mime and Pokemon Trader cards. ; this logic is suitable only for Strange Psyshock deck. -CheckWhetherToPlayItemFinder: ; 217b1 (8:57b1) +AIDecideItemFinder: ; 217b1 (8:57b1) ; skip if no Discard Pile. call CreateDiscardPileCardList jr c, .no_carry @@ -4620,7 +4620,7 @@ AIPlayImakuni: ; 21813 (8:5813) ; 0x2181e ; only sets carry if Active card is not confused. -CheckWhetherToPlayImakuni: ; 2181e (8:581e) +AIDecideImakuni: ; 2181e (8:581e) ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable and CNF_SLP_PRZ @@ -4674,7 +4674,7 @@ AIPlayGambler: ; 2182d (8:582d) ; checks whether to play Gambler. ; aside from Imakuni, all other opponents only ; play if there's less than 4 cards in the deck. -CheckWhetherToPlayGambler: ; 21875 (8:5875) +AIDecideGambler: ; 21875 (8:5875) ; Imakuni? has his own routine ld a, [wOpponentDeckID] cp IMAKUNI_DECK_ID @@ -4716,7 +4716,7 @@ AIPlayRevive: ; 21899 (8:5899) ; checks certain cards in Discard Pile to use Revive on. ; suitable for Muscle For Brains deck only. -CheckWhetherToPlayRevive: ; 218a9 (8:58a9) +AIDecideRevive: ; 218a9 (8:58a9) ; skip if no cards in Discard Pile call CreateDiscardPileCardList jr c, .no_carry @@ -4772,7 +4772,7 @@ AIPlayPokemonFlute: ; 218d8 (8:58d8) ret ; 0x218e8 -CheckWhetherToPlayPokemonFlute: ; 218e8 (8:58e8) +AIDecidePokemonFlute: ; 218e8 (8:58e8) ; if player has no Discard Pile, skip. call SwapTurn call CreateDiscardPileCardList @@ -4878,7 +4878,7 @@ AIPlayClefairyDollOrMysteriousFossil: ; 21977 (8:5977) ; 0x21982 ; AI logic for playing Clefairy Doll -CheckWhetherToPlayClefairyDollOrMysteriousFossil: ; 21982 (8:5982) +AIDecideClefairyDollOrMysteriousFossil: ; 21982 (8:5982) ; if has max number of Play Area Pokemon, skip ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable @@ -4928,7 +4928,7 @@ AIPlayPokeball: ; 219a6 (8:59a6) ret ; 0x219c6 -CheckWhetherToPlayPokeball: ; 219c6 (8:59c6) +AIDecidePokeball: ; 219c6 (8:59c6) ; go to the routines associated with deck ID ld a, [wOpponentDeckID] cp FIRE_CHARGE_DECK_ID -- cgit v1.2.3 From a20bbd2a93e4b20a5d77de6db43b0c7a27d4f5f3 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Sat, 18 Apr 2020 10:43:01 +0100 Subject: AI related constants and wram --- src/constants/card_data_constants.asm | 8 +- src/constants/duel_constants.asm | 7 + src/engine/bank05.asm | 46 ++--- src/engine/bank08.asm | 343 +++++++++++++++++++--------------- src/engine/home.asm | 2 +- src/macros/wram.asm | 2 +- src/text/text1.asm | 2 +- src/text/text_offsets.asm | 2 +- src/wram.asm | 15 +- 9 files changed, 240 insertions(+), 187 deletions(-) (limited to 'src') diff --git a/src/constants/card_data_constants.asm b/src/constants/card_data_constants.asm index 9d4c88f..e404b89 100644 --- a/src/constants/card_data_constants.asm +++ b/src/constants/card_data_constants.asm @@ -41,7 +41,7 @@ CARD_DATA_MOVE1_EFFECT_COMMANDS EQU $18 CARD_DATA_MOVE1_FLAG1 EQU $1a CARD_DATA_MOVE1_FLAG2 EQU $1b CARD_DATA_MOVE1_FLAG3 EQU $1c -CARD_DATA_MOVE1_UNKNOWN1 EQU $1d +CARD_DATA_MOVE1_EFFECT_PARAM EQU $1d CARD_DATA_MOVE1_ANIMATION EQU $1e ; TYPE_PKMN card only @@ -55,7 +55,7 @@ CARD_DATA_MOVE2_EFFECT_COMMANDS EQU $2b CARD_DATA_MOVE2_FLAG1 EQU $2d CARD_DATA_MOVE2_FLAG2 EQU $2e CARD_DATA_MOVE2_FLAG3 EQU $2f -CARD_DATA_MOVE2_UNKNOWN1 EQU $30 +CARD_DATA_MOVE2_EFFECT_PARAM EQU $30 CARD_DATA_MOVE2_ANIMATION EQU $31 ; TYPE_PKMN card only @@ -226,3 +226,7 @@ FLAG_3_BIT_1 EQU $1 << FLAG_3_BIT_1_F ; special CARD_DATA_RETREAT_COST values UNABLE_RETREAT EQU $64 + +; attack number constants +FIRST_ATTACK_OR_PKMN_POWER EQU $0 +SECOND_ATTACK EQU $1 diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index f3e2912..b1063dc 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -224,3 +224,10 @@ 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 diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index e6d80c3..f80aca9 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -116,10 +116,10 @@ CheckIfMoveKnocksOutDefendingCard: ; 140b5 (5:40b5) ; to exactly 0 HP. ; outputs that attack index in wSelectedMove. CheckIfAnyDefendingPokemonAttackDealsSameDamageAsHP: ; 140c5 (5:40c5) - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER call .check_damage ret c - ld a, $01 ; second attack + ld a, SECOND_ATTACK .check_damage call EstimateDamage_FromDefendingPokemon @@ -1223,8 +1223,8 @@ Func_1468b: ; 1468b (5:468b) call Func_14663 ld a, $f call Func_14663 - ld a, [wce20] - and $4 + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PROFESSOR_OAK jr z, .asm_14776 ld a, $1 call Func_14663 @@ -1462,7 +1462,7 @@ Func_15649: ; 15649 (5:5649) inc a ld [wcda6], a xor a - ld [wce20], a + ld [wPreviousAIFlags], a ld [wcddb], a ld [wcddc], a ld [wce03], a @@ -4374,7 +4374,7 @@ DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) jp .check_evolution .attached_energy_boost - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] cp $02 jr z, .check_surplus_energy call AddToAIScore @@ -4782,7 +4782,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) jr nz, .check_deck .second_attack - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a call CheckEnergyNeededForAttack jr nc, .check_discard_or_energy_boost @@ -4802,7 +4802,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) ; for both attacks, check if it has the effect of ; discarding energy cards or attached energy boost. - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a call CheckEnergyNeededForAttack ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F @@ -4812,7 +4812,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) call CheckLoadedMoveFlag jr c, .energy_boost_or_discard_energy - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a call CheckEnergyNeededForAttack ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F @@ -5058,8 +5058,8 @@ Func_169f8: ; 169f8 (5:69f8) xor a ld [wcdd9], a .asm_169fc - ld a, [wce20] - and $01 + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_PLUSPOWER jr z, .asm_16a0b ld a, [wcdd6] ld [wSelectedMoveIndex], a @@ -5071,11 +5071,11 @@ Func_169f8: ; 169f8 (5:69f8) jp z, .asm_16a77 ; determine AI score of both attacks. - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER call GetAIScoreOfAttack ld a, [wAIScore] ld [wPlayAreaAIScore], a - ld a, $01 ; second attack + ld a, SECOND_ATTACK call GetAIScoreOfAttack ld c, $01 ld a, [wPlayAreaAIScore] @@ -5263,7 +5263,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) .is_recoil ; sub from AI score number of damage counters ; that move deals to itself. - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] or a jp z, .check_defending_can_ko ld [wDamage], a @@ -5513,14 +5513,14 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) jr nc, .asm_16ca6 ld a, 1 call SubFromAIScore - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] call SubFromAIScore .asm_16ca6 ld a, MOVE_FLAG2_ADDRESS | FLAG_2_BIT_6_F call CheckLoadedMoveFlag jr nc, .check_nullify_flag - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] call AddToAIScore ; encourage move if it has a nullify or weaken attack effect. @@ -5543,13 +5543,13 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ld a, MOVE_FLAG2_ADDRESS | HEAL_USER_F call CheckLoadedMoveFlag jr nc, .check_status_effect - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] cp 1 jr z, .tally_heal_score ld a, [wTempAI] call CalculateByteTensDigit ld b, a - ld a, [wLoadedMoveUnknown1] + ld a, [wLoadedMoveEffectParam] cp 3 jr z, .asm_16cec srl b @@ -5568,7 +5568,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) call GetCardDamage call CalculateByteTensDigit pop bc - cp b ; wLoadedMoveUnknown1 + cp b ; wLoadedMoveEffectParam jr c, .add_heal_score ld a, b .add_heal_score @@ -6690,8 +6690,12 @@ CheckIfNotABossDeckID: ; 17426 (5:7426) ; probability to return carry: ; - 50% if deck AI is playing is on the list; -; - 25% for all other decks. -Func_1743b: ; 1743b (5:743b) +; - 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) +; boss decks always use Trainer cards. push hl push de call CheckIfNotABossDeckID diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index af95853..ee7b2d6 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -57,7 +57,7 @@ Func_200e5: ; 200e5 (8:40e5) .loop_hand ld a, [hli] - ld [wce16], a + ld [wAITrainerCardToPlay], a cp $ff ret z @@ -67,7 +67,7 @@ Func_200e5: ; 200e5 (8:40e5) ld hl, Data_20000 .loop_data xor a - ld [wce21], a + ld [wCurrentAIFlags], a ld a, [hli] cp $ff jp z, .pop_hl @@ -75,16 +75,18 @@ Func_200e5: ; 200e5 (8:40e5) ; compare input to first byte in data and continue if equal. cp d jp nz, .inc_hl_by_5 + ld a, [hli] ld [wce17], a - ld a, [wce16] + ld a, [wAITrainerCardToPlay] call LoadCardDataToBuffer1_FromDeckIndex + cp SWITCH jr nz, .skip_switch_check ld b, a - ld a, [wce20] - and $02 + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_SWITCH jr nz, .inc_hl_by_4 ld a, b @@ -95,61 +97,79 @@ Func_200e5: ; 200e5 (8:40e5) cp b jr nz, .inc_hl_by_4 +; found Trainer card push hl push de - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a + +; if Headache effects prevent playing card +; move on to the next ite, in list. bank1call CheckCantUseTrainerDueToHeadache jp c, .next_in_data + call LoadNonPokemonCardEffectCommands ld a, EFFECTCMDTYPE_INITIAL_EFFECT_1 call TryExecuteEffectCommandFunction jp c, .next_in_data - farcall Func_1743b + +; AI can randomly choose not to play card. + farcall ChooseRandomlyNotToPlayTrainerCard jr c, .next_in_data + +; call routine to decide whether to play Trainer card pop de pop hl push hl call CallIndirect pop hl jr nc, .inc_hl_by_4 + +; routine returned carry, which means +; this card should be played. inc hl inc hl - ld [wce19], a + ld [wAITrainerCardParameter], a +; show Play Trainer Card screen push de push hl - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_PLAY_TRAINER bank1call AIMakeDecision pop hl pop de jr c, .inc_hl_by_2 + +; execute the effects of the Trainer card push hl call CallIndirect pop hl inc hl inc hl - ld a, [wce20] + ld a, [wPreviousAIFlags] ld b, a - ld a, [wce21] + ld a, [wCurrentAIFlags] or b - ld [wce20], a + ld [wPreviousAIFlags], a pop hl - and $08 + and AI_FLAG_MODIFIED_HAND jp z, .loop_hand -.asm_20186 ; 20186 (8:4186) +; the hand was modified during the Trainer effect +; so it needs to be re-listed again and +; looped from the top. call CreateHandCardList ld hl, wDuelTempList ld de, wTempHandCardList call CopyBuffer ld hl, wTempHandCardList - ld a, [wce20] - and $f7 - ld [wce20], a +; clear the AI_FLAG_MODIFIED_HAND flag + ld a, [wPreviousAIFlags] + and ~AI_FLAG_MODIFIED_HAND + ld [wPreviousAIFlags], a jp .loop_hand .inc_hl_by_5 @@ -178,9 +198,9 @@ Func_200e5: ; 200e5 (8:40e5) ; makes AI use Potion card. AIPlayPotion: ; 201b5 (8:41b5) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld e, a call GetCardDamage @@ -342,7 +362,7 @@ AIDecidePotion2: ; 20204 (8:4204) ; and have the BOOST_IF_TAKEN_DAMAGE effect. .check_boost_if_taken_damage ; 2027e (8:427e) push de - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a farcall CheckIfSelectedMoveIsUnusable jr c, .second_attack @@ -350,7 +370,7 @@ AIDecidePotion2: ; 20204 (8:4204) call CheckLoadedMoveFlag jr c, .set_carry .second_attack - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a farcall CheckIfSelectedMoveIsUnusable jr c, .false @@ -369,13 +389,13 @@ AIDecidePotion2: ; 20204 (8:4204) ; makes AI use Super Potion card. AIPlaySuperPotion: ; 202a8 (8:42a8) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTempPlayAreaLocation_ffa1], a call GetEnergyCardToDiscard ldh [hTemp_ffa0], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ld e, a call GetCardDamage cp 40 @@ -411,7 +431,7 @@ AIDecideSuperPotion1: ; 202cc (8:42cc) ld a, DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable ld h, a - ld e, $00 + ld e, PLAY_AREA_ARENA call GetCardDamage cp 40 + 1 ; if damage < 40 jr c, .calculate_hp @@ -457,7 +477,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) ld a, DUELVARS_ARENA_CARD_HP call GetTurnDuelistVariable ld h, a - ld e, $00 + ld e, PLAY_AREA_ARENA call GetCardDamage cp 40 + 1 ; if damage < 40 jr c, .calculate_hp @@ -564,7 +584,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) ; and have the BOOST_IF_TAKEN_DAMAGE effect. .check_boost_if_taken_damage ; 2039e (8:439e) push de - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a farcall CheckIfSelectedMoveIsUnusable jr c, .second_attack_1 @@ -572,7 +592,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) call CheckLoadedMoveFlag jr c, .true_1 .second_attack_1 - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a farcall CheckIfSelectedMoveIsUnusable jr c, .false_1 @@ -593,7 +613,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) ; given that they have enough energy to be used before discarding. .check_energy_cost ; 203c8 (8:43c8) push de - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -605,7 +625,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) .second_attack_2 pop de push de - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -625,7 +645,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) ; 0x203f8 AIPlayDefender: ; 203f8 (8:43f8) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a xor a ldh [hTemp_ffa0], a @@ -638,7 +658,7 @@ AIPlayDefender: ; 203f8 (8:43f8) ; by the defending Pokémon. ; this takes into account both attacks and whether they're useable. AIDecideDefender1: ; 20406 (8:4406) - xor a + xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfAnyMoveKnocksOutDefendingCard jr nc, .cannot_ko @@ -740,10 +760,10 @@ AIDecideDefender2: ; 20486 (8:4486) or a jr nz, .second_attack ; first attack - ld a, [wLoadedCard2Move1Unknown1] + ld a, [wLoadedCard2Move1EffectParam] jr .check_weak .second_attack - ld a, [wLoadedCard2Move2Unknown1] + ld a, [wLoadedCard2Move2EffectParam] ; double recoil damage if card is weak to its own color. .check_weak @@ -796,12 +816,12 @@ AIDecideDefender2: ; 20486 (8:4486) ; 0x204e8 AIPlayPluspower: ; 204e8 (8:44e8) - ld a, [wce21] - or $01 - ld [wce21], a - ld a, [wce19] + ld a, [wCurrentAIFlags] + or AI_FLAG_USED_PLUSPOWER + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardParameter] ld [wcdd6], a - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -853,11 +873,11 @@ AIDecidePluspower1: ; 20501 (8:4501) ; check both attacks and decide which one ; can KO with Pluspower boost. ; if neither can KO, return no carry. - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a call .check_ko_with_pluspower jr c, .kos_with_pluspower_1 - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a call .check_ko_with_pluspower jr c, .kos_with_pluspower_2 @@ -870,14 +890,14 @@ AIDecidePluspower1: ; 20501 (8:4501) .kos_with_pluspower_1 call .check_mr_mime jr nc, .no_carry - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER scf ret ; second attack can KO with Pluspower. .kos_with_pluspower_2 call .check_mr_mime jr nc, .no_carry - ld a, $01 ; second attack + ld a, SECOND_ATTACK scf ret ; 0x20562 @@ -1008,12 +1028,12 @@ AIDecidePluspower2: ; 205a5 (8:45a5) ; 0x20612 AIPlaySwitch: ; 20612 (8:4612) - ld a, [wce21] - or $02 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_USED_SWITCH + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -1073,12 +1093,12 @@ AIDecideSwitch: ; 2062e (8:462e) ; 0x20666 AIPlayGustOfWind: ; 20666 (8:4666) - ld a, [wce21] - or $10 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_USED_GUST_OF_WIND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -1091,9 +1111,13 @@ AIDecideGustOfWind: ; 2067e (8:467e) dec a or a ret z ; no bench cards - ld a, [wce20] - and $10 + +; if used Gust Of Wind already, +; do not use it again. + ld a, [wPreviousAIFlags] + and AI_FLAG_USED_GUST_OF_WIND ret nz + farcall CheckIfActivePokemonCanUseAnyNonResidualMove ret nc ; no non-residual move can be used @@ -1252,13 +1276,13 @@ AIDecideGustOfWind: ; 2067e (8:467e) ; returns carry if neither attack can deal damage .CheckIfNoAttackDealsDamage ; 2076b (8:476b) - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a call .CheckIfAttackDealsNoDamage jr c, .second_attack ret .second_attack - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a call .CheckIfAttackDealsNoDamage jr c, .true @@ -1370,10 +1394,10 @@ AIDecideGustOfWind: ; 2067e (8:467e) ; returns carry if any of arena card's attacks ; KOs player card in location stored in e .CheckIfAnyAttackKnocksOut ; 20806 (8:4806) - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER call .CheckIfAttackKnocksOut ret c - ld a, $01 ; second attack + ld a, SECOND_ATTACK ; returns carry if attack KOs player card ; in location stored in e @@ -1458,7 +1482,7 @@ AIDecideGustOfWind: ; 2067e (8:467e) ; 0x2086d AIPlayBill: ; 2086d (8:486d) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -1474,9 +1498,9 @@ AIDecideBill: ; 20878 (8:4878) ; 0x20880 AIPlayEnergyRemoval: ; 20880 (8:4880) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a @@ -1601,7 +1625,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) ; have enough energy for either of its attacks .CheckIfNotEnoughEnergyToAttack ; 20924 (8:4924) push de - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -1610,7 +1634,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) pop de push de - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -1644,7 +1668,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) ld a, e ldh [hTempPlayAreaLocation_ff9d], a - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] or a @@ -1668,7 +1692,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) ld a, e ldh [hTempPlayAreaLocation_ff9d], a - ld a, $01 ; second attack + ld a, SECOND_ATTACK farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] or a @@ -1689,9 +1713,9 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) ; 0x20994 AIPlaySuperEnergyRemoval: ; 20994 (8:4994) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a @@ -1886,7 +1910,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ; have enough energy for either of its attacks .CheckIfNotEnoughEnergyToAttack ; 20a92 (8:4a92) push de - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -1895,7 +1919,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) pop de push de - ld a, $01 ; second attack + ld a, SECOND_ATTACK ld [wSelectedMoveIndex], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a @@ -1933,7 +1957,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ld a, e ldh [hTempPlayAreaLocation_ff9d], a - xor a ; first attack + xor a ; FIRST_ATTACK_OR_PKMN_POWER farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] or a @@ -1957,7 +1981,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ld a, e ldh [hTempPlayAreaLocation_ff9d], a - ld a, $01 ; second attack + ld a, SECOND_ATTACK farcall EstimateDamage_VersusDefendingCard ld a, [wDamage] or a @@ -1978,9 +2002,9 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ; 0x20b06 AIPlayPokemonBreeder: ; 20b06 (8:4b06) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTempPlayAreaLocation_ffa1], a ld a, [wce1a] ldh [hTemp_ffa0], a @@ -2334,10 +2358,10 @@ AIDecidePokemonBreeder: ; 20b1b (8:4b1b) ; 0x20cae AIPlayProfessorOak: ; 20cae (8:4cae) - ld a, [wce21] - or $0c - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_USED_PROFESSOR_OAK | AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -2665,12 +2689,12 @@ AIDecideProfessorOak: ; 20cc1 (8:4cc1) ; 0x20e44 AIPlayEnergyRetrieval: ; 20e44 (8:4e44) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a @@ -2924,12 +2948,12 @@ FindDuplicateCards: ; 20f38 (8:4f38) ; 0x20f80 AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a @@ -3156,7 +3180,7 @@ FindAndRemoveCardFromList: ; 210d5 (8:50d5) ; 0x210e0 AIPlayPokemonCenter: ; 210e0 (8:50e0) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -3257,7 +3281,7 @@ AIDecidePokemonCenter: ; 210eb (8:50eb) ; 0x21170 AIPlayImposterProfessorOak: ; 21170 (8:5170) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -3295,9 +3319,9 @@ AIDecideImposterProfessorOak: ; 2117b (8:517b) ; 0x2119a AIPlayEnergySearch: ; 2119a (8:519a) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -3543,7 +3567,7 @@ AIDecideEnergySearch: ; 211aa (8:51aa) ; 0x212b4 AIPlayPokedex: ; 212b4 (8:52b4) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wce1a] ldh [hTemp_ffa0], a @@ -3858,7 +3882,7 @@ PickPokedexCards: ; 2138e (8:538e) ; 0x2141d AIPlayFullHeal: ; 2141d (8:541d) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -3953,9 +3977,9 @@ AIDecideFullHeal: ; 21428 (8:5428) ; 0x21497 AIPlayMrFuji: ; 21497 (8:5497) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4027,9 +4051,9 @@ AIDecideMrFuji: ; 214a7 (8:54a7) ; 0x214f1 AIPlayScoopUp: ; 214f1 (8:54f1) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a @@ -4237,10 +4261,10 @@ AIDecideScoopUp: ; 21506 (8:5506) ; 0x2160f AIPlayMaintenance: ; 2160f (8:560f) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wce1a] ldh [hTemp_ffa0], a @@ -4265,10 +4289,10 @@ AIDecideMaintenance: ; 2162c (8:562c) jr c, .no_carry ; list out all the hand cards and remove -; the card in wce16. Then find any duplicate cards. +; wAITrainerCardToPlay from list.Then find any duplicate cards. call CreateHandCardList ld hl, wDuelTempList - ld a, [wce16] + ld a, [wAITrainerCardToPlay] call FindAndRemoveCardFromList ; if duplicates are not found, return no carry. call FindDuplicateCards @@ -4312,9 +4336,9 @@ AIDecideMaintenance: ; 2162c (8:562c) call ShuffleCards ; go through each card and find -; cards that are different from wce16. +; cards that are different from wAITrainerCardToPlay. ; if found, add those cards to wce1a and wce1a+1. - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ld b, a ld c, 2 ld de, wce1a @@ -4336,12 +4360,12 @@ AIDecideMaintenance: ; 2162c (8:562c) ; 0x2169a AIPlayRecycle: ; 2169a (8:569a) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld de, $ef + ldtx de, TrainerCardSuccessCheckText bank1call TossCoin jr nc, .asm_216ae - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a jr .asm_216b2 .asm_216ae @@ -4477,10 +4501,10 @@ AIDecideRecycle: ; 216b8 (8:56b8) ; 0x21755 AIPlayLass: ; 21755 (8:5755) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4519,16 +4543,16 @@ AIDecideLass: ; 21768 (8:5768) ; 0x2178f AIPlayItemFinder: ; 2178f (8:578f) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wce1a] ldh [hTemp_ffa0], a ld a, [wce1b] ldh [hTempPlayAreaLocation_ffa1], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTempRetreatCostCards], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4566,7 +4590,7 @@ AIDecideItemFinder: ; 217b1 (8:57b1) .loop_hand ld a, [hli] cp $ff - jr z, .asm_217eb + jr z, .choose_discard ld b, a call LoadCardDataToBuffer1_FromDeckIndex cp MR_MIME @@ -4580,11 +4604,11 @@ AIDecideItemFinder: ; 217b1 (8:57b1) jr .loop_hand ; choose cards to discard from hand. -.asm_217eb +.choose_discard ld hl, wDuelTempList -; do not discard card in wce16 - ld a, [wce16] +; do not discard wAITrainerCardToPlay + ld a, [wAITrainerCardToPlay] call FindAndRemoveCardFromList ; find any duplicates, if not found, return no carry. call FindDuplicateCards @@ -4612,7 +4636,7 @@ AIDecideItemFinder: ; 217b1 (8:57b1) ; 0x21813 AIPlayImakuni: ; 21813 (8:5813) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4634,9 +4658,9 @@ AIDecideImakuni: ; 2181e (8:581e) ; 0x2182d AIPlayGambler: ; 2182d (8:582d) - ld a, [wce21] - or $08 - ld [wce21], a + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a ld a, [wOpponentDeckID] cp IMAKUNI_DECK_ID jr z, .asm_2186a @@ -4651,7 +4675,7 @@ AIPlayGambler: ; 2182d (8:582d) ld [hld], a ld [hld], a ld [hl], a - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4664,7 +4688,7 @@ AIPlayGambler: ; 2182d (8:582d) ld [hl], a ret .asm_2186a - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision @@ -4705,11 +4729,11 @@ AIDecideGambler: ; 21875 (8:5875) ; 0x21899 AIPlayRevive: ; 21899 (8:5899) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x218a9 @@ -4763,11 +4787,11 @@ AIDecideRevive: ; 218a9 (8:58a9) ; 0x218d8 AIPlayPokemonFlute: ; 218d8 (8:58d8) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x218e8 @@ -4870,9 +4894,9 @@ AIDecidePokemonFlute: ; 218e8 (8:58e8) ; 0x21977 AIPlayClefairyDollOrMysteriousFossil: ; 21977 (8:5977) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x21982 @@ -4910,20 +4934,20 @@ AIDecideClefairyDollOrMysteriousFossil: ; 21982 (8:5982) ; 0x219a6 AIPlayPokeball: ; 219a6 (8:59a6) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld de, $ef + ldtx de, TrainerCardSuccessCheckText bank1call TossCoin ldh [hTemp_ffa0], a jr nc, .asm_219bc - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTempPlayAreaLocation_ffa1], a jr .asm_219c0 .asm_219bc ld a, $ff ldh [hTempPlayAreaLocation_ffa1], a .asm_219c0 - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x219c6 @@ -5131,18 +5155,18 @@ AIDecidePokeball: ; 219c6 (8:59c6) ; 0x21b12 AIPlayComputerSearch: ; 21b12 (8:5b12) - ld a, [wce21] - or $08 - ld [wce21], a - ld a, [wce16] + ld a, [wCurrentAIFlags] + or AI_FLAG_MODIFIED_HAND + ld [wCurrentAIFlags], a + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTempRetreatCostCards], a ld a, [wce1a] ldh [hTemp_ffa0], a ld a, [wce1b] ldh [hTempPlayAreaLocation_ffa1], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x21b34 @@ -5222,8 +5246,8 @@ AIDecideComputerSearch_RockCrusher: ; 21b55 (8:5b55) cp RHYHORN jr z, .no_carry -; if it's same as card in wce16, skip this card. - ld a, [wce16] +; if it's same as wAITrainerCardToPlay, skip this card. + ld a, [wAITrainerCardToPlay] ld b, a ld a, c cp b @@ -5315,7 +5339,10 @@ AIDecideComputerSearch_RockCrusher: ; 21b55 (8:5b55) ld bc, wce1a ld d, $00 ; start considering Trainer cards only - ld a, [wce16] + +; stores wAITrainerCardToPlay in e so that +; all routines ignore it for the discard effects. + ld a, [wAITrainerCardToPlay] ld e, a ; this loop will store in wce1a cards to discard from hand. @@ -5404,7 +5431,9 @@ AIDecideComputerSearch_WondersOfScience: ; 21c56 (8:5c56) call CreateHandCardList ld hl, wDuelTempList ld d, $00 ; first consider Trainer cards - ld a, [wce16] + +; ignore wAITrainerCardToPlay for the discard effects. + ld a, [wAITrainerCardToPlay] ld e, a call RemoveFromListDifferentCardOfGivenType jr nc, .no_carry @@ -5467,7 +5496,9 @@ AIDecideComputerSearch_FireCharge: ; 21cbb (8:5cbb) call CreateHandCardList ld hl, wDuelTempList ld d, $00 ; first consider Trainer cards - ld a, [wce16] + +; ignore wAITrainerCardToPlay for the discard effects. + ld a, [wAITrainerCardToPlay] ld e, a call RemoveFromListDifferentCardOfGivenType jr nc, .no_carry @@ -5526,7 +5557,9 @@ AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) call CreateHandCardList ld hl, wDuelTempList ld d, $00 ; first consider Trainer cards - ld a, [wce16] + +; ignore wAITrainerCardToPlay for the discard effects. + ld a, [wAITrainerCardToPlay] ld e, a call RemoveFromListDifferentCardOfGivenType jr nc, .no_carry @@ -5540,13 +5573,13 @@ AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) ; 0x21d7a AIPlayPokemonTrader: ; 21d7a (8:5d7a) - ld a, [wce16] + ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a - ld a, [wce19] + ld a, [wAITrainerCardParameter] ldh [hTemp_ffa0], a ld a, [wce1a] ldh [hTempPlayAreaLocation_ffa1], a - ld a, $07 + ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS bank1call AIMakeDecision ret ; 0x21d8f diff --git a/src/engine/home.asm b/src/engine/home.asm index b7374aa..9584db2 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -5259,7 +5259,7 @@ MoveCardToDiscardPileIfInArena: ; 1c13 (0:1c13) ret ; 0x1c35 -; calculate damage of card at CARD_LOCATION_PLAY_AREA + e +; calculate damage of card at CARD_LOCATION_* in e ; return the result in a GetCardDamage: ; 1c35 (0:1c35) push hl diff --git a/src/macros/wram.asm b/src/macros/wram.asm index ca8a9d0..ef7d8b2 100644 --- a/src/macros/wram.asm +++ b/src/macros/wram.asm @@ -35,7 +35,7 @@ move_data_struct: MACRO \1Flag1:: ds 1 \1Flag2:: ds 1 \1Flag3:: ds 1 -\1Unknown1:: ds 1 +\1EffectParam:: ds 1 \1Animation:: ds 1 ENDM diff --git a/src/text/text1.asm b/src/text/text1.asm index 075a9ef..f64553a 100644 --- a/src/text/text1.asm +++ b/src/text/text1.asm @@ -1123,7 +1123,7 @@ Text00ee: ; 37eb8 (d:7eb8) line "If Heads, Attack is successful!" done -Text00ef: ; 37eea (d:7eea) +TrainerCardSuccessCheckText: ; 37eea (d:7eea) text "Trainer card success check!" line "If Heads, you're successful!" done diff --git a/src/text/text_offsets.asm b/src/text/text_offsets.asm index 56f1f41..a415e93 100644 --- a/src/text/text_offsets.asm +++ b/src/text/text_offsets.asm @@ -240,7 +240,7 @@ TextOffsets:: ; 34000 (d:4000) textpointer Text00ec ; 0x00ec textpointer Text00ed ; 0x00ed textpointer Text00ee ; 0x00ee - textpointer Text00ef ; 0x00ef + textpointer TrainerCardSuccessCheckText ; 0x00ef textpointer Text00f0 ; 0x00f0 textpointer IfHeadsNoDamageNextTurnText ; 0x00f1 textpointer Text00f2 ; 0x00f2 diff --git a/src/wram.asm b/src/wram.asm index c0ff24e..dae9a17 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1365,7 +1365,9 @@ wce08:: ; ce08 wce0f:: ; ce0f ds $7 -wce16:: ; ce16 +; stores the deck index (0-59) of the Trainer card +; the AI intends to play from hand. +wAITrainerCardToPlay:: ; ce16 ds $1 wce17:: ; ce17 @@ -1374,7 +1376,9 @@ wce17:: ; ce17 wce18:: ; ce18 ds $1 -wce19:: ; ce19 +; paramaters output by AI Trainer card logic routines +; (e.g. what Pokemon in Play Area to use card on, etc) +wAITrainerCardParameter:: ; ce19 ds $1 wce1a:: ; ce1a @@ -1395,10 +1399,11 @@ wce1e:: ; ce1e wce1f:: ; ce1f ds $1 -wce20:: ; ce20 +; used to store previous/current flags of AI actions +; see AI_FLAG_* constants +wPreviousAIFlags:: ; ce20 ds $1 - -wce21:: ; ce21 +wCurrentAIFlags:: ; ce21 ds $1 ; During a duel, this is always $b after the first attack. -- cgit v1.2.3 From 6960c4f3ac186349828e85616f1c189c20db9b9b Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Sat, 18 Apr 2020 18:32:24 +0100 Subject: Add corrections --- src/constants/card_data_constants.asm | 2 +- src/engine/bank01.asm | 10 +- src/engine/bank05.asm | 219 +++++++++++----------- src/engine/bank08.asm | 334 +++++++++++++++++----------------- src/engine/home.asm | 14 +- src/wram.asm | 10 +- 6 files changed, 304 insertions(+), 285 deletions(-) (limited to 'src') diff --git a/src/constants/card_data_constants.asm b/src/constants/card_data_constants.asm index e404b89..3f3dd3a 100644 --- a/src/constants/card_data_constants.asm +++ b/src/constants/card_data_constants.asm @@ -227,6 +227,6 @@ FLAG_3_BIT_1 EQU $1 << FLAG_3_BIT_1_F ; special CARD_DATA_RETREAT_COST values UNABLE_RETREAT EQU $64 -; attack number constants +; attack index constants FIRST_ATTACK_OR_PKMN_POWER EQU $0 SECOND_ATTACK EQU $1 diff --git a/src/engine/bank01.asm b/src/engine/bank01.asm index 5131025..b73b47c 100644 --- a/src/engine/bank01.asm +++ b/src/engine/bank01.asm @@ -3055,7 +3055,7 @@ PracticeDuelVerify_Turn2: ; 5438 (1:5438) ld a, [wTempCardID_ccc2] cp SEAKING jp nz, ReturnWrongAction - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] cp 1 jp nz, ReturnWrongAction ld e, PLAY_AREA_ARENA @@ -3090,7 +3090,7 @@ PracticeDuelVerify_Turn4: ; 5467 (1:5467) ld a, [wTempCardID_ccc2] cp SEAKING jr nz, ReturnWrongAction - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] cp 1 jr nz, ReturnWrongAction ret @@ -3127,7 +3127,7 @@ PracticeDuelVerify_Turn7Or8: ; 54b7 (1:54b7) ld a, [wTempCardID_ccc2] cp STARMIE jr nz, ReturnWrongAction - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] cp 1 jr nz, ReturnWrongAction ret @@ -6041,7 +6041,7 @@ DisplayOpponentUsedMoveScreen: ; 6635 (1:6635) ld a, CARDPAGE_POKEMON_OVERVIEW ld [wCardPageNumber], a ld hl, wLoadedCard1Move1Name - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] or a jr z, .first_move ld hl, wLoadedCard1Move2Name @@ -6886,7 +6886,7 @@ OppAction_6b3e: ; 6b3e (1:6b3e) call SwapTurn ldh a, [hTempCardIndex_ff9f] ld [wPlayerAttackingCardIndex], a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld [wPlayerAttackingMoveIndex], a ld a, [wTempCardID_ccc2] ld [wPlayerAttackingCardID], a diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index f80aca9..ec205ce 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -91,7 +91,7 @@ Func_1409e: ; 1409e (5:409e) ; input: ; [hTempPlayAreaLocation_ff9d] = location of attacking card to consider ; output: -; [wSelectedMoveIndex] = move index that KOs +; [wSelectedAttack] = move index that KOs CheckIfAnyMoveKnocksOutDefendingCard: ; 140ae (5:40ae) xor a ; first move call CheckIfMoveKnocksOutDefendingCard @@ -326,7 +326,7 @@ Func_14226: ; 14226 (5:4226) ; can't use a move or if that selected move doesn't have enough energy ; input: ; [hTempPlayAreaLocation_ff9d] = location of Pokémon card -; [wSelectedMoveIndex] = selected move to examine +; [wSelectedAttack] = selected move to examine CheckIfSelectedMoveIsUnusable: ; 1424b (5:424b) ldh a, [hTempPlayAreaLocation_ff9d] or a @@ -340,7 +340,7 @@ CheckIfSelectedMoveIsUnusable: ; 1424b (5:424b) ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a call CopyMoveDataAndDamage_FromDeckIndex call HandleAmnesiaSubstatus @@ -361,7 +361,7 @@ CheckIfSelectedMoveIsUnusable: ; 1424b (5:424b) ; and checks if there is enough energy to execute the selected move ; input: ; [hTempPlayAreaLocation_ff9d] = location of Pokémon card -; [wSelectedMoveIndex] = selected move to examine +; [wSelectedAttack] = selected move to examine ; output: ; b = basic energy still needed ; c = colorless energy still needed @@ -374,7 +374,7 @@ CheckEnergyNeededForAttack: ; 14279 (5:4279) add DUELVARS_ARENA_CARD call GetTurnDuelistVariable ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a call CopyMoveDataAndDamage_FromDeckIndex ld hl, wLoadedMoveName @@ -686,7 +686,7 @@ LookForCardIDInHand: ; 143bf (5:43bf) ; a = move index to take into account ; [hTempPlayAreaLocation_ff9d] = location of attacking card to consider EstimateDamage_VersusDefendingCard: ; 143e5 (5:43e5) - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld e, a ldh a, [hTempPlayAreaLocation_ff9d] add DUELVARS_ARENA_CARD @@ -903,7 +903,7 @@ _CalculateDamage_VersusDefendingPokemon: ; 14462 (5:4462) ; damage as the receiver EstimateDamage_FromDefendingPokemon: ; 1450b (5:450b) call SwapTurn - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld e, a ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable @@ -1135,8 +1135,8 @@ _CalculateDamage_FromDefendingPokemon: ; 1459b (5:459b) ret ; 0x14663 -Func_14663: ; 14663 (5:4663) - farcall Func_200e5 +AIProcessHandTrainerCards: ; 14663 (5:4663) + farcall _AIProcessHandTrainerCards ret ; GENERAL DECK POINTER LIST - Not sure on all of these. @@ -1175,7 +1175,7 @@ Func_14687: ; 14687 (5:4687) Func_1468b: ; 1468b (5:468b) call Func_15649 ld a, $1 - call Func_14663 + call AIProcessHandTrainerCards farcall $8, $67d3 jp nc, $4776 farcall $8, $6790 @@ -1184,28 +1184,28 @@ Func_1468b: ; 1468b (5:468b) ret c farcall $8, $662d ld a, $2 - call Func_14663 + call AIProcessHandTrainerCards ld a, $3 - call Func_14663 + call AIProcessHandTrainerCards ld a, $4 - call Func_14663 + call AIProcessHandTrainerCards call $5eae ret c ld a, $5 - call Func_14663 + call AIProcessHandTrainerCards ld a, $6 - call Func_14663 + call AIProcessHandTrainerCards ld a, $7 - call Func_14663 + call AIProcessHandTrainerCards ld a, $8 - call Func_14663 + call AIProcessHandTrainerCards call $4786 ld a, $a - call Func_14663 + call AIProcessHandTrainerCards ld a, $b - call Func_14663 + call AIProcessHandTrainerCards ld a, $c - call Func_14663 + call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a jr nz, .asm_146ed @@ -1220,37 +1220,37 @@ Func_1468b: ; 1468b (5:468b) ld a, $d farcall $8, $619b ld a, $d - call Func_14663 + call AIProcessHandTrainerCards ld a, $f - call Func_14663 + call AIProcessHandTrainerCards ld a, [wPreviousAIFlags] and AI_FLAG_USED_PROFESSOR_OAK jr z, .asm_14776 ld a, $1 - call Func_14663 + call AIProcessHandTrainerCards ld a, $2 - call Func_14663 + call AIProcessHandTrainerCards ld a, $3 - call Func_14663 + call AIProcessHandTrainerCards ld a, $4 - call Func_14663 + call AIProcessHandTrainerCards call $5eae ret c ld a, $5 - call Func_14663 + call AIProcessHandTrainerCards ld a, $6 - call Func_14663 + call AIProcessHandTrainerCards ld a, $7 - call Func_14663 + call AIProcessHandTrainerCards ld a, $8 - call Func_14663 + call AIProcessHandTrainerCards call $4786 ld a, $a - call Func_14663 + call AIProcessHandTrainerCards ld a, $b - call Func_14663 + call AIProcessHandTrainerCards ld a, $c - call Func_14663 + call AIProcessHandTrainerCards ld a, [wAlreadyPlayedEnergy] or a jr nz, .asm_1475b @@ -1265,7 +1265,7 @@ Func_1468b: ; 1468b (5:468b) ld a, $d farcall $8, $619b ld a, $d - call Func_14663 + call AIProcessHandTrainerCards .asm_14776 ld a, $e @@ -1530,7 +1530,7 @@ Func_15649: ; 15649 (5:5649) ; after removing that attached energy card. ; input: ; [hTempPlayAreaLocation_ff9d] = location of Pokémon card -; [wSelectedMoveIndex] = selected move to examine +; [wSelectedAttack] = selected move to examine ; output: ; b = basic energy still needed ; c = colorless energy still needed @@ -1543,7 +1543,7 @@ CheckEnergyNeededForAttackAfterDiscard: ; 156c3 (5:56c3) add DUELVARS_ARENA_CARD call GetTurnDuelistVariable ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a call CopyMoveDataAndDamage_FromDeckIndex ld hl, wLoadedMoveName @@ -2372,11 +2372,11 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; to raise AI score accordingly .check_can_use_moves xor a - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable call nc, .calculate_damage ld a, $01 - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable call nc, .calculate_damage jr .check_energy_card @@ -2385,7 +2385,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) ; it can inflict to the defending Pokémon ; AI score += floor(Damage / 10) + 1 .calculate_damage - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, [wDamage] call CalculateByteTensDigit @@ -2399,7 +2399,7 @@ AIDecideBenchPokemonToSwitchTo: ; 15b72 (5:5b72) .check_energy_card call LookForEnergyNeededInHand jr nc, .check_attached_energy - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, [wDamage] call CalculateByteTensDigit @@ -3037,11 +3037,11 @@ AIDecideEvolution: ; 15f4c (5:5f4c) ; check if the card can use any moves ; and if any of those moves can KO xor a - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr nc, .can_attack ld a, $01 - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .cant_attack_or_ko .can_attack @@ -3071,11 +3071,11 @@ AIDecideEvolution: ; 15f4c (5:5f4c) ld a, [wTempAIPokemonCard] ld [hl], a xor a - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr nc, .evolution_can_attack ld a, $01 - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .evolution_cant_attack .evolution_can_attack @@ -3555,7 +3555,7 @@ CheckIfActivePokemonCanUseAnyNonResidualMove: ; 162a1 (5:62a1) xor a ; active card ldh [hTempPlayAreaLocation_ff9d], a ; first move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .next_move ld a, [wLoadedMoveCategory] @@ -3565,7 +3565,7 @@ CheckIfActivePokemonCanUseAnyNonResidualMove: ; 162a1 (5:62a1) .next_move ; second move ld a, $01 - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .fail ld a, [wLoadedMoveCategory] @@ -3591,7 +3591,7 @@ CheckIfActivePokemonCanUseAnyNonResidualMove: ; 162a1 (5:62a1) ; [hTempPlayAreaLocation_ff9d] = location of Pokémon card LookForEnergyNeededInHand: ; 162c8 (5:62c8) xor a ; first move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack ld a, b add c @@ -3605,7 +3605,7 @@ LookForEnergyNeededInHand: ; 162c8 (5:62c8) .second_attack ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack ld a, b add c @@ -3651,7 +3651,7 @@ LookForEnergyNeededInHand: ; 162c8 (5:62c8) ; return carry if successful in finding card ; input: ; [hTempPlayAreaLocation_ff9d] = location of Pokémon card -; [wSelectedMoveIndex] = selected move to examine +; [wSelectedAttack] = selected move to examine LookForEnergyNeededForMoveInHand: ; 16311 (5:6311) call CheckEnergyNeededForAttack ld a, b @@ -4360,9 +4360,9 @@ AIDecideWhichCardToAttachEnergy: ; 164fc (5:64fc) ; in order to determine whether to play energy card. ; the AI score is increased/decreased accordingly. ; input: -; [wSelectedMoveIndex] = move to check. +; [wSelectedAttack] = move to check. DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack jp c, .not_enough_energy ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F @@ -4402,7 +4402,7 @@ DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F call CheckLoadedMoveFlag jp nc, .check_evolution - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, DUELVARS_ARENA_CARD_HP call GetNonTurnDuelistVariable @@ -4481,7 +4481,7 @@ DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) ldh a, [hTempPlayAreaLocation_ff9d] or a jr nz, .check_evolution - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, DUELVARS_ARENA_CARD_HP call GetNonTurnDuelistVariable @@ -4669,7 +4669,7 @@ CheckIfEvolutionNeedsEnergyForMove: ; 16805 (5:6805) ; 0x1683b ; returns in e the card ID of the energy required for -; the Discard/Energy Boost attack loaded in wSelectedMoveIndex. +; the Discard/Energy Boost attack loaded in wSelectedAttack. ; if it's Zapdos2's Thunderbolt attack, return no carry. ; if it's Charizard's Fire Spin or Exeggutor's Big Eggplosion ; attack, don't return energy card ID, but set carry. @@ -4684,7 +4684,7 @@ GetEnergyCardForDiscardOrEnergyBoostAttack: ; 1683b (5:683b) call GetTurnDuelistVariable call LoadCardDataToBuffer2_FromDeckIndex ld b, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] or a jr z, .first_attack @@ -4771,7 +4771,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) ; if first attack doesn't need, test for the second attack. xor a ld [wTempAI], a - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack jr nc, .second_attack ld a, b @@ -4783,7 +4783,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) .second_attack ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack jr nc, .check_discard_or_energy_boost ld a, b @@ -4803,7 +4803,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) ; for both attacks, check if it has the effect of ; discarding energy cards or attached energy boost. xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F call CheckLoadedMoveFlag @@ -4813,7 +4813,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) jr c, .energy_boost_or_discard_energy ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckEnergyNeededForAttack ld a, MOVE_FLAG2_ADDRESS | ATTACHED_ENERGY_BOOST_F call CheckLoadedMoveFlag @@ -4921,7 +4921,7 @@ AITryToPlayEnergyCard: ; 1689f (5:689f) jr z, .check_first_attack ret .check_first_attack - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] or a jp z, .second_attack ret @@ -5029,14 +5029,14 @@ Func_169ca: ; 169ca (5:69ca) dec b jr nz, .loop +; copies wAIScore to wcde3 ld a, [wAIScore] ld [de], a - jr Func_169f8.asm_169fc + jr Func_169fc ; copies wTempPlayAreaAIScore to wPlayAreaAIScore ; and loads wAIscore with value in wcde3. ; identical to Func_164d3. -; TODO: reconsider function structure here. Func_169e3: ; 169e3 (5:69e3) push af ld de, wPlayAreaAIScore @@ -5048,6 +5048,7 @@ Func_169e3: ; 169e3 (5:69e3) inc de dec b jr nz, .loop + ld a, [hl] ld [wAIScore], a pop af @@ -5057,15 +5058,18 @@ Func_169e3: ; 169e3 (5:69e3) Func_169f8: ; 169f8 (5:69f8) xor a ld [wcdd9], a -.asm_169fc + ; fallthrough + +Func_169fc: ; 169fc (5:69fc) +; if AI used Pluspower, load its attack index ld a, [wPreviousAIFlags] and AI_FLAG_USED_PLUSPOWER - jr z, .asm_16a0b - ld a, [wcdd6] - ld [wSelectedMoveIndex], a - jr .first_attack - -.asm_16a0b + jr z, .no_pluspower + ld a, [wAIPluspowerAttack] + ld [wSelectedAttack], a + jr .attack_chosen + +.no_pluspower ld a, [wcda7] cp $80 jp z, .asm_16a77 @@ -5077,7 +5081,9 @@ Func_169f8: ; 169f8 (5:69f8) ld [wPlayAreaAIScore], a ld a, SECOND_ATTACK call GetAIScoreOfAttack - ld c, $01 + +; compare both attack scores + ld c, SECOND_ATTACK ld a, [wPlayAreaAIScore] ld b, a ld a, [wAIScore] @@ -5095,13 +5101,15 @@ Func_169f8: ; 169f8 (5:69f8) .asm_16a30 cp $50 ; minimum score to use attack jr c, .asm_16a77 + ; enough score, proceed + ld a, c - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a or a - jr z, .first_attack + jr z, .attack_chosen call CheckWhetherToSwitchToFirstAttack -.first_attack +.attack_chosen ld a, [wcdd9] or a jr z, .asm_16a48 @@ -5110,22 +5118,29 @@ Func_169f8: ; 169f8 (5:69f8) .asm_16a48 ld a, $0e - call Func_14663 - xor a + call AIProcessHandTrainerCards + +; load this attack's damage output against +; the current Defending Pokemon. + xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, [wDamage] + or a jr z, .asm_16a62 -.asm_16a5c + ; if damage is 0, fallthrough + +.cannot_damage xor a ld [wcdb4], a jr .asm_16a6d + .asm_16a62 ld a, MOVE_FLAG1_ADDRESS | DAMAGE_TO_OPPONENT_BENCH_F call CheckLoadedMoveFlag - jr c, .asm_16a5c + jr c, .cannot_damage ld hl, wcdb4 inc [hl] .asm_16a6d @@ -5149,7 +5164,7 @@ Func_169f8: ; 169f8 (5:69f8) ; determines the AI score of attack index in a. GetAIScoreOfAttack: ; 16a86 (5:6a86) ; initialize AI score. - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, $50 ld [wAIScore], a @@ -5192,7 +5207,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ; player is under No Damage substatus ld a, $01 ld [wAICannotDamage], a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, [wLoadedMoveCategory] cp POKEMON_POWER @@ -5206,7 +5221,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ; calculate damage to player to check if move can KO. ; encourage move if it's able to KO. .check_if_can_ko - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_VersusDefendingCard ld a, DUELVARS_ARENA_CARD_HP call GetNonTurnDuelistVariable @@ -5484,12 +5499,12 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ; if defending card can KO, encourage move ; unless move is non-damaging. .check_defending_can_ko - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] push af call CheckIfDefendingPokemonCanKnockOut pop bc ld a, b - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a jr nc, .check_discard ld a, 5 call AddToAIScore @@ -5502,7 +5517,7 @@ GetAIScoreOfAttack: ; 16a86 (5:6a86) ; subtract from AI score if this move requires ; discarding any energy cards. .check_discard - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable @@ -5860,7 +5875,7 @@ HandleSwordsDanceAndFocusEnergy: ; 16ecb (5:6ecb) or a jr nz, .success ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .success ld a, $01 ; second move @@ -5917,7 +5932,7 @@ HandlePorygonConversion: ; 16f18 (5:6f18) cp CONFUSED jp z, HandleSpecialAIMoves.zero - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] or a jr nz, .conversion_2 @@ -6142,11 +6157,11 @@ CheckWhetherToSwitchToFirstAttack: ; 17019 (5:7019) jr c, .keep_second_attack ; switch to first attack xor a - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ret .keep_second_attack ld a, $01 - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ret ; 0x17057 @@ -6275,7 +6290,7 @@ CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondMove: ; 170c9 (5:70c9) xor a ; active card ldh [hTempPlayAreaLocation_ff9d], a ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a push hl call CheckIfSelectedMoveIsUnusable pop hl @@ -6298,7 +6313,7 @@ CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondMove: ; 170c9 (5:70c9) CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) ldh a, [hTempPlayAreaLocation_ff9d] ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a push de ld a, DUELVARS_BENCH @@ -6342,7 +6357,7 @@ CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) ld a, c ldh [hTempPlayAreaLocation_ff9d], a ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a push bc push hl call CheckIfSelectedMoveIsUnusable @@ -6356,7 +6371,7 @@ CheckIfBenchCardsAreAtHalfHPCanEvolveAndUseSecondMove: ; 17101 (5:7101) pop hl pop de ld a, e - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, d ldh [hTempPlayAreaLocation_ff9d], a ld a, b @@ -6371,11 +6386,11 @@ Func_17161 ; 17161 (5:7161) ; return carry if Pokémon at play area location ; in hTempPlayAreaLocation_ff9d does not have -; energy required for the move index in wSelectedMoveIndex +; energy required for the move index in wSelectedAttack ; or has exactly the same amount of energy needed ; input: ; [hTempPlayAreaLocation_ff9d] = play area location -; [wSelectedMoveIndex] = move index to check +; [wSelectedAttack] = move index to check ; output: ; a = number of extra energy cards attached CheckIfNoSurplusEnergyForMove: ; 171fb (5:71fb) @@ -6383,7 +6398,7 @@ CheckIfNoSurplusEnergyForMove: ; 171fb (5:71fb) add DUELVARS_ARENA_CARD call GetTurnDuelistVariable ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a call CopyMoveDataAndDamage_FromDeckIndex ld hl, wLoadedMoveName @@ -6537,7 +6552,7 @@ Func_172af ; 172af (5:72af) CheckIfCanDamageDefendingPokemon: ; 17383 (5:7383) ldh [hTempPlayAreaLocation_ff9d], a xor a ; first move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .second_attack xor a @@ -6548,7 +6563,7 @@ CheckIfCanDamageDefendingPokemon: ; 17383 (5:7383) .second_attack ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call CheckIfSelectedMoveIsUnusable jr c, .no_carry ld a, $01 @@ -6615,7 +6630,7 @@ CheckIfDefendingPokemonCanKnockOut: ; 173b1 (5:73b1) ; a = move index ; [hTempPlayAreaLocation_ff9d] = location of card to check CheckIfDefendingPokemonCanKnockOutWithMove: ; 173e4 (5:73e4) - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ldh a, [hTempPlayAreaLocation_ff9d] push af xor a @@ -6629,7 +6644,7 @@ CheckIfDefendingPokemonCanKnockOutWithMove: ; 173e4 (5:73e4) jr c, .done ; player's active Pokémon can use move - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] call EstimateDamage_FromDefendingPokemon ldh a, [hTempPlayAreaLocation_ff9d] add DUELVARS_ARENA_CARD_HP @@ -6747,7 +6762,7 @@ CheckForBenchIDAtHalfHPAndCanUseSecondMove: ; 17474 (5:7474) ld [wcdf9], a ldh a, [hTempPlayAreaLocation_ff9d] ld d, a - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a push de ld a, DUELVARS_ARENA_CARD @@ -6785,7 +6800,7 @@ CheckForBenchIDAtHalfHPAndCanUseSecondMove: ; 17474 (5:7474) ld a, c ldh [hTempPlayAreaLocation_ff9d], a ld a, $01 ; second move - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a push bc call CheckIfSelectedMoveIsUnusable pop bc @@ -6795,7 +6810,7 @@ CheckForBenchIDAtHalfHPAndCanUseSecondMove: ; 17474 (5:7474) pop hl pop de ld a, e - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, d ldh [hTempPlayAreaLocation_ff9d], a ld a, b diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index ee7b2d6..ad36e90 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6,47 +6,47 @@ unknown_data_20000: MACRO ENDM Data_20000: ; 20000 (8:4000) - unknown_data_20000 $07, POTION, AIDecidePotion1, AIPlayPotion - unknown_data_20000 $0a, POTION, AIDecidePotion2, AIPlayPotion - unknown_data_20000 $08, SUPER_POTION, AIDecideSuperPotion1, AIPlaySuperPotion - unknown_data_20000 $0b, SUPER_POTION, AIDecideSuperPotion2, AIPlaySuperPotion - unknown_data_20000 $0d, DEFENDER, AIDecideDefender1, AIPlayDefender - unknown_data_20000 $0e, DEFENDER, AIDecideDefender2, AIPlayDefender - unknown_data_20000 $0d, PLUSPOWER, AIDecidePluspower1, AIPlayPluspower - unknown_data_20000 $0e, PLUSPOWER, AIDecidePluspower2, AIPlayPluspower - unknown_data_20000 $09, SWITCH, AIDecideSwitch, AIPlaySwitch - unknown_data_20000 $07, GUST_OF_WIND, AIDecideGustOfWind, AIPlayGustOfWind - unknown_data_20000 $0a, GUST_OF_WIND, AIDecideGustOfWind, AIPlayGustOfWind - unknown_data_20000 $04, BILL, AIDecideBill, AIPlayBill - unknown_data_20000 $05, ENERGY_REMOVAL, AIDecideEnergyRemoval, AIPlayEnergyRemoval - unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, AIDecideSuperEnergyRemoval, AIPlaySuperEnergyRemoval - unknown_data_20000 $07, POKEMON_BREEDER, AIDecidePokemonBreeder, AIPlayPokemonBreeder - unknown_data_20000 $0f, PROFESSOR_OAK, AIDecideProfessorOak, AIPlayProfessorOak - unknown_data_20000 $0a, ENERGY_RETRIEVAL, AIDecideEnergyRetrieval, AIPlayEnergyRetrieval - unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, AIDecideSuperEnergyRetrieval, AIPlaySuperEnergyRetrieval - unknown_data_20000 $06, POKEMON_CENTER, AIDecidePokemonCenter, AIPlayPokemonCenter - unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, AIDecideImposterProfessorOak, AIPlayImposterProfessorOak - unknown_data_20000 $0c, ENERGY_SEARCH, AIDecideEnergySearch, AIPlayEnergySearch - unknown_data_20000 $03, POKEDEX, AIDecidePokedex, AIPlayPokedex - unknown_data_20000 $07, FULL_HEAL, AIDecideFullHeal, AIPlayFullHeal - unknown_data_20000 $0a, MR_FUJI, AIDecideMrFuji, AIPlayMrFuji - unknown_data_20000 $0a, SCOOP_UP, AIDecideScoopUp, AIPlayScoopUp - unknown_data_20000 $02, MAINTENANCE, AIDecideMaintenance, AIPlayMaintenance - unknown_data_20000 $03, RECYCLE, AIDecideRecycle, AIPlayRecycle - unknown_data_20000 $0d, LASS, AIDecideLass, AIPlayLass - unknown_data_20000 $04, ITEM_FINDER, AIDecideItemFinder, AIPlayItemFinder - unknown_data_20000 $01, IMAKUNI_CARD, AIDecideImakuni, AIPlayImakuni - unknown_data_20000 $01, GAMBLER, AIDecideGambler, AIPlayGambler - unknown_data_20000 $05, REVIVE, AIDecideRevive, AIPlayRevive - unknown_data_20000 $0d, POKEMON_FLUTE, AIDecidePokemonFlute, AIPlayPokemonFlute - unknown_data_20000 $05, CLEFAIRY_DOLL, AIDecideClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil - unknown_data_20000 $05, MYSTERIOUS_FOSSIL, AIDecideClefairyDollOrMysteriousFossil, AIPlayClefairyDollOrMysteriousFossil - unknown_data_20000 $02, POKE_BALL, AIDecidePokeball, AIPlayPokeball - unknown_data_20000 $02, COMPUTER_SEARCH, AIDecideComputerSearch, AIPlayComputerSearch - unknown_data_20000 $02, POKEMON_TRADER, AIDecidePokemonTrader, AIPlayPokemonTrader + unknown_data_20000 $07, POTION, AIDecide_Potion1, AIPlay_Potion + unknown_data_20000 $0a, POTION, AIDecide_Potion2, AIPlay_Potion + unknown_data_20000 $08, SUPER_POTION, AIDecide_SuperPotion1, AIPlay_SuperPotion + unknown_data_20000 $0b, SUPER_POTION, AIDecide_SuperPotion2, AIPlay_SuperPotion + unknown_data_20000 $0d, DEFENDER, AIDecide_Defender1, AIPlay_Defender + unknown_data_20000 $0e, DEFENDER, AIDecide_Defender2, AIPlay_Defender + unknown_data_20000 $0d, PLUSPOWER, AIDecide_Pluspower1, AIPlay_Pluspower + unknown_data_20000 $0e, PLUSPOWER, AIDecide_Pluspower2, AIPlay_Pluspower + unknown_data_20000 $09, SWITCH, AIDecide_Switch, AIPlay_Switch + unknown_data_20000 $07, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind + unknown_data_20000 $0a, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind + unknown_data_20000 $04, BILL, AIDecide_Bill, AIPlay_Bill + unknown_data_20000 $05, ENERGY_REMOVAL, AIDecide_EnergyRemoval, AIPlay_EnergyRemoval + unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, AIDecide_SuperEnergyRemoval, AIPlay_SuperEnergyRemoval + unknown_data_20000 $07, POKEMON_BREEDER, AIDecide_PokemonBreeder, AIPlay_PokemonBreeder + unknown_data_20000 $0f, PROFESSOR_OAK, AIDecide_ProfessorOak, AIPlay_ProfessorOak + unknown_data_20000 $0a, ENERGY_RETRIEVAL, AIDecide_EnergyRetrieval, AIPlay_EnergyRetrieval + unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, AIDecide_SuperEnergyRetrieval, AIPlay_SuperEnergyRetrieval + unknown_data_20000 $06, POKEMON_CENTER, AIDecide_PokemonCenter, AIPlay_PokemonCenter + unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, AIDecide_ImposterProfessorOak, AIPlay_ImposterProfessorOak + unknown_data_20000 $0c, ENERGY_SEARCH, AIDecide_EnergySearch, AIPlay_EnergySearch + unknown_data_20000 $03, POKEDEX, AIDecide_Pokedex, AIPlay_Pokedex + unknown_data_20000 $07, FULL_HEAL, AIDecide_FullHeal, AIPlay_FullHeal + unknown_data_20000 $0a, MR_FUJI, AIDecide_MrFuji, AIPlay_MrFuji + unknown_data_20000 $0a, SCOOP_UP, AIDecide_ScoopUp, AIPlay_ScoopUp + unknown_data_20000 $02, MAINTENANCE, AIDecide_Maintenance, AIPlay_Maintenance + unknown_data_20000 $03, RECYCLE, AIDecide_Recycle, AIPlay_Recycle + unknown_data_20000 $0d, LASS, AIDecide_Lass, AIPlay_Lass + unknown_data_20000 $04, ITEM_FINDER, AIDecide_ItemFinder, AIPlay_ItemFinder + unknown_data_20000 $01, IMAKUNI_CARD, AIDecide_Imakuni, AIPlay_Imakuni + unknown_data_20000 $01, GAMBLER, AIDecide_Gambler, AIPlay_Gambler + unknown_data_20000 $05, REVIVE, AIDecide_Revive, AIPlay_Revive + unknown_data_20000 $0d, POKEMON_FLUTE, AIDecide_PokemonFlute, AIPlay_PokemonFlute + unknown_data_20000 $05, CLEFAIRY_DOLL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil + unknown_data_20000 $05, MYSTERIOUS_FOSSIL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil + unknown_data_20000 $02, POKE_BALL, AIDecide_Pokeball, AIPlay_Pokeball + unknown_data_20000 $02, COMPUTER_SEARCH, AIDecide_ComputerSearch, AIPlay_ComputerSearch + unknown_data_20000 $02, POKEMON_TRADER, AIDecide_PokemonTrader, AIPlay_PokemonTrader db $ff -Func_200e5: ; 200e5 (8:40e5) +_AIProcessHandTrainerCards: ; 200e5 (8:40e5) ld [wce18], a ; create hand list in wDuelTempList and wTempHandCardList. call CreateHandCardList @@ -104,7 +104,7 @@ Func_200e5: ; 200e5 (8:40e5) ldh [hTempCardIndex_ff9f], a ; if Headache effects prevent playing card -; move on to the next ite, in list. +; move on to the next item in list. bank1call CheckCantUseTrainerDueToHeadache jp c, .next_in_data @@ -197,7 +197,7 @@ Func_200e5: ; 200e5 (8:40e5) ; 0x201b5 ; makes AI use Potion card. -AIPlayPotion: ; 201b5 (8:41b5) +AIPlay_Potion: ; 201b5 (8:41b5) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -219,7 +219,7 @@ AIPlayPotion: ; 201b5 (8:41b5) ; next turn after using Potion. ; if it cannot, return carry. ; also take into account whether move is high recoil. -AIDecidePotion1: ; 201d1 (8:41d1) +AIDecide_Potion1: ; 201d1 (8:41d1) farcall AIDecideWhetherToRetreat jr c, .no_carry call Func_22bad @@ -262,7 +262,7 @@ AIDecidePotion1: ; 201d1 (8:41d1) ; output: ; a = card to use Potion on; ; carry set if Potion should be used. -AIDecidePotion2: ; 20204 (8:4204) +AIDecide_Potion2: ; 20204 (8:4204) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfDefendingPokemonCanKnockOut @@ -363,7 +363,7 @@ AIDecidePotion2: ; 20204 (8:4204) .check_boost_if_taken_damage ; 2027e (8:427e) push de xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a farcall CheckIfSelectedMoveIsUnusable jr c, .second_attack ld a, MOVE_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F @@ -371,7 +371,7 @@ AIDecidePotion2: ; 20204 (8:4204) jr c, .set_carry .second_attack ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a farcall CheckIfSelectedMoveIsUnusable jr c, .false ld a, MOVE_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F @@ -388,7 +388,7 @@ AIDecidePotion2: ; 20204 (8:4204) ; 0x202a8 ; makes AI use Super Potion card. -AIPlaySuperPotion: ; 202a8 (8:42a8) +AIPlay_SuperPotion: ; 202a8 (8:42a8) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -413,7 +413,7 @@ AIPlaySuperPotion: ; 202a8 (8:42a8) ; active card next turn after using Super Potion. ; if it cannot, return carry. ; also take into account whether move is high recoil. -AIDecideSuperPotion1: ; 202cc (8:42cc) +AIDecide_SuperPotion1: ; 202cc (8:42cc) farcall AIDecideWhetherToRetreat jr c, .no_carry call Func_22bad @@ -467,7 +467,7 @@ AIDecideSuperPotion1: ; 202cc (8:42cc) ; output: ; a = card to use Super Potion on; ; carry set if Super Potion should be used. -AIDecideSuperPotion2: ; 2030f (8:430f) +AIDecide_SuperPotion2: ; 2030f (8:430f) xor a ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfDefendingPokemonCanKnockOut @@ -585,7 +585,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) .check_boost_if_taken_damage ; 2039e (8:439e) push de xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a farcall CheckIfSelectedMoveIsUnusable jr c, .second_attack_1 ld a, MOVE_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F @@ -593,7 +593,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) jr c, .true_1 .second_attack_1 ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a farcall CheckIfSelectedMoveIsUnusable jr c, .false_1 ld a, MOVE_FLAG3_ADDRESS | BOOST_IF_TAKEN_DAMAGE_F @@ -614,7 +614,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) .check_energy_cost ; 203c8 (8:43c8) push de xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -626,7 +626,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) pop de push de ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -644,7 +644,7 @@ AIDecideSuperPotion2: ; 2030f (8:430f) ret ; 0x203f8 -AIPlayDefender: ; 203f8 (8:43f8) +AIPlay_Defender: ; 203f8 (8:43f8) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a xor a @@ -657,7 +657,7 @@ AIPlayDefender: ; 203f8 (8:43f8) ; returns carry if using Defender can prevent a KO ; by the defending Pokémon. ; this takes into account both attacks and whether they're useable. -AIDecideDefender1: ; 20406 (8:4406) +AIDecide_Defender1: ; 20406 (8:4406) xor a ; PLAY_AREA_ARENA ldh [hTempPlayAreaLocation_ff9d], a farcall CheckIfAnyMoveKnocksOutDefendingCard @@ -678,7 +678,7 @@ AIDecideDefender1: ; 20406 (8:4406) call SwapTurn jr c, .no_carry - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] farcall EstimateDamage_FromDefendingPokemon ld a, [wDamage] ld [wce06], a @@ -686,11 +686,11 @@ AIDecideDefender1: ; 20406 (8:4406) ; load in a the attack that was not selected, ; and check if it is useable. - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld b, a ld a, $01 sub b - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a push de call SwapTurn farcall CheckIfSelectedMoveIsUnusable @@ -700,7 +700,7 @@ AIDecideDefender1: ; 20406 (8:4406) ; the other attack is useable. ; compare its damage to the selected move. - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] push de farcall EstimateDamage_FromDefendingPokemon pop de @@ -712,11 +712,11 @@ AIDecideDefender1: ; 20406 (8:4406) ; and deals less damage than the selected move, ; switch back to the other attack. .switch_back - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld b, a ld a, $01 sub b - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, [wce06] ld [wDamage], a @@ -742,7 +742,7 @@ AIDecideDefender1: ; 20406 (8:4406) ; return carry if using Defender prevents Pokémon ; from being knocked out by an attack with recoil. -AIDecideDefender2: ; 20486 (8:4486) +AIDecide_Defender2: ; 20486 (8:4486) ld a, MOVE_FLAG1_ADDRESS | HIGH_RECOIL_F call CheckLoadedMoveFlag jr c, .recoil @@ -756,7 +756,7 @@ AIDecideDefender2: ; 20486 (8:4486) ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable call LoadCardDataToBuffer2_FromDeckIndex - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] or a jr nz, .second_attack ; first attack @@ -815,12 +815,12 @@ AIDecideDefender2: ; 20486 (8:4486) ret ; 0x204e8 -AIPlayPluspower: ; 204e8 (8:44e8) +AIPlay_Pluspower: ; 204e8 (8:44e8) ld a, [wCurrentAIFlags] or AI_FLAG_USED_PLUSPOWER ld [wCurrentAIFlags], a ld a, [wAITrainerCardParameter] - ld [wcdd6], a + ld [wAIPluspowerAttack], a ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -830,7 +830,8 @@ AIPlayPluspower: ; 204e8 (8:44e8) ; returns carry if using a Pluspower can KO defending Pokémon ; if active card cannot KO without the boost. -AIDecidePluspower1: ; 20501 (8:4501) +; outputs in a the attack to use. +AIDecide_Pluspower1: ; 20501 (8:4501) ; this is mistakenly duplicated xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -874,11 +875,11 @@ AIDecidePluspower1: ; 20501 (8:4501) ; can KO with Pluspower boost. ; if neither can KO, return no carry. xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call .check_ko_with_pluspower jr c, .kos_with_pluspower_1 ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call .check_ko_with_pluspower jr c, .kos_with_pluspower_2 @@ -907,7 +908,7 @@ AIDecidePluspower1: ; 20501 (8:4501) .check_ko_with_pluspower ; 20562 (8:4562) farcall CheckIfSelectedMoveIsUnusable jr c, .unusable - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] farcall EstimateDamage_VersusDefendingCard ld a, DUELVARS_ARENA_CARD_HP call GetNonTurnDuelistVariable @@ -954,7 +955,8 @@ AIDecidePluspower1: ; 20501 (8:4501) ; if selected move is useable, can't KO without Pluspower boost ; can damage Mr. Mime even with Pluspower boost ; and has a minimum damage > 0. -AIDecidePluspower2: ; 205a5 (8:45a5) +; outputs in a the attack to use. +AIDecide_Pluspower2: ; 205a5 (8:45a5) xor a ldh [hTempPlayAreaLocation_ff9d], a call .check_can_ko @@ -994,7 +996,7 @@ AIDecidePluspower2: ; 205a5 (8:45a5) .check_can_ko ; 205d7 (8:45d7) farcall CheckIfSelectedMoveIsUnusable jr c, .unuseable - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] farcall EstimateDamage_VersusDefendingCard ld a, DUELVARS_ARENA_CARD_HP call GetNonTurnDuelistVariable @@ -1016,7 +1018,7 @@ AIDecidePluspower2: ; 205a5 (8:45a5) .check_random ; 205f6 (8:45f6) farcall CheckIfSelectedMoveIsUnusable jr c, .unuseable - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] farcall EstimateDamage_VersusDefendingCard ld a, [wAIMinDamage] cp 10 @@ -1027,7 +1029,7 @@ AIDecidePluspower2: ; 205a5 (8:45a5) ret ; 0x20612 -AIPlaySwitch: ; 20612 (8:4612) +AIPlay_Switch: ; 20612 (8:4612) ld a, [wCurrentAIFlags] or AI_FLAG_USED_SWITCH ld [wCurrentAIFlags], a @@ -1045,7 +1047,7 @@ AIPlaySwitch: ; 20612 (8:4612) ; returns carry if the active card has less energy cards ; than the retreat cost and if AI can't play an energy ; card from the hand to fulfill the cost -AIDecideSwitch: ; 2062e (8:462e) +AIDecide_Switch: ; 2062e (8:462e) ; check if AI can already play an energy card from hand to retreat ld a, [wAIPlayEnergyCardForRetreat] or a @@ -1092,7 +1094,7 @@ AIDecideSwitch: ; 2062e (8:462e) ret ; 0x20666 -AIPlayGustOfWind: ; 20666 (8:4666) +AIPlay_GustOfWind: ; 20666 (8:4666) ld a, [wCurrentAIFlags] or AI_FLAG_USED_GUST_OF_WIND ld [wCurrentAIFlags], a @@ -1105,7 +1107,7 @@ AIPlayGustOfWind: ; 20666 (8:4666) ret ; 0x2067e -AIDecideGustOfWind: ; 2067e (8:467e) +AIDecide_GustOfWind: ; 2067e (8:467e) ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetNonTurnDuelistVariable dec a @@ -1277,13 +1279,13 @@ AIDecideGustOfWind: ; 2067e (8:467e) ; returns carry if neither attack can deal damage .CheckIfNoAttackDealsDamage ; 2076b (8:476b) xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call .CheckIfAttackDealsNoDamage jr c, .second_attack ret .second_attack ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a call .CheckIfAttackDealsNoDamage jr c, .true ret @@ -1294,7 +1296,7 @@ AIDecideGustOfWind: ; 2067e (8:467e) ; returns carry if attack is Pokemon Power ; or otherwise doesn't deal any damage .CheckIfAttackDealsNoDamage ; 20782 (8:4782) - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable @@ -1310,7 +1312,7 @@ AIDecideGustOfWind: ; 2067e (8:467e) ret z ; check damage against defending card - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] farcall EstimateDamage_VersusDefendingCard ld a, [wAIMaxDamage] or a @@ -1481,7 +1483,7 @@ AIDecideGustOfWind: ; 2067e (8:467e) ret ; 0x2086d -AIPlayBill: ; 2086d (8:486d) +AIPlay_Bill: ; 2086d (8:486d) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -1490,14 +1492,14 @@ AIPlayBill: ; 2086d (8:486d) ; 0x20878 ; return carry if cards in deck > 9 -AIDecideBill: ; 20878 (8:4878) +AIDecide_Bill: ; 20878 (8:4878) ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable cp DECK_SIZE - 9 ret ; 0x20880 -AIPlayEnergyRemoval: ; 20880 (8:4880) +AIPlay_EnergyRemoval: ; 20880 (8:4880) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -1510,7 +1512,7 @@ AIPlayEnergyRemoval: ; 20880 (8:4880) ; 0x20895 ; picks an energy card in the player's Play Area to remove -AIDecideEnergyRemoval: ; 20895 (8:4895) +AIDecide_EnergyRemoval: ; 20895 (8:4895) ; check if the current active card can KO player's card ; if it's possible to KO, then do not consider the player's ; active card to remove its attached energy @@ -1626,7 +1628,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) .CheckIfNotEnoughEnergyToAttack ; 20924 (8:4924) push de xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -1635,7 +1637,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) push de ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -1712,7 +1714,7 @@ AIDecideEnergyRemoval: ; 20895 (8:4895) ret ; 0x20994 -AIPlaySuperEnergyRemoval: ; 20994 (8:4994) +AIPlay_SuperEnergyRemoval: ; 20994 (8:4994) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -1733,7 +1735,7 @@ AIPlaySuperEnergyRemoval: ; 20994 (8:4994) ; 0x209bc ; picks two energy cards in the player's Play Area to remove -AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) +AIDecide_SuperEnergyRemoval: ; 209bc (8:49bc) ld e, PLAY_AREA_BENCH_1 .loop_1 ; first find an Arena card with a color energy card @@ -1911,7 +1913,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) .CheckIfNotEnoughEnergyToAttack ; 20a92 (8:4a92) push de xor a ; FIRST_ATTACK_OR_PKMN_POWER - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -1920,7 +1922,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) push de ld a, SECOND_ATTACK - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, e ldh [hTempPlayAreaLocation_ff9d], a farcall CheckEnergyNeededForAttack @@ -2001,7 +2003,7 @@ AIDecideSuperEnergyRemoval: ; 209bc (8:49bc) ret ; 0x20b06 -AIPlayPokemonBreeder: ; 20b06 (8:4b06) +AIPlay_PokemonBreeder: ; 20b06 (8:4b06) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -2013,7 +2015,7 @@ AIPlayPokemonBreeder: ; 20b06 (8:4b06) ret ; 0x20b1b -AIDecidePokemonBreeder: ; 20b1b (8:4b1b) +AIDecide_PokemonBreeder: ; 20b1b (8:4b1b) call IsPrehistoricPowerActive jp c, .done @@ -2357,7 +2359,7 @@ AIDecidePokemonBreeder: ; 20b1b (8:4b1b) ret ; 0x20cae -AIPlayProfessorOak: ; 20cae (8:4cae) +AIPlay_ProfessorOak: ; 20cae (8:4cae) ld a, [wCurrentAIFlags] or AI_FLAG_USED_PROFESSOR_OAK | AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -2370,7 +2372,7 @@ AIPlayProfessorOak: ; 20cae (8:4cae) ; sets carry if AI determines a score of playing ; Professor Oak is over a certain threshold. -AIDecideProfessorOak: ; 20cc1 (8:4cc1) +AIDecide_ProfessorOak: ; 20cc1 (8:4cc1) ; return if cards in deck <= 6 ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetTurnDuelistVariable @@ -2688,7 +2690,7 @@ AIDecideProfessorOak: ; 20cc1 (8:4cc1) ret ; 0x20e44 -AIPlayEnergyRetrieval: ; 20e44 (8:4e44) +AIPlay_EnergyRetrieval: ; 20e44 (8:4e44) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -2713,7 +2715,7 @@ AIPlayEnergyRetrieval: ; 20e44 (8:4e44) ; checks whether AI can play Energy Retrieval and ; picks the energy cards from the discard pile, ; and duplicate cards in hand to discard. -AIDecideEnergyRetrieval: ; 20e6e (8:4e6e) +AIDecide_EnergyRetrieval: ; 20e6e (8:4e6e) ; return no carry if no cards in hand farcall CreateEnergyCardListFromHand jp nc, .no_carry @@ -2947,7 +2949,7 @@ FindDuplicateCards: ; 20f38 (8:4f38) ret ; 0x20f80 -AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) +AIPlay_SuperEnergyRetrieval: ; 20f80 (8:4f80) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -2979,7 +2981,7 @@ AIPlaySuperEnergyRetrieval: ; 20f80 (8:4f80) ret ; 0x20fc1 -AIDecideSuperEnergyRetrieval: ; 20fc1 (8:4fc1) +AIDecide_SuperEnergyRetrieval: ; 20fc1 (8:4fc1) ; return no carry if no cards in hand farcall CreateEnergyCardListFromHand jp nc, .no_carry @@ -3179,7 +3181,7 @@ FindAndRemoveCardFromList: ; 210d5 (8:50d5) ret ; 0x210e0 -AIPlayPokemonCenter: ; 210e0 (8:50e0) +AIPlay_PokemonCenter: ; 210e0 (8:50e0) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -3187,7 +3189,7 @@ AIPlayPokemonCenter: ; 210e0 (8:50e0) ret ; 0x210eb -AIDecidePokemonCenter: ; 210eb (8:50eb) +AIDecide_PokemonCenter: ; 210eb (8:50eb) xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -3280,7 +3282,7 @@ AIDecidePokemonCenter: ; 210eb (8:50eb) ret ; 0x21170 -AIPlayImposterProfessorOak: ; 21170 (8:5170) +AIPlay_ImposterProfessorOak: ; 21170 (8:5170) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -3290,7 +3292,7 @@ AIPlayImposterProfessorOak: ; 21170 (8:5170) ; sets carry depending on player's number of cards ; in deck in in hand. -AIDecideImposterProfessorOak: ; 2117b (8:517b) +AIDecide_ImposterProfessorOak: ; 2117b (8:517b) ld a, DUELVARS_NUMBER_OF_CARDS_NOT_IN_DECK call GetNonTurnDuelistVariable cp DECK_SIZE - 14 @@ -3318,7 +3320,7 @@ AIDecideImposterProfessorOak: ; 2117b (8:517b) ret ; 0x2119a -AIPlayEnergySearch: ; 2119a (8:519a) +AIPlay_EnergySearch: ; 2119a (8:519a) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -3329,7 +3331,7 @@ AIPlayEnergySearch: ; 2119a (8:519a) ; 0x211aa ; AI checks for playing Energy Search -AIDecideEnergySearch: ; 211aa (8:51aa) +AIDecide_EnergySearch: ; 211aa (8:51aa) farcall CreateEnergyCardListFromHand jr c, .start call .CheckForUsefulEnergyCards @@ -3566,7 +3568,7 @@ AIDecideEnergySearch: ; 211aa (8:51aa) ret ; 0x212b4 -AIPlayPokedex: ; 212b4 (8:52b4) +AIPlay_Pokedex: ; 212b4 (8:52b4) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wce1a] @@ -3586,7 +3588,7 @@ AIPlayPokedex: ; 212b4 (8:52b4) ret ; 0x212dc -AIDecidePokedex: ; 212dc (8:52dc) +AIDecide_Pokedex: ; 212dc (8:52dc) ld a, [wcda6] cp $06 jr c, .no_carry @@ -3881,7 +3883,7 @@ PickPokedexCards: ; 2138e (8:538e) ret ; 0x2141d -AIPlayFullHeal: ; 2141d (8:541d) +AIPlay_FullHeal: ; 2141d (8:541d) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -3889,7 +3891,7 @@ AIPlayFullHeal: ; 2141d (8:541d) ret ; 0x21428 -AIDecideFullHeal: ; 21428 (8:5428) +AIDecide_FullHeal: ; 21428 (8:5428) ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable @@ -3933,7 +3935,7 @@ AIDecideFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_prz - call AIDecideScoopUp + call AIDecide_ScoopUp jr c, .no_carry .no_scoop_up_prz @@ -3960,7 +3962,7 @@ AIDecideFullHeal: ; 21428 (8:5428) ld a, SCOOP_UP call LookForCardIDInHandList_Bank8 jr nc, .no_scoop_up_cnf - call AIDecideScoopUp + call AIDecide_ScoopUp jr c, .no_carry .no_scoop_up_cnf @@ -3976,7 +3978,7 @@ AIDecideFullHeal: ; 21428 (8:5428) jr .no_carry ; 0x21497 -AIPlayMrFuji: ; 21497 (8:5497) +AIPlay_MrFuji: ; 21497 (8:5497) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -3987,7 +3989,7 @@ AIPlayMrFuji: ; 21497 (8:5497) ; 0x214a7 ; AI logic for playing Mr Fuji -AIDecideMrFuji: ; 214a7 (8:54a7) +AIDecide_MrFuji: ; 214a7 (8:54a7) ld a, $ff ld [wce06], a ld [wce08], a @@ -4050,7 +4052,7 @@ AIDecideMrFuji: ; 214a7 (8:54a7) ret ; 0x214f1 -AIPlayScoopUp: ; 214f1 (8:54f1) +AIPlay_ScoopUp: ; 214f1 (8:54f1) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -4062,7 +4064,7 @@ AIPlayScoopUp: ; 214f1 (8:54f1) ret ; 0x21506 -AIDecideScoopUp: ; 21506 (8:5506) +AIDecide_ScoopUp: ; 21506 (8:5506) xor a ldh [hTempPlayAreaLocation_ff9d], a @@ -4260,7 +4262,7 @@ AIDecideScoopUp: ; 21506 (8:5506) jp .no_carry ; 0x2160f -AIPlayMaintenance: ; 2160f (8:560f) +AIPlay_Maintenance: ; 2160f (8:560f) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -4276,7 +4278,7 @@ AIPlayMaintenance: ; 2160f (8:560f) ; 0x2162c ; AI logic for playing Maintenance -AIDecideMaintenance: ; 2162c (8:562c) +AIDecide_Maintenance: ; 2162c (8:562c) ; Imakuni? has his own thing ld a, [wOpponentDeckID] cp IMAKUNI_DECK_ID @@ -4359,7 +4361,7 @@ AIDecideMaintenance: ; 2162c (8:562c) ret ; 0x2169a -AIPlayRecycle: ; 2169a (8:569a) +AIPlay_Recycle: ; 2169a (8:569a) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ldtx de, TrainerCardSuccessCheckText @@ -4381,7 +4383,7 @@ AIPlayRecycle: ; 2169a (8:569a) ; has priorities for Ghost Deck, and a "default" priority list ; (which is the Fire Charge deck, since it's the only other ; deck that runs a Recycle card in it.) -AIDecideRecycle: ; 216b8 (8:56b8) +AIDecide_Recycle: ; 216b8 (8:56b8) ; no use checking if no cards in Discard Pile call CreateDiscardPileCardList jr c, .no_carry @@ -4500,7 +4502,7 @@ AIDecideRecycle: ; 216b8 (8:56b8) jr .loop_2 ; 0x21755 -AIPlayLass: ; 21755 (8:5755) +AIPlay_Lass: ; 21755 (8:5755) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -4511,7 +4513,7 @@ AIPlayLass: ; 21755 (8:5755) ret ; 0x21768 -AIDecideLass: ; 21768 (8:5768) +AIDecide_Lass: ; 21768 (8:5768) ; skip if player has less than 7 cards in hand ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND call GetNonTurnDuelistVariable @@ -4542,7 +4544,7 @@ AIDecideLass: ; 21768 (8:5768) ret ; 0x2178f -AIPlayItemFinder: ; 2178f (8:578f) +AIPlay_ItemFinder: ; 2178f (8:578f) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -4563,7 +4565,7 @@ AIPlayItemFinder: ; 2178f (8:578f) ; if so, find duplicate cards in hand to discard ; that are not Mr Mime and Pokemon Trader cards. ; this logic is suitable only for Strange Psyshock deck. -AIDecideItemFinder: ; 217b1 (8:57b1) +AIDecide_ItemFinder: ; 217b1 (8:57b1) ; skip if no Discard Pile. call CreateDiscardPileCardList jr c, .no_carry @@ -4635,7 +4637,7 @@ AIDecideItemFinder: ; 217b1 (8:57b1) ret ; 0x21813 -AIPlayImakuni: ; 21813 (8:5813) +AIPlay_Imakuni: ; 21813 (8:5813) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -4644,7 +4646,7 @@ AIPlayImakuni: ; 21813 (8:5813) ; 0x2181e ; only sets carry if Active card is not confused. -AIDecideImakuni: ; 2181e (8:581e) +AIDecide_Imakuni: ; 2181e (8:581e) ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable and CNF_SLP_PRZ @@ -4657,7 +4659,7 @@ AIDecideImakuni: ; 2181e (8:581e) ret ; 0x2182d -AIPlayGambler: ; 2182d (8:582d) +AIPlay_Gambler: ; 2182d (8:582d) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -4698,7 +4700,7 @@ AIPlayGambler: ; 2182d (8:582d) ; checks whether to play Gambler. ; aside from Imakuni, all other opponents only ; play if there's less than 4 cards in the deck. -AIDecideGambler: ; 21875 (8:5875) +AIDecide_Gambler: ; 21875 (8:5875) ; Imakuni? has his own routine ld a, [wOpponentDeckID] cp IMAKUNI_DECK_ID @@ -4728,7 +4730,7 @@ AIDecideGambler: ; 21875 (8:5875) ret ; 0x21899 -AIPlayRevive: ; 21899 (8:5899) +AIPlay_Revive: ; 21899 (8:5899) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -4740,7 +4742,7 @@ AIPlayRevive: ; 21899 (8:5899) ; checks certain cards in Discard Pile to use Revive on. ; suitable for Muscle For Brains deck only. -AIDecideRevive: ; 218a9 (8:58a9) +AIDecide_Revive: ; 218a9 (8:58a9) ; skip if no cards in Discard Pile call CreateDiscardPileCardList jr c, .no_carry @@ -4786,7 +4788,7 @@ AIDecideRevive: ; 218a9 (8:58a9) ret ; 0x218d8 -AIPlayPokemonFlute: ; 218d8 (8:58d8) +AIPlay_PokemonFlute: ; 218d8 (8:58d8) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -4796,7 +4798,7 @@ AIPlayPokemonFlute: ; 218d8 (8:58d8) ret ; 0x218e8 -AIDecidePokemonFlute: ; 218e8 (8:58e8) +AIDecide_PokemonFlute: ; 218e8 (8:58e8) ; if player has no Discard Pile, skip. call SwapTurn call CreateDiscardPileCardList @@ -4893,7 +4895,7 @@ AIDecidePokemonFlute: ; 218e8 (8:58e8) ret ; 0x21977 -AIPlayClefairyDollOrMysteriousFossil: ; 21977 (8:5977) +AIPlay_ClefairyDollOrMysteriousFossil: ; 21977 (8:5977) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, OPPACTION_EXECUTE_TRAINER_EFFECTS @@ -4902,7 +4904,7 @@ AIPlayClefairyDollOrMysteriousFossil: ; 21977 (8:5977) ; 0x21982 ; AI logic for playing Clefairy Doll -AIDecideClefairyDollOrMysteriousFossil: ; 21982 (8:5982) +AIDecide_ClefairyDollOrMysteriousFossil: ; 21982 (8:5982) ; if has max number of Play Area Pokemon, skip ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable @@ -4933,7 +4935,7 @@ AIDecideClefairyDollOrMysteriousFossil: ; 21982 (8:5982) ret ; 0x219a6 -AIPlayPokeball: ; 219a6 (8:59a6) +AIPlay_Pokeball: ; 219a6 (8:59a6) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ldtx de, TrainerCardSuccessCheckText @@ -4952,7 +4954,7 @@ AIPlayPokeball: ; 219a6 (8:59a6) ret ; 0x219c6 -AIDecidePokeball: ; 219c6 (8:59c6) +AIDecide_Pokeball: ; 219c6 (8:59c6) ; go to the routines associated with deck ID ld a, [wOpponentDeckID] cp FIRE_CHARGE_DECK_ID @@ -5154,7 +5156,7 @@ AIDecidePokeball: ; 219c6 (8:59c6) ret ; 0x21b12 -AIPlayComputerSearch: ; 21b12 (8:5b12) +AIPlay_ComputerSearch: ; 21b12 (8:5b12) ld a, [wCurrentAIFlags] or AI_FLAG_MODIFIED_HAND ld [wCurrentAIFlags], a @@ -5173,7 +5175,7 @@ AIPlayComputerSearch: ; 21b12 (8:5b12) ; checks what Deck ID AI is playing and handle ; them in their own routine. -AIDecideComputerSearch: ; 21b34 (8:5b34) +AIDecide_ComputerSearch: ; 21b34 (8:5b34) ; skip if number of cards in hand < 3 ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND call GetTurnDuelistVariable @@ -5182,19 +5184,19 @@ AIDecideComputerSearch: ; 21b34 (8:5b34) ld a, [wOpponentDeckID] cp ROCK_CRUSHER_DECK_ID - jr z, AIDecideComputerSearch_RockCrusher + jr z, AIDecide_ComputerSearch_RockCrusher cp WONDERS_OF_SCIENCE_DECK_ID - jp z, AIDecideComputerSearch_WondersOfScience + jp z, AIDecide_ComputerSearch_WondersOfScience cp FIRE_CHARGE_DECK_ID - jp z, AIDecideComputerSearch_FireCharge + jp z, AIDecide_ComputerSearch_FireCharge cp ANGER_DECK_ID - jp z, AIDecideComputerSearch_Anger + jp z, AIDecide_ComputerSearch_Anger .no_carry or a ret -AIDecideComputerSearch_RockCrusher: ; 21b55 (8:5b55) +AIDecide_ComputerSearch_RockCrusher: ; 21b55 (8:5b55) ; if number of cards in hand is equal to 3, ; target Professor Oak in deck ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND @@ -5372,7 +5374,7 @@ AIDecideComputerSearch_RockCrusher: ; 21b55 (8:5b55) scf ret -AIDecideComputerSearch_WondersOfScience: ; 21c56 (8:5c56) +AIDecide_ComputerSearch_WondersOfScience: ; 21c56 (8:5c56) ; if number of cards in hand < 5, target Professor Oak in deck ld a, DUELVARS_NUMBER_OF_CARDS_IN_HAND call GetTurnDuelistVariable @@ -5445,7 +5447,7 @@ AIDecideComputerSearch_WondersOfScience: ; 21c56 (8:5c56) scf ret -AIDecideComputerSearch_FireCharge: ; 21cbb (8:5cbb) +AIDecide_ComputerSearch_FireCharge: ; 21cbb (8:5cbb) ; pick target card in deck from highest to lowest priority. ; if not found in hand, go to corresponding branch. ld a, CHANSEY @@ -5511,7 +5513,7 @@ AIDecideComputerSearch_FireCharge: ; 21cbb (8:5cbb) ret ; 0x21d1e -AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) +AIDecide_ComputerSearch_Anger: ; 21d1e (8:5d1e) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -5572,7 +5574,7 @@ AIDecideComputerSearch_Anger: ; 21d1e (8:5d1e) ret ; 0x21d7a -AIPlayPokemonTrader: ; 21d7a (8:5d7a) +AIPlay_PokemonTrader: ; 21d7a (8:5d7a) ld a, [wAITrainerCardToPlay] ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] @@ -5584,34 +5586,34 @@ AIPlayPokemonTrader: ; 21d7a (8:5d7a) ret ; 0x21d8f -AIDecidePokemonTrader: ; 21d8f (8:5d8f) +AIDecide_PokemonTrader: ; 21d8f (8:5d8f) ; each deck has their own routine for picking ; what Pokemon to look for. ld a, [wOpponentDeckID] cp LEGENDARY_MOLTRES_DECK_ID - jr z, AIDecidePokemonTrader_LegendaryMoltres + jr z, AIDecide_PokemonTrader_LegendaryMoltres cp LEGENDARY_ARTICUNO_DECK_ID - jr z, AIDecidePokemonTrader_LegendaryArticuno + jr z, AIDecide_PokemonTrader_LegendaryArticuno cp LEGENDARY_DRAGONITE_DECK_ID - jp z, AIDecidePokemonTrader_LegendaryDragonite + jp z, AIDecide_PokemonTrader_LegendaryDragonite cp LEGENDARY_RONALD_DECK_ID - jp z, AIDecidePokemonTrader_LegendaryRonald + jp z, AIDecide_PokemonTrader_LegendaryRonald cp BLISTERING_POKEMON_DECK_ID - jp z, AIDecidePokemonTrader_BlisteringPokemon + jp z, AIDecide_PokemonTrader_BlisteringPokemon cp SOUND_OF_THE_WAVES_DECK_ID - jp z, AIDecidePokemonTrader_SoundOfTheWaves + jp z, AIDecide_PokemonTrader_SoundOfTheWaves cp POWER_GENERATOR_DECK_ID - jp z, AIDecidePokemonTrader_PowerGenerator + jp z, AIDecide_PokemonTrader_PowerGenerator cp FLOWER_GARDEN_DECK_ID - jp z, AIDecidePokemonTrader_FlowerGarden + jp z, AIDecide_PokemonTrader_FlowerGarden cp STRANGE_POWER_DECK_ID - jp z, AIDecidePokemonTrader_StrangePower + jp z, AIDecide_PokemonTrader_StrangePower cp FLAMETHROWER_DECK_ID - jp z, AIDecidePokemonTrader_Flamethrower + jp z, AIDecide_PokemonTrader_Flamethrower or a ret -AIDecidePokemonTrader_LegendaryMoltres: ; 21dc4 (8:5dc4) +AIDecide_PokemonTrader_LegendaryMoltres: ; 21dc4 (8:5dc4) ; look for Moltres2 card in deck to trade with a ; card in hand different from Moltres1. ld a, MOLTRES2 @@ -5627,7 +5629,7 @@ AIDecidePokemonTrader_LegendaryMoltres: ; 21dc4 (8:5dc4) or a ret -AIDecidePokemonTrader_LegendaryArticuno: ; 21dd5 (8:5dd5) +AIDecide_PokemonTrader_LegendaryArticuno: ; 21dd5 (8:5dd5) ; if has none of these cards in Hand or Play Area, proceed ld a, ARTICUNO1 call LookForCardIDInHandAndPlayArea @@ -5683,7 +5685,7 @@ AIDecidePokemonTrader_LegendaryArticuno: ; 21dd5 (8:5dd5) ret ; 0x21e24 -AIDecidePokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) +AIDecide_PokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) ; if has less than 5 cards of energy ; and of Pokemon in hand/Play Area, ; target a Kangaskhan in deck. @@ -5781,7 +5783,7 @@ AIDecidePokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) ret ; 0x21ec9 -AIDecidePokemonTrader_LegendaryRonald: ; 21ec9 (8:5ec9) +AIDecide_PokemonTrader_LegendaryRonald: ; 21ec9 (8:5ec9) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -5852,7 +5854,7 @@ AIDecidePokemonTrader_LegendaryRonald: ; 21ec9 (8:5ec9) ret ; 0x21f41 -AIDecidePokemonTrader_BlisteringPokemon: ; 21f41 (8:5f41) +AIDecide_PokemonTrader_BlisteringPokemon: ; 21f41 (8:5f41) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -5898,7 +5900,7 @@ AIDecidePokemonTrader_BlisteringPokemon: ; 21f41 (8:5f41) ret ; 0x21f85 -AIDecidePokemonTrader_SoundOfTheWaves: ; 21f85 (8:5f85) +AIDecide_PokemonTrader_SoundOfTheWaves: ; 21f85 (8:5f85) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -5975,7 +5977,7 @@ AIDecidePokemonTrader_SoundOfTheWaves: ; 21f85 (8:5f85) ret ; 0x2200b -AIDecidePokemonTrader_PowerGenerator: ; 2200b (8:600b) +AIDecide_PokemonTrader_PowerGenerator: ; 2200b (8:600b) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -6067,7 +6069,7 @@ AIDecidePokemonTrader_PowerGenerator: ; 2200b (8:600b) ret ; 0x220a8 -AIDecidePokemonTrader_FlowerGarden: ; 220a8 (8:60a8) +AIDecide_PokemonTrader_FlowerGarden: ; 220a8 (8:60a8) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -6137,7 +6139,7 @@ AIDecidePokemonTrader_FlowerGarden: ; 220a8 (8:60a8) ret ; 0x22122 -AIDecidePokemonTrader_StrangePower: ; 22122 (8:6122) +AIDecide_PokemonTrader_StrangePower: ; 22122 (8:6122) ; looks for a Pokemon in hand to trade with Mr Mime in deck. ; inputing Mr Mime in register e for the function is redundant ; since it already checks whether a Mr Mime exists in the hand. @@ -6155,7 +6157,7 @@ AIDecidePokemonTrader_StrangePower: ; 22122 (8:6122) ret ; 0x22133 -AIDecidePokemonTrader_Flamethrower: ; 22133 (8:6133) +AIDecide_PokemonTrader_Flamethrower: ; 22133 (8:6133) ; for each of the following cards, ; first run a check if there's a pre-evolution in ; Play Area or in the hand. If there is, choose it as target. @@ -7119,7 +7121,7 @@ FindDuplicatePokemonCards: ; 22b6f (8:6b6f) Func_22bad: ; 22bad (8:6bad) farcall Func_169ca ret nc - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld e, a ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable diff --git a/src/engine/home.asm b/src/engine/home.asm index 9584db2..545995a 100644 --- a/src/engine/home.asm +++ b/src/engine/home.asm @@ -4376,7 +4376,7 @@ Func_161e: ; 161e (0:161e) ; 0x16ad ; copies, given a card identified by register a (card ID): -; - e into wSelectedMoveIndex and d into hTempCardIndex_ff9f +; - e into wSelectedAttack and d into hTempCardIndex_ff9f ; - Move1 (if e == 0) or Move2 (if e == 1) data into wLoadedMove ; - Also from that move, its Damage field into wDamage ; finally, clears wNoDamageOrEffect and wDealtDamage @@ -4384,7 +4384,7 @@ CopyMoveDataAndDamage_FromCardID: ; 16ad (0:16ad) push de push af ld a, e - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, d ldh [hTempCardIndex_ff9f], a pop af @@ -4395,13 +4395,13 @@ CopyMoveDataAndDamage_FromCardID: ; 16ad (0:16ad) jr CopyMoveDataAndDamage ; copies, given a card identified by register d (0-59 deck index): -; - e into wSelectedMoveIndex and d into hTempCardIndex_ff9f +; - e into wSelectedAttack and d into hTempCardIndex_ff9f ; - Move1 (if e == 0) or Move2 (if e == 1) data into wLoadedMove ; - Also from that move, its Damage field into wDamage ; finally, clears wNoDamageOrEffect and wDealtDamage CopyMoveDataAndDamage_FromDeckIndex: ; 16c0 (0:16c0) ld a, e - ld [wSelectedMoveIndex], a + ld [wSelectedAttack], a ld a, d ldh [hTempCardIndex_ff9f], a call LoadCardDataToBuffer1_FromDeckIndex @@ -4465,7 +4465,7 @@ Func_16f6: ; 16f6 (0:16f6) ; Use an attack (from DuelMenu_Attack) or a Pokemon Power (from DuelMenu_PkmnPower) UseAttackOrPokemonPower: ; 1730 (0:1730) - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] ld [wPlayerAttackingMoveIndex], a ldh a, [hTempCardIndex_ff9f] ld [wPlayerAttackingCardIndex], a @@ -9858,7 +9858,7 @@ HandleCantAttackSubstatus: ; 33c1 (0:33c1) ret ; return carry if the turn holder's arena Pokemon cannot use -; selected move at wSelectedMoveIndex due to amnesia +; selected move at wSelectedAttack due to amnesia HandleAmnesiaSubstatus: ; 33e1 (0:33e1) ld a, DUELVARS_ARENA_CARD_SUBSTATUS2 call GetTurnDuelistVariable @@ -9874,7 +9874,7 @@ HandleAmnesiaSubstatus: ; 33e1 (0:33e1) .affected_by_amnesia ld a, DUELVARS_ARENA_CARD_DISABLED_MOVE_INDEX call GetTurnDuelistVariable - ld a, [wSelectedMoveIndex] + ld a, [wSelectedAttack] cp [hl] jr nz, .not_the_disabled_move ldtx hl, UnableToUseAttackDueToAmnesiaText diff --git a/src/wram.asm b/src/wram.asm index dae9a17..ac4648e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -955,8 +955,8 @@ wTempNonTurnDuelistCardID:: ; ccc4 wccc5:: ; ccc5 ds $1 -; may contain 0 or 1 depending on which move was selected -wSelectedMoveIndex:: ; ccc6 +; *_ATTACK constants for selected attack +wSelectedAttack:: ; ccc6 ds $1 ; if affected by a no damage or effect substatus, this flag indicates what the cause was @@ -1260,7 +1260,9 @@ wTempCardIDToLook:: ; cdd4 wcdd5:: ; cdd5 ds $1 -wcdd6:: ; cdd6 +; the index of attack chosen by AI +; to use with Pluspower. +wAIPluspowerAttack:: ; cdd6 ds $1 ; whether AI is allowed to play an energy card @@ -1705,7 +1707,7 @@ wcf17:: ; cf17 ds $15 -; used by Func_200e5, AI related +; used by _AIProcessHandTrainerCards, AI related wTempHandCardList:: ; cf68 ds DECK_SIZE -- cgit v1.2.3 From eebe2ce0026f6b1d30f33ff3fd12b2a2ad1d0e39 Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 22 Apr 2020 10:45:03 +0100 Subject: Added some AI related constants --- src/constants/card_data_constants.asm | 5 +++ src/constants/duel_constants.asm | 19 ++++++++ src/data/cards.asm | 18 ++++---- src/engine/bank05.asm | 5 ++- src/engine/bank08.asm | 81 ++++++++++++++++++----------------- src/wram.asm | 2 +- 6 files changed, 79 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/constants/card_data_constants.asm b/src/constants/card_data_constants.asm index 3f3dd3a..3f26e4d 100644 --- a/src/constants/card_data_constants.asm +++ b/src/constants/card_data_constants.asm @@ -230,3 +230,8 @@ UNABLE_RETREAT EQU $64 ; attack index constants FIRST_ATTACK_OR_PKMN_POWER EQU $0 SECOND_ATTACK EQU $1 + +; whether move with the ATTACHED_ENERGY_BOOST flag +; has limit on attached energy cards boost. +MAX_ENERGY_BOOST_IS_LIMITED EQU $2 +MAX_ENERGY_BOOST_IS_NOT_LIMITED EQU $3 diff --git a/src/constants/duel_constants.asm b/src/constants/duel_constants.asm index b1063dc..65f58e3 100644 --- a/src/constants/duel_constants.asm +++ b/src/constants/duel_constants.asm @@ -231,3 +231,22 @@ 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 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 diff --git a/src/data/cards.asm b/src/data/cards.asm index 8bbc091..48a1ba2 100644 --- a/src/data/cards.asm +++ b/src/data/cards.asm @@ -1952,7 +1952,7 @@ ExeggutorCard: ; 31689 (c:5689) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 3 + db MAX_ENERGY_BOOST_IS_NOT_LIMITED db 2 ; animation db 3 ; retreat cost @@ -3278,7 +3278,7 @@ BlastoiseCard: ; 31d23 (c:5d23) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 22 ; animation db 3 ; retreat cost @@ -3417,7 +3417,7 @@ PoliwagCard: ; 31de6 (c:5de6) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation ; move 2 @@ -3519,7 +3519,7 @@ PoliwrathCard: ; 31e68 (c:5e68) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation ; move 2 @@ -4029,7 +4029,7 @@ SeadraCard: ; 320f2 (c:60f2) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation ; move 2 @@ -4386,7 +4386,7 @@ LaprasCard: ; 322b9 (c:62b9) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation ; move 2 @@ -4502,7 +4502,7 @@ Vaporeon2Card: ; 3233b (c:633b) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation db 1 ; retreat cost @@ -4553,7 +4553,7 @@ OmanyteCard: ; 3237c (c:637c) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation db 1 ; retreat cost @@ -4590,7 +4590,7 @@ OmastarCard: ; 323bd (c:63bd) db NONE ; flags 1 db ATTACHED_ENERGY_BOOST ; flags 2 db NONE ; flags 3 - db 2 + db MAX_ENERGY_BOOST_IS_LIMITED db 19 ; animation ; move 2 diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index ec205ce..7b0d7aa 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -4375,8 +4375,11 @@ DetermineAIScoreOfMoveEnergyRequirement: ; 16695 (5:6695) .attached_energy_boost ld a, [wLoadedMoveEffectParam] - cp $02 + cp MAX_ENERGY_BOOST_IS_LIMITED jr z, .check_surplus_energy + + ; is MAX_ENERGY_BOOST_IS_NOT_LIMITED, + ; which is equal to 3, add to score. call AddToAIScore jp .check_evolution diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index ad36e90..bac8d61 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -6,44 +6,44 @@ unknown_data_20000: MACRO ENDM Data_20000: ; 20000 (8:4000) - unknown_data_20000 $07, POTION, AIDecide_Potion1, AIPlay_Potion - unknown_data_20000 $0a, POTION, AIDecide_Potion2, AIPlay_Potion - unknown_data_20000 $08, SUPER_POTION, AIDecide_SuperPotion1, AIPlay_SuperPotion - unknown_data_20000 $0b, SUPER_POTION, AIDecide_SuperPotion2, AIPlay_SuperPotion - unknown_data_20000 $0d, DEFENDER, AIDecide_Defender1, AIPlay_Defender - unknown_data_20000 $0e, DEFENDER, AIDecide_Defender2, AIPlay_Defender - unknown_data_20000 $0d, PLUSPOWER, AIDecide_Pluspower1, AIPlay_Pluspower - unknown_data_20000 $0e, PLUSPOWER, AIDecide_Pluspower2, AIPlay_Pluspower - unknown_data_20000 $09, SWITCH, AIDecide_Switch, AIPlay_Switch - unknown_data_20000 $07, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind - unknown_data_20000 $0a, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind - unknown_data_20000 $04, BILL, AIDecide_Bill, AIPlay_Bill - unknown_data_20000 $05, ENERGY_REMOVAL, AIDecide_EnergyRemoval, AIPlay_EnergyRemoval - unknown_data_20000 $05, SUPER_ENERGY_REMOVAL, AIDecide_SuperEnergyRemoval, AIPlay_SuperEnergyRemoval - unknown_data_20000 $07, POKEMON_BREEDER, AIDecide_PokemonBreeder, AIPlay_PokemonBreeder - unknown_data_20000 $0f, PROFESSOR_OAK, AIDecide_ProfessorOak, AIPlay_ProfessorOak - unknown_data_20000 $0a, ENERGY_RETRIEVAL, AIDecide_EnergyRetrieval, AIPlay_EnergyRetrieval - unknown_data_20000 $0b, SUPER_ENERGY_RETRIEVAL, AIDecide_SuperEnergyRetrieval, AIPlay_SuperEnergyRetrieval - unknown_data_20000 $06, POKEMON_CENTER, AIDecide_PokemonCenter, AIPlay_PokemonCenter - unknown_data_20000 $07, IMPOSTER_PROFESSOR_OAK, AIDecide_ImposterProfessorOak, AIPlay_ImposterProfessorOak - unknown_data_20000 $0c, ENERGY_SEARCH, AIDecide_EnergySearch, AIPlay_EnergySearch - unknown_data_20000 $03, POKEDEX, AIDecide_Pokedex, AIPlay_Pokedex - unknown_data_20000 $07, FULL_HEAL, AIDecide_FullHeal, AIPlay_FullHeal - unknown_data_20000 $0a, MR_FUJI, AIDecide_MrFuji, AIPlay_MrFuji - unknown_data_20000 $0a, SCOOP_UP, AIDecide_ScoopUp, AIPlay_ScoopUp - unknown_data_20000 $02, MAINTENANCE, AIDecide_Maintenance, AIPlay_Maintenance - unknown_data_20000 $03, RECYCLE, AIDecide_Recycle, AIPlay_Recycle - unknown_data_20000 $0d, LASS, AIDecide_Lass, AIPlay_Lass - unknown_data_20000 $04, ITEM_FINDER, AIDecide_ItemFinder, AIPlay_ItemFinder - unknown_data_20000 $01, IMAKUNI_CARD, AIDecide_Imakuni, AIPlay_Imakuni - unknown_data_20000 $01, GAMBLER, AIDecide_Gambler, AIPlay_Gambler - unknown_data_20000 $05, REVIVE, AIDecide_Revive, AIPlay_Revive - unknown_data_20000 $0d, POKEMON_FLUTE, AIDecide_PokemonFlute, AIPlay_PokemonFlute - unknown_data_20000 $05, CLEFAIRY_DOLL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil - unknown_data_20000 $05, MYSTERIOUS_FOSSIL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil - unknown_data_20000 $02, POKE_BALL, AIDecide_Pokeball, AIPlay_Pokeball - unknown_data_20000 $02, COMPUTER_SEARCH, AIDecide_ComputerSearch, AIPlay_ComputerSearch - unknown_data_20000 $02, POKEMON_TRADER, AIDecide_PokemonTrader, AIPlay_PokemonTrader + unknown_data_20000 AI_TRAINER_CARD_PHASE_07, POTION, AIDecide_Potion1, AIPlay_Potion + unknown_data_20000 AI_TRAINER_CARD_PHASE_10, POTION, AIDecide_Potion2, AIPlay_Potion + unknown_data_20000 AI_TRAINER_CARD_PHASE_08, SUPER_POTION, AIDecide_SuperPotion1, AIPlay_SuperPotion + unknown_data_20000 AI_TRAINER_CARD_PHASE_11, SUPER_POTION, AIDecide_SuperPotion2, AIPlay_SuperPotion + unknown_data_20000 AI_TRAINER_CARD_PHASE_13, DEFENDER, AIDecide_Defender1, AIPlay_Defender + unknown_data_20000 AI_TRAINER_CARD_PHASE_14, DEFENDER, AIDecide_Defender2, AIPlay_Defender + unknown_data_20000 AI_TRAINER_CARD_PHASE_13, PLUSPOWER, AIDecide_Pluspower1, AIPlay_Pluspower + unknown_data_20000 AI_TRAINER_CARD_PHASE_14, PLUSPOWER, AIDecide_Pluspower2, AIPlay_Pluspower + unknown_data_20000 AI_TRAINER_CARD_PHASE_09, SWITCH, AIDecide_Switch, AIPlay_Switch + unknown_data_20000 AI_TRAINER_CARD_PHASE_07, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind + unknown_data_20000 AI_TRAINER_CARD_PHASE_10, GUST_OF_WIND, AIDecide_GustOfWind, AIPlay_GustOfWind + unknown_data_20000 AI_TRAINER_CARD_PHASE_04, BILL, AIDecide_Bill, AIPlay_Bill + unknown_data_20000 AI_TRAINER_CARD_PHASE_05, ENERGY_REMOVAL, AIDecide_EnergyRemoval, AIPlay_EnergyRemoval + unknown_data_20000 AI_TRAINER_CARD_PHASE_05, SUPER_ENERGY_REMOVAL, AIDecide_SuperEnergyRemoval, AIPlay_SuperEnergyRemoval + unknown_data_20000 AI_TRAINER_CARD_PHASE_07, POKEMON_BREEDER, AIDecide_PokemonBreeder, AIPlay_PokemonBreeder + unknown_data_20000 AI_TRAINER_CARD_PHASE_15, PROFESSOR_OAK, AIDecide_ProfessorOak, AIPlay_ProfessorOak + unknown_data_20000 AI_TRAINER_CARD_PHASE_10, ENERGY_RETRIEVAL, AIDecide_EnergyRetrieval, AIPlay_EnergyRetrieval + unknown_data_20000 AI_TRAINER_CARD_PHASE_11, SUPER_ENERGY_RETRIEVAL, AIDecide_SuperEnergyRetrieval, AIPlay_SuperEnergyRetrieval + unknown_data_20000 AI_TRAINER_CARD_PHASE_06, POKEMON_CENTER, AIDecide_PokemonCenter, AIPlay_PokemonCenter + unknown_data_20000 AI_TRAINER_CARD_PHASE_07, IMPOSTER_PROFESSOR_OAK, AIDecide_ImposterProfessorOak, AIPlay_ImposterProfessorOak + unknown_data_20000 AI_TRAINER_CARD_PHASE_12, ENERGY_SEARCH, AIDecide_EnergySearch, AIPlay_EnergySearch + unknown_data_20000 AI_TRAINER_CARD_PHASE_03, POKEDEX, AIDecide_Pokedex, AIPlay_Pokedex + unknown_data_20000 AI_TRAINER_CARD_PHASE_07, FULL_HEAL, AIDecide_FullHeal, AIPlay_FullHeal + unknown_data_20000 AI_TRAINER_CARD_PHASE_10, MR_FUJI, AIDecide_MrFuji, AIPlay_MrFuji + unknown_data_20000 AI_TRAINER_CARD_PHASE_10, SCOOP_UP, AIDecide_ScoopUp, AIPlay_ScoopUp + unknown_data_20000 AI_TRAINER_CARD_PHASE_02, MAINTENANCE, AIDecide_Maintenance, AIPlay_Maintenance + unknown_data_20000 AI_TRAINER_CARD_PHASE_03, RECYCLE, AIDecide_Recycle, AIPlay_Recycle + unknown_data_20000 AI_TRAINER_CARD_PHASE_13, LASS, AIDecide_Lass, AIPlay_Lass + unknown_data_20000 AI_TRAINER_CARD_PHASE_04, ITEM_FINDER, AIDecide_ItemFinder, AIPlay_ItemFinder + unknown_data_20000 AI_TRAINER_CARD_PHASE_01, IMAKUNI_CARD, AIDecide_Imakuni, AIPlay_Imakuni + unknown_data_20000 AI_TRAINER_CARD_PHASE_01, GAMBLER, AIDecide_Gambler, AIPlay_Gambler + unknown_data_20000 AI_TRAINER_CARD_PHASE_05, REVIVE, AIDecide_Revive, AIPlay_Revive + unknown_data_20000 AI_TRAINER_CARD_PHASE_13, POKEMON_FLUTE, AIDecide_PokemonFlute, AIPlay_PokemonFlute + unknown_data_20000 AI_TRAINER_CARD_PHASE_05, CLEFAIRY_DOLL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil + unknown_data_20000 AI_TRAINER_CARD_PHASE_05, MYSTERIOUS_FOSSIL, AIDecide_ClefairyDollOrMysteriousFossil, AIPlay_ClefairyDollOrMysteriousFossil + unknown_data_20000 AI_TRAINER_CARD_PHASE_02, POKE_BALL, AIDecide_Pokeball, AIPlay_Pokeball + unknown_data_20000 AI_TRAINER_CARD_PHASE_02, COMPUTER_SEARCH, AIDecide_ComputerSearch, AIPlay_ComputerSearch + unknown_data_20000 AI_TRAINER_CARD_PHASE_02, POKEMON_TRADER, AIDecide_PokemonTrader, AIPlay_PokemonTrader db $ff _AIProcessHandTrainerCards: ; 200e5 (8:40e5) @@ -7133,5 +7133,6 @@ Func_22bad: ; 22bad (8:6bad) ret ; 0x22bc6 -Func_22bc6 ; 22bc6 (8:6bc6) - INCROM $22bc6, $24000 +rept $143a + db $ff +endr diff --git a/src/wram.asm b/src/wram.asm index ac4648e..7ff0dfe 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1378,7 +1378,7 @@ wce17:: ; ce17 wce18:: ; ce18 ds $1 -; paramaters output by AI Trainer card logic routines +; parameters output by AI Trainer card logic routines ; (e.g. what Pokemon in Play Area to use card on, etc) wAITrainerCardParameter:: ; ce19 ds $1 -- cgit v1.2.3 From a5e06695a1bfd86a0f24483fdfe186fb565e3faf Mon Sep 17 00:00:00 2001 From: ElectroDeoxys Date: Wed, 22 Apr 2020 11:44:38 +0100 Subject: Clean up documentation and headers --- src/engine/bank05.asm | 10 ++++++---- src/engine/bank08.asm | 35 ++++++++++++++++++++++------------- src/wram.asm | 2 ++ 3 files changed, 30 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index 7b0d7aa..ee45de4 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -1561,7 +1561,7 @@ CheckEnergyNeededForAttackAfterDiscard: ; 156c3 (5:56c3) .is_attack ldh a, [hTempPlayAreaLocation_ff9d] - farcall GetEnergyCardToDiscard + farcall AIPickEnergyCardToDiscard call LoadCardDataToBuffer1_FromDeckIndex cp DOUBLE_COLORLESS_ENERGY jr z, .colorless @@ -1765,9 +1765,11 @@ CheckIfAnyCardIDinLocation: ; 157a3 (5:57a3) ret ; 0x157c6 -; outputs in a total number of energy cards in hand +; counts total number of energy cards in opponent's hand ; plus all the cards attached in Turn Duelist's Play Area. -CountEnergyCardsInHandAndAttached: ; 157c6 (5:57c6) +; output: +; a and wTempAI = total number of energy cards. +CountOppEnergyCardsInHandAndAttached: ; 157c6 (5:57c6) xor a ld [wTempAI], a call CreateEnergyCardListFromHand @@ -3295,7 +3297,7 @@ Func_16120: ; 16120 (5:6120) cp 3 jr c, .not_enough_energy push af - farcall CountEnergyCardsInHand + farcall CountOppEnergyCardsInHand pop bc add b cp 6 diff --git a/src/engine/bank08.asm b/src/engine/bank08.asm index bac8d61..5a0f535 100644 --- a/src/engine/bank08.asm +++ b/src/engine/bank08.asm @@ -393,7 +393,7 @@ AIPlay_SuperPotion: ; 202a8 (8:42a8) ldh [hTempCardIndex_ff9f], a ld a, [wAITrainerCardParameter] ldh [hTempPlayAreaLocation_ffa1], a - call GetEnergyCardToDiscard + call AIPickEnergyCardToDiscard ldh [hTemp_ffa0], a ld a, [wAITrainerCardParameter] ld e, a @@ -1563,7 +1563,7 @@ AIDecide_EnergyRemoval: ; 20895 (8:4895) ; and set carry ld a, e push af - call PickAttachedEnergyCard + call PickAttachedEnergyCardToRemove ld [wce1a], a pop af call SwapTurn @@ -1841,7 +1841,7 @@ AIDecide_SuperEnergyRemoval: ; 209bc (8:49bc) call SwapTurn ld a, [wce0f] push af - call GetEnergyCardToDiscard + call AIPickEnergyCardToDiscard ld [wce1a], a pop af scf @@ -2618,7 +2618,7 @@ AIDecide_ProfessorOak: ; 20cc1 (8:4cc1) ; if there are more than 3 energy cards in hand, ; return no carry, otherwise check for playable cards. .check_playable_cards - call CountEnergyCardsInHand + call CountOppEnergyCardsInHand cp 4 jr nc, .no_carry_articuno @@ -5689,7 +5689,7 @@ AIDecide_PokemonTrader_LegendaryDragonite: ; 21e24 (8:5e24) ; if has less than 5 cards of energy ; and of Pokemon in hand/Play Area, ; target a Kangaskhan in deck. - farcall CountEnergyCardsInHandAndAttached + farcall CountOppEnergyCardsInHandAndAttached cp 5 jr c, .kangaskhan call CountPokemonCardsInHandAndInPlayArea @@ -6130,11 +6130,11 @@ AIDecide_PokemonTrader_FlowerGarden: ; 220a8 (8:60a8) .find_duplicates ld [wce1a], a call FindDuplicatePokemonCards - jr c, .asm_22120 + jr c, .found .no_carry or a ret -.asm_22120 +.found scf ret ; 0x22122 @@ -6223,10 +6223,13 @@ Func_2219b: ; 2219b (8:219b) INCROM $2219b, $227f6 ; lists in wDuelTempList all the basic energy cards -; is card location of a. +; in card location of a. +; outputs in a number of cards found. ; returns carry if none were found. ; input: ; a = CARD_LOCATION_* to look +; output: +; a = number of cards found FindBasicEnergyCardsInLocation: ; 227f6 (8:67f6) ld [wTempAI], a lb de, 0, 0 @@ -6287,8 +6290,13 @@ FindBasicEnergyCardsInLocation: ; 227f6 (8:67f6) ; returns in a the card index of energy card ; attached to Pokémon in Play Area location a, -; that is to be discarded. -GetEnergyCardToDiscard: ; 2282e (8:682e) +; that is to be discarded by the AI for an effect. +; outputs $ff is none was found. +; input: +; a = PLAY_AREA_* constant of card +; output: +; a = deck index of attached energy card chosen +AIPickEnergyCardToDiscard: ; 2282e (8:682e) ; load Pokémon's attached energy cards. ldh [hTempPlayAreaLocation_ff9d], a call CreateArenaOrBenchEnergyCardList @@ -6338,7 +6346,7 @@ GetEnergyCardToDiscard: ; 2282e (8:682e) ; 0x22875 ; returns in a the deck index of an energy card attached to card -; in Play Area location a.. +; in player's Play Area location a to remove. ; prioritises double colorless energy, then any useful energy, ; then defaults to the first energy card attached if neither ; of those are found. @@ -6347,7 +6355,7 @@ GetEnergyCardToDiscard: ; 2282e (8:682e) ; a = Play Area location to check ; output: ; a = deck index of attached energy card -PickAttachedEnergyCard: ; 22875 (8:6875) +PickAttachedEnergyCardToRemove: ; 22875 (8:6875) ; construct energy list and check if there are any energy cards attached ldh [hTempPlayAreaLocation_ff9d], a call CreateArenaOrBenchEnergyCardList @@ -6570,7 +6578,7 @@ ClearMemory_Bank8: ; 22983 (8:6983) ; sets carry if none are found ; output: ; a = number of energy cards found -CountEnergyCardsInHand: ; 22990 (8:6990) +CountOppEnergyCardsInHand: ; 22990 (8:6990) farcall CreateEnergyCardListFromHand ret c ld b, -1 @@ -6621,6 +6629,7 @@ CalculateWordTensDigit: ; 229b0 (8:69b0) ret ; 0x229c1 +; returns in a division of b by a CalculateBDividedByA_Bank8: ; 229c1 (8:69c1) push bc ld c, a diff --git a/src/wram.asm b/src/wram.asm index 7ff0dfe..e5fc9c6 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -956,6 +956,8 @@ wccc5:: ; ccc5 ds $1 ; *_ATTACK constants for selected attack +; 0 for the first attack (or PKMN Power) +; 1 for the second attack wSelectedAttack:: ; ccc6 ds $1 -- cgit v1.2.3