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

@ -1,4 +1,54 @@
; Used by the pureRGB AI
;shinpokerednote: ADDED: doubles the given stat
DoubleSelectedStats:
ldh a, [hWhoseTurn]
and a
ld a, [wPlayerStatsToDouble]
ld hl, wBattleMonAttack
jr z, .notEnemyTurn
ld a, [wEnemyStatsToDouble]
ld hl, wEnemyMonAttack
.notEnemyTurn
ld c, 4
ld b, a
.loop
srl b
call c, .doubleStat
inc hl
inc hl
dec c
ret z
jr .loop
.doubleStat
push bc
ld a, [hli]
ld b, a
ld c, [hl] ; bc holds value of stat to double
;double the stat
sla c
rl b
;cap stat at 999
;b register contains high byte & c register contains low byte
ld a, c ;let's work on low byte first. Note that decimal 999 is $03E7 in hex.
sub 999 % $100 ;a = a - ($03E7 % $100). Gives a = a - $E7. A byte % $100 always gives the lesser nibble.
;Note that if a < $E7 then the carry bit 'c' in the flag register gets set due to overflowing with a negative result.
ld a, b ;now let's work on the high byte
sbc 999 / $100 ;a = a - ($03E7 / $100 + c_flag). Gives a = a - ($03 + c_flag). A byte / $100 always gives the greater nibble.
;Note again that if a < $03 then the carry bit remains set.
;If the bit is already set from the lesser nibble, then its addition here can still make it remain set if a is low enough.
jr c, .donecapping ;jump to next marker if the c_flag is set. This only remains set if BC < the cap of $03E7.
;else let's continue and set the 999 cap
ld a, 999 / $100 ; else load $03 into a
ld b, a ;and store it as the high byte
ld a, 999 % $100 ; else load $E7 into a
ld c, a ;and store it as the low byte
;now registers b & c together contain $03E7 for a capped stat value of 999
.donecapping
ld a, c
ld [hld], a
ld [hl], b
pop bc
ret
;shinpokerednote: ADDED: doubles attack if burned or quadruples speed if paralyzed.
;It's meant to be run right before healing paralysis or burn so as to
;undo the stat changes.
@ -31,35 +81,6 @@ UndoBurnParStats:
ld [de], a ;reset the stat change bits
ret
; Reused for pureRGB AI
DoubleSelectedStats:
ldh a, [hWhoseTurn]
and a
ld a, [wPlayerStatsToDouble]
ld hl, wBattleMonAttack + 1
jr z, .notEnemyTurn
ld a, [wEnemyStatsToDouble]
ld hl, wEnemyMonAttack + 1
.notEnemyTurn
ld c, 4
ld b, a
.loop
srl b
call c, .doubleStat
inc hl
inc hl
dec c
ret z
jr .loop
.doubleStat
ld a, [hl]
add a
ld [hld], a
ld a, [hl]
rl a
ld [hli], a
ret
; does nothing since no stats are ever selected (barring glitches)
;HalveSelectedStats:
; ldh a, [hWhoseTurn]