diff options
author | ElectroDeoxys <ElectroDeoxys@gmail.com> | 2020-04-15 11:42:00 +0100 |
---|---|---|
committer | ElectroDeoxys <ElectroDeoxys@gmail.com> | 2020-04-15 11:42:00 +0100 |
commit | 81c72a30d42eaccd054868f73a2ff0101ed6b5ce (patch) | |
tree | c2b4efa9c04672bfb25319aaa932534e5de24660 /src | |
parent | 064ed473ff7a33b42e663105b94c9503021c11e4 (diff) |
AI Professor Oak routines
Diffstat (limited to 'src')
-rw-r--r-- | src/engine/bank05.asm | 89 | ||||
-rw-r--r-- | src/engine/bank08.asm | 446 |
2 files changed, 508 insertions, 27 deletions
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) |