Skip to navigation

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 BPL fast4 \ If Y = 1 (Professional), jump to fast4 \ 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 JMP fast5 \ Jump to fast5 to skip the following .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 \ keeping the sign intact: \ \ 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 ADC baseSpeed STA driverSpeed,X JSR GetPositionAhead \ Set X to the number of the position ahead of the \ driver whose speed we just set STX setSpeedForDriver \ Set setSpeedForDriver = X \ \ So the next call to the routine will set the speed for \ the next driver ahead RTS \ Return from the subroutine