ive got this plot routine and want to instert a random number generator into it

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

ive got this plot routine and want to instert a random number generator into it

Post by 777 »

ive tried using this routine but the plot routine uses the d and e registers to plot on the screen. ive also tried to adapt it to no avail

random number generator

Code: Select all

    add hl,hl    
    sbc a,a       
    and %00101101 
    xor l        
    ld l,a        
    ld a,r       
    add a,h       
plot routine

Code: Select all

LD D,C
; D = X and E = Y
PLOT:
ld a,7
and d
ld b,a
inc b
ld a,e
rra
scf
rra
or a
rra
ld l,a
xor e
and 248
xor e
ld h,a
ld a,d
xor l
and 7
xor d
rrca
rrca
rrca
ld l,a
ld a,1 ; one
PLOTBIT:
rrca
djnz PLOTBIT
or (hl)
ld (hl),a
RET
i realise i probably will have to have 2 of the random number generator routines, to affect the d and e registers

any help would be appreciated as always
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
Joefish
Rick Dangerous
Posts: 2059
Joined: Tue Nov 14, 2017 10:26 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by Joefish »

Take a look at the top random number generator on this page:
https://wikiti.brandonw.net/index.php?t ... ath:Random

There randData is a label denoting a place in memory for temporarily storing the seed value of the random number generator from one call to the next. If you're not doing that, then your random number generator won't work properly.
You can just add a line like:
randData dw 9999
After the routine and it'll save the number there each time. That defines the space for a word (a 16-bit number) and initially sets it to value 9999. This is how 'variables' work in machine code. You define some memory addresses, or set labels to point to just empty bytes in memory (e.g. my_var_x db 0), then you store values there with LD (my_var_x),A when you're no longer processing those numbers and don't need them held in registers, then retrieve them again with LD A,(my_var_x) when you do.

Note also how it PUSHes the registers it's going to use onto the stack before it does anything, then POPs them back afterwards, to restore them to what they were. The only thing it changes is AF, and really, just the register A comes back with the random number in it.

What you need to do is CALL a routine like this then when it returns copy A into D, then call it again and copy A into E, then call the plot routine.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by RMartins »

777 wrote: Tue Aug 16, 2022 12:38 pm ...

plot routine

Code: Select all

LD D,C
; D = X and E = Y
PLOT:
ld a,7
and d
ld b,a
inc b
ld a,e
rra
scf
rra
or a
rra
ld l,a
xor e
and 248
xor e
ld h,a
ld a,d
xor l
and 7
xor d
rrca
rrca
rrca
ld l,a
ld a,1 ; one
PLOTBIT:
rrca
djnz PLOTBIT
or (hl)
ld (hl),a
RET
Are you sure that plot routine even works ?

Looking at it, at first glance, it doesn't seem like it will work. NOTE: Assuming X and Y are in pixels.

Have you tried to plot a pixel at a fixed value first ?
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

yeah, it works. and yes ive tried that

its missing ld d,(x coordinate)
and ld e,(y coordinate) at the beginning of the code

* maybe i need to learn to spell insert properly... lol...
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

Joefish wrote: Tue Aug 16, 2022 4:09 pm Take a look at the top random number generator on this page:
https://wikiti.brandonw.net/index.php?t ... ath:Random

There randData is a label denoting a place in memory for temporarily storing the seed value of the random number generator from one call to the next. If you're not doing that, then your random number generator won't work properly.
You can just add a line like:
randData dw 9999
After the routine and it'll save the number there each time. That defines the space for a word (a 16-bit number) and initially sets it to value 9999. This is how 'variables' work in machine code. You define some memory addresses, or set labels to point to just empty bytes in memory (e.g. my_var_x db 0), then you store values there with LD (my_var_x),A when you're no longer processing those numbers and don't need them held in registers, then retrieve them again with LD A,(my_var_x) when you do.

Note also how it PUSHes the registers it's going to use onto the stack before it does anything, then POPs them back afterwards, to restore them to what they were. The only thing it changes is AF, and really, just the register A comes back with the random number in it.

What you need to do is CALL a routine like this then when it returns copy A into D, then call it again and copy A into E, then call the plot routine.
ok, this works, sort of. but i need a number from 0 to 191 for the y register. or it starts printing color attributes to the screen...

Code: Select all

org 40000
LD D,C
randData dw 9999
random:
        push    hl
        push    de
        ld      hl,(randData)
        ld      a,r
        ld      d,a
        ld      e,(hl)
        add     hl,de
        add     a,l
        xor     h
        ld      (randData),hl
        pop     de
        pop     hl
        
ld d,a
random2:
        push    hl
        push    de
        ld      hl,(randData)
        ld      a,r
        ld      d,a
        ld      e,(hl)
        add     hl,de
        add     a,l
        xor     h
        ld      (randData),hl
        pop     de
        pop     hl
        
ld e,a
; D = X and E = Y
PLOT:
ld a,7
and d
ld b,a
inc b
ld a,e
rra
scf
rra
or a
rra
ld l,a
xor e
and 248
xor e
ld h,a
ld a,d
xor l
and 7
xor d
rrca
rrca
rrca
ld l,a
ld a,1 ; one
PLOTBIT:
rrca
djnz PLOTBIT
or (hl)
ld (hl),a
jr random 
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

ok, so now i managed to divide the number by 2. unfortunately it only fills 128 pixels of the screen

Code: Select all

org 40000
LD D,C
randData dw 9999
random:
        push    hl
        push    de
        ld      hl,(randData)
        ld      a,r
        ld      d,a
        ld      e,(hl)
        add     hl,de
        add     a,l
        xor     h
        ld      (randData),hl
        pop     de
        pop     hl
        
ld d,a
random2:
        push    hl
        push    de
        ld      hl,(randData)
        ld      a,r
        ld      d,a
        ld      e,(hl)
        add     hl,de
        add     a,l
        xor     h
        ld      (randData),hl
        pop     de
        pop     hl
and %11111110
rrca    
ld e,a
; D = X and E = Y
PLOT:
ld a,7
and d
ld b,a
inc b
ld a,e
rra
scf
rra
or a
rra
ld l,a
xor e
and 248
xor e
ld h,a
ld a,d
xor l
and 7
xor d
rrca
rrca
rrca
ld l,a
ld a,1 ; one
PLOTBIT:
rrca
djnz PLOTBIT
or (hl)
ld (hl),a
jr random 
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by AndyC »

The easiest way is to compare the number against 192 and just jump back to the random number generation of it exceeds it.
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

AndyC wrote: Wed Aug 17, 2022 11:01 am The easiest way is to compare the number against 192 and just jump back to the random number generation of it exceeds it.
cool, thanks
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

ok, ive got

cp 192
jp nc, random2
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by Pobulous »

Another way to get a random number between 0 and 191 would be to get 2 random numbers, AND one of them with 127, AND the other one with 63 and then add them together. That will always take a predictable amount of time. In theory, depending on how random your routine is, you could end up with a long string of numbers > 191, causing a long delay.
User avatar
777
Manic Miner
Posts: 512
Joined: Fri Jun 26, 2020 11:23 am
Location: sw uk

Re: ive got this plot routine and want to instert a random number generator into it

Post by 777 »

AndyC wrote: Wed Aug 17, 2022 11:01 am The easiest way is to compare the number against 192 and just jump back to the random number generation of it exceeds it.
just one more thing. how do i get it to 'over 1', instead of 'over 0' each pixel? would i use xor of something like that?
i started programming the spectrum when i was 8 :-

1 plot rnd*255,rnd*175
2 goto 1
User avatar
Joefish
Rick Dangerous
Posts: 2059
Joined: Tue Nov 14, 2017 10:26 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by Joefish »

Yes, xor (hl) at the end instead of or.

Yep, the 4:3 screen ratio might be pleasing on the eye but that factor of 3 can be a pain in the bum sometimes for maths. As you've found, it'd be relatively easy to have a 256x128 pixel window as then it's a 2:1 ratio which is a doddle to handle with binary maths.

And you'll find an awful lot of games out there where they do exactly that, with a great big 8-character high scoreboard at the bottom of the screen.

The alternative to re-running the random number generator is a little check at the start of your plot routine that says if Y>191 then just return straight away. This sort of 'defensive' programming doesn't make a lot of difference when plotting, but if you were printing characters, for example, it's always good to check the co-ordinates are on-screen first!
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by AndyC »

Pobulous wrote: Wed Aug 17, 2022 11:45 am Another way to get a random number between 0 and 191 would be to get 2 random numbers, AND one of them with 127, AND the other one with 63 and then add them together. That will always take a predictable amount of time. In theory, depending on how random your routine is, you could end up with a long string of numbers > 191, causing a long delay.
The trouble with adding random numbers together like that is that it may skew the overall distribution of random numbers. That may or may not matter, but you might start to see more predictable patterns as a result. Re-picking a random number should avoid that and, if your random number generator has a good distribution in the first place, shouldn't require too many attempts. Obviously sometimes being constant time can win out over having "better" random numbers.
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by AndyC »

777 wrote: Wed Aug 17, 2022 11:47 am just one more thing. how do i get it to 'over 1', instead of 'over 0' each pixel? would i use xor of something like that?
Yes XOR is the way to go, may depend on how your PLOT routine works of course.
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by Pobulous »

AndyC wrote: Wed Aug 17, 2022 12:05 pm The trouble with adding random numbers together like that is that it may skew the overall distribution of random numbers. That may or may not matter, but you might start to see more predictable patterns as a result. Re-picking a random number should avoid that and, if your random number generator has a good distribution in the first place, shouldn't require too many attempts. Obviously sometimes being constant time can win out over having "better" random numbers.
You're right - I missed that. I was thinking that a *truly* random function could at some point generate a very long sequence of large numbers, but a pseudo-random function would actually never do that anyway.
Dr beep
Manic Miner
Posts: 381
Joined: Mon Oct 01, 2018 8:53 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by Dr beep »

loop
sub 192
jr nc,loop
add a,192
AndyC
Dynamite Dan
Posts: 1408
Joined: Mon Nov 13, 2017 5:12 am

Re: ive got this plot routine and want to instert a random number generator into it

Post by AndyC »

Again, it "works" if speed is critical but it messes up the distribution of numbers so your "random" number routine will tend to generate some numbers more often than others. This may or may not matter, depending upon what you're trying to do.
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by Pobulous »

Revisiting how to reduce the random 8 bit number to a 0-191 range.

I first looked at:

20 LET Y=INT(RND*256)
30 IF Y>256 THEN LET Y=Y-256: REM this step won't be needed in ASM
40 IF Y>191 THEN LET Y=Y-192: LET Y=Y*3


I found that there were very pronounced lines every 3rd row
Like this, though, and they disappeared

10 LET Y=0
20 LET Y=Y+INT(RND*256)
25 LET R=INT(RND*175)
30 IF Y>256 THEN LET Y=Y-256: REM this step won't be needed in ASM
40 IF Y>191 THEN LET Y=Y-192: LET Y=Y*3
50 PLOT R,Y: REM as BASIC doesn't handle 192 rows of pixels, I've rotated the output
100 GOTO 20

In ASM I have:

Code: Select all

UpdateXY:
	ld	bc,(Ypos)
	call 	random		;random (0-256) in a
	add	a,b
	ld	(Xpos),a
	
	call	random		;random (0-256) in a
	add	a,c
	cp	191
	jr	nc, validY		
	sub	192			;random (0-63)
	ld	b,a
	add	a,b
	add	a,b			;random (0-189)

validY:
	ld	(Ypos),a

	call	plot

	jp	UpdateXY
	

Ypos: db 0
Xpos:	db 0

RandData: dw 9999

random:
        ld      hl,(randData)
        ld      a,r
        ld      d,a
        ld      e,(hl)
        add     hl,de
        add     a,l
        xor     h
        ld      (randData),hl
        ret
User avatar
Pobulous
Dynamite Dan
Posts: 1366
Joined: Wed Nov 15, 2017 12:51 pm

Re: ive got this plot routine and want to instert a random number generator into it

Post by Pobulous »

OK, I didn't test the code as I hadn't integrated a plot routine. It had some bugs! Here it is with a plot routine.

Assemble it, create and run this BASIC program:

1 BORDER 7: CLS: BORDER 1
10 RANDOMIZE USR 32768: GOTO 10

crank your emulator speed up

I think that gets pretty even coverage despite using a weak RND function, and a very quick and dirty correction of the values over 191.
Adding LSb of R after 3*(Y-192) might be another improvement.
The plot code is simplified version of the ROM routine.

Code: Select all

org 32768

UpdateXY:
	ld	bc,(Xpos)
	call 	random		;random (0-256) in a
	add	a,c
	ld	(Xpos),a
	
	call	random		;random (0-256) in a
	add	a,b
	cp	192
	jr	c, validY		
	sub	192			;random (0-63)
	ld	b,a
	add	a,b
	add	a,b			;random (0-189)

validY:
	ld	(Ypos),a

	ld	bc,(Xpos)
	call	plotpoint
	
	ret
	
Xpos:
	db 0
Ypos:
	db 0
RandData:
	dw 9999

random:
	ld	hl,(randData)
	ld	a,r
	ld	d,a
	ld	e,(hl)
	add	hl,de
	add	a,l
	xor	h
	ld	(randData),hl
	ret
	
plotpoint:			;y=0 is top of screen
	ld	a,b
	and	a
	rra
	scf
	rra
	and	a
	rra
	xor	b
	and	248
	xor b
	ld	h,a
	ld	a,c
	rlca
	rlca
	rlca
	xor	b
	and	199
	xor	b
	rlca
	rlca
	ld	l,a
	ld	a,c
	and	7
				;HL=display address, A=pixel offset in byte
	ld	b,a
	ld	a,128		;set pixel and shift to correct place
plotloop:
	rrca
	djnz	plotloop
	
	or	(hl)		;write pixel to screen
	ld	(hl),a
	
	ret
Post Reply