'use strict'; // Mulberry32 - fast, deterministic PRNG function mulberry32(seed) { return function () { seed |= 0; seed = seed + 0x602a2ebf | 0; let t = Math.imul(seed ^ seed >>> 16, 0x6d349c2b); t = Math.imul(t ^ t >>> 16, 0x04c35085) | 0; t = t ^ t >>> 16; return (t >>> 0) / 4294967296; }; } // Create a seeded RNG instance function createRNG(seed) { return mulberry32(seed); } // Random integer in [min, max] inclusive function randInt(rng, min, max) { return Math.floor(rng() * (max - min + 1)) + min; } // Random float in [0, 1) function randFloat(rng) { return rng(); } // Pick random element from array function randElement(rng, arr) { return arr[Math.floor(rng() * arr.length)]; } // Shuffle array in place (Fisher-Yates) function shuffle(rng, arr) { const a = [...arr]; for (let i = a.length - 1; i > 0; i--) { const j = Math.floor(rng() * (i + 1)); [a[i], a[j]] = [a[j], a[i]]; } return a; } // Random choice with weights function weightedChoice(rng, items) { const total = items.reduce((sum, item) => sum + item.weight, 0); let r = rng() * total; for (const item of items) { r -= item.weight; if (r <= 0) return item.value; } return items[items.length - 1].value; } if (typeof module !== 'undefined' && module.exports) { module.exports = { createRNG, mulberry32, randInt, randFloat, randElement, shuffle, weightedChoice }; }