💾 Archived View for tanelorn.city › ~vidak › old-blog › guerrilla_game_random_number_translator.gemi… captured on 2020-11-07 at 01:35:35. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2020-09-24)
-=-=-=-=-=-=-
---
generator: pandoc
title: 'Guerrilla Game: Random Number Translator'
viewport: 'width=device-width, initial-scale=1.0, user-scalable=yes'
---
2018-04-05T13:13:57+10:00
Okay I have written the code for transforming the output of the 16 bit
random number generator into (what I think are) unique indexes for the
four zones to be drawn on the screen.
This is the code:
;=================================
; Forming the input of the Random Number Generator
;=================================
; Bit 5 of Map_Coords, the Up bit, is in the carry bit.
; The status register should look like this now:
;
; C76543210
; UXXXX0RLD
;==================================
;Is the UP flag set in Map_Coords?
;==================================
bcc CheckRNG_Down ; If UP flag not set, check DOWN flag
ldx #0
jmp ShiftBackwards
.CheckRNG_Down
ror ; Put D in carry bit
bcc CheckRNG_Left ; If DOWN flag not set, check LEFT flag
ldx #0
jmp ShiftForwards
.CheckRNG_Left
ror ; Put L in carry bit
bcc CheckRNG_Right ; If LEFT flag not set, check RIGHT flag
ldx #255
jmp ShiftBackwards
.CheckRNG_Right
ror ; Put R in carry bit
bcc No_RNG ; If RIGHT flag not set, then no flags set, then exit
ldx #255
;=================================
; Wait for Vertical Blank to End
;=================================
; What we're going to do is use up a blank frame of kernel time
; in order to have enough time to calculate a full row of screens:
; 256 positions on the RNG counter.
lda #$00 ; 2 13
sta COLUBK ; 3 16
RNGStartWait:
sta WSYNC
;---------------------------------
lda INTIM ; 4 4
bne RNGStartWait ; 2 6
sta VBLANK ; 3 9 - Accumulator D1=0
;=================================
; Set timer for blank frame
;
; (192 * 76) / 64 = 228
;=================================
RNG_Timer:
ldx #228
stx TIM64T
;=================================
; Random Number Generator Routine
;=================================
; SHIFT FORWARDS
ShiftForwards:
lda Rand8 ; 3 3
lsr ; 2 5
rol Rand16 ; 5 10
bcc noeor ; 2 12
eor #$D4 ; 2 14 - $D4 is the only number I know the inverse to
.noeor ;
sta Rand8 ; 3 17
eor Rand16 ; 3 20
inx
clc
bne ShiftForwards
beq Pointer_Calc
; SHIFT BACKWARDS
ShiftBackwards:
lda Rand8
lsr
rol Rand16
bcc noeorleft
eor #$A9 ; $D4 is the only number I know the inverse to
.noeorleft
sta Rand8
eor Rand16
inx
clc
bne ShiftForwards
beq Pointer_Calc
;================================================
; Translation of the output of the random number
; generator into a useful index for selecting
; a random object in ROM.
;
; Here we:
; - Buffer the output of the RNG into RAM
; - Enter into a 4 cycle loop, which masks off
; different portions of the 16 bit random number
; so that a number between 0-63 is produced.
;
; This translates the random number output into
; an index that is 64 positions long, and allows
; us to randomly select 4 different objects from
; that 64 bit number.
;
; A second level of randomness could be introduced
; by generating an 8 bit random number, and masking
; THOSE bits off. But that would make the game
; impossible to seed the same way every time.
;
;================================================
Pointer_Calc:
ldy #3
.Pointer_Calc_Loop
ldx Rand8
stx Rand_Pointer_Calc8
ldx Rand16
stx Rand_Pointer_Calc16
cpy #3
beq Band_3_Calc
cpy #2
beq Band_2_Calc
cpy #1
beq Band_1_Calc
cpy #0
beq Band_0_Calc
.Band_3_Calc
lda Rand_Pointer_Calc16
and #%11111100
lsr
lsr
sta Band_3_Index
jmp Done_Calc
.Band_0_Calc
lda Rand_Pointer_Calc8
and #%00111111
sta Band_0_Index
jmp Done_Calc
.Band_2_Calc
lda Rand_Pointer_Calc16
and #%00000111
asl
asl
asl
sta Rand_Pointer_Calc16
lda Rand_Pointer_Calc8
and #%11100000
rol
rol
rol
rol
clc
and Rand_Pointer_Calc16
sta Band_2_Index
jmp Done_Calc
.Band_1_Calc
lda Rand_Pointer_Calc16
and #%0011100
asl
asl
sta Rand_Pointer_Calc16
lda Rand_Pointer_Calc8
and #%0011100
rol
rol
clc
and Rand_Pointer_Calc16
sta Band_1_Index
.Done_Calc
dey
bpl Pointer_Calc_Loop
My main concern is that masking off 6 bits from the random number
generator output is actually reducing the number of random numbers from
the generator.
I don't quite know the maths, but I am hoping that masking off 6 bits
from the 16 bits is not actually making the output of the random number
generator less random.
If it is reducing the randomness of the generator -- how else would one
produce a random number between 0 and 2\^6 four different times over
2\^16 different screens?
My thinking was that 64 CHOOSE 4 combinations of objects is a larger
number than 2\^16, and that way there would always be a unique
combination of 4 objects across the 2\^16 screens.
The problem is, I don't quite know what mathematical function is being
performed by masking off 6 bits from 16 bits.
Any ideas?
------------------------------------------------------------------------
EDIT:
Is what is happening with my masking 16 CHOOSE 6 = 8008? Of which I am
choosing 4 combinations?
Is the randomness of that choice then 6! or 6 CHOOSE 4? or is it 64! ?
There's an answer to this, but I have never been good at combinatorial
logic and statistics...