using UnityEngine;
using System.Collections;
namespace Tenkoku.Core
{
///
/// Simple and fast random number generator which can reset to a specific iteration
///
public class Random
{
//Initialiser magic values
private const ulong m_A_Init = 181353;
private const ulong m_B_Init = 7;
//Seed
public int m_seed;
//State
public ulong m_stateA, m_stateB;
///
/// Contruct and initialise the RNG
///
///
public Random(int seed = 1)
{
m_seed = seed;
if (m_seed == 0)
{
m_seed = 1;
}
Reset();
}
///
/// Reset it to its initial state with the existing seed
///
public void Reset()
{
m_stateA = m_A_Init * (uint)m_seed;
m_stateB = m_B_Init * (uint)m_seed;
}
///
/// Restet it to a new state with a new seed
///
/// New seed
public void Reset(int seed)
{
m_seed = seed;
if (m_seed == 0)
{
m_seed = 1;
}
Reset();
}
///
/// Reset it to the stade defined by the state variables passed in
///
public void Reset(ulong stateA, ulong stateB)
{
Debug.Log("Resetting RNG State " + stateA + " " + stateB);
m_stateA = stateA;
m_stateB = stateB;
}
///
/// Return the current state for serialisation
///
/// Seed
/// State A
/// State B
public void GetState(out int seed, out ulong stateA, out ulong stateB)
{
seed = m_seed;
stateA = m_stateA;
stateB = m_stateB;
}
//Check here for wrapper functions
//https://github.com/tucano/UnityRandom/blob/master/lib/MersenneTwister.cs
///
/// Get the next value
///
/// A value between zero and one inclusive
public float Next()
{
ulong x = m_stateA;
ulong y = m_stateB;
m_stateA = y;
x ^= x << 23;
x ^= x >> 17;
x ^= y ^ (y >> 26);
m_stateB = x;
return (float)(x + y) / (float)ulong.MaxValue;
}
///
/// Return the next int
///
///
public int NextInt()
{
return (int)(Next() * int.MaxValue);
}
///
/// Get the next value and scale it between the min and max values supplied inclusive
///
/// Minimum value
/// Maximum value
/// Next value scaled beteen the range supplied
public float Next(float min, float max)
{
//float xx = min + (Next() * (max - min));
//Debug.Log(string.Format("{0:0.0000}", xx));
//return xx;
return min + (Next() * (max - min));
}
///
/// Get the next value and scale it between the min and max values supplied inclusive
///
/// Minimum value
/// Maximum value
/// Next value scaled beteen the range supplied
public int Next(int min, int max)
{
if (min == max)
{
return min;
}
return (int)Next((float)min, (float)max+0.999f);
}
///
/// Get the next value as a vector
///
/// Next value as a vector in ranges 0..1
public Vector3 NextVector()
{
return new Vector3(Next(), Next(), Next());
}
///
/// Get the next value as a vector
///
/// Minimum value
/// Maximum value
///
public Vector3 NextVector(float min, float max)
{
return new Vector3(Next(min, max), Next(min, max), Next(min, max));
}
}
}