/** Seed normalization and deterministic PRNG used only for scenario materialization. */

export function normalizeArenaSeed(value: number): number {
  if (!Number.isSafeInteger(value)) throw new RangeError("arena seed must be a safe integer");
  return value >>> 0;
}

export class ArenaRandom {
  private state: number;

  constructor(seed: number) {
    this.state = normalizeArenaSeed(seed) || 0x6d2b79f5;
  }

  next(): number {
    let value = this.state += 0x6d2b79f5;
    value = Math.imul(value ^ value >>> 15, value | 1);
    value ^= value + Math.imul(value ^ value >>> 7, value | 61);
    this.state = value >>> 0;
    return ((value ^ value >>> 14) >>> 0) / 4_294_967_296;
  }

  between(min: number, max: number): number {
    return min + (max - min) * this.next();
  }
}

export function deriveArenaSeed(seed: number, label: string): number {
  let value = normalizeArenaSeed(seed) ^ 0x811c9dc5;
  for (let index = 0; index < label.length; index += 1) {
    value ^= label.charCodeAt(index);
    value = Math.imul(value, 0x01000193) >>> 0;
  }
  return value;
}
