How Revs generates random numbers
Most games contain a sprinkling of randomness, even those that model the real world as closely as Revs. It might not be in the same ballpark as Elite, which contains an extremely sophisticated random number generation system (as explained in this deep dive in my Elite project), but Revs still has a fair amount of random behaviour in the mix.
Just like Aviator, Geoff Crammond's previous game, Revs uses a common method of adding a random element to the code: it reads the 6522 User VIA's timer, and specifically the T1C-L timer 2 low-order counter, which is mapped to memory in SHEILA &68 (you can read about Aviator's similar approach in this deep dive in my Aviator project). This timer decrements one million times a second, so assuming it is read in a fairly asynchronous manner, the result will normally be a pretty random number.
This approach is used in the following places:
- The MakeDrivingSounds routine randomly changes byte #5 of sound #4 (the low byte of the pitch for the crash/contact sound), so that on 75% of calls to the routine, the sound has its pitch set randomly. This routine is called four times on each iteration of the main driving loop, so the chances are that the sound will randomise on three of those four calls.
- Part 2 of the ProcessOvertaking routine implements a random element in the overtaking process for cars that are not visible (so you never see any randomness on-screen, only in the race results). Specifically, when a car is trying to overtake the car in front, 3% of the time the overtaking car will slam on its brakes, but only if both drivers are in the top four positions, and only if the car being overtaken is not accelerating. See the deep dive on tactics of the non-player drivers for more details.
- The ProcessEngineStart routine uses random numbers to decide whether to start the engine when "T" is being pressed, though the chances of a clean start are also affected by the setting of the oddsOfEngineStart variable (so we can make it harder to restart the car after a crash, for example).
- The ThrobRevsNoTorque routine adds a random throb to the rev count when the clutch is disengaged.
- The ApplyGrassOrTrack routine generates a random number in the range 1 to 7 that is higher with higher speeds, and which we store in the bumpyGrassHeight variable. This defines the unevenness of the grass for when we veer off the track, giving us a randomly bumpy horizon when we spin off the track.
- The SetDriverSpeed routine uses a random element when generating target driver speeds for non-player drivers in the race. These are regenerated throughout the race, to add a bit of variety to the opposition. See the deep dive on tactics of the non-player drivers for more details.
- The DrawCarInMirror routine contains my favourite example of random behaviour in Revs. If the engine is running, then any cars that are shown in the wing mirrors get randomised to simulate engine shudder; it's a very effective use of the VIA timer lookup.
These are the only random numbers in the whole game; everything else is modelled on physics, rather than chance.