Identify AI info in card data, rename AI score routines

This commit is contained in:
ElectroDeoxys 2024-11-11 22:29:51 +00:00
parent e4cf3fc950
commit 061ea37b8d
18 changed files with 561 additions and 523 deletions

View File

@ -63,7 +63,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
jr nc, .check_evolution
.atk_kos_defending
ld a, 20
call AddToAIScore
call AIEncourage
-; this is possibly a bug.
-; this is an identical check as above to test whether this card is active.
@ -72,7 +72,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
or a
jr nz, .check_evolution
ld a, 10
call AddToAIScore
call AIEncourage
...
```

View File

@ -69,12 +69,12 @@ DEF CARD_DATA_WEAKNESS EQU $33
DEF CARD_DATA_RESISTANCE EQU $34
DEF CARD_DATA_CATEGORY EQU $35
DEF CARD_DATA_POKEDEX_NUMBER EQU $37
DEF CARD_DATA_UNKNOWN1 EQU $38
DEF CARD_DATA_UNUSED EQU $38
DEF CARD_DATA_LEVEL EQU $39
DEF CARD_DATA_LENGTH EQU $3a
DEF CARD_DATA_WEIGHT EQU $3c
DEF CARD_DATA_PKMN_DESCRIPTION EQU $3e
DEF CARD_DATA_UNKNOWN2 EQU $40
DEF CARD_DATA_AI_INFO EQU $40
DEF PKMN_CARD_DATA_LENGTH EQU $41
@ -251,3 +251,13 @@ DEF SECOND_ATTACK EQU $1
; has limit on attached energy cards boost.
DEF MAX_ENERGY_BOOST_IS_LIMITED EQU $2
DEF MAX_ENERGY_BOOST_IS_NOT_LIMITED EQU $3
; CARD_DATA_AI_INFO constants
DEF AI_INFO_BENCH_UTILITY EQU $1
DEF AI_INFO_ENCOURAGE_EVO EQU $2
DEF AI_INFO_UNK_03 EQU $3
DEF AI_INFO_UNK_05 EQU $5
DEF AI_INFO_UNK_08 EQU $8
DEF HAS_EVOLUTION_F EQU 4
DEF HAS_EVOLUTION EQU 1 << HAS_EVOLUTION_F

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@ MACRO ai_trainer_card_logic
ENDM
AITrainerCardLogic:
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_07, POTION, AIDecide_Potion1, AIPlay_Potion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_10, POTION, AIDecide_Potion2, AIPlay_Potion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_07, POTION, AIDecide_Potion_Phase07, AIPlay_Potion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_10, POTION, AIDecide_Potion_Phase10, AIPlay_Potion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_08, SUPER_POTION, AIDecide_SuperPotion1, AIPlay_SuperPotion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_11, SUPER_POTION, AIDecide_SuperPotion2, AIPlay_SuperPotion
ai_trainer_card_logic AI_TRAINER_CARD_PHASE_13, DEFENDER, AIDecide_Defender1, AIPlay_Defender

View File

@ -240,7 +240,7 @@ GetAIScoreOfAttack:
jr .check_damage
.can_ko
ld a, 20
call AddToAIScore
call AIEncourage
; raise AI score by the number of damage counters that this attack deals.
; if no damage is dealt, subtract AI score. in case wDamage is zero
@ -255,17 +255,17 @@ GetAIScoreOfAttack:
or a
jr z, .no_damage
call ConvertHPToDamageCounters_Bank5
call AddToAIScore
call AIEncourage
jr .check_recoil
.no_damage
ld a, $01
ld [wAIAttackIsNonDamaging], a
call SubFromAIScore
call AIDiscourage
ld a, [wAIMaxDamage]
or a
jr z, .no_max_damage
ld a, 2
call AddToAIScore
call AIEncourage
xor a
ld [wAIAttackIsNonDamaging], a
.no_max_damage
@ -273,7 +273,7 @@ GetAIScoreOfAttack:
call CheckLoadedAttackFlag
jr nc, .check_recoil
ld a, 2
call AddToAIScore
call AIEncourage
; handle recoil attacks (low and high recoil).
.check_recoil
@ -293,7 +293,7 @@ GetAIScoreOfAttack:
call ApplyDamageModifiers_DamageToSelf
ld a, e
call ConvertHPToDamageCounters_Bank5
call SubFromAIScore
call AIDiscourage
push de
ld a, ATTACK_FLAG1_ADDRESS | HIGH_RECOIL_F
@ -309,7 +309,7 @@ GetAIScoreOfAttack:
jp nz, .check_defending_can_ko
.kos_self
ld a, 10
call SubFromAIScore
call AIDiscourage
.high_recoil
; dismiss this attack if no benched Pokémon
@ -340,7 +340,7 @@ GetAIScoreOfAttack:
.encourage_high_recoil_atk
ld a, 20
call AddToAIScore
call AIEncourage
jp .done
; Zapping Selfdestruct deck only uses this attack
@ -436,7 +436,7 @@ GetAIScoreOfAttack:
; attack causes CPU to draw all prize cards
.wins_the_duel
ld a, 20
call AddToAIScore
call AIEncourage
jp .done
; subtract from AI score number of own benched Pokémon KO'd
@ -446,13 +446,13 @@ GetAIScoreOfAttack:
or a
jr z, .count_player_ko_bench
dec a
call SubFromAIScore
call AIDiscourage
; add to AI score number of player benched Pokémon KO'd
.count_player_ko_bench
pop bc
ld a, b
call AddToAIScore
call AIEncourage
jr .check_defending_can_ko
; local function that gets called to determine damage to
@ -515,12 +515,12 @@ GetAIScoreOfAttack:
ld [wSelectedAttack], a
jr nc, .check_discard
ld a, 5
call AddToAIScore
call AIEncourage
ld a, [wAIAttackIsNonDamaging]
or a
jr z, .check_discard
ld a, 5
call SubFromAIScore
call AIDiscourage
; subtract from AI score if this attack requires
; discarding any energy cards.
@ -535,16 +535,16 @@ GetAIScoreOfAttack:
call CheckLoadedAttackFlag
jr nc, .asm_16ca6
ld a, 1
call SubFromAIScore
call AIDiscourage
ld a, [wLoadedAttackEffectParam]
call SubFromAIScore
call AIDiscourage
.asm_16ca6
ld a, ATTACK_FLAG2_ADDRESS | FLAG_2_BIT_6_F
call CheckLoadedAttackFlag
jr nc, .check_nullify_flag
ld a, [wLoadedAttackEffectParam]
call AddToAIScore
call AIEncourage
; encourage attack if it has a nullify or weaken attack effect.
.check_nullify_flag
@ -552,7 +552,7 @@ GetAIScoreOfAttack:
call CheckLoadedAttackFlag
jr nc, .check_draw_flag
ld a, 1
call AddToAIScore
call AIEncourage
; encourage attack if it has an effect to draw a card.
.check_draw_flag
@ -560,7 +560,7 @@ GetAIScoreOfAttack:
call CheckLoadedAttackFlag
jr nc, .check_heal_flag
ld a, 1
call AddToAIScore
call AIEncourage
.check_heal_flag
ld a, ATTACK_FLAG2_ADDRESS | HEAL_USER_F
@ -591,11 +591,11 @@ GetAIScoreOfAttack:
call GetCardDamageAndMaxHP
call ConvertHPToDamageCounters_Bank5
pop bc
cp b ; wLoadedAttackEffectParam
cp b
jr c, .add_heal_score
ld a, b
.add_heal_score
call AddToAIScore
call AIEncourage
.check_status_effect
ld a, DUELVARS_ARENA_CARD
@ -630,11 +630,11 @@ GetAIScoreOfAttack:
call CheckLoadedAttackFlag
jr nc, .check_sleep
ld a, 2
call SubFromAIScore
call AIDiscourage
jr .check_sleep
.add_poison_score
ld a, 2
call AddToAIScore
call AIEncourage
; encourage sleep-inducing attack if other Pokémon isn't asleep.
.check_sleep
@ -646,7 +646,7 @@ GetAIScoreOfAttack:
cp ASLEEP
jr z, .check_paralysis
ld a, 1
call AddToAIScore
call AIEncourage
; encourage paralysis-inducing attack if other Pokémon isn't asleep.
; otherwise, if other Pokémon is asleep, discourage attack.
@ -659,11 +659,11 @@ GetAIScoreOfAttack:
cp ASLEEP
jr z, .sub_prz_score
ld a, 1
call AddToAIScore
call AIEncourage
jr .check_confusion
.sub_prz_score
ld a, 1
call SubFromAIScore
call AIDiscourage
; encourage confuse-inducing attack if other Pokémon isn't asleep
; or confused already.
@ -682,11 +682,11 @@ GetAIScoreOfAttack:
cp CONFUSED
jr z, .check_if_confused
ld a, 1
call AddToAIScore
call AIEncourage
jr .check_if_confused
.sub_cnf_score
ld a, 1
call SubFromAIScore
call AIDiscourage
; if this Pokémon is confused, subtract from score.
.check_if_confused
@ -696,7 +696,7 @@ GetAIScoreOfAttack:
cp CONFUSED
jr nz, .handle_special_atks
ld a, 1
call SubFromAIScore
call AIDiscourage
; SPECIAL_AI_HANDLING marks attacks that the AI handles individually.
; each attack has its own checks and modifies AI score accordingly.
@ -708,13 +708,13 @@ GetAIScoreOfAttack:
cp $80
jr c, .negative_score
sub $80
call AddToAIScore
call AIEncourage
jr .done
.negative_score
ld b, a
ld a, $80
sub b
call SubFromAIScore
call AIDiscourage
.done
ret

View File

@ -9,12 +9,10 @@ INCLUDE "engine/duel/ai/decks/unreferenced.asm"
; [wSelectedAttack] = attack index that KOs
CheckIfAnyAttackKnocksOutDefendingCard:
xor a ; FIRST_ATTACK_OR_PKMN_POWER
call CheckIfAttackKnocksOutDefendingCard
call .CheckAttack
ret c
ld a, SECOND_ATTACK
; fallthrough
CheckIfAttackKnocksOutDefendingCard:
.CheckAttack:
call EstimateDamage_VersusDefendingCard
ld a, DUELVARS_ARENA_CARD_HP
call GetNonTurnDuelistVariable
@ -59,7 +57,7 @@ FindHighestBenchScore:
ld e, c
ld d, c
ld hl, wPlayAreaAIScore + 1
jp .next
jp .next ; can be jr
.loop
ld a, [hli]
@ -78,23 +76,23 @@ FindHighestBenchScore:
ret
; adds a to wAIScore
; if there's overflow, it's capped at $ff
; if there's overflow, it's capped at 255
; output:
; a = a + wAIScore (capped at $ff)
AddToAIScore:
; a = a + wAIScore (capped at 255)
AIEncourage:
push hl
ld hl, wAIScore
add [hl]
jr nc, .no_cap
ld a, $ff
ld a, 255
.no_cap
ld [hl], a
pop hl
ret
; subs a from wAIScore
; if there's underflow, it's capped at $00
SubFromAIScore:
; if there's underflow, it's capped at 0
AIDiscourage:
push hl
push de
ld e, a
@ -105,7 +103,7 @@ SubFromAIScore:
sub e
ld [hl], a
jr nc, .done
ld [hl], $00
ld [hl], 0
.done
pop de
pop hl
@ -631,7 +629,7 @@ CreateEnergyCardListFromHand:
call GetTurnDuelistVariable
ld c, a
inc c
ld l, LOW(wOpponentHand)
ld l, DUELVARS_HAND
jr .decrease
.loop
@ -1585,7 +1583,7 @@ SortTempHandByIDList:
CheckEnergyFlagsNeededInList:
ld e, a
ld hl, wDuelTempList
.next_card
.loop_cards
ld a, [hli]
cp $ff
jr z, .no_carry
@ -1626,7 +1624,7 @@ CheckEnergyFlagsNeededInList:
jr .check_energy
.colorless
cp DOUBLE_COLORLESS_ENERGY
jr nz, .next_card
jr nz, .loop_cards
ld a, COLORLESS_F
; if energy card matches required energy, return carry
@ -1634,7 +1632,7 @@ CheckEnergyFlagsNeededInList:
ld d, e
and e
ld e, d
jr z, .next_card
jr z, .loop_cards
scf
ret
.no_carry
@ -1652,12 +1650,12 @@ CheckEnergyFlagsNeededInList:
GetAttacksEnergyCostBits:
call LoadCardDataToBuffer2_FromDeckIndex
ld hl, wLoadedCard2Atk1EnergyCost
call GetEnergyCostBits
call .GetEnergyCostBits
ld b, a
push bc
ld hl, wLoadedCard2Atk2EnergyCost
call GetEnergyCostBits
call .GetEnergyCostBits
pop bc
or b
ret
@ -1670,7 +1668,7 @@ GetAttacksEnergyCostBits:
; [hl] = Loaded card attack energy cost
; output:
; a = bits of each energy requirement
GetEnergyCostBits:
.GetEnergyCostBits:
ld c, $00
ld a, [hli]
ld b, a
@ -1892,10 +1890,9 @@ LookForCardThatIsKnockedOutOnDevolution:
; returns carry if the following conditions are met:
; - arena card HP >= half max HP
; - arena card Unknown2's 4 bit is not set or
; is set but there's no evolution of card in hand/deck
; - arena card cannot potentially evolve
; - arena card can use second attack
CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondAttack:
CheckIfArenaCardIsFullyPowered:
ld a, DUELVARS_ARENA_CARD
call GetTurnDuelistVariable
ld d, a
@ -1910,8 +1907,8 @@ CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondAttack:
pop de
jr nc, .no_carry
ld a, [wLoadedCard1Unknown2]
and %00010000
ld a, [wLoadedCard1AIInfo]
and HAS_EVOLUTION
jr z, .check_second_attack
ld a, d
call CheckCardEvolutionInHandOrDeck
@ -1981,10 +1978,9 @@ CountNumberOfSetUpBenchPokemon:
pop de
jr nc, .next
ld a, [wLoadedCard1Unknown2]
and $10
ld a, [wLoadedCard1AIInfo]
and HAS_EVOLUTION
jr z, .check_second_attack
ld a, d
push bc
call CheckCardEvolutionInHandOrDeck
@ -1994,6 +1990,9 @@ CountNumberOfSetUpBenchPokemon:
.check_second_attack
ld a, c
ldh [hTempPlayAreaLocation_ff9d], a
; bug, there is an assumption that the card
; has a second attack, but it may be the case
; that it doesn't, which will return carry
ld a, SECOND_ATTACK
ld [wSelectedAttack], a
push bc
@ -2107,7 +2106,6 @@ AISelectSpecialAttackParameters:
; store the deck index of energy card found
ld a, b
ldh [hTempPlayAreaLocation_ffa1], a
; fallthrough
.set_carry_2
scf
@ -2132,6 +2130,7 @@ AISelectSpecialAttackParameters:
or a
jp z, .no_carry ; can be jr
; if none were found in Deck, return carry...
ld a, CARD_LOCATION_DECK
ld e, LIGHTNING_ENERGY
@ -2356,13 +2355,13 @@ CheckIfDefendingPokemonCanKnockOut:
ld [wAISecondAttackDamage], a
; first attack
call CheckIfDefendingPokemonCanKnockOutWithAttack
call .CheckAttack
jr nc, .second_attack
ld a, [wDamage]
ld [wAIFirstAttackDamage], a
.second_attack
ld a, SECOND_ATTACK
call CheckIfDefendingPokemonCanKnockOutWithAttack
call .CheckAttack
jr nc, .return_if_neither_kos
ld a, [wDamage]
ld [wAISecondAttackDamage], a
@ -2389,7 +2388,7 @@ CheckIfDefendingPokemonCanKnockOut:
; input:
; a = attack index
; [hTempPlayAreaLocation_ff9d] = location of card to check
CheckIfDefendingPokemonCanKnockOutWithAttack:
.CheckAttack:
ld [wSelectedAttack], a
ldh a, [hTempPlayAreaLocation_ff9d]
push af
@ -2411,10 +2410,10 @@ CheckIfDefendingPokemonCanKnockOutWithAttack:
call GetTurnDuelistVariable
ld hl, wDamage
sub [hl]
jr z, .set_carry
jr z, .can_ko
ret
.set_carry
.can_ko
scf
ret
@ -2515,7 +2514,7 @@ AIChooseRandomlyNotToDoAction:
; output:
; carry set if the above requirements are met
CheckForBenchIDAtHalfHPAndCanUseSecondAttack:
ld [wcdf9], a
ld [wSamePokemonCardID], a
ldh a, [hTempPlayAreaLocation_ff9d]
ld d, a
ld a, [wSelectedAttack]
@ -2549,7 +2548,7 @@ CheckForBenchIDAtHalfHPAndCanUseSecondAttack:
jr nc, .loop
; half max HP < current HP
ld a, [wLoadedCard1ID]
ld hl, wcdf9
ld hl, wSamePokemonCardID
cp [hl]
jr nz, .loop
@ -2606,107 +2605,106 @@ RaiseAIScoreToAllMatchingIDsInBench:
pop hl
jr .loop
; goes through each play area Pokémon, and
; for all cards of the same ID, determine which
; card has highest value calculated from Func_17583
; the card with highest value gets increased wPlayAreaEnergyAIScore
; while all others get decreased wPlayAreaEnergyAIScore
Func_174f2:
; used by AI to determine which Pokémon it should favor in the bench
; in order to attach an energy card from the hand, in case there are repeats
; if there is repeated Pokémon in bench, then increase wPlayAreaEnergyAIScore
; from the Pokémon with less damage and more energy cards,
; and decrease from all others
HandleAIEnergyScoringForRepeatedBenchPokemon:
; clears wSamePokemonEnergyScoreHandled
ld a, MAX_PLAY_AREA_POKEMON
ld hl, wcdfa
ld hl, wSamePokemonEnergyScoreHandled
call ClearMemory_Bank5
ld a, DUELVARS_BENCH
call GetTurnDuelistVariable
ld e, 0
.loop_play_area
.loop_bench
; clears wSamePokemonEnergyScore
push hl
ld a, MAX_PLAY_AREA_POKEMON
ld hl, wcdea
ld hl, wSamePokemonEnergyScore
call ClearMemory_Bank5
pop hl
inc e
ld a, [hli]
cp $ff
ret z
ret z ; done looping bench
ld [wcdf9], a
ld [wSamePokemonCardID], a ; deck index
; checks wSamePokemonEnergyScoreHandled of location in e
; if != 0, go to next in play area
push de
push hl
; checks wcdfa + play area location in e
; if != 0, go to next in play area
ld d, $00
ld hl, wcdfa
ld hl, wSamePokemonEnergyScoreHandled
add hl, de
ld a, [hl]
or a
pop hl
pop de
jr nz, .loop_play_area
jr nz, .loop_bench ; already handled
; loads wcdf9 with card ID
; and call Func_17583
; store this card's ID
push de
ld a, [wcdf9]
ld a, [wSamePokemonCardID]
call GetCardIDFromDeckIndex
ld a, e
ld [wcdf9], a
ld [wSamePokemonCardID], a
pop de
; calculate score of this Pokémon
; and all cards with same ID
push hl
push de
call Func_17583
; check play area Pokémon ahead
; if there is a card with the same ID,
; call Func_17583 for it as well
.loop_1
call .CalculateScore
.loop_search_same_card_id
inc e
ld a, [hli]
cp $ff
jr z, .check_if_repeated_id
jr z, .tally_repeated_pokemon
push de
call GetCardIDFromDeckIndex
ld a, [wcdf9]
ld a, [wSamePokemonCardID]
cp e
pop de
jr nz, .loop_1
call Func_17583
jr .loop_1
jr nz, .loop_search_same_card_id
call .CalculateScore
jr .loop_search_same_card_id
; if there are more than 1 of the same ID
; in play area, iterate bench backwards
; and determines which card has highest
; score in wcdea
.check_if_repeated_id
call Func_175a8
.tally_repeated_pokemon
call .CountNumberOfCardsWithSameID
jr c, .next
; has repeated card IDs in bench
; find which one has highest score
lb bc, 0, 0
ld hl, wcdea + MAX_BENCH_POKEMON
ld d, MAX_PLAY_AREA_POKEMON
ld hl, wSamePokemonEnergyScore + PLAY_AREA_BENCH_5
ld d, PLAY_AREA_BENCH_5 + 1
.loop_2
dec d
jr z, .asm_17560
jr z, .got_highest_score
ld a, [hld]
cp b
jr c, .loop_2
ld b, a
ld c, d
ld b, a ; highest score
ld c, d ; play area location
jr .loop_2
; c = play area location of highest score
; decrease wPlayAreaEnergyAIScore score for all cards with same ID
; except for the one with highest score
; increase wPlayAreaEnergyAIScore score for card with highest ID
.asm_17560
; decrease wPlayAreaEnergyAIScore score for all cards with same ID
.got_highest_score
ld hl, wPlayAreaEnergyAIScore
ld de, wcdea
ld de, wSamePokemonEnergyScore
ld b, PLAY_AREA_ARENA
.loop_3
ld a, c
cp b
jr z, .card_with_highest
ld a, [de]
ld a, [de] ; score
or a
jr z, .check_next
; decrease score
@ -2727,13 +2725,13 @@ Func_174f2:
.next
pop de
pop hl
jp .loop_play_area
jp .loop_bench
; loads wcdea + play area location in e
; loads wSamePokemonEnergyScore + play area location in e
; with energy * 2 + $80 - floor(dam / 10)
; loads wcdfa + play area location in e
; loads wSamePokemonEnergyScoreHandled + play area location in e
; with $01
Func_17583:
.CalculateScore:
push hl
push de
call GetCardDamageAndMaxHP
@ -2748,21 +2746,21 @@ Func_17583:
pop de
push de
ld d, $00
ld hl, wcdea
ld hl, wSamePokemonEnergyScore
add hl, de
ld [hl], a
ld hl, wcdfa
ld hl, wSamePokemonEnergyScoreHandled
add hl, de
ld [hl], $01
pop de
pop hl
ret
; counts how many play area locations in wcdea
; counts how many play area locations in wSamePokemonEnergyScore
; are != 0, and outputs result in a
; also returns carry if result is < 2
Func_175a8:
ld hl, wcdea
.CountNumberOfCardsWithSameID:
ld hl, wSamePokemonEnergyScore
ld d, $00
ld e, MAX_PLAY_AREA_POKEMON + 1
.loop

View File

@ -94,13 +94,11 @@ EstimateDamage_VersusDefendingCard:
; [hTempPlayAreaLocation_ff9d] = turn holder's card location as the attacker
CalculateDamage_VersusDefendingPokemon:
ld hl, wAIMinDamage
call _CalculateDamage_VersusDefendingPokemon
call .Calculate
ld hl, wAIMaxDamage
call _CalculateDamage_VersusDefendingPokemon
call .Calculate
ld hl, wDamage
; fallthrough
_CalculateDamage_VersusDefendingPokemon:
.Calculate:
ld e, [hl]
ld d, $00
push hl
@ -127,7 +125,7 @@ _CalculateDamage_VersusDefendingPokemon:
pop de
jr nc, .vulnerable
; invulnerable to damage
ld de, $0
ld de, 0
jr .done
.vulnerable
ldh a, [hTempPlayAreaLocation_ff9d]
@ -177,7 +175,7 @@ _CalculateDamage_VersusDefendingPokemon:
; test if de underflowed
bit 7, d
jr z, .no_underflow
ld de, $0
ld de, 0
.no_underflow
ld a, DUELVARS_ARENA_CARD_STATUS

View File

@ -153,7 +153,7 @@ AIProcessEnergyCards:
jr nc, .no_evolution_in_hand
ld [wTempAI], a ; store evolution card found
ld a, 2
call AddToAIScore
call AIEncourage
jr .check_venusaur
.no_evolution_in_hand
@ -161,7 +161,7 @@ AIProcessEnergyCards:
call CheckForEvolutionInDeck
jr nc, .check_venusaur
ld a, 1
call AddToAIScore
call AIEncourage
; if there's no Muk in any Play Area
; and there's VenusaurLv67 in own Play Area,
@ -174,7 +174,7 @@ AIProcessEnergyCards:
call CountTurnDuelistPokemonWithActivePkmnPower
jr nc, .check_if_active
ld a, 1
call AddToAIScore
call AIEncourage
.check_if_active
ldh a, [hTempPlayAreaLocation_ff9d]
@ -189,12 +189,12 @@ AIProcessEnergyCards:
; subtract from score instead
; if Player is running MewtwoLv53 mill deck.
ld a, 5
call SubFromAIScore
call AIDiscourage
jr .check_defending_can_ko
.add_to_score
ld a, 4
call AddToAIScore
call AIEncourage
; lower AI score if poison/double poison
; will KO Pokémon between turns
@ -220,13 +220,13 @@ AIProcessEnergyCards:
jr z, .check_defending_can_ko
.poison_will_ko
ld a, 10
call SubFromAIScore
call AIDiscourage
jr .check_bench
.check_defending_can_ko
call CheckIfDefendingPokemonCanKnockOut
jr nc, .ai_score_bonus
ld a, 10
call SubFromAIScore
call AIDiscourage
; if either poison will KO or defending Pokémon can KO,
; check if there are bench Pokémon,
@ -237,7 +237,7 @@ AIProcessEnergyCards:
dec a
jr nz, .ai_score_bonus
ld a, 6
call AddToAIScore
call AIEncourage
jr .ai_score_bonus
; lower AI score by 3 - (bench HP)/10
@ -252,7 +252,7 @@ AIProcessEnergyCards:
ld b, a
ld a, 3
sub b
call SubFromAIScore
call AIDiscourage
; check list in wAICardListEnergyBonus
.ai_score_bonus
@ -290,22 +290,22 @@ AIProcessEnergyCards:
jr c, .check_id_score
; already reached target number of energy cards
ld a, 10
call SubFromAIScore
jr .store_score
call AIDiscourage
jr .store_score ; bug, should be jr .check_boss_deck
.check_id_score
ld a, [hli]
cp $80
jr c, .decrease_score_1
sub $80
call AddToAIScore
call AIEncourage
jr .check_boss_deck
.decrease_score_1
ld d, a
ld a, $80
sub d
call SubFromAIScore
call AIDiscourage
jr .check_boss_deck
.next_id
@ -313,14 +313,16 @@ AIProcessEnergyCards:
inc hl
jr .loop_id_list
; if it's a boss deck, call Func_174f2
; if it's a boss deck, call HandleAIEnergyScoringForRepeatedBenchPokemon
; and apply to the AI score the values
; determined for this card
.check_boss_deck
call CheckIfNotABossDeckID
jr c, .skip_boss_deck
call Func_174f2
call HandleAIEnergyScoringForRepeatedBenchPokemon
; applies wPlayAreaEnergyAIScore
ldh a, [hTempPlayAreaLocation_ff9d]
ld c, a
ld b, $00
@ -330,18 +332,18 @@ AIProcessEnergyCards:
cp $80
jr c, .decrease_score_2
sub $80
call AddToAIScore
call AIEncourage
jr .skip_boss_deck
.decrease_score_2
ld b, a
ld a, $80
sub b
call SubFromAIScore
call AIDiscourage
.skip_boss_deck
ld a, 1
call AddToAIScore
call AIEncourage
; add AI score for both attacks,
; according to their energy requirements.
@ -413,7 +415,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
; is MAX_ENERGY_BOOST_IS_NOT_LIMITED,
; which is equal to 3, add to score.
call AddToAIScore
call AIEncourage
jp .check_evolution
.check_surplus_energy
@ -424,12 +426,12 @@ DetermineAIScoreOfAttackEnergyRequirement:
.asm_166c5
ld a, 5
call SubFromAIScore
call AIDiscourage
jp .check_evolution
.asm_166cd
ld a, 2
call AddToAIScore
call AIEncourage
; check whether attack has ATTACHED_ENERGY_BOOST flag
; and add to AI score if attaching another energy
@ -457,12 +459,12 @@ DetermineAIScoreOfAttackEnergyRequirement:
.attaching_kos_player
ld a, 20
call AddToAIScore
call AIEncourage
ldh a, [hTempPlayAreaLocation_ff9d]
or a
jr nz, .check_evolution
ld a, 10
call AddToAIScore
call AIEncourage
jr .check_evolution
; checks if there is surplus energy for attack
@ -482,7 +484,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
call CheckLoadedAttackFlag
jr nc, .check_color_needed
ld a, 5
call SubFromAIScore
call AIDiscourage
; if the energy card color needed is in hand, increase AI score.
; if a colorless card is needed, increase AI score.
@ -494,14 +496,14 @@ DetermineAIScoreOfAttackEnergyRequirement:
call LookForCardIDInHand
jr c, .check_colorless_needed
ld a, 4
call AddToAIScore
call AIEncourage
jr .check_total_needed
.check_colorless_needed
ld a, c
or a
jr z, .check_evolution
ld a, 3
call AddToAIScore
call AIEncourage
; if only one energy card is needed for attack,
; encourage playing energy card.
@ -511,7 +513,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
dec a
jr nz, .check_evolution
ld a, 3
call AddToAIScore
call AIEncourage
; if the attack KOs player and this is the active card, add to AI score.
ldh a, [hTempPlayAreaLocation_ff9d]
@ -527,7 +529,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
jr nc, .check_evolution
.atk_kos_defending
ld a, 20
call AddToAIScore
call AIEncourage
; this is possibly a bug.
; this is an identical check as above to test whether this card is active.
@ -536,7 +538,7 @@ DetermineAIScoreOfAttackEnergyRequirement:
or a
jr nz, .check_evolution
ld a, 10
call AddToAIScore
call AIEncourage
.check_evolution
ld a, [wTempAI] ; evolution in hand
@ -567,14 +569,14 @@ DetermineAIScoreOfAttackEnergyRequirement:
call LookForCardIDInHand
jr c, .check_colorless_needed_evo
ld a, 2
call AddToAIScore
call AIEncourage
jr .done
.check_colorless_needed_evo
ld a, c
or a
jr z, .done
ld a, 1
call AddToAIScore
call AIEncourage
; recover the original card in the Play Area location.
.done
@ -707,8 +709,8 @@ CheckIfEvolutionNeedsEnergyForAttack:
; if it's Charizard's Fire Spin or Exeggutor's Big Eggsplosion
; attack, don't return energy card ID, but set carry.
; output:
; b = 1 if needs color energy, 0 otherwise;
; c = 1 if only needs colorless energy, 0 otherwise;
; b = TRUE if needs color energy;
; c = TRUE if only needs colorless energy;
; carry set if not ZapdosLv64's Thunderbolt attack.
GetEnergyCardForDiscardOrEnergyBoostAttack:
; load card ID and check selected attack index.
@ -727,7 +729,7 @@ GetEnergyCardForDiscardOrEnergyBoostAttack:
; for both attacks, load its energy cost.
ld a, b
cp ZAPDOS_LV64
jr z, .zapdos2
jr z, .zapdos
cp CHARIZARD
jr z, .charizard_or_exeggutor
cp EXEGGUTOR
@ -777,19 +779,19 @@ GetEnergyCardForDiscardOrEnergyBoostAttack:
ld e, PSYCHIC_ENERGY
.set_carry
lb bc, $01, $00
lb bc, TRUE, FALSE
scf
ret
; for ZapdosLv64's Thunderbolt attack, return with no carry.
.zapdos2
.zapdos
or a
ret
; Charizard's Fire Spin and Exeggutor's Big Eggsplosion,
; return carry.
.charizard_or_exeggutor
lb bc, $00, $01
lb bc, FALSE, TRUE
scf
ret

View File

@ -37,11 +37,11 @@ AIDecidePlayPokemonCard:
cp 4
jr c, .has_4_or_fewer
ld a, 20
call SubFromAIScore
call AIDiscourage
jr .check_defending_can_ko
.has_4_or_fewer
ld a, 50
call AddToAIScore
call AIEncourage
; if defending Pokémon can KO active card, increase AI score
.check_defending_can_ko
@ -50,7 +50,7 @@ AIDecidePlayPokemonCard:
call CheckIfDefendingPokemonCanKnockOut
jr nc, .check_energy_cards
ld a, 20
call AddToAIScore
call AIEncourage
; if energy cards are found in hand
; for this card's attacks, raise AI score
@ -60,7 +60,7 @@ AIDecidePlayPokemonCard:
call CheckEnergyFlagsNeededInList
jr nc, .check_evolution_hand
ld a, 20
call AddToAIScore
call AIEncourage
; if evolution card is found in hand
; for this card, raise AI score
@ -69,7 +69,7 @@ AIDecidePlayPokemonCard:
call CheckForEvolutionInList
jr nc, .check_evolution_deck
ld a, 20
call AddToAIScore
call AIEncourage
; if evolution card is found in deck
; for this card, raise AI score
@ -78,7 +78,7 @@ AIDecidePlayPokemonCard:
call CheckForEvolutionInDeck
jr nc, .check_score
ld a, 10
call AddToAIScore
call AIEncourage
; if AI score is >= 180, play card from hand
.check_score
@ -203,21 +203,21 @@ AIDecideEvolution:
jr c, .evolution_cant_attack
.evolution_can_attack
ld a, 5
call AddToAIScore
call AIEncourage
jr .check_evolution_ko
.evolution_cant_attack
ld a, [wCurCardCanAttack]
or a
jr z, .check_evolution_ko
ld a, 2
call SubFromAIScore
call AIDiscourage
ld a, [wAlreadyPlayedEnergy]
or a
jr nz, .check_evolution_ko
call LookForEnergyNeededInHand
jr nc, .check_evolution_ko
ld a, 7
call AddToAIScore
call AIEncourage
; if it's an active card:
; if evolution can't KO but the current card can, lower AI score;
@ -234,14 +234,14 @@ AIDecideEvolution:
call CheckIfSelectedAttackIsUnusable
jr c, .evolution_cant_ko
ld a, 5
call AddToAIScore
call AIEncourage
jr .check_defending_can_ko_evolution
.evolution_cant_ko
ld a, [wCurCardCanKO]
or a
jr z, .check_defending_can_ko_evolution
ld a, 20
call SubFromAIScore
call AIDiscourage
; if defending Pokémon can KO evolution, lower AI score
.check_defending_can_ko_evolution
@ -253,7 +253,7 @@ AIDecideEvolution:
call CheckIfDefendingPokemonCanKnockOut
jr nc, .check_mr_mime
ld a, 5
call SubFromAIScore
call AIDiscourage
; if evolution can't damage player's Mr Mime, lower AI score
.check_mr_mime
@ -261,7 +261,7 @@ AIDecideEvolution:
call CheckDamageToMrMime
jr c, .check_defending_can_ko
ld a, 20
call SubFromAIScore
call AIDiscourage
; if defending Pokémon can KO current card, raise AI score
.check_defending_can_ko
@ -278,7 +278,7 @@ AIDecideEvolution:
call CheckIfDefendingPokemonCanKnockOut
jr nc, .check_status
ld a, 5
call AddToAIScore
call AIEncourage
; if current card has a status condition, raise AI score
.check_status
@ -287,7 +287,7 @@ AIDecideEvolution:
or a
jr z, .check_2nd_stage_hand
ld a, 4
call AddToAIScore
call AIEncourage
; if hand has 2nd stage card to evolve evolution card, raise AI score
.check_2nd_stage_hand
@ -295,7 +295,7 @@ AIDecideEvolution:
call CheckForEvolutionInList
jr nc, .check_2nd_stage_deck
ld a, 2
call AddToAIScore
call AIEncourage
jr .check_damage
; if deck has 2nd stage card to evolve evolution card, raise AI score
@ -304,7 +304,7 @@ AIDecideEvolution:
call CheckForEvolutionInDeck
jr nc, .check_damage
ld a, 1
call AddToAIScore
call AIEncourage
; decrease AI score proportional to damage
; AI score -= floor(Damage / 40)
@ -317,10 +317,10 @@ AIDecideEvolution:
srl a
srl a
call ConvertHPToDamageCounters_Bank5
call SubFromAIScore
call AIDiscourage
; if is Mysterious Fossil or
; wLoadedCard1Unknown2 is set to $02,
; wLoadedCard1AIInfo is AI_INFO_ENCOURAGE_EVO,
; raise AI score
.check_mysterious_fossil
ld a, [wTempAI]
@ -330,16 +330,17 @@ AIDecideEvolution:
ld a, [wLoadedCard1ID]
cp MYSTERIOUS_FOSSIL
jr z, .mysterious_fossil
ld a, [wLoadedCard1Unknown2]
cp $02
ld a, [wLoadedCard1AIInfo]
; bug, should mask out HAS_EVOLUTION flag first
cp AI_INFO_ENCOURAGE_EVO
jr nz, .pikachu_deck
ld a, 2
call AddToAIScore
call AIEncourage
jr .pikachu_deck
.mysterious_fossil
ld a, 5
call AddToAIScore
call AIEncourage
; in Pikachu Deck, decrease AI score for evolving Pikachu
.pikachu_deck
@ -357,7 +358,7 @@ AIDecideEvolution:
jr nz, .check_score
.pikachu
ld a, 3
call SubFromAIScore
call AIDiscourage
; if AI score >= 133, go through with the evolution
.check_score
@ -424,11 +425,11 @@ AIDecideSpecialEvolutions:
cp 6
jr c, .not_enough_energy
ld a, 3
call AddToAIScore
call AIEncourage
ret
.not_enough_energy
ld a, 10
call SubFromAIScore
call AIDiscourage
ret
; check if Magikarp is not the active card
@ -442,7 +443,7 @@ AIDecideSpecialEvolutions:
cp 2
ret c
ld a, 3
call AddToAIScore
call AIEncourage
ret
.invincible_ronald
@ -457,7 +458,7 @@ AIDecideSpecialEvolutions:
or a ; active card
ret z
ld a, 10
call AddToAIScore
call AIEncourage
ret
.legendary_ronald
@ -495,7 +496,7 @@ AIDecideSpecialEvolutions:
jr c, .check_muk
.lower_score
ld a, 10
call SubFromAIScore
call AIDiscourage
ret
; if there's no Muk, raise score
@ -504,7 +505,7 @@ AIDecideSpecialEvolutions:
call CountPokemonWithActivePkmnPowerInBothPlayAreas
jr c, .lower_score
ld a, 10
call AddToAIScore
call AIEncourage
ret
; if Dragonair is active, check its damage in HP
@ -604,11 +605,11 @@ AIDecidePlayLegendaryBirds:
; add
ld a, 70
call AddToAIScore
call AIEncourage
ret
.subtract
ld a, 100
call SubFromAIScore
call AIDiscourage
ret
.moltres

View File

@ -460,27 +460,31 @@ HandleAIPkmnPowers:
ld a, e
push bc
; check heal
; heal
cp VILEPLUME
jr nz, .check_shift
jr nz, .shift
call HandleAIHeal
jr .next_1
.check_shift
.shift
cp VENOMOTH
jr nz, .check_peek
jr nz, .peek
call HandleAIShift
jr .next_1
.check_peek
.peek
cp MANKEY
jr nz, .check_strange_behavior
jr nz, .strange_behavior
call HandleAIPeek
jr .next_1
.check_strange_behavior
.strange_behavior
cp SLOWBRO
jr nz, .check_curse
jr nz, .curse
call HandleAIStrangeBehavior
jr .next_1
.check_curse
.curse
cp GENGAR
jr nz, .next_1
call z, HandleAICurse
@ -992,7 +996,7 @@ HandleAICowardice:
; return carry if Pkmn Power was used.
; input:
; c = Play Area location (PLAY_AREA_*) of Tentacool.
.CheckWhetherToUseCowardice
.CheckWhetherToUseCowardice:
ld a, c
ldh [hTemp_ffa0], a
ld e, a

View File

@ -1,7 +1,7 @@
; determine AI score for retreating
; return carry if AI decides to retreat
AIDecideWhetherToRetreat:
ld a, [wGotHeadsFromConfusionCheckDuringRetreat]
ld a, [wConfusionRetreatCheckWasUnsuccessful]
or a
jp nz, .no_carry
xor a
@ -16,26 +16,26 @@ AIDecideWhetherToRetreat:
srl a
srl a
sla a ; *8
call AddToAIScore
call AIEncourage
.check_status
ld a, DUELVARS_ARENA_CARD_STATUS
call GetTurnDuelistVariable
or a
jr z, .check_ko_1 ; no status
jr z, .skip_status_check ; no status
and DOUBLE_POISONED
jr z, .check_cnf ; no poison
ld a, 2
call AddToAIScore
call AIEncourage
.check_cnf
ld a, [hl]
and CNF_SLP_PRZ
cp CONFUSED
jr nz, .check_ko_1
jr nz, .skip_status_check
ld a, 1
call AddToAIScore
call AIEncourage
.check_ko_1
.skip_status_check
xor a ; PLAY_AREA_ARENA
ldh [hTempPlayAreaLocation_ff9d], a
call CheckIfAnyAttackKnocksOutDefendingCard
@ -47,25 +47,25 @@ AIDecideWhetherToRetreat:
.active_cant_use_atk
ld a, 5
call SubFromAIScore
call AIDiscourage
ld a, [wAIOpponentPrizeCount]
cp 2
jr nc, .active_cant_ko_1
ld a, 35
call SubFromAIScore
call AIDiscourage
.active_cant_ko_1
call CheckIfDefendingPokemonCanKnockOut
jr nc, .defending_cant_ko
ld a, 2
call AddToAIScore
call AIEncourage
call CheckIfNotABossDeckID
jr c, .check_resistance_1
ld a, [wAIPlayerPrizeCount]
cp 2
jr nc, .check_prize_count
ld a, $01
ld a, TRUE
ld [wAIPlayEnergyCardForRetreat], a
.defending_cant_ko
@ -75,14 +75,14 @@ AIDecideWhetherToRetreat:
cp 2
jr nc, .check_prize_count
ld a, 2
call AddToAIScore
call AIEncourage
.check_prize_count
ld a, [wAIOpponentPrizeCount]
cp 2
jr nc, .check_resistance_1
ld a, 2
call SubFromAIScore
call AIDiscourage
.check_resistance_1
call GetArenaCardColor
@ -92,11 +92,11 @@ AIDecideWhetherToRetreat:
and b
jr z, .check_weakness_1
ld a, 1
call AddToAIScore
call AIEncourage
; check bench for Pokémon that
; the defending card is not resistant to
; if one is found, skip SubFromAIScore
; if one is found, skip AIDiscourage
ld a, [wAIPlayerResistance]
ld b, a
ld a, DUELVARS_BENCH
@ -113,7 +113,7 @@ AIDecideWhetherToRetreat:
jr .check_weakness_1
.exit_loop_resistance_1
ld a, 2
call SubFromAIScore
call AIDiscourage
.check_weakness_1
ld a, [wAIPlayerColor]
@ -122,11 +122,11 @@ AIDecideWhetherToRetreat:
and b
jr z, .check_resistance_2
ld a, 2
call AddToAIScore
call AIEncourage
; check bench for Pokémon that
; is not weak to defending Pokémon
; if one is found, skip SubFromAIScore
; if one is found, skip AIDiscourage
ld a, [wAIPlayerColor]
ld b, a
ld a, DUELVARS_BENCH
@ -142,7 +142,7 @@ AIDecideWhetherToRetreat:
jr .check_resistance_2
.exit_loop_weakness_1
ld a, 3
call SubFromAIScore
call AIDiscourage
.check_resistance_2
ld a, [wAIPlayerColor]
@ -151,17 +151,17 @@ AIDecideWhetherToRetreat:
and b
jr z, .check_weakness_2
ld a, 3
call SubFromAIScore
call AIDiscourage
; check bench for Pokémon that
; is the defending Pokémon's weakness
; if none is found, skip AddToAIScore
; if none is found, skip AIEncourage
.check_weakness_2
ld a, [wAIPlayerWeakness]
ld b, a
ld a, DUELVARS_BENCH
call GetTurnDuelistVariable
ld e, $00
ld e, PLAY_AREA_BENCH_1 - 1
.loop_weakness_2
inc e
ld a, [hli]
@ -175,7 +175,7 @@ AIDecideWhetherToRetreat:
and b
jr z, .loop_weakness_2
ld a, 2
call AddToAIScore
call AIEncourage
push de
ld a, DUELVARS_ARENA_CARD
@ -191,7 +191,7 @@ AIDecideWhetherToRetreat:
call CheckIfCanDamageDefendingPokemon
jr nc, .check_weakness_3
ld a, 10
call AddToAIScore
call AIEncourage
jr .check_resistance_3
.check_weakness_3
@ -202,11 +202,11 @@ AIDecideWhetherToRetreat:
and b
jr z, .check_resistance_3
ld a, 3
call SubFromAIScore
call AIDiscourage
; check bench for Pokémon that
; is resistant to defending Pokémon
; if none is found, skip AddToAIScore
; if none is found, skip AIEncourage
.check_resistance_3
ld a, [wAIPlayerColor]
ld b, a
@ -221,11 +221,11 @@ AIDecideWhetherToRetreat:
and b
jr z, .loop_resistance_2
ld a, 1
call AddToAIScore
call AIEncourage
; check bench for Pokémon that
; can KO defending Pokémon
; if none is found, skip AddToAIScore
; if none is found, skip AIEncourage
.check_ko_2
ld a, DUELVARS_BENCH
call GetTurnDuelistVariable
@ -253,7 +253,7 @@ AIDecideWhetherToRetreat:
pop bc
pop hl
ld a, 2
call AddToAIScore
call AIEncourage
; a bench Pokémon was found that can KO
; if this is a boss deck and it's at last prize card
@ -274,8 +274,8 @@ AIDecideWhetherToRetreat:
jp nc, .check_defending_id
.active_cant_ko_2
ld a, 40
call AddToAIScore
ld a, $01
call AIEncourage
ld a, TRUE
ld [wAIPlayEnergyCardForRetreat], a
.check_defending_id
@ -287,13 +287,13 @@ AIDecideWhetherToRetreat:
ld a, e
cp MR_MIME
jr z, .mr_mime_or_hitmonlee
cp HITMONLEE ; ??
cp HITMONLEE
jr nz, .check_retreat_cost
; check bench if there's any Pokémon
; that can damage defending Pokémon
; this is done because of Mr. Mime's PKMN PWR
; but why Hitmonlee ($87) as well?
; and Hitmonlee's ability to attack Bench
.mr_mime_or_hitmonlee
xor a ; PLAY_AREA_ARENA
call CheckIfCanDamageDefendingPokemon
@ -318,8 +318,8 @@ AIDecideWhetherToRetreat:
pop bc
pop hl
ld a, 5
call AddToAIScore
ld a, $01
call AIEncourage
ld a, TRUE
ld [wAIPlayEnergyCardForRetreat], a
; subtract from wAIScore if retreat cost is larger than 1
@ -337,24 +337,24 @@ AIDecideWhetherToRetreat:
jr nc, .three_or_more
; exactly two
ld a, 1
call SubFromAIScore
call AIDiscourage
jr .one_or_none
.three_or_more
ld a, 2
call SubFromAIScore
call AIDiscourage
.one_or_none
call CheckIfArenaCardIsAtHalfHPCanEvolveAndUseSecondAttack
call CheckIfArenaCardIsFullyPowered
jr c, .check_defending_can_ko
call CountNumberOfSetUpBenchPokemon
cp 2
jr c, .check_defending_can_ko
call AddToAIScore
call AIEncourage
; check bench for Pokémon that
; the defending Pokémon can't knock out
; if none is found, skip SubFromAIScore
; if none is found, skip AIDiscourage
.check_defending_can_ko
ld a, DUELVARS_BENCH
call GetTurnDuelistVariable
@ -385,7 +385,7 @@ AIDecideWhetherToRetreat:
jr .check_active_id
.exit_loop_ko
ld a, 20
call SubFromAIScore
call AIDiscourage
.check_active_id
ld a, DUELVARS_ARENA_CARD
@ -436,10 +436,10 @@ AIDecideWhetherToRetreat:
; if player's turn and loaded attack is not a Pokémon Power OR
; if opponent's turn and wAITriedAttack == 0
; set wcdda's bit 7 flag
Func_15b54:
; set wAIRetreatFlags's bit 7 flag
SetAIRetreatFlags:
xor a
ld [wcdda], a
ld [wAIRetreatFlags], a
ld a, [wWhoseTurn]
cp OPPONENT_TURN
jr z, .opponent
@ -457,7 +457,7 @@ Func_15b54:
.set_flag
ld a, %10000000
ld [wcdda], a
ld [wAIRetreatFlags], a
ret
; calculates AI score for bench Pokémon
@ -473,7 +473,7 @@ AIDecideBenchPokemonToSwitchTo:
ret c
; has at least 2 Pokémon in Play Area
call Func_15b54
call SetAIRetreatFlags
call LoadDefendingPokemonColorWRAndPrizeCards
ld a, 50
ld [wAIScore], a
@ -484,7 +484,7 @@ AIDecideBenchPokemonToSwitchTo:
push bc
jp .store_score
.next_bench
.loop_play_area
push bc
ld a, c
ldh [hTempPlayAreaLocation_ff9d], a
@ -499,15 +499,15 @@ AIDecideBenchPokemonToSwitchTo:
call CheckIfSelectedAttackIsUnusable
jr c, .check_can_use_atks
ld a, 10
call AddToAIScore
ld a, [wcdda]
call AIEncourage
ld a, [wAIRetreatFlags]
or %00000001
ld [wcdda], a
ld [wAIRetreatFlags], a
call CountPrizes
cp 2
jp nc, .check_defending_weak
ld a, 10
call AddToAIScore
call AIEncourage
; calculates damage of both attacks
; to raise AI score accordingly
@ -531,7 +531,7 @@ AIDecideBenchPokemonToSwitchTo:
ld a, [wDamage]
call ConvertHPToDamageCounters_Bank5
inc a
call AddToAIScore
call AIEncourage
ret
; if an energy card that is needed is found in hand
@ -545,7 +545,7 @@ AIDecideBenchPokemonToSwitchTo:
ld a, [wDamage]
call ConvertHPToDamageCounters_Bank5
srl a
call AddToAIScore
call AIEncourage
; if no energies attached to card, lower AI score
.check_attached_energy
@ -556,7 +556,7 @@ AIDecideBenchPokemonToSwitchTo:
or a
jr nz, .check_mr_mime
ld a, 1
call SubFromAIScore
call AIDiscourage
; if can damage Mr Mime, raise AI score
.check_mr_mime
@ -579,7 +579,7 @@ AIDecideBenchPokemonToSwitchTo:
jr z, .check_defending_weak
.can_damage
ld a, 5
call AddToAIScore
call AIEncourage
; if defending card is weak to this card, raise AI score
.check_defending_weak
@ -594,7 +594,7 @@ AIDecideBenchPokemonToSwitchTo:
and [hl]
jr z, .check_defending_resist
ld a, 3
call AddToAIScore
call AIEncourage
; if defending card is resistant to this card, lower AI score
.check_defending_resist
@ -603,7 +603,7 @@ AIDecideBenchPokemonToSwitchTo:
and [hl]
jr z, .check_resistance
ld a, 2
call SubFromAIScore
call AIDiscourage
; if this card is resistant to defending Pokémon, raise AI score
.check_resistance
@ -612,7 +612,7 @@ AIDecideBenchPokemonToSwitchTo:
and [hl]
jr z, .check_weakness
ld a, 2
call AddToAIScore
call AIEncourage
; if this card is weak to defending Pokémon, lower AI score
.check_weakness
@ -621,7 +621,7 @@ AIDecideBenchPokemonToSwitchTo:
and [hl]
jr z, .check_retreat_cost
ld a, 3
call SubFromAIScore
call AIDiscourage
; if this card's retreat cost < 2, raise AI score
; if this card's retreat cost > 2, lower AI score
@ -631,18 +631,18 @@ AIDecideBenchPokemonToSwitchTo:
jr c, .one_or_none
jr z, .check_player_prize_count
ld a, 1
call SubFromAIScore
call AIDiscourage
jr .check_player_prize_count
.one_or_none
ld a, 1
call AddToAIScore
call AIEncourage
; if wcdda != $81
; if wAIRetreatFlags != $81
; if defending Pokémon can KO this card
; if player is not at last prize card, lower 3 from AI score
; if player is at last prize card, lower 10 from AI score
.check_player_prize_count
ld a, [wcdda]
ld a, [wAIRetreatFlags]
cp %10000000 | %00000001
jr z, .check_hp
call CheckIfDefendingPokemonCanKnockOut
@ -654,7 +654,7 @@ AIDecideBenchPokemonToSwitchTo:
ld e, 10
.lower_score_1
ld a, e
call SubFromAIScore
call AIDiscourage
; if this card's HP is 0, make AI score 0
.check_hp
@ -672,7 +672,7 @@ AIDecideBenchPokemonToSwitchTo:
ld a, 4
call CalculateBDividedByA_Bank5
call ConvertHPToDamageCounters_Bank5
call AddToAIScore
call AIEncourage
; raise AI score if
; - is a Mr Mime OR
@ -684,24 +684,26 @@ AIDecideBenchPokemonToSwitchTo:
cp MR_MIME
jr z, .raise_score
cp MEW_LV8
jr nz, .asm_15cf0
jr nz, .check_if_has_bench_utility
ld a, DUELVARS_ARENA_CARD
call GetNonTurnDuelistVariable
call LoadCardDataToBuffer2_FromDeckIndex
ld a, [wLoadedCard2Stage]
or a
jr z, .asm_15cf0
jr z, .check_if_has_bench_utility
.raise_score
ld a, 5
call AddToAIScore
call AIEncourage
; if wLoadedCard1Unknown2 == $01, lower AI score
.asm_15cf0
ld a, [wLoadedCard1Unknown2]
cp $01
; if wLoadedCard1AIInfo == AI_INFO_BENCH_UTILITY,
; lower AI score
.check_if_has_bench_utility
ld a, [wLoadedCard1AIInfo]
; bug, should mask out HAS_EVOLUTION flag first
cp AI_INFO_BENCH_UTILITY
jr nz, .mysterious_fossil_or_clefairy_doll
ld a, 2
call SubFromAIScore
call AIDiscourage
; if card is Mysterious Fossil or Clefairy Doll,
; lower AI score
@ -713,7 +715,7 @@ AIDecideBenchPokemonToSwitchTo:
jr nz, .ai_score_bonus
.lower_score_2
ld a, 10
call SubFromAIScore
call AIDiscourage
.ai_score_bonus
ld b, a
@ -721,7 +723,7 @@ AIDecideBenchPokemonToSwitchTo:
or a
jr z, .store_score
ld h, a
ld a, [wAICardListRetreatBonus]
ld a, [wAICardListRetreatBonus + 0]
ld l, a
.loop_ids
@ -734,13 +736,13 @@ AIDecideBenchPokemonToSwitchTo:
cp $80
jr c, .subtract_score
sub $80
call AddToAIScore
call AIEncourage
jr .next_id
.subtract_score
ld c, a
ld a, $80
sub c
call SubFromAIScore
call AIDiscourage
.next_id
inc hl
jr .loop_ids
@ -756,7 +758,7 @@ AIDecideBenchPokemonToSwitchTo:
pop bc
inc c
dec b
jp nz, .next_bench
jp nz, .loop_play_area
; done
xor a

View File

@ -347,7 +347,7 @@ HandleSpecialAIAttacks:
ld a, DUELVARS_BENCH
call GetTurnDuelistVariable
lb de, 0, 0
lb de, 0, PLAY_AREA_BENCH_1 - 1
.loop_earthquake
inc e
ld a, [hli]
@ -355,15 +355,23 @@ HandleSpecialAIAttacks:
jr z, .count_prizes
ld a, e
add DUELVARS_ARENA_CARD_HP
; bug, GetTurnDuelistVariable clobbers hl
; uncomment the following lines to preserve hl
; push hl
call GetTurnDuelistVariable
; pop hl
cp 20
jr nc, .loop_earthquake
inc d
jr .loop_earthquake
.count_prizes
; bug, this is supposed to count the player's prize cards
; not the opponent's, missing calls to SwapTurn
push de
; call SwapTurn
call CountPrizes
; call SwapTurn
pop de
cp d
jp c, .zero_score
@ -409,25 +417,23 @@ CheckWhetherToSwitchToFirstAttack:
cp $50
jr c, .keep_second_attack
; first attack has more than minimum score to be used.
; check if second attack can KO.
; in case it can't, the AI keeps it as the attack to be used.
; (possibly due to the assumption that if the
; second attack cannot KO, the first attack can't KO as well.)
; first attack has more than minimum score to be used,
; check if it can KO, in case it can't
; then the AI keeps second attack as selection.
xor a ; PLAY_AREA_ARENA
ldh [hTempPlayAreaLocation_ff9d], a
; a = FIRST_ATTACK_OR_PKMN_POWER
call EstimateDamage_VersusDefendingCard
ld a, DUELVARS_ARENA_CARD_HP
call GetNonTurnDuelistVariable
ld hl, wDamage
sub [hl]
sub [hl] ; HP - damage
jr z, .check_flag
jr nc, .keep_second_attack
jr nc, .keep_second_attack ; cannot KO
; second attack can ko, check its flag.
; first attack can ko, check flags from second attack
; in case its effect is to heal user or nullify/weaken damage
; next turn, keep second attack as the option.
; otherwise switch to the first attack.
.check_flag
ld a, DUELVARS_ARENA_CARD
call GetTurnDuelistVariable

View File

@ -171,7 +171,7 @@ AIPlay_Potion:
; next turn after using Potion.
; if it cannot, return carry.
; also take into account whether attack is high recoil.
AIDecide_Potion1:
AIDecide_Potion_Phase07:
farcall AIDecideWhetherToRetreat
jr c, .no_carry
call AICheckIfAttackIsHighRecoil
@ -213,7 +213,7 @@ AIDecide_Potion1:
; output:
; a = card to use Potion on;
; carry set if Potion should be used.
AIDecide_Potion2:
AIDecide_Potion_Phase10:
xor a ; PLAY_AREA_ARENA
ldh [hTempPlayAreaLocation_ff9d], a
farcall CheckIfDefendingPokemonCanKnockOut

View File

@ -479,7 +479,7 @@ DuelMenu_Retreat:
cp CONFUSED
ldh [hTemp_ffa0], a
jr nz, .not_confused
ld a, [wGotHeadsFromConfusionCheckDuringRetreat]
ld a, [wConfusionRetreatCheckWasUnsuccessful]
or a
jr nz, .unable_due_to_confusion
call CheckAbleToRetreat
@ -5810,16 +5810,16 @@ AttemptRetreat:
ldtx de, ConfusionCheckRetreatText
call TossCoin
jr c, .success
ld a, 1
ld [wGotHeadsFromConfusionCheckDuringRetreat], a
ld a, TRUE
ld [wConfusionRetreatCheckWasUnsuccessful], a
scf
ret
.success
ldh a, [hTempPlayAreaLocation_ffa1]
ld e, a
call SwapArenaWithBenchPokemon
xor a
ld [wGotHeadsFromConfusionCheckDuringRetreat], a
xor a ; FALSE
ld [wConfusionRetreatCheckWasUnsuccessful], a
ret
; given a number between 0-255 in a, converts it to TX_SYMBOL format,
@ -7149,7 +7149,7 @@ ConvertSpecialTrainerCardToPokemon::
ld bc, CARD_DATA_HP
add hl, bc
ld de, .trainer_to_pkmn_data
ld c, CARD_DATA_UNKNOWN2 - CARD_DATA_HP
ld c, CARD_DATA_AI_INFO - CARD_DATA_HP
.loop
ld a, [de]
inc de
@ -7677,7 +7677,7 @@ InitVariablesToBeginDuel:
InitVariablesToBeginTurn:
xor a
ld [wAlreadyPlayedEnergy], a
ld [wGotHeadsFromConfusionCheckDuringRetreat], a
ld [wConfusionRetreatCheckWasUnsuccessful], a
ld [wGotHeadsFromSandAttackOrSmokescreenCheck], a
ldh a, [hWhoseTurn]
ld [wWhoseTurn], a

View File

@ -1725,10 +1725,10 @@ ApplyTransparencyIfApplicable::
ld de, 0
ret
; return carry and 1 into wGotHeadsFromConfusionCheck if damage will be dealt to oneself due to confusion
; return carry and TRUE in wConfusionAttackCheckWasUnsuccessful if damage will be dealt to oneself due to confusion
CheckSelfConfusionDamage::
xor a
ld [wGotHeadsFromConfusionCheck], a
xor a ; FALSE
ld [wConfusionAttackCheckWasUnsuccessful], a
ld a, DUELVARS_ARENA_CARD_STATUS
call GetTurnDuelistVariable
and CNF_SLP_PRZ
@ -1740,8 +1740,8 @@ CheckSelfConfusionDamage::
ldtx de, ConfusionCheckDamageText
call TossCoin
jr c, .no_confusion_damage
ld a, 1
ld [wGotHeadsFromConfusionCheck], a
ld a, TRUE
ld [wConfusionAttackCheckWasUnsuccessful], a
scf
ret
.no_confusion_damage

View File

@ -68,6 +68,7 @@ HandleDamageReductionExceptSubstatus2::
call GetTurnDuelistVariable
or a
jr z, .not_affected_by_substatus1
cp SUBSTATUS1_NO_DAMAGE_STIFFEN
jr z, .no_damage
cp SUBSTATUS1_NO_DAMAGE_10
@ -84,6 +85,7 @@ HandleDamageReductionExceptSubstatus2::
jr z, .prevent_less_than_40_damage
cp SUBSTATUS1_HALVE_DAMAGE
jr z, .halve_damage
.not_affected_by_substatus1
call CheckIsIncapableOfUsingPkmnPower_ArenaCard
ret c
@ -93,33 +95,38 @@ HandleDamageReductionExceptSubstatus2::
ret z
ld a, [wTempNonTurnDuelistCardID]
cp MR_MIME
jr z, .prevent_less_than_30_damage ; invisible wall
jr z, .invisible_wall
cp KABUTO
jr z, .halve_damage2 ; kabuto armor
jr z, .kabuto_armor
ret
.no_damage
ld de, 0
ret
.reduce_damage_by_10
ld hl, -10
add hl, de
ld e, l
ld d, h
ret
.reduce_damage_by_20
ld hl, -20
add hl, de
ld e, l
ld d, h
ret
.prevent_less_than_40_damage
ld bc, 40
call CompareDEtoBC
ret nc
ld de, 0
ret
.halve_damage
sla d
sla d ; bug, should be sra d
rr e
bit 0, e
ret z
@ -128,7 +135,8 @@ HandleDamageReductionExceptSubstatus2::
ld e, l
ld d, h
ret
.prevent_less_than_30_damage
.invisible_wall
ld a, [wLoadedAttackCategory]
cp POKEMON_POWER
ret z
@ -137,8 +145,9 @@ HandleDamageReductionExceptSubstatus2::
ret c
ld de, 0
ret
.halve_damage2
sla d
.kabuto_armor
sla d ; bug, should be sra d
rr e
bit 0, e
ret z
@ -331,7 +340,9 @@ HandleSandAttackOrSmokescreenSubstatus::
scf
ret
; return carry if the turn holder's arena card is under the effects of sand attack or smokescreen
; return carry if the turn holder's arena card is under
; the effects of sand attack or smokescreen
; and got tails on the coin toss
CheckSandAttackOrSmokescreenSubstatus::
ld a, DUELVARS_ARENA_CARD_SUBSTATUS2
call GetTurnDuelistVariable
@ -348,7 +359,8 @@ CheckSandAttackOrSmokescreenSubstatus::
.card_is_affected
ld a, [wGotHeadsFromSandAttackOrSmokescreenCheck]
or a
ret nz
ret nz ; got heads
; got tails
scf
ret

View File

@ -17,12 +17,12 @@ MACRO card_data_struct
\1Resistance:: ds 1
\1Category:: ds 2
\1PokedexNumber:: ds 1
\1Unknown1:: ds 1
ds 1
\1Level:: ds 1
\1Length:: ds 2
\1Weight:: ds 2
\1Description:: ds 2
\1Unknown2:: ds 1
\1AIInfo:: ds 1
ENDM
MACRO atk_data_struct

View File

@ -652,8 +652,8 @@ wGotHeadsFromSandAttackOrSmokescreenCheck:: ; cc0a
wAlreadyPlayedEnergy:: ; cc0b
ds $1
; set to 1 if the confusion check coin toss in AttemptRetreat is heads
wGotHeadsFromConfusionCheckDuringRetreat:: ; cc0c
; set to TRUE if the confusion check coin toss in AttemptRetreat is tails
wConfusionRetreatCheckWasUnsuccessful:: ; cc0c
ds $1
; DUELIST_TYPE_* of the turn holder
@ -780,8 +780,8 @@ wNoDamageOrEffect:: ; ccc7
wNumberPrizeCardsToTake:: ; ccc8
ds $1
; set to 1 if the coin toss in the confusion check is heads (CheckSelfConfusionDamage)
wGotHeadsFromConfusionCheck:: ; ccc9
; set to TRUE if the coin toss in the confusion check is tails (CheckSelfConfusionDamage)
wConfusionAttackCheckWasUnsuccessful:: ; ccc9
ds $1
; used to store card indices of all stages, in order, of a Play Area Pokémon
@ -1155,8 +1155,8 @@ wAIPluspowerAttack:: ; cdd6
; whether AI is allowed to play an energy card
; from the hand in order to retreat arena card
; $00 = not allowed
; $01 = allowed
; FALSE = not allowed
; TRUE = allowed
wAIPlayEnergyCardForRetreat:: ; cdd7
ds $1
@ -1172,7 +1172,12 @@ wAIEnergyAttachLogicFlags:: ; cdd8
wAIExecuteProcessedAttack:: ; cdd9
ds $1
wcdda:: ; cdda
; flags used by AI for retreat logic
; if bit 0 set, then it means the current Pokémon
; can KO the defending card with one of its attacks
; if bit 7 is set, then it means the switch is due
; to the effect of an attack (not Pkmn Power)
wAIRetreatFlags:: ; cdda
ds $1
wAITriedAttack:: ; cddb
@ -1194,7 +1199,7 @@ wTempAIScore:: ; cde3
wPlayAreaEnergyAIScore:: ; cde4
ds MAX_PLAY_AREA_POKEMON
wcdea:: ; cdea
wSamePokemonEnergyScore:: ; cdea
ds MAX_PLAY_AREA_POKEMON
; whether AI cannot inflict damage on player's active Pokémon
@ -1228,10 +1233,10 @@ wCurCardCanKO:: ; cdf4
ds $4
wcdf9:: ; cdf9
wSamePokemonCardID:: ; cdf9
ds $1
wcdfa:: ; cdfa
wSamePokemonEnergyScoreHandled:: ; cdfa
ds MAX_PLAY_AREA_POKEMON
wAIFirstAttackDamage:: ; ce00