Retrocomputing Stack Exchange is a question and answer site for vintage-computer hobbyists interested in restoring, preserving, and using the classic computer and gaming systems of yesteryear. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Many programs make use of randomness, from BASIC guess-the-number games to encryption key generators. This randomness could have been generated in many, many different ways: hardware, software, software seeded by hardware...

What techniques were used to generate randomness in early computers, and were cryptographically-secure sources of randomness commonly used?

share|improve this question
2  
Note there even is a classic book that can provide random numbers. See amazon.com/Million-Random-Digits-Normal-Deviates/dp/08330304‌​77/… and make sure you read the reviews ;) – tofro 17 hours ago
    
Some early Final Fantasy games are notorious for using a simple static list of 256 shuffled values, plus a variety of variables that are hard to predict, such as the number of frames elapsed, a step counter, various counters that are incremented only in some scenes, etc. It looks random, but it can be manipulated by speedrunners. – isanae 8 hours ago

The one-word answer to your question is "badly".

The way to create random numbers quickly is via a Pseudorandom number generator (PRNG). That Wikipedia page gives the history of PRNGs and in particular notes that linear congruential generators are/were common, with quite a few failings including periodicity (i.e. it cycles through the same sequence of values), poor distribution, predictability, and quite a few other faults that make them poor choices for use in cryptography. That page also describes linear-feedback shift registers but I don't recall them being used in the BASICs of my youth.

The first decent PRNG is the Mersenne Twister, which was invented in 1997. It requires 2.5kiB of RAM to store its state, and is relatively computationally intensive, so it would be ludicrous to provide it as the standard random number source of a BASIC running on a machine with only a few tens of kilobytes of RAM and a slow CPU even if the algorithm had been known at the time.

Cryptographically-secure random numbers need the aid of a hardware device that contains true randomness, such as interrupt timings from I/O devices, or even a dedicated quantum noise source. Again, older machines tended not to have much in the way of interrupt-driven I/O, commonly using a vertical blank interrupt to trigger a polling process instead.

For a concrete example, look at the source of the Sinclair ZX Spectrum's RND function. In case that link goes bad, I'll also summarise it. There is a 16 bit system variable SEED which unsurprisingly contains the current random number seed. When you call RND, it computes (SEED+1)*75 mod 65537 - 1 which it stores in SEED, and returns SEED / 65536, i.e. a value in the range [0, 1).

Because SEED is just 16 bits, it's clear that this PRNG can't have more than 65,536 possible states. Mathematical analysis of the function it uses to generate the next SEED will show that it has exactly 65,536 states, and thus will repeat and generate the same values after that many calls. It's alright for deciding where to put aliens on the screen, but I wouldn't trust my online banking to it...

share|improve this answer
3  
"dedicated quantum noise source". Hooking up with a Geiger Counter was not unknown. – PCARR 21 hours ago

Interesting question. After all, it's the main job of a computer to come up with deterministic results, which is pretty much the opposite of pure randomness.

In reality, coming up with a series of non-deterministic numbers from a digital circuit only is considered technically impossible. Modern computers use "known noise" in their peripheral devices or even dedicated noise generator circuits to seed their random number generator. Older home computers didn't really have that much periphery to choose from so used "close-to random" values as a seed like video flyback counters or "time since switched on".

Once you have a (more or less random) seed (initial value), a simple RNG (Random Number Generator) typically consists of an LFSR (linear feedback shift register) that runs the seed through a binary polynom, generating a new value from the previous one that "looks" random (picture source: Wikipedia) (Today's computers tend to use much more sophisticated RNGs)

Linear Feedback Shift Register (Source: Wikipedia)

Note what "looks like hardware" in the picture can easily be reproduced by software in a computer. A random number would then just be the current value of that 8 bit register. A new random value is being generated on every fetch by shifting the old value one bit and feeding back the "carry" and bit positions determined by the chosen polynom into the lowest bit.

In pseudocode, an RNG looks somewhat like this (implements the above picture):

carry = (x & $80) != 0 
oldx = x
x = x >> 1
x |= (carry + (oldx & $04) > 0 + (oldx & $10) > 0 + (oldx & $20) > 0) != 0

In reality, most of the RNGs did, different from the example, normally use 16-bit shift registers and the polynoms might look different.

The initial state i.e. the seed of the shift register is normally set by the RANDOMIZE (or similar) Basic keyword. This might be the most misunderstood and misused basic keyword ever - It somehow seems to imply to make the RNG "more random" but instead does the exact opposite - By seeding the RNG with a constant number, you can make different computers with the same BASIC produce the exact same sequence of random numbers. Using this technique you can easily create encryption programs that can only be decrypted by the same RNG using the initial seed as a key (i.e. cyphers produced by the Commodore C64 that can only be deciphered by a C64). I also remember a Basic program I once wrote for the Sinclair QL that calculated the value of PI by simulating rainfall (random coordinates) onto a circle in a square and determining whether the raindrop fell into the circle.

A "cryptographically secure" source of a seed for the RNG is not known to me from early computers - At least not of home computers. After all, proper encryption which is the main use for RNGs was not necessary on a non-networked computer (most of the early computers were) as long as you had a proper door in front of it. Only the development of larger networks and the internet made encryption really necessary - before that time, you could simply rely on physically securing computers.

share|improve this answer
    
Don't forget that one of the first computer applications — if not the first, as ENIAC spent much of its time doing it — was running Monte Carlo simulations. These consume quantities of random numbers, and are unrelated to networking. – scruss 7 hours ago
    
RANDOMIZE TIMER was common at least in games written in BASIC for the IBM PC family. Not much better from a cryptographic point of view than calling RANDOMIZE with a fixed seed, but good enough for hobbyist games. – Michael Kjörling 2 hours ago
    
@MichaelKjörling Not the least bit better than not calling RANDOMIZE at all on most computers. And, unfortunately, not random at all when for example called from a program that was started from AUTOEXEC.BAT that always finds the same timing. – tofro 2 hours ago
    
RANDOMIZE TIMER was good enough for casual use (but definitely not in any way good enough for cryptographic use) if your system had a RTC, which all IBM PC class machines from the AT onwards did, and which could be retrofitted to earlier systems. Using the time-since-power-on also wasn't too terrible (not saying good) if your system didn't have a RTC. Note that my comment was qualified with "the IBM PC family". – Michael Kjörling 2 hours ago
    
RANDOMIZE 1 was really useful when trying to make sure a bug wasn't caused by the RNG, or to get a random-ish pattern for a background. – Chris H 1 hour ago

Some games used the contents of ROM, or a subset of it, starting from a timer-fed address and looping. Because of the limited amount of space available, ROMs tended to be written to be very compact though you will sometimes get blocks of zeroes or repeating data, which is why a subset is often used. Other games on the Z80 CPU used the bottom 7 bits of the R register, which is actually there to provide a refresh signal for DRAMs, and increases by 1 every instruction fetch. This is often random enough for game purposes though there's a strong correlation between close reads. There wasn't much call for encryption-strength randomness on a computer not attached to a network. Some of the game loaders used scrambling and tricks to protect their games from being cracked or modified, but this decryption had to actually be deterministic to produce the same results every time.

share|improve this answer
    
Welcome to Retrocomputing Stack Exchange. Thanks for the answer. Were you involved in creating games for the Z80? If so, you might want to have a look at some Z80 questions; perhaps you could answer a few. – wizzwizz4 21 hours ago
    
Reading a random value from ROM needs a random address - so back at square one? – tofro 20 hours ago
1  
@tofro this is the problem with every pseudorandom number generation system, you need a starting value or seed. The seed could be the number of frames since the computer was switched on, for example; this has some entropy if the user needs to start the game themselves or load it from cassette. From then on you could just keep an incrementing pointer into ROM which loops round at some maximum value. It will repeat eventually, but hopefully with a large enough period that nobody will notice. – user3570736 19 hours ago
    
@user3570736 I think it's been mentioned already somewhere here: Good enough to determine the position of an alien on screen, but not much else - A simple role-playing game would probably already be unfair using such numbers (Note, on a Z80 system, for example, you're pretty likely to hit a 0C9h (RET) or 0C3H (JMP) and pretty unlikely a 076h (HLT) in code space. The likelyhood of certain opcodes, constants and hard-coded addresses is much lower than that of others.) – tofro 1 hour ago

The Commodore 64 had a built-in audio processor, called the SID chip. This chip would generate sounds based on (among other things) a frequency (e.g. 440 Hz) and a wave shape (square, sawtooth, etc.). One of the options was to generate "white noise", which is basically a random series of volumes. Now the fun bit about this is that you could read a snapshot of the current volume from one of the SID registers, which in white noise mode, was an essentially random value from 0-255. This technique was commonly used on this platform. Even, if I recall correctly, in BASIC programs, though BASIC had a built-in random function.

Now, I'm pretty sure this randomness was generated in hardware, which probably means it was closer to true randomness than the software techniques described in the other answers. Or it may have been a variant of the circuit described in tofro's answer. In any case, there may well have been biases in the distribution or other features in the values generated that would make these values weak for cryptography.

share|improve this answer
    
Welcome to Retrocomputing. Thanks for the answer; you might want to read the tour to get that badge. I completely forgot about audio chips' randomness; sometimes this was quantum randomness (cascading something something) which is technically cryptographically secure but hard to control. – wizzwizz4 16 hours ago
    
This works well with the SID chip because it isn't 100% digital and contains actual analog filter components which make the output of each chip slightly individual, plus its not well shielded and susceptible to RF noise which only adds to the randomness. – mnem 8 hours ago

On some games like "Super Mario 64", the randomness was determined by simply XORing the value whenever it's called (technical detail can be found here). This allowed it to be exploited, especially on places where it's never called naturally, like Peach's castle, but by doing moves that generate dust (which calls the RNG function itself), it can be exploited. One example of such a glitch can be seen here.

share|improve this answer
    
Could you include some of the technical details in your answer? – wizzwizz4 20 hours ago
    
@wizzwizz4 sure, I will add them asap. – Avery 20 hours ago
    
1:30 has the algorithm. – wizzwizz4 20 hours ago

Anyone who considers arithmetical methods of producing random digits is, of course, in a state of sin — John von Neumann

The method that RAND used to calculate their A Million Random Digits with 100,000 Normal Deviates is described in this brief paper: History of RAND's Random Digits: Summary from 1949. In summary, the gated output of a gas-filled thermionic valve (such as a 6D4 Thyratron, well known to produce noise under certain configurations) was used to increment a five bit counter. Once per second the noise signal was interrupted and the counter read through a BCD converter to produce decimal digits. As the counter would overflow more than 3000 times per second and was fed by pulses with very fast random timing, the results passed all randomness tests available at the time. A similar gas-discharge valve noise system was used in the UK's random draw generator (ERNIE) for premium bonds.

Alan Turing identified a very early need for true random numbers in computing, and his design for the never-built Automatic Computing Engine (ACE) (1945-6) was to include valve-based noise generators. These were to be used to assist in Monte Carlo simulations, as developed by Ulam for nuclear fission modelling.

(I seem to remember reading the statement about Turing and RNGs in George Dyson's book Turing's Cathedral, but I no longer have a copy to check.)

share|improve this answer
    
Wow. Tip of the proverbial hat to you; you really took the OP's mention of "early computers" to the next level compared to the other existing answers. – Michael Kjörling 2 hours ago

Many early systems used the RANDU PRNG (seed = seed*65539 mod 231; the initial seed must be an odd number) which happened to be not very random. If it is used to generate 3D coordinates, the resulting points are positioned on a few fixed planes. Another visualization of this in an implementation of BASIC on Elektronika BK-0010 is here.

Testing for RANDU can be done by drawing a few thousands of pixels with

PSET (RND*width,RND*height),RND*numcols

and observing the diagonal stripe pattern.

share|improve this answer
    
The Elektronika BASIC was reportedly based on a version of the MSX Basic; thus the latter might have the same PRNG algorithm. – Leo B. 1 hour ago

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.