-
Notifications
You must be signed in to change notification settings - Fork 91
Remove AI artificial delay
The AI opponent has an artificial 60 frame delay when it is processing actions for the turn. Reducing this delay is easily done by changing the delay value in AIMakeDecision
:
AIMakeDecision:
ldh [hOppActionTableIndex], a
ld hl, wSkipDuelistIsThinkingDelay
ld a, [hl]
ld [hl], $0
or a
jr nz, .skip_delay
.delay_loop
call DoFrame
ld a, [wVBlankCounter]
cp 60 ; CHANGE HERE
jr c, .delay_loop
.skip_delay
...
On the other hand, if you want to remove this functionality completely then read on.
Remove delay loop in AIMakeDecision
. Edit src/engine/duel/core.asm:
AIMakeDecision:
ldh [hOppActionTableIndex], a
- ld hl, wSkipDuelistIsThinkingDelay
- ld a, [hl]
- ld [hl], $0
- or a
- jr nz, .skip_delay
-.delay_loop
- call DoFrame
- ld a, [wVBlankCounter]
- cp 60
- jr c, .delay_loop
-
-.skip_delay
- ldh a, [hOppActionTableIndex]
ld hl, wOpponentTurnEnded
ld [hl], 0
ld hl, OppActionTable
Now there is some code that dynamically switches off the delay loop through wSkipDuelistIsThinkingDelay
, which is now redundant. We can safely remove these portions of code. Edit src/engine/duel/core.asm again:
DuelMainInterface:
...
; DUELIST_TYPE_AI_OPP
xor a
ld [wVBlankCounter], a
- ld [wSkipDuelistIsThinkingDelay], a
ldtx hl, DuelistIsThinkingText
call DrawWideTextBox_PrintTextNoDelay
call AIDoAction_Turn
AIMakeDecision:
...
ld a, [wDuelFinished]
ld hl, wOpponentTurnEnded
or [hl]
- jr nz, .turn_ended
- ld a, [wSkipDuelistIsThinkingDelay]
- or a
- ret nz
- ld [wVBlankCounter], a
- ldtx hl, DuelistIsThinkingText
- call DrawWideTextBox_PrintTextNoDelay
- or a
- ret
-
-.turn_ended
+ ret z
scf
ret
OppAction_PlayTrainerCard:
call LoadNonPokemonCardEffectCommands
call DisplayUsedTrainerCardDetailScreen
call PrintUsedTrainerCardDescription
- call ExchangeRNG
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp ExchangeRNG
OppAction_BeginUseAttack:
...
ld e, a
call CopyAttackDataAndDamage_FromDeckIndex
call UpdateArenaCardIDsAndClearTwoTurnDuelVars
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
call CheckSandAttackOrSmokescreenSubstatus
jr c, .has_status
ld a, DUELVARS_ARENA_CARD_STATUS
OppAction_UseAttack:
...
call PrintPokemonsAttackText
call WaitForWideTextBoxInput
- call ExchangeRNG
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp ExchangeRNG
.confusion_damage
call HandleConfusionDamageToSelf
OppAction_UsePokemonPower:
...
ld [wTxRam2_b + 1], a
ldtx hl, WillUseThePokemonPowerText
call DrawWideTextBox_WaitForInput_Bank1
- call ExchangeRNG
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp ExchangeRNG
; execute the EFFECTCMDTYPE_BEFORE_DAMAGE command of the used Pokemon Power
OppAction_ExecutePokemonPowerEffect:
call Func_7415
ld a, EFFECTCMDTYPE_BEFORE_DAMAGE
- call TryExecuteEffectCommandFunction
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp TryExecuteEffectCommandFunction
; execute the EFFECTCMDTYPE_AFTER_DAMAGE command of the used Pokemon Power
OppAction_6b15:
ld a, EFFECTCMDTYPE_AFTER_DAMAGE
- call TryExecuteEffectCommandFunction
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp TryExecuteEffectCommandFunction
OppAction_DrawDuelMainScene:
call DrawDuelMainScene
OppAction_TossCoinATimes:
call SerialRecv8Bytes
- call TossCoinATimes
- ld a, $01
- ld [wSkipDuelistIsThinkingDelay], a
- ret
+ jp TossCoinATimes
OppAction_6b30:
ldh a, [hWhoseTurn]
Although we switched off the delay loop,
wSkipDuelistIsThinkingDelay
is still used for Link duels, so it cannot be completely removed.
Now we are set, you'll find that the AI is much more snappy with its actions and the duel flows more fluidly.