using System; using System.Collections.Generic; using System.Threading; namespace Lidgren.Network { /// /// NetRandom base class /// public abstract class NetRandom : Random { /// /// Get global instance of NetRandom (uses MWCRandom) /// public static NetRandom Instance = new MWCRandom(); private const double c_realUnitInt = 1.0 / ((double)int.MaxValue + 1.0); /// /// Constructor with randomized seed /// public NetRandom() { Initialize(NetRandomSeed.GetUInt32()); } /// /// Constructor with provided 32 bit seed /// public NetRandom(int seed) { Initialize((uint)seed); } /// /// (Re)initialize this instance with provided 32 bit seed /// [CLSCompliant(false)] public virtual void Initialize(uint seed) { // should be abstract, but non-CLS compliant methods can't be abstract! throw new NotImplementedException("Implement this in inherited classes"); } /// /// Generates a random value from UInt32.MinValue to UInt32.MaxValue, inclusively /// [CLSCompliant(false)] public virtual uint NextUInt32() { // should be abstract, but non-CLS compliant methods can't be abstract! throw new NotImplementedException("Implement this in inherited classes"); } /// /// Generates a random value that is greater or equal than 0 and less than Int32.MaxValue /// public override int Next() { var retval = (int)(0x7FFFFFFF & NextUInt32()); if (retval == 0x7FFFFFFF) return NextInt32(); return retval; } /// /// Generates a random value greater or equal than 0 and less or equal than Int32.MaxValue (inclusively) /// public int NextInt32() { return (int)(0x7FFFFFFF & NextUInt32()); } /// /// Returns random value larger or equal to 0.0 and less than 1.0 /// public override double NextDouble() { return c_realUnitInt * NextInt32(); } /// /// Returns random value is greater or equal than 0.0 and less than 1.0 /// protected override double Sample() { return c_realUnitInt * NextInt32(); } /// /// Returns random value is greater or equal than 0.0f and less than 1.0f /// public float NextSingle() { var retval = (float)(c_realUnitInt * NextInt32()); if (retval == 1.0f) return NextSingle(); return retval; } /// /// Returns a random value is greater or equal than 0 and less than maxValue /// public override int Next(int maxValue) { return (int)(NextDouble() * maxValue); } /// /// Returns a random value is greater or equal than minValue and less than maxValue /// public override int Next(int minValue, int maxValue) { return minValue + (int)(NextDouble() * (double)(maxValue - minValue)); } /// /// Generates a random value between UInt64.MinValue to UInt64.MaxValue /// [CLSCompliant(false)] public ulong NextUInt64() { ulong retval = NextUInt32(); retval |= NextUInt32() << 32; return retval; } private uint m_boolValues; private int m_nextBoolIndex; /// /// Returns true or false, randomly /// public bool NextBool() { if (m_nextBoolIndex >= 32) { m_boolValues = NextUInt32(); m_nextBoolIndex = 1; } var retval = ((m_boolValues >> m_nextBoolIndex) & 1) == 1; m_nextBoolIndex++; return retval; } /// /// Fills all bytes from offset to offset + length in buffer with random values /// public virtual void NextBytes(byte[] buffer, int offset, int length) { int full = length / 4; int ptr = offset; for (int i = 0; i < full; i++) { uint r = NextUInt32(); buffer[ptr++] = (byte)r; buffer[ptr++] = (byte)(r >> 8); buffer[ptr++] = (byte)(r >> 16); buffer[ptr++] = (byte)(r >> 24); } int rest = length - (full * 4); for (int i = 0; i < rest; i++) buffer[ptr++] = (byte)NextUInt32(); } /// /// Fill the specified buffer with random values /// public override void NextBytes(byte[] buffer) { NextBytes(buffer, 0, buffer.Length); } } }