(function() {
	FF.Random = function(f) {
		this.func = f;
	};
	FF.Random.prototype.nextInt = function(min, max) {
		min = min || 0;
		max = max || (1 << 32) - 1;
		
		return (min == max) ? min : Math.floor(this.func() % (max-min) + min);
	};
	FF.Random.prototype.nextFloat = function() {
		return (this.func() / 0x1FFFFFFF) % 1;
	};
	
	(function() {
		FF.Random.MersenneTwister = function(seed) {
			this.MT = new Array(624);
			this.index = 0;
			
			var twister = this;
			FF.Random.call(this, function() { return twister.extract(); });
			this.init(seed);
		};
		FF.Random.MersenneTwister.prototype.init = function(seed) {
			this.MT[0] = seed;
			for (var i=1; i<624; i++) {
				this.MT[i] = (1812433253 * (this.MT[i-1] ^ (this.MT[i-1] >> 30)) + 1) & 0xFFFFFFFF;
			}
		};
		FF.Random.MersenneTwister.prototype.extract = function() {
			if (this.index == 0) {
				this.generate();
			}
			
			var y = this.MT[this.index];
			y = y ^ (y >> 11);
			y = y ^ ((y << 7) & 2636928640);
			y = y ^ ((y << 15) & 4022730752);
			y = y ^ (y >> 18);
			
			this.index = (this.index + 1) % 624;
			return y;
		};
		FF.Random.MersenneTwister.prototype.generate = function() {
			for (var i=0; i<624; i++) {
				var y = (this.MT[i] & (1 << 31)) + (this.MT[(i+1) % 624] & 0x7FFFFFFF);
				this.MT[i] = this.MT[(i + 397) % 624] ^ (y >> 1);
				
				if (y % 2 == 1) {
					this.MT[i] = this.MT[i] ^ 2567483615;
				}
			}
		};
		for (var k in FF.Random.prototype) {
			FF.Random.MersenneTwister.prototype[k] = FF.Random.prototype[k];
		}
	})();
	
})();