0
0
Fork 0
mirror of https://gitlab.com/Oreolek/salet-module.git synced 2024-06-26 03:50:49 +03:00

Mersenne-Twister random submodule

This commit is contained in:
Alexander Yakovlev 2016-09-10 08:44:27 +07:00
parent 84f4502e44
commit 9a2f780cb4
3 changed files with 196 additions and 4 deletions

View file

@ -8,6 +8,7 @@ sources = [
'character.coffee'
'room.coffee'
'localize.coffee'
'random.coffee'
'salet.coffee'
]
sourcestring = ""
@ -24,7 +25,7 @@ task 'build', 'Compile all CoffeeScript files', ->
fs.mkdirSync 'lib'
# run coffee-script compile
exec "coffee -c --no-header -j lib/index.js #{sourcestring}", (err, stdout, stderr) ->
exec "cat #{sourcestring} | coffee --compile --stdio --no-header > lib/index.js", (err, stdout, stderr) ->
if err
util.log err
process.exit 1 # abort npm packaging

183
src/random.coffee Normal file
View file

@ -0,0 +1,183 @@
###
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.
CoffeeScript port by: Jamis Buck <jamis@jamisbuck.org>
License: Public domain, baby. Knock yourself out.
The original CoffeeScript sources are always available on GitHub:
http://github.com/jamis/csmazes
###
class Random
N: 624
M: 397
MATRIX_A: 0x9908b0df
UPPER_MASK: 0x80000000
LOWER_MASK: 0x7fffffff
constructor: (seed) ->
@mt = new Array(@N)
@setSeed 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
# 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
# emulates overflow of adding two 32-bit integers. both arguments must be
# non-negative 32-bit integers.
addition32: (n1, n2) -> @unsigned32((n1 + n2) & 0xffffffff)
# 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
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)
randomInt: (upper) ->
@nextInteger(upper)
nextFloat: -> @nextInteger() / 0xffffffff
nextBoolean: -> @nextInteger() % 2 == 0
# 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)
if (plus)
result += plus
result
# Rolls dice according to a xdy+z string, where
# x and z are optional.
# This rolls *x* dice of *y* sides and adds *z* to the result.
# The *y* component can be "F" for Fudge die or "%" for percentile.
diceString: (def) ->
diceRe = /^([1-9][0-9]*)?d([%FA]|[1-9][0-9]*)([-+][1-9][0-9]*)?$/;
match = def.match(diceRe)
if (!match)
throw new Error(
"dice_string_error".l({string:def})
)
num = 1
bonus = 0
sides = undefined
if match[1]
num = parseInt(match[1], 10)
if match[3]
bonus = parseInt(match[3], 10)
switch (match[2])
when 'F'
sides = 3
bonus -= num*2
break
when '%'
sides = 100
break
else
sides = parseInt(match[2], 10)
break
return @dice(num, sides, bonus)

View file

@ -380,6 +380,8 @@ class Salet
@progress = saveFile.progress
@character = new Character
@rnd = new Random(@progress.seed)
# Start the game
@init()
@ -414,7 +416,11 @@ class Salet
console.log "There was an error loading your save. The save will be overwritten."
console.error err
else
@progress.seed = new Date().toString()
currentDate = new Date()
@progress.seed = currentDate.getMinutes() * 60000
@progress.seed += currentDate.getSeconds() * 1000
@progress.seed += currentDate.getMilliseconds()
@rnd = new Random(@progress.seed)
@progress.sequence = [{link:@start, when:0}]
@ -444,5 +450,7 @@ class Salet
return this
window.salet = new Salet()
window.salet.view.init(window.salet)
salet = new Salet()
salet.view.init(salet)
module.exports = salet