Jump to content
IGNORED

7800basic - random number seeder?


Dauber

Recommended Posts

How exactly does the seed for "rand" work??

 

Like....suppose I have this command:

rand = 42

What exactly is it going to do with that 42??

 

Reason I'm asking is because I have an array that gets populated with 28 random numbers, and then I sort the numbers. I'm getting different sets of numbers every time, but also every time, I'm noticing that there's a pretty low concentration of numbers on the low end, but the higher you get, the more concentrated they are...know what I mean??

 

For example...I might have one or two numbers between 0-20, and maybe four or five between 20-40, etc., and a whole bunch beween, say, 150-180. And I think it might be the way I'm seeding the (pseudo) random number generator.

Link to comment
Share on other sites

Looking at the assembly it seems 'rand' is initially set based on whatever the timer 'INTIM' has stored, then when you assign rand to a variable it runs the below routine, and a new 'rand' value is stored which gets fed through the function next time. By setting rand to a number of your choosing it will just use that as the number to feed through the routine next time.

 

Each bit of rand get shifted right so the leftmost bit becomes 0 and rightmost bit gets carried over. The bits for rand16 get rotated left so the carried over bit becomes the rightmost bit and whatever the leftmost bit is then gets carried over.

If anything gets carried over rand is combined with 10110100 using 'exclusive or' logic. If nothing is carried over then it stores the modified rand, and combines it with the contents of rand16 using 'exclusive or' logic so that the number returned is not the same number in rand that gets fed through the next time round.

 

I hope I got that all right.

randomize
     lda rand
     lsr
     rol rand16
     bcc noeor
     eor #$B4
noeor
     sta rand
     eor rand16
     rts
Edited by SmittyB
  • Like 1
Link to comment
Share on other sites

The 7800 doesn't have a real source of random numbers, same as pretty much every other system of the era. So 7800basic uses a 16-bit LFSR as a source of pseudo random numbers. (normally 7800basic games use just the low byte of this LFSR, but the high byte is there to allow the larger range.)

 

Some info on working with LFSRs...

 

LFSRs actually travel over every number in their range before repeating (1 to 65535 in the case of a 16-bit LFSR) so every number is actually equally represented over the long haul.

 

The seed just determines the starting point for the LFSR sequence, but the overall sequence through the range is the same, regardless of where it started.

 

The INTIM seed in 7800basic (pointed out by Smitty) is my attempt to introduce a "true" random starting point for the sequence, but it's probably in vain as RIOT timers are likely identical from boot to boot. I've also seen floating bus locations used for seeding LFSRs, but in my experience they just reflect previous bus contents, rather than being random. Much better for the game code to just grab a random number for each frame while the title screen is displayed, and let the timing of when the player starts the game become the seed.

 

In the short haul, LFSR numbers may clump up a bit. This really isn't any different than true random numbers, but it does run counter to what people generally expect from random numbers.

 

If you want your random numbers to be more fluffy, and less clumpy, you might look at throwing away values that are too close to recently drawn numbers.

  • Like 1
Link to comment
Share on other sites

What you could also do if you want a more even distribution and have the bytes to spare would be to use a lookup table of pre-randomised numbers.

I don't have many random elements in my dungeon crawler but I'm considering using a 256 byte table of all values from 0 to 255 in an order generated using random.org. That way by reading from the table in sequence and letting it loop I can tweak the appearance of the randomness to remove any runs of high or low numbers that might be frustrating to the player.

I would still need to pick an arbitrary starting point to avoid having the same series of events when the game starts.

  • Like 1
Link to comment
Share on other sites

What you could also do if you want a more even distribution and have the bytes to spare would be to use a lookup table of pre-randomised numbers.

I don't have many random elements in my dungeon crawler but I'm considering using a 256 byte table of all values from 0 to 255 in an order generated using random.org. That way by reading from the table in sequence and letting it loop I can tweak the appearance of the randomness to remove any runs of high or low numbers that might be frustrating to the player.

I would still need to pick an arbitrary starting point to avoid having the same series of events when the game starts.

 

Best thing to do for that is to have a random number generated (And discarded) every frame while sitting at the title screen. That way just idling will ensure a different potential starting number. Could spice it up so that every time a key is pressed on the controller, another random number is generated, etc.

 

What's more, if you support the save key for instance, when a game is started, you can save the current random number to it so when the next time you start up the console it'll be able to start on that number instead of the same value originally stored in the rom/etc. (But that's only if you're already using the save key/atarivox. Would be a waste to use it just for that. ;)

  • Like 2
Link to comment
Share on other sites

What's more, if you support the save key for instance, when a game is started, you can save the current random number to it so when the next time you start up the console it'll be able to start on that number instead of the same value originally stored in the rom/etc. (But that's only if you're already using the save key/atarivox. Would be a waste to use it just for that. ;)

The HSC has an unused byte mapped at $17FF. You could very easily use this as a seed, without much more code than testing if $17FF is writeable. That said, I think using the timing of the player leaving the title screen is the superior approach.

  • Like 1
Link to comment
Share on other sites

  • 5 years later...

I'm so glad this old thread is here. I have been having issues with randomizing numbers (as much as possible on a 6502) and love thee suggestions.

 

My next "random number" routine will have both a lookup table of randomly generated numbers as well as the timer seed from the title screen frame counter. Such great suggestions!

  • Like 1
Link to comment
Share on other sites

Just a quick example of using lookup tables and random numbers. I generated a list of 255 ($FF) random numbers using an external generator, added the list with a data statement, then picked a starting point from in that list using the timing of when the user clicks/presses fire.

 

JS7800 Link: https://raz0red.github.io/js7800/?cart=https://forums.atariage.com/applications/core/interface/file/attachment.php?id=1100254&key=7ed6ff1473a803fc1c2545625035ee2a

 

randomnumbertest.ziptest01.78b.a78test01.78b.bintest02.78b.a78test02.78b.bin

  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...