diff options
| author | Ben Culkin <scorpress@gmail.com> | 2020-11-21 23:11:43 -0500 |
|---|---|---|
| committer | Ben Culkin <scorpress@gmail.com> | 2020-11-21 23:11:43 -0500 |
| commit | eda9a86d8d48758e9982cfffd470c3b38a0a4b0b (patch) | |
| tree | fbe073650de751486725844ed41dfe70986a914d /dice/src/main/java/bjc | |
| parent | b5c2fb1ed923d43412694729b4445a66fa9f47fc (diff) | |
Make dice generic
Convert dice from dealing exclusively with ints, to deal with objects of
arbitrary types
Diffstat (limited to 'dice/src/main/java/bjc')
14 files changed, 254 insertions, 458 deletions
diff --git a/dice/src/main/java/bjc/dicelang/neodice/Die.java b/dice/src/main/java/bjc/dicelang/neodice/IDie.java index 9bcbb0f..274af66 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/Die.java +++ b/dice/src/main/java/bjc/dicelang/neodice/IDie.java @@ -13,7 +13,7 @@ import bjc.dicelang.neodice.diepool.*; * */ @FunctionalInterface -public interface Die { +public interface IDie<SideType> { /** * Rolls this die. * @@ -21,7 +21,7 @@ public interface Die { * * @return The result of rolling the die. */ - public int roll(Random rng); + public SideType roll(Random rng); /** * Returns a die pool which rolls this die the specified number of times. @@ -30,8 +30,11 @@ public interface Die { * * @return A die pool that rolls this die the specified number of times. */ - default DiePool times(int numTimes) { - return new TimesDiePool(this, numTimes); + default IDiePool<SideType> times(int numTimes) { + return new ExpandDiePool<>(this, (die, rng) -> { + return Stream.generate(() -> die.roll(rng)) + .limit(numTimes); + }); }; /** @@ -41,8 +44,11 @@ public interface Die { * * @return A die that rerolls when the given condition is met. */ - default Die reroll(IntPredicate condition) { - return new RerollDie(this, condition, (lst) -> lst.get(lst.size())); + default IDie<SideType> reroll( + Comparator<SideType> comparer, + Predicate<SideType> condition) { + return RerollDie.create(comparer, this, condition, + (list) -> list.get(list.size())); } /** @@ -54,21 +60,29 @@ public interface Die { * * @return A die that rerolls when the given condition is met. */ - default Die reroll(IntPredicate condition, int limit) { - return new RerollDie(this, condition, (lst) -> lst.get(lst.size()), limit); + default IDie<SideType> reroll( + Comparator<SideType> comparer, + Predicate<SideType> condition, + int limit) { + return RerollDie.create(comparer, this, condition, + (list) -> list.get(list.size()), limit); } /** - * Create an iterator which gives rolls of this dice. + * Create an stream which gives rolls of this dice. * * @param rng The source for random numbers. * * @return An iterator which gives rolls of this dice. */ - default Iterator<Integer> iterator(Random rng) { - return IntStream.generate(() -> this.roll(rng)).iterator(); + default Stream<SideType> stream(Random rng) { + return Stream.generate(() -> this.roll(rng)); } - + + default <NewType> IDie<NewType> transform(Function<SideType, NewType> mapper) { + return (rng) -> mapper.apply(this.roll(rng)); + } + /** * Create a simple polyhedral die with a fixed number of sides. * @@ -76,7 +90,7 @@ public interface Die { * * @return A die which returns a result from 1 to sides. */ - static Die polyhedral(int sides) { + static IDie<Integer> polyhedral(int sides) { return new PolyhedralDie(sides); } }
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/DiePool.java b/dice/src/main/java/bjc/dicelang/neodice/IDiePool.java index ac35988..b887784 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/DiePool.java +++ b/dice/src/main/java/bjc/dicelang/neodice/IDiePool.java @@ -2,6 +2,7 @@ package bjc.dicelang.neodice; import java.util.*; import java.util.function.*; +import java.util.stream.*; import bjc.dicelang.neodice.diepool.*; @@ -12,30 +13,30 @@ import bjc.dicelang.neodice.diepool.*; * */ @FunctionalInterface -public interface DiePool { +public interface IDiePool<SideType> { /** * Roll each die in the pool, and return the results. * - * Note that this array is not guaranteed to be the same size every time it + * 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 int[] roll(Random rng); + public Stream<SideType> roll(Random rng); /** * Gets the dice contained in this pool. * - * Note that the length of this array may not be the same as the length of - * the array returned by roll, because certain pool types may add additional + * 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 array (and the Die instances contained in it) should + * 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 array where multiple elements of it refer + * certain pool types may return an list where multiple elements of it refer * to the same Die instance. * * The default implementation throws an UnsupportedOperationException. @@ -44,7 +45,7 @@ public interface DiePool { * * @throws UnsupportedOperationException If the composite dice can't be retrieved. */ - default Die[] contained() { + default List<IDie<SideType>> contained() { throw new UnsupportedOperationException("Can't get composite dice"); } @@ -56,16 +57,18 @@ public interface DiePool { * Returns a version of this die pool which returns its results in sorted * order. * - * At the moment, sorting in descending order is somewhat less efficent than - * sorting in ascending order, because Java doesn't provide a built-in - * descending sort for primitive arrays. - * * @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 DiePool sorted(boolean isDescending) { - return new SortedDiePool(this, isDescending); + default IDiePool<SideType> sorted( + Comparator<SideType> comparer, + boolean isDescending) { + return new TransformDiePool<>(this, + (pool) -> pool.sorted( + isDescending + ? comparer.reversed() + : comparer)); } /** @@ -76,8 +79,9 @@ public interface DiePool { * * @return A die pool which contains only entries that pass the predicate. */ - default DiePool filtered(IntPredicate matcher) { - return new FilteredDiePool(this, matcher); + default IDiePool<SideType> filtered(Predicate<SideType> matcher) { + return new TransformDiePool<>(this, + (pool) -> pool.filter(matcher)); } /** @@ -87,8 +91,9 @@ public interface DiePool { * * @return A die pool which has the first entries dropped. */ - default DiePool dropFirst(int number) { - return new DropFirstPool(this, number); + default IDiePool<SideType> dropFirst(int number) { + return new TransformDiePool<>(this, + (pool) -> pool.skip(number)); } /** @@ -98,8 +103,16 @@ public interface DiePool { * * @return A die pool which has the last entries dropped. */ - default DiePool dropLast(int number) { - return new DropLastPool(this, number); + default IDiePool<SideType> dropLast(int number) { + return new TransformDiePool<>(this, (pool) -> { + Deque<SideType> temp = new ArrayDeque<>(); + + pool.forEachOrdered((die) -> temp.add(die)); + + for (int i = 0; i < number; i++) temp.pollLast(); + + return temp.stream(); + }); } /** @@ -109,8 +122,9 @@ public interface DiePool { * * @return A die pool which has the first entries kept. */ - default DiePool keepFirst(int number) { - return new KeepFirstDiePool(this, number); + default IDiePool<SideType> keepFirst(int number) { + return new TransformDiePool<>(this, + (pool) -> pool.limit(number)); } /** @@ -120,8 +134,16 @@ public interface DiePool { * * @return A die pool which has the last entries kept. */ - default DiePool keepLast(int number) { - return new KeepLastDiePool(this, number); + default IDiePool<SideType> keepLast(int number) { + return new TransformDiePool<>(this, (pool) -> { + Deque<SideType> temp = new ArrayDeque<>(); + + pool.forEachOrdered((die) -> temp.add(die)); + + while (temp.size() > number) temp.pollFirst(); + + return temp.stream(); + }); } /* @@ -136,8 +158,8 @@ public interface DiePool { * * @return A die pool which has the lowest entries dropped. */ - default DiePool dropLowest(int number) { - return this.sorted(false).dropFirst(number); + default IDiePool<SideType> dropLowest(Comparator<SideType> comparer, int number) { + return this.sorted(comparer, false).dropFirst(number); } /** @@ -147,8 +169,8 @@ public interface DiePool { * * @return A die pool which has the lowest entries dropped. */ - default DiePool dropHighest(int number) { - return this.sorted(false).dropLast(number); + default IDiePool<SideType> dropHighest(Comparator<SideType> comparer,int number) { + return this.sorted(comparer, false).dropLast(number); } /** @@ -158,8 +180,8 @@ public interface DiePool { * * @return A die pool which has the lowest entries kept. */ - default DiePool keepLowest(int number) { - return this.sorted(false).keepFirst(number); + default IDiePool<SideType> keepLowest(Comparator<SideType> comparer,int number) { + return this.sorted(comparer, false).keepFirst(number); } /** @@ -169,8 +191,8 @@ public interface DiePool { * * @return A die pool which has the highest entries kept. */ - default DiePool keepHighest(int number) { - return this.sorted(false).keepLast(number); + default IDiePool<SideType> keepHighest(Comparator<SideType> comparer,int number) { + return this.sorted(comparer, false).keepLast(number); } /* These are misc. operations that don't form new dice pools. */ @@ -182,8 +204,8 @@ public interface DiePool { * * @return An iterator over a single roll of this die pool. */ - default Iterator<Integer> iterator(Random rng) { - return Arrays.stream(this.roll(rng)).iterator(); + default Iterator<SideType> iterator(Random rng) { + return this.roll(rng).iterator(); } /** @@ -193,7 +215,8 @@ public interface DiePool { * * @return A pool which contains the provided dice. */ - static DiePool containing(Die... dice) { - return new FixedDiePool(dice); + @SafeVarargs + static <Side> IDiePool<Side> containing(IDie<Side>... dice) { + return new FixedDiePool<>(dice); } }
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/die/PolyhedralDie.java b/dice/src/main/java/bjc/dicelang/neodice/die/PolyhedralDie.java index c1bb2ac..2909724 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/die/PolyhedralDie.java +++ b/dice/src/main/java/bjc/dicelang/neodice/die/PolyhedralDie.java @@ -4,7 +4,7 @@ import java.util.*; import bjc.dicelang.neodice.*; -public class PolyhedralDie implements Die { +public class PolyhedralDie implements IDie<Integer> { private final int sides; public PolyhedralDie(int sides) { @@ -12,7 +12,7 @@ public class PolyhedralDie implements Die { } @Override - public int roll(Random rng) { + public Integer roll(Random rng) { // Dice are one-based, not zero-based. return rng.nextInt(sides) + 1; } diff --git a/dice/src/main/java/bjc/dicelang/neodice/die/RerollDie.java b/dice/src/main/java/bjc/dicelang/neodice/die/RerollDie.java index 3cd369f..f8cb0fa 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/die/RerollDie.java +++ b/dice/src/main/java/bjc/dicelang/neodice/die/RerollDie.java @@ -6,39 +6,45 @@ import java.util.function.*; import bjc.dicelang.neodice.*; import bjc.esodata.*; -public class RerollDie implements Die { - private final Die contained; +public class RerollDie<SideType> implements IDie<SideType> { + private final IDie<SideType> contained; - private final IntPredicate condition; - private final Function<MinMaxList<Integer>, Integer> chooser; + private final Predicate<SideType> condition; + private final Function<MinMaxList<SideType>, SideType> chooser; - private int limit = Integer.MAX_VALUE; + private final Comparator<SideType> comparer; + private int limit = Integer.MAX_VALUE; - public RerollDie(Die contained, IntPredicate condition, - Function<MinMaxList<Integer>, Integer> chooser) { + private RerollDie( + Comparator<SideType> comparer, + IDie<SideType> contained, + Predicate<SideType> condition, + Function<MinMaxList<SideType>, SideType> chooser) { + this.comparer = comparer; + this.contained = contained; this.condition = condition; this.chooser = chooser; } - public RerollDie(Die contained, IntPredicate condition, - Function<MinMaxList<Integer>, Integer> chooser, int limit) { - this.contained = contained; - - this.condition = condition; - this.chooser = chooser; + private RerollDie( + Comparator<SideType> comparer, + IDie<SideType> contained, + Predicate<SideType> condition, + Function<MinMaxList<SideType>, SideType> chooser, + int limit) { + this(comparer, contained, condition, chooser); this.limit = limit; } @Override - public int roll(Random rng) { - int roll = contained.roll(rng); - - MinMaxList<Integer> newRolls = new MinMaxList<Integer>( - Comparator.naturalOrder(), roll); + public SideType roll(Random rng) { + SideType roll = contained.roll(rng); + + MinMaxList<SideType> newRolls = new MinMaxList<>(comparer, roll); int rerollCount = 0; while (condition.test(roll) && rerollCount < limit) { @@ -51,5 +57,36 @@ public class RerollDie implements Die { return chooser.apply(newRolls); } - // No toString, because IntPredicate can't be converted to a string + public static <Side extends Comparable<Side>> IDie<Side> create( + IDie<Side> contained, + Predicate<Side> condition, + Function<MinMaxList<Side>, Side> chooser) { + return new RerollDie<>(Comparator.naturalOrder(), contained, condition, chooser); + } + + public static <Side extends Comparable<Side>> IDie<Side> create( + IDie<Side> contained, + Predicate<Side> condition, + Function<MinMaxList<Side>, Side> chooser, + int limit) { + return new RerollDie<>(Comparator.naturalOrder(), contained, condition, chooser, limit); + } + + + public static <Side> IDie<Side> create( + Comparator<Side> comparer, + IDie<Side> contained, + Predicate<Side> condition, + Function<MinMaxList<Side>, Side> chooser) { + return new RerollDie<Side>(comparer, contained, condition, chooser); + } + + public static <Side> IDie<Side> create( + Comparator<Side> comparer, + IDie<Side> contained, + Predicate<Side> condition, + Function<MinMaxList<Side>, Side> chooser, + int limit) { + return new RerollDie<Side>(comparer, contained, condition, chooser, limit); + } }
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/DropFirstPool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/DropFirstPool.java deleted file mode 100644 index 959678b..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/DropFirstPool.java +++ /dev/null @@ -1,58 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; - -import bjc.dicelang.neodice.*; - -public class DropFirstPool implements DiePool { - private final int number; - private final DiePool pool; - - public DropFirstPool(DiePool pool, int number) { - this.pool = pool; - this.number = number; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - if (number >= rolls.length) { - return new int[0]; - } else { - int[] newRolls = new int[rolls.length - number]; - - for (int index = number - 1; index < rolls.length; index++) { - newRolls[index - number] = rolls[index]; - } - - return newRolls; - } - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - @Override - public String toString() { - return String.format("%sdF%d", pool, number); - } - - @Override - public int hashCode() { - return Objects.hash(number, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - DropFirstPool other = (DropFirstPool) obj; - - return number == other.number && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/DropLastPool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/DropLastPool.java deleted file mode 100644 index 9503e8f..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/DropLastPool.java +++ /dev/null @@ -1,58 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; - -import bjc.dicelang.neodice.*; - -public class DropLastPool implements DiePool { - private final int number; - private final DiePool pool; - - public DropLastPool(DiePool pool, int number) { - this.pool = pool; - this.number = number; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - if (number >= rolls.length) { - return new int[0]; - } else { - int[] newRolls = new int[rolls.length - number]; - - for (int index = 0; index < rolls.length - number; index++) { - newRolls[index] = rolls[index]; - } - - return newRolls; - } - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - @Override - public String toString() { - return String.format("%sdL%d", pool, number); - } - - @Override - public int hashCode() { - return Objects.hash(number, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - DropLastPool other = (DropLastPool) obj; - - return number == other.number && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/ExpandDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/ExpandDiePool.java new file mode 100644 index 0000000..7c58e72 --- /dev/null +++ b/dice/src/main/java/bjc/dicelang/neodice/diepool/ExpandDiePool.java @@ -0,0 +1,25 @@ +package bjc.dicelang.neodice.diepool; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import bjc.dicelang.neodice.*; + +public class ExpandDiePool<SideType> implements IDiePool<SideType> { + private final IDie<SideType> contained; + + private final BiFunction<IDie<SideType>, Random, Stream<SideType>> expander; + + public ExpandDiePool(IDie<SideType> contained, + BiFunction<IDie<SideType>, Random, Stream<SideType>> expander) { + this.contained = contained; + this.expander = expander; + } + + + @Override + public Stream<SideType> roll(Random rng) { + return expander.apply(contained, rng); + } +} diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/FilteredDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/FilteredDiePool.java deleted file mode 100644 index 34d274f..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/FilteredDiePool.java +++ /dev/null @@ -1,47 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; -import java.util.function.*; - -import bjc.dicelang.neodice.*; - -public class FilteredDiePool implements DiePool { - private final DiePool pool; - private final IntPredicate filter; - - public FilteredDiePool(DiePool pool, IntPredicate filter) { - this.pool = pool; - this.filter = filter; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - return Arrays.stream(rolls).filter(filter).toArray(); - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - // No toString, since there isn't any sensible to output the filter - - @Override - public int hashCode() { - return Objects.hash(filter, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - FilteredDiePool other = (FilteredDiePool) obj; - - return Objects.equals(filter, other.filter) - && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/FixedDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/FixedDiePool.java index c60b88a..a536f62 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/FixedDiePool.java +++ b/dice/src/main/java/bjc/dicelang/neodice/diepool/FixedDiePool.java @@ -1,55 +1,46 @@ package bjc.dicelang.neodice.diepool; import java.util.*; +import java.util.stream.*; import bjc.dicelang.neodice.*; -public class FixedDiePool implements DiePool { - private final Die[] dice; +public class FixedDiePool<SideType> implements IDiePool<SideType> { + private final List<IDie<SideType>> dice; - public FixedDiePool(Die[] dice) { + public FixedDiePool(List<IDie<SideType>> dice) { this.dice = dice; } + + @SafeVarargs + public FixedDiePool(IDie<SideType>...dice) { + this.dice = new ArrayList<>(dice.length); + for (IDie<SideType> die : dice) { + this.dice.add(die); + } + } @Override - public int[] roll(Random rng) { - int[] results = new int[dice.length]; - - for (int index = 0; index < dice.length; index++) { - results[index] = dice[index].roll(rng); - } - - return results; + public Stream<SideType> roll(Random rng) { + return dice.stream().map((die) -> die.roll(rng)); } @Override - public Die[] contained() { + public List<IDie<SideType>> contained() { return dice; } @Override public String toString() { - StringBuilder builder = new StringBuilder(); - - for (int i = 0; i < dice.length; i++) { - Die die = dice[i]; - - builder.append(die); - - // Don't add an extra trailing comma - if (i < dice.length - 1) builder.append(", "); - } - - return builder.toString(); + return dice.stream() + .map(IDie<SideType>::toString) + .collect(Collectors.joining(", ")); } @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Arrays.hashCode(dice); - return result; + return Objects.hash(dice); } @Override @@ -57,9 +48,9 @@ public class FixedDiePool implements DiePool { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; + + FixedDiePool<?> other = (FixedDiePool<?>) obj; - FixedDiePool other = (FixedDiePool) obj; - - return Arrays.equals(dice, other.dice); + return Objects.equals(dice, other.dice); } }
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepFirstDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepFirstDiePool.java deleted file mode 100644 index d31f104..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepFirstDiePool.java +++ /dev/null @@ -1,58 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; - -import bjc.dicelang.neodice.*; - -public class KeepFirstDiePool implements DiePool { - private final int number; - private final DiePool pool; - - public KeepFirstDiePool(DiePool pool, int number) { - this.pool = pool; - this.number = number; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - if (rolls.length >= number) { - return rolls; - } else { - int[] newRolls = new int[number]; - - for (int index = 0; index < number; index++) { - newRolls[index] = rolls[index]; - } - - return newRolls; - } - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - @Override - public String toString() { - return String.format("%skF%d", pool, number); - } - - @Override - public int hashCode() { - return Objects.hash(number, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - KeepFirstDiePool other = (KeepFirstDiePool) obj; - - return number == other.number && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepLastDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepLastDiePool.java deleted file mode 100644 index 1e2d1ae..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/KeepLastDiePool.java +++ /dev/null @@ -1,58 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; - -import bjc.dicelang.neodice.*; - -public class KeepLastDiePool implements DiePool { - private final int number; - private final DiePool pool; - - public KeepLastDiePool(DiePool pool, int number) { - this.pool = pool; - this.number = number; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - if (rolls.length >= number) { - return rolls; - } else { - int[] newRolls = new int[number]; - - for (int index = number; index > index; index--) { - newRolls[index] = rolls[rolls.length - index]; - } - - return newRolls; - } - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - @Override - public String toString() { - return String.format("%skL%d", pool, number); - } - - @Override - public int hashCode() { - return Objects.hash(number, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - KeepLastDiePool other = (KeepLastDiePool) obj; - - return number == other.number && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/SortedDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/SortedDiePool.java deleted file mode 100644 index 79599c1..0000000 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/SortedDiePool.java +++ /dev/null @@ -1,63 +0,0 @@ -package bjc.dicelang.neodice.diepool; - -import java.util.*; - -import bjc.dicelang.neodice.*; - -public class SortedDiePool implements DiePool { - private final boolean isDescending; - private final DiePool pool; - - public SortedDiePool(DiePool pool, boolean isDescending) { - this.pool = pool; - this.isDescending = isDescending; - } - - @Override - public int[] roll(Random rng) { - int[] rolls = pool.roll(rng); - - Arrays.sort(rolls); - - if (isDescending) { - int[] newRolls = new int[rolls.length]; - - int newIndex = newRolls.length; - for (int index = 0; index < rolls.length; index++) { - newRolls[newIndex--] = rolls[index]; - } - - return newRolls; - } else { - return rolls; - } - } - - @Override - public Die[] contained() { - return pool.contained(); - } - - @Override - public String toString() { - return String.format("%s (sorted %s)", pool, - isDescending ? " descending" : "ascending"); - } - - @Override - public int hashCode() { - return Objects.hash(isDescending, pool); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; - - SortedDiePool other = (SortedDiePool) obj; - - return isDescending == other.isDescending - && Objects.equals(pool, other.pool); - } -}
\ No newline at end of file diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/TimesDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/TimesDiePool.java index 1b34247..56fe0e5 100644 --- a/dice/src/main/java/bjc/dicelang/neodice/diepool/TimesDiePool.java +++ b/dice/src/main/java/bjc/dicelang/neodice/diepool/TimesDiePool.java @@ -1,35 +1,31 @@ package bjc.dicelang.neodice.diepool; import java.util.*; +import java.util.stream.*; import bjc.dicelang.neodice.*; -public class TimesDiePool implements DiePool { - private final Die contained; +public class TimesDiePool<SideType> implements IDiePool<SideType> { + private final IDie<SideType> contained; private final int numDice; - public TimesDiePool(Die contained, int numDice) { + public TimesDiePool(IDie<SideType> contained, int numDice) { this.contained = contained; this.numDice = numDice; } @Override - public int[] roll(Random rng) { - int[] results = new int[numDice]; - - for (int index = 0; index < numDice; index++) { - results[index] = contained.roll(rng); - } - - return results; + public Stream<SideType> roll(Random rng) { + return Stream.generate(() -> contained.roll(rng)) + .limit(numDice); } @Override - public Die[] contained() { - Die[] results = new Die[numDice]; + public List<IDie<SideType>> contained() { + List<IDie<SideType>> results = new ArrayList<>(numDice); for (int index = 0; index < numDice; index++) { - results[index] = contained; + results.add(contained); } return results; @@ -51,7 +47,7 @@ public class TimesDiePool implements DiePool { if (obj == null) return false; if (getClass() != obj.getClass()) return false; - TimesDiePool other = (TimesDiePool) obj; + TimesDiePool<?> other = (TimesDiePool<?>) obj; return Objects.equals(contained, other.contained) && numDice == other.numDice; } diff --git a/dice/src/main/java/bjc/dicelang/neodice/diepool/TransformDiePool.java b/dice/src/main/java/bjc/dicelang/neodice/diepool/TransformDiePool.java new file mode 100644 index 0000000..f590e91 --- /dev/null +++ b/dice/src/main/java/bjc/dicelang/neodice/diepool/TransformDiePool.java @@ -0,0 +1,52 @@ +package bjc.dicelang.neodice.diepool; + +import java.util.*; +import java.util.function.*; +import java.util.stream.*; + +import bjc.dicelang.neodice.*; + +public class TransformDiePool<SideType> implements IDiePool<SideType> { + private final IDiePool<SideType> contained; + + private UnaryOperator<Stream<SideType>> transform; + + public TransformDiePool(IDiePool<SideType> contained, + UnaryOperator<Stream<SideType>> transform) { + super(); + this.contained = contained; + this.transform = transform; + } + + @Override + public Stream<SideType> roll(Random rng) { + return transform.apply(contained.roll(rng)); + } + + @Override + public List<IDie<SideType>> contained() { + return contained.contained(); + } + + @Override + public int hashCode() { + return Objects.hash(contained, transform); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + TransformDiePool<?> other = (TransformDiePool<?>) obj; + + return Objects.equals(contained, other.contained) + && Objects.equals(transform, other.transform); + } + + @Override + public String toString() { + return contained.toString() + "(transformed)"; + } +} |
