mirror of
https://gitlab.com/Oreolek/salet-module.git
synced 2024-06-30 22:05:02 +03:00
Fast PRNG instead of the slow Mersenne Twister
This commit is contained in:
parent
961b0a936a
commit
70c8d2c705
|
@ -1,149 +1,53 @@
|
||||||
###
|
###
|
||||||
This implementation of the Mersenne Twister is a port of the JavaScript
|
Fast performance pseudo random number generator.
|
||||||
version by Y. Okada. The JavaScript version was itself a port of a
|
|
||||||
C implementation, by Takuji Nishimura and Makoto Matsumoto.
|
|
||||||
|
|
||||||
CoffeeScript port by: Jamis Buck <jamis@jamisbuck.org>
|
Not the cryptographic-level randomness, but enough for most games.
|
||||||
License: Public domain, baby. Knock yourself out.
|
|
||||||
|
|
||||||
The original CoffeeScript sources are always available on GitHub:
|
Code from CoffeeScript Cookbook:
|
||||||
http://github.com/jamis/csmazes
|
https://coffeescript-cookbook.github.io/chapters/math/generating-predictable-random-numbers
|
||||||
###
|
###
|
||||||
|
|
||||||
class Random
|
class Random
|
||||||
N: 624
|
constructor: (@seed) ->
|
||||||
M: 397
|
@multiplier = 1664525
|
||||||
MATRIX_A: 0x9908b0df
|
@modulo = 4294967296 # 2**32-1;
|
||||||
UPPER_MASK: 0x80000000
|
@offset = 1013904223
|
||||||
LOWER_MASK: 0x7fffffff
|
unless @seed? && 0 <= seed < @modulo
|
||||||
|
@seed = (new Date().valueOf() * new Date().getMilliseconds()) % @modulo
|
||||||
|
|
||||||
constructor: (seed) ->
|
# sets new seed value
|
||||||
@mt = new Array(@N)
|
seed: (seed) ->
|
||||||
@setSeed seed
|
@seed = seed
|
||||||
|
|
||||||
# makes the argument into an unsigned integer, if it is not already one
|
getSeed: () ->
|
||||||
unsigned32: (n1) -> if n1 < 0 then (n1 ^ @UPPER_MASK) + @UPPER_MASK else n1
|
return @seed
|
||||||
|
|
||||||
# emulates underflow of subtracting two 32-bit unsigned integers. both arguments
|
# return a random integer 0 <= n < @modulo
|
||||||
# must be non-negative 32-bit integers.
|
randn: ->
|
||||||
subtraction32: (n1, n2) ->
|
# new_seed = (a * seed + c) % m
|
||||||
if n1 < n2
|
@seed = (@multiplier*@seed + @offset) % @modulo
|
||||||
@unsigned32((0x100000000 - (n2 - n1)) % 0xffffffff)
|
|
||||||
else
|
|
||||||
n1 - n2
|
|
||||||
|
|
||||||
# emulates overflow of adding two 32-bit integers. both arguments must be
|
# return a random float 0 <= f < 1.0
|
||||||
# non-negative 32-bit integers.
|
randf: ->
|
||||||
addition32: (n1, n2) -> @unsigned32((n1 + n2) & 0xffffffff)
|
this.randn() / @modulo
|
||||||
|
|
||||||
# emulates overflow of multiplying two 32-bit integers. both arguments must
|
# return a random int 0 <= f < n
|
||||||
# be non-negative 32-bit integers.
|
rand: (n) ->
|
||||||
multiplication32: (n1, n2) ->
|
Math.floor(this.randf() * n)
|
||||||
sum = 0
|
|
||||||
for i in [0...32]
|
|
||||||
if ((n1 >>> i) & 0x1)
|
|
||||||
sum = @addition32(sum, @unsigned32(n2 << i))
|
|
||||||
sum
|
|
||||||
|
|
||||||
setSeed: (seed) ->
|
# return a random int min <= f < max
|
||||||
if !seed || typeof seed == "number"
|
randRange: (min, max) ->
|
||||||
@seedWithInteger seed
|
min + this.rand(max-min)
|
||||||
else
|
|
||||||
@seedWithArray seed
|
|
||||||
|
|
||||||
defaultSeed: ->
|
|
||||||
currentDate = new Date()
|
|
||||||
currentDate.getMinutes() * 60000 + currentDate.getSeconds() * 1000 + currentDate.getMilliseconds()
|
|
||||||
|
|
||||||
seedWithInteger: (seed) ->
|
|
||||||
@seed = seed ? @defaultSeed()
|
|
||||||
@mt[0] = @unsigned32(@seed & 0xffffffff)
|
|
||||||
@mti = 1
|
|
||||||
|
|
||||||
while @mti < @N
|
|
||||||
@mt[@mti] = @addition32(
|
|
||||||
@multiplication32(1812433253, @unsigned32(@mt[@mti-1] ^ (@mt[@mti-1] >>> 30))),
|
|
||||||
@mti)
|
|
||||||
@mti[@mti] = @unsigned32(@mt[@mti] & 0xffffffff)
|
|
||||||
@mti++
|
|
||||||
|
|
||||||
seedWithArray: (key) ->
|
|
||||||
@seedWithInteger 19650218
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
j = 0
|
|
||||||
k = if @N > key.length then @N else key.length
|
|
||||||
|
|
||||||
while k > 0
|
|
||||||
_m = @multiplication32(@unsigned32(@mt[i-1] ^ (@mt[i-1] >>> 30)), 1664525)
|
|
||||||
@mt[i] = @addition32(@addition32(@unsigned32(@mt[i] ^ _m), key[j]), j)
|
|
||||||
@mt[i] = @unsigned32(@mt[i] & 0xffffffff)
|
|
||||||
|
|
||||||
i++
|
|
||||||
j++
|
|
||||||
|
|
||||||
if i >= @N
|
|
||||||
@mt[0] = @mt[@N-1]
|
|
||||||
i = 1
|
|
||||||
|
|
||||||
j = 0 if j >= key.length
|
|
||||||
k--
|
|
||||||
|
|
||||||
k = @N - 1
|
|
||||||
while k > 0
|
|
||||||
@mt[i] = @subtraction32(
|
|
||||||
@unsigned32(@mt[i] ^ @multiplication32(@unsigned32(@mt[i-1] ^ (@mt[i-1] >>> 30)), 1566083941)), i)
|
|
||||||
@mt[i] = @unsigned32(@mt[i] & 0xffffffff)
|
|
||||||
i++
|
|
||||||
if i >= @N
|
|
||||||
@mt[0] = @mt[@N-1]
|
|
||||||
i = 1
|
|
||||||
|
|
||||||
@mt[0] = 0x80000000
|
|
||||||
|
|
||||||
nextInteger: (upper) ->
|
|
||||||
return 0 if (upper ? 1) < 1
|
|
||||||
|
|
||||||
mag01 = [0, @MATRIX_A]
|
|
||||||
|
|
||||||
if @mti >= @N
|
|
||||||
kk = 0
|
|
||||||
|
|
||||||
while kk < @N - @M
|
|
||||||
y = @unsigned32((@mt[kk] & @UPPER_MASK) | (@mt[kk+1] & @LOWER_MASK))
|
|
||||||
@mt[kk] = @unsigned32(@mt[kk+@M] ^ (y >>> 1) ^ mag01[y & 0x1])
|
|
||||||
kk++
|
|
||||||
|
|
||||||
while kk < @N-1
|
|
||||||
y = @unsigned32((@mt[kk] & @UPPER_MASK) | (@mt[kk+1] & @LOWER_MASK))
|
|
||||||
@mt[kk] = @unsigned32(@mt[kk+@M-@N] ^ (y >>> 1) ^ mag01[y & 0x1])
|
|
||||||
kk++
|
|
||||||
|
|
||||||
y = @unsigned32((@mt[@N-1] & @UPPER_MASK) | (@mt[0] & @LOWER_MASK))
|
|
||||||
@mt[@N-1] = @unsigned32(@mt[@M-1] ^ (y >>> 1) ^ mag01[y & 0x1])
|
|
||||||
@mti = 0
|
|
||||||
|
|
||||||
y = @mt[@mti++]
|
|
||||||
|
|
||||||
y = @unsigned32(y ^ (y >>> 11))
|
|
||||||
y = @unsigned32(y ^ ((y << 7) & 0x9d2c5680))
|
|
||||||
y = @unsigned32(y ^ ((y << 15) & 0xefc60000))
|
|
||||||
|
|
||||||
@unsigned32(y ^ (y >>> 18)) % (upper ? 0x100000000)
|
|
||||||
|
|
||||||
randomInt: (upper) ->
|
randomInt: (upper) ->
|
||||||
@nextInteger(upper)
|
@rand(upper)
|
||||||
|
|
||||||
nextFloat: -> @nextInteger() / 0xffffffff
|
|
||||||
|
|
||||||
nextBoolean: -> @nextInteger() % 2 == 0
|
|
||||||
|
|
||||||
# Returns the result of rolling *n* dice with *dx* sides, and adding *plus*.
|
# Returns the result of rolling *n* dice with *dx* sides, and adding *plus*.
|
||||||
dice: (n, dx, plus) ->
|
dice: (n, dx, plus) ->
|
||||||
result = 0
|
result = 0
|
||||||
for i in [0..n]
|
for i in [0..n]
|
||||||
console.log i
|
console.log i
|
||||||
result += @nextInteger(1, dx)
|
result += 1 + @randRange(1,dx)
|
||||||
if (plus)
|
if (plus)
|
||||||
result += plus
|
result += plus
|
||||||
result
|
result
|
||||||
|
|
|
@ -417,10 +417,8 @@ class Salet
|
||||||
console.error err
|
console.error err
|
||||||
else
|
else
|
||||||
currentDate = new Date()
|
currentDate = new Date()
|
||||||
@progress.seed = currentDate.getMinutes() * 60000
|
@rnd = new Random()
|
||||||
@progress.seed += currentDate.getSeconds() * 1000
|
@progress.seed = @rnd.getSeed()
|
||||||
@progress.seed += currentDate.getMilliseconds()
|
|
||||||
@rnd = new Random(@progress.seed)
|
|
||||||
|
|
||||||
@progress.sequence = [{link:@start, when:0}]
|
@progress.sequence = [{link:@start, when:0}]
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue