AI Improvements

This fixes some of the issues with the current AI system to make them better. In short:

- Most Trainers should correctly recognise when a move is not very effective, and not use it. If they have a supereffective move and a regular-effective move, they will slightly prioritise the supereffective one, but not always use it like in regular RBY. This prevents the Lorelei softlock, for example.

- Trainers won't attempt to set status effects on Pokemon that already have one, won't try recovering at full health, and won't attempt to set up multiple Reflects or Light Screen

- Certain high-level trainers will recognise when a Pokemon does not have a status, and will try to inflict one if so. This makes Agatha's, Erika's and Koga's team types much more effective.

- Youngsters and Cue Balls no longer pick moves randomly and will actually give it some thought

- Brock and the Engineers now recognize type effectiveness, Students do not given how early they're encountered.

- General improvements to move choices for all Gym Leaders, E4 and Shinjuku Jacky.

We're almost done.
This commit is contained in:
Martha Schilling 2024-01-05 13:59:27 +00:00
parent a486ec7657
commit e6763371e4
6 changed files with 157 additions and 127 deletions

View file

@ -7,6 +7,18 @@ AIEnemyTrainerChooseMoves:
ld [hli], a ; move 2
ld [hli], a ; move 3
ld [hl], a ; move 4
;;;;;;;;;; shinpokerednote: ADDED: make a backup buffer
push hl
ld a, $ff
inc hl
ld [hli], a ;backup 1
ld [hli], a ;backup 2
ld [hli], a ;backup 3
ld [hl], a ;backup 4
pop hl
;;;;;;;;;;
ld a, [wEnemyDisabledMove] ; forbid disabled move (if any)
swap a
and $f
@ -52,6 +64,11 @@ AIEnemyTrainerChooseMoves:
ld de, .nextMoveChoiceModification ; set return address
push de
jp hl ; execute modification function
.loopFindMinimumEntries_backupfirst ;shinpokerednote: ADDED: make a backup of the scores
ld hl, wBuffer ; temp move selection array
ld de, wBuffer + NUM_MOVES ;backup buffer
ld bc, NUM_MOVES
rst _CopyData
.loopFindMinimumEntries ; all entries will be decremented sequentially until one of them is zero
ld hl, wBuffer ; temp move selection array
ld de, wEnemyMonMoves ; enemy moves
@ -466,10 +483,8 @@ AIMoveChoiceModification3:
jr c, .notEffectiveMove
;ld a, [wEnemyMoveEffect]
; check for reasons not to use a super effective move here
dec [hl] ; slightly encourage this super effective move
.checkSpecificEffects ; we'll further encourage certain moves
call EncouragePriorityIfSlow
call EncourageDrainingMoveIfLowHealth
jr .nextMove
.notEffectiveMove ; discourages non-effective moves if better moves are available
@ -479,7 +494,7 @@ AIMoveChoiceModification3:
ld a, [wEnemyMoveType]
ld d, a
ld hl, wEnemyMonMoves ; enemy moves
ld b, NUM_MOVES + 1
ld bc, NUM_MOVES + 1
ld c, $0
.loopMoves
dec b
@ -543,18 +558,6 @@ CompareSpeed:
ret
;;;;;;;;;;
; PureRGBnote: ADDED: encourages priority moves if the enemy's pokemon is slower than the player's and the move is neutral or super effective.
; BUT this effect is only applied after you have the soulbadge to prevent priority moves from being spammed early game.
; Applies to trainers that use AI subroutine 3
EncouragePriorityIfSlow:
ld a, [wObtainedBadges]
bit BIT_SOULBADGE, a
ret z
call CompareSpeed
ret nc
dec [hl] ; encourage the move if it's a priority move and the pokemon is slower
ret
; PureRGBnote: ADDED: if the opponent has less than 1/2 health they will prefer healing moves if they use AI subroutine 3
EncourageDrainingMoveIfLowHealth:
ld a, [wEnemyMoveEffect]
@ -576,11 +579,11 @@ AIMoveChoiceModification4:
ld b, NUM_MOVES + 1
.nextMove
dec b
jr z, .done ; processed all 4 moves
ret z ; processed all 4 moves
inc hl
ld a, [de]
and a
jr z, .done ; no more moves in move set
ret z ; no more moves in move set
inc de
call ReadMove
ld a, [wEnemyMoveEffect]
@ -626,8 +629,7 @@ AIMoveChoiceModification4:
jr z, .nextMove ; if the AI thinks the player IS NOT asleep before they switch, we shouldn't encourage based on the new mon's status
ld a, [wBattleMonStatus]
and SLP_MASK
jr nz, .preferMoveEvenMore ; heavier favor for dream eater if the opponent is asleep
jr .nextMove
jr z, .nextMove
.preferMoveEvenMore
dec [hl]
jr .preferMove
@ -676,9 +678,6 @@ TrainerAI:
ld a, [wIsInBattle]
dec a
ret z ; if not a trainer, we're done here
ld a, [wCurMap]
cp BATTLE_TENT
ret z ; if we are in battle tent, we are done
ld a, [wLinkState]
cp LINK_STATE_BATTLING
ret z ; if in a link battle, we're done as well
@ -732,12 +731,9 @@ BlackbeltAI:
jp AIUseXAttack
GiovanniAI:
cp 20 percent + 1
cp 25 percent + 1
ret nc
ld a, [wEnemyBattleStatus2]
bit GETTING_PUMPED, a
ret nz
jp AIUseDireHit
jp AIUseXAttack ; Used to use a Guard Spec. This will make the item use have a proper impact - healing doesn't feel right for a trainer fixated on strength.
CooltrainerMAI:
cp 20 percent + 1
@ -765,41 +761,46 @@ BrockAI:
jp AIUseFullHeal
MistyAI:
cp 20 percent + 1
cp 25 percent + 1
ret nc
jp AIUseXDefend
ld a, 10
call AICheckIfHPBelowFraction
ret nc
jp AIUseSuperPotion ; Replicates Starmie using Recover. Unlike other trainers that heal, Misty will do this 26% of the time instead of 51%.
LtSurgeAI:
cp 10 percent + 1
cp 20 percent + 1
ret nc
jp AIUseXSpeed
jp AIUseXSpecial
ErikaAI:
cp 50 percent + 1
ret nc
ld a, 5
ld a, 10
call AICheckIfHPBelowFraction
ret nc
jp AIUseSuperPotion
KogaAI:
cp 10 percent + 1
cp 50 percent + 1
ret nc
jp AIUseXAttack
ld a, 10
call AICheckIfHPBelowFraction
ret nc
jp AIUseSuperPotion ; Koga is weird - I don't think anything fits. X Attack is certainly not the move though...
BlaineAI: ;blaine needs to check HP. this was an oversight
cp 40 percent + 1
jr nc, .blainereturn
ld a, 2
call AICheckIfHPBelowFraction
jp c, AIUseSuperPotion
.blainereturn
ret
BlaineAI:
cp 25 percent + 1
ret nc
ld a, 10
call AICheckIfHPBelowFraction
ret nc ; this fixes the super potion thing - PvK
jp AIUseHyperPotion ; Instead of a Super Potion though, let's give him this. More impactful for the sixth gym while staying true to the meme that everyone knows Gen 1 Blaine for.
SabrinaAI:
cp 25 percent + 1
ret nc
ld a, 5
ld a, 10
call AICheckIfHPBelowFraction
ret nc
jp AIUseHyperPotion
@ -810,7 +811,7 @@ Rival2AI:
ld a, 5
call AICheckIfHPBelowFraction
ret nc
jp AIUseHyperPotion
jp AIUseSuperPotion
Rival3AI:
cp 40 percent - 1
@ -821,43 +822,51 @@ Rival3AI:
jp AIUseFullRestore
LoreleiAI:
cp 50 percent + 1
cp 15 percent + 1
ret nc
jp AIUseXSpecial
cp 40 percent + 1
ret nc
ld a, 5
call AICheckIfHPBelowFraction
ret nc
jp AIUseHyperPotion
jp AIUseFullRestore
BrunoAI:
;cp 10 percent + 1
;ret nc
;jp AIUseXDefend
cp 30 percent + 1
jr nc, .brunoreturn
cp 15 percent + 1
ret nc
jp AIUseXAttack
cp 40 percent + 1
ret nc
ld a, 5
call AICheckIfHPBelowFraction
jp c, AIUseHyperPotion
.brunoreturn
ret
ret nc
jp AIUseFullRestore
AgathaAI:
cp 8 percent
jp c, AISwitchIfEnoughMons
cp 50 percent + 1
cp 15 percent + 1
ret nc
ld a, 4
call AICheckIfHPBelowFraction
ret nc
jp AIUseHyperPotion
LanceAI:
cp 50 percent + 1
jp AIUseXAccuracy ; hahahahahahahaha
cp 40 percent + 1
ret nc
ld a, 5
call AICheckIfHPBelowFraction
ret nc
jp AIUseFullRestore
LanceAI:
cp 15 percent + 1
ret nc
jp AIUseXSpecial
cp 50 percent + 1
ret nc
ld a, 10
call AICheckIfHPBelowFraction
ret nc
jp AIUseFullRestore
GenericAI:
and a ; clear carry
ret
@ -1087,12 +1096,12 @@ AICureStatus: ;shinpokerednote: CHANGED: modified to be more robust and also und
res BADLY_POISONED, [hl] ;clear toxic bit
ret
;AIUseXAccuracy: ; unused
; call AIPlayRestoringSFX
; ld hl, wEnemyBattleStatus2
; set 0, [hl]
; ld a, X_ACCURACY
; jp AIPrintItemUse
AIUseXAccuracy:
call AIPlayRestoringSFX
ld hl, wEnemyBattleStatus2
set 0, [hl]
ld a, X_ACCURACY
jp AIPrintItemUse
;AIUseGuardSpec: ; PureRGBnote: CHANGED: now unused
; call AIPlayRestoringSFX