From 96e868388c7617136e916c27ddd90694c0bb8356 Mon Sep 17 00:00:00 2001 From: bjculkin Date: Mon, 27 Feb 2017 10:34:25 -0500 Subject: More refactoring --- dice-lang/src/bjc/dicelang/v2/DiceBox.java | 585 --------------------- dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java | 1 + dice-lang/src/bjc/dicelang/v2/Evaluator.java | 22 +- dice-lang/src/bjc/dicelang/v2/EvaluatorResult.java | 15 +- dice-lang/src/bjc/dicelang/v2/Token.java | 5 +- .../src/bjc/dicelang/v2/dice/CompoundDie.java | 31 ++ .../src/bjc/dicelang/v2/dice/CompoundingDie.java | 63 +++ dice-lang/src/bjc/dicelang/v2/dice/DiceBox.java | 142 +++++ dice-lang/src/bjc/dicelang/v2/dice/Die.java | 9 + .../src/bjc/dicelang/v2/dice/DieExpression.java | 30 ++ dice-lang/src/bjc/dicelang/v2/dice/DieList.java | 8 + .../src/bjc/dicelang/v2/dice/ExplodingDice.java | 70 +++ dice-lang/src/bjc/dicelang/v2/dice/FudgeDie.java | 37 ++ dice-lang/src/bjc/dicelang/v2/dice/MathDie.java | 74 +++ dice-lang/src/bjc/dicelang/v2/dice/ScalarDie.java | 29 + dice-lang/src/bjc/dicelang/v2/dice/SimpleDie.java | 60 +++ .../src/bjc/dicelang/v2/dice/SimpleDieList.java | 48 ++ 17 files changed, 627 insertions(+), 602 deletions(-) delete mode 100644 dice-lang/src/bjc/dicelang/v2/DiceBox.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/CompoundDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/CompoundingDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/DiceBox.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/Die.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/DieExpression.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/DieList.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/ExplodingDice.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/FudgeDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/MathDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/ScalarDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/SimpleDie.java create mode 100644 dice-lang/src/bjc/dicelang/v2/dice/SimpleDieList.java diff --git a/dice-lang/src/bjc/dicelang/v2/DiceBox.java b/dice-lang/src/bjc/dicelang/v2/DiceBox.java deleted file mode 100644 index 361b766..0000000 --- a/dice-lang/src/bjc/dicelang/v2/DiceBox.java +++ /dev/null @@ -1,585 +0,0 @@ -package bjc.dicelang.v2; - -import java.util.Arrays; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.function.Predicate; -import java.util.regex.Pattern; - -public class DiceBox { - private static final Random rng = new Random(); - - public interface Die { - boolean canOptimize(); - long optimize(); - - long roll(); - long rollSingle(); - } - - public interface DieList { - boolean canOptimize(); - long[] optimize(); - - long[] roll(); - } - - public static class DieExpression { - public final boolean isList; - - public Die scalar; - public DieList list; - - public DieExpression(Die scal) { - isList = false; - scalar = scal; - } - - public DieExpression(DieList lst) { - isList = true; - list = lst; - } - - public String toString() { - if(isList) return list.toString(); - else return scalar.toString(); - } - - public String value() { - if(isList) return Arrays.toString(list.roll()); - else return Long.toString(scalar.roll()); - } - } - - public static class ScalarDie implements Die { - private long val; - - public ScalarDie(long vl) { - val = vl; - } - - public boolean canOptimize() { - return true; - } - - public long optimize() { - return val; - } - - public long roll() { - return val; - } - - public long rollSingle() { - return val; - } - - public String toString() { - return Long.toString(val); - } - } - - public static class SimpleDie implements Die { - private Die numDice; - private Die diceSize; - - public SimpleDie(long nDice, long size) { - numDice = new ScalarDie(nDice); - diceSize = new ScalarDie(size); - } - - public SimpleDie(Die nDice, long size) { - numDice = nDice; - diceSize = new ScalarDie(size); - } - - public SimpleDie(long nDice, Die size) { - numDice = new ScalarDie(nDice); - diceSize = size; - } - - public SimpleDie(Die nDice, Die size) { - numDice = nDice; - diceSize = size; - } - - public boolean canOptimize() { - if(diceSize.canOptimize() && (diceSize.optimize() <= 1)) { - return numDice.canOptimize(); - } else return false; - } - - public long optimize() { - long optSize = diceSize.optimize(); - - if(optSize == 0) return 0; - else return numDice.optimize(); - } - - public long roll() { - long total = 0; - - long nDice = numDice.roll(); - long dSize = diceSize.roll(); - - for(int i = 0; i < nDice; i++) { - total += (Math.abs(rng.nextLong()) % dSize) + 1; - } - - return total; - } - - public long rollSingle() { - return (Math.abs(rng.nextLong()) % diceSize.roll()) + 1; - } - - public String toString() { - return numDice + "d" + diceSize; - } - } - - public static class FudgeDie implements Die { - private Die numDice; - - public FudgeDie(long nDice) { - numDice = new ScalarDie(nDice); - } - - public boolean canOptimize() { - return numDice.canOptimize() && numDice.optimize() == 0; - } - - public long optimize() { - return 0; - } - - public long roll() { - long res = 0; - - long nDice = numDice.roll(); - - for(int i = 0; i < nDice; i++) { - res += rollSingle(); - } - - return res; - } - - public long rollSingle() { - return rng.nextInt(3) - 1; - } - - public String toString() { - return numDice + "dF"; - } - } - - public static class CompoundDie implements Die { - private Die left; - private Die right; - - public CompoundDie(Die lft, Die rght) { - left = lft; - right = rght; - } - - public boolean canOptimize() { - return left.canOptimize() && right.canOptimize(); - } - - public long optimize() { - return Long.parseLong(left.optimize() + "" + right.optimize()); - } - - public long roll() { - return Long.parseLong(left.roll() + "" + right.roll()); - } - - public long rollSingle() { - return roll(); - } - - public String toString() { - return left.toString() + "c" + right.toString(); - } - } - - public static class CompoundingDie implements Die { - private Die source; - - private Predicate compoundOn; - private String compoundPattern; - - public CompoundingDie(Die src, Predicate compound) { - this(src, compound, null); - } - - public CompoundingDie(Die src, Predicate compound, String patt) { - source = src; - - compoundOn = compound; - compoundPattern = patt; - } - - public boolean canOptimize() { - return source.canOptimize() && source.optimize() == 0; - } - - public long optimize() { - return 0; - } - - public long roll() { - long res = source.roll(); - long oldRes = res; - - while(compoundOn.test(oldRes)) { - oldRes = source.rollSingle(); - - res += oldRes; - } - - return res; - } - - public long rollSingle() { - long res = source.rollSingle(); - long oldRes = res; - - while(compoundOn.test(oldRes)) { - oldRes = source.rollSingle(); - - res += oldRes; - } - - return res; - } - - public String toString() { - if(compoundPattern == null) { - return source + "!!"; - } else { - return source + "!!" + compoundPattern; - } - } - } - - public static class MathDie implements Die { - public static enum MathOp { - ADD, SUBTRACT, MULTIPLY; - - public String toString() { - switch(this) { - case ADD: - return "+"; - case SUBTRACT: - return "-"; - case MULTIPLY: - return "*"; - default: - return this.name(); - } - } - } - - private MathOp type; - - private Die left; - private Die right; - - public MathDie(MathOp op, Die lft, Die rght) { - type = op; - - left = lft; - right = rght; - } - - public boolean canOptimize() { - return left.canOptimize() && right.canOptimize(); - } - - private long performOp(long lft, long rght) { - switch(type) { - case ADD: - return lft + rght; - case SUBTRACT: - return lft - rght; - case MULTIPLY: - return lft * rght; - default: - return 0; - } - } - - public long optimize() { - long lft = left.optimize(); - long rght = right.optimize(); - - return performOp(lft, rght); - } - - public long roll() { - long lft = left.roll(); - long rght = right.roll(); - - return performOp(lft, rght); - } - - public long rollSingle() { - long lft = left.rollSingle(); - long rght = right.rollSingle(); - - return performOp(lft, rght); - } - - public String toString() { - return left.toString() + " " + type.toString() + " " + right.toString(); - } - } - - public static class SimpleDieList implements DieList { - private Die numDice; - private Die size; - - public SimpleDieList(Die nDice, Die sze) { - numDice = nDice; - size = sze; - } - - public boolean canOptimize() { - if(size.canOptimize() && size.optimize() <= 1) { - return numDice.canOptimize(); - } else { - return false; - } - } - - public long[] optimize() { - int sze = (int)numDice.optimize(); - long res = size.optimize(); - - long[] ret = new long[sze]; - - for(int i = 0; i < sze; i++) { - ret[i] = res; - } - - return ret; - } - - public long[] roll() { - int num = (int)numDice.roll(); - - long[] ret = new long[num]; - - for(int i = 0; i < num; i++) { - ret[i] = size.roll(); - } - - return ret; - } - - public String toString() { - return numDice.toString() + "dl" + size.toString(); - } - } - - public static class ExplodingDice implements DieList { - private Die source; - - private Predicate explodeOn; - private String explodePattern; - private boolean explodePenetrates; - - public ExplodingDice(Die src, Predicate explode) { - this(src, explode, null, false); - } - - public ExplodingDice(Die src, Predicate explode, boolean penetrate) { - this(src, explode, null, penetrate); - } - - public ExplodingDice(Die src, Predicate explode, String patt, - boolean penetrate) { - source = src; - explodeOn = explode; - explodePattern = patt; - explodePenetrates = penetrate; - } - - public boolean canOptimize() { - return false; - } - - public long[] optimize() { - return new long[0]; - } - - public long[] roll() { - long res = source.roll(); - long oldRes = res; - - List resList = new LinkedList<>(); - - while(explodeOn.test(oldRes)) { - oldRes = source.rollSingle(); - - if(explodePenetrates) oldRes -= 1; - resList.add(oldRes); - } - - long[] newRes = new long[resList.size() + 1]; - newRes[0] = res; - - int i = 1; - for(long rll : resList) { - newRes[i] = rll; - i += 1; - } - - return newRes; - } - - public String toString() { - if(explodePattern == null) { - return source + (explodePenetrates ? "p" : "") + "!"; - } else { - return source + (explodePenetrates ? "p" : "") + "!" + explodePattern; - } - } - } - - public static DieExpression parseExpression(String exp) { - if(!isValidExpression(exp)) return null; - - if(scalarDiePattern.matcher(exp).matches()) { - Die scal = new ScalarDie(Long.parseLong(exp.substring(0, exp.indexOf('s')))); - - return new DieExpression(scal); - } else if(simpleDiePattern.matcher(exp).matches()) { - String[] dieParts = exp.split("d"); - - long right = Long.parseLong(dieParts[1]); - if(dieParts[0].equals("")) { - Die scal = new SimpleDie(1, right); - return new DieExpression(scal); - } else { - Die scal = new SimpleDie(Long.parseLong(dieParts[0]), right); - return new DieExpression(scal); - } - } else if(fudgeDiePattern.matcher(exp).matches()) { - String nDice = exp.substring(0, exp.indexOf('d')); - - return new DieExpression(new FudgeDie(Long.parseLong(nDice))); - } else if(compoundDiePattern.matcher(exp).matches()) { - String[] dieParts = exp.split("c"); - - DieExpression left = parseExpression(dieParts[0]); - DieExpression right = parseExpression(dieParts[1]); - - return new DieExpression(new CompoundDie(left.scalar, right.scalar)); - } else if(compoundingDiePattern.matcher(exp).matches()) { - String[] dieParts = exp.split("!!"); - - DieExpression left = parseExpression(dieParts[0]); - Predicate right = deriveCond(dieParts[1]); - - Die scal = new CompoundingDie(left.scalar, right, dieParts[1]); - return new DieExpression(scal); - } else if(explodingDiePattern.matcher(exp).matches()) { - String[] dieParts = exp.split("!"); - - DieExpression left = parseExpression(dieParts[0]); - Predicate right = deriveCond(dieParts[1]); - - DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], false); - return new DieExpression(lst); - } else if(penetratingDiePattern.matcher(exp).matches()) { - String[] dieParts = exp.split("p!"); - - DieExpression left = parseExpression(dieParts[0]); - Predicate right = deriveCond(dieParts[1]); - - DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], true); - return new DieExpression(lst); - } else if(diceListPattern.matcher(exp).matches()) { - String[] dieParts = exp.split("dl"); - - DieExpression left = parseExpression(dieParts[0]); - DieExpression right = parseExpression(dieParts[1]); - - DieList lst = new SimpleDieList(left.scalar, right.scalar); - return new DieExpression(lst); - } - - // @TODO give a specific error message - return null; - } - - private static final String comparePoint = "[<>=]\\d+"; - - private static final String scalarDie = "[\\+\\-]?\\d+sd"; - private static final Pattern scalarDiePattern = Pattern.compile("\\A" + scalarDie + "\\Z"); - - private static final String simpleDie = "(?:\\d+)?d\\d+"; - private static final Pattern simpleDiePattern = Pattern.compile("\\A" + simpleDie + "\\Z"); - - private static final String fudgeDie = "(?:\\d+)?dF"; - private static final Pattern fudgeDiePattern = Pattern.compile("\\A" + fudgeDie + "\\Z"); - - private static final String compoundDie = simpleDie + "c(?:(?:" + simpleDie + ")|(?:\\d+))"; - private static final Pattern compoundDiePattern = Pattern.compile("\\A" + compoundDie + "\\Z"); - - private static final String compoundGroup = "(?:(?:" + scalarDie + ")|(?:" + simpleDie + ")|(?:" - + compoundDie + ")|(?:" + fudgeDie +"))"; - - private static final String compoundingDie = compoundGroup + "!!" + comparePoint; - private static final Pattern compoundingDiePattern = Pattern.compile("\\A" + compoundingDie + "\\Z"); - - private static final String explodingDie = compoundGroup + "!" + comparePoint; - private static final Pattern explodingDiePattern = Pattern.compile("\\A" + explodingDie + "\\Z"); - - private static final String penetratingDie = compoundGroup + "!" + comparePoint; - private static final Pattern penetratingDiePattern = Pattern.compile("\\A" + penetratingDie + "\\Z"); - - private static final String diceList = compoundGroup + "dl" + compoundGroup; - private static final Pattern diceListPattern = Pattern.compile("\\A" + diceList + "\\Z"); - - public static boolean isValidExpression(String exp) { - if(scalarDiePattern.matcher(exp).matches()) { - return true; - } else if(simpleDiePattern.matcher(exp).matches()) { - return true; - } else if(fudgeDiePattern.matcher(exp).matches()) { - return true; - } else if(compoundDiePattern.matcher(exp).matches()) { - return true; - } else if(compoundingDiePattern.matcher(exp).matches()) { - return true; - } else if(explodingDiePattern.matcher(exp).matches()) { - return true; - } else if(penetratingDiePattern.matcher(exp).matches()) { - return true; - } else if (diceListPattern.matcher(exp).matches()) { - return true; - } else { - return false; - } - } - - private static Predicate deriveCond(String patt) { - long num = Long.parseLong(patt.substring(1)); - - switch(patt.charAt(0)) { - case '<': - return (roll) -> roll < num; - case '=': - return (roll) -> roll == num; - case '>': - return (roll) -> roll > num; - default: - return (roll) -> false; - } - } -} diff --git a/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java b/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java index 8ff20ef..200c0b6 100644 --- a/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java +++ b/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java @@ -1,5 +1,6 @@ package bjc.dicelang.v2; +import bjc.dicelang.v2.dice.DiceBox; import bjc.utils.data.IPair; import bjc.utils.data.ITree; import bjc.utils.data.Pair; diff --git a/dice-lang/src/bjc/dicelang/v2/Evaluator.java b/dice-lang/src/bjc/dicelang/v2/Evaluator.java index 047e12f..ed9db17 100644 --- a/dice-lang/src/bjc/dicelang/v2/Evaluator.java +++ b/dice-lang/src/bjc/dicelang/v2/Evaluator.java @@ -1,5 +1,9 @@ package bjc.dicelang.v2; +import bjc.dicelang.v2.dice.CompoundDie; +import bjc.dicelang.v2.dice.MathDie; +import bjc.dicelang.v2.dice.SimpleDie; +import bjc.dicelang.v2.dice.SimpleDieList; import bjc.utils.data.ITree; import bjc.utils.data.SingleIterator; import bjc.utils.data.Tree; @@ -210,18 +214,18 @@ public class Evaluator { if(left.type == DICE && !left.diceVal.isList) { if(right.type == DICE && !right.diceVal.isList) { res = new EvaluatorResult(DICE, - new DiceBox.SimpleDie(left.diceVal.scalar, right.diceVal.scalar)); + new SimpleDie(left.diceVal.scalar, right.diceVal.scalar)); } else if (right.type == INT) { - res = new EvaluatorResult(DICE, new DiceBox.SimpleDie(left.diceVal.scalar, right.intVal)); + res = new EvaluatorResult(DICE, new SimpleDie(left.diceVal.scalar, right.intVal)); } else { Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); return new Tree<>(FAIL(right)); } } else if(left.type == INT) { if(right.type == DICE && !right.diceVal.isList) { - res = new EvaluatorResult(DICE, new DiceBox.SimpleDie(left.intVal, right.diceVal.scalar)); + res = new EvaluatorResult(DICE, new SimpleDie(left.intVal, right.diceVal.scalar)); } else if (right.type == INT) { - res = new EvaluatorResult(DICE, new DiceBox.SimpleDie(left.intVal, right.intVal)); + res = new EvaluatorResult(DICE, new SimpleDie(left.intVal, right.intVal)); } else { Errors.inst.printError(EK_EVAL_INVDGROUP, right.type.toString()); return new Tree<>(FAIL(right)); @@ -239,7 +243,7 @@ public class Evaluator { return new Tree<>(FAIL(right)); } else { res = new EvaluatorResult(DICE, - new DiceBox.CompoundDie(left.diceVal.scalar, right.diceVal.scalar)); + new CompoundDie(left.diceVal.scalar, right.diceVal.scalar)); } break; case DICELIST: @@ -251,7 +255,7 @@ public class Evaluator { return new Tree<>(FAIL(right)); } else { res = new EvaluatorResult(DICE, - new DiceBox.SimpleDieList(left.diceVal.scalar, right.diceVal.scalar)); + new SimpleDieList(left.diceVal.scalar, right.diceVal.scalar)); } break; default: @@ -304,7 +308,7 @@ public class Evaluator { return new Tree<>(FAIL(right)); } - res = new EvaluatorResult(DICE, new DiceBox.MathDie(DiceBox.MathDie.MathOp.ADD, + res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.ADD, left.diceVal.scalar, right.diceVal.scalar)); } else { res = new EvaluatorResult(FLOAT, left.floatVal + right.floatVal); @@ -322,7 +326,7 @@ public class Evaluator { return new Tree<>(FAIL(right)); } - res = new EvaluatorResult(DICE, new DiceBox.MathDie(DiceBox.MathDie.MathOp.SUBTRACT, + res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.SUBTRACT, left.diceVal.scalar, right.diceVal.scalar)); } else { res = new EvaluatorResult(FLOAT, left.floatVal - right.floatVal); @@ -340,7 +344,7 @@ public class Evaluator { return new Tree<>(FAIL(right)); } - res = new EvaluatorResult(DICE, new DiceBox.MathDie(DiceBox.MathDie.MathOp.MULTIPLY, + res = new EvaluatorResult(DICE, new MathDie(MathDie.MathOp.MULTIPLY, left.diceVal.scalar, right.diceVal.scalar)); } else { res = new EvaluatorResult(FLOAT, left.floatVal * right.floatVal); diff --git a/dice-lang/src/bjc/dicelang/v2/EvaluatorResult.java b/dice-lang/src/bjc/dicelang/v2/EvaluatorResult.java index 510d5e9..bac4d2d 100644 --- a/dice-lang/src/bjc/dicelang/v2/EvaluatorResult.java +++ b/dice-lang/src/bjc/dicelang/v2/EvaluatorResult.java @@ -1,5 +1,8 @@ package bjc.dicelang.v2; +import bjc.dicelang.v2.dice.Die; +import bjc.dicelang.v2.dice.DieExpression; +import bjc.dicelang.v2.dice.DieList; import bjc.utils.data.ITree; import bjc.utils.data.Tree; @@ -15,7 +18,7 @@ public class EvaluatorResult { // off of the result type public long intVal; public double floatVal; - public DiceBox.DieExpression diceVal; + public DieExpression diceVal; public String stringVal; // Original node data @@ -51,22 +54,22 @@ public class EvaluatorResult { floatVal = dVal; } - public EvaluatorResult(EvaluatorResult.Type typ, DiceBox.DieExpression dVal) { + public EvaluatorResult(EvaluatorResult.Type typ, DieExpression dVal) { this(typ); diceVal = dVal; } - public EvaluatorResult(EvaluatorResult.Type typ, DiceBox.Die dVal) { + public EvaluatorResult(EvaluatorResult.Type typ, Die dVal) { this(typ); - diceVal = new DiceBox.DieExpression(dVal); + diceVal = new DieExpression(dVal); } - public EvaluatorResult(EvaluatorResult.Type typ, DiceBox.DieList dVal) { + public EvaluatorResult(EvaluatorResult.Type typ, DieList dVal) { this(typ); - diceVal = new DiceBox.DieExpression(dVal); + diceVal = new DieExpression(dVal); } public EvaluatorResult(EvaluatorResult.Type typ, String strang) { diff --git a/dice-lang/src/bjc/dicelang/v2/Token.java b/dice-lang/src/bjc/dicelang/v2/Token.java index e5d3d9f..3d8359f 100644 --- a/dice-lang/src/bjc/dicelang/v2/Token.java +++ b/dice-lang/src/bjc/dicelang/v2/Token.java @@ -1,5 +1,6 @@ package bjc.dicelang.v2; +import bjc.dicelang.v2.dice.DieExpression; import bjc.utils.funcdata.IList; /** @@ -46,7 +47,7 @@ public class Token { // This is used for the following token types // DICE_LIT (dice value) - public DiceBox.DieExpression diceValue; + public DieExpression diceValue; // This is used for the following token types // TOKGROUP (the tokens in the group) @@ -69,7 +70,7 @@ public class Token { floatValue = val; } - public Token(Type typ, DiceBox.DieExpression val) { + public Token(Type typ, DieExpression val) { this(typ); diceValue = val; diff --git a/dice-lang/src/bjc/dicelang/v2/dice/CompoundDie.java b/dice-lang/src/bjc/dicelang/v2/dice/CompoundDie.java new file mode 100644 index 0000000..a8186eb --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/CompoundDie.java @@ -0,0 +1,31 @@ +package bjc.dicelang.v2.dice; + +public class CompoundDie implements Die { + private Die left; + private Die right; + + public CompoundDie(Die lft, Die rght) { + left = lft; + right = rght; + } + + public boolean canOptimize() { + return left.canOptimize() && right.canOptimize(); + } + + public long optimize() { + return Long.parseLong(left.optimize() + "" + right.optimize()); + } + + public long roll() { + return Long.parseLong(left.roll() + "" + right.roll()); + } + + public long rollSingle() { + return roll(); + } + + public String toString() { + return left.toString() + "c" + right.toString(); + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/CompoundingDie.java b/dice-lang/src/bjc/dicelang/v2/dice/CompoundingDie.java new file mode 100644 index 0000000..d5991ae --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/CompoundingDie.java @@ -0,0 +1,63 @@ +package bjc.dicelang.v2.dice; + +import java.util.function.Predicate; + +public class CompoundingDie implements Die { + private Die source; + + private Predicate compoundOn; + private String compoundPattern; + + public CompoundingDie(Die src, Predicate compound) { + this(src, compound, null); + } + + public CompoundingDie(Die src, Predicate compound, String patt) { + source = src; + + compoundOn = compound; + compoundPattern = patt; + } + + public boolean canOptimize() { + return source.canOptimize() && source.optimize() == 0; + } + + public long optimize() { + return 0; + } + + public long roll() { + long res = source.roll(); + long oldRes = res; + + while(compoundOn.test(oldRes)) { + oldRes = source.rollSingle(); + + res += oldRes; + } + + return res; + } + + public long rollSingle() { + long res = source.rollSingle(); + long oldRes = res; + + while(compoundOn.test(oldRes)) { + oldRes = source.rollSingle(); + + res += oldRes; + } + + return res; + } + + public String toString() { + if(compoundPattern == null) { + return source + "!!"; + } else { + return source + "!!" + compoundPattern; + } + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/DiceBox.java b/dice-lang/src/bjc/dicelang/v2/dice/DiceBox.java new file mode 100644 index 0000000..995c3bf --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/DiceBox.java @@ -0,0 +1,142 @@ +package bjc.dicelang.v2.dice; + +import java.util.Random; +import java.util.function.Predicate; +import java.util.regex.Pattern; + +public class DiceBox { + static final Random rng = new Random(); + + public static DieExpression parseExpression(String exp) { + if(!isValidExpression(exp)) return null; + + if(scalarDiePattern.matcher(exp).matches()) { + Die scal = new ScalarDie(Long.parseLong(exp.substring(0, exp.indexOf('s')))); + + return new DieExpression(scal); + } else if(simpleDiePattern.matcher(exp).matches()) { + String[] dieParts = exp.split("d"); + + long right = Long.parseLong(dieParts[1]); + if(dieParts[0].equals("")) { + Die scal = new SimpleDie(1, right); + return new DieExpression(scal); + } else { + Die scal = new SimpleDie(Long.parseLong(dieParts[0]), right); + return new DieExpression(scal); + } + } else if(fudgeDiePattern.matcher(exp).matches()) { + String nDice = exp.substring(0, exp.indexOf('d')); + + return new DieExpression(new FudgeDie(Long.parseLong(nDice))); + } else if(compoundDiePattern.matcher(exp).matches()) { + String[] dieParts = exp.split("c"); + + DieExpression left = parseExpression(dieParts[0]); + DieExpression right = parseExpression(dieParts[1]); + + return new DieExpression(new CompoundDie(left.scalar, right.scalar)); + } else if(compoundingDiePattern.matcher(exp).matches()) { + String[] dieParts = exp.split("!!"); + + DieExpression left = parseExpression(dieParts[0]); + Predicate right = deriveCond(dieParts[1]); + + Die scal = new CompoundingDie(left.scalar, right, dieParts[1]); + return new DieExpression(scal); + } else if(explodingDiePattern.matcher(exp).matches()) { + String[] dieParts = exp.split("!"); + + DieExpression left = parseExpression(dieParts[0]); + Predicate right = deriveCond(dieParts[1]); + + DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], false); + return new DieExpression(lst); + } else if(penetratingDiePattern.matcher(exp).matches()) { + String[] dieParts = exp.split("p!"); + + DieExpression left = parseExpression(dieParts[0]); + Predicate right = deriveCond(dieParts[1]); + + DieList lst = new ExplodingDice(left.scalar, right, dieParts[1], true); + return new DieExpression(lst); + } else if(diceListPattern.matcher(exp).matches()) { + String[] dieParts = exp.split("dl"); + + DieExpression left = parseExpression(dieParts[0]); + DieExpression right = parseExpression(dieParts[1]); + + DieList lst = new SimpleDieList(left.scalar, right.scalar); + return new DieExpression(lst); + } + + // @TODO give a specific error message + return null; + } + + private static final String comparePoint = "[<>=]\\d+"; + + private static final String scalarDie = "[\\+\\-]?\\d+sd"; + private static final Pattern scalarDiePattern = Pattern.compile("\\A" + scalarDie + "\\Z"); + + private static final String simpleDie = "(?:\\d+)?d\\d+"; + private static final Pattern simpleDiePattern = Pattern.compile("\\A" + simpleDie + "\\Z"); + + private static final String fudgeDie = "(?:\\d+)?dF"; + private static final Pattern fudgeDiePattern = Pattern.compile("\\A" + fudgeDie + "\\Z"); + + private static final String compoundDie = simpleDie + "c(?:(?:" + simpleDie + ")|(?:\\d+))"; + private static final Pattern compoundDiePattern = Pattern.compile("\\A" + compoundDie + "\\Z"); + + private static final String compoundGroup = "(?:(?:" + scalarDie + ")|(?:" + simpleDie + ")|(?:" + + compoundDie + ")|(?:" + fudgeDie +"))"; + + private static final String compoundingDie = compoundGroup + "!!" + comparePoint; + private static final Pattern compoundingDiePattern = Pattern.compile("\\A" + compoundingDie + "\\Z"); + + private static final String explodingDie = compoundGroup + "!" + comparePoint; + private static final Pattern explodingDiePattern = Pattern.compile("\\A" + explodingDie + "\\Z"); + + private static final String penetratingDie = compoundGroup + "!" + comparePoint; + private static final Pattern penetratingDiePattern = Pattern.compile("\\A" + penetratingDie + "\\Z"); + + private static final String diceList = compoundGroup + "dl" + compoundGroup; + private static final Pattern diceListPattern = Pattern.compile("\\A" + diceList + "\\Z"); + + public static boolean isValidExpression(String exp) { + if(scalarDiePattern.matcher(exp).matches()) { + return true; + } else if(simpleDiePattern.matcher(exp).matches()) { + return true; + } else if(fudgeDiePattern.matcher(exp).matches()) { + return true; + } else if(compoundDiePattern.matcher(exp).matches()) { + return true; + } else if(compoundingDiePattern.matcher(exp).matches()) { + return true; + } else if(explodingDiePattern.matcher(exp).matches()) { + return true; + } else if(penetratingDiePattern.matcher(exp).matches()) { + return true; + } else if (diceListPattern.matcher(exp).matches()) { + return true; + } else { + return false; + } + } + + private static Predicate deriveCond(String patt) { + long num = Long.parseLong(patt.substring(1)); + + switch(patt.charAt(0)) { + case '<': + return (roll) -> roll < num; + case '=': + return (roll) -> roll == num; + case '>': + return (roll) -> roll > num; + default: + return (roll) -> false; + } + } +} diff --git a/dice-lang/src/bjc/dicelang/v2/dice/Die.java b/dice-lang/src/bjc/dicelang/v2/dice/Die.java new file mode 100644 index 0000000..808d7fd --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/Die.java @@ -0,0 +1,9 @@ +package bjc.dicelang.v2.dice; + +public interface Die { + boolean canOptimize(); + long optimize(); + + long roll(); + long rollSingle(); +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/DieExpression.java b/dice-lang/src/bjc/dicelang/v2/dice/DieExpression.java new file mode 100644 index 0000000..93fcbb9 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/DieExpression.java @@ -0,0 +1,30 @@ +package bjc.dicelang.v2.dice; + +import java.util.Arrays; + +public class DieExpression { + public final boolean isList; + + public Die scalar; + public DieList list; + + public DieExpression(Die scal) { + isList = false; + scalar = scal; + } + + public DieExpression(DieList lst) { + isList = true; + list = lst; + } + + public String toString() { + if(isList) return list.toString(); + else return scalar.toString(); + } + + public String value() { + if(isList) return Arrays.toString(list.roll()); + else return Long.toString(scalar.roll()); + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/DieList.java b/dice-lang/src/bjc/dicelang/v2/dice/DieList.java new file mode 100644 index 0000000..ab3c7b7 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/DieList.java @@ -0,0 +1,8 @@ +package bjc.dicelang.v2.dice; + +public interface DieList { + boolean canOptimize(); + long[] optimize(); + + long[] roll(); +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/ExplodingDice.java b/dice-lang/src/bjc/dicelang/v2/dice/ExplodingDice.java new file mode 100644 index 0000000..40ff1e0 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/ExplodingDice.java @@ -0,0 +1,70 @@ +package bjc.dicelang.v2.dice; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Predicate; + +public class ExplodingDice implements DieList { + private Die source; + + private Predicate explodeOn; + private String explodePattern; + private boolean explodePenetrates; + + public ExplodingDice(Die src, Predicate explode) { + this(src, explode, null, false); + } + + public ExplodingDice(Die src, Predicate explode, boolean penetrate) { + this(src, explode, null, penetrate); + } + + public ExplodingDice(Die src, Predicate explode, String patt, + boolean penetrate) { + source = src; + explodeOn = explode; + explodePattern = patt; + explodePenetrates = penetrate; + } + + public boolean canOptimize() { + return false; + } + + public long[] optimize() { + return new long[0]; + } + + public long[] roll() { + long res = source.roll(); + long oldRes = res; + + List resList = new LinkedList<>(); + + while(explodeOn.test(oldRes)) { + oldRes = source.rollSingle(); + + if(explodePenetrates) oldRes -= 1; + resList.add(oldRes); + } + + long[] newRes = new long[resList.size() + 1]; + newRes[0] = res; + + int i = 1; + for(long rll : resList) { + newRes[i] = rll; + i += 1; + } + + return newRes; + } + + public String toString() { + if(explodePattern == null) { + return source + (explodePenetrates ? "p" : "") + "!"; + } else { + return source + (explodePenetrates ? "p" : "") + "!" + explodePattern; + } + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/FudgeDie.java b/dice-lang/src/bjc/dicelang/v2/dice/FudgeDie.java new file mode 100644 index 0000000..4c8c52a --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/FudgeDie.java @@ -0,0 +1,37 @@ +package bjc.dicelang.v2.dice; + +public class FudgeDie implements Die { + private Die numDice; + + public FudgeDie(long nDice) { + numDice = new ScalarDie(nDice); + } + + public boolean canOptimize() { + return numDice.canOptimize() && numDice.optimize() == 0; + } + + public long optimize() { + return 0; + } + + public long roll() { + long res = 0; + + long nDice = numDice.roll(); + + for(int i = 0; i < nDice; i++) { + res += rollSingle(); + } + + return res; + } + + public long rollSingle() { + return DiceBox.rng.nextInt(3) - 1; + } + + public String toString() { + return numDice + "dF"; + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/MathDie.java b/dice-lang/src/bjc/dicelang/v2/dice/MathDie.java new file mode 100644 index 0000000..55e01f8 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/MathDie.java @@ -0,0 +1,74 @@ +package bjc.dicelang.v2.dice; + +public class MathDie implements Die { + public static enum MathOp { + ADD, SUBTRACT, MULTIPLY; + + public String toString() { + switch(this) { + case ADD: + return "+"; + case SUBTRACT: + return "-"; + case MULTIPLY: + return "*"; + default: + return this.name(); + } + } + } + + private MathDie.MathOp type; + + private Die left; + private Die right; + + public MathDie(MathDie.MathOp op, Die lft, Die rght) { + type = op; + + left = lft; + right = rght; + } + + public boolean canOptimize() { + return left.canOptimize() && right.canOptimize(); + } + + private long performOp(long lft, long rght) { + switch(type) { + case ADD: + return lft + rght; + case SUBTRACT: + return lft - rght; + case MULTIPLY: + return lft * rght; + default: + return 0; + } + } + + public long optimize() { + long lft = left.optimize(); + long rght = right.optimize(); + + return performOp(lft, rght); + } + + public long roll() { + long lft = left.roll(); + long rght = right.roll(); + + return performOp(lft, rght); + } + + public long rollSingle() { + long lft = left.rollSingle(); + long rght = right.rollSingle(); + + return performOp(lft, rght); + } + + public String toString() { + return left.toString() + " " + type.toString() + " " + right.toString(); + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/ScalarDie.java b/dice-lang/src/bjc/dicelang/v2/dice/ScalarDie.java new file mode 100644 index 0000000..17714ee --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/ScalarDie.java @@ -0,0 +1,29 @@ +package bjc.dicelang.v2.dice; + +public class ScalarDie implements Die { + private long val; + + public ScalarDie(long vl) { + val = vl; + } + + public boolean canOptimize() { + return true; + } + + public long optimize() { + return val; + } + + public long roll() { + return val; + } + + public long rollSingle() { + return val; + } + + public String toString() { + return Long.toString(val); + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/SimpleDie.java b/dice-lang/src/bjc/dicelang/v2/dice/SimpleDie.java new file mode 100644 index 0000000..f084822 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/SimpleDie.java @@ -0,0 +1,60 @@ +package bjc.dicelang.v2.dice; + +public class SimpleDie implements Die { + private Die numDice; + private Die diceSize; + + public SimpleDie(long nDice, long size) { + numDice = new ScalarDie(nDice); + diceSize = new ScalarDie(size); + } + + public SimpleDie(Die nDice, long size) { + numDice = nDice; + diceSize = new ScalarDie(size); + } + + public SimpleDie(long nDice, Die size) { + numDice = new ScalarDie(nDice); + diceSize = size; + } + + public SimpleDie(Die nDice, Die size) { + numDice = nDice; + diceSize = size; + } + + public boolean canOptimize() { + if(diceSize.canOptimize() && (diceSize.optimize() <= 1)) { + return numDice.canOptimize(); + } else return false; + } + + public long optimize() { + long optSize = diceSize.optimize(); + + if(optSize == 0) return 0; + else return numDice.optimize(); + } + + public long roll() { + long total = 0; + + long nDice = numDice.roll(); + long dSize = diceSize.roll(); + + for(int i = 0; i < nDice; i++) { + total += (Math.abs(DiceBox.rng.nextLong()) % dSize) + 1; + } + + return total; + } + + public long rollSingle() { + return (Math.abs(DiceBox.rng.nextLong()) % diceSize.roll()) + 1; + } + + public String toString() { + return numDice + "d" + diceSize; + } +} \ No newline at end of file diff --git a/dice-lang/src/bjc/dicelang/v2/dice/SimpleDieList.java b/dice-lang/src/bjc/dicelang/v2/dice/SimpleDieList.java new file mode 100644 index 0000000..e5aef18 --- /dev/null +++ b/dice-lang/src/bjc/dicelang/v2/dice/SimpleDieList.java @@ -0,0 +1,48 @@ +package bjc.dicelang.v2.dice; + +public class SimpleDieList implements DieList { + private Die numDice; + private Die size; + + public SimpleDieList(Die nDice, Die sze) { + numDice = nDice; + size = sze; + } + + public boolean canOptimize() { + if(size.canOptimize() && size.optimize() <= 1) { + return numDice.canOptimize(); + } else { + return false; + } + } + + public long[] optimize() { + int sze = (int)numDice.optimize(); + long res = size.optimize(); + + long[] ret = new long[sze]; + + for(int i = 0; i < sze; i++) { + ret[i] = res; + } + + return ret; + } + + public long[] roll() { + int num = (int)numDice.roll(); + + long[] ret = new long[num]; + + for(int i = 0; i < num; i++) { + ret[i] = size.roll(); + } + + return ret; + } + + public String toString() { + return numDice.toString() + "dl" + size.toString(); + } +} \ No newline at end of file -- cgit v1.2.3