Skip to content

Instantly share code, notes, and snippets.

@satori99
Created September 9, 2015 02:20
Show Gist options
  • Save satori99/6f8a97161133d3d9f4ea to your computer and use it in GitHub Desktop.
Save satori99/6f8a97161133d3d9f4ea to your computer and use it in GitHub Desktop.
Replaces Math.random() with a seedable pseudo-random number function
/*
* A seedable (deterministic) psuedo-random number generator
*
* This script replaces native Math.random() with a deterministic psuedo-random
* number generator. It also adds a static method to reset the prng stream and
* optionally set a new seed string.
*
* @function random
* @memberof Math
* @description Generates a deterministic psuedo-random number between zero and one
* @returns {Number} psuedo-random number between zero and one
*
* @function reset
* @static
* @memberof Math.random
* @description Resets the prng stream, optionally with a new seed
* @param {String} [seed] - Optional seed text
* @returns undefined
*
* @property {String} seed - Current seed string
* @static
* @memberof Math.random
* @readonly
*
* @function native
* @static
* @memberof Math.random
* @description Native random function
* @returns {Number} random number between zero and one
*/
(function() {
'use strict';
var _native = Math.random;
var _seed = _native().toString( 36 ).slice( 2 );
var _state = new Uint8Array( 256 );
var _i = 0;
var _j = 0;
var _t = 0;
function swap ( i, j ) {
_t = _state[ i ];
_state[ i ] = _state[ j ];
_state[ j ] = _t;
}
function next () {
_i = ( _i + 1 ) % 256;
_j = ( _j + _state[ _i ] ) % 256;
swap( _i, _j );
return _state[ ( _state[ _i ] + _state[ _j ] ) % 256 ];
}
Object.defineProperty( Math, 'random', {
value: function () {
return Object.defineProperties(
function random () {
var r = next();
r = r * 256 + next();
r = r * 256 + next();
r = r * 256 + next();
r = r * 256 + next();
r = r * 256 + next();
r = r * 256 + next();
return r / 0x100000000000004;
}, {
reset: {
value: function ( seed ) {
_seed = seed ? String( seed ).trim().slice( 0, 256 ) : _seed;
_state.set( Array.apply( 0, Array( 256 ) ).map( function ( x, y ) { return y; } ) );
for ( var i = 0, j = 0; i < 256; i ++ ) {
swap( i, j = ( j + _state[ i ] + _seed[ i % _seed.length ].charCodeAt( 0 ) ) % 256 );
}
_i = _j = 0;
},
enumerable: true
},
seed: { get: function () { return _seed; }, enumerable: true },
native: { value: _native, enumerable: true }
} );
}()
} );
Math.random.reset();
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment