Prev: 9C9F Up: Map Next: 9CE8
9CA8: A random number from -A to A
Used by the routines at JOSTLE, DO_STRIKE and RANDOM_POSITIVE.
Mixes the last result, kept at RANDOM_LAST and seeded from R by START, with the byte the pointer at RANDOM_POINTER has got to -- which steps on 256 bytes every call: INC (IX+1) is its high byte, and the low byte moves on only when the high one wraps, so it sweeps the whole of memory a page at a time -- and one DE bytes past it, and draws again if that repeats the last result. The byte is then halved until it is no more than twice A, and A taken off.
The halving keeps any byte over twice A in the upper half, A to twice A, so the result is nearly always 0 to A: it is negative only when the byte is under A, about one call in 25 for A = 10 (measured through JOSTLE: 71 in 2000).
Measured over 3000 calls each, through RANDOM_POSITIVE: every value from 0 to A comes up, but not evenly -- for A = 4 the ends come up half as often as the middle, and for A = 9 the top three do.
Input
A The limit, 0 to 127
Output
A The result, -A to A
RANDOM 9CA8 PUSH IX
9CAA PUSH BC
9CAB LD C,A B = twice the limit, or $FF if that overflows
9CAC SLA A
9CAE JR NC,RANDOM_0
9CB0 LD A,$FF
RANDOM_0 9CB2 LD B,A
RANDOM_1 9CB3 LD IX,RANDOM_POINTER Step the pointer on a page: the high byte, and the low one only when that wraps
9CB7 INC (IX+$01)
9CBA JR NZ,RANDOM_2
9CBC INC (IX+$00)
RANDOM_2 9CBF LD IX,(RANDOM_POINTER) Mix two bytes from there into the last result
9CC3 LD A,(RANDOM_LAST)
9CC6 ADC A,(IX+$00)
9CC9 ADD IX,DE
9CCB XOR (IX+$01)
9CCE PUSH HL
9CCF LD HL,RANDOM_LAST
9CD2 CP (HL)
9CD3 POP HL The same as last time? Draw again; otherwise keep it
9CD4 JR Z,RANDOM_1
9CD6 LD (RANDOM_LAST),A
RANDOM_3 9CD9 CP B Halve it until it is no more than B
9CDA JR C,RANDOM_4
9CDC JR Z,RANDOM_4
9CDE SRL A
9CE0 JP RANDOM_3
RANDOM_4 9CE3 SUB C Take the limit off
9CE4 POP BC
9CE5 POP IX
9CE7 RET
Prev: 9C9F Up: Map Next: 9CE8