Skip to content

TestPage

NPO edited this page Nov 26, 2021 · 2 revisions

In Generation I, due to a slight quirk of how the accuracy code works, there's a +1/255 chance of missing any move, meaning that 100% accuracy moves have a chance of 255/256 for hitting, or 99.609375%, and not 100%.

This tutorial shows how Generation II fixes this issue.

(Code backported from Pokémon Crystal.)

Contents

1. Skip if move accuracy is 100%

In engine/battle/core.asm, we can go to the label .doAccuracyCheck to see the following:

.doAccuracyCheck
; if the random number generated is greater than or equal to the scaled accuracy, the move misses
; note that this means that even the highest accuracy is still just a 255/256 chance, not 100%
	call BattleRandom
	cp b
	jr nc, .moveMissed
	ret

Here's where we insert the proper code.

.doAccuracyCheck
; if the random number generated is greater than or equal to the scaled accuracy, the move misses
; note that this means that even the highest accuracy is still just a 255/256 chance, not 100%

+	; The following snippet is taken from Pokemon Crystal, it fixes the above bug.
+	ld a, b
+	cp $FF ; Is the value $FF?
+	jr z, .Hit ; If so, we need not calculate, just so we can fix this bug.

	call BattleRandom
	cp b
	jr nc, .moveMissed
	ret

As you can see, we've added only 3 lines of code. This fixes this bug, Gen II style. Now, let's talk about what exactly this does.

2. Explaining the fix

For anyone with GB Z80 experience, feel free to skip this part, but for anyone uninformed, I'll try my best to explain with my limited knowledge.

ld a, b loads the contents of register b into register a. This is done because b holds the move accuracy of the Pokémon currently using the move. cp $FF just compares a to $FF, technically by subtracting $FF from a. jr z, .Hit jumps ahead to the label .Hit IF the Zero flag is set. Due to how cp works, this will be set if the compared value and a are equal. In other words... branch to .Hit if equal. Therefore, if move accuracy is $FF, therefore 100%, then it doesn't bother calculating if the move will miss: after all, the move's accuracy IS 100%. This occurs after other move accuracy calculations, so those will come into effect as well.

Enjoy!

Clone this wiki locally