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 - [Skip if move accuracy is 100%](#1-skip-if-move-accuracy-is-100%) - [Explaining the fix](#2-explaining-the-fix) ## 1. Skip if move accuracy is 100% In [engine/battle/core.asm](https://github.com/pret/pokered/blob/master/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. ```diff .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? + ret z ; 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. `ret z` returns from this subroutine 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... return 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!