@yipe/dice 0.2.10 → 0.2.12
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.
- package/dist/builder/index.cjs +311 -32
- package/dist/builder/index.cjs.map +1 -1
- package/dist/builder/index.d.cts +45 -10
- package/dist/builder/index.d.ts +45 -10
- package/dist/builder/index.js +310 -33
- package/dist/builder/index.js.map +1 -1
- package/package.json +1 -1
package/dist/builder/index.cjs
CHANGED
|
@@ -2659,6 +2659,14 @@ var RollBuilder = class _RollBuilder {
|
|
|
2659
2659
|
const scaleInt = Math.floor(scale);
|
|
2660
2660
|
if (scaleInt !== scale) throw new Error("Scale must be an integer");
|
|
2661
2661
|
if (scaleInt <= 0) throw new Error("Scale must be > 0");
|
|
2662
|
+
if (scaleInt > 1) {
|
|
2663
|
+
const configs = this.getSubRollConfigs();
|
|
2664
|
+
if (configs.length === 1 && configs[0].keep && configs[0].count === 1) {
|
|
2665
|
+
const config = configs[0];
|
|
2666
|
+
const newConfig = { ...config, count: scaleInt };
|
|
2667
|
+
return new _RollBuilder([newConfig]);
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2662
2670
|
const newConfigs = this.getSubRollConfigs().map((config) => {
|
|
2663
2671
|
if (!config.sides || config.sides <= 0) return config;
|
|
2664
2672
|
return { ...config, count: config.count * scaleInt };
|
|
@@ -2875,6 +2883,113 @@ var RollBuilder = class _RollBuilder {
|
|
|
2875
2883
|
const rootConfig = this.getRootDieConfig();
|
|
2876
2884
|
return rootConfig?.reroll || 0;
|
|
2877
2885
|
}
|
|
2886
|
+
half() {
|
|
2887
|
+
return new HalfRollBuilder(this);
|
|
2888
|
+
}
|
|
2889
|
+
// Create a "max of N rolls" version of this roll for crit damage with keep operations
|
|
2890
|
+
maxOf(count) {
|
|
2891
|
+
return new MaxOfRollBuilder(this, count);
|
|
2892
|
+
}
|
|
2893
|
+
};
|
|
2894
|
+
var HalfRollBuilder = class _HalfRollBuilder extends RollBuilder {
|
|
2895
|
+
constructor(innerRoll) {
|
|
2896
|
+
super(0);
|
|
2897
|
+
this.innerRoll = innerRoll;
|
|
2898
|
+
}
|
|
2899
|
+
get lastConfig() {
|
|
2900
|
+
return this.innerRoll.lastConfig;
|
|
2901
|
+
}
|
|
2902
|
+
getSubRollConfigs() {
|
|
2903
|
+
return this.innerRoll.getSubRollConfigs();
|
|
2904
|
+
}
|
|
2905
|
+
toExpression() {
|
|
2906
|
+
const innerExpression = this.innerRoll.toExpression();
|
|
2907
|
+
return `(${innerExpression}) // 2`;
|
|
2908
|
+
}
|
|
2909
|
+
toAST() {
|
|
2910
|
+
return {
|
|
2911
|
+
type: "half",
|
|
2912
|
+
child: this.innerRoll.toAST()
|
|
2913
|
+
};
|
|
2914
|
+
}
|
|
2915
|
+
toPMF(eps = 0) {
|
|
2916
|
+
return pmfFromRollBuilder(this, eps);
|
|
2917
|
+
}
|
|
2918
|
+
copy() {
|
|
2919
|
+
return new _HalfRollBuilder(this.innerRoll.copy());
|
|
2920
|
+
}
|
|
2921
|
+
};
|
|
2922
|
+
var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
|
|
2923
|
+
constructor(innerRoll, count, diceCount, diceSides) {
|
|
2924
|
+
super(0);
|
|
2925
|
+
this.innerRoll = innerRoll;
|
|
2926
|
+
this.count = count;
|
|
2927
|
+
this.diceCount = diceCount;
|
|
2928
|
+
this.diceSides = diceSides;
|
|
2929
|
+
}
|
|
2930
|
+
get lastConfig() {
|
|
2931
|
+
return this.innerRoll.lastConfig;
|
|
2932
|
+
}
|
|
2933
|
+
getSubRollConfigs() {
|
|
2934
|
+
return this.innerRoll.getSubRollConfigs();
|
|
2935
|
+
}
|
|
2936
|
+
toExpression() {
|
|
2937
|
+
if (this.diceCount && this.diceSides) {
|
|
2938
|
+
return `max${this.count}(${this.diceCount}d${this.diceSides})`;
|
|
2939
|
+
}
|
|
2940
|
+
return `max${this.count}(?d?)`;
|
|
2941
|
+
}
|
|
2942
|
+
findDieInAST(node) {
|
|
2943
|
+
if (node.type === "die") return node;
|
|
2944
|
+
if (node.child) return this.findDieInAST(node.child);
|
|
2945
|
+
if (node.children) {
|
|
2946
|
+
for (const child of node.children) {
|
|
2947
|
+
const result = this.findDieInAST(child.node || child);
|
|
2948
|
+
if (result) return result;
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
return null;
|
|
2952
|
+
}
|
|
2953
|
+
toAST() {
|
|
2954
|
+
if (this.diceCount && this.diceSides) {
|
|
2955
|
+
const sumChild = {
|
|
2956
|
+
type: "sum",
|
|
2957
|
+
count: this.diceCount,
|
|
2958
|
+
child: { type: "die", sides: this.diceSides }
|
|
2959
|
+
};
|
|
2960
|
+
return {
|
|
2961
|
+
type: "maxOf",
|
|
2962
|
+
count: this.count,
|
|
2963
|
+
child: sumChild
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
try {
|
|
2967
|
+
const configs = this.innerRoll.getSubRollConfigs();
|
|
2968
|
+
if (configs.length === 1 && configs[0].sides) {
|
|
2969
|
+
const config = configs[0];
|
|
2970
|
+
const sumChild = {
|
|
2971
|
+
type: "sum",
|
|
2972
|
+
count: config.count,
|
|
2973
|
+
child: { type: "die", sides: config.sides }
|
|
2974
|
+
};
|
|
2975
|
+
return {
|
|
2976
|
+
type: "maxOf",
|
|
2977
|
+
count: this.count,
|
|
2978
|
+
child: sumChild
|
|
2979
|
+
};
|
|
2980
|
+
}
|
|
2981
|
+
} catch (e) {
|
|
2982
|
+
}
|
|
2983
|
+
throw new Error(
|
|
2984
|
+
`MaxOfRollBuilder.toAST(): Unsupported innerRoll configuration`
|
|
2985
|
+
);
|
|
2986
|
+
}
|
|
2987
|
+
toPMF(eps = 0) {
|
|
2988
|
+
return pmfFromRollBuilder(this, eps);
|
|
2989
|
+
}
|
|
2990
|
+
copy() {
|
|
2991
|
+
return new _MaxOfRollBuilder(this.innerRoll.copy(), this.count);
|
|
2992
|
+
}
|
|
2878
2993
|
};
|
|
2879
2994
|
|
|
2880
2995
|
// src/builder/factory.ts
|
|
@@ -2964,13 +3079,41 @@ function astFromRollConfigs(configs) {
|
|
|
2964
3079
|
appliedRollType = true;
|
|
2965
3080
|
}
|
|
2966
3081
|
if (cfg.rollType === "flat" && cfg.keep && cfg.keep.total > 0) {
|
|
2967
|
-
const
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
count:
|
|
2972
|
-
|
|
2973
|
-
|
|
3082
|
+
const baseCount = Math.max(1, Math.floor(Math.abs(count || 1)));
|
|
3083
|
+
const trials = Math.max(1, Math.floor(cfg.keep.total));
|
|
3084
|
+
const k = Math.max(0, Math.floor(cfg.keep.count));
|
|
3085
|
+
if (trials === baseCount) {
|
|
3086
|
+
const base = { type: "sum", count: trials, child: node };
|
|
3087
|
+
node = {
|
|
3088
|
+
type: "keep",
|
|
3089
|
+
mode: cfg.keep.mode,
|
|
3090
|
+
count: k,
|
|
3091
|
+
child: base
|
|
3092
|
+
};
|
|
3093
|
+
} else {
|
|
3094
|
+
const perTrial = {
|
|
3095
|
+
type: "sum",
|
|
3096
|
+
count: baseCount,
|
|
3097
|
+
child: node
|
|
3098
|
+
};
|
|
3099
|
+
if (trials === 1) {
|
|
3100
|
+
node = perTrial;
|
|
3101
|
+
} else if (k === 1 && cfg.keep.mode === "highest") {
|
|
3102
|
+
node = { type: "maxOf", count: trials, child: perTrial };
|
|
3103
|
+
} else {
|
|
3104
|
+
const trialPool = {
|
|
3105
|
+
type: "sum",
|
|
3106
|
+
count: trials,
|
|
3107
|
+
child: perTrial
|
|
3108
|
+
};
|
|
3109
|
+
node = {
|
|
3110
|
+
type: "keep",
|
|
3111
|
+
mode: cfg.keep.mode,
|
|
3112
|
+
count: k,
|
|
3113
|
+
child: trialPool
|
|
3114
|
+
};
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
2974
3117
|
} else {
|
|
2975
3118
|
const c = appliedRollType ? 1 : Math.max(1, count || 1);
|
|
2976
3119
|
node = { type: "sum", count: c, child: node };
|
|
@@ -3024,14 +3167,14 @@ function resolve(node, eps = defaultEps) {
|
|
|
3024
3167
|
return res;
|
|
3025
3168
|
}
|
|
3026
3169
|
case "keep": {
|
|
3027
|
-
const
|
|
3028
|
-
const
|
|
3029
|
-
|
|
3030
|
-
const
|
|
3031
|
-
|
|
3170
|
+
const totalTrials = getTotalCount(node);
|
|
3171
|
+
const keepCount = Math.max(0, Math.min(node.count, totalTrials));
|
|
3172
|
+
if (keepCount === 0 || totalTrials === 0) return PMF.delta(0, eps);
|
|
3173
|
+
const perTrialNode = node.child.child;
|
|
3174
|
+
const perTrialPMF = resolve(perTrialNode, eps);
|
|
3032
3175
|
return keepSumPMF(
|
|
3033
|
-
|
|
3034
|
-
|
|
3176
|
+
perTrialPMF,
|
|
3177
|
+
totalTrials,
|
|
3035
3178
|
keepCount,
|
|
3036
3179
|
node.mode === "highest",
|
|
3037
3180
|
eps
|
|
@@ -3042,14 +3185,23 @@ function resolve(node, eps = defaultEps) {
|
|
|
3042
3185
|
const rerollOne = !!childDie && (childDie.reroll || 0) >= 1;
|
|
3043
3186
|
return d20RollPMF(node.rollType, rerollOne);
|
|
3044
3187
|
}
|
|
3188
|
+
case "half": {
|
|
3189
|
+
const childPMF = resolve(node.child, eps);
|
|
3190
|
+
return childPMF.scaleDamage(0.5, "floor");
|
|
3191
|
+
}
|
|
3192
|
+
case "maxOf": {
|
|
3193
|
+
const childPMF = resolve(node.child, eps);
|
|
3194
|
+
const count = Math.max(1, Math.floor(node.count));
|
|
3195
|
+
if (count === 1) return childPMF;
|
|
3196
|
+
return computeMaxOfPMF(childPMF, count, eps);
|
|
3197
|
+
}
|
|
3045
3198
|
}
|
|
3046
3199
|
})();
|
|
3047
3200
|
builderPMFCache.set(cacheKey, result);
|
|
3048
3201
|
return result;
|
|
3049
3202
|
}
|
|
3050
3203
|
function pmfFromRollBuilder(rb, eps = defaultEps) {
|
|
3051
|
-
const
|
|
3052
|
-
const ast = astFromRollConfigs(configs) || { type: "constant", value: 0 };
|
|
3204
|
+
const ast = rb.toAST();
|
|
3053
3205
|
return resolve(ast, eps);
|
|
3054
3206
|
}
|
|
3055
3207
|
function resolveSingleDie(die, eps = defaultEps) {
|
|
@@ -3112,6 +3264,8 @@ function findDie(node) {
|
|
|
3112
3264
|
return void 0;
|
|
3113
3265
|
case "sum":
|
|
3114
3266
|
case "d20Roll":
|
|
3267
|
+
case "half":
|
|
3268
|
+
case "maxOf":
|
|
3115
3269
|
return findDie(node.child);
|
|
3116
3270
|
case "keep":
|
|
3117
3271
|
return findDie(node.child.child);
|
|
@@ -3128,6 +3282,38 @@ function getTotalCount(node) {
|
|
|
3128
3282
|
while (cur.type === "keep") cur = cur.child;
|
|
3129
3283
|
return cur.type === "sum" ? Math.max(0, Math.floor(cur.count)) : 0;
|
|
3130
3284
|
}
|
|
3285
|
+
function computeMaxOfPMF(pmf, count, eps = defaultEps) {
|
|
3286
|
+
if (count <= 1) return pmf;
|
|
3287
|
+
const support = pmf.support();
|
|
3288
|
+
const out = /* @__PURE__ */ new Map();
|
|
3289
|
+
if (count <= 6 && support.length <= 20) {
|
|
3290
|
+
let dfs = function(rollsLeft, currentMax, probability) {
|
|
3291
|
+
if (rollsLeft === 0) {
|
|
3292
|
+
out.set(currentMax, (out.get(currentMax) || 0) + probability);
|
|
3293
|
+
return;
|
|
3294
|
+
}
|
|
3295
|
+
for (const value of support) {
|
|
3296
|
+
const p = pmf.pAt(value);
|
|
3297
|
+
if (p > 0) {
|
|
3298
|
+
const newMax = Math.max(currentMax, value);
|
|
3299
|
+
dfs(rollsLeft - 1, newMax, probability * p);
|
|
3300
|
+
}
|
|
3301
|
+
}
|
|
3302
|
+
};
|
|
3303
|
+
dfs(count, -Infinity, 1);
|
|
3304
|
+
} else {
|
|
3305
|
+
const sortedSupport = [...support].sort((a, b) => a - b);
|
|
3306
|
+
for (const value of sortedSupport) {
|
|
3307
|
+
const cdfAtValue = pmf.cdfAt(value);
|
|
3308
|
+
const cdfAtValueMinus1 = value > sortedSupport[0] ? pmf.cdfAt(value - 1) : 0;
|
|
3309
|
+
const probMax = Math.pow(cdfAtValue, count) - Math.pow(cdfAtValueMinus1, count);
|
|
3310
|
+
if (probMax > eps) {
|
|
3311
|
+
out.set(value, probMax);
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
return PMF.fromMap(out, eps);
|
|
3316
|
+
}
|
|
3131
3317
|
function keepSumPMF(single, total, keep, highest, eps = defaultEps) {
|
|
3132
3318
|
if (keep >= total) return single.power(total, eps);
|
|
3133
3319
|
if (keep <= 0) return PMF.delta(0, eps);
|
|
@@ -3136,24 +3322,106 @@ function keepSumPMF(single, total, keep, highest, eps = defaultEps) {
|
|
|
3136
3322
|
const cacheKey = `keep|${pmfSig}|t:${total}|k:${keep}|h:${highest ? 1 : 0}|e:${eps}`;
|
|
3137
3323
|
const cached = builderPMFCache.get(cacheKey);
|
|
3138
3324
|
if (cached) return cached;
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
const
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3325
|
+
if (keep === 1) {
|
|
3326
|
+
if (highest) {
|
|
3327
|
+
return computeMaxOfPMF(single, total, eps);
|
|
3328
|
+
} else {
|
|
3329
|
+
const neg = single.mapDamage((v) => -v);
|
|
3330
|
+
const minPMF = computeMaxOfPMF(neg, total, eps).mapDamage((v) => -v);
|
|
3331
|
+
builderPMFCache.set(cacheKey, minPMF);
|
|
3332
|
+
return minPMF;
|
|
3333
|
+
}
|
|
3334
|
+
}
|
|
3335
|
+
let state = /* @__PURE__ */ new Map();
|
|
3336
|
+
const keyOf = (used, r) => `${used}|${r}`;
|
|
3337
|
+
state.set(keyOf(0, total), /* @__PURE__ */ new Map([[0, 1]]));
|
|
3338
|
+
const valuesDesc = highest ? [...sortedSupport].sort((a, b) => b - a) : [...sortedSupport].sort((a, b) => a - b);
|
|
3339
|
+
const binomPMF = (r, p) => {
|
|
3340
|
+
if (r <= 0) return [1];
|
|
3341
|
+
if (p <= eps) {
|
|
3342
|
+
const arr2 = new Array(r + 1).fill(0);
|
|
3343
|
+
arr2[0] = 1;
|
|
3344
|
+
return arr2;
|
|
3345
|
+
}
|
|
3346
|
+
if (1 - p <= eps) {
|
|
3347
|
+
const arr2 = new Array(r + 1).fill(0);
|
|
3348
|
+
arr2[r] = 1;
|
|
3349
|
+
return arr2;
|
|
3149
3350
|
}
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3351
|
+
const q = 1 - p;
|
|
3352
|
+
const arr = new Array(r + 1).fill(0);
|
|
3353
|
+
arr[0] = Math.pow(q, r);
|
|
3354
|
+
const ratio = p / q;
|
|
3355
|
+
for (let x = 1; x <= r; x++)
|
|
3356
|
+
arr[x] = arr[x - 1] * (r - x + 1) / x * ratio;
|
|
3357
|
+
let s = 0;
|
|
3358
|
+
for (let x = 0; x <= r; x++) s += arr[x];
|
|
3359
|
+
if (Math.abs(1 - s) > 1e-12) for (let x = 0; x <= r; x++) arr[x] /= s;
|
|
3360
|
+
return arr;
|
|
3361
|
+
};
|
|
3362
|
+
const pruneMap = (m, threshold) => {
|
|
3363
|
+
if (threshold <= 0) return m;
|
|
3364
|
+
const out = /* @__PURE__ */ new Map();
|
|
3365
|
+
for (const [sum, pr] of m) if (pr >= threshold) out.set(sum, pr);
|
|
3366
|
+
return out.size === m.size ? m : out;
|
|
3367
|
+
};
|
|
3368
|
+
const pruneState = (st, threshold) => {
|
|
3369
|
+
if (threshold <= 0) return st;
|
|
3370
|
+
const out = /* @__PURE__ */ new Map();
|
|
3371
|
+
for (const [k, m] of st) {
|
|
3372
|
+
const mm = pruneMap(m, threshold);
|
|
3373
|
+
if (mm.size > 0) out.set(k, mm);
|
|
3153
3374
|
}
|
|
3375
|
+
return out;
|
|
3376
|
+
};
|
|
3377
|
+
let processedMass = 0;
|
|
3378
|
+
for (const v of valuesDesc) {
|
|
3379
|
+
const p = single.pAt(v);
|
|
3380
|
+
if (p <= 0) continue;
|
|
3381
|
+
const q = Math.max(eps, 1 - processedMass);
|
|
3382
|
+
const pCond = Math.min(1, p / q);
|
|
3383
|
+
const next = /* @__PURE__ */ new Map();
|
|
3384
|
+
for (const [k, m] of state) {
|
|
3385
|
+
const [usedStr, rStr] = k.split("|");
|
|
3386
|
+
const used = parseInt(usedStr, 10);
|
|
3387
|
+
const r = parseInt(rStr, 10);
|
|
3388
|
+
if (r === 0) {
|
|
3389
|
+
const destKey = keyOf(used, 0);
|
|
3390
|
+
const dest = next.get(destKey) ?? /* @__PURE__ */ new Map();
|
|
3391
|
+
for (const [sum, pr] of m) dest.set(sum, (dest.get(sum) || 0) + pr);
|
|
3392
|
+
next.set(destKey, dest);
|
|
3393
|
+
continue;
|
|
3394
|
+
}
|
|
3395
|
+
const bin = binomPMF(r, pCond);
|
|
3396
|
+
const remainingCapacity = keep - used;
|
|
3397
|
+
for (let x = 0; x <= r; x++) {
|
|
3398
|
+
const px = bin[x];
|
|
3399
|
+
if (px <= eps) continue;
|
|
3400
|
+
const t = Math.min(x, remainingCapacity);
|
|
3401
|
+
const used2 = used + t;
|
|
3402
|
+
const r2 = r - x;
|
|
3403
|
+
const add = t * v;
|
|
3404
|
+
const destKey = keyOf(used2, r2);
|
|
3405
|
+
const dest = next.get(destKey) ?? /* @__PURE__ */ new Map();
|
|
3406
|
+
for (const [sum, pr] of m) {
|
|
3407
|
+
const s2 = sum + add;
|
|
3408
|
+
const prob = pr * px;
|
|
3409
|
+
const cur = dest.get(s2) || 0;
|
|
3410
|
+
const nv = cur + prob;
|
|
3411
|
+
if (nv >= eps) dest.set(s2, nv);
|
|
3412
|
+
}
|
|
3413
|
+
if (dest.size > 0) next.set(destKey, dest);
|
|
3414
|
+
}
|
|
3415
|
+
}
|
|
3416
|
+
state = pruneState(next, eps * 1e-6);
|
|
3417
|
+
processedMass += p;
|
|
3418
|
+
}
|
|
3419
|
+
const finalKey = keyOf(keep, 0);
|
|
3420
|
+
const dist = state.get(finalKey) ?? /* @__PURE__ */ new Map();
|
|
3421
|
+
if (dist.size === 0) {
|
|
3422
|
+
return PMF.emptyMass();
|
|
3154
3423
|
}
|
|
3155
|
-
|
|
3156
|
-
const result = PMF.fromMap(out, eps);
|
|
3424
|
+
const result = PMF.fromMap(dist, eps);
|
|
3157
3425
|
builderPMFCache.set(cacheKey, result);
|
|
3158
3426
|
return result;
|
|
3159
3427
|
}
|
|
@@ -3177,6 +3445,10 @@ function getASTSignature(node) {
|
|
|
3177
3445
|
return `keep{c:${node.count},m:${node.mode},ch:${getASTSignature(
|
|
3178
3446
|
node.child
|
|
3179
3447
|
)}}`;
|
|
3448
|
+
case "half":
|
|
3449
|
+
return `half{ch:${getASTSignature(node.child)}}`;
|
|
3450
|
+
case "maxOf":
|
|
3451
|
+
return `maxOf{c:${node.count},ch:${getASTSignature(node.child)}}`;
|
|
3180
3452
|
case "add": {
|
|
3181
3453
|
let constantValue = 0;
|
|
3182
3454
|
const otherChildrenSigs = [];
|
|
@@ -3236,7 +3508,12 @@ var AttackBuilder = class _AttackBuilder {
|
|
|
3236
3508
|
if (this.hitEffect) {
|
|
3237
3509
|
effectPart = `(${this.hitEffect.toExpression()})`;
|
|
3238
3510
|
if (this.critEffect !== null) {
|
|
3239
|
-
|
|
3511
|
+
let crit;
|
|
3512
|
+
if (this.critEffect) {
|
|
3513
|
+
crit = this.critEffect;
|
|
3514
|
+
} else {
|
|
3515
|
+
crit = this.hitEffect?.copy().doubleDice() ?? RollBuilder.fromArgs(0);
|
|
3516
|
+
}
|
|
3240
3517
|
const critThreshold = this.check.critThreshold;
|
|
3241
3518
|
if (critThreshold < 15 || critThreshold > 20) {
|
|
3242
3519
|
throw new Error(
|
|
@@ -3548,6 +3825,8 @@ RollBuilder.prototype.dc = function(saveDC) {
|
|
|
3548
3825
|
|
|
3549
3826
|
exports.ACBuilder = ACBuilder;
|
|
3550
3827
|
exports.DCBuilder = DCBuilder;
|
|
3828
|
+
exports.HalfRollBuilder = HalfRollBuilder;
|
|
3829
|
+
exports.MaxOfRollBuilder = MaxOfRollBuilder;
|
|
3551
3830
|
exports.RollBuilder = RollBuilder;
|
|
3552
3831
|
exports.SaveBuilder = SaveBuilder;
|
|
3553
3832
|
exports.builderPMFCache = builderPMFCache;
|