@yipe/dice 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/builder/ac.d.ts +25 -0
  2. package/dist/builder/ac.d.ts.map +1 -0
  3. package/dist/builder/ast.d.ts +9 -0
  4. package/dist/builder/ast.d.ts.map +1 -0
  5. package/dist/builder/attack.d.ts +41 -0
  6. package/dist/builder/attack.d.ts.map +1 -0
  7. package/dist/builder/d20.d.ts +6 -0
  8. package/dist/builder/d20.d.ts.map +1 -0
  9. package/dist/builder/dc.d.ts +26 -0
  10. package/dist/builder/dc.d.ts.map +1 -0
  11. package/dist/builder/example.d.ts +356 -0
  12. package/dist/builder/example.d.ts.map +1 -0
  13. package/dist/builder/factory.d.ts +17 -0
  14. package/dist/builder/factory.d.ts.map +1 -0
  15. package/dist/builder/index.cjs +106 -0
  16. package/dist/builder/index.cjs.map +1 -1
  17. package/dist/builder/index.d.ts +8 -379
  18. package/dist/builder/index.d.ts.map +1 -0
  19. package/dist/builder/index.js +105 -1
  20. package/dist/builder/index.js.map +1 -1
  21. package/dist/builder/nodes.d.ts +61 -0
  22. package/dist/builder/nodes.d.ts.map +1 -0
  23. package/dist/builder/prob.d.ts +3 -0
  24. package/dist/builder/prob.d.ts.map +1 -0
  25. package/dist/builder/roll.d.ts +205 -0
  26. package/dist/builder/roll.d.ts.map +1 -0
  27. package/dist/builder/save.d.ts +19 -0
  28. package/dist/builder/save.d.ts.map +1 -0
  29. package/dist/builder/types.d.ts +66 -0
  30. package/dist/builder/types.d.ts.map +1 -0
  31. package/dist/common/bounce.d.ts +32 -0
  32. package/dist/common/bounce.d.ts.map +1 -0
  33. package/dist/common/errors.d.ts +26 -0
  34. package/dist/common/errors.d.ts.map +1 -0
  35. package/dist/common/lru-cache.d.ts +17 -0
  36. package/dist/common/lru-cache.d.ts.map +1 -0
  37. package/dist/common/types.d.ts +65 -0
  38. package/dist/common/types.d.ts.map +1 -0
  39. package/dist/index.d.ts +9 -111
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/parser/dice.d.ts +70 -0
  42. package/dist/parser/dice.d.ts.map +1 -0
  43. package/dist/parser/parser.d.ts +14 -0
  44. package/dist/parser/parser.d.ts.map +1 -0
  45. package/dist/pmf/mixture.d.ts +37 -0
  46. package/dist/pmf/mixture.d.ts.map +1 -0
  47. package/dist/pmf/pmf.d.ts +380 -0
  48. package/dist/pmf/pmf.d.ts.map +1 -0
  49. package/dist/{pmf-D5VRghZI.d.ts → pmf/query.d.ts} +6 -464
  50. package/dist/pmf/query.d.ts.map +1 -0
  51. package/package.json +16 -15
  52. package/.claude/worktrees/amazing-matsumoto-27220c/LICENSE +0 -21
  53. package/.claude/worktrees/amazing-matsumoto-27220c/README.md +0 -518
  54. package/.claude/worktrees/vibrant-lovelace-0cc9e7/LICENSE +0 -21
  55. package/.claude/worktrees/vibrant-lovelace-0cc9e7/README.md +0 -518
  56. package/.claude/worktrees/wizardly-mclean-e375de/LICENSE +0 -21
  57. package/.claude/worktrees/wizardly-mclean-e375de/README.md +0 -518
  58. package/CHANGELOG.md +0 -224
  59. package/dist/builder/index.d.cts +0 -379
  60. package/dist/index.d.cts +0 -111
  61. package/dist/pmf-D5VRghZI.d.cts +0 -1129
@@ -1,379 +1,8 @@
1
- import { b as RollType, P as PMF, l as DiceQuery, C as CritConfig, L as LRUCache } from '../pmf-D5VRghZI.js';
2
-
3
- type RollFactory = {
4
- (count: number, sides?: number, modifier?: number): RollBuilder;
5
- (count: number, die: RollBuilder, modifier?: number): RollBuilder;
6
- d(sides: number | string): RollBuilder;
7
- hd20(): RollBuilder;
8
- d4(): RollBuilder;
9
- d6(): RollBuilder;
10
- d8(): RollBuilder;
11
- d10(): RollBuilder;
12
- d12(): RollBuilder;
13
- d20(): RollBuilder;
14
- d100(): RollBuilder;
15
- flat(n: number): RollBuilder;
16
- };
17
- type KeepMode = "highest" | "lowest";
18
- type RollConfig = {
19
- count: number;
20
- sides: number;
21
- modifier: number;
22
- reroll: number;
23
- explode: number;
24
- minimum: number;
25
- bestOf: number;
26
- keep: {
27
- total: number;
28
- count: number;
29
- mode: KeepMode;
30
- } | undefined;
31
- rollType: RollType;
32
- isSubtraction?: boolean;
33
- };
34
- type Resolution = {
35
- pmf: PMF;
36
- check: PMF;
37
- weights: {
38
- [key: string]: number;
39
- };
40
- };
41
- type AttackResolution = Resolution & {
42
- hit: PMF;
43
- crit: PMF;
44
- miss: PMF;
45
- weights: {
46
- hit: number;
47
- crit: number;
48
- miss: number;
49
- };
50
- };
51
- type SaveResolution = Resolution & {
52
- saveFail: PMF;
53
- saveSuccess: PMF;
54
- weights: {
55
- success: number;
56
- fail: number;
57
- };
58
- };
59
- interface CheckBuilder {
60
- resolve(eps?: number): Resolution;
61
- toExpression(): string;
62
- readonly pmf: PMF;
63
- }
64
-
65
- type SaveOutcome = "normal" | "half";
66
- declare class SaveBuilder implements CheckBuilder {
67
- readonly check: DCBuilder;
68
- private readonly failureEffect?;
69
- private readonly saveOutcome;
70
- constructor(check: DCBuilder, failureEffect?: RollBuilder | undefined, saveOutcome?: SaveOutcome);
71
- saveHalf(): SaveBuilder;
72
- toExpression(): string;
73
- resolve(eps?: number): SaveResolution;
74
- toPMF(eps?: number): PMF;
75
- get pmf(): PMF;
76
- toQuery(eps?: number): DiceQuery;
77
- }
78
-
79
- interface SaveConfig {
80
- dc: number;
81
- }
82
- declare class DCBuilder extends RollBuilder {
83
- private readonly saveConfig;
84
- constructor(baseRoll: RollBuilder, saveConfig?: SaveConfig);
85
- dc(saveDC: number): DCBuilder;
86
- get saveDC(): number;
87
- add(anotherRoll: RollBuilder): DCBuilder;
88
- addRoll(count?: number): DCBuilder;
89
- onSaveFailure(val: number): SaveBuilder;
90
- onSaveFailure(val: string): SaveBuilder;
91
- onSaveFailure(val: RollBuilder): SaveBuilder;
92
- onSaveFailure(count: number, die: RollBuilder): SaveBuilder;
93
- onSaveFailure(count: number, sides: number): SaveBuilder;
94
- onSaveFailure(count: number, die: RollBuilder, modifier: number): SaveBuilder;
95
- onSaveFailure(count: number, sides: number, modifier: number): SaveBuilder;
96
- withElvenAccuracy(): never;
97
- toExpression(): string;
98
- toPMF(eps?: number): PMF;
99
- }
100
-
101
- type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
102
- type DieNode = {
103
- type: "die";
104
- sides: number;
105
- reroll?: number;
106
- minimum?: number;
107
- explode?: number;
108
- };
109
- type ConstantNode = {
110
- type: "constant";
111
- value: number;
112
- };
113
- type SumNode = {
114
- type: "sum";
115
- count: number;
116
- child: ExpressionNode;
117
- };
118
- type AddNode = {
119
- type: "add";
120
- children: {
121
- node: ExpressionNode;
122
- sign: 1 | -1;
123
- }[];
124
- };
125
- type KeepNode = {
126
- type: "keep";
127
- mode: "highest" | "lowest";
128
- count: number;
129
- child: SumNode | KeepNode;
130
- };
131
- type D20RollNode = {
132
- type: "d20Roll";
133
- rollType: "advantage" | "disadvantage" | "elven accuracy";
134
- child: ExpressionNode;
135
- };
136
- type HalfNode = {
137
- type: "half";
138
- child: ExpressionNode;
139
- };
140
- type MaxOfNode = {
141
- type: "maxOf";
142
- count: number;
143
- child: ExpressionNode;
144
- };
145
-
146
- declare const defaultConfig: RollConfig;
147
- declare class RollBuilder {
148
- protected readonly subRollConfigs: readonly RollConfig[];
149
- constructor(countOrConfigs?: number | readonly RollConfig[]);
150
- protected create(configs: readonly RollConfig[]): RollBuilder;
151
- protected get lastConfig(): RollConfig;
152
- hasHiddenState(): boolean;
153
- getSubRollConfigs(): readonly RollConfig[];
154
- static fromConfig(config: Partial<RollConfig>): RollBuilder;
155
- static fromConfigs(configs: Partial<RollConfig>[]): RollBuilder;
156
- static fromArgs(...args: any[]): RollBuilder;
157
- d(sides: number | undefined): RollBuilder;
158
- plus(modOrRoll: number | RollBuilder | undefined): RollBuilder;
159
- plus(count: number, die: RollBuilder): RollBuilder;
160
- minus(modOrRoll: number | RollBuilder | undefined): RollBuilder;
161
- minus(count: number, die: RollBuilder): RollBuilder;
162
- /** Apply one-pass reroll threshold (k): reroll faces 1..k once, must keep. */
163
- reroll(value: number): RollBuilder;
164
- /** Set finite explode count for max-face explosions (Infinity allowed). */
165
- explode(count?: number | undefined): RollBuilder;
166
- /** Apply per-die minimum value (min > 0). */
167
- minimum(val: number | undefined): RollBuilder;
168
- bestOf(count: number | undefined): RollBuilder;
169
- keepHighest(total: number, count: number): RollBuilder;
170
- keepLowest(total: number, count: number): RollBuilder;
171
- keepHighestAll(total: number, count: number): PooledRollBuilder;
172
- keepLowestAll(total: number, count: number): PooledRollBuilder;
173
- withAdvantage(): RollBuilder;
174
- withDisadvantage(): RollBuilder;
175
- add(anotherRoll: RollBuilder | undefined): RollBuilder;
176
- withBonus(anotherRoll: RollBuilder): RollBuilder;
177
- addRoll(count?: number): RollBuilder;
178
- scaleDice(scale: number): RollBuilder;
179
- doubleDice(): RollBuilder;
180
- alwaysHits(): AlwaysHitBuilder;
181
- alwaysCrits(): AlwaysCritBuilder;
182
- copy(): RollBuilder;
183
- d4: () => RollBuilder;
184
- d6: () => RollBuilder;
185
- d8: () => RollBuilder;
186
- d10: () => RollBuilder;
187
- d12: () => RollBuilder;
188
- d20: () => RollBuilder;
189
- d100: () => RollBuilder;
190
- withElvenAccuracy(): RollBuilder;
191
- toExpression(): string;
192
- toPMF(eps?: number): PMF;
193
- get pmf(): PMF;
194
- toQuery(eps?: number): DiceQuery;
195
- toAST(): ExpressionNode;
196
- private configToSingleExpressionWithoutModifier;
197
- getRootDieConfig(): RollConfig | undefined;
198
- getAllDieConfigs(): readonly RollConfig[];
199
- getBonusDiceConfigs(): RollConfig[];
200
- getBonusDicePMFs(check: RollBuilder, eps?: number): PMF[];
201
- get modifier(): number;
202
- get rollType(): RollType;
203
- get baseReroll(): number;
204
- half(): HalfRollBuilder;
205
- maxOf(count: number): MaxOfRollBuilder;
206
- ac(_targetAC: number): ACBuilder;
207
- dc(_saveDC: number): DCBuilder;
208
- }
209
- declare class HalfRollBuilder extends RollBuilder {
210
- private readonly innerRoll;
211
- constructor(innerRoll: RollBuilder);
212
- hasHiddenState(): boolean;
213
- get lastConfig(): RollConfig;
214
- getSubRollConfigs(): readonly RollConfig[];
215
- toExpression(): string;
216
- toAST(): ExpressionNode;
217
- toPMF(eps?: number): PMF;
218
- copy(): HalfRollBuilder;
219
- }
220
- declare class MaxOfRollBuilder extends RollBuilder {
221
- private readonly innerRoll;
222
- private readonly count;
223
- private readonly diceCount?;
224
- private readonly diceSides?;
225
- constructor(innerRoll: RollBuilder, count: number, diceCount?: number | undefined, diceSides?: number | undefined);
226
- hasHiddenState(): boolean;
227
- get lastConfig(): RollConfig;
228
- getSubRollConfigs(): readonly RollConfig[];
229
- toExpression(): string;
230
- toAST(): ExpressionNode;
231
- toPMF(eps?: number): PMF;
232
- copy(): MaxOfRollBuilder;
233
- }
234
- declare class AlwaysHitBuilder extends RollBuilder {
235
- readonly attackConfig: CritConfig;
236
- constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
237
- protected create(configs: readonly RollConfig[]): RollBuilder;
238
- onHit(val: number): AttackBuilder;
239
- onHit(val: string): AttackBuilder;
240
- onHit(val: RollBuilder): AttackBuilder;
241
- onHit(count: number, die: RollBuilder): AttackBuilder;
242
- onHit(count: number, sides: number): AttackBuilder;
243
- onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
244
- onHit(count: number, sides: number, modifier: number): AttackBuilder;
245
- get critThreshold(): number;
246
- critOn(critThreshold: number): AlwaysHitBuilder;
247
- alwaysCrits(): AlwaysCritBuilder;
248
- toExpression(): string;
249
- toPMF(): PMF;
250
- copy(): AlwaysHitBuilder;
251
- }
252
- declare class AlwaysCritBuilder extends RollBuilder {
253
- readonly attackConfig: CritConfig & {
254
- ac?: number;
255
- };
256
- readonly fromAlwaysHit: boolean;
257
- constructor(baseRoll: RollBuilder, attackConfig?: CritConfig & {
258
- ac?: number;
259
- }, fromAlwaysHit?: boolean);
260
- protected create(configs: readonly RollConfig[]): RollBuilder;
261
- onHit(val: number): AttackBuilder;
262
- onHit(val: string): AttackBuilder;
263
- onHit(val: RollBuilder): AttackBuilder;
264
- onHit(count: number, die: RollBuilder): AttackBuilder;
265
- onHit(count: number, sides: number): AttackBuilder;
266
- onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
267
- onHit(count: number, sides: number, modifier: number): AttackBuilder;
268
- get critThreshold(): number;
269
- critOn(critThreshold: number): AlwaysCritBuilder;
270
- toExpression(): string;
271
- toPMF(): PMF;
272
- copy(): AlwaysCritBuilder;
273
- }
274
- declare class ParsedRollBuilder extends RollBuilder {
275
- private readonly cachedPMF;
276
- private readonly originalExpression;
277
- constructor(expression: string);
278
- hasHiddenState(): boolean;
279
- protected create(configs: readonly RollConfig[]): RollBuilder;
280
- toPMF(_eps?: number): PMF;
281
- toExpression(): string;
282
- toAST(): ExpressionNode;
283
- copy(): ParsedRollBuilder;
284
- doubleDice(): ParsedRollBuilder;
285
- }
286
- declare class PooledRollBuilder extends RollBuilder {
287
- private readonly baseAST;
288
- private readonly baseExpression;
289
- constructor(baseAST: ExpressionNode, baseExpression: string, configs?: readonly RollConfig[]);
290
- protected create(configs: readonly RollConfig[]): PooledRollBuilder;
291
- hasHiddenState(): boolean;
292
- d(_sides: number | undefined): RollBuilder;
293
- reroll(_value: number): RollBuilder;
294
- explode(_count?: number | undefined): RollBuilder;
295
- minimum(_val: number | undefined): RollBuilder;
296
- bestOf(_count: number | undefined): RollBuilder;
297
- keepHighest(_total: number, _count: number): RollBuilder;
298
- keepLowest(_total: number, _count: number): RollBuilder;
299
- withAdvantage(): RollBuilder;
300
- withDisadvantage(): RollBuilder;
301
- withElvenAccuracy(): RollBuilder;
302
- toAST(): ExpressionNode;
303
- toExpression(): string;
304
- copy(): PooledRollBuilder;
305
- scaleDice(scale: number): RollBuilder;
306
- times(count: number): PooledRollBuilder;
307
- }
308
-
309
- type ActionEffect = RollBuilder;
310
- declare class AttackBuilder implements CheckBuilder {
311
- readonly check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder;
312
- private readonly hitEffect?;
313
- private readonly critEffect?;
314
- private readonly missEffect?;
315
- constructor(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, hitEffect?: ActionEffect | undefined, critEffect?: (ActionEffect | null) | undefined, missEffect?: ActionEffect | undefined);
316
- onCrit(val: number): AttackBuilder;
317
- onCrit(val: string): AttackBuilder;
318
- onCrit(val: RollBuilder): AttackBuilder;
319
- onCrit(count: number, die: RollBuilder): AttackBuilder;
320
- onCrit(count: number, sides: number): AttackBuilder;
321
- onCrit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
322
- onCrit(count: number, sides: number, modifier: number): AttackBuilder;
323
- onMiss(val: number): AttackBuilder;
324
- onMiss(val: string): AttackBuilder;
325
- onMiss(val: RollBuilder): AttackBuilder;
326
- onMiss(count: number, die: RollBuilder): AttackBuilder;
327
- onMiss(count: number, sides: number): AttackBuilder;
328
- onMiss(count: number, die: RollBuilder, modifier: number): AttackBuilder;
329
- onMiss(count: number, sides: number, modifier: number): AttackBuilder;
330
- noCrit(): AttackBuilder;
331
- toExpression(): string;
332
- resolveProbabilities(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, eps?: number): {
333
- pSuccess: number;
334
- pHit: number;
335
- pCrit: number;
336
- pMiss: number;
337
- };
338
- resolve(eps?: number): AttackResolution;
339
- toPMF(eps?: number): PMF;
340
- get pmf(): PMF;
341
- toQuery(eps?: number): DiceQuery;
342
- }
343
-
344
- interface AttackConfig {
345
- ac: number;
346
- critThreshold: number;
347
- }
348
- declare class ACBuilder extends RollBuilder {
349
- readonly attackConfig: AttackConfig;
350
- constructor(baseRoll: RollBuilder, ac: number, attackConfig?: AttackConfig);
351
- onHit(val: number): AttackBuilder;
352
- onHit(val: string): AttackBuilder;
353
- onHit(val: RollBuilder): AttackBuilder;
354
- onHit(count: number, die: RollBuilder): AttackBuilder;
355
- onHit(count: number, sides: number): AttackBuilder;
356
- onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
357
- onHit(count: number, sides: number, modifier: number): AttackBuilder;
358
- get critThreshold(): number;
359
- critOn(threshold: number): ACBuilder;
360
- alwaysCrits(): AlwaysCritBuilder;
361
- toExpression(): string;
362
- toPMF(eps?: number): PMF;
363
- copy(): ACBuilder;
364
- }
365
-
366
- declare function d(sides: number | string): RollBuilder;
367
- declare const d4: RollBuilder;
368
- declare const d6: RollBuilder;
369
- declare const d8: RollBuilder;
370
- declare const d10: RollBuilder;
371
- declare const d12: RollBuilder;
372
- declare const d20: RollBuilder;
373
- declare const hd20: RollBuilder;
374
- declare const d100: RollBuilder;
375
- declare const flat: (n: number) => RollBuilder;
376
- declare const roll: RollFactory;
377
- declare const builderPMFCache: LRUCache<string, PMF>;
378
-
379
- export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, AttackBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, ParsedRollBuilder, PooledRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
1
+ export * from "./ac.js";
2
+ export * from "./attack.js";
3
+ export * from "./dc.js";
4
+ export * from "./factory.js";
5
+ export * from "./roll.js";
6
+ export * from "./save.js";
7
+ export * from "./types.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC;AACrB,cAAc,UAAU,CAAC;AACzB,cAAc,MAAM,CAAC;AACrB,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC"}
@@ -4092,6 +4092,15 @@ var RollBuilder = class _RollBuilder {
4092
4092
  half() {
4093
4093
  return new HalfRollBuilder(this);
4094
4094
  }
4095
+ /**
4096
+ * Scale this roll's result by `numerator / denominator`, rounding each outcome.
4097
+ * A general, composable form of {@link half} — used to model damage-type resistance
4098
+ * (`scaleResult(1, 2)` → `(expr) // 2`) and vulnerability (`scaleResult(2)` → `2 * (expr)`).
4099
+ * Compose several of these (and plain rolls) into one payload with {@link sumRolls}.
4100
+ */
4101
+ scaleResult(numerator, denominator = 1, rounding = "floor") {
4102
+ return new ScaleRollBuilder(this, numerator, denominator, rounding);
4103
+ }
4095
4104
  // Create a "max of N rolls" version of this roll for crit damage with keep operations
4096
4105
  maxOf(count) {
4097
4106
  return new MaxOfRollBuilder(this, count);
@@ -4146,6 +4155,50 @@ var HalfRollBuilder = class _HalfRollBuilder extends RollBuilder {
4146
4155
  return new _HalfRollBuilder(this.innerRoll.copy());
4147
4156
  }
4148
4157
  };
4158
+ var ScaleRollBuilder = class _ScaleRollBuilder extends RollBuilder {
4159
+ constructor(innerRoll, numerator, denominator = 1, rounding = "floor") {
4160
+ super(0);
4161
+ this.innerRoll = innerRoll;
4162
+ this.numerator = numerator;
4163
+ this.denominator = denominator;
4164
+ this.rounding = rounding;
4165
+ }
4166
+ hasHiddenState() {
4167
+ return this.innerRoll.hasHiddenState();
4168
+ }
4169
+ get lastConfig() {
4170
+ return this.innerRoll.lastConfig;
4171
+ }
4172
+ getSubRollConfigs() {
4173
+ return this.innerRoll.getSubRollConfigs();
4174
+ }
4175
+ toExpression() {
4176
+ const inner = this.innerRoll.toExpression();
4177
+ if (this.denominator === 1) return `${this.numerator} * (${inner})`;
4178
+ if (this.numerator === 1) return `(${inner}) // ${this.denominator}`;
4179
+ return `(${inner}) * ${this.numerator} // ${this.denominator}`;
4180
+ }
4181
+ toAST() {
4182
+ return {
4183
+ type: "scale",
4184
+ numerator: this.numerator,
4185
+ denominator: this.denominator,
4186
+ rounding: this.rounding,
4187
+ child: this.innerRoll.toAST()
4188
+ };
4189
+ }
4190
+ toPMF(eps = 0) {
4191
+ return pmfFromRollBuilder(this, eps);
4192
+ }
4193
+ copy() {
4194
+ return new _ScaleRollBuilder(
4195
+ this.innerRoll.copy(),
4196
+ this.numerator,
4197
+ this.denominator,
4198
+ this.rounding
4199
+ );
4200
+ }
4201
+ };
4149
4202
  var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
4150
4203
  constructor(innerRoll, count, diceCount, diceSides) {
4151
4204
  super(0);
@@ -4444,6 +4497,49 @@ var PooledRollBuilder = class _PooledRollBuilder extends RollBuilder {
4444
4497
  return new _PooledRollBuilder(sumNode, newExpr);
4445
4498
  }
4446
4499
  };
4500
+ var CompositeSumRollBuilder = class _CompositeSumRollBuilder extends RollBuilder {
4501
+ constructor(parts) {
4502
+ super(0);
4503
+ this.parts = parts;
4504
+ }
4505
+ hasHiddenState() {
4506
+ return true;
4507
+ }
4508
+ getSubRollConfigs() {
4509
+ return [];
4510
+ }
4511
+ toAST() {
4512
+ return {
4513
+ type: "add",
4514
+ children: this.parts.map((p) => ({
4515
+ node: p.toAST(),
4516
+ sign: 1
4517
+ }))
4518
+ };
4519
+ }
4520
+ toExpression() {
4521
+ const exprs = this.parts.map((p) => p.toExpression()).filter((e) => e && e !== "0");
4522
+ if (exprs.length === 0) return "0";
4523
+ let result = exprs[0];
4524
+ for (let i = 1; i < exprs.length; i++) {
4525
+ const e = exprs[i];
4526
+ result += e.startsWith("-") ? ` - ${e.substring(1)}` : ` + ${e}`;
4527
+ }
4528
+ return result.replace(/\+ -/g, "-");
4529
+ }
4530
+ toPMF(eps = 0) {
4531
+ return pmfFromRollBuilder(this, eps);
4532
+ }
4533
+ copy() {
4534
+ return new _CompositeSumRollBuilder(this.parts.map((p) => p.copy()));
4535
+ }
4536
+ };
4537
+ function sumRolls(parts) {
4538
+ const meaningful = parts.filter((p) => p !== void 0);
4539
+ if (meaningful.length === 0) return new RollBuilder(0);
4540
+ if (meaningful.length === 1) return meaningful[0];
4541
+ return new CompositeSumRollBuilder(meaningful);
4542
+ }
4447
4543
 
4448
4544
  // src/builder/factory.ts
4449
4545
  var rollFn = (count, sidesOrDie, modifier) => {
@@ -4674,6 +4770,11 @@ function resolve(node, eps = defaultEps) {
4674
4770
  if (count === 1) return childPMF;
4675
4771
  return computeMaxOfPMF(childPMF, count, eps);
4676
4772
  }
4773
+ case "scale": {
4774
+ const childPMF = resolve(node.child, eps);
4775
+ const denom = node.denominator === 0 ? 1 : node.denominator;
4776
+ return childPMF.scaleDamage(node.numerator / denom, node.rounding);
4777
+ }
4677
4778
  }
4678
4779
  })();
4679
4780
  builderPMFCache.set(cacheKey, result);
@@ -4745,6 +4846,7 @@ function findDie(node) {
4745
4846
  case "d20Roll":
4746
4847
  case "half":
4747
4848
  case "maxOf":
4849
+ case "scale":
4748
4850
  return findDie(node.child);
4749
4851
  case "keep":
4750
4852
  return findDie(node.child.child);
@@ -4929,6 +5031,8 @@ function getASTSignature(node) {
4929
5031
  return `half{ch:${getASTSignature(node.child)}}`;
4930
5032
  case "maxOf":
4931
5033
  return `maxOf{c:${node.count},ch:${getASTSignature(node.child)}}`;
5034
+ case "scale":
5035
+ return `scale{n:${node.numerator},d:${node.denominator},r:${node.rounding},ch:${getASTSignature(node.child)}}`;
4932
5036
  case "add": {
4933
5037
  let constantValue = 0;
4934
5038
  const otherChildrenSigs = [];
@@ -5365,6 +5469,6 @@ RollBuilder.prototype.dc = function(saveDC) {
5365
5469
  return new DCBuilder(this).dc(saveDC);
5366
5470
  };
5367
5471
 
5368
- export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, AttackBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, ParsedRollBuilder, PooledRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
5472
+ export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, AttackBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, ParsedRollBuilder, PooledRollBuilder, RollBuilder, SaveBuilder, ScaleRollBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll, sumRolls };
5369
5473
  //# sourceMappingURL=index.js.map
5370
5474
  //# sourceMappingURL=index.js.map