diff --git a/inform7/Internal/Inter/BasicInformKit/Sections/Startup.i6t b/inform7/Internal/Inter/BasicInformKit/Sections/Startup.i6t index 7017afe0a..35947431d 100644 --- a/inform7/Internal/Inter/BasicInformKit/Sections/Startup.i6t +++ b/inform7/Internal/Inter/BasicInformKit/Sections/Startup.i6t @@ -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; ];