Randomize and rotate left.

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Randomize and rotate left.

Post by Ast A. Moore »

And once you have your 16-bit “random” number, here’s how you can trim the excess to fit the range of the screen attributes area:

Code: Select all

;assuming the MSB of the “random” number is stored in H

	ld a,h	;load A with H for “questioning”
	and 3	;the MSB of attr area is in the $58–5b range,
		;in binary this means only the three least significant
		;bits change, so isolate them
	or $58	;now OR the result with $58; this will give you
		;a “random” number between $58 and 5b
	ld h,a	;back into H
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Joefish
Rick Dangerous
Posts: 2058
Joined: Tue Nov 14, 2017 10:26 am

Re: Randomize and rotate left.

Post by Joefish »

That gives you a number range of 1024 bytes. The attribute memory is only 768 bytes long.
Hikaru
Microbot
Posts: 100
Joined: Mon Nov 13, 2017 1:42 pm
Location: Russia
Contact:

Re: Randomize and rotate left.

Post by Hikaru »

Code: Select all

	ld a,h
	and 3
	cp 3
	adc #57
	ld h,a
But that makes it 'less random' because 2 -> #5A and 3 -> #5A.
Inactive account
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Randomize and rotate left.

Post by Ast A. Moore »

Joefish wrote: Tue Jan 09, 2018 10:40 am That gives you a number range of 1024 bytes. The attribute memory is only 768 bytes long.
D’oy.
Last edited by Ast A. Moore on Tue Jan 09, 2018 12:51 pm, edited 1 time in total.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Joefish
Rick Dangerous
Posts: 2058
Joined: Tue Nov 14, 2017 10:26 am

Re: Randomize and rotate left.

Post by Joefish »

Two methods:
1. If the number is too high, ask for another.

2. AND 3 in the top byte to get 0-1023. Then multiply by 3, and divide by 4. 3/4 of 1024 is 768. But you have to do this on the full 10 bits.

You can do the divide by 4 in two separate shifts downward, to save having to shift upwards to do the *3 step.
So shift it all down by 1 bit (divide by 2), add to the original (multiply by 3) and shift the answer down another bit.
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

AND the high byte with 3 then OR it with 88, so only the two lowest bits are random. Leave the low byte fully random in all eight bits.That’ll give you an actual attribute address in the correct range.

You could subtract $5B from the high byte to get back to a 0..767 offset if you needed it.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Randomize and rotate left.

Post by Ast A. Moore »

Seven.FFF wrote: Tue Jan 09, 2018 12:32 pm AND the high byte with 3 then OR it with 88, so only the two lowest bits are random. Leave the low byte fully random in all eight bits.That’ll give you an actual attribute address in the correct range.
That’s what I suggested originally, but it won’t work, because $5b is already too high. We need to limit the MSB to the $58–5a range, and that’s a tad tricky, as A is an even number.

AND with 3, CP with 3. If equal or greater than, then request a new number. Else, OR with $58 and proceed. Kind of clunky.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

oops never mind
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Randomize and rotate left.

Post by Ast A. Moore »

Seven.FFF wrote: Tue Jan 09, 2018 1:06 pm oops never mind
My sentiment exactly. Bloody reality always messes up with the way we want things to be. :evil:
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

Yes! I was coding this last night, making my stars coloured. It works there without overrunning, because I’m turning a random pixel address into an attribute address, so it’s already properly constrained.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

Both Patrik Rak's RNG's work in are used in a similar way. You can poke your own seed into part of its seed table/value(s), like R-Tape said. For the CMWC on github the seed table is ten bytes, so you could do:

Code: Select all

FRAMES equ $5C78 ; 24-bit frame counter sysvar at $5C78, $5C79 and $5C7A, gets incremented 50 times a second by the ROM in interrupt mode 1
ld hl, (FRAMES)  ; lowest 16 bits of frame counter (0..65535)
ld (table), hl   ; first two bytes of CMWC seed table
So if hl read $MMNN from FRAMES, the seed table would then be:

Code: Select all

table   db   $NN,$MM,82,97,120,111,102,116,20,15
The random value is returned in a (0..255) for both RNGs.

The CMWC changes several bytes in its seed table every time you call it, as the initial seed propagates through all ten bytes (from left to right, as we're viewing it here). So even if you reseeded the first pair of bytes with exactly the same values, you wouldn't get the same sequence of numbers returned in a.

Generally, though, you would only seed this table once. A really good way to do this is to have an initial screen (menu, etc) that requires a keypress in order to continue. As long as FRAMES is incremented during this keypress wait, which it is in the standard interrupt mode 1, you'd get a different seed value every time.

You can make this more robust by having two keypress loops. The first one loops until all keys are released, the second one loops until a key is pressed. That stops somebody holding a key down as soon as the emulator loads. (Emulators are harder to work with, because double-clicking on a tap to start most emulators takes exactly the same length of time every time you do it, so FRAMES will have the same frame count every time. That doesn't tend to happen on real hardware, cos you faff around typing LOAD "" etc, which takes a different length of time each time you do it.)

If you need random numbers on your menu as well, it gets harder to achieve!
Last edited by Seven.FFF on Tue Jan 09, 2018 5:28 pm, edited 1 time in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Randomize and rotate left.

Post by Nomad »

Thanks for the input on the fast randomization subroutines. will crack on with that tomorrow when I have more time to work through the examples.

Its great to have your input Ast A. Moore, joefish, Hikaru, AndyC, R-tape. I would be still very much lost without you guys helping out and last but not least shout out to Seven.FFF for the great explanation and examples. Tomorrow will put it to good use. 8-)

On a related note - the R register calls are said to produce random/unpredictable results. Did anyone chart the output?

I want to chart the distribution from the R register calls, is there a way I can write the output to a data file? From what I have seen R register returns a value of 0-~127 But I cant be sure until I can collate more data.

Code: Select all

; This program loads a value into memory location 51000

org 50000

MAIN:
ld a,r 				; loads the content of register r into register a
ld (51000),a		; puts content of a into memory location 51000
ret 				; return
end 50000			; end program
then just did the print loop in basic. (I was lazy..)

I put a program into a loop but it only ran for a few mins, I would like to make a much more comprehensive test. The recorder part could be in basic its no big deal the main thing is i want to get enough samples to plot the distribution.
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

r increments by one with every opcode (or by two for instructions prefixed with $DD, $FD, $ED and $CB), and restarts at 0 after 127.

No nice distribution, as you were hoping! It's rubbish for getting a sequence of numbers, but not bad for getting a single number at an arbitrary point in time.

This prints r repeatedly in Zeus, although be warned it hangs! Too much stuff going to the console window too quickly. Demonstrates the point though - the values literally just count up. You have to tick Enable Data Breakpoints to enable the printing.

Code: Select all

zeusemulate             "48K"                           ; Tell the Zeus emulator to be a 48K Spectrum
Zeus_PC                 = $8000                         ; Tell the Zeus emulator where to start running code at
org                     $8000                           ; Tell the Zeus assembler where to place the code
                        ei
Loop:
                        zeusdatabreakpoint 1, "zeusprint(1, r)", $
                        jp Loop
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

Changing it to this stops Zeus hanging, by breaking every time (the extra ", 1" at the end):

Code: Select all

zeusdatabreakpoint 1, "zeusprint(1, r), 1", $
You have to click Run or type F8 to restart again after breaking.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 744
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Randomize and rotate left.

Post by Seven.FFF »

Perhaps even more useful. The "1" first parameter of zeusprint() prints r every time, and the "r=127" condition only breaks when r is 127. It's effectively two separate breakpoint expressions chained together. The value of the last chained expression decides whether to break.

Code: Select all

zeusdatabreakpoint 1, "zeusprint(1, r), r=127", $
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Randomize and rotate left.

Post by Nomad »

Seven.FFF wrote: Tue Jan 09, 2018 5:22 pm Perhaps even more useful. The "1" first parameter of zeusprint() prints r every time, and the "r=127" condition only breaks when r is 127. It's effectively two separate breakpoint expressions chained together. The value of the last chained expression decides whether to break.

Code: Select all

zeusdatabreakpoint 1, "zeusprint(1, r), r=127", $
Thanks, it worked fine. As you say R is just an linear incrementing output. hmmm.. well its good to know.

lol zeus should really play this at these moments

Image
:lol: ok... i'll get my coat.
User avatar
lister_of_smeg
Microbot
Posts: 145
Joined: Thu Nov 16, 2017 1:44 pm

Re: Randomize and rotate left.

Post by lister_of_smeg »

For the high byte:

Code: Select all

          ld   b, 2 
loop:     sub  85
          jr   c, loop_end
          djnz loop
loop_end:
This slightly favours the attributes for the top third of the screen, but it's fast and small.
AndyC
Dynamite Dan
Posts: 1406
Joined: Mon Nov 13, 2017 5:12 am

Re: Randomize and rotate left.

Post by AndyC »

Technically R is 8-bit, but only the bottom 7 bits increment, so it will either count 0-127 or 128-255 depending upon what bit 7 is set to. As said, it's not good if you need a steady stream of random data but if you just need something simple and not very often (say choosing one of a few starting rooms ala Knight Lore) then it can be less fuss than a real random number. And, as you can see from the discussion here, getting a random number in a specific range can be a PITA if you need a nice even distribution!
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Randomize and rotate left.

Post by Nomad »

Muhahahahahaha my potato brain was working much better this morning.

(still not enough to figure out how to get the values to print out in zeus though - I ended up having to copy the output down from fuse.. thus why there are only 143 data points.)

the P Rak code is working and spitting out ints. In this trivial example it gets printed to the screen.



Image

*cue victory dance* :lol:

Image

This would have looked a lot better if there were more data points...

Image
Post Reply