Module:Random

From IdleOn MMO Wiki

Documentation for this module may be created at Module:Random/doc

require('strict')

local Assert = require('Module:Assert')
local bit32 = require('bit32')

--- @class Random
--- @field seed number
--- @field seed2 number
local Random = {}

local function imul(a, b)
	return bit32.bor(a * bit32.band(b, 65535) + bit32.bor(bit32.lshift((a * (bit32.rshift(b, 16))), 16), 0), 0)
end

local function hash(a, b)
    if b == nil then
        b = 5381
    end

    a = imul(a, -862048943)
    a = imul(bit32.bor(bit32.lshift(a, 15), bit32.rshift(a, 17)), 461845907)
    b = bit32.bxor(b, a)
    b = bit32.bor(imul(bit32.bor(bit32.lshift(b, 13), bit32.rshift(b, 19)), 5) + -430675100, 0)
    b = imul(bit32.bxor(b, bit32.arshift(b, 16)), -2048144789)
    b = imul(bit32.bxor(b, bit32.arshift(b, 13)), -1028477387)
    return bit32.bxor(b, bit32.arshift(b, 16))
end

function Random:_nextSeeds()
    self.seed = 36969 * bit32.band(self.seed, 65535) + bit32.arshift(self.seed, 16)
    self.seed2 = 18e3 * bit32.band(self.seed2, 65535) + bit32.arshift(self.seed2, 16)
end

function Random:new(a)
    Assert.isType(a, { 'nil', 'number' }, 'Seed must be either nil or a number')

    local seed = a
    if seed == nil or seed == 0 then
        seed = 1
    end

    local seed2 = hash(a)
    if seed2 == 0 then
        seed2 = 1
    end

    return setmetatable({
        seed = seed,
        seed2 = seed2
    }, { __index = Random })
end

function Random:random(a)
    self:_nextSeeds()
    return bit32.band(bit32.bor(bit32.lshift(self.seed, 16) + self.seed2, 0), 1073741823) % a
end

function Random:rand()
    return self:random(10007) / 10007
end

function Random:srand(a)
    if a == nil then
        a = 1
    end
    self:_nextSeeds()
    return bit32.bor(bit32.lshift(self.seed, 16) + self.seed2, 0) % 10007 / 10007 * a
end

function Random:int()
    self:_nextSeeds()
    return bit32.bor(bit32.lshift(self.seed, 16) + self.seed2, 0)
end

function Random:uint()
    self:_nextSeeds()
    return bit32.band(bit32.bor((bit32.lshift(self.seed, 16) + self.seed2), 0), 1073741823)
end

return Random