mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-11 09:11:50 +00:00
Tidy up ALEA RNG code
Not a performance improvement, just something that needed to be done. Slightly simplifies the structure and removes useless functions (changing the seed resets the RNG anyway - it is better to create a new instance instead).
This commit is contained in:
parent
b3d0e30c07
commit
ae739be484
@ -1,129 +0,0 @@
|
|||||||
// ALEA RNG
|
|
||||||
|
|
||||||
function Mash() {
|
|
||||||
var n = 0xefc8249d;
|
|
||||||
return function (data) {
|
|
||||||
data = data.toString();
|
|
||||||
for (var i = 0; i < data.length; i++) {
|
|
||||||
n += data.charCodeAt(i);
|
|
||||||
var h = 0.02519603282416938 * n;
|
|
||||||
n = h >>> 0;
|
|
||||||
h -= n;
|
|
||||||
h *= n;
|
|
||||||
n = h >>> 0;
|
|
||||||
h -= n;
|
|
||||||
n += h * 0x100000000; // 2^32
|
|
||||||
}
|
|
||||||
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number|string} seed
|
|
||||||
*/
|
|
||||||
function makeNewRng(seed) {
|
|
||||||
// Johannes Baagøe <baagoe@baagoe.com>, 2010
|
|
||||||
var c = 1;
|
|
||||||
var mash = Mash();
|
|
||||||
let s0 = mash(" ");
|
|
||||||
let s1 = mash(" ");
|
|
||||||
let s2 = mash(" ");
|
|
||||||
|
|
||||||
s0 -= mash(seed);
|
|
||||||
if (s0 < 0) {
|
|
||||||
s0 += 1;
|
|
||||||
}
|
|
||||||
s1 -= mash(seed);
|
|
||||||
if (s1 < 0) {
|
|
||||||
s1 += 1;
|
|
||||||
}
|
|
||||||
s2 -= mash(seed);
|
|
||||||
if (s2 < 0) {
|
|
||||||
s2 += 1;
|
|
||||||
}
|
|
||||||
mash = null;
|
|
||||||
|
|
||||||
var random = function () {
|
|
||||||
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
|
||||||
s0 = s1;
|
|
||||||
s1 = s2;
|
|
||||||
return (s2 = t - (c = t | 0));
|
|
||||||
};
|
|
||||||
|
|
||||||
random.exportState = function () {
|
|
||||||
return [s0, s1, s2, c];
|
|
||||||
};
|
|
||||||
|
|
||||||
random.importState = function (i) {
|
|
||||||
s0 = +i[0] || 0;
|
|
||||||
s1 = +i[1] || 0;
|
|
||||||
s2 = +i[2] || 0;
|
|
||||||
c = +i[3] || 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return random;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class RandomNumberGenerator {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {number|string=} seed
|
|
||||||
*/
|
|
||||||
constructor(seed) {
|
|
||||||
this.internalRng = makeNewRng(seed || Math.random());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Re-seeds the generator
|
|
||||||
* @param {number|string} seed
|
|
||||||
*/
|
|
||||||
reseed(seed) {
|
|
||||||
this.internalRng = makeNewRng(seed || Math.random());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {number} between 0 and 1
|
|
||||||
*/
|
|
||||||
next() {
|
|
||||||
return this.internalRng();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Random choice of an array
|
|
||||||
* @param {array} array
|
|
||||||
*/
|
|
||||||
choice(array) {
|
|
||||||
const index = this.nextIntRange(0, array.length);
|
|
||||||
return array[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} min
|
|
||||||
* @param {number} max
|
|
||||||
* @returns {number} Integer in range [min, max[
|
|
||||||
*/
|
|
||||||
nextIntRange(min, max) {
|
|
||||||
assert(Number.isFinite(min), "Minimum is no integer");
|
|
||||||
assert(Number.isFinite(max), "Maximum is no integer");
|
|
||||||
assert(max > min, "rng: max <= min");
|
|
||||||
return Math.floor(this.next() * (max - min) + min);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} min
|
|
||||||
* @param {number} max
|
|
||||||
* @returns {number} Number in range [min, max[
|
|
||||||
*/
|
|
||||||
nextRange(min, max) {
|
|
||||||
assert(max > min, "rng: max <= min");
|
|
||||||
return this.next() * (max - min) + min;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the seed
|
|
||||||
* @param {number} seed
|
|
||||||
*/
|
|
||||||
setSeed(seed) {
|
|
||||||
this.internalRng = makeNewRng(seed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
81
src/js/core/rng.ts
Normal file
81
src/js/core/rng.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
class Alea {
|
||||||
|
private n = 0xefc8249d;
|
||||||
|
private c = 1;
|
||||||
|
|
||||||
|
private s0: number;
|
||||||
|
private s1: number;
|
||||||
|
private s2: number;
|
||||||
|
|
||||||
|
constructor(seed: string) {
|
||||||
|
// Johannes Baagøe <baagoe@baagoe.com>, 2010
|
||||||
|
this.s0 = this.mash(" ");
|
||||||
|
this.s1 = this.mash(" ");
|
||||||
|
this.s2 = this.mash(" ");
|
||||||
|
|
||||||
|
this.s0 -= this.mash(seed);
|
||||||
|
if (this.s0 < 0) {
|
||||||
|
this.s0 += 1;
|
||||||
|
}
|
||||||
|
this.s1 -= this.mash(seed);
|
||||||
|
if (this.s1 < 0) {
|
||||||
|
this.s1 += 1;
|
||||||
|
}
|
||||||
|
this.s2 -= this.mash(seed);
|
||||||
|
if (this.s2 < 0) {
|
||||||
|
this.s2 += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected next(): number {
|
||||||
|
const t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32
|
||||||
|
this.s0 = this.s1;
|
||||||
|
this.s1 = this.s2;
|
||||||
|
return (this.s2 = t - (this.c = t | 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private mash(data: string): number {
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
this.n += data.charCodeAt(i);
|
||||||
|
let h = 0.02519603282416938 * this.n;
|
||||||
|
this.n = h >>> 0;
|
||||||
|
h -= this.n;
|
||||||
|
h *= this.n;
|
||||||
|
this.n = h >>> 0;
|
||||||
|
h -= this.n;
|
||||||
|
this.n += h * 0x100000000; // 2^32
|
||||||
|
}
|
||||||
|
return (this.n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RandomNumberGenerator extends Alea {
|
||||||
|
constructor(seed: string | number = Math.random()) {
|
||||||
|
super(seed.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Random choice of an array
|
||||||
|
*/
|
||||||
|
choice<T>(array: T[]): T {
|
||||||
|
const index = this.nextIntRange(0, array.length);
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns Integer in range [min, max]
|
||||||
|
*/
|
||||||
|
nextIntRange(min: number, max: number): number {
|
||||||
|
assert(Number.isFinite(min), "Minimum is no integer");
|
||||||
|
assert(Number.isFinite(max), "Maximum is no integer");
|
||||||
|
assert(max > min, "rng: max <= min");
|
||||||
|
return Math.floor(this.next() * (max - min) + min);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns Number in range [min, max]
|
||||||
|
*/
|
||||||
|
nextRange(min: number, max: number): number {
|
||||||
|
assert(max > min, "rng: max <= min");
|
||||||
|
return this.next() * (max - min) + min;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user