mirror of
https://github.com/ganelson/inform.git
synced 2024-07-05 08:34:22 +03:00
Partially mitigate the flaw in Glulx interpreter RNGs
This commit is contained in:
parent
dc839857d0
commit
71e5b394d2
|
@ -102,14 +102,35 @@ of the current time of day, which is unlikely to repeat or show any pattern
|
|||
in real-world use. However, early Z-machine interpreters often did this quite
|
||||
badly, starting with poor seed values which meant that the first few random
|
||||
numbers always had something in common (being fairly small in their range,
|
||||
for instance). To obviate this we extract and throw away 100 random numbers
|
||||
to get the generator going, shaking out more obvious early patterns, but
|
||||
that cannot really help much if the VM interpreter's RNG is badly written.
|
||||
for instance).
|
||||
|
||||
More recently, many Glulx interpreters also had
|
||||
[a major flaw](https://intfiction.org/t/lack-of-randomness-sometimes-when-compiling-for-glulx/64533)
|
||||
in which repeatedly calling `random(N)` when `N` was a power of 2 resulted in
|
||||
there only being `N` distinct sequences. Even worse, the first number of each
|
||||
sequence might be the same! This would mean that, for example, if a mystery
|
||||
game randomly selected the murderer from five candidates the results might
|
||||
appear random, but if there were only four candidates then the same one would
|
||||
be chosen *every* playthrough.
|
||||
|
||||
To attempt to partially mitigate these problems, we extract and throw away a
|
||||
number of random numbers to get the generator going, shaking out more obvious
|
||||
early patterns. Because of the particular nature of the flaw in those Glulx
|
||||
interpreters, we do this a random number of times.
|
||||
|
||||
Most interpreters have been updated recently to improve their random algorithms,
|
||||
but if we're running in something really old, there's only so much we can do
|
||||
to account for it. Story files which rely on quality randomness may need to
|
||||
use an extension to use a new algorithm instead of the one provided by the
|
||||
interpreter. Extensions are also needed if you want a random algorithm that is
|
||||
consistent across interpreters (for example, to be able to share a seed that
|
||||
generates the same dungeon in an procedurally-generated RPG.)
|
||||
|
||||
"Anyone who considers arithmetical methods of producing random digits is,
|
||||
of course, in a state of sin" (von Neumann).
|
||||
|
||||
=
|
||||
[ SEED_RANDOM_NUMBER_GENERATOR_R i;
|
||||
[ SEED_RANDOM_NUMBER_GENERATOR_R i count;
|
||||
if (BasicInformKit`FIX_RNG_CFGF) {
|
||||
#Ifdef TARGET_GLULX;
|
||||
@random 10000 i;
|
||||
|
@ -122,6 +143,7 @@ of course, in a state of sin" (von Neumann).
|
|||
#Endif;
|
||||
}
|
||||
if (RNG_SEED_AT_START_OF_PLAY) VM_Seed_RNG(RNG_SEED_AT_START_OF_PLAY);
|
||||
for (i=1: i<=100: i++) random(i);
|
||||
count = random(97);
|
||||
for (i = 1: i <= count: i++) random(i);
|
||||
rfalse;
|
||||
];
|
||||
|
|
Loading…
Reference in a new issue