|
From: <mar...@us...> - 2013-09-18 23:07:14
|
Revision: 102
http://sourceforge.net/p/openrpg/svn/102
Author: markt1964
Date: 2013-09-18 23:07:11 +0000 (Wed, 18 Sep 2013)
Log Message:
-----------
Complete rewrite of dice rolling code
Added Paths:
-----------
trunk/src/openrpg2/common/dice/
trunk/src/openrpg2/common/dice/CompareExpr.java
trunk/src/openrpg2/common/dice/Const.java
trunk/src/openrpg2/common/dice/DiceExpression.java
trunk/src/openrpg2/common/dice/DiceParser.java
trunk/src/openrpg2/common/dice/DieFunction.java
trunk/src/openrpg2/common/dice/Function.java
trunk/src/openrpg2/common/dice/MultiDice.java
trunk/src/openrpg2/common/dice/MultiValue.java
trunk/src/openrpg2/common/dice/MultiValueFunction.java
trunk/src/openrpg2/common/dice/NegExpr.java
trunk/src/openrpg2/common/dice/ProdExpr.java
trunk/src/openrpg2/common/dice/Scanner.java
trunk/src/openrpg2/common/dice/SumExpr.java
trunk/src/openrpg2/common/dice/TestExpr.java
trunk/src/openrpg2/common/dice/UniValue.java
trunk/src/openrpg2/common/dice/UniValueFunction.java
Removed Paths:
-------------
trunk/src/openrpg2/common/dice/
Added: trunk/src/openrpg2/common/dice/CompareExpr.java
===================================================================
--- trunk/src/openrpg2/common/dice/CompareExpr.java (rev 0)
+++ trunk/src/openrpg2/common/dice/CompareExpr.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,194 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+
+/**
+ *
+ * @author markt
+ */
+public abstract class CompareExpr implements DiceExpression {
+ /**
+ * Left and right hand sides of this expression
+ */
+ protected DiceExpression left,right;
+ /**
+ * Name for the comparitor operator in this expression
+ */
+ protected String name;
+
+ /**
+ *
+ * @return 0
+ */
+ public int getValue()
+ {
+ return 0;
+ }
+
+ /**
+ *
+ * @return text form of this compare expresssion
+ */
+ public String getText()
+ {
+ return left.getText()+name+right.getText();
+ }
+
+ /**
+ *
+ * @return text form of this compare expresssion
+ */
+ public String getTextDetail()
+ {
+ return left.getTextDetail()+name+right.getTextDetail();
+ }
+
+ /**
+ * Executes both sides of this compare expression
+ */
+ public void exec()
+ {
+ left.exec();
+ right.exec();
+ }
+
+ /**
+ * Compare Expression constructor
+ * @param l left hand side
+ * @param r right hand side
+ */
+ public CompareExpr(DiceExpression l,DiceExpression r)
+ {
+ left=l;
+ right=r;
+ }
+
+ /**
+ * Performs the actual comparison test
+ * @return true if the test is successful, false otherwise
+ */
+ public abstract boolean test();
+
+ /**
+ * Invalid for comparison functions
+ * @return nothing, throws an exception
+ */
+ public DiceExpression negate()
+ {
+ throw new UnsupportedOperationException("Not supported yet.");
+ }
+
+
+}
+class CompareL extends CompareExpr
+{
+ public CompareL(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name="<";
+ }
+
+ public boolean test()
+ {
+ return left.getValue()<right.getValue();
+ }
+}
+
+class CompareG extends CompareExpr
+{
+ public CompareG(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name=">";
+ }
+
+ public boolean test()
+ {
+ return left.getValue()>right.getValue();
+ }
+}
+
+class CompareLE extends CompareExpr
+{
+ public CompareLE(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name="<=";
+ }
+
+ public boolean test()
+ {
+ return left.getValue()<=right.getValue();
+ }
+}
+
+class CompareGE extends CompareExpr
+{
+ public CompareGE(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name=">=";
+ }
+
+ public boolean test()
+ {
+ return left.getValue()>=right.getValue();
+ }
+}
+
+class CompareE extends CompareExpr
+{
+ public CompareE(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name="=";
+ }
+
+ public boolean test()
+ {
+ if (right instanceof TestExpr)
+ {
+ return ((TestExpr)right).testValue(left.getValue());
+ }
+ else
+ {
+ return left.getValue()==right.getValue();
+ }
+ }
+}
+
+class CompareNE extends CompareExpr
+{
+ public CompareNE(DiceExpression l,DiceExpression r)
+ {
+ super(l,r);
+ name="<>";
+ }
+
+ public boolean test()
+ {
+ if (right instanceof TestExpr)
+ {
+ return !((TestExpr)right).testValue(left.getValue());
+ }
+ else
+ {
+ return left.getValue()!=right.getValue();
+ }
+ }
+}
Added: trunk/src/openrpg2/common/dice/Const.java
===================================================================
--- trunk/src/openrpg2/common/dice/Const.java (rev 0)
+++ trunk/src/openrpg2/common/dice/Const.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,88 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+/**
+ *
+ * @author markt
+ */
+public class Const implements UniValue, TestExpr
+{
+ private final int value;
+
+ /**
+ *
+ * @return value of constant expression
+ */
+ public int getValue()
+ {
+ return value;
+ }
+
+ /**
+ *
+ * @return text form of constant expression
+ */
+ public String getTextDetail()
+ {
+ return ""+value;
+ }
+
+ /**
+ *
+ * @return text form of constant expression
+ */
+ public String getText()
+ {
+ return ""+value;
+ }
+
+ /**
+ * Placeholder for executing the expression (does nothing)
+ */
+ public void exec()
+ {
+ }
+
+ /**
+ * Constructor for constant expression
+ * @param n the integer this constant represents
+ */
+ public Const(int n)
+ {
+ value=n;
+ }
+
+ /**
+ * Test function to compare an integer with this expression
+ * @param n the integer to compare to
+ * @return true if they are the same, false otherwise
+ */
+ public boolean testValue(int n)
+ {
+ return n==value;
+ }
+
+ /**
+ *
+ * @return a negated constant expression
+ */
+ public DiceExpression negate()
+ {
+ return new Const(-value);
+ }
+}
Added: trunk/src/openrpg2/common/dice/DiceExpression.java
===================================================================
--- trunk/src/openrpg2/common/dice/DiceExpression.java (rev 0)
+++ trunk/src/openrpg2/common/dice/DiceExpression.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,49 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+/**
+ *
+ * @author markt
+ */
+public interface DiceExpression
+{
+ /**
+ *
+ * @return the integer value for this expression
+ */
+ public int getValue();
+ /**
+ *
+ * @return the negated form if this expression
+ */
+ public DiceExpression negate();
+ /**
+ *
+ * @return text form of this expression
+ */
+ public String getText();
+ /**
+ *
+ * @return text form of this expression, after executing
+ */
+ public String getTextDetail();
+ /**
+ * Executes this expression
+ */
+ public void exec();
+}
Added: trunk/src/openrpg2/common/dice/DiceParser.java
===================================================================
--- trunk/src/openrpg2/common/dice/DiceParser.java (rev 0)
+++ trunk/src/openrpg2/common/dice/DiceParser.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,540 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.io.StringReader;
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Parses a numeric dice expression<br/>
+ * A dice expression is a mathematical expression that uses standard 'd'
+ * notation to represent a die with a given number of sides, and use that
+ * in an arithmetic expression, such as 3d8+1, which will roll 3 8-sided dice,
+ * and add 1 to the result.<br/>
+ * There are numerous functions and die roll modifiers that can be applied as
+ * well.<br/>
+ * For example, the dice expression <tt>highest(4d6,3)</tt> rolls 4 6-sided dice
+ * and takes the highest 3 for a result.<br/>
+ * Additionally, dice expressions can have modifers, for example
+ * <tt>5d6.reroll(1)</tt> would roll 5 6-sided dice rerolling 1's.<br/>
+ * Supported functions are as follows
+ * <ul>
+ * <li>highest(dice, n) takes the highest 'n' dice out of the ones in the dice
+ * expression.</li>
+ * <li>lowest(dice, n) takes the lowest 'n' dice out of the ones in the dice
+ * expression</li>
+ * <li>until(expr,test) keeps rerolling dice in the given expression until the
+ * value of the expression satisfies the test expression provided, which can be
+ * the word "even", "odd", "any", a single number, or a range of numbers
+ * specified as start..end (either the start or end value
+ * may optionally be omitted, in which case either would default to a minimum
+ * or maximum value, as appropriate</li>
+ * <li>max(expr,expr...) results in the maximum of the expressions passed into
+ * it.</li>
+ * <li>min(expr,expr...) results in the maximum of the expressions passed into
+ * it.</li>
+ * <li>count(dice) returns the number of dice rolled</li>
+ * </ul>
+ * Supported dice modifiers are as follows
+ * <ul>
+ * <li>min(value) specifies the minimum value for any given die.
+ * If the value rolled is less than this, the minimum is taken</li>
+ * <li>max(value) specifies the maximum value for any given die.</li>
+ * <li>reroll(test) causes dice values that satisfy test to be rerolled (see
+ * description of 'until' function above for an outline of what forms are
+ * suitable for test)</li>
+ * <li>ignore(test) causes dice values that satisfy test to be ignored.</li>
+ * <li>change(test,expr) causes dice values that satisfy test to be changed to
+ * the given expression</li>
+ * <li>more(test,expr) When a die roll satisfies the test case, add more dice to
+ * those being rolled. The number of dice to roll is given by the expression
+ * provided (and may itself be a dice expression)</li>
+ * </ul>
+ * @author markt
+ */
+public class DiceParser {
+
+ static class CIString implements Comparable<CIString>
+ {
+ private String str;
+
+ CIString(String s)
+ {
+ str=s;
+ }
+
+ @Override
+ public String toString()
+ {
+ return str;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return str.toUpperCase().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ final CIString other = (CIString) obj;
+ if ((str == null) ? (other.str != null) : !str.equalsIgnoreCase(other.str))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public int compareTo(CIString o)
+ {
+ if (str==null && o.str==null)
+ {
+ return 0;
+ }
+ if (str==null)
+ {
+ return -1;
+ }
+ if (o==null)
+ {
+ return 1;
+ }
+ return str.compareToIgnoreCase(o.str);
+ }
+
+ }
+
+ static interface DieFunctionFactory {
+ public DieFunction create();
+ }
+
+ static interface FunctionFactory {
+ public Function create();
+ }
+
+ static Map<CIString,DieFunctionFactory> dieFunctions = new HashMap<CIString,DieFunctionFactory>();
+ static Map<CIString,FunctionFactory> functions = new HashMap<CIString,FunctionFactory>();
+
+ static {
+ dieFunctions.put(new CIString("min"), new DieFunctionFactory()
+ {
+ public DieFunction create()
+ {
+ return new MinDieFunc();
+ }
+ });
+ dieFunctions.put(new CIString("max"), new DieFunctionFactory()
+ {
+ public DieFunction create()
+ {
+ return new MaxDieFunc();
+ }
+ });
+ dieFunctions.put(new CIString("reroll"), new DieFunctionFactory()
+ {
+
+ public DieFunction create()
+ {
+ return new RerollDieFunc();
+ }
+ });
+ dieFunctions.put(new CIString("ignore"), new DieFunctionFactory()
+ {
+ public DieFunction create()
+ {
+ return new IgnoreDieFunc();
+ }
+ });
+ dieFunctions.put(new CIString("change"), new DieFunctionFactory()
+ {
+ public DieFunction create()
+ {
+ return new ChangeDieFunc();
+ }
+ });
+ dieFunctions.put(new CIString("more"), new DieFunctionFactory()
+ {
+ public DieFunction create()
+ {
+ return new MoreDieFunc();
+ }
+ });
+
+ functions.put(new CIString("min"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new MinFunc();
+ }
+ });
+ functions.put(new CIString("max"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new MaxFunc();
+ }
+ });
+ functions.put(new CIString("highest"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new HighestFunc();
+ }
+ });
+ functions.put(new CIString("lowest"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new LowestFunc();
+ }
+ });
+ functions.put(new CIString("until"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new UntilFunc();
+ }
+ });
+ functions.put(new CIString("dice"), new FunctionFactory()
+ {
+ public Function create()
+ {
+ return new DiceFunc();
+ }
+ });
+ }
+
+ /**
+ * Gets a test expression
+ * @param scanner Scanner to read from
+ * @return a test expression
+ * @throws ParseException on error
+ */
+ public static TestExpr getTest(Scanner scanner) throws ParseException
+ {
+ Object token = scanner.getToken();
+ TestExpr test =null;
+ if (token==Scanner.TINTEGER)
+ {
+ int start;
+ start = scanner.getIntValue();
+ scanner.scan();
+ if (scanner.getToken()==Scanner.TDOTDOT)
+ {
+ scanner.scan();
+ if(scanner.getToken()==Scanner.TINTEGER)
+ {
+ int end = scanner.getIntValue();
+ scanner.scan();
+ if ( end < start )
+ {
+ throw new ParseException("Second value cannot be before first",scanner.getLastPosition());
+ }
+ if ( end == start )
+ {
+ test = new Const(start);
+ }
+ else
+ {
+ test = new RangeTest(start,end);
+ }
+ }
+ else
+ {
+ test = new RangeTest(start,Integer.MAX_VALUE);
+ }
+ }
+ else
+ {
+ test = new Const(start);
+ }
+ }
+ else if (token==Scanner.TDOTDOT)
+ {
+ scanner.scan();
+ if(scanner.getToken()==Scanner.TINTEGER)
+ {
+ test=new RangeTest(Integer.MIN_VALUE,scanner.getIntValue());
+ scanner.scan();
+ }
+ else
+ {
+ test = new RangeTest(Integer.MIN_VALUE,Integer.MAX_VALUE);
+ }
+ }
+ else if (token==Scanner.TID)
+ {
+ if (scanner.getString().equalsIgnoreCase("any"))
+ {
+ test = new RangeTest(Integer.MIN_VALUE,Integer.MAX_VALUE);
+ scanner.scan();
+ }
+ else if (scanner.getString().equalsIgnoreCase("even"))
+ {
+ test = new EvenTest();
+ scanner.scan();
+ }
+ else if (scanner.getString().equalsIgnoreCase("odd"))
+ {
+ test = new OddTest();
+ scanner.scan();
+ }
+ }
+ if ( test==null )
+ {
+ throw new ParseException("Expected test value",scanner.getLastPosition());
+ }
+ return test;
+ }
+
+ /**
+ * Gets an expression
+ * @param scanner Scanner to read from
+ * @return the expression at the current position in the scanner
+ * @throws ParseException on error
+ */
+ public static DiceExpression getExpression(Scanner scanner) throws ParseException
+ {
+ DiceExpression expr = null;
+ expr = getTerm(scanner);
+ if(scanner.getToken()==Scanner.TPLUS || scanner.getToken()==Scanner.TMINUS)
+ {
+ SumExpr result = new SumExpr();
+ result.append(expr);
+ while(scanner.getToken()==Scanner.TPLUS || scanner.getToken()==Scanner.TMINUS)
+ {
+ if(scanner.getToken()==Scanner.TPLUS)
+ {
+ scanner.scan();
+ }
+ result.append(getTerm(scanner));
+ }
+ return result;
+ }
+ return expr;
+ }
+
+ /**
+ * Gets a single term expression
+ * @param scanner Scanner to read from
+ * @return a single term expression from the scanner
+ * @throws ParseException on error
+ */
+ public static DiceExpression getTerm(Scanner scanner) throws ParseException
+ {
+ DiceExpression expr = getFactor(scanner);
+ if(scanner.getToken()==Scanner.TSTAR || scanner.getToken()==Scanner.TSLASH)
+ {
+ ProdExpr result = new ProdExpr();
+ result.appendNum(expr);
+ while(scanner.getToken()==Scanner.TSTAR || scanner.getToken()==Scanner.TSLASH)
+ {
+ if(scanner.getToken()==Scanner.TSTAR)
+ {
+ scanner.scan();
+ result.appendNum(getFactor(scanner));
+ }
+ else
+ {
+ scanner.scan();
+ result.appendDen(getFactor(scanner));
+ }
+ }
+ return result;
+ }
+ return expr;
+ }
+
+ /**
+ * Gets a single factor
+ * @param scanner Scanner to read from
+ * @return a single factor from the scanner
+ * @throws ParseException on error
+ */
+ public static DiceExpression getFactor(Scanner scanner) throws ParseException
+ {
+ DiceExpression result;
+ boolean negate = false;
+ while (scanner.getToken()==Scanner.TMINUS)
+ {
+ negate=!negate;
+ scanner.scan();
+ }
+ result=getUnary(scanner);
+ if (negate)
+ {
+ result=result.negate();
+ }
+ return result;
+ }
+
+ /**
+ * Gets a unary expression from the scanner
+ * @param scanner the Scanner to read from
+ * @return the unary expression from the scanner
+ * @throws ParseException on error
+ */
+ public static DiceExpression getUnary(Scanner scanner) throws ParseException
+ {
+ if (scanner.getToken()==Scanner.TLEFT)
+ {
+ DiceExpression result;
+ scanner.scan();
+ result=getExpression(scanner);
+ if(scanner.getToken()!=Scanner.TRIGHT)
+ {
+ throw new ParseException("Expected ')'",scanner.getLastPosition());
+ }
+ scanner.scan();
+ return result;
+ }
+ else if (scanner.getToken()==Scanner.TDICE)
+ {
+ MultiDice result = new MultiDice(scanner.getIntValue(),scanner.getDiceValue());
+ scanner.scan();
+ while(scanner.getToken()==Scanner.TDOT)
+ {
+ scanner.scan();
+ if(scanner.getToken()!=Scanner.TID)
+ {
+ throw new ParseException("Expected function name",scanner.getLastPosition());
+ }
+ DieFunctionFactory factory = dieFunctions.get(new CIString(scanner.getString()));
+ if(factory==null)
+ {
+ throw new ParseException("Expected function name",scanner.getLastPosition());
+ }
+ DieFunction diefunc = factory.create();
+ scanner.scan();
+ if (scanner.getToken()!=Scanner.TLEFT)
+ {
+ throw new ParseException("Expected '('",scanner.getLastPosition());
+
+ }
+ scanner.scan();
+ boolean parse = diefunc.parse(scanner);
+ if (!parse)
+ {
+ throw new ParseException("Invalid Argument(s)",scanner.getLastPosition());
+ }
+ if (scanner.getToken()!=Scanner.TRIGHT)
+ {
+ throw new ParseException("Expected ')'",scanner.getLastPosition());
+ }
+ scanner.scan();
+ result.addModifier(diefunc);
+ }
+ return result;
+ }
+ else if (scanner.getToken()==Scanner.TINTEGER)
+ {
+ Const result = new Const(scanner.getIntValue());
+ scanner.scan();
+ return result;
+ }
+ else if (scanner.getToken()==Scanner.TID)
+ {
+ FunctionFactory factory=functions.get(new CIString(scanner.getString()));
+ if(factory==null)
+ {
+ throw new ParseException("Expected function name",scanner.getLastPosition());
+ }
+ Function result = factory.create();
+ scanner.scan();
+ if (scanner.getToken()!=Scanner.TLEFT)
+ {
+ throw new ParseException("Expected '('",scanner.getLastPosition());
+
+ }
+ scanner.scan();
+ boolean parse = result.parse(scanner);
+ if (!parse)
+ {
+ throw new ParseException("Invalid Argument(s)",scanner.getLastPosition());
+ }
+ if (scanner.getToken()!=Scanner.TRIGHT)
+ {
+ throw new ParseException("Expected ')'",scanner.getLastPosition());
+ }
+ scanner.scan();
+ return result;
+ }
+ else
+ {
+ throw new ParseException("Expected expression",scanner.getLastPosition());
+ }
+ }
+
+ /**
+ * Parses a string to retrieve a DiceExpression.
+ * @param s The string to parse
+ * @return a Dice Expression which represents what was in the string
+ * @throws ParseException
+ */
+ public static DiceExpression parse(String s) throws ParseException
+ {
+ Scanner scanner=new Scanner(new StringReader(s));
+ DiceExpression result=getExpression(scanner);
+ if ( scanner.getToken() != Scanner.TEOF )
+ {
+ throw new ParseException("Unexpected characters at end of expression",scanner.getLastPosition());
+ }
+ return result;
+ }
+
+ /**
+ * Test function
+ * @param args
+ * @throws ParseException on error
+ */
+ public static void main(String[] args) throws ParseException
+ {
+ String s="dice(until(3d8,3..18),until(3d8,3..18),until(3d8,3..18),until(3d8,3..18),until(3d8,3..18),until(3d8,3..18))";
+ DiceExpression express=parse(s);
+ for(int i=0;i<100;i++)
+ {
+ express.exec();
+ //System.out.print(express.getValue()+" ");
+ System.out.print('[');
+ int [] details=((MultiValue)express).getDetails();
+ for(int j=0;j<details.length;j++)
+ {
+ if ( j != 0 )
+ {
+ System.out.print(',');
+ }
+ if ( details[j] < 10 )
+ {
+ System.out.print(' ');
+ }
+ System.out.print(details[j]);
+ }
+ System.out.println(']');
+ }
+ }
+}
Added: trunk/src/openrpg2/common/dice/DieFunction.java
===================================================================
--- trunk/src/openrpg2/common/dice/DieFunction.java (rev 0)
+++ trunk/src/openrpg2/common/dice/DieFunction.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,305 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+
+
+/**
+ *
+ * @author markt
+ */
+public abstract class DieFunction
+{
+ private final String name;
+ /**
+ * Parameters for this dice function
+ */
+ protected ArrayList<DiceExpression> params = new ArrayList<DiceExpression>();
+
+ /**
+ * Constructor for DieFunction
+ * @param n name of die function
+ */
+ public DieFunction(String n)
+ {
+ name=n;
+ }
+
+ /**
+ *
+ * @return text form of the die function, plus parameters
+ */
+ public String getText()
+ {
+ StringBuilder result=new StringBuilder();
+ result.append(name+"(");
+ boolean comma=false;
+ for(DiceExpression i:params)
+ {
+ if(comma)
+ {
+ result.append(',');
+ }
+ else
+ {
+ comma=true;
+ }
+ result.append(i.getText());
+ }
+ result.append(')');
+ return result.toString();
+ }
+
+ /**
+ * Executes the die function
+ */
+ public void exec()
+ {
+ for(DiceExpression i:params)
+ {
+ i.exec();
+ }
+ }
+
+ /**
+ * Says what the new value of the currently rolled die should be
+ * @param orig original rolled value
+ * @param current rolled value
+ * @return new value
+ */
+ public int getAlteredValue(int orig,int current)
+ {
+ return current;
+ }
+
+ /**
+ * Tells how many more new dice should be rolled
+ * @param orig original rolled value
+ * @param current rolled value
+ * @return number of extra dice to roll
+ */
+ public int getNewDice(int orig,int current)
+ {
+ return 0;
+ }
+
+ /**
+ * DiceParser for the die function, parses each argument
+ * @param scanner Scanner being used to read input
+ * @return true if the function was parsed successfully, false otherwise
+ * @throws ParseException on error
+ */
+ public abstract boolean parse(Scanner scanner) throws ParseException;
+}
+class RerollDieFunc extends DieFunction
+{
+ public RerollDieFunc()
+ {
+ super("reroll");
+ }
+
+ @Override
+ public int getAlteredValue(int orig,int current)
+ {
+ TestExpr test = (TestExpr) params.get(0);
+ if (test.testValue(current))
+ {
+ return 0;
+ }
+ return current;
+ }
+
+ @Override
+ public int getNewDice(int orig,int current)
+ {
+ TestExpr test = (TestExpr) params.get(0);
+ if (test.testValue(current))
+ {
+ return 1;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ params.add(DiceParser.getTest(scanner));
+ return true;
+ }
+}
+
+class MinDieFunc extends DieFunction
+{
+ public MinDieFunc()
+ {
+ super("min");
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ DiceExpression expr = DiceParser.getExpression(scanner);
+ if ( expr != null )
+ {
+ params.add(expr);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getAlteredValue(int orig,int current)
+ {
+ int test = params.get(0).getValue();
+ if ( current < test )
+ {
+ return test;
+ }
+ return current;
+ }
+}
+
+class MaxDieFunc extends DieFunction
+{
+ public MaxDieFunc()
+ {
+ super("max");
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ DiceExpression expr = DiceParser.getExpression(scanner);
+ if ( expr != null )
+ {
+ params.add(expr);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getAlteredValue(int orig,int current)
+ {
+ int test = params.get(0).getValue();
+ if ( current > test )
+ {
+ return test;
+ }
+ return current;
+ }
+}
+
+class IgnoreDieFunc extends DieFunction
+{
+ public IgnoreDieFunc()
+ {
+ super("ignore");
+ }
+
+
+ @Override
+ public int getAlteredValue(int orig,int current)
+ {
+ TestExpr test = (TestExpr) params.get(0);
+ if (test.testValue(current))
+ {
+ return 0;
+ }
+ return current;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ params.add(DiceParser.getTest(scanner));
+ return true;
+ }
+
+}
+
+class ChangeDieFunc extends DieFunction
+{
+
+ public ChangeDieFunc()
+ {
+ super("change");
+ }
+
+ @Override
+ public int getAlteredValue(int orig,int current)
+ {
+ TestExpr test = (TestExpr) params.get(0);
+ if (test.testValue(current))
+ {
+ params.get(1).exec();
+ return params.get(1).getValue();
+ }
+ return current;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ params.add(DiceParser.getTest(scanner));
+ if ( scanner.getToken()!=Scanner.TCOMMA )
+ {
+ throw new ParseException("Expected ','",scanner.getLastPosition());
+ }
+ scanner.scan();
+ params.add(DiceParser.getExpression(scanner));
+ return true;
+ }
+
+}
+
+class MoreDieFunc extends DieFunction
+{
+
+ public MoreDieFunc()
+ {
+ super("more");
+ }
+
+ @Override
+ public int getNewDice(int orig,int current)
+ {
+ TestExpr test = (TestExpr) params.get(0);
+ if (test.testValue(current))
+ {
+ params.get(1).exec();
+ return params.get(1).getValue();
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ params.add(DiceParser.getTest(scanner));
+ if ( scanner.getToken()!=Scanner.TCOMMA )
+ {
+ throw new ParseException("Expected ','",scanner.getLastPosition());
+ }
+ scanner.scan();
+ params.add(DiceParser.getExpression(scanner));
+ return true;
+ }
+
+}
\ No newline at end of file
Added: trunk/src/openrpg2/common/dice/Function.java
===================================================================
--- trunk/src/openrpg2/common/dice/Function.java (rev 0)
+++ trunk/src/openrpg2/common/dice/Function.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,145 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+
+/**
+ *
+ * @author markt
+ */
+public abstract class Function implements DiceExpression {
+ /**
+ * parameters for the function
+ */
+ protected ArrayList<DiceExpression> params=new ArrayList<DiceExpression>();
+
+ private final String name;
+
+ /**
+ * Gets the text detail for one of the paremeters of the function
+ * @param index which parameter to examine
+ * @return the text detail for the index'th parameter to the function
+ */
+ public String getParameterTextDetail(int index)
+ {
+ return params.get(index).getTextDetail();
+
+ }
+ /**
+ *
+ * @return text form of this expression (after executing)
+ */
+ public String getTextDetail()
+ {
+ StringBuilder result=new StringBuilder();
+ result.append(name+"(");
+ for(int i=0; i< params.size();i++)
+ {
+ if (i!=0)
+ result.append(",");
+ result.append(getParameterTextDetail(i));
+ }
+ result.append(")");
+ if ( this instanceof UniValue )
+ {
+ result.append("->("+this.getValue()+")");
+ }
+ else if ( this instanceof MultiValue )
+ {
+ MultiValue val=(MultiValue)this;
+ result.append("->[");
+ for(int i=0;i<val.getDetails().length;i++)
+ {
+ if ( i > 0 )
+ {
+ result.append(',');
+ }
+ result.append(val.getDetails()[i]);
+ }
+ result.append("]");
+ }
+ return result.toString();
+ }
+
+ /**
+ *
+ * @return text form of this expression
+ */
+ public String getText()
+ {
+ StringBuilder result=new StringBuilder();
+ result.append(name+"(");
+ boolean comma=false;
+ for(DiceExpression i:params)
+ {
+ if(comma)
+ {
+ result.append(",");
+ }
+ else
+ {
+ comma=true;
+ }
+ result.append(i.getText());
+ }
+ result.append(")");
+ return result.toString();
+ }
+
+ /**
+ * executes the function
+ */
+ public void exec()
+ {
+ for(DiceExpression i:params)
+ {
+ i.exec();
+ }
+ run();
+ }
+
+ /**
+ * Function constructor
+ * @param n name of the function
+ */
+ public Function(String n)
+ {
+ name=n;
+ }
+
+ public DiceExpression negate()
+ {
+ return new NegExpr(this);
+ }
+
+ /**
+ * Parses the function
+ * @param scanner Scanner that is reading the input
+ * @return true if the function has been parsed, false otherwise
+ * @throws ParseException on error
+ */
+ public abstract boolean parse(Scanner scanner) throws ParseException;
+
+ /**
+ * Executes the function after the parameters have been processed
+ */
+ public abstract void run();
+}
+
+
Added: trunk/src/openrpg2/common/dice/MultiDice.java
===================================================================
--- trunk/src/openrpg2/common/dice/MultiDice.java (rev 0)
+++ trunk/src/openrpg2/common/dice/MultiDice.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,159 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+/**
+ *
+ * @author markt
+ */
+public class MultiDice implements DiceExpression, MultiValue {
+ private final static Random random = new Random();
+ private final int sides;
+ private final int count;
+ private int[] details;
+ private final ArrayList<DieFunction> modifiers = new ArrayList<DieFunction>();
+
+ public int getValue()
+ {
+ int result=0;
+ for(int i=0;i<details.length;i++ )
+ {
+ result+=details[i];
+ }
+ if ( count < 0 )
+ {
+ result=-result;
+ }
+ return result;
+ }
+
+ public int[] getDetails()
+ {
+ return details;
+ }
+
+ /**
+ * Executes this expression
+ */
+ public void exec()
+ {
+ ArrayList<Integer> list = new ArrayList<Integer>();
+ for(int i=0;i<Math.abs(count);i++ )
+ {
+ int c = random.nextInt(sides)+1;
+ int old=c;
+ for(DieFunction j:modifiers)
+ {
+ j.exec();
+ i-=j.getNewDice(old,c);
+ c=j.getAlteredValue(old,c);
+ if(c==0)
+ {
+ break;
+ }
+ }
+ if (c!=0)
+ {
+ list.add(new Integer(c));
+ }
+ }
+ details=new int[list.size()];
+ for(int i=0;i<details.length;i++)
+ {
+ details[i]=list.get(i).intValue();
+ }
+ }
+
+ /**
+ * Constructor for the multidice expression
+ * @param n number of dice to roll
+ * @param s number of sides for the dice
+ */
+ public MultiDice(int n,int s)
+ {
+ count=n;
+ sides=s;
+ details = new int[0];
+ }
+
+ /**
+ *
+ * @return text form of the expression
+ */
+ public String getText()
+ {
+ StringBuilder result=new StringBuilder();
+ if (count<0)
+ {
+ result.append('-');
+ }
+ if ( Math.abs(count) != 1 )
+ {
+ result.append(Math.abs(count));
+ }
+ result.append('d');
+ result.append(sides);
+ for(DieFunction j:modifiers)
+ {
+ result.append(".");
+ result.append(j.getText());
+ }
+ return result.toString();
+ }
+
+ /**
+ *
+ * @return detailed text form of the expression
+ */
+ public String getTextDetail()
+ {
+ StringBuilder result=new StringBuilder();
+ if (count<0)
+ {
+ result.append('-');
+ }
+ result.append("[");
+ if (details.length>0)
+ {
+ result.append(details[0]);
+ }
+ for(int i=1;i<details.length;i++)
+ {
+ result.append(",");
+ result.append(details[i]);
+ }
+ result.append("]");
+ return result.toString();
+ }
+
+ /**
+ * Adds a die function into this expression
+ * @param m DieFunction to add into the expression
+ */
+ public void addModifier(DieFunction m)
+ {
+ modifiers.add(m);
+ }
+
+ public DiceExpression negate()
+ {
+ return new NegExpr(this);
+ }
+}
Added: trunk/src/openrpg2/common/dice/MultiValue.java
===================================================================
--- trunk/src/openrpg2/common/dice/MultiValue.java (rev 0)
+++ trunk/src/openrpg2/common/dice/MultiValue.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,30 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+/**
+ *
+ * @author markt
+ */
+public interface MultiValue
+{
+ /**
+ *
+ * @return the values that this represents
+ */
+ public int[] getDetails();
+}
Added: trunk/src/openrpg2/common/dice/MultiValueFunction.java
===================================================================
--- trunk/src/openrpg2/common/dice/MultiValueFunction.java (rev 0)
+++ trunk/src/openrpg2/common/dice/MultiValueFunction.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,362 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.text.ParseException;
+import java.util.Arrays;
+
+
+/**
+ *
+ * @author markt
+ */
+public abstract class MultiValueFunction extends Function implements MultiValue
+{
+ public int getValue()
+ {
+ int[] array=getDetails();
+ int result=0;
+ for(int i=0;i<array.length;i++)
+ {
+ result+=array[i];
+ }
+ return result;
+ }
+
+ MultiValueFunction(String name)
+ {
+ super(name);
+ }
+}
+class DiceFunc extends MultiValueFunction
+{
+ public DiceFunc()
+ {
+ super("dice");
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ params.add(DiceParser.getExpression(scanner));
+ while(scanner.getToken()==Scanner.TCOMMA)
+ {
+ scanner.scan();
+ params.add(DiceParser.getExpression(scanner));
+ }
+ return true;
+ }
+
+ @Override
+ public void run()
+ {
+ }
+
+ public int[] getDetails()
+ {
+ int [] result=new int[params.size()];
+ for(int i=0;i<result.length;i++)
+ {
+ result[i]=params.get(i).getValue();
+ }
+ return result;
+ }
+
+ @Override
+ public String getTextDetail()
+ {
+ StringBuilder result=new StringBuilder();
+ result.append(']');
+ boolean comma=false;
+ for(DiceExpression i:params)
+ {
+ if(comma)
+ {
+ result.append(",");
+ }
+ else
+ {
+ comma=true;
+ }
+ result.append(i.getTextDetail());
+ }
+ result.append(']');
+ return result.toString();
+ }
+}
+
+class HighestFunc extends MultiValueFunction
+{
+ MultiValue param;
+ int [] details = new int[0];
+ HighestFunc()
+ {
+ super("highest");
+ }
+
+ public int[] getDetails()
+ {
+ return details;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ DiceExpression first = DiceParser.getExpression(scanner);
+ if(first instanceof MultiValue)
+ {
+ param = (MultiValue)first;
+ }
+ else
+ {
+ throw new ParseException("Not a compound value",scanner.getLastPosition());
+ }
+ params.add(first);
+ if(scanner.getToken()!=Scanner.TCOMMA)
+ {
+ throw new ParseException("Expected ','",scanner.getLastPosition());
+ }
+ scanner.scan();
+ if(scanner.getToken()!=Scanner.TINTEGER)
+ {
+ throw new ParseException("Expected integer",scanner.getLastPosition());
+ }
+ if(scanner.getIntValue()<0)
+ {
+ throw new ParseException("Cannot have < 0 dice",scanner.getLastPosition());
+ }
+ params.add(new Const(scanner.getIntValue()));
+ scanner.scan();
+ return true;
+ }
+
+ @Override
+ public void run()
+ {
+ int[] detailsSrc = param.getDetails();
+ int count = params.get(1).getValue();
+ details = new int[Math.min( count, detailsSrc.length )];
+ for(int i=0;i<details.length;i++)
+ {
+ details[i]=i;
+ }
+ int comp=0;
+ for(int k=0;k<details.length;k++)
+ {
+ if(detailsSrc[details[k]]<detailsSrc[details[comp]])
+ {
+ comp=k;
+ }
+ }
+ for(int i=details.length;i<detailsSrc.length;i++)
+ {
+ if (detailsSrc[i]>detailsSrc[details[comp]])
+ {
+ details[comp]=i;
+ for(int k=0;i<details.length;k++)
+ {
+ if(detailsSrc[details[k]]<detailsSrc[details[comp]])
+ {
+ comp=k;
+ }
+ }
+ }
+ }
+ Arrays.sort(details);
+ for(int i=0;i<details.length;i++)
+ {
+ details[i]=detailsSrc[details[i]];
+ }
+ }
+
+}
+
+class LowestFunc extends MultiValueFunction
+{
+ MultiValue param;
+ int [] details = new int[0];
+ LowestFunc()
+ {
+ super("lowest");
+ }
+
+ public int[] getDetails()
+ {
+ return details;
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ DiceExpression first = DiceParser.getExpression(scanner);
+ if(first instanceof MultiValue)
+ {
+ param = (MultiValue)first;
+ }
+ else
+ {
+ throw new ParseException("Not a compound value",scanner.getLastPosition());
+ }
+ params.add(first);
+ if(scanner.getToken()!=Scanner.TCOMMA)
+ {
+ throw new ParseException("Expected ','",scanner.getLastPosition());
+ }
+ scanner.scan();
+ if(scanner.getToken()!=Scanner.TINTEGER)
+ {
+ throw new ParseException("Expected integer",scanner.getLastPosition());
+ }
+ if(scanner.getIntValue()<0)
+ {
+ throw new ParseException("Cannot have < 0 dice",scanner.getLastPosition());
+ }
+ params.add(new Const(scanner.getIntValue()));
+ scanner.scan();
+ return true;
+ }
+
+ @Override
+ public void run()
+ {
+ int[] detailsSrc = param.getDetails();
+ int count = params.get(1).getValue();
+ details = new int[Math.min( count, detailsSrc.length )];
+ for(int i=0;i<details.length;i++)
+ {
+ details[i]=i;
+ }
+ int comp=0;
+ for(int k=0;k<details.length;k++)
+ {
+ if(detailsSrc[details[k]]>detailsSrc[details[comp]])
+ {
+ comp=k;
+ }
+ }
+ for(int i=details.length;i<detailsSrc.length;i++)
+ {
+ if (detailsSrc[i]<detailsSrc[details[comp]])
+ {
+ details[comp]=i;
+ for(int k=0;i<details.length;k++)
+ {
+ if(detailsSrc[details[k]]>detailsSrc[details[comp]])
+ {
+ comp=k;
+ }
+ }
+ }
+ }
+ Arrays.sort(details);
+ for(int i=0;i<details.length;i++)
+ {
+ details[i]=detailsSrc[details[i]];
+ }
+ }
+}
+
+class UntilFunc extends MultiValueFunction
+{
+ private static final int[] empty = new int[0];
+ boolean counting;
+
+ public UntilFunc()
+ {
+ super("until");
+ }
+
+ public String getParameterTextDetail(int index)
+ {
+ if (index==1 && counting)
+ return "#" + super.getParameterTextDetail(index);
+ else
+ return super.getParameterTextDetail(index);
+
+ }
+
+ @Override
+ public boolean parse(Scanner scanner) throws ParseException
+ {
+ counting = false;
+ params.add(DiceParser.getExpression(scanner));
+ if ( scanner.getToken()!=Scanner.TCOMMA )
+ {
+ throw new ParseException("Expected ','",scanner.getLastPosition());
+ }
+ scanner.scan();
+ if (scanner.getToken()==Scanner.THATCH)
+ {
+ scanner.scan();
+ counting = true;
+ }
+ params.add(DiceParser.getTest(scanner));
+ return true;
+ }
+
+ private int getTestValue(DiceExpression test)
+ {
+ if (counting)
+ {
+ if (test instanceof MultiValue)
+ {
+ return ((MultiValue)test).getDetails().length;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ return test.getValue();
+ }
+ }
+
+ @Override
+ public void exec()
+ {
+ do
+ {
+ params.get(0).exec();
+ params.get(1).exec();
+ }
+ while (!((TestExpr)params.get(1)).testValue(getTestValue(params.get(0))));
+ run();
+ }
+
+ @Override
+ public void run()
+ {
+ }
+
+ @Override
+ public int getValue()
+ {
+ return params.get(0).getValue();
+ }
+
+ public int[] getDetails()
+ {
+ if ( params.get(0) instanceof MultiValue )
+ {
+ return ((MultiValue)params.get(0)).getDetails();
+ }
+ return empty;
+ }
+
+}
\ No newline at end of file
Added: trunk/src/openrpg2/common/dice/NegExpr.java
===================================================================
--- trunk/src/openrpg2/common/dice/NegExpr.java (rev 0)
+++ trunk/src/openrpg2/common/dice/NegExpr.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,73 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+/**
+ *
+ * @author markt
+ */
+public class NegExpr implements DiceExpression,UniValue {
+ private final DiceExpression base;
+
+ public int getValue()
+ {
+ return -base.getValue();
+ }
+
+ public String getText()
+ {
+ if ( base instanceof SumExpr || base instanceof ProdExpr || base instanceof NegExpr )
+ {
+ return "-("+base.getText()+")";
+ }
+ else
+ {
+ return "-"+base.getText();
+ }
+ }
+
+ public String getTextDetail()
+ {
+ if ( base instanceof SumExpr || base instanceof ProdExpr || base instanceof NegExpr )
+ {
+ return "-("+base.getTextDetail()+")";
+ }
+ else
+ {
+ return "-"+base.getTextDetail();
+ }
+ }
+
+ public void exec()
+ {
+ base.exec();
+ }
+
+ /**
+ * Constructor for NegExpr
+ * @param e expression to negate
+ */
+ public NegExpr(DiceExpression e)
+ {
+ base = e;
+ }
+
+ public DiceExpression negate()
+ {
+ return base;
+ }
+}
Added: trunk/src/openrpg2/common/dice/ProdExpr.java
===================================================================
--- trunk/src/openrpg2/common/dice/ProdExpr.java (rev 0)
+++ trunk/src/openrpg2/common/dice/ProdExpr.java 2013-09-18 23:07:11 UTC (rev 102)
@@ -0,0 +1,205 @@
+/*
+ * ====================================================================
+ * Copyright (C) 2005-2006 The OpenRPG Project (www.openrpg.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License on www.gnu.org for more details.
+ * ====================================================================
+ */
+
+package openrpg2.common.dice;
+
+import java.util.ArrayList;
+
+/**
+ *
+ * @author markt
+ */
+public class ProdExpr implements DiceExpression,UniValue
+{
+ private ArrayList<DiceExpression> numerator = new ArrayList<DiceExpression>();
+ private ArrayList<DiceExpression> denominator = new ArrayList<DiceExpression>();
+
+ public int getValue()
+ {
+ int result=1;
+ for(DiceExpression j:numerator)
+ {
+ result*=j.getValue();
+ }
+ for(DiceExpression j:denominator)
+ {
+ result/=j.getValue();
+ }
+ return result;
+ }
+
+ public String getText()
+ {
+ StringBuilder result=new StringBuilder();
+ boolean product=false;
+ for(DiceExpression j:numerator)
+ {
+ if (product)
+ {
+ result.append('*');
+ }
+ else
+ {
+ product=true;
+ }
+ if (j instanceof SumExpr || j instanceof ProdExpr)
+ {
+ result.append('(');
+ result.append(j.getText());
+ result.append(')');
+ }
+ else
+ {
+ result.append(j.getText());
+ }
+ }
+ if (denominator.size()>0)
+ {
+ result.append('/');
+ if (denominator.size()>1)
+ {
+ result.append('(');
+ }
+ for(DiceExpression j:denominator)
+ {
+ if (product)
+ {
+ result.append('*');
+ }
+ else
+ {
+ product=true;
+ }
+ if (j instanceof SumExpr)
+ {
+ result.append('(');
+ result.append(j.getText());
+ result.append(')');
+ }
+ else
+ {
+ result.append(j.getText());
+ }
+ }
+ if (denominator.size()>1)
+ {
+ result.append(')');
+ }
+ }
+ return result.toString();
+ }
+
+ public String getTextDetail()
+ {
+ StringBuilder result=new StringBuilder();
+ boolean product=false;
+ for(DiceExpression j:numerator)
+ {
+ if (product)
+ {
+ result.append('*');
+ }
+ else
+ {
+ ...
[truncated message content] |