Jump to content

Photo

7800basic - random number seeder?


5 replies to this topic

#1 Dauber OFFLINE  

Dauber

    Quadrunner

  • 5,651 posts
  • What's for tea, luv?
  • Location:Right by where The Lone Ranger went to high school

Posted Tue Jun 5, 2018 1:19 PM

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.



#2 SmittyB OFFLINE  

SmittyB

    Moonsweeper

  • 278 posts

Posted Tue Jun 5, 2018 1:59 PM

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, Tue Jun 5, 2018 2:02 PM.


#3 RevEng OFFLINE  

RevEng

    River Patroller

  • 4,976 posts
  • Bitnik
  • Location:bottom of the stack

Posted Tue Jun 5, 2018 7:46 PM

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.

#4 SmittyB OFFLINE  

SmittyB

    Moonsweeper

  • 278 posts

Posted Wed Jun 6, 2018 10:32 AM

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.

#5 Mord OFFLINE  

Mord

    River Patroller

  • 2,660 posts
  • Location:Canada

Posted Thu Jun 7, 2018 10:32 AM

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. ;)



#6 RevEng OFFLINE  

RevEng

    River Patroller

  • 4,976 posts
  • Bitnik
  • Location:bottom of the stack

Posted Sat Jun 9, 2018 2:15 PM

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.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users