--LRNG: Lightweight high-quality psuedorandom numbers (1.1) --Based on the SFC32 PRNG algorithm --Released under CC0. local LRNG = {} --Returns 32 bits of random data as an integer that can be negative. local function rng_next(state) local b, c, counter = state[2], state[3], state[4] local output = state[1] + b + counter state[4] = counter + 1 state[1] = b ^^ (b >> 9) state[2] = c * 9 state[3] = output + ((c << 21) | (c >> 11)) return output end --Reseeds a state with up to 3 seed values in-place. local function rng_seed(state, ...) local fallback_seeds = {1, 69105, 4142001} local seeds = {...} for i=1, 3 do state[4-i] = seeds[i] or fallback_seeds[i] end state[4] = 1 for i=1, 20 do rng_next(state) end end LRNG.NextInt = rng_next LRNG.Seed = rng_seed -- The rest of these are optional and can be removed if you do not need them. --Creates a new state with up to 3 seed values. function LRNG.New(...) local state = {} rng_seed(state, ...) return state end --Returns a random integer that will be positive. function LRNG.NextPositive(state) return rng_next(state) >> 1 end --Returns a random integer between 0 and FRACUNIT. function LRNG.NextFixed(state) return rng_next(state) >> 16 end --Only guaranteed to work properly with positive keys --Based on the JDK implementation function LRNG.NextKey(state, limit) if limit < 0 then error("limit can't be negative: "..tostring(n), 2) elseif limit < 2 then return 0 end local rand, result local mod = limit-1 repeat rand = rng_next(state) >> 1 result = rand % limit until rand - result + mod >= 0 return result end function LRNG.NextRange(state, min, max) if max < min then error("max can't be less than min", 2) elseif max-min == -1 then return rng_next(state) end return min + LRNG.NextKey(state, max-min + 1) end --Shuffles the array part of a table using Knuth's shuffle algorithm. --Works in place, so returns nothing. function LRNG.Shuffle(state, array) for i=#array, 2, -1 do local rand_val = LRNG.NextKey(state, i) + 1 array[i], array[rand_val] = array[rand_val], array[i] end end function LRNG.NextBits(state, bits) if bits < 1 or bits > 32 then error("invalid bits value ".. bits, 2) end return rng_next(state) >> (32-bits) end rawset(_G,"LRNG",LRNG)