summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/ComplexDice.java
blob: 81699ae25e75ca7f7aefe63f7aac45ab77d84e28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package bjc.dicelang;

/**
 * Implements a collection of one or more of a particular die, where the
 * number of dice in the group is variable.
 * 
 * @author ben
 *
 */
public class ComplexDice implements IDiceExpression {
	/**
	 * Create a dice from a string expression
	 * 
	 * @param expression
	 *            The string to parse the dice from
	 * @return A dice group parsed from the string
	 */
	public static IDiceExpression fromString(String expression) {
		// Handle the case where someone passes us a simple expression
		// containing a single die
		if (!expression.contains("d")) {
			return new Die(Integer.parseInt(expression));
		}

		// Split it on the dice type marker

		String[] strangs = expression.split("d");

		try {
			// Create the actual group of dice
			return new ComplexDice(
					new ScalarDie(Integer.parseInt(strangs[0])),
					new Die(Integer.parseInt(strangs[1])));
		} catch (NumberFormatException nfex) {
			// We don't care about details

			// Tell the user the expression is invalid
			throw new IllegalArgumentException(
					"Attempted to create a set of dice using invalid arguments."
							+ " They must be integers. " + strangs[0]
							+ " and " + strangs[1]
							+ " are likely culprits.");
		}
	}

	/*
	 * The die being rolled
	 */
	private IDiceExpression	die;

	/*
	 * The number of the particular die to roll
	 */
	private IDiceExpression	nDice;

	/**
	 * Create a new collection of dice
	 * 
	 * @param nDce
	 *            The number of dice in the collection
	 * @param de
	 *            The type of dice the collection is composed of
	 */
	public ComplexDice(IDiceExpression nDce, IDiceExpression de) {
		nDice = nDce;
		die = de;
	}

	/**
	 * Create a new collection of dice
	 * 
	 * @param nSides
	 *            The number of dice in the collection
	 * @param de
	 *            The type of dice the collection is composed of
	 */
	public ComplexDice(int nSides, int de) {
		nDice = new ScalarDie(nSides);
		die = new Die(de);
	}

	@Override
	public boolean canOptimize() {
		// Can only optimize this dice group if both components can be
		// optimized and the die itself has only one value
		if (nDice.canOptimize() && die.canOptimize()) {
			return die.optimize() == 1;
		}

		return false;
	}

	@Override
	public int optimize() {
		if (!canOptimize()) {
			throw new UnsupportedOperationException(
					"This complex dice cannot be optimized. "
							+ "Both the dice to be rolled and the number of"
							+ " dice must be optimizable.");
		}

		return nDice.optimize();
	}

	@Override
	public int roll() {
		int res = 0;

		/*
		 * Add the results of rolling each die
		 */
		int nRoll = nDice.roll();

		if (nRoll < 0) {
			throw new UnsupportedOperationException(
					"Attempted to roll a negative number of dice. "
							+ "The problematic expression is " + nDice);
		}

		// Roll all the dice and combine them
		for (int i = 0; i < nRoll; i++) {
			res += die.roll();
		}

		return res;
	}

	@Override
	public String toString() {
		// Print simple dice groups in a much clearer manner
		if (nDice instanceof ScalarDie && die instanceof Die) {
			return nDice.toString() + die.toString();
		}

		return "complex[n=" + nDice.toString() + ", d=" + die.toString()
				+ "]";
	}
}