#nullable enable using System; using System.Collections.Generic; namespace ReplacedPerson.Core { /// PCG-XSH-RR 32; state is explicit so replays are portable across Unity and .NET. public sealed class Pcg32 { public ulong State { get; private set; } public ulong Increment { get; private set; } public Pcg32(ulong seed, ulong stream = 54UL) { State = 0UL; Increment = (stream << 1) | 1UL; NextUInt(); State += seed; NextUInt(); } private Pcg32(ulong state, ulong increment, bool _) { State = state; Increment = increment; } public Pcg32 Clone() => new(State, Increment, true); public uint NextUInt() { var oldState = State; State = unchecked(oldState * 6364136223846793005UL + Increment); var xorShifted = (uint)(((oldState >> 18) ^ oldState) >> 27); var rotation = (int)(oldState >> 59); return (xorShifted >> rotation) | (xorShifted << ((-rotation) & 31)); } public int NextInt(int exclusiveMax) { if (exclusiveMax <= 0) throw new ArgumentOutOfRangeException(nameof(exclusiveMax)); var bound = (uint)exclusiveMax; var threshold = unchecked((uint)(-bound)) % bound; while (true) { var value = NextUInt(); if (value >= threshold) return (int)(value % bound); } } public int RollD6() => NextInt(6) + 1; public void Shuffle(IList values) { if (values == null) throw new ArgumentNullException(nameof(values)); for (var i = values.Count - 1; i > 0; i--) { var j = NextInt(i + 1); (values[i], values[j]) = (values[j], values[i]); } } } }