package squidpony.squidmath;
/**
* A slight variant on RNG that always uses a stateful RandomessSource and so can have its state
* set or retrieved using setState() or getState().
* Created by Tommy Ettinger on 9/15/2015.
* @author Tommy Ettinger
*/
public class StatefulRNG extends RNG {
private static final long serialVersionUID = -2456306898212937163L;
public StatefulRNG() {
super(new LightRNG());
}
public StatefulRNG(RandomnessSource random) {
super((random instanceof StatefulRandomness) ? random : new LightRNG(random.nextLong()));
}
/**
* Seeded constructor uses LightRNG, which is of high quality, but low period (which rarely matters for games),
* and has good speed and tiny state size.
*/
public StatefulRNG(long seed) {
this(new LightRNG(seed));
}
/**
* String-seeded constructor uses the hash of the String as a seed for LightRNG, which is of high quality, but low
* period (which rarely matters for games), and has good speed and tiny state size.
*
* Note: This constructor changed behavior on April 22, 2017, when it was noticed that it was not seeding very
* effectively (only assigning to 32 bits of seed instead of all 64). If you want to keep the older behavior, you
* can by replacing {@code new StatefulRNG(text)} with {@code new StatefulRNG(CrossHash.hash(text))} . The new
* technique assigns to all 64 bits and has less correlation between similar inputs causing similar starting states.
* It's also faster, but that shouldn't matter in a constructor.
*/
public StatefulRNG(String seedString) {
this(new LightRNG(CrossHash.Wisp.hash64(seedString)));
}
@Override
public void setRandomness(RandomnessSource random) {
super.setRandomness((random instanceof StatefulRandomness) ? random : new LightRNG(random.nextLong()));
}
/**
* Creates a copy of this StatefulRNG; it will generate the same random numbers, given the same calls in order, as
* this StatefulRNG at the point copy() is called. The copy will not share references with this StatefulRNG.
*
* @return a copy of this StatefulRNG
*/
@Override
public RNG copy() {
return new StatefulRNG(random.copy());
}
/**
* Get a long that can be used to reproduce the sequence of random numbers this object will generate starting now.
* @return a long that can be used as state.
*/
public long getState()
{
return ((StatefulRandomness)random).getState();
}
/**
* Sets the state of the random number generator to a given long, which will alter future random numbers this
* produces based on the state.
* @param state a long, which typically should not be 0 (some implementations may tolerate a state of 0, however).
*/
public void setState(long state)
{
((StatefulRandomness)random).setState(state);
}
@Override
public String toString() {
return "StatefulRNG{" + Long.toHexString(((StatefulRandomness)random).getState()) + "}";
}
}