@yipe/dice 0.5.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 (57) 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.d.ts +8 -429
  16. package/dist/builder/index.d.ts.map +1 -0
  17. package/dist/builder/nodes.d.ts +61 -0
  18. package/dist/builder/nodes.d.ts.map +1 -0
  19. package/dist/builder/prob.d.ts +3 -0
  20. package/dist/builder/prob.d.ts.map +1 -0
  21. package/dist/builder/roll.d.ts +205 -0
  22. package/dist/builder/roll.d.ts.map +1 -0
  23. package/dist/builder/save.d.ts +19 -0
  24. package/dist/builder/save.d.ts.map +1 -0
  25. package/dist/builder/types.d.ts +66 -0
  26. package/dist/builder/types.d.ts.map +1 -0
  27. package/dist/common/bounce.d.ts +32 -0
  28. package/dist/common/bounce.d.ts.map +1 -0
  29. package/dist/common/errors.d.ts +26 -0
  30. package/dist/common/errors.d.ts.map +1 -0
  31. package/dist/common/lru-cache.d.ts +17 -0
  32. package/dist/common/lru-cache.d.ts.map +1 -0
  33. package/dist/common/types.d.ts +65 -0
  34. package/dist/common/types.d.ts.map +1 -0
  35. package/dist/index.d.ts +9 -111
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/parser/dice.d.ts +70 -0
  38. package/dist/parser/dice.d.ts.map +1 -0
  39. package/dist/parser/parser.d.ts +14 -0
  40. package/dist/parser/parser.d.ts.map +1 -0
  41. package/dist/pmf/mixture.d.ts +37 -0
  42. package/dist/pmf/mixture.d.ts.map +1 -0
  43. package/dist/pmf/pmf.d.ts +380 -0
  44. package/dist/pmf/pmf.d.ts.map +1 -0
  45. package/dist/{pmf-D5VRghZI.d.cts → pmf/query.d.ts} +6 -464
  46. package/dist/pmf/query.d.ts.map +1 -0
  47. package/package.json +16 -15
  48. package/.claude/worktrees/amazing-matsumoto-27220c/LICENSE +0 -21
  49. package/.claude/worktrees/amazing-matsumoto-27220c/README.md +0 -518
  50. package/.claude/worktrees/vibrant-lovelace-0cc9e7/LICENSE +0 -21
  51. package/.claude/worktrees/vibrant-lovelace-0cc9e7/README.md +0 -518
  52. package/.claude/worktrees/wizardly-mclean-e375de/LICENSE +0 -21
  53. package/.claude/worktrees/wizardly-mclean-e375de/README.md +0 -518
  54. package/CHANGELOG.md +0 -239
  55. package/dist/builder/index.d.cts +0 -429
  56. package/dist/index.d.cts +0 -111
  57. package/dist/pmf-D5VRghZI.d.ts +0 -1129
@@ -1,85 +1,5 @@
1
- /**
2
- * Simple LRU cache implementation
3
- */
4
- declare class LRUCache<K, V> {
5
- private readonly maxSize;
6
- private cache;
7
- constructor(maxSize?: number);
8
- get(key: K): V | undefined;
9
- delete(key: K): void;
10
- set(key: K, value: V): this;
11
- clear(): void;
12
- get size(): number;
13
- has(key: K): boolean;
14
- keys(): IterableIterator<K>;
15
- values(): IterableIterator<V>;
16
- }
17
-
18
- /** Mapping from outcome label to probability mass or damage attribution. */
19
- type OutcomeLabelMap = Partial<Record<string, number>>;
20
- /** Computational epsilon for pruning negligible probabilities. */
21
- declare const EPS = 1e-12;
22
- /** A probability bin for a specific damage value. */
23
- interface Bin {
24
- /** Total probability mass at this damage value. */
25
- p: number;
26
- /** Per-outcome probability mass contributions at this damage. */
27
- count: OutcomeLabelMap;
28
- /** Optional per-outcome damage attribution at this damage. */
29
- attr?: OutcomeLabelMap;
30
- }
31
- interface CritConfig {
32
- critThreshold: number;
33
- }
34
- /** Simple mapping from damage value to probability. */
35
- type DamageDistribution = Record<number, number>;
36
- /** Canonical outcome labels supported by the query helpers. */
37
- type OutcomeType = "crit" | "hit" | "missNone" | "missDamage" | "saveHalf" | "saveFail" | "pc";
38
- type Rounding = "none" | "floor" | "round" | "ceil";
39
- /** How a d20 attack roll resolves: single die, keep-highest of 2/3, or keep-lowest of 2. */
40
- type RollType = "flat" | "advantage" | "disadvantage" | "elven accuracy";
41
- /**
42
- * P(critical hit) for the given crit window and d20 {@link RollType}.
43
- *
44
- * `critRange` is the number of top faces that crit (1 for a natural 20, 2 for
45
- * 19–20, …), so a single die crits with probability `critRange / 20`. Advantage
46
- * rolls two d20s / elven accuracy three, keeping the best; disadvantage keeps
47
- * the worst of two.
48
- */
49
- declare function critProbability(critRange: number, rollType?: RollType): number;
50
- /**
51
- * The canonical "clean miss" outcome — a point of zero damage with no rider.
52
- * This is the {@link OutcomeType} that attribution charts and outcome stats key
53
- * on, and is distinct from the builder's attack-resolution `miss` weight label.
54
- */
55
- declare const MISS_NONE_OUTCOME: OutcomeType;
56
- /**
57
- * All outcome types in canonical severity order — clean miss → crit. This is
58
- * also the natural stacking order for attribution charts (least- to
59
- * most-impactful, bottom → top). Enumerates every {@link OutcomeType} exactly
60
- * once; use it instead of hand-maintained per-consumer outcome tables.
61
- */
62
- declare const ALL_OUTCOME_TYPES: OutcomeType[];
63
- /**
64
- * Outcome types in display order for stats / breakdown rows — most prominent
65
- * first (crit, hit, …) down to the clean miss.
66
- */
67
- declare const OUTCOME_DISPLAY_ORDER: OutcomeType[];
68
- /**
69
- * Sort outcome labels by a canonical order (defaults to {@link ALL_OUTCOME_TYPES}).
70
- * Labels not present in `order` sort after known ones, alphabetically — so
71
- * ad-hoc/test labels outside the {@link OutcomeType} union stay stable.
72
- */
73
- declare function sortOutcomes<T extends string>(outcomes: Iterable<T>, order?: readonly string[]): T[];
74
- declare const onAnyHit: OutcomeType[];
75
- declare const onCritOnly: OutcomeType[];
76
- declare const onHitOnly: OutcomeType[];
77
- declare const onMissOnly: OutcomeType[];
78
- declare const onMissDamageOnly: OutcomeType[];
79
- declare const onSaveHalfOnly: OutcomeType[];
80
- declare const onSaveFailOnly: OutcomeType[];
81
- declare const onPotentCantripOnly: OutcomeType[];
82
-
1
+ import type { OutcomeType } from "../common/types.js";
2
+ import { PMF } from "./pmf.js";
83
3
  /**
84
4
  * Query interface for analyzing dice roll probability distributions.
85
5
  *
@@ -90,7 +10,7 @@ declare const onPotentCantripOnly: OutcomeType[];
90
10
  * - Data export (charts, tables, visualizations)
91
11
  *
92
12
  */
93
- declare class DiceQuery {
13
+ export declare class DiceQuery {
94
14
  readonly singles: PMF[];
95
15
  private readonly _eps;
96
16
  private readonly _combinedProvided;
@@ -729,7 +649,7 @@ declare class DiceQuery {
729
649
  */
730
650
  firstSuccessSplit(successOutcome: OutcomeType | OutcomeType[], subsetOutcome: OutcomeType | OutcomeType[], eps?: number): readonly [pSuccess: number, pSubset: number, pAny: number, pNone: number];
731
651
  }
732
- type OutcomeSnapshot = {
652
+ export type OutcomeSnapshot = {
733
653
  atLeastOneProbability: number;
734
654
  allProbability: number;
735
655
  damageRange: {
@@ -738,7 +658,7 @@ type OutcomeSnapshot = {
738
658
  max: number;
739
659
  };
740
660
  };
741
- type Snapshot = {
661
+ export type Snapshot = {
742
662
  averageDPR: number;
743
663
  damageChance: number;
744
664
  percentiles: {
@@ -748,382 +668,4 @@ type Snapshot = {
748
668
  };
749
669
  outcomes: Map<OutcomeType, OutcomeSnapshot>;
750
670
  };
751
-
752
- declare const pmfCache: LRUCache<string, PMF>;
753
- /**
754
- * Probability Mass Function for discrete damage distributions.
755
- */
756
- declare class PMF {
757
- readonly map: Map<number, Bin>;
758
- readonly epsilon: number;
759
- readonly normalized: boolean;
760
- readonly identifier: string;
761
- private _preservedProvenance;
762
- private static __anonIdCounter;
763
- private _support?;
764
- private _min?;
765
- private _max?;
766
- private _totalMass?;
767
- private _mean?;
768
- private _variance?;
769
- private _stdev?;
770
- private _fingerprint?;
771
- constructor(map?: Map<number, Bin>, epsilon?: number, normalized?: boolean, identifier?: string, _preservedProvenance?: boolean);
772
- static empty(epsilon?: number, identifier?: string): PMF;
773
- static zero(epsilon?: number): PMF;
774
- static delta(value: number, epsilon?: number): PMF;
775
- /**
776
- * Point mass at damage 0 tagged with the canonical `missNone` outcome.
777
- *
778
- * Differs from {@link PMF.zero}, which labels its zero bin `miss` — the
779
- * builder's attack-resolution vocabulary. This uses the `missNone`
780
- * {@link OutcomeType} that the attribution charts and outcome stats key on,
781
- * so it is the correct "clean miss / no damage" delta for provenance-aware
782
- * mixtures feeding those consumers.
783
- */
784
- static missNone(epsilon?: number): PMF;
785
- static emptyMass(): PMF;
786
- [Symbol.iterator](): IterableIterator<[number, Bin]>;
787
- static clearCache(): void;
788
- /**
789
- * Creates a conditional PMF from two branches (success and failure) and a probability.
790
- * This is the core logic for modeling any probabilistic event where there are two
791
- * distinct outcomes.
792
- */
793
- static branch(successPMF: PMF, failurePMF: PMF, successProbability: number): PMF;
794
- /**
795
- * withProbability()
796
- *
797
- * A convenience wrapper around branch() for the common case where the "failure" branch is always zero().
798
- *
799
- * Think of this as a shortcut for:
800
- * pmf.gate(p, PMF.zero())
801
- *
802
- * Use this to model a *single* Bernoulli event — an outcome that either happens or doesn't,
803
- * like an opportunity attack that occurs with probability p, or a single attack that either hits or misses.
804
- *
805
- * This is **not** for combining multiple independent attacks or mutually exclusive multi-outcome scenarios.
806
- * - For multiple independent swings, use DiceQuery with separate PMFs for each attack.
807
- * - For modeling "first success" logic across multiple attacks (like Sneak Attack or Smite)
808
- * use query.firstSuccessSplit() to get the exact probabilities.
809
- * - For scenarios with several mutually exclusive outcomes (like crit vs hit vs none), use PMF.exclusive().
810
- *
811
- */
812
- static withProbability(successPMF: PMF, probability: number): PMF;
813
- /**
814
- * gate()
815
- *
816
- * A conditional wrapper around branch() that applies this PMF with probability `p`,
817
- * and applies a provided fallback PMF otherwise.
818
- *
819
- * This is useful for modeling a binary choice between two outcomes:
820
- * - The "success" outcome (this PMF) happens with probability `p`.
821
- * - The "failure" outcome (fallback PMF) happens with probability `1 - p`.
822
- *
823
- * Examples:
824
- * - 25% chance to include an opportunity attack, otherwise nothing:
825
- * attackPMF.gate(0.25, PMF.zero())
826
- *
827
- * - 50% chance to deal fireball damage, otherwise cone of cold damage:
828
- * fireballPMF.gate(0.5, coneOfColdPMF)
829
- *
830
- * Relationship to other helpers:
831
- * - **withProbability()** is a shortcut for the common case where the fallback is `PMF.zero()`.
832
- * - **exclusive()** is for three or more mutually exclusive outcomes (e.g., crit vs hit vs none).
833
- *
834
- * @param p Probability of applying this PMF (between 0 and 1).
835
- * @param fallback PMF to apply when this PMF is *not* selected.
836
- * @returns A new PMF representing the weighted mixture of this PMF and the fallback.
837
- */
838
- gate(p: number, fallback: PMF): PMF;
839
- /**
840
- * PMF.exclusive()
841
- *
842
- * Builds a single PMF from a set of mutually exclusive weighted outcomes.
843
- * Exactly one of the provided options will occur.
844
- *
845
- * Each option has:
846
- * - A PMF representing its outcome (e.g., damage dice).
847
- * - A weight representing its probability of being selected.
848
- *
849
- * Notes:
850
- * - If total weight < 1 (within eps), leftover mass is assumed to be PMF.zero()
851
- *
852
- * @param options Array of `{ pmf, weight }` or `[PMF, number]`.
853
- * @param eps Optional tolerance for floating point rounding.
854
- */
855
- static exclusive(options: Array<{
856
- pmf: PMF;
857
- weight: number;
858
- } | [PMF, number]>, eps?: number): PMF;
859
- /**
860
- * PMF.mix()
861
- *
862
- * Builds a PMF as a linear combination of input PMFs with the given weights.
863
- * Unlike `exclusive`, this does NOT:
864
- * - enforce that weights sum to 1
865
- * - add leftover probability to δ0 (PMF.zero())
866
- *
867
- * Use when outcomes are not mutually exclusive, or for interpolation/blending.
868
- *
869
- * @param options Array of `{ pmf, weight }` or `[PMF, number]`.
870
- * @param eps Optional tolerance for skipping tiny weights.
871
- */
872
- static mix(options: Array<{
873
- pmf: PMF;
874
- weight: number;
875
- } | [PMF, number]>, eps?: number): PMF;
876
- /**
877
- * Adds damage attribution metadata to this PMF based on existing count metadata.
878
- * For each bin, sets attr[outcome] = damage × count[outcome].
879
- *
880
- * This enables damage attribution charts to work with builder-generated PMFs.
881
- * The parser generates attr automatically, but builder PMFs only have count.
882
- *
883
- * @returns New PMF with attr field populated in each bin
884
- */
885
- /**
886
- * Returns true if this PMF already carries damage attribution metadata.
887
- *
888
- * Only the first positive-damage bin is inspected (parser-generated PMFs
889
- * populate `attr` uniformly), so this is O(1) in practice.
890
- */
891
- hasAttribution(): boolean;
892
- withAttribution(): PMF;
893
- /**
894
- * General-purpose N-way mixture.
895
- * weights: Array of [weight, PMF].
896
- *
897
- * Example: PMF.mixN([
898
- * [pMiss, zero],
899
- * [pHit, hitPMF],
900
- * [pCrit, critPMF],
901
- * ]);
902
- */
903
- static mixN(weights: [number, PMF][], eps?: number): PMF;
904
- private setPreservedProvenance;
905
- preservedProvenance(): boolean;
906
- private getPowerCacheKey;
907
- /**
908
- * Efficiently computes this PMF convolved with itself `n` times.
909
- * Uses exponentiation by squaring to reduce total convolutions.
910
- * n must be a positive integer.
911
- * *
912
- * * NOTE: This folds multiple independent attacks into a single PMF.
913
- * As a result, The power() method causes a loss of data provenance.
914
- * This is ONLY SAFE if you are trying to calculate masses.
915
- * If you want to query any atLeast probabilities, you should use the DiceQuery class instead without power().
916
- */
917
- power(n: number, eps?: number): PMF;
918
- replicate(n: number): PMF[];
919
- mass(): number;
920
- outcomeMass(outcome: string): number;
921
- faceTotal(): number;
922
- normalize(): PMF;
923
- /**
924
- * Returns a copy with negligible probabilities removed (p < eps).
925
- * If keepFinalBin is true, the bin with the largest key is always kept,
926
- * even if its probability is below eps. count/attr submaps are still cleaned.
927
- */
928
- compact(eps?: number, keepFinalBin?: boolean): PMF;
929
- support(): number[];
930
- min(): number;
931
- max(): number;
932
- /**
933
- * Returns the expected (mean) damage value.
934
- * Cached for performance since this requires iterating through all bins.
935
- */
936
- mean(): number;
937
- /**
938
- * Returns the variance of the damage distribution.
939
- * Cached for performance since this requires mean calculation plus iteration.
940
- */
941
- variance(): number;
942
- /**
943
- * Returns the standard deviation of the damage distribution.
944
- */
945
- stdev(): number;
946
- /** Deep-copies a Bin, cloning its count and (optional) attr maps. */
947
- private static cloneBin;
948
- /** Returns a new Bin with p, count, and attr all multiplied by `factor`. */
949
- private static scaleBin;
950
- private static mergeInto;
951
- add(other: PMF): PMF;
952
- /**
953
- * Returns a new PMF with a scaled branch added to this one.
954
- * The branch PMF is scaled by the given probability before merging
955
- * This will be very useful for conditional effects and for being
956
- * able to model "I can probably have this opportunity attack 40% of rounds"
957
- * Example: `pmf.addScaled(critBranch, 0.05)` → PMF including 5% crit outcomes
958
- */
959
- addScaled(branch: PMF, probability: number): PMF;
960
- /**
961
- * Redistributes probability mass to model an effect that only occurs with
962
- * probability `frequency` — a conditional attack, an on-hit rider, or a
963
- * sub-one AoE target fraction.
964
- *
965
- * Every hit outcome (damage > 0) is scaled by `frequency` — probability mass,
966
- * per-label `count`, AND per-label `attr` — and the freed mass is moved into
967
- * the miss bin at damage 0, tagged with the canonical `missNone` outcome.
968
- * Total probability mass is preserved.
969
- *
970
- * Unlike a bare {@link scaleMass} or {@link mapDamage}, this keeps damage
971
- * attribution (`attr`) intact, so a frequency-scaled PMF still renders
972
- * correctly in the damage-attribution charts.
973
- *
974
- * `frequency >= 1` (or non-finite) returns this PMF unchanged; `frequency <= 0`
975
- * collapses all mass into the miss bin. The miss outcome is assumed to be
976
- * encoded at damage value 0.
977
- *
978
- * @param frequency Probability in [0, 1] that the effect occurs.
979
- */
980
- applyHitFrequency(frequency: number): PMF;
981
- scaleMass(factor: number): PMF;
982
- mapDamage(damageTransformFunction: (damageValue: number) => number): PMF;
983
- scaleDamage(factor: number, rounding?: "floor" | "round" | "ceil"): PMF;
984
- private getPMFCombineCacheKey;
985
- /**
986
- * A small content fingerprint (mass + bin count + face sum) so convolution
987
- * cache keys change if the underlying numbers do. Memoized because a PMF is
988
- * immutable once constructed — this avoids re-summing every key on each
989
- * convolve() call (including cache hits).
990
- */
991
- fingerprint(): string;
992
- convolve(other: PMF, eps?: number, raw?: boolean): PMF;
993
- combineRaw(other: PMF, eps?: number): PMF;
994
- private static reduceConvolveLeft;
995
- /**
996
- * Convolves multiple PMFs using linear convolution with automatic caching.
997
- * Uses a left-to-right accumulation approach for maximum cache reuse.
998
- * Each convolve() call automatically uses the convolution cache for performance.
999
- *
1000
- * This linear approach provides better cache hits than pairwise because:
1001
- * - Intermediate results are more predictable and stable
1002
- * - Similar PMF lists share common prefixes (A+B, (A+B)+C, etc.)
1003
- * - Order-independent cache keys work better with consistent build patterns
1004
- */
1005
- static convolveMany(pmfList: PMF[], eps?: number): PMF;
1006
- /**
1007
- * Returns a plain, JSON-serializable representation of this PMF.
1008
- *
1009
- * Follows the standard `toJSON` contract, so `JSON.stringify(pmf)` produces
1010
- * the expected output (no double-encoding). Use {@link PMF.fromJSON} to
1011
- * reconstruct, or {@link PMF.toJSONString} if you need the string directly.
1012
- */
1013
- toJSON(): {
1014
- bins: Array<[number, Bin]>;
1015
- normalized: boolean;
1016
- identifier: string;
1017
- };
1018
- /** Serializes this PMF to a JSON string (equivalent to `JSON.stringify(pmf)`). */
1019
- toJSONString(): string;
1020
- static fromJSON(jsonData: {
1021
- bins: Array<[number, Bin]>;
1022
- normalized?: boolean;
1023
- identifier?: string;
1024
- }): PMF;
1025
- /**
1026
- * Relative pruning with optional top-K floor.
1027
- * Keeps bins with p >= epsRel * peak, always keeps min and max damage,
1028
- * optionally guarantees at least `minBins` survivors by adding top-K.
1029
- * Returns a new, non-normalized PMF.
1030
- */
1031
- prune(epsRel: number, minBins?: number): PMF;
1032
- /** Probability mass at exactly x. */
1033
- pAt(x: number): number;
1034
- /**
1035
- * P(any damage) — the mass on all non-zero outcomes, i.e. `1 - P(0)`.
1036
- * Assumes a miss is encoded as the damage-0 bin (the convention used across
1037
- * attack/save PMFs). The dual of {@link missProbability}.
1038
- */
1039
- hitProbability(): number;
1040
- /** P(no damage) — the mass at damage 0. The dual of {@link hitProbability}. */
1041
- missProbability(): number;
1042
- /**
1043
- * Coarsen the distribution into at most `maxBuckets` contiguous, equal-width
1044
- * damage buckets, aggregating probability mass (and `count`/`attr`
1045
- * provenance) into each bucket's start value. Returns this PMF unchanged when
1046
- * its integer support already fits within `maxBuckets`.
1047
- *
1048
- * This is a lossy display/downsampling transform (bucket start replaces the
1049
- * exact damage value) — use it for charting wide distributions, not for DPR
1050
- * math.
1051
- */
1052
- rebin(maxBuckets: number): PMF;
1053
- /** Dense integer support from min..max (inclusive).
1054
- * Useful for showing empty bars in charts.
1055
- */
1056
- denseSupport(): number[];
1057
- /** CDF at x: P(X ≤ x). */
1058
- cdfAt(x: number): number;
1059
- /** Quantile / inverse CDF for p in [0,1]. Returns smallest x with CDF ≥ p. */
1060
- quantile(p: number): number;
1061
- /** Get outcome probability at specific damage value. */
1062
- outcomeAt(damage: number, outcome: string): number;
1063
- /** Get all outcome types present in this PMF. */
1064
- outcomes(): string[];
1065
- /** Get total probability of an outcome across all damage values. */
1066
- outcomeProbability(outcome: string): number;
1067
- /** Get damage attribution for an outcome at specific damage value. */
1068
- outcomeAttributionAt(damage: number, outcome: string): number;
1069
- /** Get all outcome data at specific damage value. */
1070
- binAt(damage: number): {
1071
- p: number;
1072
- count: Record<string, number>;
1073
- attr?: Record<string, number>;
1074
- } | null;
1075
- /** Check if outcome exists in this PMF. */
1076
- hasOutcome(outcome: string): boolean;
1077
- /**
1078
- * Split each damage value's probability mass across outcome labels, returning
1079
- * per-label maps of `damage value → probability mass attributable to that
1080
- * label`. Summing over labels at a given value recovers that value's `p`.
1081
- *
1082
- * Damage-bearing bins are split by `attr` weight (the share of damage each
1083
- * outcome contributed); the clean-miss bin at 0 is split by `count` weight
1084
- * (there is no damage to attribute). Attribution is computed on demand via
1085
- * {@link withAttribution} when absent, so builder-generated PMFs work too.
1086
- *
1087
- * This is the provenance core of the stacked damage-attribution chart — the
1088
- * caller only maps these series into its rendering format (colors, binning,
1089
- * axis labels).
1090
- */
1091
- attributionByValue(): Map<string, Map<number, number>>;
1092
- tailProbGE(t: number): number;
1093
- tailProbGT(t: number): number;
1094
- /**
1095
- * Returns a new PMF containing only bins where the specified outcome has non-zero probability.
1096
- * This creates a marginal distribution for the given outcome type, with probabilities
1097
- * scaled to represent the unconditional mass attributable to that outcome.
1098
- */
1099
- filterOutcome(outcome: string): PMF;
1100
- /**
1101
- * Calculates probabilities for first-success outcomes across n independent attempts.
1102
- *
1103
- * @param pSuccess - Total probability of any success on a single attempt.
1104
- * @param pSpecial - Probability of a specific subset of successes (e.g., critical success).
1105
- * @param n - Number of independent attempts.
1106
- *
1107
- * Returns:
1108
- * - pSpecificSuccess: Probability that the first success was of the "special" type
1109
- * - pGeneralSuccess: Probability that the first success was of the non-special type
1110
- * - pNone: Probability that no successes occurred
1111
- * - pAny: Probability that at least one success occurred
1112
- */
1113
- static firstSuccessWeights(pSuccess: number, pSpecial: number, n: number): {
1114
- pSpecificSuccess: number;
1115
- pGeneralSuccess: number;
1116
- pNone: number;
1117
- pAny: number;
1118
- };
1119
- mapValues(f: (v: number) => number, eps?: number, opts?: {
1120
- rounding?: Rounding;
1121
- preserveCounts?: boolean;
1122
- }): PMF;
1123
- static fromMap(m: Map<number, number>, eps?: number, { requireIntegerValues }?: {
1124
- requireIntegerValues?: boolean;
1125
- }): PMF;
1126
- query(): DiceQuery;
1127
- }
1128
-
1129
- export { ALL_OUTCOME_TYPES as A, type Bin as B, type CritConfig as C, type DamageDistribution as D, EPS as E, LRUCache as L, MISS_NONE_OUTCOME as M, type OutcomeLabelMap as O, PMF as P, type Rounding as R, type Snapshot as S, type OutcomeType as a, type RollType as b, critProbability as c, OUTCOME_DISPLAY_ORDER as d, onCritOnly as e, onHitOnly as f, onMissOnly as g, onMissDamageOnly as h, onSaveHalfOnly as i, onSaveFailOnly as j, onPotentCantripOnly as k, DiceQuery as l, type OutcomeSnapshot as m, onAnyHit as o, pmfCache as p, sortOutcomes as s };
671
+ //# sourceMappingURL=query.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/pmf/query.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yipe/dice",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "A high-performance dice probability engine for D&D 5e DPR calculations. Powers dprcalc.com.",
5
5
  "keywords": [
6
6
  "dnd",
@@ -21,7 +21,7 @@
21
21
  "license": "MIT",
22
22
  "author": "Michael Margolis <acct@yipe.org>",
23
23
  "type": "module",
24
- "packageManager": "yarn@4.9.4",
24
+ "packageManager": "yarn@4.17.1",
25
25
  "exports": {
26
26
  ".": {
27
27
  "types": "./dist/index.d.ts",
@@ -62,11 +62,11 @@
62
62
  "./dist/builder/dc.js"
63
63
  ],
64
64
  "scripts": {
65
- "format": "eslint . --fix",
66
- "lint": "eslint .",
65
+ "format": "node -r ./config/eslint-ts6-alias.cjs ./node_modules/eslint/bin/eslint.js . --fix",
66
+ "lint": "node -r ./config/eslint-ts6-alias.cjs ./node_modules/eslint/bin/eslint.js .",
67
67
  "typecheck": "tsc -p config/tsconfig.build.json --noEmit",
68
- "build": "tsup --config config/tsup.config.ts",
69
- "types": "tsc -p config/tsconfig.build.json --emitDeclarationOnly",
68
+ "build": "tsup --config config/tsup.config.ts && yarn types",
69
+ "types": "tsc -p config/tsconfig.build.json --emitDeclarationOnly && node config/postbuild-dts.mjs",
70
70
  "test": "vitest run",
71
71
  "test:watch": "vitest watch",
72
72
  "prepare": "yarn build",
@@ -80,14 +80,15 @@
80
80
  "node": ">=18.17"
81
81
  },
82
82
  "devDependencies": {
83
- "@types/node": "^26.0.1",
84
- "@typescript-eslint/eslint-plugin": "^8.62.0",
85
- "@typescript-eslint/parser": "^8.62.0",
86
- "@vitest/coverage-v8": "^4.1.9",
87
- "eslint": "^10.6.0",
83
+ "@types/node": "^26.1.1",
84
+ "@typescript-eslint/eslint-plugin": "^8.64.0",
85
+ "@typescript-eslint/parser": "^8.64.0",
86
+ "@typescript/typescript6": "^6.0.2",
87
+ "@vitest/coverage-v8": "^4.1.10",
88
+ "eslint": "^10.7.0",
88
89
  "tsup": "^8.5.1",
89
- "tsx": "^4.22.4",
90
- "typescript": "^6.0.3",
91
- "vitest": "^4.1.9"
90
+ "tsx": "^4.23.1",
91
+ "typescript": "^7.0.2",
92
+ "vitest": "^4.1.10"
92
93
  }
93
- }
94
+ }
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Michael Margolis
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.