Lander uses a random-number algorithm from the ARM Evaluation System
Like almost all games, Lander needs a reliable source of random numbers. That said, random numbers are only used in seven places in the entire game:
- AddMovingParticleToBuffer adds a random element to a particle's lifespan and initial velocity.
- AddSmokeParticleToBuffer sets a random grey colour for smoke particles.
- AddDebrisParticleToBuffer sets a random purple-brownish-green colour for debris particles.
- AddSprayParticleToBuffer sets a random blue colour for spray particles.
- DropRocksFromTheSky randomly decides whether to drop a rock, depending on the current score.
- DropARockFromTheSky sets a random purple-brownish-green colour for falling rocks.
- PlaceObjectsOnMap places objects randomly on the object map before the start of each new game.
Each of these routines calls the GetRandomNumbers routine to generate two random numbers, which are returned in R0 and R1. Normally, at this point in a deep dive, I would explain the random number algorithm, but this time I'm going to leave that to the experts, as frankly this algorithm is enough to make my head spin.
Interestingly, the random number algorithm in Lander is taken directly from the original 1986 ARM Assembler manual that came with Acorn's ARM Evaluation System. This was the world's first ARM-based development system, and its "cheese wedge" case houses an ARM1 processor in a second processor that you plug into the Tube interface in a BBC Micro or BBC Master. This is the exact system on which Lander was birthed, so it's not much of a surprise to see example code from the manual sneak into the platform's very first game (see the deep dive on Lander's origins on the ARM1 for details).
Here's the relevant page from that manual (it's in section 11.2 on page 96):
The same code also appears in later Acorn manuals, such as Acorn Desktop Assembler (release 2), where it's on page 186.
Here's the algorithm's description from the manual:
It is often necessary to generate (pseudo-)random numbers and the most efficient algorithms are based on shift generators with exclusive-or feedback rather like a cyclic redundancy check generator. Unfortunately the sequence of a 32-bit generator needs more than one feedback tap to be maximal length (that is 2^32-1 cycles before repetition). A 33-bit shift generator with taps at bits 20 and 33 is required. The basic algorithm is newbit := bit33 eor bit20, shift left the 33 bit number and put in newbit at the bottom. Then do this for all the newbits needed, that is 32 of them. Luckily this can all be done in five S cycles.
If you understand this, good for you! And if you don't, then you can at least join me in appreciating this algorithm's origins...