YoYoGames / GameMaker-Bugs

Public tracking for GameMaker bugs
24 stars 8 forks source link

Increase the number of possible RNG states #3006

Open KormexGit opened 1 year ago

KormexGit commented 1 year ago

Is your feature request related to a problem?

Currently, if you run this code in gamemaker var roll; repeat(10000000000000000) { randomize(); roll = irandom_range(1, 30000); if roll == 1 { show_message(roll); } } the message will never ever ever appear. This is because gamemaker only has 65536 possible RNG states, and 0 of them are capable of rolling a 1 on a irandom_range(1, 30000) check that immediately follows setting the seed. The same issue occurs if you use random_set_seed and increase it every iteration. This causes problems for games that save the player's seed and set the seed to it before doing certain rolls for save-scum prevention. Even if every player has a different starting seed, it will still never roll 1, and now the check will fail for every single player, every single time.

Describe the solution you'd like

A much larger number of RNG states would greatly reduce the chances of these sorts of situations happening. 65536 isn't that many when dealing with randomization of large numbers.

Describe alternatives you've considered

Changing how RNG works could potentially cause problems for existing games that use saved seeds, so perhaps some new alternative way to generate seeds could be added, or the old way of handling seeds could be left in as separate functions for legacy support.

Additional context

No response

colinator27 commented 1 year ago

For a code explanation, this would essentially be changing the following line on HTML5 (presumably a similar line exists on other runtime versions): https://github.com/YoYoGames/GameMaker-HTML5/blob/b38464df25ed7de8ab378896ef84f81a4223c102/scripts/functions/Function_Maths.js#L432C3-L432C3

s = (((s * 214013 + 2531011) >> 16) & 0x7fffffff) | 0;

Currently, the above line has a bitwise right-shift of 16 bits, which loses 16 bits worth of information from the 32-bit seed. Honestly, I'm not sure why that shift is there in the first place - this seems to be a LCG to populate the initial RNG state.

Macj0rdan commented 1 year ago

@colinator27 I need a temp fix for this so redid this code in gamemaker code and removed the bitshift. Will that be enough until yoyo fixes this?

colinator27 commented 1 year ago

@colinator27 I need a temp fix for this so redid this code in gamemaker code and removed the bitshift. Will that be enough until yoyo fixes this?

Depends on your specific use case, and how YoYo decides to address this. You can always keep your own RNG code for yourself, though, if you want it to remain the same forever.

Macj0rdan commented 1 year ago

@colinator27 I need a temp fix for this so redid this code in gamemaker code and removed the bitshift. Will that be enough until yoyo fixes this?

Depends on your specific use case, and how YoYo decides to address this. You can always keep your own RNG code for yourself, though, if you want it to remain the same forever.

Well in this case I just want the randomness to not have the issue described above. I reimplemented the random functions but removed the 16 bitshift and now the PRNG seems to be doing what it should and not missing the roll sometimes But maybe this ruins the generator in a way I am not considering. I don't care about cryptography I just want to be random enough for ingame seeded drops

DrunkenParrot commented 1 year ago

@Macj0rdan

@colinator27 I need a temp fix for this so redid this code in gamemaker code and removed the bitshift. Will that be enough until yoyo fixes this?

Depends on your specific use case, and how YoYo decides to address this. You can always keep your own RNG code for yourself, though, if you want it to remain the same forever.

Well in this case I just want the randomness to not have the issue described above. I reimplemented the random functions but removed the 16 bitshift and now the PRNG seems to be doing what it should and not missing the roll sometimes But maybe this ruins the generator in a way I am not considering. I don't care about cryptography I just want to be random enough for ingame seeded drops

So did you pretty much copy/paste the random functions from that JavaScript file ( InitRandom, rand, irandom, etc.) as-is and only changed the one line above to this? Or were there other changes required?

s = ((s * 214013 + 2531011) & 0x7fffffff) | 0;

Macj0rdan commented 1 year ago

Yeah thats basically what I did @DrunkenParrot. Redo all the random functions in GML, rename them to avoid collisions and then use them instead of the default ones. Just be warned, it is a good bit slower than using the normal functions.

Macj0rdan commented 8 months ago

Hi is there any update on this? The custom solution I had to use is a good bit slower then just using the native RNG code.