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
139
140
141
142
143
144
145
|
package bjc.dicelang.dicev2;
import java.util.Random;
/**
* A dice where both the number of dice to roll and the number of sides of the
* dice are specified by other dice.
*
* @author Ben Culkin
*
*/
public class CompositeDie extends Die {
/**
* The die that provides the number of dice to roll.
*/
public final Die numDice;
/**
* The die that provides the number of sides of the dice to roll.
*/
public final Die numSides;
/**
* Should the number of sides per dice be rerolled after every dice is rolled?
*
* By default, the number of sides will be rolled once per roll of this die.
*/
public final boolean rerollSides;
/**
* Create a new composite dice that rolls the number of sides once.
*
* @param numDice
* The number of dice to roll.
* @param numSides
* The number of sides on the dice.
*/
public CompositeDie(Die numDice, Die numSides) {
this(numDice, numSides, false);
}
/**
* Create a new composite dice with the specified side-rolling behavior.
*
* @param numDice
* The number of dice to roll.
* @param numSides
* The number of sides on the dice.
* @param rerollSides
* Whether to rolls the sides once per roll, or once per
* dice.
*/
public CompositeDie(Die numDice, Die numSides, boolean rerollSides) {
super();
this.numDice = numDice;
this.numSides = numSides;
this.rerollSides = rerollSides;
}
/**
* Create a new composite dice using a specific RNG, rolling dice one per side.
*
* @param rnd
* The RNG to use.
* @param numDice
* The number of dice to use.
* @param numSides
* The number of sides for the dice.
*/
public CompositeDie(Random rnd, Die numDice, Die numSides) {
this(rnd, numDice, numSides, false);
}
/**
* Create a new composite dice using a specific RNG and side-rolling behavior.
*
* @param rnd
* The RNG to use.
* @param numDice
* The number of dice to use.
* @param numSides
* The number of sides on the dice.
* @param rerollSides
* Whether to rolls the sides once per roll, or once per
* dice.
*/
public CompositeDie(Random rnd, Die numDice, Die numSides, boolean rerollSides) {
super(rnd);
this.numDice = numDice;
this.numSides = numSides;
this.rerollSides = rerollSides;
}
@Override
public long[] roll() {
int target = (int) numDice.rollSingle();
int sides = (int) numSides.rollSingle();
long[] res = new long[target];
for (int i = 0; i < target; i++) {
res[i] = rng.nextInt(sides) + 1;
if (rerollSides)
sides = (int) numSides.rollSingle();
}
return res;
}
@Override
public long rollSingle() {
return rng.nextInt((int) numSides.rollSingle());
}
@Override
public boolean canOptimize() {
if (numSides.canOptimize()) {
if (numSides.optimize() <= 1) {
return true;
}
}
if (numDice.canOptimize()) {
if (numDice.optimize() == 0) {
return true;
}
}
return false;
}
@Override
public long optimize() {
if (numDice.canOptimize())
return 0;
if (numSides.canOptimize() && numSides.optimize() == 0)
return 0;
return numDice.rollSingle();
}
}
|