@yipe/dice 0.8.0 → 0.8.1

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.
@@ -4,6 +4,8 @@ import { SaveBuilder } from "./save.js";
4
4
  interface SaveConfig {
5
5
  dc: number;
6
6
  }
7
+ /** Clears the DC-check PMF cache (test/bench seam). */
8
+ export declare function clearDCCache(): void;
7
9
  export declare class DCBuilder extends RollBuilder {
8
10
  private readonly saveConfig;
9
11
  constructor(baseRoll: RollBuilder, saveConfig?: SaveConfig);
@@ -20,6 +22,12 @@ export declare class DCBuilder extends RollBuilder {
20
22
  onSaveFailure(count: number, sides: number, modifier: number): SaveBuilder;
21
23
  withElvenAccuracy(): never;
22
24
  toExpression(): string;
25
+ /**
26
+ * The DC check's PMF is fully determined by the save DC plus everything `toPMF` below reads off the roll
27
+ * configs (`rollType`, `baseReroll`, `modifier`, bonus dice) — all of which `super.cacheKey()` already
28
+ * serializes. So extend the base key with the DC, mirroring {@link AlwaysHitBuilder.cacheKey}.
29
+ */
30
+ cacheKey(): string | null;
23
31
  toPMF(eps?: number): PMF;
24
32
  }
25
33
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"dc.d.ts","sourceRoot":"","sources":["../../src/builder/dc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,qBAAa,SAAU,SAAQ,WAAW;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IAExC,YAAY,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,UAAU,EAGzD;IAEQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAOrC;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEQ,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,SAAS,CAGhD;IAEQ,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAG1C;IAED,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAAC;IAC7C,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,WAAW,CAAC;IAC5D,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IACzD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9E,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;IAMlE,iBAAiB,IAAI,KAAK,CAIlC;IAGQ,YAAY,IAAI,MAAM,CAK9B;IAEQ,KAAK,CAAC,GAAG,GAAE,MAAU,GAAG,GAAG,CA2BnC;CACF"}
1
+ {"version":3,"file":"dc.d.ts","sourceRoot":"","sources":["../../src/builder/dc.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAGjC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;CACZ;AAQD,uDAAuD;AACvD,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,qBAAa,SAAU,SAAQ,WAAW;IACxC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IAExC,YAAY,QAAQ,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,UAAU,EAGzD;IAEQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAOrC;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAEQ,GAAG,CAAC,WAAW,EAAE,WAAW,GAAG,SAAS,CAGhD;IAEQ,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAG1C;IAED,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAAC;IACxC,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAAC;IAC7C,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,WAAW,CAAC;IAC5D,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;IACzD,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9E,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,CAAC;IAMlE,iBAAiB,IAAI,KAAK,CAIlC;IAGQ,YAAY,IAAI,MAAM,CAK9B;IAED;;;;OAIG;IACM,QAAQ,IAAI,MAAM,GAAG,IAAI,CAGjC;IAEQ,KAAK,CAAC,GAAG,GAAE,MAAU,GAAG,GAAG,CAoCnC;CACF"}
@@ -3454,6 +3454,10 @@ function d20PMF(rerollOne) {
3454
3454
  }
3455
3455
 
3456
3456
  // src/builder/roll.ts
3457
+ var rollPMFCache = new LRUCache(4e3);
3458
+ function clearRollCache() {
3459
+ rollPMFCache.clear();
3460
+ }
3457
3461
  var defaultConfig = {
3458
3462
  count: 1,
3459
3463
  sides: 0,
@@ -3866,8 +3870,16 @@ var RollBuilder = class _RollBuilder {
3866
3870
  }
3867
3871
  return result.replace(/\+ -/g, "-");
3868
3872
  }
3873
+ // Main AST entry point. Cached by the cheap config key across identical rebuilds; see `rollPMFCache`.
3869
3874
  toPMF(eps = 0) {
3870
- return pmfFromRollBuilder(this, eps);
3875
+ const key = this.cacheKey();
3876
+ if (key === null) return pmfFromRollBuilder(this, eps);
3877
+ const fullKey = `${key}*e${eps}`;
3878
+ const cached = rollPMFCache.get(fullKey);
3879
+ if (cached) return cached;
3880
+ const pmf = pmfFromRollBuilder(this, eps);
3881
+ rollPMFCache.set(fullKey, pmf);
3882
+ return pmf;
3871
3883
  }
3872
3884
  get pmf() {
3873
3885
  return this.toPMF();
@@ -5296,6 +5308,10 @@ RollBuilder.prototype.ac = function(targetAC) {
5296
5308
  };
5297
5309
 
5298
5310
  // src/builder/save.ts
5311
+ var savePMFCache = new LRUCache(4e3);
5312
+ function clearSaveCache() {
5313
+ savePMFCache.clear();
5314
+ }
5299
5315
  var SaveBuilder = class _SaveBuilder {
5300
5316
  constructor(check, failureEffect, saveOutcome = "normal") {
5301
5317
  this.check = check;
@@ -5332,9 +5348,32 @@ var SaveBuilder = class _SaveBuilder {
5332
5348
  weights: { success: psuccess, fail: pfail }
5333
5349
  };
5334
5350
  }
5335
- // By default, create PMF with no pruning
5351
+ /**
5352
+ * A cheap, complete key for this save's resolved PMF, or `null` when it can't be cached soundly.
5353
+ * {@link resolve} reads exactly three things: the DC check (via `resolveProbabilities`), the failure
5354
+ * effect's PMF, and the save outcome — so composing their keys pins it. A `ParsedRollBuilder` failure
5355
+ * effect returns `null`, which correctly forces this uncached.
5356
+ */
5357
+ cacheKey(eps) {
5358
+ const checkKey = this.check.cacheKey();
5359
+ if (checkKey === null) return null;
5360
+ let failKey = "";
5361
+ if (this.failureEffect) {
5362
+ const k = this.failureEffect.cacheKey();
5363
+ if (k === null) return null;
5364
+ failKey = k;
5365
+ }
5366
+ return `${checkKey}*F${failKey}*O${this.saveOutcome}*e${eps}`;
5367
+ }
5368
+ // By default, create PMF with no pruning. Cached by the cheap config key across identical rebuilds.
5336
5369
  toPMF(eps = 0) {
5337
- return this.resolve(eps).pmf;
5370
+ const key = this.cacheKey(eps);
5371
+ if (key === null) return this.resolve(eps).pmf;
5372
+ const cached = savePMFCache.get(key);
5373
+ if (cached) return cached;
5374
+ const pmf = this.resolve(eps).pmf;
5375
+ savePMFCache.set(key, pmf);
5376
+ return pmf;
5338
5377
  }
5339
5378
  get pmf() {
5340
5379
  return this.toPMF();
@@ -5370,6 +5409,10 @@ function resolveProbabilities(check) {
5370
5409
  }
5371
5410
 
5372
5411
  // src/builder/dc.ts
5412
+ var dcPMFCache = new LRUCache(4e3);
5413
+ function clearDCCache() {
5414
+ dcPMFCache.clear();
5415
+ }
5373
5416
  var DCBuilder = class _DCBuilder extends RollBuilder {
5374
5417
  constructor(baseRoll, saveConfig) {
5375
5418
  super(baseRoll.getSubRollConfigs());
@@ -5410,7 +5453,22 @@ var DCBuilder = class _DCBuilder extends RollBuilder {
5410
5453
  const expression = new RollBuilder(allConfigs).toExpression();
5411
5454
  return `(${expression} DC ${this.saveConfig.dc})`;
5412
5455
  }
5456
+ /**
5457
+ * The DC check's PMF is fully determined by the save DC plus everything `toPMF` below reads off the roll
5458
+ * configs (`rollType`, `baseReroll`, `modifier`, bonus dice) — all of which `super.cacheKey()` already
5459
+ * serializes. So extend the base key with the DC, mirroring {@link AlwaysHitBuilder.cacheKey}.
5460
+ */
5461
+ cacheKey() {
5462
+ const base = super.cacheKey();
5463
+ return base === null ? null : `DC|${this.saveConfig.dc}|${base}`;
5464
+ }
5413
5465
  toPMF(eps = 0) {
5466
+ const key = this.cacheKey();
5467
+ const fullKey = key === null ? null : `${key}*e${eps}`;
5468
+ if (fullKey !== null) {
5469
+ const cached = dcPMFCache.get(fullKey);
5470
+ if (cached) return cached;
5471
+ }
5414
5472
  const saveDC = this.saveDC;
5415
5473
  const rollType = this.rollType;
5416
5474
  const rerollOne = this.baseReroll > 0;
@@ -5432,7 +5490,9 @@ var DCBuilder = class _DCBuilder extends RollBuilder {
5432
5490
  [0, psuccess > 0 ? psuccess : 0],
5433
5491
  [1, pfail > 0 ? pfail : 0]
5434
5492
  ]);
5435
- return PMF.fromMap(m, eps);
5493
+ const pmf = PMF.fromMap(m, eps);
5494
+ if (fullKey !== null) dcPMFCache.set(fullKey, pmf);
5495
+ return pmf;
5436
5496
  }
5437
5497
  };
5438
5498
  RollBuilder.prototype.dc = function(saveDC) {
@@ -5454,6 +5514,9 @@ exports.SaveBuilder = SaveBuilder;
5454
5514
  exports.ScaleRollBuilder = ScaleRollBuilder;
5455
5515
  exports.builderPMFCache = builderPMFCache;
5456
5516
  exports.clearAttackCache = clearAttackCache;
5517
+ exports.clearDCCache = clearDCCache;
5518
+ exports.clearRollCache = clearRollCache;
5519
+ exports.clearSaveCache = clearSaveCache;
5457
5520
  exports.d = d;
5458
5521
  exports.d10 = d10;
5459
5522
  exports.d100 = d100;