Everybody knows about Math.random(), and for good reason. It’s pretty much the way to get random numbers in AS3, AS2, and JavaScript other than bizarre alternatives like AS3′s BitmapData.noise(). However, it has one critical problem that arises when you want to repeat a certain test or prevent game cheaters from exploiting the randomizer until they get an “easy” setup or desirable outcome. This problem is the lack of repeatability.

Making a pseudo-random number generator is easy. Making a good one is hard. Here, I’m going to present you with a very basic one for very basic pseudo-random number generation. I don’t remember where I found this one, but there are very many hits if you Google it. If you need something that’s cryptographically strong or to generate really good noise, you should not use this. If you just need to get a few random numbers to generate a game level, randomize starting points of some display objects, or the like, this should be random enough for you.

package
{
	/**
	*   A random number generator
	*   @author Jackson Dunstan
	*/
	public class Random
	{
		/** Current seed value */
		private var __seed:int;
 
		/**
		*   Make the random number generator
		*   @param seed Initial seed value
		*/
		public function Random(seed:int)
		{
			__seed = seed;
		}
 
		/**
		*   Get the current seed value
		*   @return The current seed value
		*/
		public function get seed(): int
		{
			return __seed;
		}
 
		/**
		*   Set the current seed value
		*   @param seed The current seed value
		*/
		public function set seed(seed:int): void
		{
			__seed = seed;
		}
 
		/**
		*   Get the next integer in the pseudo-random sequence
		*   @param n (optional) Maximum value
		*   @return The next integer in the pseudo-random sequence
		*/
		public function nextInt(n:int = int.MAX_VALUE): int
		{
			return n > 0 ? nextNumber() * n : nextNumber();
		}
 
		/**
		*   Get the next random number in the pseudo-random sequence
		*   @return The next random number in the pseudo-random sequence
		*/
		public function nextNumber(): Number
		{
			__seed = (__seed*9301+49297) % 233280;
			return __seed / 233280.0;
		}
	}
}

The class is really simple. Unlike Math.random(), you need to create an instance of a Random object. This is where you get the opportunity to pass the random “seed”, which determines the sequence of “random” numbers you get out of it. This lends it the desired property of repeatability. So in the case that you want the same random number sequence over and over, simply make sure you pass the same seed to the constructor. For example, you can make sure that the “random” occurrences in a game are the same each time by saving the random seed in the save game file and simply using it again the next time the user loads the game. I’m pretty sure Civilization III does this as I may have attempted to exploit it (as was possible in Civilization II) once or twice. Anyhow, once you have the Random object, you simply call nextNumber() or nextInt() on it to your heart’s content. The sequence of numbers you get back is infinitely long. Here’s a little chunk of code to test this out and make sure that the sequence of numbers is indeed repeatable:

const NUM_VALS:int = 100000;
var seed:int = getTimer();
var r:Random = new Random(seed);
var ints:Vector.<int> = new Vector.<int>(NUM_VALS);
var numbers:Vector.<Number> = new Vector.<Number>(NUM_VALS);
for (var i:int = 0; i < 10; ++i)
{
	ints[i] = r.nextInt(100);
	numbers[i] = r.nextNumber();
}
r = new Random(seed);
var passed:Boolean = true;
for (i = 0; i < 10; ++i)
{
	if (r.nextInt(100) != ints[i])
	{
		passed = false;
		break;
	}
 
	if (r.nextNumber() != numbers[i])
	{
		passed = false;
		break;
	}
}
trace(passed ? "SUCCESS" : "FAIL");

This always prints “SUCCESS” for me, no matter how I change the seed or how many iterations I put in. This confirms the repeatability. While the above code is in AS3, it can easily and straightforwardly be converted to an AS2 or JavaScript class. Therefore, this should be useful to you wherever on the (client side) web you’re needing repeatable random numbers. Enjoy!