{"version":3,"sources":["../src/common/bounce.ts","../src/common/errors.ts","../src/common/lru-cache.ts","../src/common/types.ts","../src/pmf/query.ts","../src/pmf/pmf.ts","../src/parser/dice.ts","../src/parser/parser.ts","../src/parser/rollType.ts","../src/pmf/mixture.ts"],"names":["cumulativeSum","result","check"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Bounce odds — the \"birthday problem\" for bouncing damage dice (e.g. Chromatic\n * Orb): the probability that at least two of K dice with S faces show the same\n * value, which is what lets the spell jump to another target.\n *\n * Accounts for two modifiers:\n * - **Elemental Adept** (`minimumDieRoll >= 2`): rolls below the minimum are\n *   bumped up to it, collapsing the low faces onto a single heavier value.\n * - **Empowered Spell** (`rerollDamageDice > 0`): a number of dice may be\n *   rerolled once, giving a second chance at a match.\n *\n * The base and Elemental-Adept cases are computed exactly (see\n * {@link pAllDistinct}); the Empowered-Spell reroll is an explicit model layered\n * on the exact base match probability.\n */\n\n/** Options that modify bounce odds via metamagic / feats. */\nexport interface BounceOddsOptions {\n  /** Minimum die roll — e.g. 2 for Elemental Adept, 3 for Great Weapon Fighting 2024. */\n  minimumDieRoll?: number;\n  /** Number of dice that may be rerolled once — e.g. CHA modifier for Empowered Spell. */\n  rerollDamageDice?: number;\n}\n\n/** Binomial coefficient C(n, k), 0 for out-of-range k. */\nfunction binom(n: number, k: number): number {\n  if (k < 0 || k > n) return 0;\n  let result = 1;\n  for (let i = 0; i < k; i++) result = (result * (n - i)) / (i + 1);\n  return result;\n}\n\n/**\n * Exact P(all K dice show distinct values) for a die with `uniformCount`\n * ordinary faces (each probability `1/faces`) plus one optional heavy face whose\n * probability is `heavyWeight` (used for the Elemental-Adept collapse; pass 0\n * for a plain die). Uses the elementary symmetric polynomial e_K over the face\n * probabilities: P(all distinct) = K! · e_K.\n */\nfunction pAllDistinct(\n  dice: number,\n  faces: number,\n  uniformCount: number,\n  heavyWeight: number\n): number {\n  const light = 1 / faces;\n  // e_K = (choose K distinct light faces) + (heavy face + K-1 light faces).\n  const eK =\n    binom(uniformCount, dice) * Math.pow(light, dice) +\n    heavyWeight * binom(uniformCount, dice - 1) * Math.pow(light, dice - 1);\n  let kFactorial = 1;\n  for (let i = 2; i <= dice; i++) kFactorial *= i;\n  return kFactorial * eK;\n}\n\n/** Exact P(at least one duplicate) among `dice` dice, honoring Elemental Adept. */\nfunction pMatch(dice: number, faces: number, minimumDieRoll: number): number {\n  if (dice <= 1) return 0;\n  if (dice > faces) return 1;\n\n  if (minimumDieRoll >= 2) {\n    // Rolls 1..minimumDieRoll collapse onto the value `minimumDieRoll`, giving it\n    // weight minimumDieRoll/faces; the faces above it stay uniform at 1/faces.\n    const uniformCount = faces - minimumDieRoll; // values minimumDieRoll+1 .. faces\n    const effectiveValues = uniformCount + 1; // + the collapsed value\n    if (dice > effectiveValues) return 1;\n    const heavyWeight = minimumDieRoll / faces;\n    const distinct = pAllDistinct(dice, faces, uniformCount, heavyWeight);\n    return Math.min(1, Math.max(0, 1 - distinct));\n  }\n\n  // Plain die: P(all distinct) = falling_factorial(faces, dice) / faces^dice.\n  let pDistinct = 1;\n  for (let i = 0; i < dice; i++) pDistinct *= (faces - i) / faces;\n  return 1 - pDistinct;\n}\n\n/**\n * P(at least two of `diceCount` dice with `dieFaces` faces match), honoring\n * Elemental Adept and Empowered Spell. Returns a probability in [0, 1].\n *\n * @param diceCount Number of dice rolled.\n * @param dieFaces Faces per die (e.g. 8 for d8).\n * @param options Optional metamagic / feat modifiers.\n */\nexport function calculateBounceOdds(\n  diceCount: number,\n  dieFaces: number,\n  options?: BounceOddsOptions\n): number {\n  if (diceCount <= 1) return 0;\n  if (diceCount > dieFaces) return 1; // pigeonhole\n\n  const minimumDieRoll = options?.minimumDieRoll ?? 0;\n  const rerollDamageDice = options?.rerollDamageDice ?? 0;\n\n  const pMatchFirst = pMatch(diceCount, dieFaces, minimumDieRoll);\n\n  // Without Empowered Spell we're done.\n  const rerollCount = Math.min(rerollDamageDice, diceCount);\n  if (rerollCount <= 0) return pMatchFirst;\n\n  // Empowered Spell: reroll `rerollCount` non-matching dice once. Model the\n  // second chance as (a rerolled die matching one of the kept dice) OR (the\n  // rerolled dice matching among themselves).\n  const pNoMatchFirst = 1 - pMatchFirst;\n  const keptDice = diceCount - rerollCount;\n  const effectiveFaces = minimumDieRoll >= 2 ? dieFaces - (minimumDieRoll - 1) : dieFaces;\n\n  // With no kept dice, a rerolled die vacuously \"misses\" all of them (prob 1), so\n  // the only way to match is among the rerolled dice themselves (pRerolledMatch below).\n  const pRerollDieMissesAll =\n    keptDice > 0 ? Math.pow((effectiveFaces - keptDice) / effectiveFaces, rerollCount) : 1;\n  const pAtLeastOneRerollMatches = 1 - pRerollDieMissesAll;\n  const pRerolledMatch = rerollCount >= 2 ? pMatch(rerollCount, dieFaces, minimumDieRoll) : 0;\n  const pMatchAfterReroll = Math.min(\n    1,\n    pAtLeastOneRerollMatches + pRerolledMatch * (1 - pAtLeastOneRerollMatches)\n  );\n\n  return Math.min(1, pMatchFirst + pNoMatchFirst * pMatchAfterReroll);\n}\n","/**\n * Error thrown when a dice expression cannot be parsed.\n *\n * Extends the built-in {@link Error}, so existing `catch (e)` / message checks\n * continue to work, while callers can now narrow with `instanceof DiceParseError`.\n *\n * @example\n * try {\n *   parse(\"d6@3\");\n * } catch (e) {\n *   if (e instanceof DiceParseError) {\n *     // e.expression === \"d6@3\"\n *   }\n * }\n */\nexport class DiceParseError extends Error {\n  /** The original expression that failed to parse, when available. */\n  readonly expression?: string;\n\n  /** The underlying error that triggered this one, when available. */\n  readonly cause?: unknown;\n\n  constructor(\n    message: string,\n    options?: { expression?: string; cause?: unknown }\n  ) {\n    super(message);\n    this.name = \"DiceParseError\";\n    this.expression = options?.expression;\n    this.cause = options?.cause;\n    // Restore the prototype chain for reliable `instanceof` across targets.\n    Object.setPrototypeOf(this, DiceParseError.prototype);\n  }\n}\n","/**\n * Simple LRU cache implementation\n */\n\nexport class LRUCache<K, V> {\n  private cache = new Map<K, V>();\n\n  constructor(private readonly maxSize = 1000) {}\n\n  get(key: K): V | undefined {\n    const value = this.cache.get(key);\n    if (value === undefined) return undefined;\n\n    this.cache.delete(key);\n    this.cache.set(key, value);\n    return value;\n  }\n\n  delete(key: K): void {\n    this.cache.delete(key);\n  }\n\n  set(key: K, value: V): this {\n    if (this.cache.size >= this.maxSize && !this.cache.has(key)) {\n      const oldestKey = this.cache.keys().next().value;\n      this.cache.delete(oldestKey as K);\n    }\n    this.cache.delete(key);\n    this.cache.set(key, value);\n    return this;\n  }\n\n  clear(): void {\n    this.cache.clear();\n  }\n\n  get size(): number {\n    return this.cache.size;\n  }\n\n  has(key: K): boolean {\n    return this.cache.has(key);\n  }\n\n  keys(): IterableIterator<K> {\n    return this.cache.keys();\n  }\n\n  values(): IterableIterator<V> {\n    return this.cache.values();\n  }\n}\n","/** Mapping from outcome label to probability mass or damage attribution. */\nexport type OutcomeLabelMap = Partial<Record<string, number>>;\n\n/** Computational epsilon for pruning negligible probabilities. */\nexport const EPS = 1e-12;\n\n/** A probability bin for a specific damage value. */\nexport interface Bin {\n  /** Total probability mass at this damage value. */\n  p: number;\n  /** Per-outcome probability mass contributions at this damage. */\n  count: OutcomeLabelMap;\n  /** Optional per-outcome damage attribution at this damage. */\n  attr?: OutcomeLabelMap;\n}\n\nexport interface CritConfig {\n    critThreshold: number;\n}\n\n/** Simple mapping from damage value to probability. */\nexport type DamageDistribution = Record<number, number>;\n/** Canonical outcome labels supported by the query helpers. */\nexport type OutcomeType =\n  | \"crit\"\n  | \"hit\"\n  | \"missNone\"\n  | \"missDamage\"\n  | \"saveHalf\"\n  | \"saveFail\"\n  | \"pc\";\n\nexport type Rounding = \"none\" | \"floor\" | \"round\" | \"ceil\";\n\n/** How a d20 attack roll resolves: single die, keep-highest of 2/3, or keep-lowest of 2. */\nexport type RollType = \"flat\" | \"advantage\" | \"disadvantage\" | \"elven accuracy\";\n\n/**\n * P(critical hit) for the given crit window and d20 {@link RollType}.\n *\n * `critRange` is the number of top faces that crit (1 for a natural 20, 2 for\n * 19–20, …), so a single die crits with probability `critRange / 20`. Advantage\n * rolls two d20s / elven accuracy three, keeping the best; disadvantage keeps\n * the worst of two.\n */\nexport function critProbability(critRange: number, rollType: RollType = \"flat\"): number {\n  const base = critRange / 20;\n  switch (rollType) {\n    case \"advantage\":\n      return 1 - (1 - base) ** 2;\n    case \"elven accuracy\":\n      return 1 - (1 - base) ** 3;\n    case \"disadvantage\":\n      return base ** 2;\n    case \"flat\":\n    default:\n      return base;\n  }\n}\n\n/**\n * The canonical \"clean miss\" outcome — a point of zero damage with no rider.\n * This is the {@link OutcomeType} that attribution charts and outcome stats key\n * on, and is distinct from the builder's attack-resolution `miss` weight label.\n */\nexport const MISS_NONE_OUTCOME: OutcomeType = \"missNone\";\n\n/**\n * All outcome types in canonical severity order — clean miss → crit. This is\n * also the natural stacking order for attribution charts (least- to\n * most-impactful, bottom → top). Enumerates every {@link OutcomeType} exactly\n * once; use it instead of hand-maintained per-consumer outcome tables.\n */\nexport const ALL_OUTCOME_TYPES: OutcomeType[] = [\n  \"missNone\",\n  \"missDamage\",\n  \"saveFail\",\n  \"saveHalf\",\n  \"pc\",\n  \"hit\",\n  \"crit\",\n];\n\n/**\n * Outcome types in display order for stats / breakdown rows — most prominent\n * first (crit, hit, …) down to the clean miss.\n */\nexport const OUTCOME_DISPLAY_ORDER: OutcomeType[] = [\n  \"crit\",\n  \"hit\",\n  \"missDamage\",\n  \"saveHalf\",\n  \"saveFail\",\n  \"pc\",\n  \"missNone\",\n];\n\n/**\n * Sort outcome labels by a canonical order (defaults to {@link ALL_OUTCOME_TYPES}).\n * Labels not present in `order` sort after known ones, alphabetically — so\n * ad-hoc/test labels outside the {@link OutcomeType} union stay stable.\n */\nexport function sortOutcomes<T extends string>(\n  outcomes: Iterable<T>,\n  order: readonly string[] = ALL_OUTCOME_TYPES\n): T[] {\n  const rank = new Map(order.map((o, i) => [o, i]));\n  return [...outcomes].sort((a, b) => {\n    const ra = rank.get(a);\n    const rb = rank.get(b);\n    if (ra !== undefined && rb !== undefined) return ra - rb;\n    if (ra !== undefined) return -1;\n    if (rb !== undefined) return 1;\n    return a.localeCompare(b);\n  });\n}\n\nexport const onAnyHit: OutcomeType[] = [\"hit\", \"crit\"];\nexport const onCritOnly: OutcomeType[] = [\"crit\"];\nexport const onHitOnly: OutcomeType[] = [\"hit\"];\nexport const onMissOnly: OutcomeType[] = [\"missNone\", \"missDamage\"];\nexport const onMissDamageOnly: OutcomeType[] = [\"missDamage\"];\nexport const onSaveHalfOnly: OutcomeType[] = [\"saveHalf\"];\nexport const onSaveFailOnly: OutcomeType[] = [\"saveFail\"];\nexport const onPotentCantripOnly: OutcomeType[] = [\"pc\"];\n","import type { OutcomeType } from \"../common/types\";\nimport { ALL_OUTCOME_TYPES, EPS } from \"../common/types\";\nimport { PMF } from \"./pmf\";\nimport type { DamageAttributionChartModel } from \"./pmf\";\n\n/**\n * Query interface for analyzing dice roll probability distributions.\n *\n * Combines multiple attack PMFs and provides statistical analysis methods for:\n * - Basic statistics (mean, variance, min/max, percentiles)\n * - Probability queries (hit chances, success rates, exact counts)\n * - Damage analysis (ranges by outcome type, expected values)\n * - Data export (charts, tables, visualizations)\n *\n */\n\nexport class DiceQuery {\n  public readonly singles: PMF[];\n  private readonly _eps: number;\n  private readonly _combinedProvided: boolean;\n  private _combined?: PMF;\n  private _combinedWithAttr?: PMF;\n\n  constructor(singles: PMF | PMF[], combined?: PMF, eps = EPS) {\n    this.singles = Array.isArray(singles) ? singles : [singles];\n    if (this.singles.some((s) => s === undefined)) {\n      throw new Error(\"DiceQuery contains undefined singles\");\n    }\n    this._eps = eps;\n    // When the caller supplies an explicit combined distribution that may not\n    // equal convolve(singles), the additive closed-form moments would describe\n    // a different distribution than cdf/percentiles. Track this so mean()/\n    // variance() can fall back to the provided combined and stay consistent.\n    this._combinedProvided = combined !== undefined;\n    if (combined !== undefined) {\n      this._combined =\n        Math.abs(combined.mass() - 1) <= eps ? combined : combined.normalize();\n    }\n  }\n\n  /**\n   * The combined damage distribution of all single PMFs (their convolution),\n   * normalized to total probability 1.\n   *\n   * Computed lazily on first access and cached. Queries that only need\n   * additive statistics — {@link DiceQuery.mean}, {@link DiceQuery.variance},\n   * {@link DiceQuery.stddev} — never trigger this convolution.\n   */\n  get combined(): PMF {\n    if (this._combined === undefined) {\n      const c = PMF.convolveMany(this.singles);\n      this._combined =\n        Math.abs(c.mass() - 1) <= this._eps ? c : c.normalize();\n    }\n    return this._combined;\n  }\n\n  private static readonly DEFAULT_OUTCOMES: readonly OutcomeType[] = [\n    \"hit\",\n    \"crit\",\n    \"missNone\",\n  ] as const;\n\n  /**\n   * Returns a new PMF with damage attribution metadata populated.\n   *\n   * This method computes attribution on-demand for builder-generated PMFs,\n   * enabling them to work with damage attribution charts. The `attr` field\n   * tracks how much damage each outcome type contributes at each damage value.\n   *\n   * For each bin at damage D: sum(attr.values()) ≈ D × P(damage = D)\n   *\n   * Performance: Cached after first call. Adds minimal overhead vs `combined`.\n   *\n   * @returns PMF with attr field populated for damage attribution charts\n   *\n   * @example\n   * const attack = d20.plus(5).ac(15).onHit(d(2,6).plus(3)).onCrit(d(2,6))\n   * const query = attack.toQuery()\n   * const pmf = query.combinedWithAttribution()\n   * // Now pmf can be used with attributionByValue() / damageAttributionChartModel()\n   */\n  combinedWithAttribution(): PMF {\n    if (this._combinedWithAttr) {\n      return this._combinedWithAttr;\n    }\n\n    // An explicitly provided `combined` is NOT the convolution of `singles` —\n    // a Turn's exact joint distribution, for instance, is narrower than the\n    // independent product because riders correlate with their sources.\n    // Re-convolving would silently discard it (and drop the riders' damage\n    // entirely), so attribute the provided distribution itself.\n    if (this._combinedProvided) {\n      this._combinedWithAttr = this.combined.withAttribution();\n      return this._combinedWithAttr;\n    }\n\n    // Fast path: if every single already carries attribution (as parser-\n    // generated PMFs do), the attributed convolution is bit-for-bit identical\n    // to `combined` — reuse it instead of convolving a second time.\n    if (this.singles.every((pmf) => pmf.hasAttribution())) {\n      this._combinedWithAttr = this.combined;\n      return this._combinedWithAttr;\n    }\n\n    // Otherwise (e.g. builder-generated PMFs that only carry `count`), add\n    // attribution to each single PMF, then convolve.\n    const singlesWithAttr = this.singles.map((pmf) => pmf.withAttribution());\n    const combined = PMF.convolveMany(singlesWithAttr, this.combined.epsilon);\n\n    // Normalize if needed\n    const normalized =\n      Math.abs(combined.mass() - 1) <= this.combined.epsilon\n        ? combined\n        : combined.normalize();\n\n    this._combinedWithAttr = normalized;\n    return normalized;\n  }\n\n  /**\n   * Per-label `damage value → probability mass` series for the combined,\n   * attribution-carrying distribution — the provenance core of the stacked\n   * damage-attribution chart. Convenience for\n   * `combinedWithAttribution().attributionByValue()`; see\n   * {@link PMF.attributionByValue}.\n   */\n  attributionByValue(): Map<string, Map<number, number>> {\n    return this.combinedWithAttribution().attributionByValue();\n  }\n\n  /**\n   * Full numeric model for the stacked damage-attribution chart. Convenience for\n   * `combinedWithAttribution().damageAttributionChartModel(options)`; see\n   * {@link PMF.damageAttributionChartModel}.\n   */\n  damageAttributionChartModel(options?: {\n    maxBuckets?: number;\n    stackOrder?: readonly string[];\n    epsilon?: number;\n  }): DamageAttributionChartModel {\n    return this.combinedWithAttribution().damageAttributionChartModel(options);\n  }\n\n  /**\n   * How many of the independent single PMFs can produce the given outcome\n   * label. Useful for \"all of them succeeded\" style probabilities where the\n   * exponent is the number of contributing attacks (see\n   * {@link DiceQuery.probExactlyK}).\n   */\n  countSinglesWith(label: string): number {\n    let count = 0;\n    for (const single of this.singles) {\n      if (single.hasOutcome(label)) count++;\n    }\n    return count;\n  }\n\n  /**\n   * Returns the expected damage across all possible outcomes.\n   *\n   * Example: `query.mean()` → 12.5\n   * Use case: \"What's my average damage per round?\"\n   */\n  mean(): number {\n    // If the caller supplied a combined distribution that may diverge from\n    // convolve(singles), report its mean so mean() stays consistent with\n    // cdf/percentiles/min/max (which all read `combined`).\n    if (this._combinedProvided) {\n      let m = 0;\n      for (const [damageValue, bin] of this.combined) m += damageValue * bin.p;\n      return m;\n    }\n    // Expectation is additive over independent attacks: E[Σ Xᵢ] = Σ E[Xᵢ].\n    // Computing it directly from the singles avoids building `combined`.\n    let totalMean = 0;\n    for (const single of this.singles) {\n      const mass = single.mass();\n      if (mass <= 0) continue;\n      // Match `combined`'s semantics: only divide by mass when it is not\n      // already 1 (within eps), so an already-normalized single is bit-exact.\n      totalMean +=\n        Math.abs(mass - 1) <= this._eps ? single.mean() : single.mean() / mass;\n    }\n    return totalMean;\n  }\n\n  /**\n   * Returns the variance of the damage distribution.\n   *\n   * Example: `query.variance()` → 45.2\n   * Use case: \"How much does my damage vary from the average?\"\n   * High variance means higher risk/reward. Lower variance means more consistent damage.\n   */\n  variance(): number {\n    // Consistent with mean(): if a (possibly divergent) combined was provided,\n    // compute the variance of that distribution directly.\n    if (this._combinedProvided) {\n      const mu = this.mean();\n      let v = 0;\n      for (const [damageValue, bin] of this.combined) {\n        const dev = damageValue - mu;\n        v += dev * dev * bin.p;\n      }\n      return v;\n    }\n    // Variance is additive over independent attacks: Var[Σ Xᵢ] = Σ Var[Xᵢ].\n    // Use the centered form per single (E[(X−μ)²]) rather than E[X²]−μ², which\n    // suffers catastrophic cancellation when damage has a large constant offset.\n    let totalVariance = 0;\n    for (const single of this.singles) {\n      const mass = single.mass();\n      if (mass <= 0) continue;\n      if (Math.abs(mass - 1) <= this._eps) {\n        // PMF.variance() is the centered, cached, mass-1 variance.\n        totalVariance += single.variance();\n      } else {\n        // Normalized centered variance of a non-unit-mass single.\n        let mu = 0;\n        for (const [d, b] of single) mu += d * (b.p / mass);\n        let v = 0;\n        for (const [d, b] of single) {\n          const dev = d - mu;\n          v += dev * dev * (b.p / mass);\n        }\n        totalVariance += v;\n      }\n    }\n    return totalVariance;\n  }\n\n  /**\n   * Returns the standard deviation of the damage distribution.\n   *\n   * Example: `query.stdev()` → 6.7\n   * Use case: \"What's the typical spread around my average damage?\"\n   * Used to determine how consistent the damage is.\n   */\n  stddev(): number {\n    return Math.sqrt(this.variance());\n  }\n\n  /** Alias of {@link DiceQuery.stddev}, matching {@link PMF.stdev}. */\n  stdev(): number {\n    return this.stddev();\n  }\n\n  /**\n   * Returns the Cumulative Distribution Function.\n   */\n  cdf(x: number): number {\n    return this.probTotalAtMost(x);\n  }\n\n  /**\n   * Returns the probability of dealing X damage or less.\n   * In statistics, this is called the cumulative distribution function (CDF).\n   * Example: `query.cdf(20)` → 0.75\n   * Use case: \"What's the chance I deal 20 damage or less?\"\n   */\n  probTotalAtMost(x: number): number {\n    let cumulativeProbability = 0;\n    for (const [damageValue, probabilityBin] of this.combined) {\n      if (damageValue <= x) {\n        cumulativeProbability += probabilityBin.p;\n      }\n    }\n    return cumulativeProbability;\n  }\n\n  /**\n   * Returns the Complementary Cumulative Distribution Function.\n   */\n  ccdf(x: number): number {\n    return this.probTotalAtLeast(x);\n  }\n\n  /**\n   * Returns the probability of dealing at least X damage.\n   *\n   * Example: `query.probTotalAtLeast(25)` → 0.35\n   * Use case: \"What's the chance I deal at least 25 damage to finish the enemy?\"\n   */\n  probTotalAtLeast(threshold: number): number {\n    let probabilitySum = 0;\n    for (const [damageValue, probabilityBin] of this.combined) {\n      if (damageValue >= threshold) {\n        probabilitySum += probabilityBin.p;\n      }\n    }\n    return probabilitySum;\n  }\n\n  /**\n   * Returns damage values at specific percentiles.\n   *\n   * Example: `query.percentiles([0.25, 0.5, 0.75])` → [8, 12, 18]\n   * Use case: \"What are my 25th, 50th, and 75th percentile damage values?\"\n   */\n  percentiles(percentileValues: number[]): number[] {\n    const sortedDamageValues = this.combined.support();\n    if (sortedDamageValues.length === 0) return percentileValues.map(() => 0);\n\n    const cumulativeProbabilities: number[] = [];\n    let runningProbabilitySum = 0;\n    for (const damageValue of sortedDamageValues) {\n      runningProbabilitySum += this.combined.map.get(damageValue)!.p;\n      cumulativeProbabilities.push(runningProbabilitySum);\n    }\n\n    return percentileValues.map((targetPercentile) => {\n      // Binary search for efficiency\n      let leftBound = 0;\n      let rightBound = cumulativeProbabilities.length - 1;\n\n      while (leftBound <= rightBound) {\n        const middleIndex = Math.floor((leftBound + rightBound) / 2);\n        if (cumulativeProbabilities[middleIndex] >= targetPercentile) {\n          rightBound = middleIndex - 1;\n        } else {\n          leftBound = middleIndex + 1;\n        }\n      }\n\n      return leftBound < sortedDamageValues.length\n        ? sortedDamageValues[leftBound]\n        : sortedDamageValues[sortedDamageValues.length - 1];\n    });\n  }\n\n  /**\n   * Returns the minimum possible damage.\n   *\n   * Example: `query.min()` → 0\n   * Use case: \"What's the worst-case damage if everything misses?\"\n   */\n  min(): number {\n    return this.combined.min();\n  }\n\n  /**\n   * Returns the maximum possible damage.\n   *\n   * Example: `query.max()` → 56\n   * Use case: \"What's the best-case damage if everything crits and rolls max?\"\n   */\n  max(): number {\n    return this.combined.max();\n  }\n\n  private singleProb(diceIndex: number, label: OutcomeType): number {\n    const single = this.singles[diceIndex];\n    let probabilitySum = 0;\n    for (const [, probabilityBin] of single) {\n      probabilitySum += probabilityBin.count[label] || 0;\n    }\n    // Return the conditional per-event probability. Dividing by the single's\n    // mass keeps the result in [0,1] for a non-normalized single (e.g. one that\n    // has been scaled), so probAtLeastOne / the binomial DP stay mass-invariant.\n    const mass = single.mass();\n    return mass > 0 ? probabilitySum / mass : 0;\n  }\n\n  /**\n   * Full count distribution [P(0), P(1), …, P(n)] for \"an attack succeeds if it\n   * carries ANY of `labels`\", over the n independent singles.\n   *\n   * Each single's per-event success probability is the Poisson-binomial\n   * marginal P(≥1 of labels) from {@link probabilityOf} (i.e. probAtLeastOne),\n   * computed exactly once. The binomial DP then runs once to produce the whole\n   * distribution, so the array-label paths of probExactlyK / probAtLeastK /\n   * probAtMostK can slice or sum from it instead of rebuilding a DiceQuery and\n   * re-running the DP per requested k.\n   */\n  private countDistribution(labels: OutcomeType[]): number[] {\n    const n = this.singles.length;\n    const successProbabilities = this.singles.map((single) =>\n      new DiceQuery([single]).probabilityOf(labels)\n    );\n\n    const dist = new Array(n + 1).fill(0);\n    dist[0] = 1;\n    for (const successProb of successProbabilities) {\n      for (let outcomeCount = n; outcomeCount >= 1; outcomeCount--) {\n        dist[outcomeCount] =\n          dist[outcomeCount] * (1 - successProb) +\n          dist[outcomeCount - 1] * successProb;\n      }\n      dist[0] *= 1 - successProb;\n    }\n    return dist;\n  }\n\n  probAtLeastK(labels: OutcomeType | OutcomeType[], k: number): number {\n    const L = Array.isArray(labels) ? [...new Set(labels)] : [labels];\n    const n = this.singles.length;\n\n    if (k <= 0) return 1;\n    if (k > n) return 0;\n\n    // Sum the upper tail of the single, shared count distribution rather than\n    // calling probExactlyK (which rebuilt the distribution) once per i.\n    const dist = this.countDistribution(L);\n    let tail = 0;\n    for (let i = k; i <= n; i++) {\n      tail += dist[i];\n    }\n\n    if (tail < 0) return 0;\n    if (tail > 1) return 1;\n    return tail;\n  }\n\n  /**\n   * Returns the probability that at least one attack has the specified outcome(s).\n   * - This is the complement of probAtMostK(labels, 0)\n   *\n   * Examples:\n   * - `query.probAtLeastOne('hit')` → 0.88 (88% chance at least one attack hits)\n   * - `query.probAtLeastOne(['hit', 'crit'])` → 0.96 (96% chance at least one succeeds)\n   *\n   * Use cases:\n   * - \"What's the chance at least one of my attacks connects?\"\n   *\n   * Note:\n   *\n   * - You have to pass in an array of labels to avoid double-counting if you are\n   *   using multiple labels. You cannot just add them.\n   */\n  probAtLeastOne(labels: OutcomeType | OutcomeType[]): number {\n    // Handle single label case (backward compatibility)\n    if (typeof labels === \"string\") {\n      labels = [labels];\n    }\n\n    let productOfNonOccurrence = 1;\n    for (let diceIndex = 0; diceIndex < this.singles.length; diceIndex++) {\n      // Calculate total probability of any of the specified labels occurring.\n      // Clamp to [0,1] so floating-point drift in the per-attack sum cannot push\n      // the complement out of range.\n      let combinedProbability = 0;\n      for (const label of labels) {\n        combinedProbability += this.singleProb(diceIndex, label);\n      }\n      if (combinedProbability < 0) combinedProbability = 0;\n      else if (combinedProbability > 1) combinedProbability = 1;\n      productOfNonOccurrence *= 1 - combinedProbability;\n    }\n    const result = 1 - productOfNonOccurrence;\n    return result < 0 ? 0 : result > 1 ? 1 : result;\n  }\n\n  /**\n   * Computes binomial probabilities for exactly 0, 1, 2, ..., maxK occurrences of a label.\n   *\n   * Uses dynamic programming to efficiently calculate the probability distribution\n   * of how many attacks will have the specified outcome, accounting for different\n   * success probabilities across individual attacks.\n   *\n   * Example: For 3 attacks with 50% hit chance each, returns:\n   * [0.125, 0.375, 0.375, 0.125] = [P(0 hits), P(1 hit), P(2 hits), P(3 hits)]\n   *\n   * @param label - The outcome type to count\n   * @param maxK - Maximum number of occurrences to calculate (usually number of attacks)\n   * @returns Array where index K contains P(exactly K attacks have the label)\n   */\n  private computeBinomialProbabilities(\n    label: OutcomeType,\n    maxK: number\n  ): number[] {\n    const individualProbabilities = this.singles.map((_, diceIndex) =>\n      this.singleProb(diceIndex, label)\n    );\n    const binomialProbs = new Array(maxK + 1).fill(0);\n    binomialProbs[0] = 1;\n\n    for (const singleProbability of individualProbabilities) {\n      for (let outcomeCount = maxK; outcomeCount >= 1; outcomeCount--) {\n        binomialProbs[outcomeCount] =\n          binomialProbs[outcomeCount] * (1 - singleProbability) +\n          binomialProbs[outcomeCount - 1] * singleProbability;\n      }\n      binomialProbs[0] *= 1 - singleProbability;\n    }\n\n    return binomialProbs;\n  }\n\n  /**\n   * Returns the probability that exactly K attacks result in the specified outcome(s).\n   *\n   * Single label examples:\n   * - probExactlyK('hit', 2) = probability exactly 2 attacks hit\n   * - probExactlyK('crit', 1) = probability exactly 1 attack crits\n   * - probExactlyK('crit', 0) = probability no attacks crit\n   *\n   * Array examples:\n   * - probExactlyK(['hit', 'crit'], 2) = probability exactly 2 attacks succeed\n   * - probExactlyK(['hit', 'crit'], 1) = probability exactly 1 attack succeeds\n   * - probExactlyK(['missDamage', 'missNone'], 0) = probability no attacks miss\n   *\n   * Use cases:\n   * - \"What's the chance exactly one of my attacks hits?\"\n   * - \"How likely am I to get exactly 2 successes out of 3 attacks?\"\n   * - \"What's the probability that exactly half my attacks succeed?\"\n   *\n   * Note: For arrays, an attack counts as a \"success\" if it has any of the specified labels.\n   * This is different from probAtMostK, which counts an attack as a \"success\" if it has ALL of the specified labels.\n   */\n  probExactlyK(labels: OutcomeType | OutcomeType[], k: number): number {\n    // Handle single label case (backward compatibility)\n    if (typeof labels === \"string\") {\n      const probabilityArray = this.computeBinomialProbabilities(labels, k);\n      return probabilityArray[k];\n    }\n\n    // For multiple labels, derive P(exactly k) from the single shared count\n    // distribution. (k > n is impossible, so index out of range reads as 0.)\n    const dist = this.countDistribution(labels);\n    return k >= 0 && k < dist.length ? dist[k] : 0;\n  }\n\n  /**\n   * Returns the probability that AT MOST K attacks result in the specified outcome(s).\n   *\n   * Single label examples:\n   * - probAtMostK('hit', 1) = probability 0 or 1 attacks hit (at most 1)\n   * - probAtMostK('crit', 0) = probability no attacks crit\n   * - probAtMostK('missDamage', 2) = probability at most 2 attacks miss\n   *\n   * Array examples:\n   * - probAtMostK(['hit', 'crit'], 1) = probability at most 1 attack succeeds\n   * - probAtMostK(['hit', 'crit'], 0) = probability no attacks succeed (all miss)\n   *\n   * Use cases:\n   * - \"What's the chance that at most one attack hits?\" (rest miss)\n   * - \"How likely am I to have mostly failures?\" (at most 1 success)\n   * - \"What's the probability of a really bad turn?\" (at most 0 successes)\n   *\n   */\n  probAtMostK(labels: OutcomeType | OutcomeType[], k: number): number {\n    // Handle single label case (backward compatibility)\n    if (typeof labels === \"string\") {\n      const probabilityArray = this.computeBinomialProbabilities(labels, k);\n      let cumulativeSum = 0;\n      for (let outcomeCount = 0; outcomeCount <= k; outcomeCount++) {\n        cumulativeSum += probabilityArray[outcomeCount];\n      }\n      return cumulativeSum;\n    }\n\n    // For multiple labels, sum the lower tail of the single shared count\n    // distribution rather than recomputing it per outcomeCount.\n    const dist = this.countDistribution(labels);\n    const upper = Math.min(k, dist.length - 1);\n    let cumulativeSum = 0;\n    for (let outcomeCount = 0; outcomeCount <= upper; outcomeCount++) {\n      cumulativeSum += dist[outcomeCount];\n    }\n    return cumulativeSum;\n  }\n\n  /**\n   * Returns the expected damage attributed to specific outcome types.\n   *\n   * Single label examples:\n   * - expectedDamageFrom('hit') = expected damage from hit components\n   * - expectedDamageFrom('crit') = expected damage from crit components\n   *\n   * Array examples:\n   * - expectedDamageFrom(['hit', 'crit']) = expected damage from any success\n   * - expectedDamageFrom(['missDamage', 'missNone']) = expected damage from misses\n   *\n   * Use cases:\n   * - \"How much damage do I expect from successful attacks?\"\n   * - \"What's the damage contribution from critical hits specifically?\"\n   * - \"How much damage comes from miss effects (like save-for-half spells)?\"\n   */\n  expectedDamageFrom(labels: OutcomeType | OutcomeType[]): number {\n    const wanted = Array.isArray(labels) ? labels : [labels];\n\n    let total = 0;\n    // By linearity of expectation, we can sum the expected damages from each individual PMF. This avoids issues with the `count` aggregation during\n    for (const single of this.singles) {\n      for (const [dmg, bin] of single) {\n        let p = 0;\n        for (const label of wanted) p += bin.count[label] ?? 0;\n        total += dmg * p;\n      }\n    }\n    return total;\n  }\n\n  /**\n   * Returns damage statistics for scenarios where AT LEAST ONE attack results in\n   * the specified outcome(s).\n   *\n   * This method answers \"What happens when things go reasonably well?\" rather than\n   * \"What's the theoretical maximum?\" It includes mixed scenarios which are more\n   * common and tactically relevant than pure scenarios.\n   *\n   * Single label examples:\n   * - damageStatsFrom('hit') = damage range when at least one attack hits\n   * - damageStatsFrom('crit') = damage range when at least one attack crits\n   *\n   * Array examples:\n   * - damageStatsFrom(['hit', 'crit']) = damage range when at least one attack succeeds\n   * - damageStatsFrom(['missDamage', 'missNone']) = damage range when at least one attack misses\n   *\n   * Tactical Use Cases:\n   * - \"Given that I don't completely whiff (99% of turns), what damage should I expect?\"\n   * - \"When planning to kill a 60 HP enemy, what's my damage range on successful turns?\"\n   * - \"Should I use this risky spell if it has good damage when it works?\"\n   * - \"What's my damage potential when something goes right?\" (vs pure failure)\n   *\n   * Combat Planning Examples:\n   * - 4 attacks with 90% hit chance: \"96% of the time you'll do 25-150 damage, avg 52\"\n   *   (Much more useful than \"You average 50 damage including complete misses\")\n   * - Risk assessment: \"80% of successful turns do 40-80 damage, but 20% do 80-150\"\n   * - Resource management: \"If I hit anything, I'll likely finish this enemy\"\n   *\n   * Statistical Note:\n   * This includes mixed scenarios (2 hits + 1 crit, 3 hits + 1 miss, etc.) which\n   * occur far more frequently than pure scenarios. For pure scenarios, use combinedDamageStats.\n   *\n   * KNOWN LIMITATION (multi-attack, single label): the returned `count` is an\n   * EXPECTED COUNT (E[#label], so > 1 for N≥2 attacks, not a probability), and\n   * `avg` is the size-biased conditional mean E[dmg·#label]/E[#label] rather than\n   * E[dmg | the label occurs]. For a single attack both are the plain\n   * conditional figures. Use {@link probAtLeastOne} for the scenario probability.\n   *\n   * @example\n   * // High-level tactical planning\n   * const successStats = query.damageStatsFrom('hit')\n   * const successChance = query.probAtLeastOne('hit')\n   * console.log(`${(successChance*100).toFixed(1)}% chance to do ${successStats.min}-${successStats.max} damage`)\n   */\n  damageStatsFrom(labels: OutcomeType | OutcomeType[]): {\n    min: number;\n    max: number;\n    avg: number;\n    count: number;\n  } {\n    // Normalize input to array for uniform handling\n    const labelArray = typeof labels === \"string\" ? [labels] : labels;\n\n    let minDamage = Infinity;\n    let maxDamage = -Infinity;\n    let totalDamage = 0;\n    let totalCount = 0;\n\n    for (const [damage, probabilityBin] of this.combined) {\n      // Check if this bin has any of the specified labels\n      let binHasAnyLabel = false;\n      let binContribution = 0;\n\n      for (const label of labelArray) {\n        const count = probabilityBin.count[label] as number;\n        if (count && count > 0) {\n          binHasAnyLabel = true;\n          binContribution += count;\n        }\n      }\n\n      if (damage > 0 && binHasAnyLabel) {\n        minDamage = Math.min(minDamage, damage);\n        maxDamage = Math.max(maxDamage, damage);\n\n        // For single labels, use the specific count; for multiple labels, use total probability\n        const weightToUse =\n          labelArray.length === 1 ? binContribution : probabilityBin.p;\n        totalDamage += damage * weightToUse;\n        totalCount += weightToUse;\n      }\n    }\n\n    return {\n      min: minDamage === Infinity ? 0 : minDamage,\n      max: maxDamage === -Infinity ? 0 : maxDamage,\n      avg: totalCount > 0 ? totalDamage / totalCount : 0,\n      count: totalCount,\n    };\n  }\n\n  /**\n   * Returns damage statistics for scenarios where ALL attacks result in the specified\n   * outcome, calculated by leveraging the pure partition of singles.\n   *\n   * This method answers \"What's the theoretical best/worst case?\" and \"What are the\n   * clean mathematical boundaries?\" It provides pure scenarios without mixing outcomes.\n   *\n   * Examples:\n   * - combinedDamageStats('hit') = damage range when all attacks hit (none crit, none miss)\n   * - combinedDamageStats('crit') = damage range when all attacks crit (none just hit)\n   *\n   * UI and Display Use Cases:\n   * - Statistics panels showing \"MAX Hit Damage\" (users expect pure hits, not mixed)\n   * - \"Best case scenario\" vs \"worst case scenario\" analysis\n   * - Mathematical verification: \"Does our hit damage calculation match manual math?\"\n   * - Clean damage type attribution: \"How much comes from base hits vs crits?\"\n   *\n   * Design and Balance Use Cases:\n   * - Game designers: \"What's the damage ceiling if someone gets lucky?\"\n   * - Character optimization: \"What's my absolute maximum potential?\"\n   * - Ability comparison: \"Which build has higher crit ceiling?\"\n   * - Minimum guaranteed damage: \"What's the worst I can do if everything hits?\"\n   *\n   * Mathematical Use Cases:\n   * - Validating complex calculations against simple manual math\n   * - Understanding damage component contributions in isolation\n   * - Separating luck (crit variance) from consistency (hit variance)\n   * - Building intuition about damage sources\n   *\n   * When to Use This vs damageStatsFrom():\n   * - Use THIS for: UI max/min displays, theoretical limits, clean comparisons\n   * - Use damageStatsFrom() for: tactical planning, realistic expectations, mixed scenarios\n   *\n   * Statistical Note:\n   * Pure scenarios (all hits, all crits) are rare but represent clear mathematical\n   * boundaries. These stats help understand the \"shape\" of your damage potential.\n   *\n   * @example\n   * // UI display logic\n   * const pureHitMax = query.combinedDamageStats('hit').max    // Clean \"MAX Hit Damage: 90\"\n   * const pureCritMax = query.combinedDamageStats('crit').max  // Clean \"MAX Crit Damage: 168\"\n   *\n   * // vs tactical planning (use damageStatsFrom instead)\n   * const realisticRange = query.damageStatsFrom('hit')  // Includes mixed scenarios\n   */\n  combinedDamageStats(targetLabel: OutcomeType): {\n    min: number;\n    max: number;\n    avg: number;\n    count: number;\n  } {\n    // Get pure statistics from each single attack (singles are already pure partitions)\n    const singleStats = this.singles.map((single) =>\n      new DiceQuery([single]).damageStatsFrom(targetLabel)\n    );\n\n    // If any single attack has no outcomes of this type, return zeros\n    if (singleStats.some((stats) => stats.count === 0)) {\n      return { min: 0, max: 0, avg: 0, count: 0 };\n    }\n\n    // Calculate combined statistics for N attacks all of target type\n    const combinedMin = singleStats.reduce((sum, stats) => sum + stats.min, 0);\n    const combinedMax = singleStats.reduce((sum, stats) => sum + stats.max, 0);\n    const combinedAvg = singleStats.reduce((sum, stats) => sum + stats.avg, 0);\n    const combinedProb = singleStats.reduce(\n      (product, stats) => product * stats.count,\n      1\n    );\n\n    return {\n      min: combinedMin,\n      max: combinedMax,\n      avg: combinedAvg,\n      count: combinedProb,\n    };\n  }\n\n  /**\n   * Returns the probability that at least one attack carries ANY of the\n   * specified labels (the marginal P(≥1) across the independent attacks).\n   *\n   * Examples:\n   * - `query.probabilityOf('hit')` → 0.88 (probability at least one hit occurs)\n   * - `query.probabilityOf(['hit', 'crit'])` → 0.96 (probability of any success)\n   *\n   * Use cases:\n   * - \"What's the chance my resolution includes a success label?\"\n   * - \"How likely am I to get any hits or crits across all attacks?\"\n   *\n   * Note: this must NOT be computed by summing `combined` bin probabilities. A\n   * single combined damage total is reachable by many outcome combinations and\n   * a bin can hold several labels at once, so summing `bin.p` over bins that\n   * contain a label over-counts. The correct marginal is the Poisson-binomial\n   * complement over the per-attack probabilities, i.e. {@link probAtLeastOne}.\n   */\n  probabilityOf(labels: OutcomeType | OutcomeType[]): number {\n    return this.probAtLeastOne(labels);\n  }\n\n  /**\n   * Returns the probability of missing (any type of miss).\n   *\n   * Example: `query.missChance()` → 0.04\n   * Use case: \"What's the chance I miss completely this turn?\"\n   */\n  missChance(): number {\n    // Miss can be either explicit misses with damage or zero-damage misses\n    return this.probabilityOf([\"missDamage\", \"missNone\"]);\n  }\n\n  /**\n   * Returns data formatted for plotting damage probability distribution.\n   *\n   * Example: `query.toChartSeries()` → [{x: 0, y: 0.04}, {x: 6, y: 0.1}, ...]\n   * Use case: \"I want to visualize my damage distribution in a chart.\"\n   */\n  toChartSeries(): Array<{ x: number; y: number }> {\n    return this.combined.support().map((damageValue) => ({\n      x: damageValue,\n      y: this.combined.map.get(damageValue)!.p,\n    }));\n  }\n\n  /**\n   * Returns tabular data showing damage values and their probability breakdowns.\n   *\n   * Example: `query.toLabeledTable(['hit', 'crit'])` →\n   *   [{damage: 6, total: 0.01, hit: 0.008, crit: 0}, ...]\n   *\n   * Use case: \"I want to see exactly how hit/crit probabilities contribute to each damage value.\"\n   */\n  toLabeledTable(\n    labels: OutcomeType[] = []\n  ): Array<{ damage: number; total: number } & Record<string, number>> {\n    return this.combined.support().map((damageValue) => {\n      const probabilityBin = this.combined.map.get(damageValue)!;\n      const tableRow: { damage: number; total: number } & Record<\n        string,\n        number\n      > = {\n        damage: damageValue,\n        total: probabilityBin.p,\n      };\n      for (const outcomeLabel of labels) {\n        tableRow[outcomeLabel] = probabilityBin.count[outcomeLabel] || 0;\n      }\n      return tableRow;\n    });\n  }\n\n  /**\n   * Returns data for stacked charts with unconditional per-label probability mass per damage.\n   *\n   * - Each dataset value equals the unconditional probability mass for that label at that damage\n   *   (i.e., `bin.count[label]`).\n   * - Column sums may be less than the total probability `bin.p` when you omit labels or when\n   *   there is unlabeled mass. Include all relevant outcome labels if you need the sum to match.\n   * - This behavior matches tests that expect raw per-label mass (not proportional scaling).\n   * - NOTE: This implementation may break dprcalc.com chart binning at large n, need to test it more.\n   *\n   * @example\n   * query.toStackedChartData(['hit', 'crit'])\n   * // → {labels: [0, 6, 12, ...], datasets: [{label: 'hit', data: [0, 0.03, ...]}, ...]}\n   */\n  toStackedChartData(\n    labels: OutcomeType[] = [],\n    epsilon = EPS\n  ): { labels: number[]; datasets: Array<{ label: string; data: number[] }> } {\n    const damageValues = this.combined.support();\n\n    const datasets = labels.map((outcomeLabel) => ({\n      label: outcomeLabel,\n      data: damageValues.map((dmg) => {\n        const bin = this.combined.map.get(dmg);\n        const v = bin ? (bin.count[outcomeLabel] as number) || 0 : 0;\n        return v <= epsilon ? 0 : v;\n      }),\n    }));\n\n    return { labels: damageValues, datasets };\n  }\n\n  /**\n   * Returns pure mathematical data for cumulative distribution function (CDF).\n   * Shows P(X ≤ x) - the probability of getting at most x damage.\n   *\n   * @param asPercentages Whether to return percentages (0-100) or probabilities (0-1)\n   * @returns Pure data structure with support and cumulative probabilities\n   *\n   * @example\n   * query.toCDFSeries()\n   * // → {support: [0, 6, 12], data: [5.2, 18.3, 45.1]}\n   */\n  toCDFSeries(asPercentages: boolean = true): {\n    support: number[];\n    data: number[];\n  } {\n    const originalSupport = this.combined.support();\n    if (originalSupport.length === 0) {\n      return { support: [], data: [] };\n    }\n\n    // Create complete integer range from min to max\n    const minDamage = Math.min(...originalSupport);\n    const maxDamage = Math.max(...originalSupport);\n    const support = Array.from(\n      { length: maxDamage - minDamage + 1 },\n      (_, i) => minDamage + i\n    );\n\n    let cumulativeProbability = 0;\n    const cdfData: number[] = [];\n\n    for (const damage of support) {\n      const bin = this.combined.map.get(damage);\n      if (bin) {\n        cumulativeProbability += bin.p;\n      }\n      cdfData.push(\n        asPercentages ? cumulativeProbability * 100 : cumulativeProbability\n      );\n    }\n\n    return {\n      support,\n      data: cdfData,\n    };\n  }\n\n  /**\n   * Returns pure mathematical data for complementary cumulative distribution function (CCDF).\n   * Shows P(X ≥ x) - the probability of getting at least x damage.\n   *\n   * @param asPercentages Whether to return percentages (0-100) or probabilities (0-1)\n   * @returns Pure data structure with support and complementary cumulative probabilities\n   *\n   * @example\n   * query.toCCDFSeries()\n   * // → {support: [0, 6, 12], data: [100, 94.8, 81.7]}\n   */\n  toCCDFSeries(asPercentages: boolean = true): {\n    support: number[];\n    data: number[];\n  } {\n    const originalSupport = this.combined.support();\n    if (originalSupport.length === 0) {\n      return { support: [], data: [] };\n    }\n\n    // Create complete integer range from min to max\n    const minDamage = Math.min(...originalSupport);\n    const maxDamage = Math.max(...originalSupport);\n    const support = Array.from(\n      { length: maxDamage - minDamage + 1 },\n      (_, i) => minDamage + i\n    );\n\n    // Calculate CCDF: P(X ≥ x) = 1 - P(X < x)\n    let cumulativeProbability = 0;\n    const ccdfData: number[] = [];\n\n    for (const damage of support) {\n      // For CCDF at point x, we want P(X ≥ x) = 1 - P(X < x)\n      // which is the total probability minus cumulative up to (but not including) x\n      const ccdf = 1 - cumulativeProbability;\n      ccdfData.push(asPercentages ? ccdf * 100 : ccdf);\n\n      // Now add current probability for next iteration\n      const bin = this.combined.map.get(damage);\n      if (bin) {\n        cumulativeProbability += bin.p;\n      }\n    }\n\n    return {\n      support,\n      data: ccdfData,\n    };\n  }\n\n  /*\n        Statistics snapshot of the query.\n            */\n\n  /** Probability of doing strictly more than threshold damage (default >0). */\n  probDamageGreaterThan(threshold = 0): number {\n    let acc = 0;\n    for (const [x, bin] of this.combined.map) if (x > threshold) acc += bin.p;\n    return acc;\n  }\n\n  /** All outcome keys actually present (typed & ordered if you pass an order). */\n  outcomeKeys(order?: OutcomeType[]): OutcomeType[] {\n    const found = new Set<string>();\n    for (const [, bin] of this.combined.map) {\n      for (const k in bin.count)\n        if (bin.count[k] && (bin.count[k] as number) > 0) found.add(k);\n    }\n    if (found.size === 0)\n      [\"hit\", \"crit\", \"missNone\"].forEach((k) => found.add(k));\n    const keys = Array.from(found).filter(\n      (k) => order?.includes(k as OutcomeType) ?? true\n    ) as OutcomeType[];\n    if (order && order.length)\n      keys.sort((a, b) => order.indexOf(a) + 999 - (order.indexOf(b) + 999));\n    return keys;\n  }\n\n  /** Total probability per outcome across the PMF. */\n  outcomeTotals(\n    outcomes: OutcomeType[] = this.outcomeKeys()\n  ): Map<OutcomeType, number> {\n    const totals = new Map<OutcomeType, number>();\n    outcomes.forEach((o) => totals.set(o, 0));\n    for (const [, row] of this.combined.map) {\n      for (const o of outcomes) {\n        const p = (row.count[o] as number) || 0; // if your bins store per-outcome p; else derive via toLabeledTable\n        totals.set(o, (totals.get(o) || 0) + p);\n      }\n    }\n    return totals;\n  }\n\n  /** Conditional damage range per outcome (min/avg/max of X | outcome). */\n  outcomeDamageRanges(\n    outcomes: OutcomeType[] = this.outcomeKeys()\n  ): Map<OutcomeType, { min: number; avg: number; max: number }> {\n    // Use toLabeledTable to stay consistent with your existing attribution\n    const table = this.toLabeledTable(outcomes);\n    const ranges = new Map<\n      OutcomeType,\n      { min?: number; max?: number; sum: number; mass: number }\n    >();\n    outcomes.forEach((o) => ranges.set(o, { sum: 0, mass: 0 }));\n\n    for (const row of table) {\n      const dmg = row.damage as number;\n      for (const o of outcomes) {\n        const p = (row[o] as number) || 0; // joint mass at (damage, outcome)\n        if (p > 0) {\n          const r = ranges.get(o)!;\n          r.sum += dmg * p;\n          r.mass += p;\n          if (r.min === undefined || dmg < r.min) r.min = dmg;\n          if (r.max === undefined || dmg > r.max) r.max = dmg;\n        }\n      }\n    }\n\n    const out = new Map<\n      OutcomeType,\n      { min: number; avg: number; max: number }\n    >();\n    for (const o of outcomes) {\n      const r = ranges.get(o)!;\n      const avg = r.mass > 0 ? r.sum / r.mass : 0;\n      out.set(o, { min: r.min ?? 0, avg, max: r.max ?? 0 });\n    }\n    return out;\n  }\n\n  /**\n   * Per-outcome probabilities and damage ranges, aggregated over the individual\n   * singles rather than read off the combined distribution.\n   *\n   * `damageRange` is the sum, over every single that can produce the outcome, of\n   * that single's own conditional damage range: \"what this outcome contributes\n   * across the whole turn when every attack that can produce it does\". Linear in\n   * the number of attacks by construction.\n   *\n   * Prefer this over {@link DiceQuery.snapshot} for a multi-attack query.\n   * `snapshot` reads `damageRange` off the combined PMF's `count`, which the\n   * convolution accumulates as an expected count, so its `avg` is size-biased\n   * for N≥2 (its own doc comment says so). The two agree for a single attack.\n   *\n   * Only outcomes that actually occur appear in the result.\n   *\n   * Like every `singles`-based helper on this class, it describes the singles\n   * and not an explicitly provided `combined`. `Turn.toQuery()` supplies one whose\n   * distribution also contains rider attacks that are absent from `singles`\n   * (an `otherwise([unarmed, unarmed])` flurry, say), so those attacks do not\n   * appear here. For rider-inclusive figures read the combined distribution\n   * directly: {@link DiceQuery.outcomeTotals}, {@link DiceQuery.outcomeDamageRanges}.\n   *\n   * @param outcomes Which outcomes to consider; defaults to every canonical one.\n   */\n  outcomeStats(\n    outcomes: readonly OutcomeType[] = ALL_OUTCOME_TYPES\n  ): Map<OutcomeType, OutcomeSnapshot> {\n    const stats = new Map<OutcomeType, OutcomeSnapshot>();\n    const perSingle = this.singles.map((pmf) => new DiceQuery([pmf], undefined, this._eps));\n\n    for (const outcome of outcomes) {\n      const atLeastOneProbability = this.probAtLeastOne(outcome);\n      if (atLeastOneProbability <= 0) continue;\n\n      const damageRange = { min: 0, avg: 0, max: 0 };\n      let contributors = 0;\n      for (const single of perSingle) {\n        if (single.probAtLeastOne(outcome) <= 0) continue;\n        contributors++;\n        const stat = single.damageStatsFrom(outcome);\n        damageRange.min += stat.min;\n        damageRange.avg += stat.avg;\n        damageRange.max += stat.max;\n      }\n\n      stats.set(outcome, {\n        atLeastOneProbability,\n        allProbability:\n          contributors > 0 ? this.probExactlyK(outcome, contributors) : 0,\n        damageRange,\n      });\n    }\n\n    return stats;\n  }\n\n  /**\n   * Snapshot of the distribution in the exact shape the UI consumes.\n   * - outcome probabilities are \"at least one\" (and equal to \"all\" for a single PMF)\n   * - damageRange is conditional on the outcome occurring\n   *\n   * The outcome probabilities use the correct Poisson-binomial marginals\n   * (`atLeastOneProbability` = P(≥1 attack has it), `allProbability` = P(all do)),\n   * so they are always valid probabilities in [0,1].\n   *\n   * KNOWN LIMITATION (multi-attack): `damageRange.avg` is still aggregated from\n   * the combined PMF's `count`, which the convolution accumulates as an EXPECTED\n   * COUNT, so for N≥2 attacks it is the size-biased mean E[dmg·#label]/E[#label]\n   * rather than a clean conditional expectation. It is correct for a single\n   * attack.\n   */\n  snapshot(order?: readonly OutcomeType[]): Snapshot {\n    // 1) Discover which outcomes actually appear in this PMF\n    const discovered = new Set<string>();\n    for (const [, bin] of this.combined.map) {\n      for (const k in bin.count) {\n        if (bin.count[k] && (bin.count[k] as number) > 0) discovered.add(k);\n      }\n    }\n    if (discovered.size === 0) {\n      for (const k of DiceQuery.DEFAULT_OUTCOMES) discovered.add(k);\n    }\n\n    let outcomes = Array.from(discovered);\n\n    // Optional filtering + ordering if a preferred order was provided\n    if (order && order.length) {\n      const inOrder = new Set(order);\n      outcomes = outcomes.filter((k) => inOrder.has(k as OutcomeType));\n      const rank = new Map(order.map((k, i) => [k, i]));\n      outcomes.sort(\n        (a, b) =>\n          (rank.get(a as OutcomeType) ?? 999) -\n          (rank.get(b as OutcomeType) ?? 999)\n      );\n    }\n\n    // 2) Aggregate per-outcome mass and conditional damage ranges via labeled table\n    const rows = this.toLabeledTable(outcomes as OutcomeType[]);\n\n    const rangeAcc = new Map<\n      OutcomeType,\n      { min?: number; max?: number; sum: number; mass: number }\n    >();\n    for (const ot of outcomes) {\n      rangeAcc.set(ot as OutcomeType, { sum: 0, mass: 0 });\n    }\n\n    for (const row of rows) {\n      const dmg = row.damage as number;\n      for (const ot of outcomes) {\n        const p = (row[ot] as number) || 0;\n        if (p <= 0) continue;\n\n        const r = rangeAcc.get(ot as OutcomeType)!;\n        r.sum += dmg * p;\n        r.mass += p;\n        if (r.min === undefined || dmg < r.min) r.min = dmg;\n        if (r.max === undefined || dmg > r.max) r.max = dmg;\n      }\n    }\n\n    const n = this.singles.length;\n    const outcomeMap = new Map<OutcomeType, OutcomeSnapshot>();\n    for (const ot of outcomes) {\n      const r = rangeAcc.get(ot as OutcomeType)!;\n      const avg = r.mass > 0 ? r.sum / r.mass : 0;\n      // Use the correct per-attack marginals (Poisson-binomial) so these are\n      // always valid probabilities in [0,1]. For a single attack both reduce to\n      // P(outcome); the previous `total` was an expected count and could exceed 1.\n      outcomeMap.set(ot as OutcomeType, {\n        atLeastOneProbability: this.probAtLeastOne(ot as OutcomeType),\n        allProbability: this.probAtLeastK(ot as OutcomeType, n),\n        damageRange: { min: r.min ?? 0, avg, max: r.max ?? 0 },\n      });\n    }\n\n    // 3) Scalars: mean, damageChance, and percentiles from the dense CDF\n    const averageDPR = this.mean();\n\n    let damageChance = 0; // P(total damage > 0)\n    for (const [x, bin] of this.combined.map) if (x > 0) damageChance += bin.p;\n\n    const { support, data } = this.toCDFSeries(false); // P(X ≤ x) in 0..1\n    const quantile = (p: number) => {\n      if (support.length === 0) return 0;\n      for (let i = 0; i < support.length; i++)\n        if (data[i] >= p) return support[i];\n      return support[support.length - 1];\n    };\n    const percentiles = {\n      p25: quantile(0.25),\n      p50: quantile(0.5),\n      p75: quantile(0.75),\n    };\n\n    return { averageDPR, damageChance, percentiles, outcomes: outcomeMap };\n  }\n\n  /**\n   * PMF Transformation Methods\n   *\n   * These methods provide a fluent API for transforming dice queries by wrapping\n   * the underlying PMF transformation methods. All operations work on the combined\n   * PMF and return new DiceQuery instances.\n   */\n\n  /**\n   * Returns a new DiceQuery with normalized probabilities (ensuring they sum to 1.0).\n   *\n   * @returns New DiceQuery with normalized combined PMF\n   */\n  normalize(): DiceQuery {\n    return new DiceQuery([this.combined.normalize()]);\n  }\n\n  /**\n   * Returns a new DiceQuery with low-probability outcomes removed.\n   *\n   * @param eps Minimum probability threshold (defaults to PMF epsilon)\n   * @param keepFinalBin Whether to keep the highest damage bin regardless of probability\n   * @returns New DiceQuery with compacted combined PMF\n   */\n  compact(eps?: number, keepFinalBin?: boolean): DiceQuery {\n    return new DiceQuery([this.combined.compact(eps, keepFinalBin)]);\n  }\n\n  /**\n   * Returns a new DiceQuery with an additional scaled branch added.\n   * Useful for conditional outcomes like \"30% chance of opportunity attack\".\n   *\n   * @param branch DiceQuery to add as a scaled branch\n   * @param probability Probability of the branch occurring (0-1)\n   * @returns New DiceQuery combining this query with the scaled branch\n   *\n   * @example\n   * const baseAttack = parse(\"(d20 + 5 AC 15) * (2d6 + 3)\");\n   * const opportunityAttack = parse(\"(d20 + 5 AC 15) * (1d8 + 3)\");\n   * const withOpportunity = baseAttack.addScaled(opportunityAttack, 0.3);\n   */\n  addScaled(branch: DiceQuery, probability: number): DiceQuery {\n    return new DiceQuery([\n      this.combined.addScaled(branch.combined, probability),\n    ]);\n  }\n\n  /**\n   * Returns a new DiceQuery with all probabilities scaled by a factor.\n   * Used for conditional scenarios where the entire outcome has reduced probability.\n   *\n   * @param factor Scaling factor for probabilities\n   * @returns New DiceQuery with scaled probabilities\n   *\n   * @example\n   * const fullAttack = parse(\"(d20 + 5 AC 15) * (2d6 + 3)\");\n   * const conditionalAttack = fullAttack.scaleMass(0.3); // 30% chance scenario\n   */\n  scaleMass(factor: number): DiceQuery {\n    return new DiceQuery([this.combined.scaleMass(factor)]);\n  }\n\n  totalMass(): number {\n    return this.combined.mass();\n  }\n\n  /**\n   * Returns a new DiceQuery with damage values transformed by a function.\n   * Useful for applying modifiers, resistances, or other damage transformations.\n   *\n   * @param damageTransformFunction Function to transform each damage value\n   * @returns New DiceQuery with transformed damage values\n   *\n   * @example\n   * const baseAttack = parse(\"2d6 + 3\");\n   * const withResistance = baseAttack.mapDamage(dmg => Math.floor(dmg / 2)); // Half damage\n   * const withBonus = baseAttack.mapDamage(dmg => dmg + 5); // +5 damage\n   */\n  mapDamage(\n    damageTransformFunction: (damageValue: number) => number\n  ): DiceQuery {\n    return new DiceQuery([this.combined.mapDamage(damageTransformFunction)]);\n  }\n\n  /**\n   * Returns a new DiceQuery with damage values scaled by a factor.\n   * Convenient wrapper around mapDamage for multiplicative scaling.\n   *\n   * @param factor Scaling factor for damage values\n   * @param rounding Rounding method: \"floor\" (default), \"round\", or \"ceil\"\n   * @returns New DiceQuery with scaled damage values\n   *\n   * @example\n   * const baseAttack = parse(\"2d6 + 3\");\n   * const doubled = baseAttack.scaleDamage(2); // Double damage\n   * const halfDamage = baseAttack.scaleDamage(0.5, \"round\"); // Half damage, rounded\n   */\n  scaleDamage(\n    factor: number,\n    rounding: \"floor\" | \"round\" | \"ceil\" = \"floor\"\n  ): DiceQuery {\n    return new DiceQuery([this.combined.scaleDamage(factor, rounding)]);\n  }\n\n  /**\n   * Returns a new DiceQuery combining this query with another via convolution.\n   * Equivalent to rolling both queries independently and adding results.\n   * It is important to use this rather than combing()ing the PMFs directly!\n   * This method maintains the provenance of the PMFs which is needed for damage attribution.\n   * Combining the .combined PMFs directly is still valid for DPR calculations but\n   * is not statistically sound for queries.\n   *\n   * @param other DiceQuery to combine with\n   * @param eps Optional epsilon for precision control\n   * @returns New DiceQuery representing the combined outcome\n   *\n   * @example\n   * const mainAttack = parse(\"(d20 + 5 AC 15) * (2d6 + 3)\");\n   * const bonusAttack = parse(\"(d20 + 3 AC 15) * (1d6 + 1)\");\n   * const bothAttacks = mainAttack.convolve(bonusAttack);\n   */\n  convolve(other: DiceQuery): DiceQuery {\n    const singles = [...this.singles, ...other.singles];\n    return new DiceQuery(singles);\n  }\n\n  /**\n   * First-success split over an ordered list of DISTINCT single-swing PMFs.\n   * Each PMF may have different success/subset probabilities (from labels).\n   *\n   * successOutcome: e.g., [\"success\"] or [\"hit\", \"crit\"]\n   * subsetOutcome:  e.g., [\"subset\"] or [\"crit\"] where subset ⊆ success\n   *\n   * Returns tuple: [pFirstNonSubset, pFirstSubset, pAnySuccess, pNone]\n   */\n  public firstSuccessSplit(\n    successOutcome: OutcomeType | OutcomeType[],\n    subsetOutcome: OutcomeType | OutcomeType[],\n    eps = EPS\n  ): readonly [pSuccess: number, pSubset: number, pAny: number, pNone: number] {\n    const pmfs = this.singles;\n    if (!pmfs.length) {\n      throw new Error(\"firstSuccessSplitFromPMFs: pmfs must be non-empty\");\n    }\n\n    const toArr = (x: OutcomeType | OutcomeType[]): OutcomeType[] =>\n      Array.isArray(x) ? x : [x];\n    const clamp01 = (x: number) => Math.max(0, Math.min(1, x));\n    const tol = Math.max(eps, 8 * Number.EPSILON);\n\n    // Per-event probabilities from each PMF via DiceQuery([pmf])\n    const per = pmfs.map((pmf) => {\n      const dq = new DiceQuery([pmf]);\n      const pS = dq.probAtLeastOne(toArr(successOutcome));\n      const pB = dq.probAtLeastOne(toArr(subsetOutcome));\n      if (pB - pS > eps) {\n        throw new Error(\n          \"firstSuccessSplitFromPMFs: P(subset) > P(success) for an event. Ensure subset ⊆ success.\"\n        );\n      }\n      return { pS, pB };\n    });\n\n    // Aggregate with running miss prefix\n    let missSoFar = 1;\n    let pFirstSubset = 0;\n    let pFirstNonSubset = 0;\n    let pNone = 1;\n\n    for (const { pS, pB } of per) {\n      pFirstSubset += missSoFar * pB;\n      pFirstNonSubset += missSoFar * (pS - pB);\n      const miss = 1 - pS;\n      missSoFar *= miss;\n      pNone *= miss;\n    }\n\n    const pAny = 1 - pNone;\n\n    // Clamp and sanity check\n    const a = clamp01(pFirstNonSubset);\n    const b = clamp01(pFirstSubset);\n    const any = clamp01(pAny);\n    const none = clamp01(pNone);\n\n    if (Math.abs(a + b - any) > tol * Math.max(1, any)) {\n      throw new Error(\n        `firstSuccessSplitFromPMFs: parts do not sum to pAny. got a+b=${\n          a + b\n        }, pAny=${any}`\n      );\n    }\n\n    return [a, b, any, none] as const;\n  }\n}\n// Make sure these types are exported in your public index, or inline them here.\nexport type OutcomeSnapshot = {\n  atLeastOneProbability: number; // P(outcome occurs at least once)\n  allProbability: number; // equal to atLeastOneProbability for a single aggregated PMF\n  damageRange: { min: number; avg: number; max: number }; // conditional on the outcome occurring\n};\n\nexport type Snapshot = {\n  averageDPR: number;\n  damageChance: number; // P(total damage > 0)\n  percentiles: { p25: number; p50: number; p75: number };\n  outcomes: Map<OutcomeType, OutcomeSnapshot>;\n};\n","import { LRUCache } from \"../common/lru-cache\";\nimport type { Bin, OutcomeLabelMap, Rounding } from \"../common/types\";\nimport {\n  ALL_OUTCOME_TYPES,\n  EPS,\n  MISS_NONE_OUTCOME,\n  sortOutcomes,\n} from \"../common/types\";\nimport { DiceQuery } from \"./query\";\n\nconst cacheEnabled = true;\n\nexport const pmfCache = new LRUCache<string, PMF>(1000);\n\n/**\n * Complete numeric model for the stacked damage-attribution chart, produced by\n * {@link PMF.damageAttributionChartModel}. Carries every dice-and-probability\n * value the chart needs; a renderer only maps these numbers into its own format\n * (colors, human labels, axis units, dataset objects).\n */\nexport interface DamageAttributionChartModel {\n  /** Bucket-start value for each column. Numeric; the caller stringifies for labels. */\n  labels: number[];\n  /** Present only when the distribution was coarsened; [start,end] inclusive, per bucket. */\n  binRanges?: { start: number; end: number }[];\n  /** Discovered outcome labels in stack order. Empty for pure (unattributed) distributions. */\n  outcomes: string[];\n  /** outcome → per-bucket probability mass (fraction 0..1). Bar heights. Σ over outcomes ≈ totals[i]. */\n  series: Map<string, number[]>;\n  /**\n   * outcome → per-bucket conditional share (fraction 0..1) of that bucket's total.\n   * Tooltip signal. 0 where the bucket total is below `epsilon`; otherwise Σ over\n   * outcomes ≈ 1.\n   */\n  shares: Map<string, number[]>;\n  /** Per-bucket total probability mass (fraction 0..1). The only signal for pure distributions. */\n  totals: number[];\n  /** Reversed-convention CCDF markers: damage at which P(X ≥ x) crosses 80/50/20%. */\n  percentiles: { p80: number; p50: number; p20: number };\n  /** Distribution mean, `this.mean()`. */\n  mean: number;\n}\n\n/**\n * Probability Mass Function for discrete damage distributions.\n */\nexport class PMF {\n  // Unique ID generator for anonymous PMFs to avoid cache key collisions\n  private static __anonIdCounter = 1;\n\n  // Cached computed values\n  private _support?: number[];\n  private _min?: number;\n  private _max?: number;\n  private _totalMass?: number;\n  private _mean?: number;\n  private _variance?: number;\n  private _stdev?: number;\n  private _fingerprint?: string;\n\n  constructor(\n    public readonly map: Map<number, Bin> = new Map(),\n    public readonly epsilon = EPS,\n    public readonly normalized = false,\n    public readonly identifier: string = `anon#${PMF.__anonIdCounter++}`,\n    private _preservedProvenance = true\n  ) {}\n\n  static empty(epsilon = EPS, identifier = \"empty\") {\n    return new PMF(new Map(), epsilon, false, identifier);\n  }\n\n  // This has a single bin at value 0, mass of 1\n  static zero(epsilon = EPS): PMF {\n    const m = new Map();\n    m.set(0, { p: 1, count: { miss: 1 }, attr: {} });\n    return new PMF(m, epsilon, false, \"zero\");\n  }\n\n  static delta(value: number, epsilon = EPS): PMF {\n    return PMF.fromMap(new Map([[value, 1]]), epsilon);\n  }\n\n  /**\n   * Point mass at damage 0 tagged with the canonical `missNone` outcome.\n   *\n   * Differs from {@link PMF.zero}, which labels its zero bin `miss` — the\n   * builder's attack-resolution vocabulary. This uses the `missNone`\n   * {@link OutcomeType} that the attribution charts and outcome stats key on,\n   * so it is the correct \"clean miss / no damage\" delta for provenance-aware\n   * mixtures feeding those consumers.\n   */\n  static missNone(epsilon = EPS): PMF {\n    const m = new Map<number, Bin>();\n    m.set(0, { p: 1, count: { [MISS_NONE_OUTCOME]: 1 }, attr: {} });\n    return new PMF(m, epsilon, false, \"missNone\");\n  }\n\n  // This creates a single bin at value 0, but with weight 0.\n  static emptyMass(): PMF {\n    return PMF.zero().scaleMass(0);\n  }\n\n  //  Makes PMF iterable over [damage, bin] pairs.\n  [Symbol.iterator](): IterableIterator<[number, Bin]> {\n    return this.map[Symbol.iterator]();\n  }\n\n  static clearCache() {\n    pmfCache.clear();\n  }\n\n  /**\n   * Creates a conditional PMF from two branches (success and failure) and a probability.\n   * This is the core logic for modeling any probabilistic event where there are two\n   * distinct outcomes.\n   */\n  static branch(\n    successPMF: PMF,\n    failurePMF: PMF,\n    successProbability: number\n  ): PMF {\n    let p = successProbability;\n    if (!Number.isFinite(p)) p = 0;\n    if (p < 0) p = 0;\n    if (p > 1) p = 1;\n\n    const q = 1 - p;\n\n    // Fast paths. scaleMass(1) returns the same instance, so these hand back the\n    // branch PMF unchanged. That is safe because PMFs are treated as immutable\n    // (compact() and the other transforms now clone bins rather than mutate).\n    if (p === 0) return failurePMF.scaleMass(1);\n    if (p === 1) return successPMF.scaleMass(1);\n\n    // Choose epsilon. You can also pick Math.min for a tighter threshold.\n    const eps = successPMF.epsilon ?? failurePMF.epsilon;\n    const id = `branch(${failurePMF.identifier}*${q.toFixed(6)} + ${\n      successPMF.identifier\n    }*${p.toFixed(6)})`;\n\n    // Proper Bernoulli mixture: q·failure ⊕ p·success, assembled in a single\n    // pass. The previous `empty().addScaled(failure,q).addScaled(success,p)`\n    // chain copied failurePMF's bins twice (into the intermediate, then again\n    // when the intermediate was copied by the second addScaled). Merging both\n    // scaled branches directly into one fresh map keeps the same accumulation\n    // order — q·failure first, then p·success — so the result is bit-identical.\n    const resultMap = new Map<number, Bin>();\n    for (const [damageValue, bin] of failurePMF.map) {\n      PMF.mergeInto(resultMap, damageValue, PMF.scaleBin(bin, q));\n    }\n    for (const [damageValue, bin] of successPMF.map) {\n      PMF.mergeInto(resultMap, damageValue, PMF.scaleBin(bin, p));\n    }\n\n    return new PMF(resultMap, eps, false, id);\n  }\n\n  /**\n   * withProbability()\n   *\n   * A convenience wrapper around branch() for the common case where the \"failure\" branch is always zero().\n   *\n   *  Think of this as a shortcut for:\n   *    pmf.gate(p, PMF.zero())\n   *\n   * Use this to model a *single* Bernoulli event — an outcome that either happens or doesn't,\n   * like an opportunity attack that occurs with probability p, or a single attack that either hits or misses.\n   *\n   * This is **not** for combining multiple independent attacks or mutually exclusive multi-outcome scenarios.\n   * - For multiple independent swings, use DiceQuery with separate PMFs for each attack.\n   * - For modeling \"first success\" logic across multiple attacks (like Sneak Attack or Smite)\n   *   use query.firstSuccessSplit() to get the exact probabilities.\n   * - For scenarios with several mutually exclusive outcomes (like crit vs hit vs none), use PMF.exclusive().\n   *\n   */\n  static withProbability(successPMF: PMF, probability: number): PMF {\n    return PMF.branch(successPMF, PMF.zero(), probability);\n  }\n\n  /**\n   * gate()\n   *\n   * A conditional wrapper around branch() that applies this PMF with probability `p`,\n   * and applies a provided fallback PMF otherwise.\n   *\n   * This is useful for modeling a binary choice between two outcomes:\n   * - The \"success\" outcome (this PMF) happens with probability `p`.\n   * - The \"failure\" outcome (fallback PMF) happens with probability `1 - p`.\n   *\n   * Examples:\n   * - 25% chance to include an opportunity attack, otherwise nothing:\n   *     attackPMF.gate(0.25, PMF.zero())\n   *\n   * - 50% chance to deal fireball damage, otherwise cone of cold damage:\n   *     fireballPMF.gate(0.5, coneOfColdPMF)\n   *\n   * Relationship to other helpers:\n   * - **withProbability()** is a shortcut for the common case where the fallback is `PMF.zero()`.\n   * - **exclusive()** is for three or more mutually exclusive outcomes (e.g., crit vs hit vs none).\n   *\n   * @param p Probability of applying this PMF (between 0 and 1).\n   * @param fallback PMF to apply when this PMF is *not* selected.\n   * @returns A new PMF representing the weighted mixture of this PMF and the fallback.\n   */\n  gate(p: number, fallback: PMF) {\n    return PMF.branch(this, fallback, p);\n  }\n\n  /**\n   * PMF.exclusive()\n   *\n   * Builds a single PMF from a set of mutually exclusive weighted outcomes.\n   * Exactly one of the provided options will occur.\n   *\n   * Each option has:\n   *  - A PMF representing its outcome (e.g., damage dice).\n   *  - A weight representing its probability of being selected.\n   *\n   * Notes:\n   *  - If total weight < 1 (within eps), leftover mass is assumed to be PMF.zero()\n   *\n   * @param options Array of `{ pmf, weight }` or `[PMF, number]`.\n   * @param eps Optional tolerance for floating point rounding.\n   */\n  static exclusive(\n    options: Array<{ pmf: PMF; weight: number } | [PMF, number]>,\n    eps = EPS\n  ): PMF {\n    const items = options.map((o) =>\n      Array.isArray(o) ? { pmf: o[0], weight: o[1] } : o\n    );\n\n    // Validate weights\n    for (const { weight } of items) {\n      if (!Number.isFinite(weight) || weight < -eps) {\n        throw new Error(`PMF.exclusive: invalid weight ${weight}.`);\n      }\n    }\n\n    // Sum and check\n    let totalWeight = items.reduce((s, { weight }) => s + weight, 0);\n\n    // Normalize tiny negatives to 0 and tiny overshoot to 1 when within eps\n    if (Math.abs(totalWeight) <= eps) totalWeight = 0;\n    if (Math.abs(1 - totalWeight) <= eps) totalWeight = 1;\n\n    if (totalWeight > 1 + EPS) {\n      throw new Error(\n        `PMF.exclusive: total weight ${totalWeight} exceeds 1. (epsilon: ${eps})`\n      );\n    }\n\n    // Accumulate scaled components, skipping near-zero weights\n    let out = PMF.empty(eps);\n    for (const { pmf, weight } of items) {\n      if (weight > eps) out = out.addScaled(pmf, weight);\n    }\n\n    // Add leftover mass at zero outcome\n    const leftover = Math.max(0, 1 - totalWeight);\n    if (leftover > eps) {\n      out = out.addScaled(PMF.zero(), leftover);\n    }\n\n    return out;\n  }\n\n  /**\n   * PMF.mix()\n   *\n   * Builds a PMF as a linear combination of input PMFs with the given weights.\n   * Unlike `exclusive`, this does NOT:\n   *  - enforce that weights sum to 1\n   *  - add leftover probability to δ0 (PMF.zero())\n   *\n   * Use when outcomes are not mutually exclusive, or for interpolation/blending.\n   *\n   * @param options Array of `{ pmf, weight }` or `[PMF, number]`.\n   * @param eps Optional tolerance for skipping tiny weights.\n   */\n  static mix(\n    options: Array<{ pmf: PMF; weight: number } | [PMF, number]>,\n    eps = EPS\n  ): PMF {\n    const items = options.map((o) =>\n      Array.isArray(o) ? { pmf: o[0], weight: o[1] } : o\n    );\n\n    // Validate weights, but do not constrain their sum.\n    for (const { weight } of items) {\n      if (!Number.isFinite(weight)) {\n        throw new Error(`PMF.mix: invalid weight ${weight}.`);\n      }\n    }\n\n    let out = PMF.empty(eps);\n    for (const { pmf, weight } of items) {\n      if (Math.abs(weight) <= eps) continue; // ignore crumbs\n      out = out.addScaled(pmf, weight);\n    }\n    return out;\n  }\n  /**\n   * Adds damage attribution metadata to this PMF based on existing count metadata.\n   * For each bin, sets attr[outcome] = damage × count[outcome].\n   *\n   * This enables damage attribution charts to work with builder-generated PMFs.\n   * The parser generates attr automatically, but builder PMFs only have count.\n   *\n   * @returns New PMF with attr field populated in each bin\n   */\n  /**\n   * Returns true if this PMF already carries damage attribution metadata.\n   *\n   * Only the first positive-damage bin is inspected (parser-generated PMFs\n   * populate `attr` uniformly), so this is O(1) in practice.\n   */\n  hasAttribution(): boolean {\n    for (const [damage, bin] of this.map) {\n      if (damage !== 0 && bin.attr && Object.keys(bin.attr).length > 0) {\n        return true;\n      }\n      // Only check the first non-zero bin for performance\n      if (damage > 0) break;\n    }\n    return false;\n  }\n\n  withAttribution(): PMF {\n    // Fast path: if attr already exists, return this PMF unchanged\n    if (this.hasAttribution()) return this;\n\n    const newMap = new Map<number, Bin>();\n\n    for (const [damage, bin] of this.map) {\n      const attr: OutcomeLabelMap = {};\n\n      // For each outcome type in count, compute its damage contribution\n      for (const outcome in bin.count) {\n        const probability = bin.count[outcome] as number;\n        if (probability > 0) {\n          attr[outcome] = damage * probability;\n        }\n      }\n\n      // Create new bin with attribution\n      newMap.set(damage, {\n        p: bin.p,\n        count: { ...bin.count },\n        attr: Object.keys(attr).length > 0 ? attr : undefined,\n      });\n    }\n\n    // Use a different identifier to avoid cache collisions with non-attributed version\n    return new PMF(\n      newMap,\n      this.epsilon,\n      this.normalized,\n      `${this.identifier}~attr`\n    );\n  }\n\n  /**\n   * General-purpose N-way mixture.\n   * weights: Array of [weight, PMF].\n   *\n   * Example: PMF.mixN([\n   *   [pMiss, zero],\n   *   [pHit, hitPMF],\n   *   [pCrit, critPMF],\n   * ]);\n   */\n  static mixN(weights: [number, PMF][], eps = EPS): PMF {\n    // Treat tiny/negative as zero; keep performance clean\n    const filtered = weights.filter(([w]) => w > eps);\n\n    if (filtered.length === 0) {\n      return PMF.emptyMass(); // not PMF.zero(): we want \"no mass\" mixture\n    }\n\n    // No need to normalize up front; we accumulate and blend by relative weight\n    let acc: PMF | null = null;\n    let sum = 0;\n\n    for (const [w, pmf] of filtered) {\n      if (acc === null) {\n        acc = pmf;\n        sum = w;\n      } else {\n        const q = w / (sum + w); // relative weight of the new component\n        acc = PMF.branch(pmf, acc, q); // success=new pmf, failure=acc\n        sum += w;\n      }\n    }\n\n    // If everything got filtered out (all ~0), return empty mass\n    return acc ?? PMF.emptyMass();\n  }\n\n  // This is a convenience method for when we use power\n  // TODO: It can be smarter in the future, and we can also add it to query\n  // That way statistics operations on invalid PMFs can throw an error\n  // TODO… how can we detect if manually merging two queries' combined PMFs, as that loses provenance?\n  private setPreservedProvenance(preserved: boolean) {\n    if (!this._preservedProvenance && preserved) {\n      throw new Error(\n        \"Preserved provenance is already set to false, cannot fix that\"\n      );\n    }\n    this._preservedProvenance = preserved;\n  }\n\n  public preservedProvenance(): boolean {\n    return this._preservedProvenance;\n  }\n\n  private getPowerCacheKey(n: number, eps: number): string {\n    // Includes fingerprint() (per-bin probability/count/attr content), matching convolve()'s\n    // cache key: the identifier alone is not content-unique. `mapDamage`/`scaleDamage`,\n    // `normalize()`, and `compact()` all keep the PARENT's identifier while producing a\n    // numerically different PMF\n    // (e.g. `X.mapDamage(f).power(2)` and `X.mapDamage(g).power(2)` would otherwise collide on\n    // the same key `map(X)+map(X)@eps` and silently return each other's cached result).\n    const id = this.identifier;\n    let key = `${id}`;\n    for (let i = 1; i < n; i++) key += `+${id}`;\n    return `${key}@${eps}|${this.fingerprint()}`;\n  }\n\n  /**\n   * Efficiently computes this PMF convolved with itself `n` times.\n   * Uses exponentiation by squaring to reduce total convolutions.\n   * n must be a positive integer.\n   * *\n   * * NOTE: This folds multiple independent attacks into a single PMF.\n   * As a result, The power() method causes a loss of data provenance.\n   * This is ONLY SAFE if you are trying to calculate masses.\n   * If you want to query any atLeast probabilities, you should use the DiceQuery class instead without power().\n   */\n  power(n: number, eps = this.epsilon): PMF {\n    if (!Number.isInteger(n) || n <= 0) {\n      throw new Error(\"power(n): n must be a positive integer\");\n    }\n    if (n === 1) return this;\n\n    const epsilon = eps ?? this.epsilon;\n\n    const key = this.getPowerCacheKey(n, epsilon);\n    if (cacheEnabled) {\n      const cached = pmfCache?.get(key);\n      if (cached) return cached;\n    }\n\n    // Start from the base PMF and accumulate n-1 additional powers\n    let base: PMF = this.normalized ? this : this.normalize();\n    let result: PMF = base;\n    let exp = n - 1;\n\n    while (exp > 0) {\n      if (exp & 1) {\n        result = result.convolve(base, epsilon);\n      }\n      exp >>= 1;\n      if (exp > 0) {\n        base = base.convolve(base, epsilon);\n      }\n    }\n\n    result.setPreservedProvenance(false);\n    if (cacheEnabled) {\n      pmfCache?.set(key, result);\n    }\n    return result;\n  }\n\n  /*\n   * Helper for chaining multiple identical attacks\n   */\n  replicate(n: number): PMF[] {\n    if (!Number.isInteger(n) || n <= 0) {\n      throw new Error(\"replicate(n): n must be a positive integer\");\n    }\n    if (n === 1) return [this];\n    return Array.from({ length: n }, () => this);\n  }\n\n  mass(): number {\n    if (this._totalMass === undefined) {\n      let totalProbabilityMass = 0;\n      for (const { p } of this.map.values()) {\n        totalProbabilityMass += p;\n      }\n      this._totalMass = totalProbabilityMass;\n    }\n    return this._totalMass;\n  }\n\n  outcomeMass(outcome: string): number {\n    let totalProbabilityMass = 0;\n    for (const { p, count } of this.map.values()) {\n      totalProbabilityMass += p * ((count[outcome] as number) ?? 0);\n    }\n    return totalProbabilityMass;\n  }\n\n  // Helper for testing\n  faceTotal(): number {\n    return [...this.map.keys()].reduce((sum, key) => sum + key, 0);\n  }\n\n  normalize(): PMF {\n    if (this.normalized) return this;\n    const normalizationFactor = this.mass();\n    if (normalizationFactor === 0) return this;\n\n    // Note: this divides by normalizationFactor rather than multiplying by its\n    // reciprocal, to keep results bit-identical to direct division.\n    const normalizedMap = new Map<number, Bin>();\n    for (const [damageValue, probabilityBin] of this.map) {\n      const normalizedCount: OutcomeLabelMap = {};\n      for (const labelKey in probabilityBin.count) {\n        normalizedCount[labelKey] =\n          (probabilityBin.count[labelKey] as number) / normalizationFactor;\n      }\n\n      let normalizedAttributes: OutcomeLabelMap | undefined;\n      if (probabilityBin.attr) {\n        normalizedAttributes = {};\n        for (const labelKey in probabilityBin.attr) {\n          normalizedAttributes[labelKey] =\n            (probabilityBin.attr[labelKey] as number) / normalizationFactor;\n        }\n      }\n\n      normalizedMap.set(damageValue, {\n        p: probabilityBin.p / normalizationFactor,\n        count: normalizedCount,\n        attr: normalizedAttributes,\n      });\n    }\n    return new PMF(normalizedMap, this.epsilon, true, this.identifier);\n  }\n\n  /**\n   * Returns a copy with negligible probabilities removed (p < eps).\n   * If keepFinalBin is true, the bin with the largest key is always kept,\n   * even if its probability is below eps. count/attr submaps are still cleaned.\n   */\n  compact(eps = this.epsilon, keepFinalBin = false): PMF {\n    let maxKey = -Infinity;\n    if (keepFinalBin) {\n      for (const key of this.map.keys()) {\n        if (key > maxKey) maxKey = key;\n      }\n    }\n\n    const compactedMap = new Map<number, Bin>();\n\n    for (const [damageValue, probabilityBin] of this.map) {\n      const shouldKeep =\n        probabilityBin.p >= eps || (keepFinalBin && damageValue === maxKey);\n\n      if (!shouldKeep) continue;\n\n      // Build a fresh Bin rather than mutating the source. Bins are shared by\n      // reference across PMFs (e.g. branch()/addScaled()/scaleMass() fast paths\n      // can carry another PMF's bin objects), so deleting sub-eps entries in\n      // place would silently corrupt the source PMF's count/attr.\n      const cleanedBin = PMF.cloneBin(probabilityBin);\n\n      for (const labelKey in cleanedBin.count) {\n        if (Math.abs(cleanedBin.count[labelKey] || 0) < eps) {\n          delete cleanedBin.count[labelKey];\n        }\n      }\n\n      if (cleanedBin.attr) {\n        for (const labelKey in cleanedBin.attr) {\n          if (Math.abs(cleanedBin.attr[labelKey] || 0) < eps) {\n            delete cleanedBin.attr[labelKey];\n          }\n        }\n        if (Object.keys(cleanedBin.attr).length === 0) {\n          cleanedBin.attr = undefined;\n        }\n      }\n\n      compactedMap.set(damageValue, cleanedBin);\n    }\n\n    return new PMF(compactedMap, eps, this.normalized, this.identifier);\n  }\n\n  // Note: The \"support\" of a PMF is the set of all non-zero probability outcomes.\n  // This returns all damage values with non-zero probability, sorted ascending.\n  support(): number[] {\n    if (this._support === undefined) {\n      this._support = [...this.map.keys()].sort((a, b) => a - b);\n    }\n    return this._support!;\n  }\n\n  // Minimum possible damage value.\n  min(): number {\n    if (this._min === undefined) {\n      const support = this.support();\n      this._min = support.length > 0 ? support[0] : 0;\n    }\n    return this._min;\n  }\n\n  // Maximum possible damage value.\n  max(): number {\n    if (this._max === undefined) {\n      const support = this.support();\n      this._max = support.length > 0 ? support[support.length - 1] : 0;\n    }\n    return this._max;\n  }\n\n  /**\n   * Returns the expected (mean) damage value.\n   * Cached for performance since this requires iterating through all bins.\n   */\n  mean(): number {\n    if (this._mean === undefined) {\n      let totalSum = 0;\n      for (const [damageValue, probabilityBin] of this.map) {\n        totalSum += damageValue * probabilityBin.p;\n      }\n      this._mean = totalSum;\n    }\n    return this._mean;\n  }\n\n  /**\n   * Returns the variance of the damage distribution.\n   * Cached for performance since this requires mean calculation plus iteration.\n   */\n  variance(): number {\n    if (this._variance === undefined) {\n      const meanValue = this.mean();\n      let varianceSum = 0;\n      for (const [damageValue, probabilityBin] of this.map) {\n        const deviationFromMean = damageValue - meanValue;\n        varianceSum += deviationFromMean * deviationFromMean * probabilityBin.p;\n      }\n      this._variance = varianceSum;\n    }\n    return this._variance;\n  }\n\n  /**\n   * Returns the standard deviation of the damage distribution.\n   */\n  stdev(): number {\n    if (this._stdev === undefined) {\n      this._stdev = Math.sqrt(this.variance());\n    }\n    return this._stdev;\n  }\n\n  /** Deep-copies a Bin, cloning its count and (optional) attr maps. */\n  private static cloneBin(bin: Bin): Bin {\n    return {\n      p: bin.p,\n      count: { ...bin.count },\n      attr: bin.attr ? { ...bin.attr } : undefined,\n    };\n  }\n\n  /** Returns a new Bin with p, count, and attr all multiplied by `factor`. */\n  private static scaleBin(bin: Bin, factor: number): Bin {\n    const count: OutcomeLabelMap = {};\n    for (const k in bin.count) {\n      count[k] = (bin.count[k] as number) * factor;\n    }\n\n    let attr: OutcomeLabelMap | undefined;\n    if (bin.attr) {\n      attr = {};\n      for (const k in bin.attr) {\n        attr[k] = (bin.attr[k] as number) * factor;\n      }\n    }\n\n    return { p: bin.p * factor, count, attr };\n  }\n\n  private static mergeInto(\n    destinationMap: Map<number, Bin>,\n    damageValue: number,\n    binToAdd: Bin\n  ) {\n    const existingBin = destinationMap.get(damageValue);\n    if (!existingBin) {\n      destinationMap.set(damageValue, PMF.cloneBin(binToAdd));\n      return;\n    }\n\n    existingBin.p += binToAdd.p;\n\n    for (const labelKey in binToAdd.count) {\n      existingBin.count[labelKey] =\n        (existingBin.count[labelKey] || 0) +\n        (binToAdd.count[labelKey] as number);\n    }\n\n    if (binToAdd.attr) {\n      if (!existingBin.attr) {\n        existingBin.attr = {};\n      }\n      for (const labelKey in binToAdd.attr) {\n        existingBin.attr[labelKey] =\n          (existingBin.attr[labelKey] || 0) +\n          (binToAdd.attr[labelKey] as number);\n      }\n    }\n  }\n\n  // Convenience method\n  add(other: PMF): PMF {\n    return this.addScaled(other, 1);\n  }\n\n  /**\n   * Returns a new PMF with a scaled branch added to this one.\n   * The branch PMF is scaled by the given probability before merging\n   * This will be very useful for conditional effects and for being\n   * able to model \"I can probably have this opportunity attack 40% of rounds\"\n   * Example: `pmf.addScaled(critBranch, 0.05)` → PMF including 5% crit outcomes\n   */\n  addScaled(branch: PMF, probability: number): PMF {\n    if (probability === 0) return this;\n\n    const resultMap = new Map<number, Bin>();\n    for (const [dmg, bin] of this.map) {\n      resultMap.set(dmg, PMF.cloneBin(bin));\n    }\n\n    for (const [damageValue, probabilityBin] of branch.map) {\n      PMF.mergeInto(\n        resultMap,\n        damageValue,\n        PMF.scaleBin(probabilityBin, probability)\n      );\n    }\n\n    return new PMF(\n      resultMap,\n      this.epsilon,\n      false,\n      `${this.identifier}+scaled(${branch.identifier},${probability})`\n    );\n  }\n\n  /**\n   * Redistributes probability mass to model an effect that only occurs with\n   * probability `frequency` — a conditional attack, an on-hit rider, or a\n   * sub-one AoE target fraction.\n   *\n   * Every hit outcome (damage > 0) is scaled by `frequency` — probability mass,\n   * per-label `count`, AND per-label `attr` — and the freed mass is moved into\n   * the miss bin at damage 0, tagged with the canonical `missNone` outcome.\n   * Total probability mass is preserved.\n   *\n   * Unlike a bare {@link scaleMass} or {@link mapDamage}, this keeps damage\n   * attribution (`attr`) intact, so a frequency-scaled PMF still renders\n   * correctly in the damage-attribution charts.\n   *\n   * `frequency >= 1` (or non-finite) returns this PMF unchanged; `frequency <= 0`\n   * collapses all mass into the miss bin. The miss outcome is assumed to be\n   * encoded at damage value 0.\n   *\n   * @param frequency Probability in [0, 1] that the effect occurs.\n   */\n  applyHitFrequency(frequency: number): PMF {\n    if (!Number.isFinite(frequency) || frequency >= 1) return this;\n    const freq = Math.max(0, frequency);\n\n    const pMiss = this.pAt(0);\n    const pHit = 1 - pMiss;\n    const newMissMass = pMiss + (1 - freq) * pHit;\n\n    const newMap = new Map<number, Bin>();\n    newMap.set(0, {\n      p: newMissMass,\n      count: { [MISS_NONE_OUTCOME]: newMissMass },\n      attr: {},\n    });\n\n    for (const [damage, bin] of this.map) {\n      if (damage <= 0) continue;\n      newMap.set(damage, PMF.scaleBin(bin, freq));\n    }\n\n    return new PMF(\n      newMap,\n      this.epsilon,\n      false,\n      `freq(${this.identifier},${freq})`\n    );\n  }\n\n  scaleMass(factor: number): PMF {\n    if (factor === 1) return this;\n\n    const scaledMap = new Map<number, Bin>();\n    for (const [damageValue, probabilityBin] of this.map) {\n      scaledMap.set(damageValue, PMF.scaleBin(probabilityBin, factor));\n    }\n    return new PMF(\n      scaledMap,\n      this.epsilon,\n      false,\n      `scale(${this.identifier},${factor})`\n    );\n  }\n\n  mapDamage(damageTransformFunction: (damageValue: number) => number): PMF {\n    const transformedMap = new Map<number, Bin>();\n    for (const [originalDamage, probabilityBin] of this.map) {\n      const transformedDamage = damageTransformFunction(originalDamage);\n      PMF.mergeInto(\n        transformedMap,\n        transformedDamage,\n        PMF.cloneBin(probabilityBin)\n      );\n    }\n    return new PMF(\n      transformedMap,\n      this.epsilon,\n      this.normalized,\n      `map(${this.identifier})`\n    );\n  }\n\n  scaleDamage(\n    factor: number,\n    rounding: \"floor\" | \"round\" | \"ceil\" = \"floor\"\n  ): PMF {\n    const roundFunction =\n      rounding === \"round\"\n        ? Math.round\n        : rounding === \"ceil\"\n        ? Math.ceil\n        : Math.floor;\n    return this.mapDamage((damageValue) => roundFunction(damageValue * factor));\n  }\n\n  private getPMFCombineCacheKey(\n    p1: PMF,\n    p2: PMF,\n    eps: number,\n    raw: boolean\n  ): string {\n    const [id1, id2] = [p1.identifier, p2.identifier].sort();\n\n    return `v4:${raw ? \"RAW\" : \"N\"}:${id1}+${id2}@${eps}|${p1.fingerprint()}|${p2.fingerprint()}`;\n  }\n\n  /**\n   * A content fingerprint of every bin (probability, per-label `count`, per-label `attr`) plus\n   * the `normalized` flag, so convolution/power cache keys change whenever the underlying\n   * numbers do. Mass/bin-count/face-sum alone are not content-unique: `mapDamage` variants can\n   * keep the same identifier, support, mass, and face sum while differing in per-bin\n   * probabilities or in the `count`/`attr` channels `convolve()`/`power()` actually propagate --\n   * that previously let `power()` return one PMF's cached result for a different PMF. Memoized\n   * because a PMF is immutable once constructed -- this avoids re-deriving the key on every\n   * convolve()/power() call (including cache hits). Bin order is sorted by damage value (and\n   * label keys sorted within each bin) so two equal-content PMFs built via different code paths\n   * fingerprint identically regardless of Map insertion order.\n   */\n  fingerprint(): string {\n    if (this._fingerprint === undefined) {\n      const bins = [...this.map.entries()].sort((a, b) => a[0] - b[0]);\n      const parts: string[] = [];\n      for (const [damageValue, bin] of bins) {\n        const countStr = Object.keys(bin.count)\n          .sort()\n          .map((k) => `${k}:${bin.count[k]}`)\n          .join(\",\");\n        const attrStr = bin.attr\n          ? Object.keys(bin.attr)\n              .sort()\n              .map((k) => `${k}:${(bin.attr as OutcomeLabelMap)[k]}`)\n              .join(\",\")\n          : \"\";\n        parts.push(`${damageValue}:${bin.p}[${countStr}]{${attrStr}}`);\n      }\n      this._fingerprint = `${this.normalized ? 1 : 0}|${parts.join(\";\")}`;\n    }\n    return this._fingerprint;\n  }\n\n  convolve(other: PMF, eps?: number, raw = false): PMF {\n    const epsilon = eps ?? this.epsilon;\n\n    // Normalize-by-value on non-raw path\n    const norm = (x: PMF) =>\n      raw ? x : Math.abs(x.mass() - 1) <= epsilon ? x : x.normalize();\n    const A0 = norm(this);\n    const B0 = norm(other);\n\n    const [A, B] = A0.identifier <= B0.identifier ? [A0, B0] : [B0, A0];\n    const cacheKey = this.getPMFCombineCacheKey(A, B, epsilon, raw);\n    const cached = pmfCache?.get(cacheKey);\n    if (cached) return cached;\n\n    // Accumulate directly into each destination bin instead of building a\n    // temporary Bin per (a,b) pair and merging it. The probability channel\n    // (`dest.p += ap*bp`) accumulates in the same order as before, so it is\n    // bit-identical; only the per-label `count`/`attr` sums re-associate, which\n    // shifts them by at most a few ULP (far below the eps pruning threshold).\n    const combinedMap = new Map<number, Bin>();\n    for (const [aVal, aBin] of A.map) {\n      const ap = aBin.p;\n      const aCount = aBin.count;\n      const aAttr = aBin.attr;\n      for (const [bVal, bBin] of B.map) {\n        const bp = bBin.p;\n        const dmg = aVal + bVal;\n\n        let dest = combinedMap.get(dmg);\n        if (dest === undefined) {\n          dest = { p: 0, count: {} };\n          combinedMap.set(dmg, dest);\n        }\n\n        dest.p += ap * bp;\n\n        const dc = dest.count;\n        for (const k in aCount) dc[k] = (dc[k] || 0) + (aCount[k] as number) * bp;\n        for (const k in bBin.count)\n          dc[k] = (dc[k] || 0) + (bBin.count[k] as number) * ap;\n\n        if (aAttr || bBin.attr) {\n          let da = dest.attr;\n          if (da === undefined) {\n            da = {};\n            dest.attr = da;\n          }\n          if (aAttr)\n            for (const k in aAttr) da[k] = (da[k] || 0) + (aAttr[k] as number) * bp;\n          if (bBin.attr)\n            for (const k in bBin.attr)\n              da[k] = (da[k] || 0) + (bBin.attr[k] as number) * ap;\n        }\n      }\n    }\n\n    let result = new PMF(\n      combinedMap,\n      epsilon,\n      !raw,\n      `${A.identifier}${raw ? \"*\" : \"+\"}${B.identifier}`\n    );\n\n    // Enforce mass invariant: mass(out) = (raw? A.mass():1) * (raw? B.mass():1)\n    const mExp = (raw ? A.mass() : 1) * (raw ? B.mass() : 1);\n    const mGot = result.mass();\n    // Guard mGot !== 0: a zero-mass operand convolves to the zero measure\n    // (mass 0). Without this guard the non-raw path would scaleMass(mExp/0) =\n    // scaleMass(Infinity), poisoning every bin to 0*Infinity = NaN.\n    if (mExp !== 0 && mGot !== 0 && Math.abs(mGot - mExp) > epsilon) {\n      result = result.scaleMass(mExp / mGot);\n    }\n    if (!raw && mGot !== 0 && Math.abs(result.mass() - 1) > epsilon)\n      result = result.normalize();\n\n    pmfCache?.set(cacheKey, result);\n    return result;\n  }\n\n  // 3) Nice wrapper so you can call pmf.combineRaw(other)\n  combineRaw(other: PMF, eps?: number): PMF {\n    return this.convolve(other, eps, true);\n  }\n\n  // Reduce a list of PMFs by left-folding convolve() with the given eps\n  private static reduceConvolveLeft(pmfList: PMF[], eps: number): PMF {\n    let result = pmfList[0];\n    for (let i = 1; i < pmfList.length; i++) {\n      result = result.convolve(pmfList[i], eps);\n    }\n    return result;\n  }\n\n  /**\n   * Convolves multiple PMFs using linear convolution with automatic caching.\n   * Uses a left-to-right accumulation approach for maximum cache reuse.\n   * Each convolve() call automatically uses the convolution cache for performance.\n   *\n   * This linear approach provides better cache hits than pairwise because:\n   * - Intermediate results are more predictable and stable\n   * - Similar PMF lists share common prefixes (A+B, (A+B)+C, etc.)\n   * - Order-independent cache keys work better with consistent build patterns\n   */\n  static convolveMany(pmfList: PMF[], eps = EPS): PMF {\n    if (pmfList.length === 0) return PMF.empty(eps);\n    if (pmfList.length === 1) return pmfList[0];\n\n    // Linear combination with automatic intermediate caching: each prefix\n    // (A+B, (A+B)+C, ...) is a stable cache key, maximizing reuse.\n    return PMF.reduceConvolveLeft(pmfList, eps);\n  }\n\n  /**\n   * Returns a plain, JSON-serializable representation of this PMF.\n   *\n   * Follows the standard `toJSON` contract, so `JSON.stringify(pmf)` produces\n   * the expected output (no double-encoding). Use {@link PMF.fromJSON} to\n   * reconstruct, or {@link PMF.toJSONString} if you need the string directly.\n   */\n  toJSON(): {\n    bins: Array<[number, Bin]>;\n    normalized: boolean;\n    identifier: string;\n  } {\n    return {\n      bins: [...this.map.entries()],\n      normalized: this.normalized,\n      identifier: this.identifier,\n    };\n  }\n\n  /** Serializes this PMF to a JSON string (equivalent to `JSON.stringify(pmf)`). */\n  toJSONString(): string {\n    return JSON.stringify(this);\n  }\n\n  static fromJSON(jsonData: {\n    bins: Array<[number, Bin]>;\n    normalized?: boolean;\n    identifier?: string;\n  }) {\n    return new PMF(\n      new Map(jsonData.bins),\n      EPS,\n      !!jsonData.normalized,\n      jsonData.identifier || \"fromJSON\"\n    );\n  }\n\n  /**\n   * Relative pruning with optional top-K floor.\n   * Keeps bins with p >= epsRel * peak, always keeps min and max damage,\n   * optionally guarantees at least `minBins` survivors by adding top-K.\n   * Returns a new, non-normalized PMF.\n   */\n  prune(epsRel: number, minBins = 0): PMF {\n    const size = this.map.size;\n    if (size === 0) return this;\n\n    // One pass: peak, min, max\n    let peak = 0;\n    let minDamage = Number.POSITIVE_INFINITY;\n    let maxDamage = Number.NEGATIVE_INFINITY;\n    for (const [dmg, bin] of this.map) {\n      if (bin.p > peak) peak = bin.p;\n      if (dmg < minDamage) minDamage = dmg;\n      if (dmg > maxDamage) maxDamage = dmg;\n    }\n    if (peak === 0)\n      return new PMF(new Map(this.map), epsRel, false, this.identifier);\n\n    const thresh = epsRel * peak;\n    const entries = [...this.map.entries()];\n\n    // Protect endpoints\n    const survivorsByDmg = new Map<number, Bin>();\n    const protect = (d: number) => {\n      const b = this.map.get(d);\n      if (b) survivorsByDmg.set(d, b);\n    };\n    protect(minDamage);\n    if (maxDamage !== minDamage) protect(maxDamage);\n\n    // Relative survivors\n    for (const [dmg, bin] of entries) {\n      if (bin.p >= thresh) survivorsByDmg.set(dmg, bin);\n    }\n\n    // Enforce minBins via top-K if requested\n    if (minBins > 0 && survivorsByDmg.size < minBins) {\n      // Sort all entries by probability desc (or replace with Quickselect for O(n))\n      entries.sort((a, b) => b[1].p - a[1].p);\n      for (const [dmg, bin] of entries) {\n        if (!survivorsByDmg.has(dmg)) {\n          survivorsByDmg.set(dmg, bin);\n          if (survivorsByDmg.size >= minBins) break;\n        }\n      }\n    }\n\n    // Rebuild map, pruning tiny count/attr entries with the same threshold\n    const prunedMap = new Map<number, Bin>();\n    for (const [dmg, bin] of survivorsByDmg) {\n      const newCount: OutcomeLabelMap = {};\n      for (const k in bin.count) {\n        const v = bin.count[k] as number;\n        if (Math.abs(v) >= thresh) newCount[k] = v;\n      }\n      let newAttr: OutcomeLabelMap | undefined;\n      if (bin.attr) {\n        for (const k in bin.attr) {\n          const v = bin.attr[k] as number;\n          if (Math.abs(v) >= thresh) {\n            if (!newAttr) newAttr = {};\n            newAttr[k] = v;\n          }\n        }\n      }\n      prunedMap.set(dmg, { p: bin.p, count: newCount, attr: newAttr });\n    }\n\n    // Return non-normalized PMF\n    return new PMF(prunedMap, epsRel, false, `prune(${this.identifier})`);\n  }\n\n  /** Probability mass at exactly x. */\n  pAt(x: number): number {\n    return this.map.get(x)?.p ?? 0;\n  }\n\n  /**\n   * P(any damage) — the mass on all non-zero outcomes, i.e. `1 - P(0)`.\n   * Assumes a miss is encoded as the damage-0 bin (the convention used across\n   * attack/save PMFs). The dual of {@link missProbability}.\n   */\n  hitProbability(): number {\n    return 1 - this.pAt(0);\n  }\n\n  /** P(no damage) — the mass at damage 0. The dual of {@link hitProbability}. */\n  missProbability(): number {\n    return this.pAt(0);\n  }\n\n  /**\n   * Coarsen the distribution into at most `maxBuckets` contiguous, equal-width\n   * damage buckets, aggregating probability mass (and `count`/`attr`\n   * provenance) into each bucket's start value. Returns this PMF unchanged when\n   * its integer support already fits within `maxBuckets`.\n   *\n   * This is a lossy display/downsampling transform (bucket start replaces the\n   * exact damage value) — use it for charting wide distributions, not for DPR\n   * math.\n   */\n  rebin(maxBuckets: number): PMF {\n    if (!(maxBuckets > 0)) return this;\n    const support = this.support();\n    if (support.length === 0) return this;\n    const min = support[0];\n    const max = support[support.length - 1];\n    const range = max - min;\n    if (range + 1 <= maxBuckets) return this;\n    const binSize = Math.ceil((range + 1) / maxBuckets);\n    return this.mapDamage((d) => min + Math.floor((d - min) / binSize) * binSize);\n  }\n\n  /** Dense integer support from min..max (inclusive).\n   * Useful for showing empty bars in charts.\n   */\n  denseSupport(): number[] {\n    const s = this.support();\n    if (s.length === 0) return [];\n    const lo = Math.min(...s),\n      hi = Math.max(...s);\n    return Array.from({ length: hi - lo + 1 }, (_, i) => lo + i).sort(\n      (a, b) => a - b\n    );\n  }\n\n  /** CDF at x: P(X ≤ x). */\n  cdfAt(x: number): number {\n    let acc = 0;\n    for (const [val, bin] of this.map) if (val <= x) acc += bin.p;\n    return acc;\n  }\n\n  /** Quantile / inverse CDF for p in [0,1]. Returns smallest x with CDF ≥ p. */\n  quantile(p: number): number {\n    if (this.map.size === 0) return 0;\n    const totalMass = this.mass();\n    if (totalMass <= 0) return 0;\n    const s = this.support().sort((a, b) => a - b);\n    let acc = 0;\n    for (const x of s) {\n      acc += this.pAt(x);\n      if (acc / totalMass >= p) return x;\n    }\n    return s[s.length - 1];\n  }\n\n  /** Get outcome probability at specific damage value. */\n  outcomeAt(damage: number, outcome: string): number {\n    return (this.map.get(damage)?.count[outcome] as number) ?? 0;\n  }\n\n  /** Get all outcome types present in this PMF. */\n  outcomes(): string[] {\n    const outcomeSet = new Set<string>();\n    for (const [, bin] of this.map) {\n      for (const outcome in bin.count) {\n        if ((bin.count[outcome] as number) > 0) {\n          outcomeSet.add(outcome);\n        }\n      }\n    }\n    return Array.from(outcomeSet).sort();\n  }\n\n  /** Get total probability of an outcome across all damage values. */\n  outcomeProbability(outcome: string): number {\n    let total = 0;\n    for (const [, bin] of this.map) {\n      total += (bin.count[outcome] as number) ?? 0;\n    }\n    return total;\n  }\n\n  /** Get damage attribution for an outcome at specific damage value. */\n  outcomeAttributionAt(damage: number, outcome: string): number {\n    return (this.map.get(damage)?.attr?.[outcome] as number) ?? 0;\n  }\n\n  /** Get all outcome data at specific damage value. */\n  binAt(damage: number): {\n    p: number;\n    count: Record<string, number>;\n    attr?: Record<string, number>;\n  } | null {\n    const bin = this.map.get(damage);\n    if (!bin) return null;\n\n    return {\n      p: bin.p,\n      count: { ...bin.count } as Record<string, number>,\n      attr: bin.attr ? ({ ...bin.attr } as Record<string, number>) : undefined,\n    };\n  }\n\n  /** Check if outcome exists in this PMF. */\n  hasOutcome(outcome: string): boolean {\n    for (const [, bin] of this.map) {\n      if (((bin.count[outcome] as number) ?? 0) > 0) {\n        return true;\n      }\n    }\n    return false;\n  }\n\n  /**\n   * Split each damage value's probability mass across outcome labels, returning\n   * per-label maps of `damage value → probability mass attributable to that\n   * label`. Summing over labels at a given value recovers that value's `p`.\n   *\n   * Damage-bearing bins are split by `attr` weight (the share of damage each\n   * outcome contributed); the clean-miss bin at 0 is split by `count` weight\n   * (there is no damage to attribute). Attribution is computed on demand via\n   * {@link withAttribution} when absent, so builder-generated PMFs work too.\n   *\n   * This is the provenance core of the stacked damage-attribution chart — the\n   * caller only maps these series into its rendering format (colors, binning,\n   * axis labels).\n   */\n  attributionByValue(): Map<string, Map<number, number>> {\n    const src = this.hasAttribution() ? this : this.withAttribution();\n    const result = new Map<string, Map<number, number>>();\n\n    const add = (label: string, damage: number, mass: number): void => {\n      if (!(mass > 0)) return;\n      let series = result.get(label);\n      if (!series) {\n        series = new Map<number, number>();\n        result.set(label, series);\n      }\n      series.set(damage, (series.get(damage) ?? 0) + mass);\n    };\n\n    for (const [damage, bin] of src.map) {\n      const p = bin.p || 0;\n      if (p <= 0) continue;\n      const isMissBin = damage === 0;\n\n      // Damage-0 (clean miss): split by count, crediting the missNone label.\n      if (isMissBin) {\n        let totalCount = 0;\n        for (const k in bin.count) totalCount += (bin.count[k] as number) || 0;\n        if (totalCount > 0) {\n          const c = (bin.count[MISS_NONE_OUTCOME] as number) || 0;\n          add(MISS_NONE_OUTCOME, damage, (c / totalCount) * p);\n        }\n        continue;\n      }\n\n      // Damage-bearing bin: split by attribution weight.\n      let totalAttr = 0;\n      if (bin.attr) for (const k in bin.attr) totalAttr += (bin.attr[k] as number) || 0;\n      if (bin.attr && totalAttr > 0) {\n        for (const k in bin.attr) {\n          if (k === MISS_NONE_OUTCOME) continue;\n          add(k, damage, (((bin.attr[k] as number) || 0) / totalAttr) * p);\n        }\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Reversed-convention CCDF percentile markers used by the attribution chart:\n   * for each target probability t, the largest damage x still reached with\n   * P(X ≥ x) > t%, falling back to the smallest/largest support value at the\n   * edges. Ported verbatim from the app so `p80/p50/p20` keep their intentional\n   * reversed meaning (p80 is the low-damage end). Computed on the full, un-binned\n   * support. Assumes a non-empty map.\n   */\n  private attributionPercentiles(): { p80: number; p50: number; p20: number } {\n    const sortedKeys = [...this.map.keys()].sort((a, b) => a - b);\n    const sparseCCDF: { x: number; y: number }[] = [];\n    let cumulativeP = 0;\n    for (let i = sortedKeys.length - 1; i >= 0; i--) {\n      const key = sortedKeys[i];\n      const bin = this.map.get(key);\n      if (!bin) continue;\n      cumulativeP += bin.p;\n      sparseCCDF.unshift({ x: key, y: cumulativeP * 100 });\n    }\n    const findDamageAtProbability = (targetProb: number): number => {\n      for (let i = 0; i < sparseCCDF.length; i++) {\n        if (sparseCCDF[i].y <= targetProb) {\n          return i > 0 ? sparseCCDF[i - 1].x : sparseCCDF[i].x;\n        }\n      }\n      return sparseCCDF[sparseCCDF.length - 1].x;\n    };\n    return {\n      p80: findDamageAtProbability(80),\n      p50: findDamageAtProbability(50),\n      p20: findDamageAtProbability(20),\n    };\n  }\n\n  /**\n   * Full numeric model for the stacked damage-attribution chart — bar-height\n   * masses, tooltip shares, bucket labels/ranges, percentile markers, and the\n   * mean. The caller only maps these into a rendering format (colors, labels,\n   * axis units); all of the dice-and-probability logic lives here.\n   *\n   * Built split-first-then-bin: the attribution split ({@link attributionByValue})\n   * runs on the un-binned distribution, then the resulting series are coarsened.\n   * {@link rebin} is deliberately *not* used — rebinning first would fold any\n   * sub-`binSize` damage into the damage-0 bucket, which the split then mistakes\n   * for a clean miss and drops.\n   *\n   * @param options.maxBuckets Coarsen to at most this many equal-width buckets\n   *   when the integer support is wider (`range > maxBuckets`); omit for a dense,\n   *   per-integer model.\n   * @param options.stackOrder Preferred outcome order (defaults to\n   *   {@link ALL_OUTCOME_TYPES}); labels outside it sort alphabetically after.\n   * @param options.epsilon Bucket-total floor below which a `shares` entry is 0\n   *   (divide-by-~0 guard). Defaults to 1e-9.\n   */\n  damageAttributionChartModel(\n    options: {\n      maxBuckets?: number;\n      stackOrder?: readonly string[];\n      epsilon?: number;\n    } = {}\n  ): DamageAttributionChartModel {\n    const { maxBuckets, stackOrder = ALL_OUTCOME_TYPES, epsilon = 1e-9 } = options;\n\n    const empty: DamageAttributionChartModel = {\n      labels: [],\n      outcomes: [],\n      series: new Map(),\n      shares: new Map(),\n      totals: [],\n      percentiles: { p80: 0, p50: 0, p20: 0 },\n      mean: 0,\n    };\n    if (this.map.size === 0) return empty;\n\n    // Split on the un-binned distribution: outcome → (damage → probability mass).\n    const split = this.attributionByValue();\n\n    // Discover outcomes across BOTH count and attr keys so any all-zero legend\n    // entries survive (matches the app's discovery), then order for stacking.\n    const discovered = new Set<string>();\n    for (const [, bin] of this.map) {\n      for (const k in bin.count) discovered.add(k);\n      if (bin.attr) for (const k in bin.attr) discovered.add(k);\n    }\n    const outcomes = sortOutcomes([...discovered], stackOrder);\n    const hasAttribution = outcomes.length > 0;\n\n    // Support window over values carrying positive mass (the app's allDamageValues):\n    // from the split for attributed PMFs, from positive-p bins for pure ones.\n    let min = Infinity;\n    let max = -Infinity;\n    const widen = (d: number): void => {\n      if (d < min) min = d;\n      if (d > max) max = d;\n    };\n    if (hasAttribution) {\n      for (const s of split.values())\n        for (const [d, m] of s) if (m > 0) widen(d);\n    } else {\n      for (const [d, bin] of this.map) if ((bin.p || 0) > 0) widen(d);\n    }\n    if (max < min) return empty; // nothing carried positive mass\n    const range = max - min;\n\n    // Binning geometry — dense (per-integer) unless range > maxBuckets.\n    const binned =\n      maxBuckets !== undefined && maxBuckets > 0 && range > maxBuckets;\n    const binSize = binned ? Math.ceil((range + 1) / maxBuckets!) : 1;\n    const numBins = binned ? Math.ceil((range + 1) / binSize) : range + 1;\n    const bucketOf = (d: number): number => Math.floor((d - min) / binSize);\n\n    const labels: number[] = [];\n    const binRanges: { start: number; end: number }[] | undefined = binned\n      ? []\n      : undefined;\n    for (let i = 0; i < numBins; i++) {\n      const start = min + i * binSize;\n      labels.push(start);\n      if (binRanges)\n        binRanges.push({ start, end: Math.min(start + binSize - 1, max) });\n    }\n\n    // Aggregate per-outcome masses into buckets.\n    const series = new Map<string, number[]>();\n    for (const outcome of outcomes) {\n      const arr = new Array<number>(numBins).fill(0);\n      const s = split.get(outcome);\n      if (s) {\n        for (const [d, m] of s) {\n          const b = bucketOf(d);\n          if (b >= 0 && b < numBins) arr[b] += m;\n        }\n      }\n      series.set(outcome, arr);\n    }\n\n    // Per-bucket totals: sum of the attributed series, or (pure) of raw p.\n    const totals = new Array<number>(numBins).fill(0);\n    if (hasAttribution) {\n      for (const arr of series.values())\n        for (let i = 0; i < numBins; i++) totals[i] += arr[i];\n    } else {\n      for (const [d, bin] of this.map) {\n        const p = bin.p || 0;\n        if (p <= 0) continue;\n        const b = bucketOf(d);\n        if (b >= 0 && b < numBins) totals[b] += p;\n      }\n    }\n\n    // Conditional shares for tooltips (guarded against a ~zero bucket total).\n    const shares = new Map<string, number[]>();\n    for (const outcome of outcomes) {\n      const arr = series.get(outcome)!;\n      const sh = new Array<number>(numBins).fill(0);\n      for (let i = 0; i < numBins; i++) {\n        sh[i] = totals[i] > epsilon ? arr[i] / totals[i] : 0;\n      }\n      shares.set(outcome, sh);\n    }\n\n    return {\n      labels,\n      binRanges,\n      outcomes,\n      series,\n      shares,\n      totals,\n      percentiles: this.attributionPercentiles(),\n      mean: this.mean(),\n    };\n  }\n\n  tailProbGE(t: number): number {\n    let s = 0;\n    for (const [x, bin] of this) {\n      if (bin.p > 0 && x >= t) s += bin.p;\n    }\n    return s;\n  }\n\n  tailProbGT(t: number): number {\n    let s = 0;\n    for (const [x, rec] of this) {\n      if (x > t) s += rec.p;\n    }\n    return s;\n  }\n\n  /**\n   * Returns a new PMF containing only bins where the specified outcome has non-zero probability.\n   * This creates a marginal distribution for the given outcome type, with probabilities\n   * scaled to represent the unconditional mass attributable to that outcome.\n   */\n  filterOutcome(outcome: string): PMF {\n    const filteredMap = new Map<number, Bin>();\n\n    for (const [damageValue, bin] of this.map) {\n      const outcomeCount = (bin.count[outcome] as number) ?? 0;\n\n      // total paths that reached this bin (sum across labels)\n      const totalCount = Object.values(bin.count ?? {}).reduce(\n        (a, b) => (a ?? 0) + ((b as number) ?? 0),\n        0\n      );\n\n      if (outcomeCount > 0 && totalCount !== undefined && totalCount > 0) {\n        // proportion of this bin's mass attributable to the outcome\n        const proportion = outcomeCount / totalCount;\n\n        // downweight p to the unconditional mass from the outcome only\n        const newP = bin.p * proportion;\n\n        const newCount: OutcomeLabelMap = { [outcome]: outcomeCount };\n\n        let newAttr: OutcomeLabelMap | undefined;\n        if (bin.attr && bin.attr[outcome] !== undefined) {\n          // If attr is a count-like accumulator, scale it too.\n          // If attr is already per-outcome only, you can just carry it over.\n          newAttr = { [outcome]: (bin.attr[outcome] as number) * proportion };\n        }\n\n        filteredMap.set(damageValue, {\n          p: newP,\n          count: newCount,\n          attr: newAttr,\n        });\n      }\n    }\n\n    return new PMF(\n      filteredMap,\n      this.epsilon,\n      false, // don't normalize by default\n      `filter(${this.identifier},${outcome})`\n    );\n  }\n  /**\n   * Calculates probabilities for first-success outcomes across n independent attempts.\n   *\n   * @param pSuccess - Total probability of any success on a single attempt.\n   * @param pSpecial - Probability of a specific subset of successes (e.g., critical success).\n   * @param n - Number of independent attempts.\n   *\n   * Returns:\n   *  - pSpecificSuccess: Probability that the first success was of the \"special\" type\n   *  - pGeneralSuccess: Probability that the first success was of the non-special type\n   *  - pNone: Probability that no successes occurred\n   *  - pAny: Probability that at least one success occurred\n   */\n  public static firstSuccessWeights(\n    pSuccess: number,\n    pSpecial: number,\n    n: number\n  ) {\n    // Preconditions: the \"special\" successes are a subset of all successes, so\n    // 0 <= pSpecial <= pSuccess <= 1. Without this guard, violating inputs\n    // silently produce probabilities outside [0,1].\n    if (\n      !Number.isFinite(pSuccess) ||\n      !Number.isFinite(pSpecial) ||\n      pSuccess < 0 ||\n      pSuccess > 1 ||\n      pSpecial < 0 ||\n      pSpecial - pSuccess > EPS\n    ) {\n      throw new Error(\n        `firstSuccessWeights: require 0 <= pSpecial <= pSuccess <= 1 (got pSuccess=${pSuccess}, pSpecial=${pSpecial})`\n      );\n    }\n\n    const pFail = 1 - pSuccess;\n    const pFailAll = Math.pow(pFail, n);\n\n    // Probability of at least one success\n    const pAny = 1 - pFailAll;\n\n    // Avoid divide-by-zero if pSuccess is 0\n    const denom = pSuccess === 0 ? 1 : pSuccess;\n\n    // Breakdown of first success type\n    const pSpecificSuccess = (pSpecial * pAny) / denom;\n    const pGeneralSuccess = ((pSuccess - pSpecial) * pAny) / denom;\n\n    const pNone = 1 - pSpecificSuccess - pGeneralSuccess; // Should equal pFailAll\n\n    return { pSpecificSuccess, pGeneralSuccess, pNone, pAny };\n  }\n\n  mapValues(\n    f: (v: number) => number,\n    eps: number = EPS,\n    opts?: { rounding?: Rounding; preserveCounts?: boolean }\n  ): PMF {\n    const rounding = opts?.rounding ?? \"none\";\n    const preserveCounts = opts?.preserveCounts ?? true;\n\n    const round = (x: number) =>\n      rounding === \"floor\"\n        ? Math.floor(x)\n        : rounding === \"ceil\"\n        ? Math.ceil(x)\n        : rounding === \"round\"\n        ? Math.round(x)\n        : x;\n\n    // Accumulate probs and merged counts\n    const probs = new Map<number, number>();\n    const counts = new Map<number, Record<string, number>>();\n\n    for (const [v, bin] of this) {\n      if (Math.abs(bin.p) < eps) continue;\n      const u = round(f(v));\n      probs.set(u, (probs.get(u) ?? 0) + bin.p);\n\n      if (preserveCounts) {\n        // Merge counts if present\n        const src = bin.count;\n        if (src) {\n          const dest = counts.get(u) ?? {};\n          for (const k in src) {\n            dest[k] = (dest[k] ?? 0) + (src[k] as number);\n          }\n          counts.set(u, dest);\n        }\n      }\n    }\n\n    // Build PMF with merged counts, then normalize\n    const internal = new Map<number, Bin>();\n    for (const [u, p] of probs) {\n      internal.set(u, { p, count: counts.get(u) ?? {} });\n    }\n    // Normalize via pmfFromMap to keep one source of truth\n    return PMF.fromMap(\n      new Map(Array.from(internal, ([u, b]) => [u, b.p] as [number, number])),\n      eps\n    );\n  }\n\n  static fromMap(\n    m: Map<number, number>,\n    eps: number = EPS,\n    { requireIntegerValues = true }: { requireIntegerValues?: boolean } = {}\n  ): PMF {\n    const filtered: Array<[number, number]> = [];\n    for (const [v, p] of m) {\n      if (!Number.isFinite(v) || !Number.isFinite(p)) continue;\n      if (p <= 0 || Math.abs(p) < eps) continue;\n      if (requireIntegerValues && !Number.isInteger(v)) {\n        throw new Error(`fromMap: non-integer outcome ${v}`);\n      }\n      filtered.push([v, p]);\n    }\n\n    if (filtered.length === 0) {\n      throw new Error(\"fromMap: empty or invalid input map\");\n    }\n\n    // Kahan sum for stability\n    let sum = 0;\n    let c = 0;\n    for (const [, p] of filtered) {\n      const y = p - c;\n      const t = sum + y;\n      c = t - sum - y;\n      sum = t;\n    }\n    if (sum <= 0) throw new Error(\"pmfFromMap: probabilities sum to 0\");\n\n    filtered.sort((a, b) => a[0] - b[0]);\n\n    const internal = new Map<number, Bin>();\n    for (const [v, p] of filtered) {\n      internal.set(v, { p: p / sum, count: {} }); // keep count object present for consistency\n    }\n    return new PMF(internal, eps);\n  }\n\n  query(): DiceQuery {\n    return new DiceQuery(this);\n  }\n}\n","// dice.ts (internal)\n\nimport { DiceParseError } from \"../common/errors\";\nimport type {\n  Bin,\n  DamageDistribution,\n  OutcomeLabelMap,\n  OutcomeType,\n} from \"../common/types\";\nimport { EPS } from \"../common/types\";\nimport { PMF } from \"../pmf/pmf\";\n\n/**\n * Work budget for a single dice×dice operation. binaryOp is O(faces₁ × faces₂),\n * so two individually-legal large dice (e.g. `d100000 + d100000`) would otherwise\n * enumerate ~10^10 face pairs and hang. The parser's per-die / per-count caps\n * bound each operand but not their product, so this bounds the operation itself.\n * Generous enough for any realistic expression; only pathological blow-ups trip\n * it. (Chosen so expressions well beyond normal use still parse; tune if needed.)\n */\nconst MAX_BINARY_OUTCOMES = 100_000_000;\n\n/** Internal bookkeeping attached to a {@link Dice} during parsing. */\nexport interface DicePrivateData {\n  /** Marks a DC (saving-throw) check so outcomes are attributed correctly. */\n  isDCCheck?: boolean;\n  /** The \"other\" distribution recorded by {@link Dice.combine}. */\n  except?: Dice | Record<string, never>;\n  /** Keep-highest/lowest selector applied when a die is multiplied out. */\n  keep?: (values: number[]) => number;\n  /** Set on a freshly parsed flat `dN`/`hdN` atom: its own face count and whether it rerolls a\n   * natural 1 once (Halfling Luck). Read by {@link parseExpression} in parser.ts to recover a\n   * base check die's natural-max identity after it has been convolved with bonus to-hit dice\n   * and modifiers, for a correct plain-`crit` probability. See parser.ts's \"Track a flat ...\n   * base check die\" comment. */\n  checkDie?: { sides: number; rerollOne: boolean };\n  /** Set on the result of a tracked AC gate (see parser.ts): the exact \"natural max, any bonus\n   * roll\" sub-distribution, already isolated from the rest of the to-hit total. A plain `crit`\n   * clause reads this directly instead of peeling the combined expression's single highest\n   * face, which is wrong whenever bonus dice are present. */\n  natMaxCritSlice?: Dice;\n}\n\n/**\n * @internal\n */\nexport class Dice {\n  private readonly faces: DamageDistribution = {};\n  public privateData: DicePrivateData = {};\n  // Partial: the object starts empty and gains keys as outcomes are recorded,\n  // so the type must not claim every OutcomeType is present. (Previously typed\n  // as a full Record via an `as` cast, which lied about missing keys.)\n  private outcomeData: Partial<Record<OutcomeType, DamageDistribution>> = {};\n  private hasHitDistributionCalculated = false;\n  public identifier?: string;\n\n  constructor(x: number = 0) {\n    if (x <= 0) return;\n    for (let i = 1; i <= x; i++) {\n      this.faces[i] = 1;\n    }\n  }\n\n  getOutcomeDistribution(key: OutcomeType): DamageDistribution | undefined {\n    if (key === \"hit\") {\n      this.ensureHitDistribution();\n    }\n\n    const distribution = this.outcomeData[key];\n    if (distribution === undefined) return undefined;\n\n    return { ...distribution };\n  }\n\n  getFullOutcomeDistribution(): Partial<\n    Record<OutcomeType, DamageDistribution>\n  > {\n    return { ...this.outcomeData };\n  }\n\n  setOutcomeDistribution(\n    key: OutcomeType,\n    data: DamageDistribution | undefined\n  ): void {\n    if (data) {\n      this.outcomeData[key] = data;\n    } else {\n      delete this.outcomeData[key];\n    }\n  }\n\n  hasOutcomeData(key: OutcomeType): boolean {\n    if (key === \"hit\") {\n      this.ensureHitDistribution();\n    }\n    const data = this.outcomeData[key];\n    return data !== undefined && Object.keys(data).length > 0;\n  }\n\n  getOutcomeCount(key: OutcomeType, face: number): number {\n    return this.outcomeData[key]?.[face] ?? 0;\n  }\n\n  getAverage(key: OutcomeType): number {\n    const distribution = this.getOutcomeDistribution(key);\n    if (!distribution) return 0;\n    // TODO caching opportunity\n\n    const totalCount = Object.values(distribution).reduce(\n      (sum, count) => sum + count,\n      0\n    );\n    const expectedDamage = Object.entries(distribution).reduce(\n      (sum, [damage, count]) => sum + Number(damage) * count,\n      0\n    );\n    if (totalCount === 0) return 0;\n    return expectedDamage / totalCount;\n  }\n\n  // TODO this can be private later if we change how testing works\n  calculateHitDistribution(): DamageDistribution {\n    const hitValues: DamageDistribution = {};\n\n    // Hoist the per-outcome distributions out of the face loop: they are\n    // constant across faces, so fetching (and previously cloning) them once is\n    // O(faces + outcomes) instead of O(faces × outcomes). The stored maps are\n    // only read here, never mutated, so reading them directly is safe and\n    // produces identical counts.\n    const subtractedOutcomes: (DamageDistribution | undefined)[] = [\n      this.outcomeData.crit,\n      this.outcomeData.missNone,\n      this.outcomeData.missDamage,\n      this.outcomeData.saveHalf,\n      this.outcomeData.saveFail,\n      this.outcomeData.pc,\n    ];\n\n    for (const [face, totalCount] of Object.entries(this.faces)) {\n      const numFace = Number(face);\n      let hitCount = totalCount;\n\n      for (const distribution of subtractedOutcomes) {\n        const outcomeCount = distribution?.[numFace];\n        if (outcomeCount) {\n          hitCount -= outcomeCount;\n        }\n      }\n\n      // Zero damage should not be counted as hits - they represent misses\n      if (numFace === 0) {\n        hitCount = 0;\n      }\n\n      // Defensive clamp: guards against negative hit counts from older\n      // inclusion-exclusion logic. Should never trigger in practice.\n      if (hitCount < 0) {\n        hitCount = 0;\n      }\n      hitValues[numFace] = hitCount;\n    }\n\n    return hitValues;\n  }\n\n  private ensureHitDistribution(): void {\n    if (!this.hasHitDistributionCalculated) {\n      const hitValues = this.calculateHitDistribution();\n      this.setOutcomeDistribution(\"hit\", hitValues);\n      this.hasHitDistributionCalculated = true;\n    }\n  }\n\n  // PRIVATE FUNCTIONS\n\n  private binaryOp(\n    other: Dice | number,\n    op: (a: number, b: number) => number,\n    diceConstructor?: () => Dice\n  ): Dice {\n    const result = diceConstructor ? diceConstructor() : new Dice();\n\n    const isScalar = typeof other === \"number\";\n    const keys1 = this.keys();\n    // Hoist the inner die's faces out of the outer loop: they are constant\n    // across key1, so computing them once avoids re-allocating the array on\n    // every outer iteration.\n    const keys2 = isScalar ? [] : (other as Dice).keys();\n\n    // Guard the O(faces₁ × faces₂) work before running it: a binary op between\n    // two large (but individually legal) dice would otherwise blow up.\n    if (!isScalar && keys1.length * keys2.length > MAX_BINARY_OUTCOMES) {\n      throw new DiceParseError(\n        `Dice operation over ${keys1.length}×${keys2.length} face pairs exceeds the maximum of ${MAX_BINARY_OUTCOMES}`\n      );\n    }\n\n    for (const key1 of keys1) {\n      const value1 = this.faces[key1]!;\n\n      if (isScalar) {\n        const resultKey = op(key1, other as number);\n        result.increment(resultKey, value1);\n      } else {\n        for (const key2 of keys2) {\n          const value2 = other.faces[key2]!;\n          const resultKey = op(key1, key2);\n          result.increment(resultKey, value1 * value2);\n        }\n      }\n    }\n\n    return result;\n  }\n\n  private removeFaces(facesToRemove: number[]): Dice {\n    const result = new Dice();\n\n    for (const [key, value] of Object.entries(this.faces)) {\n      const numKey = Number(key);\n      if (!facesToRemove.includes(numKey)) {\n        result.faces[numKey] = value;\n      }\n    }\n\n    result.privateData = { ...this.privateData };\n    result.outcomeData = { ...this.outcomeData };\n    return result;\n  }\n\n  // PUBLIC FUNCTIONS\n\n  getFaceEntries(): [number, number][] {\n    return Object.entries(this.faces).map(([k, v]) => [Number(k), v]);\n  }\n\n  getFaceMap(): DamageDistribution {\n    return { ...this.faces };\n  }\n\n  get(face: number): number {\n    return this.faces[face] ?? 0;\n  }\n\n  keys(): number[] {\n    return Object.keys(this.faces).map(Number);\n  }\n\n  values(): number[] {\n    return Object.values(this.faces);\n  }\n\n  total(): number {\n    return Object.values(this.faces).reduce((sum, value) => sum + value, 0);\n  }\n\n  public setFace(key: number, value: number): void {\n    this.faces[key] = value;\n  }\n\n  public static scalar(value: number): Dice {\n    const result = new Dice();\n    result.increment(value, 1);\n    return result;\n  }\n\n  public maxFace(): number {\n    const numericKeys = this.keys();\n\n    if (numericKeys.length === 0) {\n      throw new Error(\"No numeric faces found\");\n    }\n\n    return Math.max(...numericKeys);\n  }\n\n  public minFace(): number {\n    const numericKeys = this.keys();\n\n    if (numericKeys.length === 0) {\n      throw new Error(\"No numeric faces found\");\n    }\n\n    return Math.min(...numericKeys);\n  }\n\n  public increment(face: number, count: number): void {\n    const current = this.faces[face] || 0;\n    this.faces[face] = current + count;\n  }\n\n  public normalize(scalar: number): Dice {\n    const result = new Dice();\n\n    for (const [face, count] of Object.entries(this.faces)) {\n      result.faces[Number(face)] = count * scalar;\n    }\n\n    result.privateData = { ...this.privateData };\n    result.outcomeData = { ...this.outcomeData };\n    return result;\n  }\n\n  // OPERATIONS\n\n  public add(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => a + b);\n  }\n\n  public subtract(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => a - b);\n  }\n\n  public conditionalApply(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => (a === 0 ? 0 : 1) * b);\n  }\n\n  public multiply(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => a * b);\n  }\n\n  public addNonZero(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => (a !== 0 ? a + b : a));\n  }\n\n  public eq(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => (a === b ? 1 : 0));\n  }\n\n  public max(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => Math.max(a, b));\n  }\n\n  public min(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => Math.min(a, b));\n  }\n\n  public advantage(): Dice {\n    return this.max(this);\n  }\n\n  public ge(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => (a >= b ? 0 : 1));\n  }\n\n  public divide(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => a / b);\n  }\n\n  public divideRoundUp(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => Math.ceil(a / b));\n  }\n\n  public divideRoundDown(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => Math.floor(a / b));\n  }\n\n  public and(other: Dice | number): Dice {\n    return this.binaryOp(other, (a, b) => (a && b ? 1 : 0));\n  }\n\n  private checkTarget(\n    other: Dice | number,\n    comparisonLogic: (roll: number, target: number) => number\n  ): Dice {\n    const createResult = () => {\n      const result = new Dice();\n      result.increment(0, 0); // Success\n      result.increment(1, 0); // Failure\n      return result;\n    };\n\n    return this.binaryOp(other, comparisonLogic, createResult);\n  }\n\n  public dc(other: Dice | number): Dice {\n    const dcCheck = (a: number, b: number) => (a >= b ? 0 : 1);\n    const result = this.checkTarget(other, dcCheck);\n    // Mark this as a DC check (save mechanic) for proper attribute assignment\n    result.privateData.isDCCheck = true;\n    return result;\n  }\n\n  public ac(other: Dice | number): Dice {\n    const acCheck = (a: number, b: number) => (a >= b ? a : 0);\n    return this.checkTarget(other, acCheck);\n  }\n\n  public deleteFace(face: number): Dice {\n    const result = new Dice();\n\n    for (const [key, value] of Object.entries(this.faces)) {\n      const numKey = Number(key);\n      if (numKey !== face) {\n        result.increment(numKey, value);\n      }\n    }\n\n    result.privateData = { ...this.privateData };\n    result.outcomeData = { ...this.outcomeData };\n    return result;\n  }\n\n  public reroll(toReroll: Dice | number): Dice {\n    const rerollDice =\n      typeof toReroll === \"number\" ? Dice.scalar(toReroll) : toReroll;\n\n    const rerollKeys = rerollDice.keys();\n    const rerollSet = new Set(rerollKeys);\n    const removed = this.removeFaces(rerollKeys);\n    let result = new Dice();\n\n    for (const face of this.keys()) {\n      const wasRerolled = rerollSet.has(face);\n      result = result.combine(removed);\n      if (wasRerolled) {\n        result = result.combine(this);\n      }\n    }\n\n    return result;\n  }\n\n  // This is not addition and not rolling two dice at once.\n  // Instead, it’s mixing two distributions into a single weighted die.\n  public combine(other: Dice | number): Dice {\n    if (typeof other === \"number\") {\n      other = Dice.scalar(other);\n    }\n\n    // Start by copying \"other\" into a new Dice object\n    const result = new Dice();\n    for (const [key, value] of Object.entries(other.faces)) {\n      result.faces[Number(key)] = value;\n    }\n\n    // Build the \"except\" dice and add faces from `this` to result\n    const except = new Dice();\n    for (const [key, value] of Object.entries(this.faces)) {\n      const numKey = Number(key);\n      result.increment(numKey, value);\n\n      // If the key did not already exist in `other`, we remove it from `except`\n      if (!(numKey in other.faces)) {\n        except.increment(numKey, value); // still tracked in except\n      }\n    }\n\n    result.privateData = { ...this.privateData, except: other };\n    result.outcomeData = { ...this.outcomeData };\n    return result;\n  }\n\n  public combineInPlace(other: Dice): void {\n    for (const [key, value] of Object.entries(other.faces)) {\n      const numKey = Number(key);\n      const current = this.faces[numKey] || 0;\n      this.faces[numKey] = current + value;\n    }\n  }\n\n  public percent(): DamageDistribution {\n    const total = this.total();\n    const result: DamageDistribution = {};\n\n    for (const [face, count] of Object.entries(this.faces)) {\n      result[Number(face)] = count / total;\n    }\n\n    return result;\n  }\n\n  public average(): number {\n    const total = this.total();\n    if (total === 0) return 0;\n\n    let sum = 0;\n    for (const [key, value] of Object.entries(this.faces)) {\n      sum += Number(key) * value;\n    }\n\n    return sum / total;\n  }\n\n  /*\n   * Convert dice to PMF using OutcomeType labels directly from damage distribution.\n   * This is much cleaner than the original complex distribution conversion.\n   */\n  public toPMF(numEpsilon: number = EPS): PMF {\n    const total = this.total();\n    if (total === 0) return PMF.empty(numEpsilon);\n\n    // Ensure hit distribution is calculated before using it\n    this.ensureHitDistribution();\n\n    const map = new Map<number, Bin>();\n\n    // Outcome distributions (counts, not probabilities)\n    const hitDistro = this.getOutcomeDistribution(\"hit\") || {};\n    const critDistro = this.getOutcomeDistribution(\"crit\") || {};\n    const missDistro = this.getOutcomeDistribution(\"missDamage\") || {};\n    const saveDistro = this.getOutcomeDistribution(\"saveHalf\") || {};\n    const pcDistro = this.getOutcomeDistribution(\"pc\") || {};\n\n    // A non-empty save distribution means the \"save\" mechanic was used (e.g.\n    // \"save half\"): its success mass is a saveHalf outcome and the remaining\n    // (full-damage) mass is a saveFail. The previous heuristic — \"isSaveHalf iff\n    // 2×(a half value) appears in the hit distribution\" — false-negatived on odd\n    // or constant damage, mislabeling saveHalf as saveFail and saveFail as hit.\n    const isSaveHalf = Object.keys(saveDistro).length > 0;\n\n    const isDCCheck = this.privateData.isDCCheck === true;\n\n    const clampNonNeg = (x: number) => (x < 0 && x > -1e-15 ? 0 : x);\n\n    // Process each face value (iterate the internal map directly; this loop\n    // only reads it, so the defensive clone from getFaceMap() is unnecessary)\n    for (const [faceStr, faceCountRaw] of Object.entries(this.faces)) {\n      const face = Number(faceStr);\n      const faceCount = Number(faceCountRaw);\n\n      // Skip structurally present but empty bins early\n      if (faceCount <= 0) continue;\n\n      let p = faceCount / total;\n      p = clampNonNeg(p);\n\n      // Always drop exact zeros to keep PMF semantics clean\n      if (!(p > 0)) continue;\n\n      // Optional pruning only when epsilon is enabled\n      if (numEpsilon >= 0 && p < numEpsilon) continue;\n\n      const count: OutcomeLabelMap = {};\n      const attr: OutcomeLabelMap = {};\n\n      // Add distribution counts and attributions\n      if (hitDistro[face]) {\n        const c = clampNonNeg(hitDistro[face] / total);\n        if (c > 0) {\n          if (isSaveHalf || isDCCheck) {\n            count.saveFail = c; // full damage on failed save\n            attr.saveFail = clampNonNeg((face * hitDistro[face]) / total);\n          } else {\n            count.hit = c;\n            attr.hit = clampNonNeg((face * hitDistro[face]) / total);\n          }\n        }\n      }\n\n      if (critDistro[face]) {\n        const c = clampNonNeg(critDistro[face] / total);\n        if (c > 0) {\n          count.crit = c;\n          attr.crit = clampNonNeg((face * critDistro[face]) / total);\n        }\n      }\n\n      if (missDistro[face]) {\n        const c = clampNonNeg(missDistro[face] / total);\n        if (c > 0) {\n          count.missDamage = c;\n          attr.missDamage = clampNonNeg((face * missDistro[face]) / total);\n        }\n      }\n\n      if (saveDistro[face]) {\n        const c = clampNonNeg(saveDistro[face] / total);\n        if (c > 0) {\n          if (isSaveHalf) {\n            count.saveHalf = c; // half damage on successful save\n            attr.saveHalf = clampNonNeg((face * saveDistro[face]) / total);\n          } else {\n            count.saveFail = (count.saveFail ?? 0) + c; // regular fail\n            attr.saveFail = clampNonNeg(\n              (attr.saveFail ?? 0) + (face * saveDistro[face]) / total\n            );\n          }\n        }\n      }\n\n      if (pcDistro[face]) {\n        const c = clampNonNeg(pcDistro[face] / total);\n        if (c > 0) {\n          count.pc = c;\n          attr.pc = clampNonNeg((face * pcDistro[face]) / total);\n        }\n      }\n\n      // Handle faces with no specific distribution (missNone) for non-save and non-DC checks\n      if (!isSaveHalf && !isDCCheck) {\n        const distroCountRaw =\n          (hitDistro[face] || 0) +\n          (critDistro[face] || 0) +\n          (missDistro[face] || 0) +\n          (saveDistro[face] || 0) +\n          (pcDistro[face] || 0);\n\n        const unaccountedCount = clampNonNeg(faceCount - distroCountRaw);\n        if (unaccountedCount > 0) {\n          const frac = clampNonNeg(unaccountedCount / total);\n          if (frac > 0) {\n            count.missNone = (count.missNone ?? 0) + frac;\n            // missNone does 0 damage, so no attr contribution\n          }\n        }\n      }\n\n      const bin: Bin = { p, count };\n      if (Object.keys(attr).length > 0) {\n        bin.attr = attr;\n      }\n\n      map.set(face, bin);\n    }\n\n    // Fall back to a sentinel identifier if none was assigned. This indicates\n    // a Dice constructed outside the normal parse/build flow.\n    const identifier = this.identifier || \"ERROR\";\n\n    // Normalize, drop zeros again if any snuck in, then compaction and pruning\n    return new PMF(map, numEpsilon, true, identifier).compact(numEpsilon, true);\n  }\n}\n\nexport type _DiceInternal = never;\n","import { DiceParseError } from \"../common/errors\";\nimport { LRUCache } from \"../common/lru-cache\";\nimport type { OutcomeType } from \"../common/types\";\nimport type { PMF } from \"../pmf/pmf\";\nimport { Dice } from \"./dice\";\n\ntype DiceOperation = ((this: Dice, other: Dice | number) => Dice) & {\n  unary?: boolean;\n};\n\n/**\n * Resource-exhaustion guards. Adversarial expressions (a huge die, a huge dice\n * count, or a keep over a large enumerated pool) can otherwise blow up memory\n * and CPU. These caps are deliberately generous so every legitimate expression\n * the suite exercises (e.g. d100000) still parses.\n */\n// Must stay >= 100000: the suite asserts d100000 (100k faces) parses.\nconst MAX_DIE_SIDES = 1_000_000;\nconst MAX_DICE_COUNT = 10_000;\n// multiplyDiceByDice enumerates faces^count outcomes when a keep is applied.\nconst MAX_KEEP_OUTCOMES = 1_000_000;\n\n/**\n * Internal parse cache for PMFs produced from string expressions.\n * Keyed by cleaned expression (spaces stripped, lowercased) and optional `n` value.\n */\nconst parseCache = new LRUCache<string, PMF>(1000);\n\nlet cachingEnabled = true;\n\n/** Enable or disable the internal parse cache. */\nexport function setCachingEnabled(enabled: boolean): void {\n  cachingEnabled = enabled;\n  if (!enabled) clearParserCache();\n}\n\n/** Returns whether the internal parse cache is currently enabled. */\nexport function getCachingEnabled(): boolean {\n  return cachingEnabled;\n}\n\n/** Clears the internal parse cache. */\nexport function clearParserCache(): void {\n  parseCache.clear();\n}\n\n/**\n * Parse a dice expression into a PMF.\n *\n * - Expression is case-insensitive and ignores spaces.\n */\nexport function parse(expression: string, n: number = 0): PMF {\n  // Check cache first if enabled\n  const cleaned = expression.replace(/ /g, \"\").toLowerCase();\n\n  if (cachingEnabled) {\n    const cacheKey = `${cleaned}:${n}`;\n    const cached = parseCache.get(cacheKey);\n    if (cached) return cached;\n  }\n\n  const chars = [...cleaned];\n\n  let result: Dice;\n  try {\n    result = parseExpression(chars, n);\n  } catch (error) {\n    throw new DiceParseError(\n      `Cannot parse dice expression [${expression}]: ${error}`,\n      { expression, cause: error }\n    );\n  }\n\n  result.privateData = result.privateData || {};\n  result.identifier = cleaned;\n\n  if (chars.length > 0) {\n    throw new DiceParseError(\n      `Unexpected token: '${chars[0]}' from expression: '${expression}'`,\n      { expression }\n    );\n  }\n\n  // When creating the PMF, do not epsilon prune\n  const resultPMF = result.toPMF(-1);\n  if (cachingEnabled) {\n    // store using the same cleaned key we used for lookup\n    const cacheKey = `${cleaned}:${n}`;\n    parseCache.set(cacheKey, resultPMF);\n  }\n\n  return resultPMF;\n}\n\nfunction combineDiceWithNormalization(\n  dice: Dice,\n  normValue: number,\n  outcomeType: OutcomeType,\n  currentNorm: number,\n  finalResult: Dice\n): { newNorm: number; updatedResult: Dice } {\n  dice = dice.normalize(currentNorm);\n  finalResult = finalResult.normalize(normValue);\n  finalResult.setOutcomeDistribution(outcomeType, dice.getFaceMap());\n  finalResult = finalResult.combine(dice);\n  return { newNorm: currentNorm * normValue, updatedResult: finalResult };\n}\n\n/**\n * Face-wise histogram difference. NOT the same as {@link Dice.subtract}, which convolves VALUES\n * (`a - b` as numbers); this subtracts raw face COUNTS, used to isolate \"everything except this\n * natural-die-value's contribution\" out of an already-convolved to-hit total.\n */\nfunction subtractCounts(a: Dice, b: Dice): Dice {\n  const result = new Dice();\n  for (const [key, value] of a.getFaceEntries()) result.increment(key, value);\n  for (const [key, value] of b.getFaceEntries()) result.increment(key, -value);\n  return result;\n}\n\nfunction parseExpression(arr: string[], n: number): Dice {\n  const result = (() => {\n    const res = parseArgument(arr, n);\n    return typeof res === \"number\" ? Dice.scalar(res) : res;\n  })();\n\n  let op = parseOperation(arr);\n  let finalResult = result;\n\n  // Track a flat (no advantage/disadvantage/reroll) base check die's natural-max face\n  // separately from whatever bonus-to-hit dice and modifiers get added to it, so a later plain\n  // `crit` clause -- possibly in an OUTER parseExpression call, once this AC-checked\n  // sub-expression has already collapsed to one Dice -- can recover the exact \"natural max, any\n  // bonus roll\" slice instead of peeling the combined expression's single highest TOTAL, which\n  // undercounts crit mass whenever bonus dice are present (e.g. Bless: \"d20 + 5 + 1d4\" reported\n  // a crit probability of 1/(20*4) instead of 1/20).\n  //\n  // Scoped narrowly and deliberately: only a bare flat `dN` base die with no reroll, combined\n  // solely via `+`/`-`, terminated by a numeric `AC`/`DC` target. Anything else --\n  // advantage/disadvantage/elven accuracy on the base die, halfling reroll, a dynamic\n  // (dice-valued) AC target, or `xcrit` (an expanded crit RANGE, which needs its own AC check\n  // per natural face) -- invalidates tracking and falls back to the legacy peel-based behavior,\n  // which remains correct with no bonus dice and is the same known-imperfect approximation\n  // otherwise. See CHANGELOG.\n  let baseDieMeta =\n    result.privateData?.checkDie && !result.privateData.checkDie.rerollOne\n      ? result.privateData.checkDie\n      : undefined;\n  let bonusOnly = Dice.scalar(0);\n\n  while (op != null) {\n    const arg = !op.unary ? parseArgument(arr, n) : finalResult;\n\n    let acAlreadyApplied = false;\n    if (baseDieMeta) {\n      if (op === Dice.prototype.addNonZero) {\n        bonusOnly = bonusOnly.add(arg);\n      } else if (op === Dice.prototype.subtract) {\n        bonusOnly = bonusOnly.subtract(arg);\n      } else if (op === Dice.prototype.ac && typeof arg === \"number\") {\n        // Isolate the natural-max face's contribution BEFORE gating, so the crit clause can use\n        // it directly (see below) -- but AC-gate it exactly like every other natural value (no\n        // RAW \"natural 20 always hits\" exception here: that would change this checked total's\n        // hit/miss math, not just crit attribution, and several tests pin the parser's existing\n        // \"AC is a pure numeric threshold, no natural-face exceptions\" behavior, e.g. an\n        // unreachably high AC yields zero mass even on a natural max). Splitting into two pieces\n        // and re-gating each is mathematically identical to gating the whole, since `.ac()` acts\n        // per-face independently.\n        const natMaxSlice = bonusOnly.add(baseDieMeta.sides);\n        const restSlice = subtractCounts(finalResult, natMaxSlice);\n        const gatedNatMaxSlice = natMaxSlice.ac(arg);\n        finalResult = restSlice.ac(arg).combine(gatedNatMaxSlice);\n        finalResult.privateData.checkDie = baseDieMeta;\n        finalResult.privateData.natMaxCritSlice = gatedNatMaxSlice;\n        acAlreadyApplied = true;\n        baseDieMeta = undefined;\n      } else {\n        baseDieMeta = undefined;\n      }\n    }\n\n    // Handle crit (e.g. xcrit, crit)\n    let crit: Dice | undefined;\n    let critNorm = 1;\n    if (arr[0] === \"x\" || arr[0] === \"c\") {\n      const isXcrit = arr[0] === \"x\";\n      if (isXcrit) assertToken(arr, \"x\");\n      assertToken(arr, \"c\");\n      assertToken(arr, \"r\");\n      assertToken(arr, \"i\");\n      assertToken(arr, \"t\");\n\n      const count = isXcrit ? parseNumber(arr, n) : 1;\n      const trackedCritSlice = finalResult.privateData?.natMaxCritSlice;\n\n      if (count === 1 && trackedCritSlice) {\n        // Exact path: trackedCritSlice already isolates \"natural max, any bonus roll\" (see the\n        // AC-tracking block above), independent of how many bonus-to-hit dice sides would\n        // otherwise smear that mass across several total values.\n        crit = trackedCritSlice;\n        finalResult = subtractCounts(finalResult, trackedCritSlice);\n      } else {\n        // KNOWN LIMITATION (xcrit, or no tracked base die -- advantage/disadvantage/elven\n        // accuracy, halfling reroll, or bonus dice mixed into a non-flat check): peels the\n        // maximum FACE of the already-convolved to-hit distribution. Correct only when the\n        // to-hit has no bonus dice, since bonus dice otherwise smear a natural-max roll's mass\n        // across several total values that also contain non-crit mass. Use the builder API\n        // (d20.plus(...).plus(bonusDie).ac(...).onCrit(...)) for a correct crit probability with\n        // bonus to-hit dice in these cases. See CHANGELOG.\n        crit = new Dice();\n        for (let i = 0; i < count; i++) {\n          const max = finalResult.maxFace();\n          crit.setFace(max, finalResult.get(max));\n          finalResult = finalResult.deleteFace(max);\n        }\n      }\n\n      critNorm = crit.total();\n      crit = op.call(crit, parseBinaryArgument(arg, arr, n));\n\n      critNorm = crit && critNorm ? crit.total() / critNorm : 1;\n    }\n\n    // Handle save\n    let save: Dice | undefined;\n    let saveNorm = 1;\n    if (arr[0] === \"s\") {\n      assertToken(arr, \"s\");\n      assertToken(arr, \"a\");\n      assertToken(arr, \"v\");\n      assertToken(arr, \"e\");\n\n      save = new Dice();\n      const min = finalResult.minFace();\n      save.increment(min > 0 ? min : 1, finalResult.get(min));\n\n      saveNorm = save.total();\n      finalResult = finalResult.deleteFace(min);\n      save = op.call(save, parseBinaryArgument(arg, arr, n));\n      saveNorm = save && saveNorm ? save.total() / saveNorm : 1;\n    }\n\n    // Handle half damage on hit (potent cantrip)\n    let pc: Dice | undefined;\n    let pcNorm = 1;\n\n    if (arr.length >= 2 && arr[0] === \"p\" && arr[1] === \"c\") {\n      assertToken(arr, \"p\");\n      assertToken(arr, \"c\");\n\n      pc = new Dice();\n      const min = finalResult.minFace();\n      pc.increment(min > 0 ? min : 1, finalResult.get(min));\n\n      const missBefore = pc.total();\n      finalResult = finalResult.deleteFace(min);\n\n      pc = op.call(pc, parseBinaryArgument(arg, arr, n)).divideRoundDown(2); // parse the damage\n\n      const missAfter = pc ? pc.total() : 0;\n      pcNorm = missBefore ? missAfter / missBefore : 1;\n    }\n\n    // Handle miss\n    let miss: Dice | undefined;\n    let missNorm = 1;\n\n    if (arr[0] === \"m\") {\n      assertToken(arr, \"m\");\n      assertToken(arr, \"i\");\n      assertToken(arr, \"s\");\n      assertToken(arr, \"s\");\n\n      miss = new Dice();\n      const min = finalResult.minFace();\n      miss.increment(min > 0 ? min : 1, finalResult.get(min));\n\n      missNorm = miss.total();\n      finalResult = finalResult.deleteFace(min);\n\n      miss = op.call(miss, parseBinaryArgument(arg, arr, n));\n      missNorm = miss && missNorm ? miss.total() / missNorm : 1;\n    }\n\n    let norm = finalResult.total();\n\n    if (!acAlreadyApplied) {\n      finalResult = op.call(finalResult, arg);\n    }\n    norm = norm ? finalResult.total() / norm : 1;\n\n    // Combine dice with normalization\n    if (crit) {\n      const result = combineDiceWithNormalization(\n        crit,\n        critNorm,\n        \"crit\",\n        norm,\n        finalResult\n      );\n      norm = result.newNorm;\n      finalResult = result.updatedResult;\n    }\n\n    if (save) {\n      const result = combineDiceWithNormalization(\n        save,\n        saveNorm,\n        \"saveHalf\",\n        norm,\n        finalResult\n      );\n      norm = result.newNorm;\n      finalResult = result.updatedResult;\n    }\n\n    if (miss) {\n      const result = combineDiceWithNormalization(\n        miss,\n        missNorm,\n        \"missDamage\",\n        norm,\n        finalResult\n      );\n      norm = result.newNorm;\n      finalResult = result.updatedResult;\n    }\n\n    if (pc) {\n      const result = combineDiceWithNormalization(\n        pc,\n        pcNorm,\n        \"pc\",\n        norm,\n        finalResult\n      );\n      norm = result.newNorm;\n      finalResult = result.updatedResult;\n    }\n\n    op = parseOperation(arr);\n  }\n\n  return finalResult;\n}\n\nfunction parseArgument(s: string[], n: number): Dice | number {\n  let result = parseArgumentInternal(s, n);\n\n  while (true) {\n    const next = parseArgumentInternal(s, n);\n    if (next === undefined) break;\n\n    result = multiplyDiceByDice(result as Dice | number, next);\n  }\n\n  return result as Dice | number;\n}\n\nfunction multiplyDiceByDice(d1: Dice | number, d2: Dice | number): Dice {\n  if (typeof d1 === \"number\") d1 = Dice.scalar(d1);\n  if (typeof d2 === \"number\") d2 = Dice.scalar(d2);\n\n  const result = new Dice();\n  // Keyed by face value. A Map avoids the number→string→parseFloat round-trip of\n  // an object and preserves insertion order, which matches d1.keys() ascending\n  // order — so the combine order below is identical to the previous version.\n  const faces = new Map<number, Dice>();\n  let normalizationFactor = 1;\n\n  for (const key of d1.keys()) {\n    let face: Dice;\n\n    if (typeof key !== \"number\") {\n      continue; // Skip invalid scalar\n    }\n\n    if (d2.privateData.keep) {\n      // Repeat dice2 \"key\" times and apply keep. opDice enumerates the full\n      // faces^count outcome space, so guard against a combinatorial blow-up.\n      const faceCount = d2.keys().length;\n      if (Math.pow(faceCount, key) > MAX_KEEP_OUTCOMES) {\n        throw new DiceParseError(\n          `Keep enumeration of ${faceCount}^${key} outcomes exceeds the maximum of ${MAX_KEEP_OUTCOMES}`\n        );\n      }\n      const repeat: Dice[] = Array(key).fill(d2);\n      face = opDice(repeat, d2.privateData.keep);\n    } else {\n      face = multiplyDice(key, d2);\n    }\n\n    normalizationFactor *= face.total();\n    faces.set(key, face);\n  }\n\n  for (const [k, face] of faces) {\n    const count = d1.get(k);\n    result.combineInPlace(\n      face.normalize((count * normalizationFactor) / face.total())\n    );\n  }\n\n  result.privateData.except = {};\n  return result;\n}\n\nfunction multiplyDice(n: number, d: Dice): Dice {\n  if (n > MAX_DICE_COUNT) {\n    throw new DiceParseError(\n      `Dice count ${n} exceeds the maximum of ${MAX_DICE_COUNT}`\n    );\n  }\n  if (n === 0) return new Dice(0);\n  if (n === 1) return d;\n\n  const half = Math.floor(n / 2);\n  let result = multiplyDice(half, d);\n  result = result.add(result);\n\n  if (n % 2 === 1) {\n    result = result.add(d);\n  }\n\n  return result;\n}\n\nfunction opDice(diceList: Dice[], keepFn: (values: number[]) => number): Dice {\n  return opDiceInternal(diceList, new Dice(), 0, [], 1, keepFn);\n}\n\nfunction opDiceInternal(\n  diceList: Dice[],\n  result: Dice,\n  index: number,\n  values: number[],\n  weight: number,\n  combineFn: (values: number[]) => number\n): Dice {\n  if (index === diceList.length) {\n    return result.combine(Dice.scalar(combineFn(values)).normalize(weight));\n  }\n\n  const currentDice = diceList[index];\n  for (const face of currentDice.keys()) {\n    values.push(face as number);\n    result = opDiceInternal(\n      diceList,\n      result,\n      index + 1,\n      values,\n      weight * currentDice.get(face),\n      combineFn\n    );\n    values.pop();\n  }\n\n  return result;\n}\n\nfunction parseArgumentInternal(\n  s: string[],\n  n: number\n): Dice | number | undefined {\n  if (s.length === 0) return;\n\n  const c = s[0];\n\n  switch (c) {\n    case \"(\":\n      s.shift();\n      return assertToken(s, \")\", parseExpression(s, n));\n\n    case \"h\":\n    case \"d\":\n      return parseDice(s, n);\n\n    case \"k\":\n      assertToken(s, \"k\");\n      return parseKeep(s, n);\n\n    case \"n\":\n      return parseNumber(s, n);\n\n    default:\n      if (isDigit(c)) return parseNumber(s, n);\n      return;\n  }\n}\n\nfunction parseBinaryArgument(\n  arg: Dice | number,\n  arr: string[],\n  n: number\n): Dice {\n  if (arr.length >= 4 && arr[0] === \"h\" && peek(arr, \"half\")) {\n    assertToken(arr, \"half\");\n\n    const diceArg = typeof arg === \"number\" ? Dice.scalar(arg) : arg;\n    return diceArg.divideRoundDown(2);\n  }\n\n  const parsed = parseArgument(arr, n);\n  return typeof parsed === \"number\" ? Dice.scalar(parsed) : parsed;\n}\n\nfunction assertToken<T>(s: string[], expected: string, ret?: T): T | undefined {\n  for (const ch of expected) {\n    const found = s.shift();\n    if (found !== ch) {\n      throw new Error(`Expected character '${ch}', found '${found}'`);\n    }\n  }\n  return ret;\n}\n\nfunction parseDice(s: string[], n: number): Dice | undefined {\n  let rerollOne = false;\n\n  if (peek(s, \"hd\") && peekIsNumber(s, 2)) {\n    assertToken(s, \"h\");\n    assertToken(s, \"d\");\n    rerollOne = true;\n  } else if (peek(s, \"d\") && peekIsNumber(s, 1)) {\n    assertToken(s, \"d\");\n  } else {\n    return;\n  }\n\n  const sides = parseNumber(s, n);\n  if (sides > MAX_DIE_SIDES) {\n    throw new DiceParseError(\n      `Die size ${sides} exceeds the maximum of ${MAX_DIE_SIDES}`\n    );\n  }\n  let result = new Dice(sides);\n\n  if (rerollOne) {\n    // Reroll a rolled 1 exactly once, keeping the second roll (e.g. halfling\n    // luck). This is the same semantics as the `reroll 1` operator; the previous\n    // deleteFace(1).combine(result) computed a weighted union (P(1)=1/(2s−1)),\n    // not a reroll (correct P(1)=1/s²).\n    result = result.reroll(1);\n  }\n\n  result.privateData.checkDie = { sides, rerollOne };\n  return result;\n}\n\nfunction peek(arr: string[], expected: string): boolean {\n  if (expected.length > arr.length) return false;\n\n  for (let i = 0; i < expected.length; i++) {\n    if (arr[i] !== expected.charAt(i)) return false;\n  }\n\n  return true;\n}\n\nfunction peekIsNumber(arr: string[], index: number): boolean {\n  if (index >= arr.length) return false;\n  return isDigit(arr[index]) || arr[index] === \"n\";\n}\n\nfunction parseNumber(s: string[], n: number): number {\n  let ret = \"\";\n\n  while (s.length > 0 && (isDigit(s[0]) || s[0] === \"n\")) {\n    const ch = s.shift()!;\n    ret += ch === \"n\" ? n.toString() : ch;\n  }\n\n  if (ret.length === 0) {\n    throw new Error(`Expected number, found: '${s[0]}'`);\n  }\n\n  return parseInt(ret, 10);\n}\n\nfunction isDigit(c: string): boolean {\n  return c >= \"0\" && c <= \"9\";\n}\n\nfunction parseKeep(s: string[], n: number): Dice | undefined {\n  let keepLowest = false;\n\n  if (peek(s, \"l\")) {\n    assertToken(s, \"l\");\n    keepLowest = true;\n  } else if (peek(s, \"h\")) {\n    assertToken(s, \"h\");\n    keepLowest = false;\n  } else {\n    return;\n  }\n\n  const keepCount = parseNumber(s, n);\n  const result = parseArgumentInternal(s, n);\n\n  if (result instanceof Dice) {\n    result.privateData.keep = keepN(keepCount, keepLowest);\n    return result;\n  }\n\n  throw new Error(\"Expected Dice after keep modifier\");\n}\n\nfunction keepN(n: number, low: boolean): (values: number[]) => number {\n  return (values: number[]): number => {\n    const sorted = [...values].sort((a, b) => (low ? a - b : b - a));\n    return sorted.slice(0, n).reduce((sum, val) => sum + val, 0);\n  };\n}\n\nfunction parseOperation(s: string[]): DiceOperation | undefined {\n  switch (s[0]) {\n    case \")\":\n      return;\n\n    case \"a\":\n      assertToken(s, \"ac\");\n      return Dice.prototype.ac;\n\n    case \"d\":\n      assertToken(s, \"dc\");\n      return Dice.prototype.dc;\n\n    case \"!\":\n      assertToken(s, \"!\");\n      const adv = Dice.prototype.advantage as DiceOperation;\n      adv.unary = true;\n      return adv;\n\n    case \">\":\n      assertToken(s, \">\");\n      return Dice.prototype.max;\n\n    case \"<\":\n      assertToken(s, \"<\");\n      return Dice.prototype.min;\n\n    case \"+\":\n      assertToken(s, \"+\");\n      return Dice.prototype.addNonZero;\n\n    case \"~\":\n      assertToken(s, \"~\");\n      assertToken(s, \"+\");\n      return Dice.prototype.add;\n\n    case \"-\":\n      assertToken(s, \"-\");\n      return Dice.prototype.subtract;\n\n    case \"&\":\n      assertToken(s, \"&\");\n      return Dice.prototype.combine;\n\n    case \"r\":\n      assertToken(s, \"reroll\");\n      return Dice.prototype.reroll;\n\n    case \"*\":\n      assertToken(s, \"*\");\n\n      if (peek(s, \"*\")) {\n        assertToken(s, \"*\");\n        return Dice.prototype.multiply;\n      }\n\n      return Dice.prototype.conditionalApply;\n\n    case \"/\":\n      assertToken(s, \"/\");\n      if (s[0] === \"/\") {\n        assertToken(s, \"/\");\n        return Dice.prototype.divideRoundDown;\n      }\n      return Dice.prototype.divideRoundUp;\n\n    case \"=\":\n      assertToken(s, \"=\");\n      return Dice.prototype.eq;\n  }\n\n  return;\n}\n","import type { RollType } from \"../common/types\";\nimport { PMF } from \"../pmf/pmf\";\nimport { parse } from \"./parser\";\n\n/** A bare decimal integer, optionally signed, with surrounding whitespace. */\nconst DECIMAL_INTEGER = /^\\s*[+-]?\\d+\\s*$/;\n\n/**\n * Parse without throwing — for UI code that reparses on every keystroke, where\n * a transiently invalid expression is normal rather than exceptional.\n *\n * Also accepts a *signed* integer, which the grammar rejects: `\"-3\"` becomes a\n * delta at -3, `\"+7\"` one at 7. Unsigned integers need no help — `parse(\"7\")`\n * already returns a delta at 7 — but a half-typed damage field is a bare signed\n * number often enough to be worth covering.\n *\n * The failure value is {@link PMF.empty}, which has **mass 0**, not a\n * distribution. Convolving it collapses the whole result to mass 0, so a caller\n * combining several expressions should check `mass()` (or skip empties) rather\n * than assume a usable PMF. Anywhere a bad expression should be surfaced instead\n * of absorbed, call {@link parse} and handle `DiceParseError`.\n *\n * Takes no second argument on purpose. {@link parse}'s is `n`, the substitution\n * value for an `n`-dice expression — not an epsilon — so forwarding one here\n * would silently reinterpret it: `tryParse(\"nd6\", 1e-9)` rolled `1d6` and\n * reported 3.5 where the default `n` of 0 means no dice at all.\n *\n * @returns the parsed PMF, or an empty (mass 0) PMF for input that is neither a\n * valid expression nor an integer.\n */\nexport function tryParse(expression: string): PMF {\n  // Checked before `parse`, not only in the fallback: `parse` accepts unsigned\n  // integers itself and converts them with the same precision loss, so\n  // `parse(\"9007199254740993\")` would hand back a delta at …992.\n  if (DECIMAL_INTEGER.test(expression)) {\n    const value = Number(expression);\n    return Number.isSafeInteger(value) ? PMF.delta(value) : PMF.empty();\n  }\n\n  try {\n    return parse(expression);\n  } catch {\n    return PMF.empty();\n  }\n}\n\n/** The token naming a check: `AC` for an attack roll, `DC` for a saving throw. */\nconst CHECK_TOKEN = /\\b(AC|DC)\\b/i;\n\n/** The d20 run at the head of a check: `d20`, `hd20 > d20`, `d20 < d20`, … */\nconst D20_RUN = /\\bh?d20(?:\\s*[><]\\s*h?d20)*/i;\n\nconst RUN_FOR_ROLL_TYPE: Record<RollType, string> = {\n  flat: \"d20\",\n  advantage: \"d20 > d20\",\n  disadvantage: \"d20 < d20\",\n  \"elven accuracy\": \"d20 > d20 > d20\",\n};\n\n/**\n * Rewrite an expression's attack roll to a different d20 {@link RollType},\n * leaving everything else — damage, crit clause, miss clause, bonuses —\n * untouched.\n *\n * ```ts\n * withRollType(\"(d20 + 8 AC 16) * (1d4 + 4)\", \"advantage\");\n * // \"(d20 > d20 + 8 AC 16) * (1d4 + 4)\"\n * ```\n *\n * **Every** `AC` group is rewritten, because one expression can hold several\n * attacks (`(d20 + 8 AC 16) * (1d8) + (d20 + 5 AC 16) * (1d6)`) and leaving the\n * later ones flat would quietly chart the wrong curve.\n *\n * A `DC` group is the *target's* saving throw, which the attacker's advantage\n * does not touch, so save expressions come back unchanged — as does anything\n * with no attack roll at all. This makes the function safe to map over a mixed\n * list of expressions.\n *\n * Assumes **one check per group**, which is what every well-formed attack or\n * save expression looks like and what `modelToExpression` emits. The grammar\n * will swallow a group naming two — `(d20 + 5 DC 16 + d20 + 8 AC 16)` parses,\n * as a single `AC` check whose roll happens to contain the save's 0/1 result —\n * but that is not an expression anyone means, and the roll type it should get is\n * undefined. Such input is rewritten on a best-effort basis rather than\n * diagnosed.\n *\n * A halfling-luck `h` prefix is preserved on the first die of each run, since it\n * describes the same roll.\n */\nexport function withRollType(expression: string, rollType: RollType): string {\n  const scopes = enclosingScopes(expression);\n  let rewritten = \"\";\n  let copiedUpTo = 0;\n\n  for (const run of expression.matchAll(new RegExp(D20_RUN, \"gi\"))) {\n    const at = run.index as number;\n    if (!isAttackRoll(expression, scopes, at)) continue;\n\n    const replacement = run[0].toLowerCase().startsWith(\"h\")\n      ? `h${RUN_FOR_ROLL_TYPE[rollType]}`\n      : RUN_FOR_ROLL_TYPE[rollType];\n\n    rewritten += expression.slice(copiedUpTo, at) + replacement;\n    copiedUpTo = at + run[0].length;\n  }\n\n  return rewritten + expression.slice(copiedUpTo);\n}\n\n/**\n * Balanced parenthesised ranges, innermost first, so a run's enclosing scopes\n * can be walked outwards. Unbalanced input simply yields fewer scopes; the\n * parser is what rejects it.\n */\nfunction enclosingScopes(\n  expression: string\n): readonly { start: number; end: number }[] {\n  const open: number[] = [];\n  const scopes: { start: number; end: number }[] = [];\n\n  for (let i = 0; i < expression.length; i++) {\n    if (expression[i] === \"(\") open.push(i);\n    else if (expression[i] === \")\") {\n      const start = open.pop();\n      if (start !== undefined) scopes.push({ start, end: i + 1 });\n    }\n  }\n\n  // Closing order is innermost-first already; sorting by width keeps that true\n  // for sibling groups too.\n  return scopes.sort((a, b) => a.end - a.start - (b.end - b.start));\n}\n\n/**\n * Whether the d20 run at `at` is the attack roll of a check.\n *\n * Classified by the nearest enclosing group that names a check, widening\n * outwards, which is what makes nesting work: in `((d20 + 8) AC 16)` the run's\n * own group names nothing and the group outside it says `AC`.\n *\n * A run whose groups name no check is not an attack roll — the second run in\n * `(d20 + 8 AC 16) * (d20)` is damage — and an unparenthesised run is judged by\n * the whole expression, since there is nothing narrower to go on.\n */\nfunction isAttackRoll(\n  expression: string,\n  scopes: readonly { start: number; end: number }[],\n  at: number\n): boolean {\n  let scoped = false;\n\n  for (const scope of scopes) {\n    if (at < scope.start || at >= scope.end) continue;\n    scoped = true;\n    const check = CHECK_TOKEN.exec(expression.slice(scope.start, scope.end));\n    if (check) return check[1].toUpperCase() === \"AC\";\n  }\n\n  if (scoped) return false;\n\n  const check = CHECK_TOKEN.exec(expression);\n  return check !== null && check[1].toUpperCase() === \"AC\";\n}\n","import type { Bin } from \"../common/types\";\nimport { EPS } from \"../common/types\";\nimport { PMF } from \"./pmf\";\n\n/** A labeled mixture builder that preserves provenance in Bin.count. */\nexport class Mixture<L extends string = string> {\n  private readonly totals = new Map<number, number>(); // raw mass per outcome (pre-normalization)\n  private readonly labelMass = new Map<number, Record<L, number>>(); // raw mass per outcome per label\n  private readonly eps: number;\n\n  constructor(eps: number = EPS) {\n    this.eps = Number.isFinite(eps) ? eps : EPS;\n  }\n\n  /** Remove all accumulated state. */\n  clear(): this {\n    this.totals.clear();\n    this.labelMass.clear();\n    return this;\n  }\n\n  /** Number of distinct outcome values currently accumulated. */\n  size(): number {\n    return this.totals.size;\n  }\n\n  /** Whether a label was ever added. */\n  hasLabel(label: L): boolean {\n    for (const bag of this.labelMass.values()) if (bag[label]) return true;\n    return false;\n  }\n\n  /**\n   * Add a labeled component with a mixture weight.\n   * Weight can be any positive finite number. Very small contributions are pruned by eps.\n   */\n  add(label: L, pmf: PMF, weight = 1): this {\n    if (!Number.isFinite(weight) || weight <= 0) return this;\n\n    // Stream probabilities from each [value, Bin] pair.\n    for (const [v, bin] of pmf) {\n      const p = bin.p;\n      if (p <= 0) continue;\n\n      const add = weight * p;\n      if (!Number.isFinite(add) || Math.abs(add) < this.eps) continue;\n\n      this.totals.set(v, (this.totals.get(v) ?? 0) + add);\n      const bag = this.labelMass.get(v) ?? ({} as Record<L, number>);\n      bag[label] = (bag[label] ?? 0) + add;\n      this.labelMass.set(v, bag);\n    }\n\n    return this;\n  }\n\n  buildPMF(eps: number = EPS): PMF {\n    // Kahan sum for robustness.\n    let grand = 0;\n    let c = 0;\n    for (const m of this.totals.values()) {\n      const y = m - c;\n      const t = grand + y;\n      c = t - grand - y;\n      grand = t;\n    }\n    if (!(grand > 0)) throw new Error(\"Mixture: zero total mass\");\n\n    const internal = new Map<number, Bin>();\n    for (const [v, m] of this.totals) {\n      if (m <= 0 || Math.abs(m) < this.eps) continue;\n      const count = this.labelMass.get(v) ?? {};\n      internal.set(v, { p: m / grand, count });\n    }\n    return new PMF(internal, eps);\n  }\n\n  /**\n   * Produce normalized *per-label* PMFs (labels independent).\n   * These are unlabeled PMFs built from the raw mass of that label alone.\n   */\n  byOutcome(): Record<L, PMF> {\n    // Collect the set of labels present.\n    const labels = new Set<L>();\n    for (const bag of this.labelMass.values()) {\n      for (const k of Object.keys(bag) as L[]) labels.add(k);\n    }\n\n    const out = {} as Record<L, PMF>;\n    for (const label of labels) {\n      const m = new Map<number, number>();\n      for (const [v, bag] of this.labelMass) {\n        const w = bag[label];\n        if (w && Math.abs(w) >= this.eps) m.set(v, w);\n      }\n      if (m.size > 0) out[label] = PMF.fromMap(m, this.eps);\n    }\n    return out;\n  }\n\n  /**\n   * Mixture weights per label, normalized to sum to 1 over labels that appeared.\n   * Uses raw mass before per-outcome normalization.\n   */\n  weights(): Record<L, number> {\n    const res = {} as Record<L, number>;\n    for (const [, bag] of this.labelMass) {\n      for (const [lab, w] of Object.entries(bag) as [L, number][]) {\n        if (!Number.isFinite(w) || w <= 0) continue;\n        res[lab] = (res[lab] ?? 0) + w;\n      }\n    }\n    // Normalize\n    let total = 0;\n    let c = 0;\n    for (const v of Object.values(res)) {\n      const y = (v as number) - c;\n      const t = total + y;\n      c = t - total - y;\n      total = t;\n    }\n    if (total > 0) {\n      for (const k in res) res[k as L] = res[k as L] / total;\n    }\n    return res;\n  }\n\n  toJSON(): {\n    totals: Array<[number, number]>;\n    labels: Array<[number, Record<L, number>]>;\n    eps: number;\n  } {\n    return {\n      totals: Array.from(this.totals.entries()).sort((a, b) => a[0] - b[0]),\n      labels: Array.from(this.labelMass.entries()).sort((a, b) => a[0] - b[0]),\n      eps: this.eps,\n    };\n  }\n\n  static mix<L extends string = string>(\n    items: Array<[label: L, pmf: PMF, weight: number]>,\n    eps: number = EPS\n  ): PMF {\n    const mix = new Mixture<L>(eps);\n    for (const [lab, pmf, w] of items) mix.add(lab, pmf, w);\n    return mix.buildPMF();\n  }\n}\n"]}