Quite a while ago, I started playing with random numbers on 8 Bit machines. I don't think anyone is doing "serious" work on these machines, but playing with Ciphers and Crypto got me at least curious about how a Commodore 64 generates random numbers.
There are many ways to determine randomness. Humans are pretty good at picking out patterns in visual representations. Luckily our beloved machines have easy screen memory access. Let's poke some random stuff to the screen and see what we see.
Oh, that isn't pleasant
Maybe they fixed it on the 128?
But it doesn't happen on many other machines
I tried the PET first since it was on my desk.
Is this a Commodore thing?
Nope. The Apple IIe (Applesoft BASIC) seems okay.
It gets worse
If we get a random float and then get a bunch more, we get the same nine-digit number several times in just 100k samples. Bleh.
A little review
There are three ways to call
RND from BASIC on a Commodore.
RND(1) Pick the next number out of the LFSR running sequence. The seed always starts at .185564016
RND(0) uses the VIA(PET and VIC-20)/CIA(64 and 128) timer and gives a much better random value. This is a problem on the C64 (and 128).
RND(negative number) the random number algorithm is reseeded with whatever the argument is.
So what gives
I scratched my head about this for quite some time. I consulted what I consider to be the Commodore 64 Bible. There are books by the same author for the PET and VIC-20, and it says almost the same thing for them.
According to this source, it appears that RND(0) should get randomness from the CIA timer and give a decent pseudo random sequence. We can see from testing that it does not. So what's going on here?
Old books to the rescue
Another of the best books ever created for the C64: Mapping the C64 (there is the same book for the VIC )
In it, we have the answer. It's broken. Very broken.
So the short-short version is: the CIA timer isn't running on startup, and starting it doesn't really help because the C64/128 uses BCD for this register. This limits the number of possible numbers out of the random number generator severely. So severely that we got the same nine-digit precision decimal number 5 times out of 100k samples.
You won't EVER get it to return the number 1.
But it'll give you zero lots of times
What to do?
The easiest thing is to do what people have been doing since the BASIC version 1 in the PET. You can get a reasonably random seed by using TI. Early PETs also had a bug in RND, so it became common to reseed the RND(1) and use it. So something like this works pretty well:
No repeats in 1 million tries. Much better.
Is it random? Not REALLY. Is it good enough for what you're doing on a Commodore 64? Probably.