Package squidpony.squidmath
Class MoonwalkRNG
java.lang.Object
squidpony.squidmath.AbstractRNG
squidpony.squidmath.MoonwalkRNG
- All Implemented Interfaces:
Serializable,IRNG,IStatefulRNG,RandomnessSource,SkippingRandomness,StatefulRandomness
public class MoonwalkRNG extends AbstractRNG implements IStatefulRNG, SkippingRandomness, Serializable
An IRNG implementation that allows the extra functionality of a StatefulRandomness and a SkippingRandomness, as well
as allowing reverse-lookup of the state that produced a long using the static
Internally, this is like
The name comes from the ability of this generator to easily go in reverse, like the moonwalk dance move, including
Created by Tommy Ettinger on 4/14/2018.
inverseNextLong(long) method,
and distance checks between two generated numbers with the static distance(long, long) method. A task this
might be useful for could be simple obfuscation that is hard to undo unless you know the starting state, like this:
- take a sequence of numbers or characters and a MoonwalkRNG with a given starting state,
- modify each item in the sequence with a random but reversible change such as a bitwise XOR
with a number produced by the MoonwalkRNG (such as by
nextInt()), - on a later run, take the modified sequence and a MoonwalkRNG with the same starting state (but no direct
access to the starting sequence), and skip ahead by the length of the sequence with
skip(long), - starting at the end of the sequence, apply the reverse change to the items with numbers generated
backwards by MoonwalkRNG with
previousInt()(such as a XOR if the number was originally modified with a XOR or an addition if it was originally modified with a subtraction), - when the full sequence has been reversed, you now have the original sequence again.
Internally, this is like
StatefulRNG if it always used LightRNG and allowed access to LightRNG's
skip() method as well as the reverse lookup and distance methods that aren't in LightRNG but are allowed by it.
The name comes from the ability of this generator to easily go in reverse, like the moonwalk dance move, including
previousLong() and skip(long) for advancing backwards, but also inverseNextLong(long) to
go from output back to state.
Created by Tommy Ettinger on 4/14/2018.
- See Also:
- Serialized Form
-
Constructor Summary
Constructors Constructor Description MoonwalkRNG()Default constructor; uses a random seed.MoonwalkRNG(long seed)Constructs a MoonwalkRNG with the given seed as-is; any seed can be given.MoonwalkRNG(CharSequence seedString)String-seeded constructor; uses a platform-independent hash of the String (it does not use String.hashCode) as a seed for this RNG. -
Method Summary
Modifier and Type Method Description MoonwalkRNGcopy()Creates a copy of this MoonwalkRNG; it will generate the same random numbers, given the same calls in order, as this MoonwalkRNG at the point copy() is called.static longdistance(long out1, long out2)Returns the number of steps (where a step is equal to one call to most random number methods in this class) needed to go from receiving out1 from a MoonwalkRNG'snextLong()method to receiving out2 from another call.booleanequals(Object o)longgetState()Get the current internal state of the StatefulRandomness as a long.inthashCode()static longinverseNextLong(long out)Given the output of a call tonextLong()asout, this finds the state of the MoonwalkRNG that produce that output.intnext(int bits)Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbitsbits to represent.booleannextBoolean()Get a random bit of state, interpreted as true or false with approximately equal likelihood.doublenextDouble()Gets a random double between 0.0 inclusive and 1.0 exclusive.floatnextFloat()Gets a random float between 0.0f inclusive and 1.0f exclusive.intnextInt()Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).longnextLong()Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).intpreviousInt()Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextInt()alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls.longpreviousLong()Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextLong()alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls.voidsetState(long state)Set the current internal state of this StatefulRandomness with a long; all longs are allowed.longskip(long advance)Advances or rolls back the SkippingRandomness' state without actually generating each number.SerializabletoSerializable()Gets a view of this IRNG in a way that implementsSerializable, which may simply be this IRNG if it implements Serializable as well as IRNG.StringtoString()Methods inherited from class squidpony.squidmath.AbstractRNG
between, between, between, getRandomElement, getRandomElement, getRandomElement, nextDouble, nextFloat, nextInt, nextLong, nextSignedInt, nextSignedLong, randomOrdering, randomOrdering, randomPortion, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace, swapMethods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, waitMethods inherited from interface squidpony.squidmath.IRNG
between, between, between, getRandomElement, getRandomElement, getRandomElement, nextDouble, nextFloat, nextInt, nextLong, nextSignedInt, nextSignedLong, randomOrdering, randomOrdering, randomPortion, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace
-
Constructor Details
-
MoonwalkRNG
public MoonwalkRNG()Default constructor; uses a random seed. -
MoonwalkRNG
Constructs a MoonwalkRNG with the given seed as-is; any seed can be given.- Parameters:
seed- any long
-
MoonwalkRNG
String-seeded constructor; uses a platform-independent hash of the String (it does not use String.hashCode) as a seed for this RNG.- Parameters:
seedString- any CharSequence, such as a String or StringBuilder; if null this will use the seed 0
-
-
Method Details
-
next
Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbitsbits to represent.- Specified by:
nextin interfaceIRNG- Specified by:
nextin interfaceRandomnessSource- Specified by:
nextin classAbstractRNG- Parameters:
bits- an int between 1 and 32, both inclusive- Returns:
- a random number that fits in the specified number of bits
-
nextInt
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive).- Specified by:
nextIntin interfaceIRNG- Specified by:
nextIntin classAbstractRNG- Returns:
- a 32-bit random int.
-
nextLong
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive).- Specified by:
nextLongin interfaceIRNG- Specified by:
nextLongin interfaceRandomnessSource- Specified by:
nextLongin classAbstractRNG- Returns:
- a 64-bit random long.
-
previousInt
Get a random integer between Integer.MIN_VALUE to Integer.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextInt()alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls. This can be useful withskip(long)when it advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number generations that had been done by other code.- Returns:
- a 32-bit random int.
-
previousLong
Get a random long between Long.MIN_VALUE to Long.MAX_VALUE (both inclusive), but advances the state "backwards," such that callingnextLong()alternating with this method will return the same pair of numbers for as long as you keep alternating those two calls. This can be useful withskip(long)when it advances ahead by a large amount and you want to step backward to reverse another set of forward-advancing number generations that had been done by other code.- Returns:
- a 64-bit random long.
-
nextBoolean
Get a random bit of state, interpreted as true or false with approximately equal likelihood.
This implementation uses a sign check and is able to avoid some calculations needed to get a full int or long.- Specified by:
nextBooleanin interfaceIRNG- Specified by:
nextBooleanin classAbstractRNG- Returns:
- a random boolean.
-
nextDouble
Gets a random double between 0.0 inclusive and 1.0 exclusive. This returns a maximum of 0.9999999999999999 because that is the largest double value that is less than 1.0 .- Specified by:
nextDoublein interfaceIRNG- Specified by:
nextDoublein classAbstractRNG- Returns:
- a double between 0.0 (inclusive) and 0.9999999999999999 (inclusive)
-
nextFloat
Gets a random float between 0.0f inclusive and 1.0f exclusive. This returns a maximum of 0.99999994 because that is the largest float value that is less than 1.0f .- Specified by:
nextFloatin interfaceIRNG- Specified by:
nextFloatin classAbstractRNG- Returns:
- a float between 0f (inclusive) and 0.99999994f (inclusive)
-
copy
Creates a copy of this MoonwalkRNG; it will generate the same random numbers, given the same calls in order, as this MoonwalkRNG at the point copy() is called. The copy will not share references with this MoonwalkRNG.- Specified by:
copyin interfaceIRNG- Specified by:
copyin interfaceRandomnessSource- Specified by:
copyin interfaceStatefulRandomness- Specified by:
copyin classAbstractRNG- Returns:
- a copy of this IRNG
-
toSerializable
Gets a view of this IRNG in a way that implementsSerializable, which may simply be this IRNG if it implements Serializable as well as IRNG.
For implementors: It is suggested to return anRNGinitialized by callingRNG(long)withnextLong()if you are unable to save the current state of this IRNG and the caller still needs something saved. This won't preserve the current state or the choice of IRNG implementation, however, so it is simply a last resort in case you don't want to throw an exception.- Specified by:
toSerializablein interfaceIRNG- Specified by:
toSerializablein classAbstractRNG- Returns:
- a
Serializableview of this IRNG or a similar one; may bethis
-
skip
Advances or rolls back the SkippingRandomness' state without actually generating each number. Skips forward or backward a number of steps specified by advance, where a step is equal to one call tonextLong(), and returns the random number produced at that step. Negative numbers can be used to step backward, or 0 can be given to get the most-recently-generated long fromnextLong().- Specified by:
skipin interfaceSkippingRandomness- Parameters:
advance- Number of future generations to skip over; can be negative to backtrack, 0 gets the most-recently-generated number- Returns:
- the random long generated after skipping forward or backwards by
advancenumbers
-
getState
Get the current internal state of the StatefulRandomness as a long.- Specified by:
getStatein interfaceStatefulRandomness- Returns:
- the current internal state of this object as a long
-
setState
Set the current internal state of this StatefulRandomness with a long; all longs are allowed.- Specified by:
setStatein interfaceStatefulRandomness- Parameters:
state- a 64-bit long; this can be any long, even 0
-
toString
-
equals
-
hashCode
-
inverseNextLong
Given the output of a call tonextLong()asout, this finds the state of the MoonwalkRNG that produce that output. If you set the state of a MoonwalkRNG withsetState(long)to the result of this method and then callnextLong()on it, you should get backout.
This isn't as fast asnextLong(), but both run in constant time. Some random number generators take more than constant time to reverse, so one was chosen for this class that would still be efficient (LightRNG).
This will not necessarily work if out was produced by a generator other than a MoonwalkRNG, or if it was produced with the boundedAbstractRNG.nextLong(long)method by any generator.- Parameters:
out- a long as produced bynextLong(), without changes- Returns:
- the state of the RNG that will produce the given long
-
distance
Returns the number of steps (where a step is equal to one call to most random number methods in this class) needed to go from receiving out1 from a MoonwalkRNG'snextLong()method to receiving out2 from another call. This number can be used withskip(long)to move a MoonwalkRNG forward or backward by the desired distance.- Parameters:
out1- a long as produced bynextLong(), without changesout2- a long as produced bynextLong(), without changes- Returns:
- the number of calls to
nextLong()that would be required to go from producing out1 to producing out2; can be positive or negative, and can be passed toskip(long)
-