Class 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.
See Also:
Serialized Form
  • Field Details

    • rawLatest

      public double 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

      public EditRNG​(long seed)
      Construct a new EditRNG with the given seed.
      Parameters:
      seed - used to seed the default RandomnessSource.
    • EditRNG

      public EditRNG​(CharSequence seed)
      Construct a new EditRNG with the given seed.
      Parameters:
      seed - used to seed the default RandomnessSource.
    • EditRNG

      public EditRNG​(long seed, double expected)
      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

      public EditRNG​(String seed, double expected)
      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

      public EditRNG​(long seed, double expected, double centrality)
      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
      centrality - 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

      public EditRNG​(String seed, double expected, double centrality)
      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
      centrality - 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

      public EditRNG​(RandomnessSource rs)
      Construct a new EditRNG with the given seed.
      Parameters:
      rs - the implementation used to generate random bits.
    • EditRNG

      public EditRNG​(RandomnessSource rs, double expected)
      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

      public EditRNG​(RandomnessSource rs, double expected, double centrality)
      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
      centrality - 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

      public double nextDouble()
      Generate a random double, altered to try to match the expected average and centrality.
      Specified by:
      nextDouble in interface IRNG
      Overrides:
      nextDouble in class RNG
      Returns:
      a double between 0.0 (inclusive) and 1.0 (exclusive)
    • nextDouble

      public double nextDouble​(double max)
      This returns a random double between 0.0 (inclusive) and max (exclusive).
      Specified by:
      nextDouble in interface IRNG
      Overrides:
      nextDouble in class RNG
      Parameters:
      max - the outer exclusive bound as a double; can be negative or positive
      Returns:
      a value between 0 (inclusive) and max (exclusive)
    • nextInt

      public int nextInt​(int bound)
      Returns a random integer below the given bound, or 0 if the bound is 0 or negative.
      Specified by:
      nextInt in interface IRNG
      Overrides:
      nextInt in class RNG
      Parameters:
      bound - the upper bound (exclusive)
      Returns:
      the found number
    • nextInt

      public int nextInt()
      Returns a random integer, which may be positive or negative.
      Specified by:
      nextInt in interface IRNG
      Overrides:
      nextInt in class RNG
      Returns:
      A random int
    • nextLong

      public long nextLong()
      Returns a random long, which may be positive or negative.
      Specified by:
      nextLong in interface IRNG
      Specified by:
      nextLong in interface RandomnessSource
      Overrides:
      nextLong in class RNG
      Returns:
      A random long
    • nextLong

      public long nextLong​(long bound)
      Returns a random long below the given bound, or 0 if the bound is 0 or negative.
      Specified by:
      nextLong in interface IRNG
      Overrides:
      nextLong in class RNG
      Parameters:
      bound - the upper bound (exclusive)
      Returns:
      the found number
    • getExpected

      public double getExpected()
      Gets the current expected average for this EditRNG.
      Returns:
      the current expected average.
    • setExpected

      public 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.
      Parameters:
      expected - the expected average to use, which should be 0.1 <= fairness < 0.9
    • getCentrality

      public double 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

      public void setCentrality​(double centrality)
      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

      public int next​(int bits)
      Description copied from class: RNG
      Get up to 32 bits (inclusive) of random output; the int this produces will not require more than bits bits to represent.
      Specified by:
      next in interface IRNG
      Specified by:
      next in interface RandomnessSource
      Overrides:
      next in class RNG
      Parameters:
      bits - the number of bits to be returned
      Returns:
      a random int of the number of bits specified.
    • nextFloat

      public float 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 .
      Specified by:
      nextFloat in interface IRNG
      Overrides:
      nextFloat in class RNG
      Returns:
      a float between 0f (inclusive) and 0.99999994f (inclusive)
    • nextBoolean

      public boolean 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 than rng.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 with rng.next(1) and very good output with rng.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 interface IRNG
      Overrides:
      nextBoolean in class RNG
      Returns:
      a random boolean.
    • getRandomness

      Overrides:
      getRandomness in class RNG
    • setRandomness

      public void setRandomness​(RandomnessSource random)
      Overrides:
      setRandomness in class StatefulRNG
    • getRawLatest

      public 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(). 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

      public 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. The copy will not share references with this StatefulRNG.
      Specified by:
      copy in interface IRNG
      Specified by:
      copy in interface RandomnessSource
      Specified by:
      copy in interface StatefulRandomness
      Overrides:
      copy in class StatefulRNG
      Returns:
      a copy of this StatefulRNG
    • toString

      public String toString()
      Overrides:
      toString in class StatefulRNG
    • equals

      public boolean equals​(Object o)
      Overrides:
      equals in class RNG
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class RNG
    • nextIntHasty

      public int nextIntHasty​(int bound)
      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 class RNG
      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 only IRNG's methods can be called.
      Specified by:
      toSerializable in interface IRNG
      Overrides:
      toSerializable in class StatefulRNG
      Returns:
      a Serializable view of this EditRNG; always this