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