From eda9a86d8d48758e9982cfffd470c3b38a0a4b0b Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Sat, 21 Nov 2020 23:11:43 -0500 Subject: Make dice generic Convert dice from dealing exclusively with ints, to deal with objects of arbitrary types --- .../main/java/bjc/dicelang/neodice/IDiePool.java | 222 +++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 dice/src/main/java/bjc/dicelang/neodice/IDiePool.java (limited to 'dice/src/main/java/bjc/dicelang/neodice/IDiePool.java') diff --git a/dice/src/main/java/bjc/dicelang/neodice/IDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/IDiePool.java new file mode 100644 index 0000000..b887784 --- /dev/null +++ b/dice/src/main/java/bjc/dicelang/neodice/IDiePool.java @@ -0,0 +1,222 @@ +package bjc.dicelang.neodice; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import bjc.dicelang.neodice.diepool.*; + +/** + * Represents a pool of dice. + * + * @author Ben Culkin + * + */ +@FunctionalInterface +public interface IDiePool { + /** + * Roll each die in the pool, and return the results. + * + * Note that this list is not guaranteed to be the same size every time it + * is rolled, because there are some pool types that could add/remove dice. + * + * @param rng The source for random numbers + * + * @return The result of rolling each die in the pool. + */ + public Stream roll(Random rng); + + /** + * Gets the dice contained in this pool. + * + * Note that the length of this list may not be the same as the length of + * the list returned by roll, because certain pool types may add additional + * dice. + * + * Also note that this list (and the Die instances contained in it) should + * not be modified. That may work for certain pool types, but it isn't + * guaranteed to work, and can lead to unintuitive behavior. For instances, + * certain pool types may return an list where multiple elements of it refer + * to the same Die instance. + * + * The default implementation throws an UnsupportedOperationException. + * + * @return The dice contained in this pool. + * + * @throws UnsupportedOperationException If the composite dice can't be retrieved. + */ + default List> contained() { + throw new UnsupportedOperationException("Can't get composite dice"); + } + + /* + * These die pool operations transform this pool in some way. + */ + + /** + * Returns a version of this die pool which returns its results in sorted + * order. + * + * @param isDescending True to sort in descending order, false to sort in ascending order. + * + * @return The die pool, which returns its results in sorted order. + */ + default IDiePool sorted( + Comparator comparer, + boolean isDescending) { + return new TransformDiePool<>(this, + (pool) -> pool.sorted( + isDescending + ? comparer.reversed() + : comparer)); + } + + /** + * Return a die pool which rolls this one, then filters out any results that + * don't match the provided predicate. + * + * @param matcher The predicate that determines + * + * @return A die pool which contains only entries that pass the predicate. + */ + default IDiePool filtered(Predicate matcher) { + return new TransformDiePool<>(this, + (pool) -> pool.filter(matcher)); + } + + /** + * Return a die pool which rolls this one, then drops a number of the first values. + * + * @param number The number of first values to drop. + * + * @return A die pool which has the first entries dropped. + */ + default IDiePool dropFirst(int number) { + return new TransformDiePool<>(this, + (pool) -> pool.skip(number)); + } + + /** + * Return a die pool which rolls this one, then drops a number of the last values. + * + * @param number The number of last values to drop. + * + * @return A die pool which has the last entries dropped. + */ + default IDiePool dropLast(int number) { + return new TransformDiePool<>(this, (pool) -> { + Deque temp = new ArrayDeque<>(); + + pool.forEachOrdered((die) -> temp.add(die)); + + for (int i = 0; i < number; i++) temp.pollLast(); + + return temp.stream(); + }); + } + + /** + * Return a die pool which rolls this one, then keeps a number of the first values. + * + * @param number The number of first values to keep. + * + * @return A die pool which has the first entries kept. + */ + default IDiePool keepFirst(int number) { + return new TransformDiePool<>(this, + (pool) -> pool.limit(number)); + } + + /** + * Return a die pool which rolls this one, then keeps a number of the last values. + * + * @param number The number of last values to keep. + * + * @return A die pool which has the last entries kept. + */ + default IDiePool keepLast(int number) { + return new TransformDiePool<>(this, (pool) -> { + Deque temp = new ArrayDeque<>(); + + pool.forEachOrdered((die) -> temp.add(die)); + + while (temp.size() > number) temp.pollFirst(); + + return temp.stream(); + }); + } + + /* + * These die-pool operations are formed exclusively through other die pool + * operations. + */ + + /** + * Return a die pool which rolls this one, then drops a number of the lowest values. + * + * @param number The number of lowest values to drop. + * + * @return A die pool which has the lowest entries dropped. + */ + default IDiePool dropLowest(Comparator comparer, int number) { + return this.sorted(comparer, false).dropFirst(number); + } + + /** + * Return a die pool which rolls this one, then drops a number of the lowest values. + * + * @param number The number of lowest values to drop. + * + * @return A die pool which has the lowest entries dropped. + */ + default IDiePool dropHighest(Comparator comparer,int number) { + return this.sorted(comparer, false).dropLast(number); + } + + /** + * Return a die pool which rolls this one, then keeps a number of the lowest values. + * + * @param number The number of lowest values to keep. + * + * @return A die pool which has the lowest entries kept. + */ + default IDiePool keepLowest(Comparator comparer,int number) { + return this.sorted(comparer, false).keepFirst(number); + } + + /** + * Return a die pool which rolls this one, then keeps a number of the highest values. + * + * @param number The number of highest values to keep. + * + * @return A die pool which has the highest entries kept. + */ + default IDiePool keepHighest(Comparator comparer,int number) { + return this.sorted(comparer, false).keepLast(number); + } + + /* These are misc. operations that don't form new dice pools. */ + + /** + * Get an iterator which iterates over a single roll of this die pool. + * + * @param rng The source of random numbers. + * + * @return An iterator over a single roll of this die pool. + */ + default Iterator iterator(Random rng) { + return this.roll(rng).iterator(); + } + + /** + * Create a die pool containing the provided dice. + * + * @param dice The dice to put into the pool. + * + * @return A pool which contains the provided dice. + */ + @SafeVarargs + static IDiePool containing(IDie... dice) { + return new FixedDiePool<>(dice); + } +} \ No newline at end of file -- cgit v1.2.3