All Downloads are FREE. Search and download functionalities are using the official Maven repository.

squidpony.squidmath.CriticalRNG Maven / Gradle / Ivy

Go to download

SquidLib platform-independent logic and utility code. Please refer to https://github.com/SquidPony/SquidLib .

There is a newer version: 3.0.6
Show newest version
package squidpony.squidmath;

import java.util.*;

/**
 * A type of RNG that can generate values larger or smaller than the normal maximum or minimum, based on a modifier.
 * You should not use this as a general-purpose substitute for {@link RNG}; it is meant for cases where there is no hard
 * maximum or minimum for a random value, so it is a poor fit for getting random items from collections or shuffling.
 * It also uses a curved distribution (almost Gaussian, but slightly more shallow), which makes its results to be most
 * often near the center of the range they can fall into. The {@link #luck} field affects the distribution simply, and
 * should generally be between -0.5f and 0.5f except in cases where a character or event routinely defies all odds.
 * There is no value for luck that will prevent this from sometimes producing values outside the requested range, though
 * at luck = 0 it is somewhat rare for the bounds to be significantly exceeded.
 * 
* The name comes from "critical hit," the rare but potentially very significant strike in many role-playing games. *
* Created by Tommy Ettinger on 9/20/2017. */ public class CriticalRNG extends RNG { /** * Positive for higher results, negative for lower results; usually this is small, between -0.5f and 0.5f . */ public float luck = 0f; /** * Makes a CriticalRNG with a luck factor of 0 and a randomly-seeded DiverRNG for its RandomnessSource. */ public CriticalRNG() { super(new DiverRNG()); } /** * Makes a CriticalRNG with a luck factor of 0 and a DiverRNG with the given seed for its RandomnessSource. * @param seed any long */ public CriticalRNG(long seed) { super(new DiverRNG(seed)); } /** * Makes a CriticalRNG with a luck factor of 0 and a DiverRNG with the given seed for its RandomnessSource (this * will hash seedString using {@link CrossHash#hash64(CharSequence)} and use the result to seed the DiverRNG). * @param seedString any String */ public CriticalRNG(CharSequence seedString) { super(new DiverRNG(CrossHash.hash64(seedString))); } /** * Makes a CriticalRNG with a luck factor of 0 and the given RandomnessSource. * @param random a RandomnessSource, such as a {@link LongPeriodRNG} or {@link LightRNG} */ public CriticalRNG(RandomnessSource random) { super(random); } /** * Makes a CriticalRNG with the given luck factor and a randomly-seeded DiverRNG for its RandomnessSource. * @param luck typically a small float, often between -0.5f and 0.5f, that will affect the results this returns */ public CriticalRNG(float luck) { super(new DiverRNG()); this.luck = luck; } /** * Makes a CriticalRNG with the given luck factor and a DiverRNG with the given seed for its RandomnessSource. * @param seed any long * @param luck typically a small float, often between -0.5f and 0.5f, that will affect the results this returns */ public CriticalRNG(long seed, float luck) { super(new DiverRNG(seed)); this.luck = luck; } /** * Makes a CriticalRNG with a luck factor of 0 and a DiverRNG with the given seed for its RandomnessSource (this * will hash seedString using {@link CrossHash#hash64(CharSequence)} and use the result to seed the DiverRNG). * @param seedString any String * @param luck typically a small float, often between -0.5f and 0.5f, that will affect the results this returns */ public CriticalRNG(CharSequence seedString, float luck) { super(new DiverRNG(CrossHash.hash64(seedString))); this.luck = luck; } /** * Makes a CriticalRNG with a luck factor of 0 and the given RandomnessSource. * @param random a RandomnessSource, such as a {@link LongPeriodRNG} or {@link LightRNG} * @param luck typically a small float, often between -0.5f and 0.5f, that will affect the results this returns */ public CriticalRNG(RandomnessSource random, float luck) { super(random); this.luck = luck; } @Override public double nextDouble() { return NumberTools.formCurvedDouble(random.nextLong()) * 0.875 + 0.5 + luck; } @Override public double nextDouble(double max) { return (NumberTools.formCurvedDouble(random.nextLong()) * 0.875 + 0.5 + luck) * max; } @Override public float nextFloat() { return NumberTools.formCurvedFloat(random.nextLong()) * 0.875f + 0.5f + luck; } @Override public boolean nextBoolean() { return NumberTools.formCurvedFloat(random.nextLong()) * 0.875f + 0.5f + luck >= 0f; } private static int intify(final double t) { return t >= 0.0 ? (int) (t + 0.5) : (int) (t - 0.5); } private static long longify(final double t) { return t >= 0.0 ? (long) (t + 0.5) : (long) (t - 0.5); } @Override public long nextLong() { return longify((NumberTools.formCurvedDouble(random.nextLong()) + luck * -2.0) * 0x8000000000000000L); } @Override public long nextLong(long bound) { return longify((NumberTools.formCurvedDouble(random.nextLong()) * 0.875 + 0.5 + luck) * bound); } @Override public int nextInt(int bound) { return intify((NumberTools.formCurvedDouble(random.nextLong()) * 0.875 + 0.5 + luck) * bound); } @Override public int nextIntHasty(int bound) { return intify((NumberTools.formCurvedDouble(random.nextLong()) * 0.875 + 0.5 + luck) * bound); } @Override public int nextInt() { return intify((NumberTools.formCurvedDouble(random.nextLong()) + luck * -2.0) * 0x80000000); } @Override public T getRandomElement(T[] array) { if (array.length < 1) { return null; } return array[super.nextIntHasty(array.length)]; } @Override public T getRandomElement(List list) { if (list.isEmpty()) { return null; } return list.get(super.nextIntHasty(list.size())); } @Override public short getRandomElement(ShortSet set) { if (set.size <= 0) { throw new UnsupportedOperationException("ShortSet cannot be empty when getting a random element"); } int n = super.nextIntHasty(set.size); short s = 0; ShortSet.ShortSetIterator ssi = set.iterator(); while (n-- >= 0 && ssi.hasNext) s = ssi.next(); ssi.reset(); return s; } @Override public T getRandomElement(Collection coll) { int n; if ((n = coll.size()) <= 0) { return null; } n = super.nextIntHasty(n); T t = null; Iterator it = coll.iterator(); while (n-- >= 0 && it.hasNext()) t = it.next(); return t; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy