Package squidpony.squidmath
Class EditRNG
java.lang.Object
squidpony.squidmath.RNG
squidpony.squidmath.StatefulRNG
squidpony.squidmath.EditRNG
- All Implemented Interfaces:
Serializable
,IRNG
,IStatefulRNG
,RandomnessSource
,StatefulRandomness
public class EditRNG extends StatefulRNG implements Serializable
A subclass of StatefulRNG (and thus RNG) that allows customizing many parts of the random number generation.
This is meant to be a more comprehensible version of the functionality present in RandomBias, and also for it to be
easier to use with methods that expect an RNG.
You can change the expected average for the values this produces, which uses the RandomBias.EXPONENTIAL distribution, with all the caveats it has: it strongly favors either high or low values when the average gets especially high or low, but it can essentially cover all averages between 0.0 and 1.0 (this class limits it to 0.1 and 0.9, so other techniques can be used effectively).
You can also affect the "centrality" of random numbers, causing more to occur near the expected average (a bell curve effect), or cause more near extreme ends of the random number spectrum. In practice, centrality changes are hard to notice, but may be useful to simulate certain effects. An example of centrality changes in existing games include the Nintendo title Advance Wars 2, where a brutish commander could increase the amount of damage his units dealt but also suffered unpredictability; attacks could deal even more or much less damage than normal without any way to build tactics around it. Square Enix's Final Fantasy XII also notably differentiated certain weapons (axes, hammers, and "hand-cannons") from other similar options by making them deal less predictable damage. In both cases the connotation is that more randomness is fitting for a brute-force approach to combat where pre-planned strategies are less emphasized. It should also be noted that increasing the frequency of extreme results makes small bonuses to defense or offense typically less useful, and small penalties less harmful. The opposite can be true for a carefully tuned game where the most common results are tightly clustered, and most target numbers are just slightly above the ordinary average. In tabletop games, 1d20 and 3d6 have the same average, but 1d20 is uniform, where 3d6 is clustered around 10 and 11, each the result of 1/8 of rolls on their own and 1/4 together. This makes the case where a +1 bonus to succeed changes the outcome on approximately 5% of 1d20 rolls, regardless of the required number to succeed if it is less than 20. However, a +1 bonus matters on a variable portion of 3d6 rolls; if you become able to succeed on a 10 or 11 where that was a failure before, the bonus applies approximately 12.5% of the time. Becoming able to succeed on an 18 where that was a failure before is essentially worthless, affecting less than 0.5% of rolls. This property of centralized results should be considered if game balance and/or the lethality of combat is important. One lengthy stretch of extreme results by enemies that work against the favor of a player character generally result in a dead player character, and RNGs that make extreme results more common may seem particularly cruel to players.
This generator sets a field, rawLatest, every time a random number is produced. This stores a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive) that is not subject to the bias an expected average introduces, and is close to uniformly distributed. You should expect rawLatest to be higher when higher numbers are returned from a method like nextInt(), and lower when lower numbers are returned. This can be useful for rare effects that should not be drastically more or less likely when slight changes are made to the expected average; if the expected average is 0.65, many more random doubles from nextDouble() will be between 0.95 and 1.0 (probably more than 10% of random numbers), but rawLatest will only be between 0.95 and 1.0 for close to 5% of all generations.
You can get and set the state this uses internally, and this is stored as a 64-bit long.
The choice of RandomnessSource doesn't really matter since this will always use a LightRNG internally. LightRNG is the current best StatefulRandomness implementation, with excellent performance characteristics and few flaws, and though its relatively low period may sometimes be a detriment, all StatefulRandomness implementations will have the same or lower period.
More customizations may be added in the future to the ones available currently.
You can change the expected average for the values this produces, which uses the RandomBias.EXPONENTIAL distribution, with all the caveats it has: it strongly favors either high or low values when the average gets especially high or low, but it can essentially cover all averages between 0.0 and 1.0 (this class limits it to 0.1 and 0.9, so other techniques can be used effectively).
You can also affect the "centrality" of random numbers, causing more to occur near the expected average (a bell curve effect), or cause more near extreme ends of the random number spectrum. In practice, centrality changes are hard to notice, but may be useful to simulate certain effects. An example of centrality changes in existing games include the Nintendo title Advance Wars 2, where a brutish commander could increase the amount of damage his units dealt but also suffered unpredictability; attacks could deal even more or much less damage than normal without any way to build tactics around it. Square Enix's Final Fantasy XII also notably differentiated certain weapons (axes, hammers, and "hand-cannons") from other similar options by making them deal less predictable damage. In both cases the connotation is that more randomness is fitting for a brute-force approach to combat where pre-planned strategies are less emphasized. It should also be noted that increasing the frequency of extreme results makes small bonuses to defense or offense typically less useful, and small penalties less harmful. The opposite can be true for a carefully tuned game where the most common results are tightly clustered, and most target numbers are just slightly above the ordinary average. In tabletop games, 1d20 and 3d6 have the same average, but 1d20 is uniform, where 3d6 is clustered around 10 and 11, each the result of 1/8 of rolls on their own and 1/4 together. This makes the case where a +1 bonus to succeed changes the outcome on approximately 5% of 1d20 rolls, regardless of the required number to succeed if it is less than 20. However, a +1 bonus matters on a variable portion of 3d6 rolls; if you become able to succeed on a 10 or 11 where that was a failure before, the bonus applies approximately 12.5% of the time. Becoming able to succeed on an 18 where that was a failure before is essentially worthless, affecting less than 0.5% of rolls. This property of centralized results should be considered if game balance and/or the lethality of combat is important. One lengthy stretch of extreme results by enemies that work against the favor of a player character generally result in a dead player character, and RNGs that make extreme results more common may seem particularly cruel to players.
This generator sets a field, rawLatest, every time a random number is produced. This stores a pseudo-random double between 0.0 (inclusive) and 1.0 (exclusive) that is not subject to the bias an expected average introduces, and is close to uniformly distributed. You should expect rawLatest to be higher when higher numbers are returned from a method like nextInt(), and lower when lower numbers are returned. This can be useful for rare effects that should not be drastically more or less likely when slight changes are made to the expected average; if the expected average is 0.65, many more random doubles from nextDouble() will be between 0.95 and 1.0 (probably more than 10% of random numbers), but rawLatest will only be between 0.95 and 1.0 for close to 5% of all generations.
You can get and set the state this uses internally, and this is stored as a 64-bit long.
The choice of RandomnessSource doesn't really matter since this will always use a LightRNG internally. LightRNG is the current best StatefulRandomness implementation, with excellent performance characteristics and few flaws, and though its relatively low period may sometimes be a detriment, all StatefulRandomness implementations will have the same or lower period.
More customizations may be added in the future to the ones available currently.
- See Also:
- Serialized Form
-
Nested Class Summary
-
Field Summary
Fields Modifier and Type Field Description double
rawLatest
The latest generated double, between 0.0 and 1.0, before changes for centrality and expected average. -
Constructor Summary
Constructors Constructor Description EditRNG()
Constructs an EditRNG with a pseudo-random seed from Math.random().EditRNG(long seed)
Construct a new EditRNG with the given seed.EditRNG(long seed, double expected)
Construct a new EditRNG with the given seed.EditRNG(long seed, double expected, double centrality)
Construct a new EditRNG with the given seed.EditRNG(CharSequence seed)
Construct a new EditRNG with the given seed.EditRNG(String seed, double expected)
Construct a new EditRNG with the given seed.EditRNG(String seed, double expected, double centrality)
Construct a new EditRNG with the given seed.EditRNG(RandomnessSource rs)
Construct a new EditRNG with the given seed.EditRNG(RandomnessSource rs, double expected)
Construct a new EditRNG with the given seed.EditRNG(RandomnessSource rs, double expected, double centrality)
Construct a new EditRNG with the given seed. -
Method Summary
Modifier and Type Method Description EditRNG
copy()
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.boolean
equals(Object o)
double
getCentrality()
Gets the current centrality measure of this EditRNG.double
getExpected()
Gets the current expected average for this EditRNG.RandomnessSource
getRandomness()
double
getRawLatest()
Gets the latest "un-biased" random double used to produce the most recent (potentially) biased random number generated for another method in this class, such as nextDouble(), between(), or getRandomElement().int
hashCode()
int
next(int bits)
Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbits
bits to represent.boolean
nextBoolean()
Get a random bit of state, interpreted as true or false with approximately equal likelihood.double
nextDouble()
Generate a random double, altered to try to match the expected average and centrality.double
nextDouble(double max)
This returns a random double between 0.0 (inclusive) and max (exclusive).float
nextFloat()
Gets a random float between 0.0f inclusive and 1.0f exclusive.int
nextInt()
Returns a random integer, which may be positive or negative.int
nextInt(int bound)
Returns a random integer below the given bound, or 0 if the bound is 0 or negative.int
nextIntHasty(int bound)
Returns a random non-negative integer below the given bound, or 0 if the bound is 0.long
nextLong()
Returns a random long, which may be positive or negative.long
nextLong(long bound)
Returns a random long below the given bound, or 0 if the bound is 0 or negative.void
setCentrality(double centrality)
Gets the current centrality measure of this EditRNG.void
setExpected(double expected)
Sets the expected average for random doubles this produces, which must always be between 0.1 and 0.9, and will be set to 0.5 if an invalid value is passed.void
setRandomness(RandomnessSource random)
Serializable
toSerializable()
Returns this EditRNG in a way that can be deserialized even if onlyIRNG
's methods can be called.String
toString()
Methods inherited from class squidpony.squidmath.RNG
approximateBits, asRandom, between, between, between, betweenWeighted, getRandomCellsIterable, getRandomElement, getRandomElement, getRandomElement, getRandomStartIterable, getRandomUniqueCells, getRandomUniqueCells, getRandomUniqueCells, maxDoubleOf, maxFloatOf, maxIntOf, maxLongOf, minDoubleOf, minFloatOf, minIntOf, minLongOf, nextBytes, nextCoord, nextCurvedFloat, nextDoubleInclusive, nextDoubleInclusive, nextFloat, nextFloatInclusive, nextFloatInclusive, nextSignedInt, nextSignedLong, randomInterleave, randomOrdering, randomOrdering, randomPortion, randomPortion, randomRange, randomRotation, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface squidpony.squidmath.IRNG
between, between, between, getRandomElement, getRandomElement, getRandomElement, nextFloat, nextSignedInt, nextSignedLong, randomOrdering, randomOrdering, randomPortion, shuffle, shuffle, shuffle, shuffle, shuffleInPlace, shuffleInPlace
-
Field Details
-
rawLatest
The latest generated double, between 0.0 and 1.0, before changes for centrality and expected average. Doubles are used to generate all random numbers this class produces, so be aware that calling getRandomElement() will change this just as much as nextDouble(), nextInt(), or between() will. Primarily useful to obtain uniformly-distributed random numbers that are related to the biased random numbers this returns as a main result, such as to find when the last number generated was in the bottom 5% (less than 0.05, which could represent some kind of critical failure or fumble) or top 10% (greater than or equal to 0.9, which could grant a critical success or luck-based reward of some kind).
-
-
Constructor Details
-
EditRNG
public EditRNG()Constructs an EditRNG with a pseudo-random seed from Math.random(). -
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9centrality
- if positive, makes results more likely to be near expected; if negative, the opposite. The absolute value of centrality affects how centered results will be, with 0 having no effect
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
seed
- used to seed the default RandomnessSource.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9centrality
- if positive, makes results more likely to be near expected; if negative, the opposite. The absolute value of centrality affects how centered results will be, with 0 having no effect
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
rs
- the implementation used to generate random bits.
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
rs
- the implementation used to generate random bits.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9
-
EditRNG
Construct a new EditRNG with the given seed.- Parameters:
rs
- the implementation used to generate random bits.expected
- the expected average for random doubles, which will be capped between 0.1 and 0.9centrality
- if positive, makes results more likely to be near expected; if negative, the opposite. The absolute value of centrality affects how centered results will be, with 0 having no effect
-
-
Method Details
-
nextDouble
Generate a random double, altered to try to match the expected average and centrality.- Specified by:
nextDouble
in interfaceIRNG
- Overrides:
nextDouble
in classRNG
- Returns:
- a double between 0.0 (inclusive) and 1.0 (exclusive)
-
nextDouble
This returns a random double between 0.0 (inclusive) and max (exclusive).- Specified by:
nextDouble
in interfaceIRNG
- Overrides:
nextDouble
in classRNG
- Parameters:
max
- the outer exclusive bound as a double; can be negative or positive- Returns:
- a value between 0 (inclusive) and max (exclusive)
-
nextInt
Returns a random integer below the given bound, or 0 if the bound is 0 or negative. -
nextInt
Returns a random integer, which may be positive or negative. -
nextLong
Returns a random long, which may be positive or negative. -
nextLong
Returns a random long below the given bound, or 0 if the bound is 0 or negative. -
getExpected
Gets the current expected average for this EditRNG.- Returns:
- the current expected average.
-
setExpected
Sets the expected average for random doubles this produces, which must always be between 0.1 and 0.9, and will be set to 0.5 if an invalid value is passed.- Parameters:
expected
- the expected average to use, which should be 0.1 <= fairness < 0.9
-
getCentrality
Gets the current centrality measure of this EditRNG. Centrality has several possible effects: When positive, makes the generator more likely to generate values close to the average (bell curve). When zero (the default), makes no changes to the centering of values. When negative, makes the generator swing more toward extremes rather than gravitate toward the average.
Values are typically between -100 and 100, but can have extreme weight and overshadow other parts of the RNG if they go much higher than 200.- Returns:
- the current centrality
-
setCentrality
Gets the current centrality measure of this EditRNG. Centrality has several possible effects: When positive, makes the generator more likely to generate values close to the average (bell curve). When zero (the default), makes no changes to the centering of values. When negative, makes the generator swing more toward extremes rather than gravitate toward the average.
Values are typically between -100 and 100, but can have extreme weight and overshadow other parts of the RNG if they go much higher than 200.- Parameters:
centrality
- the new centrality measure to use
-
next
Description copied from class:RNG
Get up to 32 bits (inclusive) of random output; the int this produces will not require more thanbits
bits to represent. -
nextFloat
Description copied from class:RNG
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 . -
nextBoolean
Description copied from class:RNG
Get a random bit of state, interpreted as true or false with approximately equal likelihood. This may have better behavior thanrng.next(1)
, depending on the RandomnessSource implementation; the default DiverRNG will behave fine, as will LightRNG and ThrustAltRNG (these all use similar algorithms), but the normally-high-quality XoRoRNG will produce very predictable output withrng.next(1)
and very good output withrng.nextBoolean()
. This is a known and considered flaw of Xoroshiro128+, the algorithm used by XoRoRNG, and a large number of generators have lower quality on the least-significant bit than the most- significant bit, where this method only checks the most-significant bit.- Specified by:
nextBoolean
in interfaceIRNG
- Overrides:
nextBoolean
in classRNG
- Returns:
- a random boolean.
-
getRandomness
- Overrides:
getRandomness
in classRNG
-
setRandomness
- Overrides:
setRandomness
in classStatefulRNG
-
getRawLatest
Gets the latest "un-biased" random double used to produce the most recent (potentially) biased random number generated for another method in this class, such as nextDouble(), between(), or getRandomElement(). This is a double between 0.0 (inclusive) and 1.0 (exclusive).- Returns:
- the latest uniformly-distributed double before bias is added; between 0.0 and 1.0 (exclusive upper)
-
copy
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.- Specified by:
copy
in interfaceIRNG
- Specified by:
copy
in interfaceRandomnessSource
- Specified by:
copy
in interfaceStatefulRandomness
- Overrides:
copy
in classStatefulRNG
- Returns:
- a copy of this StatefulRNG
-
toString
- Overrides:
toString
in classStatefulRNG
-
equals
-
hashCode
-
nextIntHasty
Returns a random non-negative integer below the given bound, or 0 if the bound is 0. Uses a slightly optimized technique. This method is considered "hasty" since it should be faster than nextInt() doesn't check for "less-valid" bounds values. It also has undefined behavior if bound is negative, though it will probably produce a negative number (just how negative is an open question).- Overrides:
nextIntHasty
in classRNG
- Parameters:
bound
- the upper bound (exclusive); behavior is undefined if bound is negative- Returns:
- the found number
-
toSerializable
Returns this EditRNG in a way that can be deserialized even if onlyIRNG
's methods can be called.- Specified by:
toSerializable
in interfaceIRNG
- Overrides:
toSerializable
in classStatefulRNG
- Returns:
- a
Serializable
view of this EditRNG; alwaysthis
-