Randomize and rotate left.

The place for codemasters or beginners to talk about programming any language for the Spectrum.
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: 1405
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