Skip to content

Commit a1a9789

Browse files
committed
split results into 'results' and 'discarded'
feels like these are distinct things, so they should be put into distinct bins. it also felt awkward to always remember when performing operations on 'results' that some of those need to be skipped due to being discarded.
1 parent 95f435d commit a1a9789

File tree

6 files changed

+149
-121
lines changed

6 files changed

+149
-121
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@ Roll results have changed significantly (again). It's amazing what having users
1111
- remove metadata & score from RollResult
1212
- rather than simple list of Integers representing the output of a roll or operation, now each
1313
die rolled is a 'RolledDie' object which has the metadata/score.
14-
- RollResult.results will include both discarded an not-discarded RolledDie. TODO: change?
14+
- the RollResult's results field changes from List<int> to List<RolledDie>. RolledDie represents not just the
15+
outcome of the roll, but also includes metadata about the type of die, nsides of the die (if polyhedral die),
16+
and metadata about the dice expression's modification of the rolls.
17+
- RollResult.results will include both discarded an not-discarded RolledDie.
18+
- RollSummary.results is just not-discarded die, there's a separate RollSummary.discarded. Alternatively, look at
19+
RollSummary.detailedResults.results to see the whole set of die that accumulated while evaluating the expression.
1520

1621
# 7.1.1
1722

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ void main() {
3838

3939
* advantage
4040
* `2d20-L` -- drop lowest
41-
* `2d20k`, `2d20kh` -- keep highest
41+
* `2d20k`, or `2d20kh` -- keep highest
4242
* disadvantage
4343
* `2d20-H` -- drop highest
4444
* `2d20-kl` -- keep lowest
@@ -141,6 +141,7 @@ void main() {
141141
* `(5d6+5d10)-L2` -- roll 5d6 and 5d10, and from aggregate results drop the lowest 2.
142142
* `5d6+5d10-L2` -- roll 5d6 and 5d10, and from only the 5d10 results drop the lowest 2. equivalent to
143143
`5d6+(5d10-L2)`
144+
* `((1d6 + 1d8)-L)!` -- roll 1d6 and 1d8, drop the lowest result, and explode the remaining die
144145
* `*` for multiplication
145146
* `-` for subtraction
146147
* numbers must be integers
@@ -168,9 +169,7 @@ final roll = diceExpr_SecureRNG.roll();
168169
169170
//....
170171
// when dice expr changes, update the stats graph.
171-
final stats = await
172-
diceExpr_FastRNG.stats
173-
();
172+
final stats = await diceExpr_FastRNG.stats();
174173
// output of stats: {mean: 6.98, stddev: 2.41, min: 2, max: 12, count: 10000, histogram: {2: 310, 3: 557, 4: 787, 5: 1090, 6: 1450, 7: 1646, 8: 1395, 9: 1147, 10: 825, 11: 526, 12: 267}}
175174
176175
```

lib/src/ast.dart

Lines changed: 40 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -181,26 +181,23 @@ class CountOp extends Binary {
181181
}
182182
}
183183

184-
final filteredResults = lhs.results.notDiscarded.where(test);
184+
final filteredResults = lhs.results.where(test);
185185

186186
if (countType == CountType.count) {
187187
// if counting, the count becomes the new result
188188

189189
return RollResult(
190190
expression: toString(),
191191
opType: OpType.count,
192-
results: [
193-
RolledDie.singleVal(result: filteredResults.length),
194-
...lhs.results.notDiscarded.map(RolledDie.discard),
195-
...lhs.results.discarded,
196-
],
192+
results: [RolledDie.singleVal(result: filteredResults.length)],
193+
discarded: [...lhs.results.map(RolledDie.discard), ...lhs.discarded],
197194
left: lhs,
198195
right: rhs,
199196
);
200197
} else {
201198
// if counting success/failures, the results are updated w/ scoring
202199

203-
final otherResults = lhs.results.notDiscarded.whereNot(test);
200+
final nonScoredResults = lhs.results.whereNot(test);
204201

205202
return RollResult(
206203
expression: toString(),
@@ -209,9 +206,9 @@ class CountOp extends Binary {
209206
...filteredResults.map(
210207
(v) => RolledDie.scoreForCountType(v, countType: countType),
211208
),
212-
...otherResults,
213-
...lhs.results.discarded,
209+
...nonScoredResults,
214210
],
211+
discarded: lhs.discarded,
215212
left: lhs,
216213
right: rhs,
217214
);
@@ -238,23 +235,22 @@ class DropOp extends Binary {
238235

239236
final Iterable<RolledDie> results;
240237
final Iterable<RolledDie> dropped;
241-
final notDiscarded = lhs.results.notDiscarded;
242238
switch (name) {
243239
case '-<': // drop <
244-
results = notDiscarded.where((v) => v.result >= target);
245-
dropped = notDiscarded.where((v) => v.result < target);
240+
results = lhs.results.where((v) => v.result >= target);
241+
dropped = lhs.results.where((v) => v.result < target);
246242
case '-<=': // drop <=
247-
results = notDiscarded.where((v) => v.result > target);
248-
dropped = notDiscarded.where((v) => v.result <= target);
243+
results = lhs.results.where((v) => v.result > target);
244+
dropped = lhs.results.where((v) => v.result <= target);
249245
case '->': // drop >
250-
results = notDiscarded.where((v) => v.result <= target);
251-
dropped = notDiscarded.where((v) => v.result > target);
246+
results = lhs.results.where((v) => v.result <= target);
247+
dropped = lhs.results.where((v) => v.result > target);
252248
case '->=': // drop >=
253-
results = notDiscarded.where((v) => v.result < target);
254-
dropped = notDiscarded.where((v) => v.result >= target);
249+
results = lhs.results.where((v) => v.result < target);
250+
dropped = lhs.results.where((v) => v.result >= target);
255251
case '-=': // drop =
256-
results = notDiscarded.where((v) => v.result != target);
257-
dropped = notDiscarded.where((v) => v.result == target);
252+
results = lhs.results.where((v) => v.result != target);
253+
dropped = lhs.results.where((v) => v.result == target);
258254
default:
259255
throw FormatException(
260256
"unknown drop operation '$name'",
@@ -266,11 +262,8 @@ class DropOp extends Binary {
266262
return RollResult(
267263
expression: toString(),
268264
opType: OpType.drop,
269-
results: [
270-
...results,
271-
...dropped.map(RolledDie.discard),
272-
...lhs.results.discarded,
273-
],
265+
results: [...results],
266+
discarded: [...dropped.map(RolledDie.discard), ...lhs.discarded],
274267
left: lhs,
275268
right: rhs,
276269
);
@@ -285,7 +278,7 @@ class DropHighLowOp extends Binary {
285278
RollResult eval() {
286279
final lhs = left();
287280
final rhs = right();
288-
final sorted = lhs.results.notDiscarded.toList()..sort();
281+
final sorted = lhs.results.toList()..sort();
289282
final numToDrop = rhs.totalOrDefault(() => 1); // if missing, assume '1'
290283
final Iterable<RolledDie> results;
291284
final Iterable<RolledDie> dropped;
@@ -315,11 +308,8 @@ class DropHighLowOp extends Binary {
315308
return RollResult(
316309
expression: toString(),
317310
opType: OpType.drop,
318-
results: [
319-
...results,
320-
...dropped.map(RolledDie.discard),
321-
...lhs.results.discarded,
322-
],
311+
results: [...results],
312+
discarded: [...dropped.map(RolledDie.discard), ...lhs.discarded],
323313
left: lhs,
324314
right: rhs,
325315
);
@@ -343,7 +333,7 @@ class ClampOp extends Binary {
343333
});
344334

345335
final newResults = <RolledDie>[];
346-
for (final d in lhs.results.notDiscarded) {
336+
for (final d in lhs.results) {
347337
if (name == 'c>' && d.result > target) {
348338
newResults.add(RolledDie.copyWith(d, result: target, clampHigh: true));
349339
} else if (name == 'c<' && d.result < target) {
@@ -355,7 +345,8 @@ class ClampOp extends Binary {
355345
return RollResult(
356346
expression: toString(),
357347
opType: OpType.clamp,
358-
results: [...newResults, ...lhs.results.discarded],
348+
results: newResults,
349+
discarded: lhs.discarded,
359350
left: lhs,
360351
right: rhs,
361352
);
@@ -459,6 +450,7 @@ class D66Dice extends UnaryDice {
459450
RollResult eval() {
460451
final lhs = left();
461452
final ndice = lhs.totalOrDefault(() => 1);
453+
// TODO: capture the rolls as discarded.
462454
final results = [
463455
for (var i = 0; i < ndice; i++)
464456
roller.roll(1, 6).total * 10 + roller.roll(1, 6).total,
@@ -563,7 +555,7 @@ class RerollDice extends BinaryDice {
563555
}
564556

565557
final results = <RolledDie>[];
566-
lhs.results.notDiscarded.forEachIndexed((i, v) {
558+
lhs.results.forEachIndexed((i, v) {
567559
if (test(v)) {
568560
RolledDie rerolled;
569561
var rerollCount = 0;
@@ -584,7 +576,8 @@ class RerollDice extends BinaryDice {
584576
return RollResult(
585577
expression: toString(),
586578
opType: OpType.reroll,
587-
results: [...results, ...lhs.results.discarded],
579+
results: results,
580+
discarded: lhs.discarded,
588581
left: lhs,
589582
right: rhs,
590583
);
@@ -638,7 +631,8 @@ class CompoundingDice extends BinaryDice {
638631
}
639632

640633
final results = <RolledDie>[];
641-
lhs.results.notDiscarded.forEachIndexed((i, v) {
634+
final discarded = <RolledDie>[];
635+
lhs.results.forEachIndexed((i, v) {
642636
if (test(v)) {
643637
var sum = v.result;
644638
RolledDie rerolled;
@@ -647,10 +641,13 @@ class CompoundingDice extends BinaryDice {
647641
rerolled = roller
648642
.roll(1, v.nsides, '(compound ind $i, #$numCompounded)')
649643
.results[0];
644+
discarded.add(
645+
RolledDie.copyWith(rerolled, discarded: true, compounded: true),
646+
);
650647
sum += rerolled.result;
651648
numCompounded++;
652649
} while (test(rerolled) && numCompounded < limit);
653-
results.add(RolledDie.copyWith(v, result: sum, compounded: true));
650+
results.add(RolledDie.copyWith(v, result: sum, compoundedFinal: true));
654651
} else {
655652
results.add(v);
656653
}
@@ -659,7 +656,8 @@ class CompoundingDice extends BinaryDice {
659656
return RollResult(
660657
expression: toString(),
661658
opType: OpType.compound,
662-
results: [...results, ...lhs.results.discarded],
659+
results: results,
660+
discarded: lhs.discarded + discarded,
663661
left: lhs,
664662
right: rhs,
665663
);
@@ -713,27 +711,24 @@ class ExplodingDice extends BinaryDice {
713711
}
714712

715713
final newResults = <RolledDie>[];
716-
for (final rolledDie in lhs.results.notDiscarded.where(test)) {
714+
for (final rolledDie in lhs.results.where(test)) {
715+
newResults.add(RolledDie.copyWith(rolledDie, exploded: true));
717716
var numExplosions = 0;
718717
RolledDie rerolledDie;
719718
do {
720719
rerolledDie = roller
721720
.roll(1, rolledDie.nsides, '(explode #${numExplosions + 1})')
722721
.results[0];
723722
numExplosions++;
724-
newResults.add(RolledDie.copyWith(rolledDie, exploded: true));
725723
newResults.add(RolledDie.copyWith(rerolledDie, explosion: true));
726724
} while (test(rerolledDie) && numExplosions < limit);
727725
}
728726

729727
return RollResult(
730728
expression: toString(),
731729
opType: OpType.explode,
732-
results: [
733-
...newResults,
734-
...lhs.results.notDiscarded.whereNot(test),
735-
...lhs.results.discarded,
736-
],
730+
results: [...newResults, ...lhs.results.whereNot(test)],
731+
discarded: lhs.discarded,
737732
left: lhs,
738733
right: rhs,
739734
);

lib/src/parser.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import 'ast.dart';
44
import 'dice_expression.dart';
55
import 'dice_roller.dart';
66

7+
// TODO: support commas `(<expr>,<expr>,<expr>)kh` -- evaluate each subexpression into a new die result, discarding the ones that had been combined
8+
79
Parser<DiceExpression> parserBuilder(DiceRoller roller) {
810
final builder = ExpressionBuilder<DiceExpression>();
911
// numbers

0 commit comments

Comments
 (0)