summaryrefslogtreecommitdiff
path: root/dice/src
diff options
context:
space:
mode:
Diffstat (limited to 'dice/src')
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/DieBoxCLI.java190
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/commands/PolyhedralDieCommand.java6
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/commands/RollCommand.java9
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/statements/DiePoolStatementValue.java6
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/statements/DieStatementValue.java6
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/statements/IntArrayStatementValue.java50
-rw-r--r--dice/src/example/java/bjc/dicelang/neodice/statements/StatementValue.java2
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/IDie.java (renamed from dice/src/main/java/bjc/dicelang/neodice/Die.java)40
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/IDiePool.java (renamed from dice/src/main/java/bjc/dicelang/neodice/DiePool.java)95
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/die/PolyhedralDie.java4
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/die/RerollDie.java75
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/DropFirstPool.java58
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/DropLastPool.java58
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/ExpandDiePool.java25
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/FilteredDiePool.java47
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/FixedDiePool.java53
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/KeepFirstDiePool.java58
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/KeepLastDiePool.java58
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/SortedDiePool.java63
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/TimesDiePool.java26
-rw-r--r--dice/src/main/java/bjc/dicelang/neodice/diepool/TransformDiePool.java52
-rw-r--r--dice/src/test/java/bjc/dicelang/neodice/DiePoolTest.java21
-rw-r--r--dice/src/test/java/bjc/dicelang/neodice/DieTest.java34
23 files changed, 376 insertions, 660 deletions
diff --git a/dice/src/example/java/bjc/dicelang/neodice/DieBoxCLI.java b/dice/src/example/java/bjc/dicelang/neodice/DieBoxCLI.java
index 557fd51..1d6e808 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/DieBoxCLI.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/DieBoxCLI.java
@@ -20,61 +20,55 @@ import bjc.funcdata.*;
*/
public class DieBoxCLI {
private static final Pattern INT_PATTERN = Pattern.compile("(?:\\+|-)?\\d+");
- Scanner input;
+ Scanner input;
public PrintStream output;
-
+
public IMap<String, StatementValue> bindings = new FunctionalMap<>();
public Random rng = new Random();
-
+
static final IMap<String, Command> builtInCommands;
static final IMap<String, Command> builtInliterals;
-
+
final IMap<String, Command> commands;
final IMap<String, Command> literals;
-
+
private int numStatements = 0;
/**
* Whether or not to print out a prompt before asking for input
*/
public boolean doPrompt = true;
-
+
/**
* Whether or not to output the results of each command.
*/
public boolean doOutput = true;
-
+
/**
* Should warning messages be printed?
*/
public boolean doWarn = true;
-
+
static {
// Initialize all of our literal-formers
builtInliterals = new FunctionalMap<>();
-
- builtInliterals.put("void",
- new LiteralCommand(
- VOID_INST,
- "the unique instance of type VOID",
- "Returns a reference to the unique instance of type VOID."));
- builtInliterals.put("true",
- new LiteralCommand(
- TRUE_INST,
- "the unique true value of type BOOLEAN",
- "Returns a reference to the unique true instance of type BOOLEAN"));
- builtInliterals.put("false",
- new LiteralCommand(
- FALSE_INST,
- "the unique false value of type BOOLEAN",
- "Returns a reference to the unique false instance of type BOOLEAN"));
-
+
+ builtInliterals.put("void", new LiteralCommand(VOID_INST,
+ "the unique instance of type VOID",
+ "Returns a reference to the unique instance of type VOID."));
+ builtInliterals.put("true", new LiteralCommand(TRUE_INST,
+ "the unique true value of type BOOLEAN",
+ "Returns a reference to the unique true instance of type BOOLEAN"));
+ builtInliterals.put("false", new LiteralCommand(FALSE_INST,
+ "the unique false value of type BOOLEAN",
+ "Returns a reference to the unique false instance of type BOOLEAN"));
+
builtInliterals.deepFreeze();
-
- // Initialize all of our built-in commands
+
+ // Initialize all of our built-in commands
builtInCommands = new FunctionalMap<>();
-
+
builtInCommands.put("show-bindings", new ShowBindingsCommand());
builtInCommands.put("bind", new BindCommand());
builtInCommands.put("polyhedral-die", new PolyhedralDieCommand());
@@ -82,26 +76,30 @@ public class DieBoxCLI {
builtInCommands.put("help", new HelpCommand());
builtInCommands.deepFreeze();
}
-
+
/**
* Create a new CLI for interacting with dice.
*
- * @param input The place to read input from.
- * @param output The place to read output from.
+ * @param input
+ * The place to read input from.
+ * @param output
+ * The place to read output from.
*/
public DieBoxCLI(Scanner input, PrintStream output) {
- this.input = input;
+ this.input = input;
this.output = output;
-
+
this.commands = builtInCommands.extend();
this.literals = builtInliterals.extend();
}
-
+
/**
* Create a new CLI for interacting with dice.
*
- * @param input The place to read input from.
- * @param output The place to read output from.
+ * @param input
+ * The place to read input from.
+ * @param output
+ * The place to read output from.
*/
public DieBoxCLI(InputStream input, OutputStream output) {
this(new Scanner(input), new PrintStream(output));
@@ -110,45 +108,51 @@ public class DieBoxCLI {
/**
* Main method.
*
- * @param args Currently unused CLI arguments.
+ * @param args
+ * Currently unused CLI arguments.
*/
public static void main(String[] args) {
- Scanner input = new Scanner(System.in);
+ Scanner input = new Scanner(System.in);
PrintStream output = System.out;
-
+
DieBoxCLI box = new DieBoxCLI(input, output);
box.run();
}
- private void run() {
+ private void run() {
if (doPrompt) {
output.println("diebox CLI - enter 'help' for help, 'exit' to exit");
}
-
- if (doPrompt) output.printf("diebox(%d)> ", numStatements);
- while(input.hasNextLine()) {
+
+ if (doPrompt)
+ output.printf("diebox(%d)> ", numStatements);
+ while (input.hasNextLine()) {
String nextLine = input.nextLine().trim();
-
+
numStatements += 1;
-
- if (nextLine.equals("")) continue;
+
+ if (nextLine.equals(""))
+ continue;
// @FIXME Nov 15th, 2020 Ben Culkin :HardcodeExit
// Exit should not be hard-coded like this
- if (nextLine.equals("exit")) break;
-
+ if (nextLine.equals("exit"))
+ break;
+
String[] lineWords = nextLine.split("\\s+");
Iterator<String> wordIter = new ArrayIterator<>(lineWords);
try {
StatementValue val = runStatement(wordIter);
-
- if (doOutput) output.printf("%s%s\n", doPrompt ? "==> " : "", val);
+
+ if (doOutput)
+ output.printf("%s%s\n", doPrompt ? "==> " : "",
+ val);
} catch (DieBoxException dbex) {
output.printf("ERROR (in statement %d): %s\n",
numStatements, dbex.getMessage());
Throwable curEx = dbex.getCause();
while (curEx != null) {
output.printf("...caused by: %s\n", curEx);
-
+
curEx = dbex.getCause();
}
} catch (Exception ex) {
@@ -156,10 +160,11 @@ public class DieBoxCLI {
numStatements, ex.getMessage());
ex.printStackTrace(output);
}
-
- if (doPrompt) output.printf("diebox(%d)> ", numStatements);
+
+ if (doPrompt)
+ output.printf("diebox(%d)> ", numStatements);
}
-
+
input.close();
output.close();
}
@@ -168,52 +173,57 @@ public class DieBoxCLI {
if (!words.hasNext()) {
return VOID_INST;
}
-
+
String command = words.next().trim();
-
+ DieBoxCLI state = this;
+
if (command.startsWith("$")) {
// All variable refs start with $
String varName = command.substring(1);
-
- if (bindings.containsKey(varName)) {
- return bindings.get(varName);
- } else {
- // @TODO Nov 15th, 2020 Ben Culkin :Autovars
- // Perhaps something along the lines of 'auto-variables' (here
- // called 'spring-loaded variables') should be created? These
- // would be essentially values which invoke a given expression
- // whenever they are referenced.
- throw new DieBoxException("Attempted to reference non-existing variable %s", varName);
- }
+
+ return bindings.get(varName)
+ .orElseThrow(() -> new DieBoxException(
+ "Attempted to reference non-existing variable %s",
+ varName));
+ // @TODO Nov 15th, 2020 Ben Culkin :Autovars
+ // Perhaps something along the lines of 'auto-variables' (here
+ // called 'spring-loaded variables') should be created? These
+ // would be essentially values which invoke a given expression
+ // whenever they are referenced.
} else if (command.startsWith("#")) {
// All literals/literal-formers start with #
String actualCommand = command.substring(1);
-
+
// Attempt to use a mapped literal/literal-former
- Command literalCommand = literals.get(actualCommand);
- if (literalCommand != null) {
- return literalCommand.execute(words, this);
- } else {
- if (INT_PATTERN.matcher(actualCommand).matches()) {
- try {
- int val = Integer.parseInt(actualCommand);
-
- return new IntegerStatementValue(val);
- } catch (NumberFormatException nfex) {
- throw new DieBoxException(nfex, "Improper integer literal (%s)", actualCommand);
- }
- } else {
- throw new DieBoxException("Unknown literal format (%s)", actualCommand);
- }
+ StatementValue val = literals.get(actualCommand)
+ .map((com) -> com.execute(words, state))
+ .orElseGet(() -> parseActualLiteral(actualCommand));
+
+ return val;
+ } else {
+ // Attempt to use a mapped command first
+ StatementValue val = commands.get(command)
+ .map((com) -> com.execute(words, state))
+ .orElseThrow(() -> new DieBoxException(
+ "Unknown command %s", command));
+ return val;
+ }
+ }
+
+ private StatementValue parseActualLiteral(String litText) {
+ if (INT_PATTERN.matcher(litText).matches()) {
+ try {
+ int val = Integer.parseInt(litText);
+
+ return new IntegerStatementValue(val);
+ } catch (NumberFormatException nfex) {
+ throw new DieBoxException(nfex,
+ "Improper integer literal (%s)",
+ litText);
}
} else {
- // Attempt to use a mapped command first
- Command mapCommand = commands.get(command);
- if (mapCommand != null) {
- return mapCommand.execute(words, this);
- } else {
- throw new DieBoxException("Unknown command %s", command);
- }
+ throw new DieBoxException("Unknown literal format (%s)",
+ litText);
}
}
} \ No newline at end of file
diff --git a/dice/src/example/java/bjc/dicelang/neodice/commands/PolyhedralDieCommand.java b/dice/src/example/java/bjc/dicelang/neodice/commands/PolyhedralDieCommand.java
index 95e9dff..6af495e 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/commands/PolyhedralDieCommand.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/commands/PolyhedralDieCommand.java
@@ -20,7 +20,11 @@ public class PolyhedralDieCommand implements Command {
if (numSides < 0) throw new DieBoxException("Number of sides to polyhedral-die was not valid (must be less than 0, was %d)", numSides);
- return new DieStatementValue(Die.polyhedral(numSides));
+ IDie<StatementValue> die = IDie
+ .polyhedral(numSides)
+ .transform(IntegerStatementValue::new);
+
+ return new DieStatementValue(INTEGER, die);
} else {
throw new DieBoxException("Number of sides to polyhedral-die wasn't an integer (was %s, of type %s)",
sideValue, sideValue.type);
diff --git a/dice/src/example/java/bjc/dicelang/neodice/commands/RollCommand.java b/dice/src/example/java/bjc/dicelang/neodice/commands/RollCommand.java
index eb7b597..eb8beda 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/commands/RollCommand.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/commands/RollCommand.java
@@ -18,11 +18,16 @@ public class RollCommand implements Command {
if (toRoll.type == DIE) {
DieStatementValue die = (DieStatementValue) toRoll;
- return new IntegerStatementValue(die.value.roll(state.rng));
+ return die.value.roll(state.rng);
} else if (toRoll.type == DIEPOOL) {
DiePoolStatementValue pool = (DiePoolStatementValue) toRoll;
- return new IntArrayStatementValue(pool.value.roll(state.rng));
+ StatementValue[] values = pool.value
+ .roll(state.rng)
+ .toArray((sz) -> new StatementValue[sz]);
+
+ return new ArrayStatementValue<>(pool.elementType,
+ values);
} else {
throw new DieBoxException("Roll was provided something that wasn't rollable (only DIE and DIEPOOL objects are rollable) (was %s, of type %s)",
toRoll, toRoll.type);
diff --git a/dice/src/example/java/bjc/dicelang/neodice/statements/DiePoolStatementValue.java b/dice/src/example/java/bjc/dicelang/neodice/statements/DiePoolStatementValue.java
index a4a9104..551c0e9 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/statements/DiePoolStatementValue.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/statements/DiePoolStatementValue.java
@@ -7,11 +7,13 @@ import java.util.*;
import bjc.dicelang.neodice.*;
public class DiePoolStatementValue extends StatementValue {
- public final DiePool value;
+ public final Type elementType;
+ public final IDiePool<StatementValue> value;
- public DiePoolStatementValue(DiePool value) {
+ public DiePoolStatementValue(Type elementType, IDiePool<StatementValue> value) {
super(DIEPOOL);
+ this.elementType = elementType;
this.value = value;
}
diff --git a/dice/src/example/java/bjc/dicelang/neodice/statements/DieStatementValue.java b/dice/src/example/java/bjc/dicelang/neodice/statements/DieStatementValue.java
index 55a6856..e1dbde8 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/statements/DieStatementValue.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/statements/DieStatementValue.java
@@ -7,11 +7,13 @@ import java.util.*;
import bjc.dicelang.neodice.*;
public class DieStatementValue extends StatementValue {
- public final Die value;
+ public final Type sideType;
+ public final IDie<StatementValue> value;
- public DieStatementValue(Die value) {
+ public DieStatementValue(Type sideType, IDie<StatementValue> value) {
super(DIE);
+ this.sideType = sideType;
this.value = value;
}
diff --git a/dice/src/example/java/bjc/dicelang/neodice/statements/IntArrayStatementValue.java b/dice/src/example/java/bjc/dicelang/neodice/statements/IntArrayStatementValue.java
deleted file mode 100644
index b313d42..0000000
--- a/dice/src/example/java/bjc/dicelang/neodice/statements/IntArrayStatementValue.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package bjc.dicelang.neodice.statements;
-
-import static bjc.dicelang.neodice.statements.StatementValue.Type.*;
-
-import java.util.*;
-
-public class IntArrayStatementValue extends StatementValue {
- public final int[] values;
-
- public IntArrayStatementValue(int... values) {
- super(INT_ARRAY);
-
- this.values = values;
- }
-
- @Override
- public String toString() {
- StringBuilder buffer = new StringBuilder();
-
- buffer.append('(');
- for (int index = 0; index < values.length; index++) {
- int value = values[index];
-
- buffer.append(value);
- if (index < values.length - 1) buffer.append(", ");
- }
- buffer.append(')');
-
- return buffer.toString();
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = super.hashCode();
- result = prime * result + Arrays.hashCode(values);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) return true;
- if (!super.equals(obj)) return false;
- if (getClass() != obj.getClass()) return false;
-
- IntArrayStatementValue other = (IntArrayStatementValue) obj;
-
- return Arrays.equals(values, other.values);
- }
-} \ No newline at end of file
diff --git a/dice/src/example/java/bjc/dicelang/neodice/statements/StatementValue.java b/dice/src/example/java/bjc/dicelang/neodice/statements/StatementValue.java
index 5090bc7..de796e5 100644
--- a/dice/src/example/java/bjc/dicelang/neodice/statements/StatementValue.java
+++ b/dice/src/example/java/bjc/dicelang/neodice/statements/StatementValue.java
@@ -8,8 +8,6 @@ public abstract class StatementValue {
BOOLEAN,
INTEGER,
- INT_ARRAY,
-
DIE,
DIEPOOL,
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)";
+ }
+}
diff --git a/dice/src/test/java/bjc/dicelang/neodice/DiePoolTest.java b/dice/src/test/java/bjc/dicelang/neodice/DiePoolTest.java
index 3614cd3..fda1505 100644
--- a/dice/src/test/java/bjc/dicelang/neodice/DiePoolTest.java
+++ b/dice/src/test/java/bjc/dicelang/neodice/DiePoolTest.java
@@ -10,24 +10,5 @@ import org.junit.*;
public class DiePoolTest {
private static final Random rng = new Random();
- @Test
- public void containedOneDieYieldsOneDie() {
- Die oneSidedDie = Die.polyhedral(1);
- DiePool pool = DiePool.containing(oneSidedDie);
-
- assertArrayEquals(
- "A contained pool created with one die, yields that die",
- new Die[] {oneSidedDie}, pool.contained());
- }
-
- @Test
- public void containedOneDieRollsOneDie() {
- Die oneSidedDie = Die.polyhedral(1);
- DiePool pool = DiePool.containing(oneSidedDie);
-
- for (int i = 0; i < 10; i++) {
- assertArrayEquals("One-die pools roll one die",
- new int[] {1}, pool.roll(rng));
- }
- }
+ // Some tests, I suppose
}
diff --git a/dice/src/test/java/bjc/dicelang/neodice/DieTest.java b/dice/src/test/java/bjc/dicelang/neodice/DieTest.java
index 202688b..baee4cc 100644
--- a/dice/src/test/java/bjc/dicelang/neodice/DieTest.java
+++ b/dice/src/test/java/bjc/dicelang/neodice/DieTest.java
@@ -10,37 +10,5 @@ import org.junit.*;
public class DieTest {
private final static Random rng = new Random();
- @Test
- public void onesidedDiceReturnOne() {
- Die die = Die.polyhedral(1);
-
- for (int i = 0; i < 10; i++) {
- assertEquals("One-sided dice always return 1", 1, die.roll(rng));
- }
- }
-
- @Test
- public void polyhedralDiceStayInRange() {
- Die die = Die.polyhedral(6);
-
- for (int i = 0; i < 50; i++) {
- int result = die.roll(rng);
-
- boolean inRange = result <= 6 && result >= 1;
-
- assertTrue("Six-sided dice always return a value from 1 to 6", inRange);
- }
- }
-
- @Test
- public void polyhedralDiceEqualityFunctionsProperly() {
- Die dieA1 = Die.polyhedral(1);
- Die dieA2 = Die.polyhedral(1);
- Die dieB1 = Die.polyhedral(2);
-
- assertEquals("Polyhedral dice with the same number of sides are equal",
- dieA1, dieA2);
- assertNotEquals("Polyhedral dice with a diffeent number of sides aren't equal",
- dieA1, dieB1);
- }
+ // Some tests, I guess
}