mirror of
https://github.com/ganelson/inform.git
synced 2024-07-08 10:04:21 +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
|
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
|
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,
|
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
|
for instance).
|
||||||
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.
|
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,
|
"Anyone who considers arithmetical methods of producing random digits is,
|
||||||
of course, in a state of sin" (von Neumann).
|
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) {
|
if (BasicInformKit`FIX_RNG_CFGF) {
|
||||||
#Ifdef TARGET_GLULX;
|
#Ifdef TARGET_GLULX;
|
||||||
@random 10000 i;
|
@random 10000 i;
|
||||||
|
@ -122,6 +143,7 @@ of course, in a state of sin" (von Neumann).
|
||||||
#Endif;
|
#Endif;
|
||||||
}
|
}
|
||||||
if (RNG_SEED_AT_START_OF_PLAY) VM_Seed_RNG(RNG_SEED_AT_START_OF_PLAY);
|
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;
|
rfalse;
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in a new issue