@yipe/dice 0.2.13 → 0.2.15

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,4 +1,4 @@
1
- import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-D1p2Re-J.cjs';
1
+ import { P as PMF, C as CritConfig, i as DiceQuery, L as LRUCache } from '../pmf-CYaEbY7m.cjs';
2
2
 
3
3
  type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
4
4
  type DieNode = {
@@ -138,6 +138,7 @@ declare class RollBuilder {
138
138
  addRoll(count?: number): RollBuilder;
139
139
  scaleDice(scale: number): RollBuilder;
140
140
  doubleDice(): RollBuilder;
141
+ alwaysHits(): AlwaysHitBuilder;
141
142
  copy(): RollBuilder;
142
143
  d4: () => RollBuilder;
143
144
  d6: () => RollBuilder;
@@ -182,19 +183,42 @@ declare class MaxOfRollBuilder extends RollBuilder {
182
183
  get lastConfig(): any;
183
184
  getSubRollConfigs(): readonly RollConfig[];
184
185
  toExpression(): string;
185
- private findDieInAST;
186
186
  toAST(): ExpressionNode;
187
187
  toPMF(eps?: number): PMF;
188
188
  copy(): MaxOfRollBuilder;
189
189
  }
190
+ declare class AlwaysHitBuilder extends RollBuilder {
191
+ readonly attackConfig: CritConfig;
192
+ constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
193
+ onHit(val: number): AttackBuilder;
194
+ onHit(val: RollBuilder): AttackBuilder;
195
+ onHit(count: number, die: RollBuilder): AttackBuilder;
196
+ onHit(count: number, sides: number): AttackBuilder;
197
+ onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
198
+ onHit(count: number, sides: number, modifier: number): AttackBuilder;
199
+ get critThreshold(): number;
200
+ critOn(critThreshold: number): AlwaysHitBuilder;
201
+ toExpression(): string;
202
+ toPMF(): PMF;
203
+ copy(): AlwaysHitBuilder;
204
+ }
205
+ declare class AlwaysCritBuilder extends RollBuilder {
206
+ readonly attackConfig: CritConfig;
207
+ constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
208
+ get critThreshold(): number;
209
+ critOn(critThreshold: number): AlwaysHitBuilder;
210
+ toExpression(): string;
211
+ toPMF(): PMF;
212
+ copy(): AlwaysHitBuilder;
213
+ }
190
214
 
191
215
  type ActionEffect = RollBuilder;
192
216
  declare class AttackBuilder implements CheckBuilder {
193
- readonly check: ACBuilder;
217
+ readonly check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder;
194
218
  private readonly hitEffect?;
195
219
  private readonly critEffect?;
196
220
  private readonly missEffect?;
197
- constructor(check: ACBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
221
+ constructor(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
198
222
  onCrit(val: number): AttackBuilder;
199
223
  onCrit(val: RollBuilder): AttackBuilder;
200
224
  onCrit(count: number, die: RollBuilder): AttackBuilder;
@@ -209,7 +233,7 @@ declare class AttackBuilder implements CheckBuilder {
209
233
  onMiss(count: number, sides: number, modifier: number): AttackBuilder;
210
234
  noCrit(): AttackBuilder;
211
235
  toExpression(): string;
212
- resolveProbabilities(check: ACBuilder, eps?: number): {
236
+ resolveProbabilities(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, eps?: number): {
213
237
  pSuccess: number;
214
238
  pHit: number;
215
239
  pCrit: number;
@@ -299,4 +323,4 @@ declare const flat: (n: number) => RollBuilder;
299
323
  declare const roll: RollFactory;
300
324
  declare const builderPMFCache: LRUCache<string, PMF>;
301
325
 
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 };
326
+ export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, 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,4 +1,4 @@
1
- import { P as PMF, i as DiceQuery, L as LRUCache } from '../pmf-D1p2Re-J.js';
1
+ import { P as PMF, C as CritConfig, i as DiceQuery, L as LRUCache } from '../pmf-CYaEbY7m.js';
2
2
 
3
3
  type ExpressionNode = DieNode | ConstantNode | SumNode | AddNode | KeepNode | D20RollNode | HalfNode | MaxOfNode;
4
4
  type DieNode = {
@@ -138,6 +138,7 @@ declare class RollBuilder {
138
138
  addRoll(count?: number): RollBuilder;
139
139
  scaleDice(scale: number): RollBuilder;
140
140
  doubleDice(): RollBuilder;
141
+ alwaysHits(): AlwaysHitBuilder;
141
142
  copy(): RollBuilder;
142
143
  d4: () => RollBuilder;
143
144
  d6: () => RollBuilder;
@@ -182,19 +183,42 @@ declare class MaxOfRollBuilder extends RollBuilder {
182
183
  get lastConfig(): any;
183
184
  getSubRollConfigs(): readonly RollConfig[];
184
185
  toExpression(): string;
185
- private findDieInAST;
186
186
  toAST(): ExpressionNode;
187
187
  toPMF(eps?: number): PMF;
188
188
  copy(): MaxOfRollBuilder;
189
189
  }
190
+ declare class AlwaysHitBuilder extends RollBuilder {
191
+ readonly attackConfig: CritConfig;
192
+ constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
193
+ onHit(val: number): AttackBuilder;
194
+ onHit(val: RollBuilder): AttackBuilder;
195
+ onHit(count: number, die: RollBuilder): AttackBuilder;
196
+ onHit(count: number, sides: number): AttackBuilder;
197
+ onHit(count: number, die: RollBuilder, modifier: number): AttackBuilder;
198
+ onHit(count: number, sides: number, modifier: number): AttackBuilder;
199
+ get critThreshold(): number;
200
+ critOn(critThreshold: number): AlwaysHitBuilder;
201
+ toExpression(): string;
202
+ toPMF(): PMF;
203
+ copy(): AlwaysHitBuilder;
204
+ }
205
+ declare class AlwaysCritBuilder extends RollBuilder {
206
+ readonly attackConfig: CritConfig;
207
+ constructor(baseRoll: RollBuilder, attackConfig?: CritConfig);
208
+ get critThreshold(): number;
209
+ critOn(critThreshold: number): AlwaysHitBuilder;
210
+ toExpression(): string;
211
+ toPMF(): PMF;
212
+ copy(): AlwaysHitBuilder;
213
+ }
190
214
 
191
215
  type ActionEffect = RollBuilder;
192
216
  declare class AttackBuilder implements CheckBuilder {
193
- readonly check: ACBuilder;
217
+ readonly check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder;
194
218
  private readonly hitEffect?;
195
219
  private readonly critEffect?;
196
220
  private readonly missEffect?;
197
- constructor(check: ACBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
221
+ constructor(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, hitEffect?: ActionEffect, critEffect?: ActionEffect | null, missEffect?: ActionEffect);
198
222
  onCrit(val: number): AttackBuilder;
199
223
  onCrit(val: RollBuilder): AttackBuilder;
200
224
  onCrit(count: number, die: RollBuilder): AttackBuilder;
@@ -209,7 +233,7 @@ declare class AttackBuilder implements CheckBuilder {
209
233
  onMiss(count: number, sides: number, modifier: number): AttackBuilder;
210
234
  noCrit(): AttackBuilder;
211
235
  toExpression(): string;
212
- resolveProbabilities(check: ACBuilder, eps?: number): {
236
+ resolveProbabilities(check: ACBuilder | AlwaysHitBuilder | AlwaysCritBuilder, eps?: number): {
213
237
  pSuccess: number;
214
238
  pHit: number;
215
239
  pCrit: number;
@@ -299,4 +323,4 @@ declare const flat: (n: number) => RollBuilder;
299
323
  declare const roll: RollFactory;
300
324
  declare const builderPMFCache: LRUCache<string, PMF>;
301
325
 
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 };
326
+ export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, 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,14 +2657,6 @@ 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
- }
2668
2660
  const newConfigs = this.getSubRollConfigs().map((config) => {
2669
2661
  if (!config.sides || config.sides <= 0) return config;
2670
2662
  return { ...config, count: config.count * scaleInt };
@@ -2674,6 +2666,9 @@ var RollBuilder = class _RollBuilder {
2674
2666
  doubleDice() {
2675
2667
  return this.scaleDice(2);
2676
2668
  }
2669
+ alwaysHits() {
2670
+ return new AlwaysHitBuilder(this);
2671
+ }
2677
2672
  copy() {
2678
2673
  return new this.constructor(this.getSubRollConfigs());
2679
2674
  }
@@ -2937,17 +2932,6 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
2937
2932
  }
2938
2933
  return `max${this.count}(?d?)`;
2939
2934
  }
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
2935
  toAST() {
2952
2936
  if (this.diceCount && this.diceSides) {
2953
2937
  const sumChild = {
@@ -2989,6 +2973,80 @@ var MaxOfRollBuilder = class _MaxOfRollBuilder extends RollBuilder {
2989
2973
  return new _MaxOfRollBuilder(this.innerRoll.copy(), this.count);
2990
2974
  }
2991
2975
  };
2976
+ var AlwaysHitBuilder = class _AlwaysHitBuilder extends RollBuilder {
2977
+ constructor(baseRoll, attackConfig) {
2978
+ super(baseRoll.getSubRollConfigs());
2979
+ __publicField(this, "attackConfig");
2980
+ if (attackConfig) {
2981
+ this.attackConfig = { ...attackConfig };
2982
+ } else {
2983
+ this.attackConfig = { critThreshold: 20 };
2984
+ }
2985
+ }
2986
+ onHit(...args) {
2987
+ const damageRoll = RollBuilder.fromArgs(...args);
2988
+ return new AttackBuilder(this, damageRoll);
2989
+ }
2990
+ get critThreshold() {
2991
+ return this.attackConfig.critThreshold;
2992
+ }
2993
+ // TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
2994
+ critOn(critThreshold) {
2995
+ const newConfig = { critThreshold };
2996
+ return new _AlwaysHitBuilder(this, newConfig);
2997
+ }
2998
+ // Legacy expressions
2999
+ toExpression() {
3000
+ const configs = this.getSubRollConfigs();
3001
+ return new RollBuilder(configs).toExpression();
3002
+ }
3003
+ toPMF() {
3004
+ const rollType = this.rollType;
3005
+ const rerollOne = this.baseReroll > 0;
3006
+ return d20RollPMF(rollType, rerollOne);
3007
+ }
3008
+ copy() {
3009
+ const baseCopy = new RollBuilder(this.getSubRollConfigs());
3010
+ const critThreshold = this.critThreshold;
3011
+ const newConfig = { critThreshold };
3012
+ return new _AlwaysHitBuilder(baseCopy, newConfig);
3013
+ }
3014
+ };
3015
+ var AlwaysCritBuilder = class extends RollBuilder {
3016
+ constructor(baseRoll, attackConfig) {
3017
+ super(baseRoll.getSubRollConfigs());
3018
+ __publicField(this, "attackConfig");
3019
+ if (attackConfig) {
3020
+ this.attackConfig = { ...attackConfig };
3021
+ } else {
3022
+ this.attackConfig = { critThreshold: 20 };
3023
+ }
3024
+ }
3025
+ get critThreshold() {
3026
+ return this.attackConfig.critThreshold;
3027
+ }
3028
+ // TODO - move this to AC Builder… or if we create a DC builder that has critOn, throw an error?
3029
+ critOn(critThreshold) {
3030
+ const newConfig = { critThreshold };
3031
+ return new AlwaysHitBuilder(this, newConfig);
3032
+ }
3033
+ // Legacy expressions
3034
+ toExpression() {
3035
+ const configs = this.getSubRollConfigs();
3036
+ return new RollBuilder(configs).toExpression();
3037
+ }
3038
+ toPMF() {
3039
+ const rollType = this.rollType;
3040
+ const rerollOne = this.baseReroll > 0;
3041
+ return d20RollPMF(rollType, rerollOne);
3042
+ }
3043
+ copy() {
3044
+ const baseCopy = new RollBuilder(this.getSubRollConfigs());
3045
+ const critThreshold = this.critThreshold;
3046
+ const newConfig = { critThreshold };
3047
+ return new AlwaysHitBuilder(baseCopy, newConfig);
3048
+ }
3049
+ };
2992
3050
 
2993
3051
  // src/builder/factory.ts
2994
3052
  var rollFn = (count, sidesOrDie, modifier) => {
@@ -3541,11 +3599,25 @@ var AttackBuilder = class _AttackBuilder {
3541
3599
  return `${checkPart} * ${effectPart}`;
3542
3600
  }
3543
3601
  resolveProbabilities(check, eps = 0) {
3544
- const ac = check.attackConfig.ac;
3602
+ if (check instanceof AlwaysCritBuilder) {
3603
+ return { pSuccess: 1, pHit: 0, pCrit: 1, pMiss: 0 };
3604
+ }
3545
3605
  const rollType = check.rollType;
3546
3606
  const rerollOne = check.baseReroll > 0;
3547
3607
  const critThreshold = check.critThreshold;
3548
3608
  const d202 = d20RollPMF(rollType, rerollOne);
3609
+ if (check instanceof AlwaysHitBuilder) {
3610
+ let pCrit = 0;
3611
+ for (const [r, rec] of d202) {
3612
+ const pr = typeof rec === "number" ? rec : rec.p;
3613
+ if (pr <= 0) continue;
3614
+ if (r >= critThreshold) pCrit += pr;
3615
+ }
3616
+ const pHit = 1 - pCrit;
3617
+ const pMiss = 0;
3618
+ return { pSuccess: 1, pHit, pCrit, pMiss };
3619
+ }
3620
+ const ac = check.attackConfig.ac;
3549
3621
  const staticMod = this.check.modifier;
3550
3622
  const bonusDicePMFs = this.check.getBonusDicePMFs(this.check, eps);
3551
3623
  const bonusPMF = bonusDicePMFs.length ? PMF.convolveMany(bonusDicePMFs, eps) : PMF.delta(0, eps);
@@ -3830,6 +3902,6 @@ RollBuilder.prototype.dc = function(saveDC) {
3830
3902
  return new DCBuilder(this).dc(saveDC);
3831
3903
  };
3832
3904
 
3833
- export { ACBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
3905
+ export { ACBuilder, AlwaysCritBuilder, AlwaysHitBuilder, DCBuilder, HalfRollBuilder, MaxOfRollBuilder, RollBuilder, SaveBuilder, builderPMFCache, d, d10, d100, d12, d20, d4, d6, d8, defaultConfig, flat, hd20, roll };
3834
3906
  //# sourceMappingURL=index.js.map
3835
3907
  //# sourceMappingURL=index.js.map