Prev: 9BF4 Up: Map Next: 9C3D
9BFD: Random number in a range
Returns a random number in A in the range -C to +C (signed). The random byte is produced from the seed at B5FE (set from the R register in 6C27), the counter at $B602 and a byte fetched from memory.
The random bytes come from memory itself. A 16-bit counter at $B602 is increased on every call and used as an address; the byte found there (and one a little further on) is mixed with the previous result. So the program code, the tables and even the ROM serve as the game's random number table, and the R register seed from the start of the game (6C27) decides where the sequence begins. A result equal to the previous one is thrown away.
The way it narrows the random byte down to the range is unusual: B is set to 2*C, and then the random byte is halved (SRL A) until it is no more than B. Finally C is subtracted. Because 0-255 has to be halved several times, the upper half of the range gets far more than its share: with C=10, values 0-10 of the byte (results -10 to 0) mostly come only from the original byte being 0-10 directly, while 11-20 are hit by many different starting values. For C=10 the results come out approximately: each of -10 to -1: 1/256; 0: 16/256; +1 to +5: 31/256 each; +6 to +10: 15/256 each.
Input
C Range
Output
A Random value from -C to +C
9BFD PUSH IX
9BFF PUSH BC
9C00 LD C,A C = the range
9C01 SLA A B = twice the range...
9C03 JR NC,$9C07
9C05 LD A,$FF ...capped at 255
9C07 LD B,A
9C08 LD IX,$B602 Advance the 16-bit counter at $B602-$B603
9C0C INC (IX+$01)
9C0F JR NZ,$9C14
9C11 INC (IX+$00)
9C14 LD IX,($B602) IX = the counter, used as an ADDRESS: it points somewhere in memory
9C18 LD A,($B5FE) A = the seed...
9C1B ADC A,(IX+$00) ...plus the byte at that address...
9C1E ADD IX,DE (move on by DE, whatever it happens to hold)
9C20 XOR (IX+$01) ...exclusive-ORed with the byte after
9C23 PUSH HL
9C24 LD HL,$B5FE
9C27 CP (HL) The same as the previous random number?
9C28 POP HL
9C29 JR Z,$9C08 Yes: try again
9C2B LD ($B5FE),A Save it as the new seed
9C2E CP B Is it within 0 to 2 x range?
9C2F JR C,$9C38
9C31 JR Z,$9C38
9C33 SRL A No: halve it and try again (this is what skews the results)
9C35 JP $9C2E
9C38 SUB C Subtract the range to give -range to +range
9C39 POP BC
9C3A POP IX
9C3C RET
Prev: 9BF4 Up: Map Next: 9C3D