diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/engine/bank05.asm | 578 | ||||
-rw-r--r-- | src/wram.asm | 46 |
2 files changed, 571 insertions, 53 deletions
diff --git a/src/engine/bank05.asm b/src/engine/bank05.asm index c5c4035..1ff8c6d 100644 --- a/src/engine/bank05.asm +++ b/src/engine/bank05.asm @@ -200,6 +200,21 @@ StoreDefendingPokemonColorWRAndPrizeCards: ; 1411d (5:411d) Func_14145: ; 14145 (5:4145) INCROM $14145, $14184 +; return carry if any of the following is satisfied: +; - deck index in a corresponds to a double colorless energy card; +; - card type in wTempCardType is double colorless energy; +; - card ID in wTempCardID is a Pokémon card that has +; moves that require energy other than its color and +; the deck index in a corresponds to that energy type; +; - card ID is Eevee and a corresponds to an energy type +; of water, fire or lightning; +; - type of card in register a is the same as wTempCardType. +; used for knowing if a given energy card can be discarded +; from a given Pokémon card +; input: +; a = energy card attached to Pokémon to check +; [wTempCardType] = TYPE_ENERGY_* of given Pokémon +; [wTempCardID] = card index of Pokémon card to check Func_14184: ; 14184 (5:4184) push de call GetCardIDFromDeckIndex @@ -238,7 +253,7 @@ Func_14184: ; 14184 (5:4184) jr z, .set_carry .check_type - ld d, $00 + ld d, $00 ; unnecessary? call GetCardType ld d, a ld a, [wTempCardType] @@ -1190,7 +1205,71 @@ Func_1468b: ; 1468b (5:468b) ret ; 0x14786 - INCROM $14786, $1514f +Func_14786: ; 14786 (5:4786) + INCROM $14786, $14c91 + +Func_14c91: ; 14c91 (5:4c91) + call SwapTurn + call CountPrizes + call SwapTurn + cp 3 + ret c + +; player prizes >= 3 + ld a, $59 + call Func_17474 + jr c, .asm_14ccb + ld a, $5e + call Func_17474 + jr c, .asm_14cb4 + ld a, $4c + call Func_17474 + jr c, .asm_14cb4 + jr .asm_14ccb + +.asm_14cb4 + ld a, $59 + ld b, $01 + call Func_155ef + jr nc, .asm_14ccb + ld e, a + call CountNumberOfEnergyCardsAttached + cp 3 + jr nc, .asm_14ccb + ld a, $59 + call Func_174cd + ret + +.asm_14ccb + ld a, $5e + ld b, $01 + call Func_155ef + jr nc, .asm_14cda + ld a, $5e + call Func_174cd + ret + +.asm_14cda + ld a, $4c + ld b, $01 + call Func_155ef + jr nc, .asm_14ce9 + ld a, $4c + call Func_174cd + ret + +.asm_14ce9 + ld a, $4b + ld b, $01 + call Func_155ef + ret nc + ld a, $4b + call Func_174cd + ret +; 0x14cf7 + +Func_14cf7: ; 14cf7 (5:4cf7) + INCROM $14cf7, $1514f ; these seem to be lists of card IDs ; for the AI to look up in their hand @@ -1419,7 +1498,7 @@ Func_158b2: ; 158b2 (5:58b2) or a jp nz, .no_carry xor a - ld [$cdd7], a + ld [wAIPlayEnergyCardForRetreat], a call StoreDefendingPokemonColorWRAndPrizeCards ld a, 128 ; initial retreat score ld [wAIScore], a @@ -1479,7 +1558,7 @@ Func_158b2: ; 158b2 (5:58b2) cp 2 jr nc, .check_prize_count ld a, $01 - ld [$cdd7], a + ld [wAIPlayEnergyCardForRetreat], a .defending_cant_ko call CheckIfNotABossDeckID @@ -1668,15 +1747,17 @@ Func_158b2: ; 158b2 (5:58b2) ld a, 2 call AddToAIScore +; a bench Pokémon was found that can KO +; if this is a boss deck and it's at last prize card +; if arena Pokémon cannot KO, add to AI score +; and set wAIPlayEnergyCardForRetreat to $01 + ld a, [wAIOpponentPrizeCount] cp 2 jr nc, .check_defending_id call CheckIfNotABossDeckID jr c, .check_defending_id -; is boss deck and is at last prize card -; if arena Pokémon cannot KO or cannot use -; its first move, add to AI score xor a ldh [hTempPlayAreaLocation_ff9d], a call CheckIfAnyMoveKnocksOutDefendingCard @@ -1687,7 +1768,7 @@ Func_158b2: ; 158b2 (5:58b2) ld a, 40 call AddToAIScore ld a, $01 - ld [$cdd7], a + ld [wAIPlayEnergyCardForRetreat], a .check_defending_id ld a, DUELVARS_ARENA_CARD @@ -1731,7 +1812,7 @@ Func_158b2: ; 158b2 (5:58b2) ld a, 5 call AddToAIScore ld a, $01 - ld [$cdd7], a + ld [wAIPlayEnergyCardForRetreat], a ; subtract from wAIScore if retreat cost is larger than 1 ; then check if any cards have at least half HP, @@ -2174,20 +2255,27 @@ Func_15b72: ; 15b72 (5:5b72) jp FindHighestBenchScore ; 0x15d4f +; handles AI action of retreating Arena Pokémon +; and chooses which energy cards to discard +; if card can't discard, return carry Func_15d4f: ; 15d4f (5:5d4f) push af - ld a, [$cdd7] + ld a, [wAIPlayEnergyCardForRetreat] or a - jr z, .mysterious_fossil_or_clefairy_doll + jr z, .check_id + +; AI is allowed to play an energy card +; from the hand in order to provide +; the necessary energy for retreat cost ; check status ld a, DUELVARS_ARENA_CARD_STATUS call GetTurnDuelistVariable and CNF_SLP_PRZ cp ASLEEP - jp z, .mysterious_fossil_or_clefairy_doll + jp z, .check_id cp PARALYZED - jp z, .mysterious_fossil_or_clefairy_doll + jp z, .check_id ; if an energy card hasn't been played yet, ; checks if the Pokémon needs just one more energy to retreat @@ -2195,7 +2283,7 @@ Func_15d4f: ; 15d4f (5:5d4f) ; and if there are, play that energy card ld a, [wAlreadyPlayedEnergy] or a - jr nz, .mysterious_fossil_or_clefairy_doll + jr nz, .check_id ld e, PLAY_AREA_ARENA call CountNumberOfEnergyCardsAttached push af @@ -2204,14 +2292,14 @@ Func_15d4f: ; 15d4f (5:5d4f) call GetPlayAreaCardRetreatCost pop bc cp b - jr c, .mysterious_fossil_or_clefairy_doll - jr z, .mysterious_fossil_or_clefairy_doll + jr c, .check_id + jr z, .check_id ; energy attached < retreat cost sub b cp 1 - jr nz, .mysterious_fossil_or_clefairy_doll + jr nz, .check_id call CreateEnergyCardListFromHand - jr c, .mysterious_fossil_or_clefairy_doll + jr c, .check_id ld a, [wDuelTempList] ldh [hTemp_ffa0], a xor a @@ -2219,16 +2307,18 @@ Func_15d4f: ; 15d4f (5:5d4f) ld a, $03 ; OppAction_PlayEnergyCard bank1call AIMakeDecision -.mysterious_fossil_or_clefairy_doll +.check_id ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable call GetCardIDFromDeckIndex ld a, e cp MYSTERIOUS_FOSSIL - jp z, .asm_15e7c + jp z, .mysterious_fossil_or_clefairy_doll cp CLEFAIRY_DOLL - jp z, .asm_15e7c + jp z, .mysterious_fossil_or_clefairy_doll +; if card is Asleep or Paralyzed, set carry and exit +; else, load the status in hTemp_ffa0 pop af ldh [hTempPlayAreaLocation_ffa1], a ld a, DUELVARS_ARENA_CARD_STATUS @@ -2241,24 +2331,29 @@ Func_15d4f: ; 15d4f (5:5d4f) jp z, .set_carry ld a, b ldh [hTemp_ffa0], a - ld a, $ff ldh [hTempRetreatCostCards], a + +; check energy required to retreat +; if the cost is 0, retreat right away xor a ldh [hTempPlayAreaLocation_ff9d], a call GetPlayAreaCardRetreatCost ld [wTempCardRetreatCost], a or a jp z, .retreat + +; if cost > 0 and number of energy cards attached == cost +; discard them all xor a call CreateArenaOrBenchEnergyCardList - ld e, $00 + ld e, PLAY_AREA_ARENA call GetPlayAreaCardAttachedEnergies ld a, [wTotalAttachedEnergies] ld c, a ld a, [wTempCardRetreatCost] cp c - jr nz, .asm_15df5 + jr nz, .choose_energy_discard ld hl, hTempRetreatCostCards ld de, wDuelTempList @@ -2270,7 +2365,9 @@ Func_15d4f: ; 15d4f (5:5d4f) jr nz, .loop_1 jp .retreat -.asm_15df5 +; if cost > 0 and number of energy cards attached > cost +; choose energy cards to discard according to color +.choose_energy_discard ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable call GetCardIDFromDeckIndex @@ -2282,15 +2379,18 @@ Func_15d4f: ; 15d4f (5:5d4f) ld [wTempCardType], a ld a, [wTempCardRetreatCost] ld c, a + +; first, look for and discard double colorless energy +; if retreat cost is >= 2 ld hl, wDuelTempList ld de, hTempRetreatCostCards .loop_2 ld a, c cp 2 - jr c, .asm_15e37 + jr c, .energy_not_same_color ld a, [hli] cp $ff - jr z, .asm_15e37 + jr z, .energy_not_same_color ld [de], a push de call GetCardIDFromDeckIndex @@ -2305,30 +2405,39 @@ Func_15d4f: ; 15d4f (5:5d4f) dec c dec c jr nz, .loop_2 - jr .asm_15e70 - -.asm_15e37 + jr .end_retreat_list + +; second, shuffle attached cards and discard energy cards +; that are not of the same type as the Pokémon +; the exception for this are cards that are needed for +; some attacks but are not of the same color as the Pokémon +; (i.e. Psyduck's Headache attack) +; and energy cards attached to Eevee corresponding to a +; color of any of its evolutions (water, fire, lightning) +.energy_not_same_color ld hl, wDuelTempList call CountCardsInDuelTempList call ShuffleCards -.asm_15e40 +.loop_3 ld a, [hli] cp $ff - jr z, .asm_15e56 + jr z, .any_energy ld [de], a call Func_14184 - jr c, .asm_15e40 + jr c, .loop_3 ld a, [de] call RemoveCardFromDuelTempList dec hl inc de dec c - jr nz, .asm_15e40 - jr .asm_15e70 + jr nz, .loop_3 + jr .end_retreat_list -.asm_15e56 +; third, discard any card until +; cost requirement is met +.any_energy ld hl, wDuelTempList -.loop_3 +.loop_4 ld a, [hli] cp $ff jr z, .set_carry @@ -2339,13 +2448,14 @@ Func_15d4f: ; 15d4f (5:5d4f) ld a, e pop de cp DOUBLE_COLORLESS_ENERGY - jr nz, .asm_15e6d + jr nz, .not_double_colorless dec c - jr z, .asm_15e70 -.asm_15e6d + jr z, .end_retreat_list +.not_double_colorless dec c - jr nz, .loop_3 -.asm_15e70 + jr nz, .loop_4 + +.end_retreat_list ld a, $ff ld [de], a @@ -2358,14 +2468,19 @@ Func_15d4f: ; 15d4f (5:5d4f) scf ret -.asm_15e7c: +; handle Mysterious Fossil and Clefairy Doll +; if there are bench Pokémon, use effect to discard card +; this is equivalent to using its Pokémon Power +.mysterious_fossil_or_clefairy_doll: ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA call GetTurnDuelistVariable cp 2 - jr nc, .asm_15e88 + jr nc, .has_bench + ; doesn't have any bench pop af jr .set_carry -.asm_15e88 + +.has_bench ld a, DUELVARS_ARENA_CARD call GetTurnDuelistVariable ldh [hTempCardIndex_ff9f], a @@ -3519,10 +3634,295 @@ CheckForEvolutionInDeck: ; 16451 (5:6451) ; 0x16488 Func_16488 ; 16488 (5:6488) - INCROM $16488, $164e8 + INCROM $16488, $164d3 + +; copies bench AI score to wcddd +; and loads in wAIscore value in wcde3 +Func_164d3: ; 164d3 (5:64d3) + push af + ld de, wBenchAIScore + ld hl, wcddd + ld b, MAX_PLAY_AREA_POKEMON +.loop + ld a, [hli] + ld [de], a + inc de + dec b + jr nz, .loop + ld a, [hl] + ld [wAIScore], a + pop af + ret +; 0x164e8 + +Func_164e8: ; 164e8 (5:64e8) + xor a + ld [wcdd8], a + call CreateEnergyCardListFromHand + jr nc, .has_energy + +; no energy + ld a, [wcdd8] + or a + jr z, .exit + ; can this even be reached? + jp Func_164d3 +.exit + or a + ret + +.has_energy + ld a, $80 + ld b, MAX_PLAY_AREA_POKEMON + ld hl, wcde4 +.loop + ld [hli], a + dec b + jr nz, .loop + + call Func_175bd + ld b, PLAY_AREA_ARENA + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + ld c, a + +.asm_16512 + push bc + ld a, b + ldh [hTempPlayAreaLocation_ff9d], a + ld a, $80 + ld [wAIScore], a + ld a, $ff + ld [wCurCardPlayAreaLocation], a + ld a, [wcdd8] + and $02 + jr nz, .check_venusaur + + call CreateHandCardList + ldh a, [hTempPlayAreaLocation_ff9d] + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + ld [wCurCardCanAttack], a + call GetMovesEnergyCostBits + ld hl, wDuelTempList + call CheckEnergyFlagsNeededInList + jp nc, .asm_16661 + ld a, [wCurCardCanAttack] + call CheckForEvolutionInList + jr nc, .asm_16552 + ld [wCurCardPlayAreaLocation], a + ld a, 2 + call AddToAIScore + jr .check_venusaur +.asm_16552 + ld a, [wCurCardCanAttack] + call CheckForEvolutionInDeck + jr nc, .check_venusaur + ld a, 1 + call AddToAIScore + +; if there's no Muk in Play Area +; and there's Venusaur1, add to AI score +.check_venusaur + ld a, MUK + call CountPokemonIDInBothPlayAreas + jr c, .asm_16572 + ld a, VENUSAUR2 + call CountPokemonIDInPlayArea + jr nc, .asm_16572 + ld a, 1 + call AddToAIScore + +.asm_16572 + ldh a, [hTempPlayAreaLocation_ff9d] + or a + jr nz, .bench + +; arena + ld a, [wcda7] + bit 7, a + jr z, .check_arena_hp + ld a, 5 + call SubFromAIScore + jr .check_defending_can_ko + +; lower AI score if poison/double poison +; will KO Pokémon between turns +; or if the defending Pokémon can KO +.check_arena_hp + ld a, 4 + call AddToAIScore + + ld a, DUELVARS_ARENA_CARD_HP + call GetTurnDuelistVariable + call CalculateTensDigit + cp 3 + jr nc, .check_defending_can_ko +; hp < 30 + cp 2 + jr z, .has_20_hp +; hp = 10 + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and POISONED + jr z, .check_defending_can_ko + jr .poison_will_ko +.has_20_hp + ld a, DUELVARS_ARENA_CARD_STATUS + call GetTurnDuelistVariable + and DOUBLE_POISONED + jr z, .check_defending_can_ko +.poison_will_ko + ld a, 10 + call SubFromAIScore + jr .check_bench +.check_defending_can_ko + call CheckIfDefendingPokemonCanKnockOut + jr nc, .asm_165e1 + ld a, 10 + call SubFromAIScore + +; if either poison will KO or +; defending Pokémon can KO, +; check if there are bench Pokémon +; if there are not, add AI score +.check_bench + ld a, DUELVARS_NUMBER_OF_POKEMON_IN_PLAY_AREA + call GetTurnDuelistVariable + dec a + jr nz, .asm_165e1 + ld a, 6 + call AddToAIScore + jr .asm_165e1 -Func_164e8 ; 164e8 (5:64e8) - INCROM $164e8, $169f8 +; lower AI score by 3 - (bench HP)/10 +; if bench HP < 30 +.bench + add DUELVARS_ARENA_CARD_HP + call GetTurnDuelistVariable + call CalculateTensDigit + cp 3 + jr nc, .asm_165e1 +; hp < 30 + ld b, a + ld a, 3 + sub b + call SubFromAIScore + +.asm_165e1 + ld a, [wcdb3] + or a + jr z, .asm_1662f + ld h, a + ld a, [wcdb2] + ld l, a + + push hl + ldh a, [hTempPlayAreaLocation_ff9d] + add DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + call GetCardIDFromDeckIndex + pop hl +.asm_165f8 + ld a, [hli] + or a + jr z, .asm_1662f + cp e + jr nz, .asm_1662b + ld a, [hli] + ld d, a + push de + ldh a, [hTempPlayAreaLocation_ff9d] + ld e, a + call GetPlayAreaCardAttachedEnergies + ld a, [wTotalAttachedEnergies] + pop de + cp d + jr c, .asm_16616 + ld a, $0a + call SubFromAIScore + jr .asm_16661 +.asm_16616 + ld a, [hli] + cp $80 + jr c, .asm_16622 + sub $80 + call AddToAIScore + jr .asm_1662f +.asm_16622 + ld d, a + ld a, $80 + sub d + call SubFromAIScore + jr .asm_1662f +.asm_1662b + inc hl + inc hl + jr .asm_165f8 + +.asm_1662f + call CheckIfNotABossDeckID + jr c, .asm_16653 + call Func_174f2 + ldh a, [hTempPlayAreaLocation_ff9d] + ld c, a + ld b, $00 + ld hl, wcde4 + add hl, bc + ld a, [hl] + cp $80 + jr c, .asm_1664c + sub $80 + call AddToAIScore + jr .asm_16653 +.asm_1664c + ld b, a + ld a, $80 + sub b + call SubFromAIScore +.asm_16653 + ld a, 1 + call AddToAIScore + + xor a + call Func_16695 + ld a, $01 + call Func_16695 +.asm_16661 + ldh a, [hTempPlayAreaLocation_ff9d] + ld c, a + ld b, $00 + ld hl, wBenchAIScore + add hl, bc + ld a, [wAIScore] + ld [hl], a + pop bc + inc b + dec c + jp nz, .asm_16512 + call Func_167b5 + jp nc, Func_1668a + ld a, [wcdd8] + or a + jr z, .asm_16684 + scf + jp Func_164d3 +.asm_16684 + call CreateEnergyCardListFromHand + jp Func_1689f +; 0x1668a + +Func_1668a ; 1668a (5:668a) + INCROM $1668a, $16695 + +Func_16695 ; 16695 (5:6695) + INCROM $16695, $167b5 + +Func_167b5 ; 167b5 (5:67b5) + INCROM $167b5, $1689f + +Func_1689f ; 1689f (5:689f) + INCROM $1689f, $169f8 Func_169f8 ; 169f8 (5:69f8) INCROM $169f8, $170c9 @@ -3864,4 +4264,84 @@ CheckIfNotABossDeckID: ; 17426 (5:7426) ; 0x1743b Func_1743b ; 1743b (5:743b) - INCROM $1743b, $18000
\ No newline at end of file + INCROM $1743b, $17474 + +Func_17474: ; 17474 (5:7474) + ld [wcdf9], a + ldh a, [hTempPlayAreaLocation_ff9d] + ld d, a + ld a, [wSelectedMoveIndex] + ld e, a + push de + ld a, DUELVARS_ARENA_CARD + call GetTurnDuelistVariable + lb bc, 0, 0 + push hl + +.loop + inc c + pop hl + ld a, [hli] + push hl + cp $ff + jr z, .asm_174bf + ld d, a + push de + push bc + call LoadCardDataToBuffer1_FromDeckIndex + pop bc + ld a, c + add DUELVARS_ARENA_CARD_HP + call GetTurnDuelistVariable + ld d, a + ld a, [wLoadedCard1HP] + rrca + cp d + pop de + jr nc, .loop + ld a, [wLoadedCard1ID] + ld hl, wcdf9 + cp [hl] + jr nz, .loop + + ld a, c + ldh [hTempPlayAreaLocation_ff9d], a + ld a, $01 + ld [wSelectedMoveIndex], a + push bc + call CheckIfCardCanUseSelectedMove + pop bc + jr c, .loop + inc b +.asm_174bf + pop hl + pop de + ld a, e + ld [wSelectedMoveIndex], a + ld a, d + ldh [hTempPlayAreaLocation_ff9d], a + ld a, b + or a + ret z + scf + ret +; 0x174cd + +Func_174cd ; 174cd (5:74cd) + INCROM $174cd, $174f2 + +Func_174f2 ; 174f2 (5:74f2) + INCROM $174f2, $175bd + +Func_175bd: ; 175bd (5:75bd) + ld a, [wOpponentDeckID] + cp LEGENDARY_ARTICUNO_DECK_ID + jr z, .articuno_deck + ret +.articuno_deck + call Func_14c91 + ret +; 0x175c9 + +Func_175c9 ; 175c9 (5:75c9) + INCROM $175c9, $18000
\ No newline at end of file diff --git a/src/wram.asm b/src/wram.asm index d2a5ac5..0ef674e 100644 --- a/src/wram.asm +++ b/src/wram.asm @@ -1190,7 +1190,14 @@ wcda7:: ; cda7 wcdae:: ; cdae ds $2 - ds $5 + ds $2 + +wcdb2:: ; cdb2 + ds $1 +wcdb3:: ; cdb3 + ds $1 + + ds $1 ; information about various properties of ; loaded move for AI calculations @@ -1243,7 +1250,24 @@ wAIOpponentPrizeCount:: ; cdd3 wTempCardIDToLook:: ; cdd4 ds $1 - ds $5 +wcdd5:: ; cdd5 + ds $1 + +wcdd6:: ; cdd6 + ds $1 + +; whether AI is allowed to play an energy card +; from the hand in order to retreat arena card +; $00 = not allowed +; $01 = allowed +wAIPlayEnergyCardForRetreat:: ; cdd7 + ds $1 + +wcdd8:: ; cdd8 + ds $1 + +wcdd9:: ; cdd9 + ds $1 wcdda:: ; cdda ds $1 @@ -1254,7 +1278,16 @@ wcddb:: ; cddb wcddc:: ; cddc ds $1 - ds $14 +wcddd:: ; cddd + ds MAX_PLAY_AREA_POKEMON + +wcde3:: ; cde3 + ds $1 + +wcde4:: ; cde4 + ds MAX_PLAY_AREA_POKEMON + + ds $7 ; a PLAY_AREA_* constant (0: arena card, 1-5: bench card) ; used by the AI to temporarily store card location @@ -1279,7 +1312,12 @@ wTempAIPokemonCard:: ; cdf3 wCurCardCanKO:: ; cdf4 ds $1 - ds $b + ds $4 + +wcdf9:: ; cdf9 + ds $1 + + ds $6 wce00:: ; ce00 ds $1 |