using Pcg; namespace PkmnLib.Static.Utils; /// /// Wrapper interface for getting random numbers. /// public interface IRandom { /// /// Get a random integer between min and max. /// /// The minimum value (inclusive). /// The maximum value (exclusive). /// A random integer that is greater than or equal to min and less than max. public int GetInt(int min, int max); /// /// Get a random integer between 0 and max. /// /// The maximum value (exclusive). /// A random integer that is greater than or equal to 0 and less than max. public int GetInt(int max); /// /// Get a random integer between 0 and . /// /// A random integer that is greater than or equal to 0 and less than . public int GetInt(); /// /// Get a random float that is greater than or equal to 0.0 and less than 1.0. /// /// A random float that is greater than or equal to 0.0 and less than 1.0. public float GetFloat(); /// /// Get a random float that is greater than or equal to min and less than max. /// /// The minimum value (inclusive). /// The maximum value (exclusive). /// A random float that is greater than or equal to min and less than max. public float GetFloat(float min, float max); /// /// Get a random boolean. 50% chance of being true. /// public bool GetBool(); /// /// Get a random element from the given list. /// public T OneOf(IReadOnlyList list); } /// public class RandomImpl : IRandom { private readonly PcgRandom _random; /// /// Creates a new instance that uses the given instance as its source of randomness. /// public RandomImpl(PcgRandom random) { _random = random; } /// /// Creates a new instance that uses the given seed to create a new instance. /// public RandomImpl(int seed) { _random = new PcgRandom(seed); } /// /// Creates a new instance that uses a new instance. /// public RandomImpl() { _random = new PcgRandom(); } /// public int GetInt(int min, int max) => _random.Next(min, max); /// public int GetInt(int max) => _random.Next(max); /// public int GetInt() => _random.Next(); /// public float GetFloat() => (float)_random.NextDouble(); /// public float GetFloat(float min, float max) => (float)(_random.NextDouble() * (max - min) + min); /// public bool GetBool() => _random.Next(2) == 1; /// public T OneOf(IReadOnlyList list) { if (list.Count == 0) throw new ArgumentException("List cannot be empty.", nameof(list)); return list[GetInt(list.Count)]; } /// /// Generates a new random . /// /// /// The goal of this method is to create a new unique identifier that can be used for various purposes, /// without having to rely on the system's built-in GUID generation. The built-in GUID generation /// can be slow (see also: https://github.com/dotnet/runtime/issues/13628) /// public Guid NewGuid() { var guidBytes = GuidCache.Value.AsSpan(); _random.NextBytes(guidBytes); return new Guid(guidBytes); } private static readonly ThreadLocal GuidCache = new(() => new byte[16]); }