pokemon-speedrunning / Gen1CatchRateCalculator

Gen 1 Pokemon Catch Rate Calculator
MIT License
2 stars 3 forks source link

Add carry bit to the initial rerolls #2

Closed antialiasis closed 3 years ago

antialiasis commented 3 years ago

When the RNG adds to the hRandomAdd byte, it's an add with carry. Whenever we perform a reroll of the first random byte, the carry bit should always be set to 1, as on a reroll this random call immediately follows a jr c, .loop. (The latter random call follows an and a, which should reset the carry bit, so that one is unchanged.)

This slightly alters some results; for example, without this patch, a full-health level 20 Tauros in an Ultra Ball in Red/Blue is shown as having a 6.56% chance of being caught, while with the patch it becomes a 6.54% chance, and for a Great Ball it goes from 11.82% to 11.89%.

TiKevin83 commented 3 years ago

Makes sense to me, if you can run gulp and commit again to get it into the compiled files that'd be awesome, otherwise I can do that after merging

CasualPokePlayer commented 3 years ago

This looks like it might be a bit more complicated than this. This random call is only guaranteed to have carry set for successive calls. However, for the first call, whether carry is set would be based on the map you are in (a side effect of the code that checks for the Marowak ghost). For map IDs less than 0x93, carry is set. For map IDs more than 0x91, carry is not set. For specifically map ID 0x93 (ie Pokemon Tower 6F), carry could be set or not set depending on the Pokemon encountered. For Pokemon IDs less than or equal to 0x91, carry is set (although equal to is irrelevant as that skips the Random call, again Marowak ghost code). For Pokemon IDs more than 0x91, carry is not set. For perspective, the Pokemon that can be caught here are Gastly, Haunter, and Cubone. Gastly and Cubone will have carry set here, but Haunter will not.

antialiasis commented 3 years ago

@CasualPokePlayer That’s correct - however, whether there’s a carry on the first call is not actually going to have any effect on the outcome! That is because the first roll having a carry is exactly equivalent to the initial RNG byte just happening to have been one higher to begin with. Since the calculator already assumes the initial RNG byte might be any value and weighs those outcomes equally (as it should, since it’s genuinely randomly distributed during normal gameplay), it simply evens out. I originally worked through the same logic you did but it doesn’t actually change anything for those cases! We only care how the subsequent numbers generated turn out after a given initial roll.

On Tue, 1 Dec 2020 at 05:24, CasualPokePlayer notifications@github.com wrote:

This looks like it might be a bit more complicated than this. This random call is only guaranteed to have carry set for successive calls. However, for the first call, whether carry is set would be based on the map you are in (a side effect of the code that checks for the Marowak ghost). For map IDs less than 0x93, carry is set. For map IDs more than 0x91, carry is not set. For specifically map ID 0x93 (ie Pokemon Tower 6F), carry could be set or not set depending on the Pokemon encountered. For Pokemon IDs less than or equal to 0x91, carry is set (although equal to is irrelevant as that skips the Random call, again Marowak ghost code). For Pokemon IDs more than 0x91, carry is not set. For perspective, the Pokemon that can be caught here are Gastly, Haunter, and Cubone. Gastly and Cubone will have carry set here, but Haunter will not.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/pokemon-speedrunning/Gen1CatchRateCalculator/pull/2#issuecomment-736226958, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKD236CBIAFWZ7ZA4FZ4C3SSR4YTANCNFSM4UIEYQ5A .

-- ~Butterfree/Dragonfree/antialiasis of The Cave of Dragonflies http://www.dragonflycave.com

antialiasis commented 3 years ago

@TiKevin83 Added!

Incidentally, don't know if you're interested at all given the speed of the calculator is perfectly adequate already, but I figured out a couple of optimizations in the process of making my own calculator, to save time on the brute-forcing: