/** * シードデータ生成用の決定論的乱数ユーティリティ。 * mulberry32 を用い、固定シードで再現可能なデータを生成する。 */ export type Rng = () => number; export function createRng(seed: number): Rng { let a = seed >>> 0; return () => { a |= 0; a = (a + 0x6d2b79f5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } export function pick(rng: Rng, arr: readonly T[]): T { return arr[Math.floor(rng() * arr.length)]!; } export function pickN(rng: Rng, arr: readonly T[], n: number): T[] { return shuffle(rng, arr).slice(0, Math.min(n, arr.length)); } export function randInt(rng: Rng, min: number, max: number): number { return Math.floor(rng() * (max - min + 1)) + min; } export function shuffle(rng: Rng, arr: readonly T[]): T[] { const out = [...arr]; for (let i = out.length - 1; i > 0; i--) { const j = Math.floor(rng() * (i + 1)); [out[i], out[j]] = [out[j]!, out[i]!]; } return out; } export function chance(rng: Rng, p: number): boolean { return rng() < p; } export function seededUuid(rng: Rng): string { const hex = () => Math.floor(rng() * 0x10000) .toString(16) .padStart(4, '0'); return `${hex()}${hex()}-${hex()}-${hex()}-${hex()}-${hex()}${hex()}${hex()}`; }