I was especially clever tonight. I am very proud of myself for this.

First, why I needed what I did. We're writing a program in my Java

class to roll 5d6 (that's five normal dice, for the non-gamers),

which means I need to call up 5 random numbers nearly simultaneously.

Well, it turns out that Java has a poorly implemented Random()

function. For the laymen, I provide some background on how

pseudo-random numbers are generated by computers. First, they take

some seed number gathered from one of a few places (I will get to

that later), and perform some extensive computational formulae on

that seed to generate a new number.

So, for instance, you could have a very simple formula of:

( (seed/2) + (seed*seed) ) / 3

The actual formulae used by the computers are going to be much more

complicated than that, but it will do for the purposes of my

explanation here. What this means is that if you have a seed of,

say, 5.. you do:

( (5/2) + (5*5) ) / 3

Which is, (2.5+25)/3, or 9.1666666. Computers will then drop the

fractional portion (at least for the purposes of making a random

integer) and return the 9 alone.

Now, there are two implementations of Java's Random function,

Random() and Random(seed). Random(seed) essentially means that the

number you enter as the seed value is seeded in the formula like

the 5 above; the next iteration of that same Random(seed) call will

input the number returned as the seed for the next input. However,

this creates a very predictable series of numbers. Why? Well,

using the example above, when we put in 5 as the seed, we will

always get 9 as the return... inputting 9 returns 28, then 28 becomes

266, etc. This is *always* the case for the series when you start

with the same seed number. When rolling dice, you don't really

want to know what numbers are always going to be rolled, so this

becomes useless. When I tried this method, I always got the

series, 4 2 0 1 5, which was nice the first time I ran the game,

but boring the next zillion times I saw it.

Random() is generally more useful, as it looks at the current time

in the system clock and uses that as its seed. But unfortunately,

computers are very fast; so fast that they execute several lines

of code in a single millisecond. The system's clock generally only

gives a number to the millisecond, so if you're trying to gain a

few random numbers within the same area of code the system clock

seed number will not have changed. As above, if you always input

5, you will always return 9. I discovered this problem when I

"rolled" my dice in my program, and consistently got five dice

showing the same number (though that number changed each time I

rolled all five dice). Very big problem.

Ok, so my cleverness... I did some searching and probing some friends

(many thanks to jonrc, who does not have an lj account), I compiled

into my brain some very simple algorithms which still didn't really

work, and some very complex algorithms (Blum Blum Shub!) which work

extraordinarily well for Cryptography, but would be too much overhead

for this class (I promised the prof I'd send on anything I found

to fix the problem so that he could share it with the other students).

And somewhere it sprung out what is probably my reservoir of clever

for the month:

SEED = ( Random() + Random(SEED) ) / 2

The SEED is "static", so each iteration of that formula means the

old SEED is the seed for the next loop; I also return SEED to the

user as the random integer generated. Back to the laymen's terms,

what I am doing is combining the quirks of both the system clock

seeded Random, and the predictable pattern seeded Random, and letting

them interfere with each other enough to generate something more

random than either of them can be. I then take the average simply

so that I keep the generated number around the same range of numbers

the original functions produce.

This isn't airtight, it shouldn't be used in Cryptography, because

honestly, given it starting at *just* the right time, the pattern

of numbers generated can be predicted -- when this formula is

executed in the rapid fire fashion it's being done at, Random()

will remain the same number for the set of numbers generated, and

Random(seed) will give a predictable series of numbers. However,

for the purposes of some game where it's totally unknown when the

initial throw is made, this is just about as random as you can make

it without too much overhead. I also *somewhat* worry about the

Random(seed) series not leading to enough repeat numbers, but when

I did a bunch of tests on it (including a few 100d100 throws), it

was coming out with nice results.

There! I explain my geeky pride! I hope it made sense to y'all!

Or even if it didn't, accept that I was clever! I feel smert! :)