Dauber Posted June 5, 2018 Share Posted June 5, 2018 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. Quote Link to comment Share on other sites More sharing options...
+SmittyB Posted June 5, 2018 Share Posted June 5, 2018 (edited) 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 June 5, 2018 by SmittyB 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted June 6, 2018 Share Posted June 6, 2018 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. 1 Quote Link to comment Share on other sites More sharing options...
+SmittyB Posted June 6, 2018 Share Posted June 6, 2018 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. 1 Quote Link to comment Share on other sites More sharing options...
Mord Posted June 7, 2018 Share Posted June 7, 2018 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. 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted June 9, 2018 Share Posted June 9, 2018 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. 1 Quote Link to comment Share on other sites More sharing options...
+saxmeister Posted March 8 Share Posted March 8 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! 1 Quote Link to comment Share on other sites More sharing options...
+saxmeister Posted March 8 Share Posted March 8 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 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.