How random is RND in Color BASIC?

Random thought of the day…

Recently, Steve Ostrom posted to the Facebook CoCo group a puzzle he was trying to work out:

It’s been a few years since I turned on my Coco, even though it’s still all set up. I came across an interesting probability problem a few days ago, so I fired up the Coco and wrote a program to calculate the approximate answers using a random number generator. I’ll work on the real probability calculations maybe when I get even more bored. So, here’s the problem: You have 15 marbles in a bag. 5 are red, 4 are blue, 3 are white and 3 are black. You pull out one marble at a time, without putting it back, until you have 3 marbles of the same color. What are the odds of getting 3 red marbles, of getting 3 blue marbles, of getting 3 white marbles or of getting 3 black marbles. I ran 100,000 iterations (took most of the night) and here are the rounded percentages I found. Red = 42.5%, blue = 27.5%, white and black are both 15.0%. Anyone else want to try?  :-) Three cheers for the Coco and the ability to write quick programs !!

Steve Ostrom (March 21, 2020 on the CoCo Facebook Group)

This started a discussion on the CoCo Mailing List about just how random the RND() function is in Color BASIC. This reminds me of one of my earliest computer encounters back around 1979-1980.

I was living in Mequite, Texas (near Dallas) and my next door neighbor’s mom worked for Texas Instruments. They had plenty of TI stuff at home (watches and such) as well as a TI-99 home computer. Due to the year, it must have been the original TI-99/4.

His mom has typed in a BASIC program that played a card game. My friend Kris explained that he knew all the cards it would pick because it did the same ones each time. My memory seems to recall him trying to explain that the computer did not do random numbers, so his mother programmed the card sequence. Looking back, maybe what he was explaining was that it did the same numbers each time.

He was, of course, very good at this card game because of this.

Years later, I was shown an amazing magic trick as a friend talked to me over the phone and had me type in things into my CoCo and he told me what the result would be. Turn on a CoCo (or load an emulator, even the online JS Mocha or Xroar versions), and type this in:

FOR A=1 TO 10:PRINT RND(0):NEXT

What do you get if you try that on a real CoCo 1, 2 or 3?

If I recall, the RND function was meant to be used like this:

CoCo 3 BASIC manual entry on RND.

I am quite sure he just had me type “PRINT RND(100)” and he could tell me the results each time.

The pseudo random number generator in Color BASIC will do the same sequence every time, so after a power up, any game that relied on RND would be as predictable as my friend’s TI-99/4 card game was.

You can “seed” the random number generator by giving it a negative number:

As you can see, the random number generator will reset and generate the same sequence of numbers based on the negative value you give it.

Ever play Mine Sweeper on Windows? It had an option to enter a number and replay the same game. I am guessing this just seeded the Microsoft random number generator in the same way, and allowed the randomly generated playfield to be the same each time you gave it the same seed number.

Seems we could do that on the CoCo too and have a random game that you could let others try, using the same sequence of randomness.

I did not understand this when I was first getting in to the CoCo, but I knew you were supposed to seed the generator doing something like:

A=RND(-TIMER)

In Extended Color BASIC, TIMER was an incrementing variable that started at 0 on power up, and then counted up 60 times a second (the screen refresh interrupt time) until it rolled over at 65535 (about 18 minutes).

Since the time it took to turn on a computer, load a program and type run would vary, using the negative value of the timer gave a different random seed each time. I suppose if you had a BOOT rom that would automatically start up and run something (like RGB-DOS’s AUTOEXEC.BAS), maybe it would be the same amount of time each time, but beyond that, this was a good way to make the predictable RND function a bit less predictable.

As suggested on the mailing list, you can “see” the randomness by plotting out the values, such as doing something like this:

10 PMODE 4,1:SCREEN 1,1:PCLS
20 PSET(RND(256)-1,RND(192)-1):GOTO 20

Or, to make that a tad faster, use HEX in that line 20 loop and add the double speed poke (for the CoCo 3, POKE 65497,0 is even faster):

10 POKE 65495,0:PMODE 4,1:SCREEN 1,1:PCLS
20 PSET(RND(&H100)-&H1,RND(&HC0)-&H1):GOTO 20

…then let it run for awhile. If it was truly random, eventually it should set every single dot on the screen. But, pseudo random number generators have patterns. There is a level of predictability in them which has been used by hackers to exploit “secure” Internet connections for many years.

Randomly plotting points on a CoCo PMODE 4 screen.

Interesting. I never would have thought to try that back in the 1980s.

Random Benchmarking

And, lastly, benchmarks! How fast is decimal versus hex for plotting on the screen?

10 PMODE 4,1:SCREEN 1,1:PCLS
15 TIMER=0:FOR A=1 TO 1000
20 PSET(RND(256)-1,RND(192)-1):NEXT
30 PRINT TIMER/60

Versus:

10 PMODE 4,1:SCREEN 1,1:PCLS
15 TIMER=0:FOR A=1 TO 1000
20 PSET(RND(&H100)-&H1,RND(&HC0)-&H1):NEXT
30 PRINT TIMER/60

The decimal version reports 23.58 seconds. The hex version reports 20.1 seconds. Changing the numbers to variables can make it a tad faster:

10 PMODE 4,1:SCREEN 1,1:PCLS
11 X=256:Y=192
15 TIMER=0:FOR A=1 TO 1000
20 PSET(RND(X)-&H1,RND(Y)-&H1):NEXT
30 PRINT TIMER/60

19.23 seconds. I wonder if the &H1 is slower than a variable?

10 PMODE 4,1:SCREEN 1,1:PCLS
11 X=256:Y=192:O=1
15 TIMER=0:FOR A=1 TO 1000
20 PSET(RND(X)-O,RND(Y)-O):NEXT
30 PRINT TIMER/60

Hey hey! 18.61 seconds! I sure wish I knew all this back when I was writing BASIC programs in the 80s…

Oh, and FOR/NEXT is faster than a GOTO since it does not have to scan through lines to find where it is going. I think if I was going to let this run for a few hours, I might do this:

10 PMODE 4,1:SCREEN 1,1:PCLS
11 X=256:Y=192:O=1
15 FOR A=1 TO 2 STEP 0
20 PSET(RND(X)-O,RND(Y)-O):NEXT

That should be marginally faster than the GOTO 20 was.

I’ll tell you how it turns out tomorrow.

Tomorrow

Well, it looks like RND does hit every location from 0 to 255. Here is what my screen looked like after running overnight:

Randomly plotting points on a CoCo PMODE 4 screen, the next morning.

I guess I need a better test to show the frequency that each value comes up. Sorta like Steve’s original project of randomly pulling colored marbles from a bag.

Until next time…

4 thoughts on “How random is RND in Color BASIC?

  1. James Jones

    There are some very bad random number generators out there. Probably the most infamous one is RANDU, from IBM’s OS/360 SSP (Scientific Subroutine Package). If you take values from it and group them in threes as coordinates in R3, they lie in a set of 15 planes.

    I’d say the thing to do is to print out a bunch of results of RND(0) and feed them to one of the various random number generator tests, like DieHarder (a battery of tests–eh eh, nudge nudge). They may expect to be able to call the generator, so it might take running DriveWire and making the function they call just read the next value off the “printer”.

    Reply
  2. MiaM

    Don’t know about the 6809 implementation, but the 6502 version of Microsoft Basic is IIRC rather bad when seeding with larger numbers, with the pseudo-random sequence repeating after a relatively small number of random generations. You were supposed to seed it in a similar way on the Commodores, RND(-TI), but the random numbers would probably be better if you divide or right shift the -TI or -TIMER varlue a bit. Maybe this differs between the 6502 and the 6809 versions though. The 6509 version does only return values where 0<=valuue<1, and IIRC the regular way to get a random value was to use RND(1) rather than RND(0), but I can't recall why. Maybe RND(0) just did something with the timer rather than use a random number algorithm?

    Btw re autostart: Booting from phyiscal disks will introduce a slight time difference due to that the disk might be in any position and thus the time for the disk to rotate to the correct sector might vary (even if the head is already at the correct track). So if TIMER counts fractions of a second there would at least be a few different seeds, even though the number of possible seeds would be rather low.

    Reply
  3. Pingback: The marbles in a bag puzzle in Color BASIC | Sub-Etha Software

  4. Pingback: Random Easter Egg | Sub-Etha Software

Leave a Reply to MiaMCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.