Revs on the BBC Micro

# Drivers: SetDriverSpeed

```       Name: SetDriverSpeed                                          [Show more]
Type: Subroutine
Category: Drivers
Summary: Set the speed for a specific driver
Deep dive: Tactics of the non-player drivers
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* InitialiseDrivers calls SetDriverSpeed
* ProcessTime calls SetDriverSpeed

Arguments:

setSpeedForDriver    The number of the driver to set the speed for

Returns:

X                    The number of the previous driver

setSpeedForDriver    Points to the next driver, ready for the next call to
SetDriverSpeed

.SetDriverSpeed

LDX setSpeedForDriver  \ Set X to the driver number to initialise

\ We now start a lengthy calculation of a figure in A
\ that we will add to the track's base speed to
\ determine the speed for this driver, with a higher
\ figure in A giving the car a higher speed in the race

LDA VIA+&68            \ Read 6522 User VIA T1C-L timer 2 low-order counter
\ (SHEILA &68), which decrements one million times a
\ second and will therefore be pretty random

PHP                    \ Store the processor flags from the random timer value
\ on the stack

AND #%01111111         \ Clear bit 0 of the random number in A, so A is now in
\ the range 0 to 127

\ The following calculates the following:
\
\   * If A is in the range 0 to 63, A = A mod 4
\
\   * If A is in the range 64 to 127, A = (A - 64) mod 7
\
\ Given that A starts out as a random number, this will
\ produce a random number with the following chances:
\
\   50% of the time, 25% chance of 0 to 3
\   50% of the time, 12.5% chance of 0 to 7
\
\ So the probability of getting each of the numbers from
\ 0 to 7 is:
\
\   0 to 3 = 0.5 * 0.25 + 0.5 * 0.125 = 0.1875 = 18.75%
\   4 to 7 = 0.5 * 0.125              = 0.0625 =  6.25%
\
\ So we're three times more likely to get a number in
\ the range 0 to 3 as in the range 4 to 7

LDY #16                \ Set a loop counter in Y to subtract 16 lots of 4

.fast1

CMP #4                 \ If A < 4, jump to fast3, as A now contains the
BCC fast3              \ original value of A mod 4

SBC #4                 \ A >= 4, so set A = A - 4

DEY                    \ Decrement the loop counter

BNE fast1              \ Loop back until we have either reduced A to be less
\ than 4, or we have subtracted 16 * 4 = 64

\ If we get here then the original A was 64 or more,
\ 64, and A is now in the range 0 to 63

LDY #9                 \ Set a loop counter in Y to subtract 9 lots of 7

.fast2

CMP #7                 \ If A < 7, jump to fast3, as A now contains the
BCC fast3              \ original value of (A - 64) mod 7

SBC #7                 \ A >= 7, so set A = A - 7

DEY                    \ Decrement the loop counter

BNE fast2              \ Loop back until we have either reduced A to be less
\ than 7, or we have subtracted 9 * 7 = 63

\ If we get here then the original A was 127, and we
\ first subtracted 64 and then 63 to give us 0

.fast3

\ We now have our random number in the range 0 to 7,
\ with 0 to 3 more likely than 4 to 7

PLP                    \ Retrieve the processor flags from the random timer
\ value that we put on the stack above, which sets the
\ N flag randomly (amongst others)

JSR Absolute8Bit       \ The first instruction of Absolute8Bit is a BPL, which
\ normally skips negation for positive numbers, but in
\ this case it means the Absolute8Bit routine randomly
\ changes the sign of A, so A is now in the range
\ -7 to +7, with -3 to +3 more likely than -7 to -4 or
\ 4 to 7

ASL A                  \ Set A = A << 1, so A is now in the range -14 to +14,
\ with -6 to +6 more likely than -14 to -7 or 7 to 14

SEC                    \ Set A = A - driverGridRow for this driver
SBC driverGridRow,X    \
\ So A is left alone for the two cars at the front of
\ the grid, is reduced by 1 for the next two cars, and
\ is reduced by 9 for the two cars at the back

STA T                  \ Set T = A

\ By this point, the value in A (and T) is in the range:
\
\   * -14 to +14 for the front two cars
\   * -15 to +13 for the next two cars
\     ...
\   * -23 to +4 for the last two cars
\
\ We now alter this according to the race class

LDY raceClass          \ Set Y to the race class

DEY                    \ Decrement Y, so it will be -1 for Novice, 0 for
\ Amateur and 1 for Professional

BEQ fast5              \ If Y = 0 (Amateur), jump to fast5 to leave A alone

\ If we get here, then the race class is Novice

ASL A                  \ Set A = A << 1
\
\ so A is now in the range:
\
\   * -28 to +28 for the front two cars
\   * -30 to +26 for the next two cars
\     ...
\   * -46 to +8 for the last two cars
\
\ This makes the range of speeds less tightly bunched,
\ so the race is less intense

.fast4

\ If we get here, then the race class is Professional

ROL T                  \ Shift bit 7 of T into the C flag, and because T = A,
\ this puts bit 7 of A into the C flag

ROR A                  \ Shift A right while inserting a copy of bit 7 into
\ bit 7, so this effectively divides A by two while
\
\   A = A / 2
\
\ So A is now in the range:
\
\   * -7 to +7 for the front two cars
\   * -8 to +6 for the next two cars
\     ...
\   * -12 to +2 for the last two cars
\
\ This makes the range of speeds more tightly bunched,
\ so the race is more intense

.fast5

\ By this point we have our value A, which determines
\ the speed of the driver based on our random number,
\ the car's grid position and the race class, so now we
\ add this to the track's base speed to get the driver's
\ speed for the race
\
\ The track's base speed is different depending on the
\ race class, so taking Silverstone as an example, we
\ get these final ranges for the front two cars:
\
\   * Novice       = 134 plus -28 to +28 = 106 to 162
\   * Amateur      = 146 plus -14 to +14 = 132 to 160
\   * Professional = 153 plus  -7 to  +7 = 146 to 160
\
\ and these final ranges for the two cars at the back:
\
\   * Novice       = 134 plus -46 to +8 =  88 to 142
\   * Amateur      = 146 plus -23 to +4 = 123 to 150
\   * Professional = 153 plus -12 to +2 = 141 to 155

CLC                    \ Set the driverSpeed for driver X to baseSpeed + A