Package squidpony.squidmath
Class RandomBias
java.lang.Object
squidpony.squidmath.RandomBias
- All Implemented Interfaces:
Serializable
public class RandomBias extends Object implements Serializable
A class that wraps an RNG and allows different String keys to be associated with biases toward low or high results
when a method is called that gets a number from the wrapped RNG. With this, you could make a category of "blessed" or
"cursed" biases that, instead of using a uniform distribution that produces all numbers approximately with equal
likelihood (with doubles between 0.0 and 1.0 averaging at 0.5), have different averages, like 0.7 for blessed or 0.3
for cursed, when generating between 0.0 and 1.0. You could also use this to favor or disfavor the player for "easy
mode" or "hard mode" categories of play.
The API allows you to associate an alternative average with a kind as a String, like "blessed to-hit" or "hard mode enemy damage", if you expect to use that number more than once and might want to tweak any averages by changing one number at a later point. You can also give an average as a double in place of a kind as a String, which avoids a HashMap lookup and lets you give flexibly-adjusted numbers, but does need more effort to change many values throughout a codebase if averages aren't all generated by a formula. You can also set the distribution in the constructor or by changing the public distribution field; you can use constants in this class, TRIANGULAR, EXPONENTIAL, TRUNCATED, SOFT_TRIANGULAR, and EXP_TRI (the average of EXPONENTIAL and TRIANGULAR), for different choices, with the default being EXP_TRI. Each one of these has different behavior regarding a preference toward extreme values; TRIANGULAR almost never produces very high or very low values, EXPONENTIAL frequently produces the highest or lowest values for high or low expected averages, respectively, TRUNCATED will simply never generate values that are too far from the average (otherwise it's uniform), SOFT_TRIANGULAR will produce a rounded version of TRIANGULAR's distribution with less of an angular peak and more frequent high and low values, and EXP_TRI will have something like a curve shape that may "collide" slightly with the upper bound if the average is high enough.
Credit for the technique used for the exponential modification to distributions goes to user pjs on StackOverflow, http://stackoverflow.com/a/17796997 . Credit should also be given to user vydd of the LispGames community, who made a visualization of the distribution changing as the expected average changed (at the time, the typical behavior of an exponential distribution looked like a bug, and the visualization showed that it was correct behavior). Derrick Creamer noticed how strange the exponential distribution would seem to most players, and that led to adding the simple triangular distribution. Created by Tommy Ettinger on 3/20/2016.
The API allows you to associate an alternative average with a kind as a String, like "blessed to-hit" or "hard mode enemy damage", if you expect to use that number more than once and might want to tweak any averages by changing one number at a later point. You can also give an average as a double in place of a kind as a String, which avoids a HashMap lookup and lets you give flexibly-adjusted numbers, but does need more effort to change many values throughout a codebase if averages aren't all generated by a formula. You can also set the distribution in the constructor or by changing the public distribution field; you can use constants in this class, TRIANGULAR, EXPONENTIAL, TRUNCATED, SOFT_TRIANGULAR, and EXP_TRI (the average of EXPONENTIAL and TRIANGULAR), for different choices, with the default being EXP_TRI. Each one of these has different behavior regarding a preference toward extreme values; TRIANGULAR almost never produces very high or very low values, EXPONENTIAL frequently produces the highest or lowest values for high or low expected averages, respectively, TRUNCATED will simply never generate values that are too far from the average (otherwise it's uniform), SOFT_TRIANGULAR will produce a rounded version of TRIANGULAR's distribution with less of an angular peak and more frequent high and low values, and EXP_TRI will have something like a curve shape that may "collide" slightly with the upper bound if the average is high enough.
Credit for the technique used for the exponential modification to distributions goes to user pjs on StackOverflow, http://stackoverflow.com/a/17796997 . Credit should also be given to user vydd of the LispGames community, who made a visualization of the distribution changing as the expected average changed (at the time, the typical behavior of an exponential distribution looked like a bug, and the visualization showed that it was correct behavior). Derrick Creamer noticed how strange the exponential distribution would seem to most players, and that led to adding the simple triangular distribution. Created by Tommy Ettinger on 3/20/2016.
- See Also:
- Serialized Form
-
Field Summary
Fields Modifier and Type Field Description static int
BATHTUB_TRUNCATED
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0.int
distribution
static int
EXP_TRI
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0.static int
EXPONENTIAL
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0.IRNG
rng
static int
SOFT_TRIANGULAR
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0.static int
TRIANGULAR
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0.static int
TRUNCATED
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. -
Constructor Summary
Constructors Constructor Description RandomBias()
RandomBias(IRNG rng)
RandomBias(IRNG rng, Map<String,Double> mapping)
RandomBias(IRNG rng, Map<String,Double> mapping, int distribution)
-
Method Summary
Modifier and Type Method Description double
biasedBetween(double expectedAverage, double min, double max)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.int
biasedBetween(double expectedAverage, int min, int max)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.long
biasedBetween(double expectedAverage, long min, long max)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.double
biasedBetween(String kind, double min, double max)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.int
biasedBetween(String kind, int min, int max)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.long
biasedBetween(String kind, long min, long max)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.boolean
biasedBoolean(double expectedAverage)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.boolean
biasedBoolean(String kind)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.double
biasedDouble(double expectedAverage)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.double
biasedDouble(double expectedAverage, double bound)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.double
biasedDouble(String kind)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.double
biasedDouble(String kind, double bound)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.float
biasedFloat(double expectedAverage)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.float
biasedFloat(double expectedAverage, float bound)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.float
biasedFloat(String kind)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.float
biasedFloat(String kind, float bound)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.int
biasedInt(double expectedAverage)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.int
biasedInt(double expectedAverage, int bound)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.int
biasedInt(String kind)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.int
biasedInt(String kind, int bound)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.long
biasedLong(double expectedAverage)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.long
biasedLong(double expectedAverage, long bound)
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average.long
biasedLong(String kind)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.long
biasedLong(String kind, long bound)
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG.RandomBias
putBias(String kind, double expectedAverage)
Adds a kind of bias that can be used to change the average of random numbers generated when specified with that kind.RandomBias
putBiases(Map<String,Double> mapping)
Adds a number of kinds of bias that can be used to change the average of random numbers generated when specified with one of those kinds.String
toString()
-
Field Details
-
rng
-
distribution
-
TRIANGULAR
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
EXPONENTIAL
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
TRUNCATED
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
SOFT_TRIANGULAR
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
EXP_TRI
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
BATHTUB_TRUNCATED
A constant for a distribution that linearly increases in probability from a 0.0 chance of 0.0. to a 0.3333... chance of getting the expected average, then linearly decreases until it reaches a 0.0 chance of 1.0. Doesn't really support expected averages below 1/3 or above 2/3, due to how the triangular distribution works.- See Also:
- Constant Field Values
-
-
Constructor Details
-
RandomBias
public RandomBias() -
RandomBias
-
RandomBias
-
RandomBias
-
-
Method Details
-
putBias
Adds a kind of bias that can be used to change the average of random numbers generated when specified with that kind.- Parameters:
kind
- a String that will be used as a key in a Map; can be given later on to bias results using this keyexpectedAverage
- above 0.0 and below 1.0, with 0.5 as the normal average but other values are more useful.- Returns:
- this for chaining
-
putBiases
Adds a number of kinds of bias that can be used to change the average of random numbers generated when specified with one of those kinds.- Parameters:
mapping
- should have String keys that can be used later, and double values greater than 0 but less than 1.- Returns:
- this for chaining
-
biasedLong
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a positive long in either case, but not all long values are possible if this is biased, in part because of generating a double, which has less precision than long, and in part because some numbers need to be more common than others. If the kind is not in the map, this generates a positive long, using 63 bits instead of RNG's normal 64 bits since it never generates negative numbers.- Parameters:
kind
- the kind of bias to look up- Returns:
- a random 63-bit positive long, potentially influenced by the bias associated with kind, if present
-
biasedLong
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a long between 0 and bound (exclusive on bound), where bound can be negative (and this behavior is allowed even though RNG normally returns 0 for all negative bounds). If the kind is not in the map, this generates a long between 0 and bound (exclusive on bound), even if bound is negative.- Parameters:
kind
- the kind of bias to look upbound
- the outer bound, exclusive; can be negative- Returns:
- a random long between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedDouble
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a double between 0.0 and 1.0 (exclusive on 1.0). If the kind is not in the map, this generates a double using RNG and no further changes.- Parameters:
kind
- the kind of bias to look up- Returns:
- a random double between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedDouble
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a double between 0 and bound (exclusive on bound), where bound can be negative (the same as RNG). If the kind is not in the map, this doesn't adjust the average, and acts exactly like RNG.- Parameters:
kind
- the kind of bias to look upbound
- the outer bound, exclusive; can be negative- Returns:
- a random double between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedInt
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a positive int in either case. If the kind is not in the map, this generates a positive int, using 31 bits instead of RNG's normal 32 bits since it never generates negative numbers.- Parameters:
kind
- the kind of bias to look up- Returns:
- a random 31-bit positive int, potentially influenced by the bias associated with kind, if present
-
biasedInt
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be an int between 0 and bound (exclusive on bound), where bound can be negative (and this behavior is allowed even though RNG normally returns 0 for all negative bounds). If the kind is not in the map, this generates an int between 0 and bound (exclusive on bound), even if bound is negative.- Parameters:
kind
- the kind of bias to look upbound
- the outer bound, exclusive; can be negative- Returns:
- a random int between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedFloat
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a float between 0.0 and 1.0 (exclusive on 1.0). If the kind is not in the map, this generates a float using RNG and no further changes.- Parameters:
kind
- the kind of bias to look up- Returns:
- a random float between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedFloat
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a float between 0 and bound (exclusive on bound), where bound can be negative. If the kind is not in the map, this doesn't adjust the average.- Parameters:
kind
- the kind of bias to look upbound
- the outer bound, exclusive; can be negative- Returns:
- a random double between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedBoolean
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned boolean will be true if the random number (between 0.0 and 1.0, exclusive upper) is greater than or equal to 0.5. If the kind is not in the map, this generates a boolean using RNG and no further changes.- Parameters:
kind
- the kind of bias to look up- Returns:
- a random float between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be an int between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative. If the kind is not in the map, this doesn't adjust the average.- Parameters:
kind
- the kind of bias to look upmin
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random int between min and max, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a long between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative. If the kind is not in the map, this doesn't adjust the average.- Parameters:
kind
- the kind of bias to look upmin
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random long between min and max, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Looks up the given kind in the Map of biases this stores, and generates a random number using this object's RNG. If the kind is in the Map, this adjusts the generated number so it matches a distribution that would have the expected average the kind was associated with. The returned number will be a double between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative. If the kind is not in the map, this doesn't adjust the average.- Parameters:
kind
- the kind of bias to look upmin
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random double between min and max, potentially influenced by the bias associated with kind, if present
-
biasedLong
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a positive long in either case, but not all long values are possible if this is biased, in part because of generating a double, which has less precision than long, and in part because some numbers need to be more common than others.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0- Returns:
- a random 63-bit positive long, potentially influenced by the bias associated with kind, if present
-
biasedLong
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a long between 0 and bound (exclusive on bound), where bound can be negative (and this behavior is allowed even though RNG normally returns 0 for all negative bounds).- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0bound
- the outer bound, exclusive; can be negative- Returns:
- a random long between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedDouble
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a double between 0.0 and 1.0 (exclusive on 1.0).- Parameters:
expectedAverage
- the desired average- Returns:
- a random double between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedDouble
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a double between 0 and bound (exclusive on bound), where bound can be negative (the same as RNG).- Parameters:
expectedAverage
- the desired averagebound
- the outer bound, exclusive; can be negative- Returns:
- a random double between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedInt
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a positive int from 0 to (2 to the 31)-1 in either case.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0- Returns:
- a random 31-bit positive int, potentially influenced by the bias associated with kind, if present
-
biasedInt
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be an int between 0 and bound (exclusive on bound), where bound can be negative (and this behavior is allowed even though RNG normally returns 0 for all negative bounds).- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0bound
- the outer bound, exclusive; can be negative- Returns:
- a random int between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedFloat
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a float between 0.0f and 1.0f (exclusive on 1.0f).- Parameters:
expectedAverage
- the desired average- Returns:
- a random float between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedFloat
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a float between 0f and bound (exclusive on bound), where bound can be negative.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0bound
- the outer bound, exclusive; can be negative- Returns:
- a random double between 0 and bound, potentially influenced by the bias associated with kind, if present
-
biasedBoolean
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned boolean will be true if the random number (between 0.0 and 1.0, exclusive upper) is greater than or equal to 0.5.- Parameters:
expectedAverage
- the desired probability of a true result, between 0.0 and 1.0- Returns:
- a random float between 0.0 and 1.0, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be an int between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0min
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random int between min and max, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a long between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0min
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random long between min and max, potentially influenced by the bias associated with kind, if present
-
biasedBetween
Generates a random number using this object's RNG and adjusts the generated number so it matches a distribution that would have the given expected average. The returned number will be a double between min and max (exclusive on max), where min and/or max can be negative, and the difference between the two can be either positive or negative.- Parameters:
expectedAverage
- the desired average if the minimum value was 0.0 and the exclusive max was 1.0min
- the inner bound, inclusive; can be negativemax
- the outer bound, exclusive; can be negative- Returns:
- a random double between min and max, potentially influenced by the bias associated with kind, if present
-
toString
-