## How to create random number with machine code?

Here you can ask questions or provide insights about how to use efficiently 6502 assembly code on the Oric.
peacer
Flight Lieutenant
Posts: 412
Joined: Wed Jun 09, 2010 9:23 pm
Location: Turkey
Contact:

### How to create random number with machine code?

Can you help me how to create a random number with machine code?

I need 4 different cases when I call the routine. So what ı want is ;

For example.. As basic commands
CALL x
P=PEEK(0)

So, P will get 0,1,2 or 3 randomly from memory adress 0

To explain it briefly Its like P=INT (4*RND(0))

Thanks

Symoon
Archivist
Posts: 1862
Joined: Sat Jan 14, 2006 12:44 am
Location: Paris, France
Contact:

### Re: How to create random number with machine code?

Short reply (sorry, in a hurry): I would read the timer's low byte and keep the 2 lower bits from it.

Something like
LDA \$0308
then any other instruction to set the 6 bits to 0, giving 000000xy
(than would probably be AND #\$03 but please double check, I have to leave now )

then A = 0, 1, 2 or 3.
Store it in \$00 with
STA \$00

and don't forget to end the program with
RTS

peacer
Flight Lieutenant
Posts: 412
Joined: Wed Jun 09, 2010 9:23 pm
Location: Turkey
Contact:

### Re: How to create random number with machine code?

Thank you, short and easy

Badger
Pilot Officer
Posts: 72
Joined: Sat Sep 22, 2018 10:04 am
Location: Wigan, England

### Re: How to create random number with machine code?

I can confirm Symoon's answer is correct.

In basic you can just do :-
POKE 0,PEEK(#308)AND3

and in assembly

lda \$0308
and #\$03
sta \$00
rts
Amateurs built the Ark, Professionals built the Titanic.

peacer
Flight Lieutenant
Posts: 412
Joined: Wed Jun 09, 2010 9:23 pm
Location: Turkey
Contact:

### Re: How to create random number with machine code?

Thank you too

NekoNoNiaow
Flight Lieutenant
Posts: 272
Joined: Sun Jan 15, 2006 10:08 pm
Location: Montreal, Canadia

### Re: How to create random number with machine code?

How are you using the generated random numbers?
I ask because if you are generating them inside a loop there is a high chance that they will repeat if the timing of the loop is more or less constant. What I would recommend actually is to use a simple modulo based random generator (*) and initialize it using the number read from the timer.

(*) here is a simple enough one that gives very acceptable results for a relatively good performance (if you use a multiplication table): https://en.m.wikipedia.org/wiki/Lehmer_ ... _generator.
There was a very good article about random number generation in STMag back in the day which implemented that type of particular generator. If someone recalls which issue that was then please mention it, as it is probably very simple to adapt to the Oric.

Badger
Pilot Officer
Posts: 72
Joined: Sat Sep 22, 2018 10:04 am
Location: Wigan, England

### Re: How to create random number with machine code?

I discovered this online somewhere to give integers upto 255 :-

Code: Select all

``````getrand
.(
lda \$01
beq doEor
asl
beq noEor ;if the input was \$80, skip the EOR
bcc noEor
doEor
eor #\$1d
noEor
sta \$01
rts
.)``````
All you need to do is seed \$01 with any number at the start or again later with something like the value of the timer after a keypress.
I put together the below to show this. It waits for a keypress and seeds the random number generator (shown above) with the timer value. Prints the seed on the status line, then prints 200 random numbers to the main part of the screen.

Code: Select all

``````#define STATUS_LINE (\$BB80+2)		;first char of status line ignoring attribute chars
#define DISPLAY_ADDRESS (\$BB82+40) 	;first char of non-status line ignoring attribute columns
#define RANDLOC \$01  			;memory location of random number - change as you like
.text
main
.(
jsr clrscreen			;clears the screen

nokey					;check for any keypress
lda \$208
cmp #56
beq nokey

setseed
lda #<STATUS_LINE		;set up memory to print seed on status line
sta write+1
lda #>STATUS_LINE
sta write+2
jsr gettimer 			;seed random generator with current value of timer 1
lda RANDLOC
jsr PrDec			;Print value of random number seeded to screen

lda #<DISPLAY_ADDRESS		;set up memory of 1st character to display random numbers
sta write+1
lda #>DISPLAY_ADDRESS
sta write+2
ldx #200 			; loop counter
mainloop
jsr getrand			; random number generator
jsr PrDec
jsr addspace			;add spaces between numbers
dex
bne mainloop
rts

write				; write char and advance 1 position
sta \$0123
clc			; Calc new scren address
lda write+1
adc #01
sta write+1
lda write+2
adc #0
sta write+2
rts

addspace			;add spaces between numbers
clc
lda write+1
adc #2
sta write+1
lda write+2
adc #0
sta write+2
rts

PrDec						; routine to print out decimals to screen
ldy #\$FF
sec
PrDec100
iny
sbc #100
bcs PrDec100  				;\ Count how many 100s
adc #100
jsr PrDecDigit    			;\ Print the 100s
ldy #\$FF
sec               			;\ Prepare for subtraction
PrDec10
iny
sbc #10
bcs PrDec10    				;\ Count how many 10s
adc #10
jsr PrDecDigit     			;\ Print the 10s
tay	                        	;\ Pass 1s into X
PrDecDigit
pha
tya			                ;\ Save A, pass digit to A
ora #\$30
jsr write
pla
rts

.)

gettimer			;get current value of timer 1
.(
lda \$304
sta RANDLOC			; store as seed for random number generator
.)

clrscreen			; clears text screen
.(
lda #<DISPLAY_ADDRESS
sta write2+1
lda #>DISPLAY_ADDRESS
sta write2+2

ldy #27			;row to loop
clearloop2
ldx #38			;cols to loop
clearloop1
lda #32			;ASCII of char to write to screen
jsr write2
jsr add1		; advance to next screen position
dex
bne clearloop1
jsr newline		; advance to next line and skip attribute columns
dey
bne clearloop2
rts

write2
sta \$0123
rts
add1
clc
lda write2+1
adc #1
sta write2+1
lda write2+2
adc #0
sta write2+2
rts

newline
clc
lda write2+1
adc #2
sta write2+1
lda write2+2
adc #0
sta write2+2
rts

.)

getrand				; random number generator
.(
lda RANDLOC			;loads A with last value of random generator (either the seed or last random)
beq doEor
asl
beq noEor 			;if the input was \$80, skip the EOR
bcc noEor
doEor
eor #\$1d
noEor
sta RANDLOC
rts
.)``````
As an aside to this, I've found that the PrDec routine to the status line is ideal for watching the values of memory or registers without using the monitor or over-writing anything on the main screen.

Hope this helps.
Amateurs built the Ark, Professionals built the Titanic.

iss
Wing Commander
Posts: 1032
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

### Re: How to create random number with machine code?

@Badger: +1!
IMO this is the best way to produce random numbers too: keypress+timer+algo.
I'm using the same algorithm and the original comes from HERE.

Chema
Game master
Posts: 2621
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

### Re: How to create random number with machine code?

This is the routine I use in my games. I remember I tested its randomness and it was quite good!

Code: Select all

``````; A real random generator...
randseed .word \$dead 	; will it be \$dead again?
randgen
.(
lda randseed     	; get old lsb of seed.
ora \$308		; lsb of VIA T2L-L/T2C-L.
rol			; this is even, but the carry fixes this.
adc \$304		; lsb of VIA TK-L/T1C-L.  This is taken mod 256.
sta randseed     	; random enough yet.
sbc randseed+1   	; minus the hsb of seed...
rol			; same comment than before.  Carry is fairly random.
sta randseed+1   	; we are set.
rts			; see you later alligator.
.)``````

goyo
1st Star Corporal
Posts: 12
Joined: Sat Jan 12, 2019 10:16 am

### Re: How to create random number with machine code?

Badger wrote:
Fri Feb 01, 2019 10:23 am
I discovered this online somewhere to give integers upto 255 :-

Code: Select all

``````getrand
.(
lda \$01
beq doEor
asl
beq noEor ;if the input was \$80, skip the EOR
bcc noEor
doEor
eor #\$1d
noEor
sta \$01
rts
.)``````
All you need to do is seed \$01 with any number at the start or again later with something like the value of the timer after a keypress.
I put together the below to show this. It waits for a keypress and seeds the random number generator (shown above) with the timer value. Prints the seed on the status line, then prints 200 random numbers to the main part of the screen.
I tried to call your method from c but it's look like a répétitive séquence ... :

Code: Select all

``````unsigned char b;
asm("lda %b;"
"beq doEor;"
"asl;"
"beq noEor;"
"bcc noEor;"
"doEor:    eor #\$1d;"
"noEor:  sta %b;");``````
with this following program we can see the repetitive sequence (graphics):

Code: Select all

``````// unsigned int randgen();

unsigned i;
unsigned char b;

void main()
{

unsigned adr=0xA000;
b=65;
hires();
//cls();
for (i=0;i<8000;i++)
{

asm("lda %b;"
"beq doEor;"
"asl;"
"beq noEor;"
"bcc noEor;"
"doEor:    eor #\$1d;"
"noEor:  sta %b;");

//printf("b=%d \n",b);
if ((b>0)&&(b<128))
{
if ((b>7)&&(b<16))
{
}
else
{
if ((b<24)||(b>31))
{

poke(adr+i,b);

}
}
}
}

}
``````

iss
Wing Commander
Posts: 1032
Joined: Sat Apr 03, 2010 5:43 pm
Location: Bulgaria
Contact:

### Re: How to create random number with machine code?

Well spotted, goyo!
This algo actually generates chains with period of 256 and "will cycle through the values \$00-\$ff exactly once, in a scrambled order". I.e it's like doing "shuffle" but with 256 cards . I recall that I've used this code because it was small and I needed only numbers in range 0..3, so I've used only 2 low bits.

For a "more real" random generator why not use the OSDK's one but see the Dbug's note here.

Badger
Pilot Officer
Posts: 72
Joined: Sat Sep 22, 2018 10:04 am
Location: Wigan, England

### Re: How to create random number with machine code?

Yes Goyo, there is a trade off between small fast code and randomness and if the seed isnt altered then it will be repetetive.

In a game with lots of keypresses you could just re-seed the routine with the value of the timer (\$304) on each keypress which would probably make it as close to random as possible.

I guess, it all depends on what you need and how random you need it to be. In a card game for instance you might actually not want repeating numbers when you shuffle the pack.
Amateurs built the Ark, Professionals built the Titanic.

Chema
Game master
Posts: 2621
Joined: Tue Jan 17, 2006 10:55 am
Location: Gijón, SPAIN
Contact:

### Re: How to create random number with machine code?

Just for the records. The routine I posted before (made by a friend of mine) produces a repeatable series of numbers between 0 and 32768 (repeatable if the seed is re-used, that is), with quite nice randomness properties. Matlab's randomness test shows:

Code: Select all

``````[h,p]=runstest(v, median(v))
Warning: X values exactly equal to V are omitted.
> In runstest (line 167)
h =
0
p =
0.8864``````
Which apparently means it cannot discard it is a random sequence (which is quite good).

Also this is the histogram of generated values:
hist.png (7.3 KiB) Viewed 8224 times
And the routine is small and fast...