summaryrefslogtreecommitdiff
path: root/dice/src/main/java
diff options
context:
space:
mode:
authorBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-02 17:32:24 -0300
committerBenjamin J. Culkin <bjculkin@mix.wvu.edu>2018-06-02 17:32:24 -0300
commit775394cf6b4a3c6a7e7345affeb45bb34f6e4517 (patch)
treea193472620f796b3701fa979cba84d4361eef0c0 /dice/src/main/java
parent09f161528619f9396aa07c784c15bc1d33f5c047 (diff)
Finish die rewrite
This adds all of the remaining missing die modifiers, as well as a few base die types that were missing.
Diffstat (limited to 'dice/src/main/java')
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/CompositeDie.java78
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/CompoundDieMod.java80
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/ComputedDie.java75
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/ConcatDieMod.java (renamed from dice/src/main/java/bjc/dicelang/dicev2/SumDieMod.java)18
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/CountDieMod.java52
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/DieMods.java151
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/Dies.java39
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/ExplodingDieMod.java72
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/FilterDieMod.java48
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/MapDieMod.java39
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/PoolDiceMod.java42
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/ReduceDieMod.java53
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/ScalarDie.java8
-rw-r--r--dice/src/main/java/bjc/dicelang/dicev2/SortDieMod.java53
14 files changed, 786 insertions, 22 deletions
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/CompositeDie.java b/dice/src/main/java/bjc/dicelang/dicev2/CompositeDie.java
new file mode 100644
index 0000000..e9bb585
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/CompositeDie.java
@@ -0,0 +1,78 @@
+package bjc.dicelang.dicev2;
+
+import java.util.Random;
+
+public class CompositeDie extends Die {
+ public final Die numDice;
+ public final Die numSides;
+
+ public final boolean rerollSides;
+
+ public CompositeDie(Die numDice, Die numSides) {
+ this(numDice, numSides, false);
+ }
+
+ public CompositeDie(Die numDice, Die numSides, boolean rerollSides) {
+ super();
+
+ this.numDice = numDice;
+ this.numSides = numSides;
+
+ this.rerollSides = rerollSides;
+ }
+
+ public CompositeDie(Random rnd, Die numDice, Die numSides) {
+ this(rnd, numDice, numSides, false);
+ }
+
+ public CompositeDie(Random rnd, Die numDice, Die numSides, boolean rerollSides) {
+ super(rnd);
+
+ this.numDice = numDice;
+ this.numSides = numSides;
+
+ this.rerollSides = rerollSides;
+ }
+
+ public long[] roll() {
+ int target = (int)numDice.rollSingle();
+ int sides = (int)numSides.rollSingle();
+
+ long[] res = new long[target];
+
+ for(int i = 0; i < target; i++) {
+ res[i] = rng.nextInt(sides) + 1;
+
+ if(rerollSides) sides = (int)numSides.rollSingle();
+ }
+
+ return res;
+ }
+
+ public long rollSingle() {
+ return rng.nextInt((int)numSides.rollSingle());
+ }
+
+ public boolean canOptimize() {
+ if(numSides.canOptimize()) {
+ if(numSides.optimize() <= 1) {
+ return true;
+ }
+ }
+
+ if(numDice.canOptimize()) {
+ if(numDice.optimize() == 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public long optimize() {
+ if(numDice.canOptimize()) return 0;
+ if(numSides.canOptimize() && numSides.optimize() == 0) return 0;
+
+ return numDice.rollSingle();
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/CompoundDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/CompoundDieMod.java
new file mode 100644
index 0000000..6b752f2
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/CompoundDieMod.java
@@ -0,0 +1,80 @@
+package bjc.dicelang.dicev2;
+
+import bjc.utils.funcutils.ListUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.LongPredicate;
+
+public class CompoundDieMod extends Die {
+ public final Die[] dice;
+
+ public final LongPredicate compound;
+
+ public final boolean penetrate;
+
+ public CompoundDieMod(LongPredicate compound, Die... dice) {
+ this(compound, false, dice);
+ }
+
+ public CompoundDieMod(LongPredicate compound, boolean penetrate, Die... dice) {
+ super();
+
+ this.dice = dice;
+
+ this.compound = compound;
+
+ this.penetrate = penetrate;
+ }
+
+ public long[] roll() {
+ List<Long> lst = new ArrayList<>(5);
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ long res = val;
+
+ long newVal = die.rollSingle();
+
+ while(compound.test(newVal)) {
+ if(penetrate) newVal -= 1;
+
+ res += newVal;
+
+ newVal = die.rollSingle();
+ }
+
+ lst.add(res);
+ }
+ }
+
+ return ListUtils.toPrimitive(lst);
+ }
+
+ public long rollSingle() {
+ Die die = dice[0];
+
+ long newVal = die.rollSingle();
+
+ long res = newVal;
+
+ while(compound.test(newVal)) {
+ newVal = die.rollSingle();
+
+ if(penetrate) newVal -= 1;
+
+ res += newVal;
+ }
+
+ return res;
+ }
+
+ /* :UnoptimizableDice */
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Exploding dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/ComputedDie.java b/dice/src/main/java/bjc/dicelang/dicev2/ComputedDie.java
new file mode 100644
index 0000000..89405fe
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/ComputedDie.java
@@ -0,0 +1,75 @@
+package bjc.dicelang.dicev2;
+
+import java.util.Random;
+import java.util.function.IntSupplier;
+
+public class ComputedDie extends Die {
+ public final IntSupplier numDice;
+ public final IntSupplier numSides;
+
+ public final boolean rerollSides;
+
+ public ComputedDie(IntSupplier numDice, IntSupplier numSides) {
+ this(numDice, numSides, false);
+ }
+
+ public ComputedDie(IntSupplier numDice, IntSupplier numSides, boolean rerollSides) {
+ super();
+
+ this.numDice = numDice;
+ this.numSides = numSides;
+
+ this.rerollSides = rerollSides;
+ }
+
+ public ComputedDie(Random rnd, IntSupplier numDice, IntSupplier numSides) {
+ this(rnd, numDice, numSides, false);
+ }
+
+ public ComputedDie(Random rnd, IntSupplier numDice, IntSupplier numSides, boolean rerollSides) {
+ super(rnd);
+
+ this.numDice = numDice;
+ this.numSides = numSides;
+
+ this.rerollSides = rerollSides;
+ }
+
+ public long[] roll() {
+ int target = numDice.getAsInt();
+ int sides = numSides.getAsInt();
+
+ long[] res = new long[target];
+
+ for(int i = 0; i < target; i++) {
+ res[i] = rng.nextInt(sides) + 1;
+
+ if(rerollSides) sides = numSides.getAsInt();
+ }
+
+ return res;
+ }
+
+ public long rollSingle() {
+ return rng.nextInt(numSides.getAsInt());
+ }
+
+ /*
+ * @NOTE
+ *
+ * :UnoptimizableDice
+ *
+ * Here, we assume that we can't optimize because we have no way
+ * of knowing that our suppliers will always return the same
+ * thing. As a matter of fact, they almost always will have that
+ * behavior, otherwise you wouldn't need ComputedDie.
+ */
+
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("ComputedDie cannot be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/SumDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/ConcatDieMod.java
index 54ae3d0..94815d8 100644
--- a/dice/src/main/java/bjc/dicelang/dicev2/SumDieMod.java
+++ b/dice/src/main/java/bjc/dicelang/dicev2/ConcatDieMod.java
@@ -1,9 +1,9 @@
package bjc.dicelang.dicev2;
-public class SumDieMod extends Die {
+public class ConcatDieMod extends Die {
public final Die[] dice;
- public SumDieMod(Die... dice) {
+ public ConcatDieMod(Die... dice) {
super();
this.dice = dice;
@@ -14,15 +14,15 @@ public class SumDieMod extends Die {
}
public long rollSingle() {
- long res = 0;
+ StringBuilder sb = new StringBuilder();
for(Die die : dice) {
for(long val : die.roll()) {
- res += val;
+ sb.append(val);
}
}
- return res;
+ return Long.parseLong(sb.toString());
}
public boolean canOptimize() {
@@ -32,14 +32,14 @@ public class SumDieMod extends Die {
return true;
}
-
+
public long optimize() {
- long res = 0;
+ StringBuilder sb = new StringBuilder();
for(Die die : dice) {
- res += die.optimize();
+ sb.append(die.optimize());
}
- return res;
+ return Long.parseLong(sb.toString());
}
}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/CountDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/CountDieMod.java
new file mode 100644
index 0000000..0b5ec5b
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/CountDieMod.java
@@ -0,0 +1,52 @@
+package bjc.dicelang.dicev2;
+
+import java.util.function.LongPredicate;
+
+public class CountDieMod extends Die {
+ public final Die[] dice;
+
+ public final LongPredicate success;
+
+ public LongPredicate failure;
+
+ public CountDieMod(LongPredicate success, Die... dice) {
+ this(success, null, dice);
+ }
+
+ public CountDieMod(LongPredicate success, LongPredicate failure, Die... dice) {
+ super();
+
+ this.success = success;
+ this.failure = failure;
+
+ this.dice = dice;
+ }
+
+ public long[] roll() {
+ return new long[] { rollSingle() };
+ }
+
+ public long rollSingle() {
+ long count = 0;
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ if(success.test(val)) count += 1;
+
+ if(failure != null && failure.test(val)) count -= 1;
+ }
+ }
+
+ return count;
+ }
+
+ /* :UnoptimizableDice */
+
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Counted dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/DieMods.java b/dice/src/main/java/bjc/dicelang/dicev2/DieMods.java
index afdb604..929cd6e 100644
--- a/dice/src/main/java/bjc/dicelang/dicev2/DieMods.java
+++ b/dice/src/main/java/bjc/dicelang/dicev2/DieMods.java
@@ -1,7 +1,156 @@
package bjc.dicelang.dicev2;
+import bjc.utils.data.GeneratingIterator;
+
+import java.util.Comparator;
+import java.util.Iterator;
+
+import java.util.function.LongPredicate;
+import java.util.function.LongBinaryOperator;
+import java.util.function.LongUnaryOperator;
+
+/*
+ * @NOTE
+ *
+ * :SyntheticMod
+ *
+ * These mods are less efficent than if they were hard-coded, involving
+ * additional function calls and object allocations. If this ends up causing
+ * performance issues, replace these with custom classes.
+ */
+
public class DieMods {
+ public Die reduce(LongBinaryOperator fold, long initial, Die... dice) {
+ return new ReduceDieMod(fold, initial, dice);
+ }
+
+ public Die concat(Die... dice) {
+ return new ConcatDieMod(dice);
+ }
+
+ public Die counted(LongPredicate success, Die... dice) {
+ return new CountDieMod(success, dice);
+ }
+
+ public Die counted(LongPredicate success, LongPredicate failure, Die... dice) {
+ return new CountDieMod(success, failure, dice);
+ }
+
+ public Die explode(LongPredicate explode, Die... dice) {
+ return new ExplodingDieMod(explode, dice);
+ }
+
+ public Die explode(LongPredicate explode, boolean penetrate, Die... dice) {
+ return new ExplodingDieMod(explode, penetrate, dice);
+ }
+
+ public Die compound(LongPredicate compound, Die... dice) {
+ return new CompoundDieMod(compound, dice);
+ }
+
+ public Die compound(LongPredicate compound, boolean penetrate, Die... dice) {
+ return new CompoundDieMod(compound, penetrate, dice);
+ }
+
+ public Die pool(Die... dice) {
+ return new PoolDiceMod(dice);
+ }
+
+ public Die filter(LongPredicate filter, Die... dice) {
+ return new FilterDieMod(filter, dice);
+ }
+
+ public Die sort(Comparator<Long> sorter, Die die) {
+ return new SortDieMod(sorter, die);
+ }
+
+ public Die map(LongUnaryOperator map, Die die) {
+ return new MapDieMod(map, die);
+ }
+
+ /* :SyntheticMod */
public Die sum(Die... dice) {
- return new SumDieMod(dice);
+ return reduce((l, r) -> l + r, 0, dice);
+ }
+
+ /* :SyntheticMod */
+ public Die subtract(Die... dice) {
+ return reduce((l, r) -> l - r, 0, dice);
+ }
+
+ /* :SyntheticMod */
+ public Die multiply(Die... dice) {
+ return reduce((l, r) -> l * r, 1, dice);
+ }
+
+ /* :SyntheticMod */
+ public Die divide(Die... dice) {
+ return reduce((l, r) -> l / r, 1, dice);
+ }
+
+ /* :SyntheticMod */
+ public Die ascending(Die die) {
+ return new SortDieMod(Comparator.naturalOrder(), die);
+ }
+
+ /* :SyntheticMod */
+ public Die descending(Die die) {
+ Comparator<Long> cmp = (Comparator<Long>)Comparator.naturalOrder().reversed();
+
+ return new SortDieMod(cmp, die);
+ }
+
+ /* :SyntheticMod */
+ public Die take(int num, Die die) {
+ GeneratingIterator<Integer> itr = new GeneratingIterator<>(num, (val) -> {
+ return val - 1;
+ }, (val) -> val == 0);
+
+ return filter((val) -> {
+ if(itr.hasNext()) {
+ itr.next();
+ return true;
+ }
+
+ return false;
+ }, die);
+ }
+
+ /* :SyntheticMod */
+ public Die drop(int num, Die die) {
+ GeneratingIterator<Integer> itr = new GeneratingIterator<>(num, (val) -> {
+ return val - 1;
+ }, (val) -> val == 0);
+
+ return filter((val) -> {
+ if(itr.hasNext()) {
+ itr.next();
+ return false;
+ }
+
+ return true;
+ }, die);
+ }
+
+ /* :SyntheticMod */
+ public Die rerollOnce(LongPredicate reroll, Die die) {
+ return map((val) -> {
+ if(reroll.test(val)) return die.rollSingle();
+
+ return val;
+ }, die);
+ }
+
+ /* :SyntheticMod */
+ public Die reroll(LongPredicate reroll, Die die) {
+ return map((val) -> {
+ long nVal = val;
+
+ while(reroll.test(nVal)) {
+ nVal = die.rollSingle();
+ }
+
+ return nVal;
+ }, die);
}
}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/Dies.java b/dice/src/main/java/bjc/dicelang/dicev2/Dies.java
index 98ffbaa..1d29b55 100644
--- a/dice/src/main/java/bjc/dicelang/dicev2/Dies.java
+++ b/dice/src/main/java/bjc/dicelang/dicev2/Dies.java
@@ -1,16 +1,13 @@
package bjc.dicelang.dicev2;
import java.util.Random;
+import java.util.function.IntSupplier;
public class Dies {
- public static Die scalar(int val) {
+ public static Die scalar(long val) {
return new ScalarDie(val);
}
- public static Die scalar(Random rnd, int val) {
- return new ScalarDie(rnd, val);
- }
-
public static Die polyhedral(int dice, int sides) {
return new PolyhedralDie(dice, sides);
}
@@ -26,4 +23,36 @@ public class Dies {
public static Die fudge(Random rnd, int dice) {
return new FudgeDie(rnd, dice);
}
+
+ public static Die composite(Die numDice, Die numSides) {
+ return new CompositeDie(numDice, numSides);
+ }
+
+ public static Die composite(Die numDice, Die numSides, boolean rerollSides) {
+ return new CompositeDie(numDice, numSides, rerollSides);
+ }
+
+ public static Die composite(Random rnd, Die numDice, Die numSides) {
+ return new CompositeDie(rnd, numDice, numSides);
+ }
+
+ public static Die composite(Random rnd, Die numDice, Die numSides, boolean rerollSides) {
+ return new CompositeDie(rnd, numDice, numSides, rerollSides);
+ }
+
+ public static Die computed(IntSupplier numDice, IntSupplier numSides) {
+ return new ComputedDie(numDice, numSides);
+ }
+
+ public static Die computed(IntSupplier numDice, IntSupplier numSides, boolean rerollSides) {
+ return new ComputedDie(numDice, numSides, rerollSides);
+ }
+
+ public static Die computed(Random rnd, IntSupplier numDice, IntSupplier numSides) {
+ return new ComputedDie(rnd, numDice, numSides);
+ }
+
+ public static Die computed(Random rnd, IntSupplier numDice, IntSupplier numSides, boolean rerollSides) {
+ return new ComputedDie(rnd, numDice, numSides, rerollSides);
+ }
}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/ExplodingDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/ExplodingDieMod.java
new file mode 100644
index 0000000..885e02d
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/ExplodingDieMod.java
@@ -0,0 +1,72 @@
+package bjc.dicelang.dicev2;
+
+import bjc.utils.funcutils.ListUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.LongPredicate;
+
+public class ExplodingDieMod extends Die {
+ public final Die[] dice;
+
+ public final LongPredicate explode;
+
+ public final boolean penetrate;
+
+ public ExplodingDieMod(LongPredicate explode, Die... dice) {
+ this(explode, false, dice);
+ }
+
+ public ExplodingDieMod(LongPredicate explode, boolean penetrate, Die... dice) {
+ super();
+
+ this.dice = dice;
+
+ this.explode = explode;
+
+ this.penetrate = penetrate;
+ }
+
+ public long[] roll() {
+ List<Long> lst = new ArrayList<>(dice.length);
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ lst.add(val);
+
+ long newVal = val;
+
+ while(explode.test(newVal)) {
+ newVal = die.rollSingle();
+
+ if(penetrate) newVal -= 1;
+
+ lst.add(newVal);
+ }
+ }
+ }
+
+ return ListUtils.toPrimitive(lst);
+ }
+
+ /*
+ * @NOTE
+ *
+ * :NoSingleRolls
+ *
+ * It makes no sense to roll a 'single' exploding dice, since it
+ * exploding adds another die. Use compounding dice for that case.
+ */
+ public long rollSingle() {
+ throw new UnsupportedOperationException("Exploding dice can't be rolled singly");
+ }
+
+ /* :UnoptimizableDice */
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Exploding dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/FilterDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/FilterDieMod.java
new file mode 100644
index 0000000..47917c4
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/FilterDieMod.java
@@ -0,0 +1,48 @@
+package bjc.dicelang.dicev2;
+
+import bjc.utils.funcutils.ListUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import java.util.function.LongPredicate;
+
+public class FilterDieMod extends Die {
+ public final Die[] dice;
+
+ public final LongPredicate filter;
+
+ public FilterDieMod(LongPredicate filter, Die[] dice) {
+ super();
+
+ this.filter = filter;
+
+ this.dice = dice;
+ }
+
+ public long[] roll() {
+ List<Long> lst = new ArrayList<>(dice.length);
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ if(filter.test(val)) lst.add(val);
+ }
+ }
+
+ return ListUtils.toPrimitive(lst);
+ }
+
+ public long rollSingle() {
+ throw new UnsupportedOperationException("Filtered dice can't be rolled singly");
+ }
+
+ /* :UnoptimizableDice */
+
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Filtered dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/MapDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/MapDieMod.java
new file mode 100644
index 0000000..d6d5dd0
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/MapDieMod.java
@@ -0,0 +1,39 @@
+package bjc.dicelang.dicev2;
+
+import java.util.function.LongUnaryOperator;
+
+public class MapDieMod extends Die {
+ public final Die die;
+
+ public final LongUnaryOperator map;
+
+ public MapDieMod(LongUnaryOperator map, Die die) {
+ super();
+
+ this.die = die;
+ this.map = map;
+ }
+
+ public long[] roll() {
+ long[] res = die.roll();
+
+ for(int i = 0; i < res.length; i++) {
+ res[i] = map.applyAsLong(res[i]);
+ }
+
+ return res;
+ }
+
+ public long rollSingle() {
+ return map.applyAsLong(die.rollSingle());
+ }
+
+ /* :UnoptimizableDice */
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Mapped dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/PoolDiceMod.java b/dice/src/main/java/bjc/dicelang/dicev2/PoolDiceMod.java
new file mode 100644
index 0000000..8733908
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/PoolDiceMod.java
@@ -0,0 +1,42 @@
+package bjc.dicelang.dicev2;
+
+import bjc.utils.funcutils.ListUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PoolDiceMod extends Die {
+ public Die[] dice;
+
+ public PoolDiceMod(Die... dice) {
+ super();
+
+ this.dice = dice;
+ }
+
+ public long[] roll() {
+ List<Long> lst = new ArrayList<>(dice.length);
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ lst.add(val);
+ }
+ }
+
+ return ListUtils.toPrimitive(lst);
+ }
+
+ /* :NoSingleRolls */
+ public long rollSingle() {
+ throw new UnsupportedOperationException("Pooled dice can't be rolled singly");
+ }
+
+ /* :UnoptimizableDice */
+ public boolean canOptimize() {
+ return false;
+ }
+
+ public long optimize() {
+ throw new UnsupportedOperationException("Pooled dice can't be optimized");
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/ReduceDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/ReduceDieMod.java
new file mode 100644
index 0000000..266e270
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/ReduceDieMod.java
@@ -0,0 +1,53 @@
+package bjc.dicelang.dicev2;
+
+import java.util.function.LongBinaryOperator;
+
+public class ReduceDieMod extends Die {
+ public final Die[] dice;
+
+ public final LongBinaryOperator fold;
+ public final long initial;
+
+ public ReduceDieMod(LongBinaryOperator fold, long initial, Die... dice) {
+ super();
+
+ this.dice = dice;
+
+ this.fold = fold;
+ this.initial = initial;
+ }
+
+ public long[] roll() {
+ return new long[] { rollSingle() };
+ }
+
+ public long rollSingle() {
+ long res = initial;
+
+ for(Die die : dice) {
+ for(long val : die.roll()) {
+ res = fold.applyAsLong(res, val);
+ }
+ }
+
+ return res;
+ }
+
+ public boolean canOptimize() {
+ for(Die die : dice) {
+ if(!die.canOptimize()) return false;
+ }
+
+ return true;
+ }
+
+ public long optimize() {
+ long res = 0;
+
+ for(Die die : dice) {
+ res = fold.applyAsLong(res, die.optimize());
+ }
+
+ return res;
+ }
+}
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/ScalarDie.java b/dice/src/main/java/bjc/dicelang/dicev2/ScalarDie.java
index 548b4e9..c206c25 100644
--- a/dice/src/main/java/bjc/dicelang/dicev2/ScalarDie.java
+++ b/dice/src/main/java/bjc/dicelang/dicev2/ScalarDie.java
@@ -11,14 +11,8 @@ public class ScalarDie extends Die {
this.val = val;
}
- public ScalarDie(Random rnd, long val) {
- super(rnd);
-
- this.val = val;
- }
-
public long[] roll() {
- return new long[] { val };
+ return new long[] { rollSingle() };
}
public long rollSingle() {
diff --git a/dice/src/main/java/bjc/dicelang/dicev2/SortDieMod.java b/dice/src/main/java/bjc/dicelang/dicev2/SortDieMod.java
new file mode 100644
index 0000000..50963e1
--- /dev/null
+++ b/dice/src/main/java/bjc/dicelang/dicev2/SortDieMod.java
@@ -0,0 +1,53 @@
+package bjc.dicelang.dicev2;
+
+import bjc.utils.funcutils.ListUtils;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Comparator;
+
+public class SortDieMod extends Die {
+ public final Die die;
+
+ public Comparator<Long> sorter;
+
+ public SortDieMod(Comparator<Long> sorter, Die die) {
+ super();
+
+ this.sorter = sorter;
+
+ this.die = die;
+ }
+
+ public long[] roll() {
+ /*
+ * @NOTE
+ *
+ * This is likely quite a bit slower than using Arrays.sort, but
+ * that only sorts in ascending numeric order. If this ends up
+ * being a performance issue, add another sort that does that.
+ */
+ List<Long> lst = new ArrayList<>();
+
+ for(long val : die.roll()) {
+ lst.add(val);
+ }
+
+ lst.sort(sorter);
+
+ return ListUtils.toPrimitive(lst);
+ }
+
+ public long rollSingle() {
+ return die.rollSingle();
+ }
+
+ public boolean canOptimize() {
+ return die.canOptimize();
+ }
+
+ public long optimize() {
+ return die.optimize();
+ }
+}