Skip to navigation

Revs on the BBC Micro

Drivers: AwardRacePoints

Name: AwardRacePoints [Show more] Type: Subroutine Category: Drivers Summary: Award points following a race
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * MainLoop (Part 6 of 6) calls AwardRacePoints

This routine awards points to a driver for finishing in the top six in a race, or for getting the fastest lap time. The points awarded are based on the driver's race position, as per the pointsForPlace table: * 9 points for first place * 6 points for second place * 4 points for third place * 3 points for fourth place * 2 points for fifth place * 1 point for sixth place * 1 point for the fastest lap In single-player races, the points are awarded as above. In multi-player races, an algorithm is used to share out the points in a way that takes the relative skills into consideration. Specifically, the routine awards this many points: (U T) * the points from the above list This is how (U T) is calculated: * Single-player race: (U T) = numberOfPlayers = 1, so we award the amount of points shown above * Multi-player race: If we are awarding points to the current player: (U T) = (numberOfPlayers - 1) * numberOfPlayers If we are awarding points to a human player but not the current player: (U T) = numberOfPlayers If we are awarding points to a computer driver: (U T) = (numberOfPlayers - 1) * 2 I have no idea why the algorithm works like this. It needs more analysis!
Arguments: X The race position to award points to: * 0 to 5 for the first six places * 6 for the fastest lap
.AwardRacePoints LDA #0 \ Zero the points in (racePointsHi racePointsLo) for STA racePointsLo,X \ race position X STA racePointsHi,X STA U \ Set U = 0, to act as the high byte of (U T) LDY driversInOrder,X \ Set Y to the number of the driver in race position X CPX #6 \ If we called the routine with X = 0 to 5, then jump to BNE poin1 \ poin1 to skip the following instruction LDY driversInOrder \ We called the routine with X = 6, so set Y to the \ winning driver's number, i.e. the driver with the \ fastest lap .poin1 \ By this point, Y contains the number of the driver we \ want to give the points to, so now we calculate the \ number of points to award LDA numberOfPlayers \ Set A to the number of players - 1 SEC SBC #1 BEQ poin3 \ If A = 0 then there is only one player, so jump to \ poin3 to skip the following CPY currentPlayer \ If Y is the number of the current player, jump to BEQ poin2 \ poin2 CPY lowestPlayerNumber \ If Y >= lowestPlayerNumber then this is a human BCS poin3 \ player but not the current player, so jump to poin3 \ If we get here then we are awarding points to a \ computer-controlled driver ASL A \ Double the value of A, to use as the value of T, so \ we will get: \ \ (U T) = (0 T) \ = T \ = A * 2 \ = (numberOfPlayers - 1) * 2 BNE poin4 \ Jump to poin4 (this BNE is effectively a JMP, as A is \ never zero) .poin2 \ If we get here then we are awarding points to the \ current player STA U \ Set U = A = numberOfPlayers - 1 LDA numberOfPlayers \ Set A = numberOfPlayers JSR Multiply8x8 \ Set (A T) = A * U \ = (numberOfPlayers - 1) * numberOfPlayers STA U \ Set (U T) = (A T) \ = (numberOfPlayers - 1) * numberOfPlayers JMP poin5 \ Jump to poin5 .poin3 \ If we get here then either there is only one player, \ or we are awarding points to a human player but not \ the current player LDA numberOfPlayers \ Set A to the number of players, to use as the value of \ T, so we will get: \ \ (U T) = (0 T) \ = (0 numberOfPlayers) \ = numberOfPlayers BNE poin4 \ This instruction has no effect as poin4 is the next \ instruction anyway .poin4 STA T \ Store A in T, so this sets (U T) = (U A) .poin5 SED \ Set the D flag to switch arithmetic to Binary Coded \ Decimal (BCD) \ We now do the following addition 256 * U + T times, so \ the total number of points added is: \ \ (256 * U + T) * (9, 6, 4, 3, 2 or 1) \ \ or putting it another way: \ \ (U T) * (9, 6, 4, 3, 2 or 1) .poin6 LDA pointsForPlace,X \ Add the X-th entry in pointsForPlace to the X-th entry CLC \ in (racePointsHi racePointsLo), starting with the low ADC racePointsLo,X \ bytes STA racePointsLo,X LDA racePointsHi,X \ And then the high bytes ADC #0 STA racePointsHi,X DEC T \ Decrement the counter in T BNE poin6 \ Loop back to poin6 so we do the addition a total of T \ times DEC U \ Decrement the counter in U BPL poin6 \ Loop back to poin6 so we do an additional U loops, \ with the inner loop repeating 256 times as T is now 0, \ so this does a total of 256 * U additional additions JSR AddRacePoints \ Add the race points from above to the accumulated \ points for driver Y RTS \ Return from the subroutine