@yipe/dice 0.2.11 → 0.2.13

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.
@@ -1,6 +1,6 @@
1
1
  import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-D1p2Re-J.cjs';
2
2
 
3
- type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode;
3
+ type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
4
4
  type DieNode = {
5
5
  type: "die";
6
6
  sides: number;
@@ -39,6 +39,11 @@ type HalfNode = {
39
39
  type: "half";
40
40
  child: ExpressionNode;
41
41
  };
42
+ type MaxOfNode = {
43
+ type: "maxOf";
44
+ count: number;
45
+ child: ExpressionNode;
46
+ };
42
47
 
43
48
  type RollFactory = {
44
49
  (count: number, sides?: number, modifier?: number): RollBuilder;
@@ -156,6 +161,7 @@ declare class RollBuilder {
156
161
  get rollType(): RollType;
157
162
  get baseReroll(): number;
158
163
  half(): HalfRollBuilder;
164
+ maxOf(count: number): MaxOfRollBuilder;
159
165
  }
160
166
  declare class HalfRollBuilder extends RollBuilder {
161
167
  private readonly innerRoll;
@@ -167,6 +173,20 @@ declare class HalfRollBuilder extends RollBuilder {
167
173
  toPMF(eps?: number): PMF;
168
174
  copy(): HalfRollBuilder;
169
175
  }
176
+ declare class MaxOfRollBuilder extends RollBuilder {
177
+ private readonly innerRoll;
178
+ private readonly count;
179
+ private readonly diceCount?;
180
+ private readonly diceSides?;
181
+ constructor(innerRoll: RollBuilder, count: number, diceCount?: number, diceSides?: number);
182
+ get lastConfig(): any;
183
+ getSubRollConfigs(): readonly RollConfig[];
184
+ toExpression(): string;
185
+ private findDieInAST;
186
+ toAST(): ExpressionNode;
187
+ toPMF(eps?: number): PMF;
188
+ copy(): MaxOfRollBuilder;
189
+ }
170
190
 
171
191
  type ActionEffect = RollBuilder;
172
192
  declare class AttackBuilder implements CheckBuilder {
@@ -279,4 +299,4 @@ declare const flat: (n: number) => RollBuilder;
279
299
  declare const roll: RollFactory;
280
300
  declare const builderPMFCache: LRUCache<string, PMF>;
281
301
 
282
- export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
302
+ export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
@@ -1,6 +1,6 @@
1
1
  import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-D1p2Re-J.js';
2
2
 
3
- type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode;
3
+ type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
4
4
  type DieNode = {
5
5
  type: "die";
6
6
  sides: number;
@@ -39,6 +39,11 @@ type HalfNode = {
39
39
  type: "half";
40
40
  child: ExpressionNode;
41
41
  };
42
+ type MaxOfNode = {
43
+ type: "maxOf";
44
+ count: number;
45
+ child: ExpressionNode;
46
+ };
42
47
 
43
48
  type RollFactory = {
44
49
  (count: number, sides?: number, modifier?: number): RollBuilder;
@@ -156,6 +161,7 @@ declare class RollBuilder {
156
161
  get rollType(): RollType;
157
162
  get baseReroll(): number;
158
163
  half(): HalfRollBuilder;
164
+ maxOf(count: number): MaxOfRollBuilder;
159
165
  }
160
166
  declare class HalfRollBuilder extends RollBuilder {
161
167
  private readonly innerRoll;
@@ -167,6 +173,20 @@ declare class HalfRollBuilder extends RollBuilder {
167
173
  toPMF(eps?: number): PMF;
168
174
  copy(): HalfRollBuilder;
169
175
  }
176
+ declare class MaxOfRollBuilder extends RollBuilder {
177
+ private readonly innerRoll;
178
+ private readonly count;
179
+ private readonly diceCount?;
180
+ private readonly diceSides?;
181
+ constructor(innerRoll: RollBuilder, count: number, diceCount?: number, diceSides?: number);
182
+ get lastConfig(): any;
183
+ getSubRollConfigs(): readonly RollConfig[];
184
+ toExpression(): string;
185
+ private findDieInAST;
186
+ toAST(): ExpressionNode;
187
+ toPMF(eps?: number): PMF;
188
+ copy(): MaxOfRollBuilder;
189
+ }
170
190
 
171
191
  type ActionEffect = RollBuilder;
172
192
  declare class AttackBuilder implements CheckBuilder {
@@ -279,4 +299,4 @@ declare const flat: (n: number) => RollBuilder;
279
299
  declare const roll: RollFactory;
280
300
  declare const builderPMFCache: LRUCache<string, PMF>;
281
301
 
282
- export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
302
+ export { ACBuilder, type AttackConfig, type AttackResolution, type CheckBuilder, DCBuilder, HalfRollBuilder, type KeepMode, MaxOfRollBuilder, type Resolution, RollBuilder, type RollConfig, type RollFactory, type RollType, SaveBuilder, type SaveOutcome, type SaveResolution, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
@@ -2657,6 +2657,14 @@ var RollBuilder = class _RollBuilder {
2657
2657
  const scaleInt = Math.floor(scale);
2658
2658
  if (scaleInt !== scale) throw new Error("Scale must be an integer");
2659
2659
  if (scaleInt <= 0) throw new Error("Scale must be > 0");
2660
+ if (scaleInt > 1) {
2661
+ const configs = this.getSubRollConfigs();
2662
+ if (configs.length === 1 && configs[0].keep && configs[0].count === 1) {
2663
+ const config = configs[0];
2664
+ const newConfig = { ...config, count: scaleInt };
2665
+ return new _RollBuilder([newConfig]);
2666
+ }
2667
+ }
2660
2668
  const newConfigs = this.getSubRollConfigs().map((config) => {
2661
2669
  if (!config.sides || config.sides <= 0) return config;
2662
2670
  return { ...config, count: config.count * scaleInt };
@@ -2876,6 +2884,10 @@ var RollBuilder = class _RollBuilder {
2876
2884
  half() {
2877
2885
  return new HalfRollBuilder(this);
2878
2886
  }
2887
+ // Create a "max of N rolls" version of this roll for crit damage with keep operations
2888
+ maxOf(count) {
2889
+ return new MaxOfRollBuilder(this, count);
2890
+ }
2879
2891
  };
2880
2892
  var HalfRollBuilder = class _HalfRollBuilder extends RollBuilder {
2881
2893
  constructor(innerRoll) {
@@ -2905,6 +2917,78 @@ var HalfRollBuilder = class _HalfRollBuilder extends RollBuilder {
2905
2917
  return new _HalfRollBuilder(this.innerRoll.copy());
2906
2918
  }
2907
2919
  };
2920
+ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
2921
+ constructor(innerRoll, count, diceCount, diceSides) {
2922
+ super(0);
2923
+ this.innerRoll = innerRoll;
2924
+ this.count = count;
2925
+ this.diceCount = diceCount;
2926
+ this.diceSides = diceSides;
2927
+ }
2928
+ get lastConfig() {
2929
+ return this.innerRoll.lastConfig;
2930
+ }
2931
+ getSubRollConfigs() {
2932
+ return this.innerRoll.getSubRollConfigs();
2933
+ }
2934
+ toExpression() {
2935
+ if (this.diceCount && this.diceSides) {
2936
+ return `max${this.count}(${this.diceCount}d${this.diceSides})`;
2937
+ }
2938
+ return `max${this.count}(?d?)`;
2939
+ }
2940
+ findDieInAST(node) {
2941
+ if (node.type === "die") return node;
2942
+ if (node.child) return this.findDieInAST(node.child);
2943
+ if (node.children) {
2944
+ for (const child of node.children) {
2945
+ const result = this.findDieInAST(child.node || child);
2946
+ if (result) return result;
2947
+ }
2948
+ }
2949
+ return null;
2950
+ }
2951
+ toAST() {
2952
+ if (this.diceCount && this.diceSides) {
2953
+ const sumChild = {
2954
+ type: "sum",
2955
+ count: this.diceCount,
2956
+ child: { type: "die", sides: this.diceSides }
2957
+ };
2958
+ return {
2959
+ type: "maxOf",
2960
+ count: this.count,
2961
+ child: sumChild
2962
+ };
2963
+ }
2964
+ try {
2965
+ const configs = this.innerRoll.getSubRollConfigs();
2966
+ if (configs.length === 1 && configs[0].sides) {
2967
+ const config = configs[0];
2968
+ const sumChild = {
2969
+ type: "sum",
2970
+ count: config.count,
2971
+ child: { type: "die", sides: config.sides }
2972
+ };
2973
+ return {
2974
+ type: "maxOf",
2975
+ count: this.count,
2976
+ child: sumChild
2977
+ };
2978
+ }
2979
+ } catch (e) {
2980
+ }
2981
+ throw new Error(
2982
+ `MaxOfRollBuilder.toAST(): Unsupported innerRoll configuration`
2983
+ );
2984
+ }
2985
+ toPMF(eps = 0) {
2986
+ return pmfFromRollBuilder(this, eps);
2987
+ }
2988
+ copy() {
2989
+ return new _MaxOfRollBuilder(this.innerRoll.copy(), this.count);
2990
+ }
2991
+ };
2908
2992
 
2909
2993
  // src/builder/factory.ts
2910
2994
  var rollFn = (count, sidesOrDie, modifier) => {
@@ -2993,13 +3077,50 @@ function astFromRollConfigs(configs) {
2993
3077
  appliedRollType = true;
2994
3078
  }
2995
3079
  if (cfg.rollType === "flat" && cfg.keep && cfg.keep.total > 0) {
2996
- const base = { type: "sum", count: cfg.keep.total, child: node };
2997
- node = {
2998
- type: "keep",
2999
- mode: cfg.keep.mode,
3000
- count: cfg.keep.count,
3001
- child: base
3002
- };
3080
+ const baseCount = Math.max(1, Math.floor(Math.abs(count || 1)));
3081
+ const trials = Math.max(1, Math.floor(cfg.keep.total));
3082
+ const k = Math.max(0, Math.floor(cfg.keep.count));
3083
+ if (k === 1 && cfg.keep.mode === "highest") {
3084
+ const perTrial = {
3085
+ type: "sum",
3086
+ count: baseCount,
3087
+ child: node
3088
+ };
3089
+ if (trials === 1) {
3090
+ node = perTrial;
3091
+ } else {
3092
+ node = { type: "maxOf", count: trials, child: perTrial };
3093
+ }
3094
+ } else if (trials === baseCount) {
3095
+ const base = { type: "sum", count: trials, child: node };
3096
+ node = {
3097
+ type: "keep",
3098
+ mode: cfg.keep.mode,
3099
+ count: k,
3100
+ child: base
3101
+ };
3102
+ } else {
3103
+ const perTrial = {
3104
+ type: "sum",
3105
+ count: baseCount,
3106
+ child: node
3107
+ };
3108
+ if (trials === 1) {
3109
+ node = perTrial;
3110
+ } else {
3111
+ const trialPool = {
3112
+ type: "sum",
3113
+ count: trials,
3114
+ child: perTrial
3115
+ };
3116
+ node = {
3117
+ type: "keep",
3118
+ mode: cfg.keep.mode,
3119
+ count: k,
3120
+ child: trialPool
3121
+ };
3122
+ }
3123
+ }
3003
3124
  } else {
3004
3125
  const c = appliedRollType ? 1 : Math.max(1, count || 1);
3005
3126
  node = { type: "sum", count: c, child: node };
@@ -3053,14 +3174,14 @@ function resolve(node, eps = defaultEps) {
3053
3174
  return res;
3054
3175
  }
3055
3176
  case "keep": {
3056
- const total = getTotalCount(node);
3057
- const die = findDie(node.child.child);
3058
- const perDie = die ? resolveSingleDie(die, eps) : PMF.delta(0, eps);
3059
- const keepCount = Math.max(0, Math.min(node.count, total));
3060
- if (keepCount === 0 || total === 0) return PMF.delta(0, eps);
3177
+ const totalTrials = getTotalCount(node);
3178
+ const keepCount = Math.max(0, Math.min(node.count, totalTrials));
3179
+ if (keepCount === 0 || totalTrials === 0) return PMF.delta(0, eps);
3180
+ const perTrialNode = node.child.child;
3181
+ const perTrialPMF = resolve(perTrialNode, eps);
3061
3182
  return keepSumPMF(
3062
- perDie,
3063
- total,
3183
+ perTrialPMF,
3184
+ totalTrials,
3064
3185
  keepCount,
3065
3186
  node.mode === "highest",
3066
3187
  eps
@@ -3075,6 +3196,12 @@ function resolve(node, eps = defaultEps) {
3075
3196
  const childPMF = resolve(node.child, eps);
3076
3197
  return childPMF.scaleDamage(0.5, "floor");
3077
3198
  }
3199
+ case "maxOf": {
3200
+ const childPMF = resolve(node.child, eps);
3201
+ const count = Math.max(1, Math.floor(node.count));
3202
+ if (count === 1) return childPMF;
3203
+ return computeMaxOfPMF(childPMF, count, eps);
3204
+ }
3078
3205
  }
3079
3206
  })();
3080
3207
  builderPMFCache.set(cacheKey, result);
@@ -3145,6 +3272,7 @@ function findDie(node) {
3145
3272
  case "sum":
3146
3273
  case "d20Roll":
3147
3274
  case "half":
3275
+ case "maxOf":
3148
3276
  return findDie(node.child);
3149
3277
  case "keep":
3150
3278
  return findDie(node.child.child);
@@ -3161,6 +3289,38 @@ function getTotalCount(node) {
3161
3289
  while (cur.type === "keep") cur = cur.child;
3162
3290
  return cur.type === "sum" ? Math.max(0, Math.floor(cur.count)) : 0;
3163
3291
  }
3292
+ function computeMaxOfPMF(pmf, count, eps = defaultEps) {
3293
+ if (count <= 1) return pmf;
3294
+ const support = pmf.support();
3295
+ const out = /* @__PURE__ */ new Map();
3296
+ if (count <= 6 && support.length <= 20) {
3297
+ let dfs = function(rollsLeft, currentMax, probability) {
3298
+ if (rollsLeft === 0) {
3299
+ out.set(currentMax, (out.get(currentMax) || 0) + probability);
3300
+ return;
3301
+ }
3302
+ for (const value of support) {
3303
+ const p = pmf.pAt(value);
3304
+ if (p > 0) {
3305
+ const newMax = Math.max(currentMax, value);
3306
+ dfs(rollsLeft - 1, newMax, probability * p);
3307
+ }
3308
+ }
3309
+ };
3310
+ dfs(count, -Infinity, 1);
3311
+ } else {
3312
+ const sortedSupport = [...support].sort((a, b) => a - b);
3313
+ for (const value of sortedSupport) {
3314
+ const cdfAtValue = pmf.cdfAt(value);
3315
+ const cdfAtValueMinus1 = value > sortedSupport[0] ? pmf.cdfAt(value - 1) : 0;
3316
+ const probMax = Math.pow(cdfAtValue, count) - Math.pow(cdfAtValueMinus1, count);
3317
+ if (probMax > eps) {
3318
+ out.set(value, probMax);
3319
+ }
3320
+ }
3321
+ }
3322
+ return PMF.fromMap(out, eps);
3323
+ }
3164
3324
  function keepSumPMF(single, total, keep, highest, eps = defaultEps) {
3165
3325
  if (keep >= total) return single.power(total, eps);
3166
3326
  if (keep <= 0) return PMF.delta(0, eps);
@@ -3169,24 +3329,106 @@ function keepSumPMF(single, total, keep, highest, eps = defaultEps) {
3169
3329
  const cacheKey = `keep|${pmfSig}|t:${total}|k:${keep}|h:${highest ? 1 : 0}|e:${eps}`;
3170
3330
  const cached = builderPMFCache.get(cacheKey);
3171
3331
  if (cached) return cached;
3172
- const support = single.support();
3173
- const probs = support.map((v) => ({ v, p: single.pAt(v) }));
3174
- const out = /* @__PURE__ */ new Map();
3175
- function dfs(i, accValues, weight) {
3176
- if (i === total) {
3177
- const sorted = [...accValues].sort((a, b) => highest ? b - a : a - b);
3178
- let sum = 0;
3179
- for (let j = 0; j < keep; j++) sum += sorted[j];
3180
- out.set(sum, (out.get(sum) || 0) + weight);
3181
- return;
3332
+ if (keep === 1) {
3333
+ if (highest) {
3334
+ return computeMaxOfPMF(single, total, eps);
3335
+ } else {
3336
+ const neg = single.mapDamage((v) => -v);
3337
+ const minPMF = computeMaxOfPMF(neg, total, eps).mapDamage((v) => -v);
3338
+ builderPMFCache.set(cacheKey, minPMF);
3339
+ return minPMF;
3340
+ }
3341
+ }
3342
+ let state = /* @__PURE__ */ new Map();
3343
+ const keyOf = (used, r) => `${used}|${r}`;
3344
+ state.set(keyOf(0, total), /* @__PURE__ */ new Map([[0, 1]]));
3345
+ const valuesDesc = highest ? [...sortedSupport].sort((a, b) => b - a) : [...sortedSupport].sort((a, b) => a - b);
3346
+ const binomPMF = (r, p) => {
3347
+ if (r <= 0) return [1];
3348
+ if (p <= eps) {
3349
+ const arr2 = new Array(r + 1).fill(0);
3350
+ arr2[0] = 1;
3351
+ return arr2;
3352
+ }
3353
+ if (1 - p <= eps) {
3354
+ const arr2 = new Array(r + 1).fill(0);
3355
+ arr2[r] = 1;
3356
+ return arr2;
3182
3357
  }
3183
- for (const { v, p } of probs) {
3184
- if (p <= 0) continue;
3185
- dfs(i + 1, [...accValues, v], weight * p);
3358
+ const q = 1 - p;
3359
+ const arr = new Array(r + 1).fill(0);
3360
+ arr[0] = Math.pow(q, r);
3361
+ const ratio = p / q;
3362
+ for (let x = 1; x <= r; x++)
3363
+ arr[x] = arr[x - 1] * (r - x + 1) / x * ratio;
3364
+ let s = 0;
3365
+ for (let x = 0; x <= r; x++) s += arr[x];
3366
+ if (Math.abs(1 - s) > 1e-12) for (let x = 0; x <= r; x++) arr[x] /= s;
3367
+ return arr;
3368
+ };
3369
+ const pruneMap = (m, threshold) => {
3370
+ if (threshold <= 0) return m;
3371
+ const out = /* @__PURE__ */ new Map();
3372
+ for (const [sum, pr] of m) if (pr >= threshold) out.set(sum, pr);
3373
+ return out.size === m.size ? m : out;
3374
+ };
3375
+ const pruneState = (st, threshold) => {
3376
+ if (threshold <= 0) return st;
3377
+ const out = /* @__PURE__ */ new Map();
3378
+ for (const [k, m] of st) {
3379
+ const mm = pruneMap(m, threshold);
3380
+ if (mm.size > 0) out.set(k, mm);
3186
3381
  }
3382
+ return out;
3383
+ };
3384
+ let processedMass = 0;
3385
+ for (const v of valuesDesc) {
3386
+ const p = single.pAt(v);
3387
+ if (p <= 0) continue;
3388
+ const q = Math.max(eps, 1 - processedMass);
3389
+ const pCond = Math.min(1, p / q);
3390
+ const next = /* @__PURE__ */ new Map();
3391
+ for (const [k, m] of state) {
3392
+ const [usedStr, rStr] = k.split("|");
3393
+ const used = parseInt(usedStr, 10);
3394
+ const r = parseInt(rStr, 10);
3395
+ if (r === 0) {
3396
+ const destKey = keyOf(used, 0);
3397
+ const dest = next.get(destKey) ?? /* @__PURE__ */ new Map();
3398
+ for (const [sum, pr] of m) dest.set(sum, (dest.get(sum) || 0) + pr);
3399
+ next.set(destKey, dest);
3400
+ continue;
3401
+ }
3402
+ const bin = binomPMF(r, pCond);
3403
+ const remainingCapacity = keep - used;
3404
+ for (let x = 0; x <= r; x++) {
3405
+ const px = bin[x];
3406
+ if (px <= eps) continue;
3407
+ const t = Math.min(x, remainingCapacity);
3408
+ const used2 = used + t;
3409
+ const r2 = r - x;
3410
+ const add = t * v;
3411
+ const destKey = keyOf(used2, r2);
3412
+ const dest = next.get(destKey) ?? /* @__PURE__ */ new Map();
3413
+ for (const [sum, pr] of m) {
3414
+ const s2 = sum + add;
3415
+ const prob = pr * px;
3416
+ const cur = dest.get(s2) || 0;
3417
+ const nv = cur + prob;
3418
+ if (nv >= eps) dest.set(s2, nv);
3419
+ }
3420
+ if (dest.size > 0) next.set(destKey, dest);
3421
+ }
3422
+ }
3423
+ state = pruneState(next, eps * 1e-6);
3424
+ processedMass += p;
3425
+ }
3426
+ const finalKey = keyOf(keep, 0);
3427
+ const dist = state.get(finalKey) ?? /* @__PURE__ */ new Map();
3428
+ if (dist.size === 0) {
3429
+ return PMF.emptyMass();
3187
3430
  }
3188
- dfs(0, [], 1);
3189
- const result = PMF.fromMap(out, eps);
3431
+ const result = PMF.fromMap(dist, eps);
3190
3432
  builderPMFCache.set(cacheKey, result);
3191
3433
  return result;
3192
3434
  }
@@ -3212,6 +3454,8 @@ function getASTSignature(node) {
3212
3454
  )}}`;
3213
3455
  case "half":
3214
3456
  return `half{ch:${getASTSignature(node.child)}}`;
3457
+ case "maxOf":
3458
+ return `maxOf{c:${node.count},ch:${getASTSignature(node.child)}}`;
3215
3459
  case "add": {
3216
3460
  let constantValue = 0;
3217
3461
  const otherChildrenSigs = [];
@@ -3271,7 +3515,12 @@ var AttackBuilder = class _AttackBuilder {
3271
3515
  if (this.hitEffect) {
3272
3516
  effectPart = `(${this.hitEffect.toExpression()})`;
3273
3517
  if (this.critEffect !== null) {
3274
- const crit = this.critEffect ?? this.hitEffect.copy().doubleDice();
3518
+ let crit;
3519
+ if (this.critEffect) {
3520
+ crit = this.critEffect;
3521
+ } else {
3522
+ crit = this.hitEffect?.copy().doubleDice() ?? RollBuilder.fromArgs(0);
3523
+ }
3275
3524
  const critThreshold = this.check.critThreshold;
3276
3525
  if (critThreshold < 15 || critThreshold > 20) {
3277
3526
  throw new Error(
@@ -3581,6 +3830,6 @@ RollBuilder.prototype.dc = function(saveDC) {
3581
3830
  return new DCBuilder(this).dc(saveDC);
3582
3831
  };
3583
3832
 
3584
- export { ACBuilder, DCBuilder, HalfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
3833
+ export { ACBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
3585
3834
  //# sourceMappingURL=index.js.map
3586
3835
  //# sourceMappingURL=index.js.map