[Outdated] New RBY Sleep Mechanics Discovery

Status
Not open for further replies.

Shellnuts

Rustiest Player Around
is a Community Contributor
Hello everyone, so a while ago I came across the following question from Volk asking how the probabilities of the different sleep rolls are distributed:

1719097354943.png


At the time I expected the probabilities would be roughly even, maybe with 1 sleep roll slightly more likely than the others. But after looking through the code, that is not the case at all, it is far more likely that you will get a 1 turn sleep (25% chance) than any of the other sleep rolls (all other rolls occur 12.5% of the time).

This is the case because of how the game determines the number of turns a Pokémon will sleep for. When the game determines how long it should put a Pokémon to sleep for, it generates a random number (well technically for link battles it generates them 10 at a time and then iterates through the ones it generated, but it doesn't matter for this) and checks if it is a multiple of 8; if it is zero then it generates a new random number and performs the same check, looping until it finds a random number which is not a multiple of 8. It then sets the number of turns that a Pokémon is sleeping for equal to that random number modulo 8.

In all fairness to the programmers, this approach would actually give a random number from 1 to 7 if the RNG formula was any good, however for link battles the RNG formula used is very bad. In order to generate a new random value for link battles, the game will multiply the value of the current random number by 5 and add 1 (all done modulo 256 since this is 8 bit arithmetic). But this means that when it attempts to put a Pokémon to sleep, if the random number it gets modulo 8 is zero, then the next random value generated modulo 8 will always be 1.

This affects the distribution of sleep turns heavily in link battles. If the initial random number used when determining if a Pokémon should be put to sleep is uniformly distributed between 0 and 255, then modulo 8 it is equally likely to get any value from 0 to 7 with a 1/8 chance for each. But since it re-rolls the random number if the initial one modulo 8 is zero, which always returns a random value that is 1 greater than a multiple of 8, then the chance of putting a Pokémon to sleep for only 1 turn is actually 1/4, while all other values remain at 1/8.

In pseudocode it looks like this:
C-like:
unsigned char rng_value;                             // initially a uniformly distributed random 8-bit value

...

unsigned char get_sleep_turns() {
    unsigned char sleep_turns = rng_value & 7;       // same as mod 8
    while (sleep_turns == 0) {
        rng_value = (rng_value * 5 + 1) & 255;       // same as mod 256, 8 bit arithmetic is always done mod 256, I'm just including the & 255 for clarity
        sleep_turns = rng_value & 7;                 // same as mod 8
    }
    return sleep_turns;
}
This currently is not how Pokémon Showdown determines whether or not to put someone to sleep. Currently, Showdown generates a random number from 1 to 7 from a uniform distribution when it is determining how long a Pokémon should be put to sleep; which is not how it should work. In reality it should work as I described above; putting a Pokémon to sleep should last for a single turn 1/4 of the time, while all other values happen only 1/8th of the time. I have submitted a pull request which fixes this, which hopefully will be implemented.

Implications:

This affects the metagame in a number of ways. To list a few of the ways I would expect this affects the metagame:
  • It is now much riskier to immediately switch to Tauros as soon as you put an opponent to sleep, since it's now much likelier they wake up the turn it comes in.
  • Jynx's matchup improves against lead Gengar since if Gengar puts Jynx to sleep for 1 turn, Jynx is more likely to instantly wake up, while if Jynx puts Gengar to sleep then since it's slower, it still gets a chance to land a Psychic.
  • Lead Starmie, Alakazam, and Jolteon, are a bit better, since if they get put to sleep they are more likely to wake up early now. This matters especially for Jolteon, since an early wakeup lets it help stave off Zapdos better. I am unsure how much this buffs lead Starmie or Alakazam though.
Conclusion:

If implemented, this would probably be the most significant change to the simulator's mechanics since 2015. I would like to hear what ideas other people have for how this would affect the metagame if this gets put into the simulators. Hopefully you've enjoyed this deep-dive into RBY's mechanics, cheers.

Addendum (GSC Sleep Mechanics):

After looking into how GSC sleep works (credit to Isa for asking me this), I found that because the RNG used for link-battles operates identically to how it operates in RBY and because how it rolls for sleep works almost identically (with a caveat I will address in a moment), a similar thing happens in GSC as well. The one difference between how GSC and RBY roll for sleep durations is that GSC re-rolls the RNG when the random value modulo 8 is either 0 or 7, while in RBY it only re-rolls when the random value is 0 modulo 8. The result of this difference is that in GSC both a 1-turn sleep and a 4-turn sleep have a 1/4 chance of occurring each, all other rolls still have a 1/8 chance of occurring, as is the case in RBY.

Code relevant for this discovery (credit to PokeRed, PokeYellow, and PokeCrystal decompilations):

Code used for handling when a Pokemon is put to sleep:
Pokemon Red: https://github.com/pret/pokered/blob/master/engine/battle/effects.asm#L26
Pokemon Yellow: https://github.com/pret/pokeyellow/blob/master/engine/battle/effects.asm#L26
Pokemon Crystal: https://github.com/pret/pokecrystal/blob/master/engine/battle/effect_commands.asm#L3615


Code used for generating RNG for battles:
Pokemon Red: https://github.com/pret/pokered/blob/master/engine/battle/core.asm#L6668
Pokemon Yellow: https://github.com/pret/pokeyellow/blob/master/engine/battle/core.asm#L6851
Pokemon Crystal: https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm#L6880
 
Last edited:
Interesting discovery, thank you for documenting it.

Do you know if this is similar in GSC?
Update to my previous post: For link battles GSC uses the same RNG formula and generates sleep rolls the same way in link battles, so yes it does also affect GSC.

Edit for clarifying how this works in GSC:
In GSC this works almost identical to how it works in RBY, except it will re-roll when the random number generated is 0 or 7, (not just 0 as in RBY), this doesn't affect the chance that a 1-turn sleep occurs (still 1/4 chance), but it does increase the chance for a 4-turn sleep from 1/8 to 1/4.

Relevant Decomp Code (credit to PokeCrystal decompilation):

Code used when putting Pokémon to sleep (note: SLP_MASK is just 7 in binary, which is 0b111):
https://github.com/pret/pokecrystal/blob/master/engine/battle/effect_commands.asm#L3615

Code used for generating RNG for battles:
https://github.com/pret/pokecrystal/blob/master/engine/battle/core.asm#L6880
 
Last edited:
That’s interesting. Back almost a decade ago, when the BSlam mechanic discovery was made, I distinctly remember the sleep mechanic being looked into as well. There was a player or two who thought that we might have made a mistake implementing wake up. I can’t remember who (it definitely wasn’t Crystal though), had reported that it was distributed uniformly and the way it’s coded on the sim now is more or less correct. I guess nobody checked into the claim after that, because I heard that parroted for years after that. And some people even mentioned that it was looked into already when new players brought it up.

I actually like this change a lot. Gen 1 has felt like just going for the big haxy play to cheese a KO -instead of positioning your win- for a long time now. This sleep nerf helps reverse that a little bit, but also keeps the gen’s unique long sleep mechanic.

Sleep sacing T Wave leads is going to be less of sac if you have a good chance at actually waking up in the late game. Hypnosis and Sing users have also become worse. The zero turn wake up means that you need to hit more poor accuracy moves in a row to actually keep the mon a sleep. Essentially making their accuracy even worse than before.

I’m actually happy for this change and look forward to seeing Showdown be patched so we can see if/how the meta changes. If we go back to more Big 4 style games from the boomer times, I might actually try to find time to play OU tours again.
 
Since this discovery also affects GSC - any small ideas on how this could impact the GSC metas as well? I'm thinking definitely not as heavily as in RBY tho, i feel sleep inducing as a whole is a tad less potent there with most mons running sleep talk anyways
 
I would like to hear what ideas other people have for how this would affect the metagame if this gets put into the simulators.
I considered the impact on the GSC metagame.
(I don't know deeply about RBY, so I don't mention RBY)

This will definitely lead to a decline in the value of Sleep Moves in GSC.
This not only increases the probability of 1 turn awake and decreases the average sleep turns, but also prevents to miss sleeptalk (using sleeptalk on an awake turn) by making it easier to predict an awake turn. In particular, playing which uses Rest (or any other moves) instead of using sleeptalk in sleep turn 4 will become more important.
Note : When facing a Sleep Inducer which outspeeds a Resttalker, missing sleeptalk on turn 4 is more dangerous than continuing sleep turn, and clicking sleeptalk sometimes isn't suitable.

In OU format, the most affected mon is probably Jynx.
She relies on Thief and dice rolls to wall break, and Sleep Move (Lovely Kiss) is indispensable for her as a means of rolling dice.
Nidoking has a similar tendency, but his main wall break methods are good typing (paticularly Toxic immune) and mixed attack moves includeing STAB Earthquake, and he also has slightly niche methods like Roar, so he is less depend on Sleep Move than Jynx in my oppinion.

Smeagle may be the next most influenced mon after Jynx.
Smeagle is a good Baton Passer which can counter phazers with 100% accuracy Sleep Move (Spore), but increasing the probability of 1 turn awake will reduce virtually accuracy.

Snorlax may be affected surprisingly strongly.
Snorlax's Sleep Move (Lovely Kiss) usage rate is not high, but it worsens the matchup against Sleeptalk Snorlax. This matchup is inherently close, and there is a possibility that it will cross 50% win rate (a line that we don't want to cross psychologically).
Even if you were to face a Snorlax other than Sleeptalk, the possibility of losing in a matchup which should originally be advantageous increases.

Exeggutor may not be affected much.
In addition to Sleep Move (Sleep Powder), Exeggutor's moves include a number of powerful ones such as Hidden Power Fire, Thief, and Stun Spore.
As means of wall break, Hidden Power Fire and Thief, and as means of supporting to Machamp and Marowak, Stun Spore, are often a better move than Sleep Powder in my oppinion.
 
Last edited:
Since this discovery also affects GSC - any small ideas on how this could impact the GSC metas as well? I'm thinking definitely not as heavily as in RBY tho, i feel sleep inducing as a whole is a tad less potent there with most mons running sleep talk anyways

It at most makes stalls life a bit easier since sleep sacking Skarmory/ the Flamelax check can be a bit more enticing, so it won't really have as much of an impact as its being implied in RBY. Eggy is a massive loser of this change though: Its' already feeling like it has the flattest sleep game out of the sleepers and it absolutely despises what happens when what it sleeps have odds to just wake up instantly and make Sleep Powder Egg spend its extremely telegraphed explosion early.

Tidbit on Ubers:

Man alive Growth recipient Mewtwo and Barrier + Flamethrower + Toxic become mildly annoying with this change. LK Lax will still just chew through them with high likelyhood in the 1v1 but now having to respect Mewtwo waking up on turn 1 with relative frequency (8.333.... something chance) and just clicking Recover with Barrier boosts..
Annoying. Not broken but definitely annoying.
 
Last edited:
It at most makes stalls life a bit easier since sleep sacking Skarmory/ the Flamelax check can be a bit more enticing, so it won't really have as much of an impact as its being implied in RBY. Eggy is a massive loser of this change though: Its' already feeling like it has the flattest sleep game out of the sleepers and it absolutely despises what happens when what it sleeps have odds to just wake up instantly and make Sleep Powder Egg spend its extremely telegraphed explosion early.
I read this along with the Discord post, and it's likely that the usage rate of Exeggutor's Sleep Powder is expected to decrease, which will affect Exeggutor's playing predictability.
Let me give you one example. I once faced the opponent's Snorlax with my Exeggutor in the tournament. Generally, it was a turn where an ally often used Sleep Powder, and a turn where an opponent was likely to switch to a status absorber including Snorlax, but here the opponent switched to Tyranitar and I chose Explosion, so my Exeggutor was wasted.
I think it's possible that the opponent knew that I don't use Sleep Powder Exeggutor, and I guess this will happen more often in the future.

Also, as I recall, extremely offensive Snorlax without Rest can sometimes have Lovely Kiss. The value of such Snorlax will also decrease a little.
 
Hello everyone, so it's nearly 4 am for me and I've finally been able to write down in notes everything that happens in link battles while the turn takes place and have performed some preliminary analysis on some of the results found. This is all from the PokeRed decomp, however I expect these results to hold true in Pokémon Yellow as well (I will verify these results later). I will later attempt to verify some of these results for Pokémon Crystal as well.

Note that all of the probabilities that follow assume that the previously called RNG value is a uniformly distributed random variable between 0 and 255 (inclusive).

1. Wrap (or other partial trapping moves) can never last 4 turns in link battles, 2 turn wraps happen 50% of the time, 5 and 3 turn wraps happen 25% of the time.
2. Same thing as above happens for multihit moves, most notably this doubles the chance that Jolteon OHKO's Exeggutor with Pin Missile.
3. Damage rolls are completely skewed. In gen 1 uses a number between 217 and 255 for it's random value, however as you might have noticed, this range is quite a bit smaller than the one I listed. So in order to get rolls into this range, it will re-cycle the RNG repeatedly until it gets a random number in this range, but this very heavily affects the distribution of values that occur, with some damage rolls occurring nearly 10% of the time while others are as unlikely as a 1/256 miss. Overall these rolls skew towards the lower end by around 5% or so, marking a net nerf to damage rolls.

To be specific, from lowest damage roll (217) on the left to the highest damage roll (255) on the right, here is the number of times out of 256 each roll will occur.
[1, 2, 21, 8, 15, 1, 4, 2, 9, 12, 1, 3, 26, 2, 11, 1, 5, 3, 17, 6, 1, 23, 9, 3, 6, 1, 2, 7, 6, 3, 1, 19, 2, 5, 5, 1, 4, 6, 2]

I will continue looking at these results tomorrow to look at other correlations between rolls for crits, damage rolls, paralysis, secondary effects, and misses, as well as checking other things such as how secondary effect chances are correlated with damage rolls (not as much mechanics discoveries but still interesting and I said I would answer someone's question about it).
 
I don't know so much about mechanics, so I apologize if I'm asking a low level question.

To be specific, from lowest damage roll (217) on the left to the highest damage roll (255) on the right, here is the number of times out of 256 each roll will occur.
[1, 2, 21, 8, 15, 1, 4, 2, 9, 12, 1, 3, 26, 2, 11, 1, 5, 3, 17, 6, 1, 23, 9, 3, 6, 1, 2, 7, 6, 3, 1, 19, 2, 5, 5, 1, 4, 6, 2]
Was this obtained as a result of analyzing the assembly code?
Assuming that values from 0 to 255 are generated with evenly probability, the algorithm will allocate 1 of them for the lowest damage, 2 of them for the second lowest damage, 21 of them for the third lowest damage... does that mean it was?
 
Hmm I smell another cart accuracy argument on the horizon, which isn't great. The stuff for sleep and multi-hit/turn moves are too fundamental to ignore, but previously smogon staff have said they don't implement RNG quirks (which is bullshit). This was in the context of impossible DV/IV values for certain pokemon, which is different from any damage roll weirdness, but I'm concerned that the latter will nonetheless be swept under the rug in a similar fashion.

Honestly at this point I think we should build an emulator (or rather adapt an open source one) with all the functionality of a simulator. I was actually wanting to do this myself, but I had to give it up bc I didn't really know what I was doing with a project of that scope and I wasn't able to invest the time to upskill

Anyway, amazing work Shellnuts (even though you mentioned not being done investigating yet), it's amazing that we're still learning about RBY this many years after its release and I'm looking forward to these changes shaking things up
 
Last edited:
1. Wrap (or other partial trapping moves) can never last 4 turns in link battles, 2 turn wraps happen 50% of the time, 5 and 3 turn wraps happen 25% of the time.
2. Same thing as above happens for multihit moves, most notably this doubles the chance that Jolteon OHKO's Exeggutor with Pin Missile.
Could you elaborate a bit on this?
 
Partial trapping and Pin Missile were 37.5% to hit 2 or 3 times and 12.5% to hit 4 or 5 times. Turns out in link battles it's 50% 2 times, 25% 3 times, 25% 5 times.
This isn't true in Red/Blue either. In a dozen test battles so far I've also seen significantly more 3-hits than anything else.
4slaps.gif
 
Hi, this thread is incorrect. It's going under the assumption that a random number is ×5+1 of one random number ago. Link battle random numbers are ×5+1 of nine random numbers ago, with the first nine being individually random.

(from Pokemon Speedrunning discord + pre)
 
Last edited:
Hi, this thread is incorrect. It's going under the assumption that a random number is ×5+1 of one random number ago. Link battle random numbers are ×5+1 of ten random numbers ago, with the first ten being individually random.

(from Pokemon Speedrunning discord)
Thank you for correcting me on this, I see this line now I missed this one line while reading through the ASM code https://github.com/pret/pokered/blob/master/engine/battle/core.asm#L6709 which does affect a lot of these results (sleep turn distribution is definitely not what I initially thought they were in the initial post, I will add a correction to it later).

I think it is likely that these values are correlated in a non-random way however, since (from skimming through the decompiled code), while the initial value generated might be random (since it relies on the number of cycles since power-on of the gameboy, the value of the carry bit, the value of rDiv, and the add/subtract bytes), subsequent RNG calls will probably not be due to the consistent number of cycles between RNG calls and since all of the loops the processor executes seem to be very close together when it is generating those initial 10 values (seen here: https://github.com/pret/pokered/blob/master/engine/link/cable_club.asm#L42C1-L48C38). And since the way it generates them is incredibly simple from an arithmetic perspective, it is likely that these correlations are preserved under the LCG operations (though I haven't proven it yet).

I'll probably remain silent for the next bit (to avoid accidentally saying anything wrong) while I go through the code on how the initial generation of those 10 numbers works more rigorously and analyze whether any arithmetic relationships are preserved under these operations.
 
Very glad we didn't have this until now, it's without a doubt bad for competitive games.

First turn wakes were always awful because even if you account for them, there is nothing to do about it.
- Stay in you do no damage that they can't recover, restarting the sleep attempt cycle.
- Switch out to something defensive and you let them burn turns for free while not threating the switch ins.
- Switch to Tauros/Zapdos, the only good move because letting them in and attack for free carries some consequence.

Not only going Tauros was always the best move, it was the only one acceptable really, the rest are just wasting time if the opponent stays in. Boosting the odds of first turn wakes is really bad, it makes people more wary of doing the only good move they should do on a stay in, and they raise the chances of a careless stay in bail out. Going Tauros remains the only good play even with these worse odds, if you assume the pokemon wakes immediatly you have no good moves anyway so you just bite the bullet and cross your fingers.

It isn't the end of the world, just some additional worse odds for the more skilled player to overcome but definetly not good news, luckily none of my business, have fun figuring it out.

Edit: I will leave the comment here even if it turned out false, it's insight for new players i suppose.
 
Last edited:
Very glad we didn't have this until now, it's without a doubt bad for competitive games.

First turn wakes were always awful because even if you account for them, there is nothing to do about it.
- Stay in you do no damage that they can't recover, restarting the sleep attempt cycle.
- Switch out to something defensive and you let them burn turns for free while not threating the switch ins.
- Switch to Tauros/Zapdos, the only good move because letting them in and attack for free carries some consequence.

Not only going Tauros was always the best move, it was the only one acceptable really, the rest are just wasting time if the opponent stays in. Boosting the odds of first turn wakes is really bad, it makes people more wary of doing the only good move they should do on a stay in, and they raise the chances of a careless stay in bail out. Going Tauros remains the only good play even with these worse odds, if you assume the pokemon wakes immediatly you have no good moves anyway so you just bite the bullet and cross your fingers.

It isn't the end of the world, just some additional worse odds for the more skilled player to overcome but definetly not good news, luckily none of my business, have fun figuring it out.
None of it is even true
 
Status
Not open for further replies.
Back
Top