UNPKG

@randsum/mcp

Version:

Model Context Protocol stdio server exposing the RANDSUM dice rolling ecosystem to AI agents

1,482 lines (1,470 loc) 155 kB
#!/usr/bin/env node // src/index.ts import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; // src/server.ts import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z as z3 } from "zod"; // package.json var version = "2.0.0"; // ../roller/dist/shared/chunk-b1m8anm6.js var A = { INVALID_NOTATION: "INVALID_NOTATION", MODIFIER_ERROR: "MODIFIER_ERROR", VALIDATION_ERROR: "VALIDATION_ERROR", ROLL_ERROR: "ROLL_ERROR" }; class z extends Error { code; context; constructor(j, k, q) { super(j); this.name = "RandsumError", this.code = k, this.context = q; } } class H extends z { suggestion; constructor(j, k, q, B) { let F = q ? `Invalid notation "${j}": ${k}. Did you mean "${q}"?` : `Invalid notation "${j}": ${k}`, G = { notation: j, ...B }; super(F, A.INVALID_NOTATION, G); this.name = "NotationParseError", this.suggestion = q; } } class I extends z { constructor(j, k, q) { super(`Modifier error for "${j}": ${k}`, A.MODIFIER_ERROR, q); this.name = "ModifierError"; } } class J extends z { constructor(j, k) { super(`Validation error: ${j}`, A.VALIDATION_ERROR, k); this.name = "ValidationError"; } } class K extends z { constructor(j, k) { super(j, A.ROLL_ERROR, k); this.name = "RollError"; } } // ../games/dist/shared/chunk-ncvrq0cn.js class E extends z { code; constructor(e, r) { super(e, r); this.name = "SchemaError", this.code = r; } } // ../roller/dist/shared/chunk-c998prkd.js function q(r) { if (!r.length) return ""; if (r.length === 1) return `${r[0]}`; let e = r.map((u) => `${u}`), t = e.pop(); return `${e.join(" ")} and ${t}`; } function O(r) { let t = r.replace(/[{}]/g, "").split(",").map((f) => f.trim()).filter(Boolean), u = {}, m = []; for (let f of t) if (f.startsWith(">=")) { let n = Number(f.slice(2)); if (!isNaN(n)) u.greaterThanOrEqual = n; } else if (f.startsWith("<=")) { let n = Number(f.slice(2)); if (!isNaN(n)) u.lessThanOrEqual = n; } else if (f.startsWith(">")) { let n = Number(f.slice(1)); if (!isNaN(n)) u.greaterThan = n; } else if (f.startsWith("<")) { let n = Number(f.slice(1)); if (!isNaN(n)) u.lessThan = n; } else if (f.startsWith("=")) { let n = Number(f.slice(1)); if (!isNaN(n)) m.push(n); } else { let n = Number(f); if (!isNaN(n)) m.push(n); } if (m.length > 0) u.exact = m; return u; } function a(r) { return r.greaterThan !== undefined || r.greaterThanOrEqual !== undefined || r.lessThan !== undefined || r.lessThanOrEqual !== undefined || r.exact !== undefined && r.exact.length > 0; } function K2({ greaterThan: r, greaterThanOrEqual: e, lessThan: t, lessThanOrEqual: u, exact: m }) { let f = []; if (m?.length) f.push(q(m)); if (e !== undefined) f.push(`greater than or equal to ${e}`); if (r !== undefined) f.push(`greater than ${r}`); if (u !== undefined) f.push(`less than or equal to ${u}`); if (t !== undefined) f.push(`less than ${t}`); return f; } function C({ greaterThan: r, greaterThanOrEqual: e, lessThan: t, lessThanOrEqual: u, exact: m }) { let f = []; if (m?.length) f.push(...m.map(String)); if (e !== undefined) f.push(`>=${e}`); if (r !== undefined) f.push(`>${r}`); if (u !== undefined) f.push(`<=${u}`); if (t !== undefined) f.push(`<${t}`); return f; } function h(r) { return r; } var I2 = /[Cc]\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\}/; var w = h({ name: "cap", priority: 10, pattern: I2, parse: (r) => { let e = I2.exec(r); if (!e?.[1]) return {}; let t = O(e[1]), u = {}; if (t.greaterThan !== undefined) u.greaterThan = t.greaterThan; if (t.greaterThanOrEqual !== undefined) u.greaterThanOrEqual = t.greaterThanOrEqual; if (t.lessThan !== undefined) u.lessThan = t.lessThan; if (t.lessThanOrEqual !== undefined) u.lessThanOrEqual = t.lessThanOrEqual; if (t.exact?.length) u.exact = t.exact; return Object.keys(u).length > 0 ? { cap: u } : {}; }, toNotation: (r) => { let e = C(r); return e.length ? `C{${e.join(",")}}` : undefined; }, toDescription: (r) => { let { exact: e, ...t } = r, u = []; if (e?.length) u.push(...e.map((f) => `No Rolls Greater Than ${f}`)); let m = K2(t); return u.push(...m.map((f) => `No Rolls ${f}`)), u; } }); var T = /!!(\d+)?(\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\})?/; var W = h({ name: "compound", priority: 51, pattern: T, parse: (r) => { let e = T.exec(r); if (!e) return {}; let t = e[1], u = e[3]; if (u) { let m = O(u); if (a(m)) return { compound: m }; } if (t !== undefined) return { compound: Number(t) }; return { compound: true }; }, toNotation: (r) => { if (r === true) return "!!"; if (typeof r === "number") return `!!${r}`; if (typeof r === "object") { let e = C(r); if (!e.length) return "!!"; return `!!{${e.join(",")}}`; } return; }, toDescription: (r) => { if (r === true) return ["Compounding Dice"]; if (r === 0) return ["Compounding Dice (unlimited)"]; if (typeof r === "number") return [`Compounding Dice (max ${r} times)`]; if (typeof r === "object") { let e = K2(r); if (e.length === 0) return ["Compounding Dice"]; return [`Compounding Dice on ${e.join(" or ")}`]; } return []; } }); var R = /#\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\}/; var V = h({ name: "count", priority: 80, pattern: R, parse: (r) => { let e = R.exec(r); if (!e) return {}; let t = O(e[1] ?? ""), u = t.greaterThan !== undefined || t.greaterThanOrEqual !== undefined, m = t.lessThan !== undefined || t.lessThanOrEqual !== undefined, f = { ...t }; if (u && m) f.deduct = true; return { count: f }; }, toNotation: (r) => { let e = []; if (r.exact?.length) e.push(...r.exact.map((t) => `=${t}`)); if (r.greaterThanOrEqual !== undefined) e.push(`>=${r.greaterThanOrEqual}`); if (r.greaterThan !== undefined) e.push(`>${r.greaterThan}`); if (r.lessThanOrEqual !== undefined) e.push(`<=${r.lessThanOrEqual}`); if (r.lessThan !== undefined) e.push(`<${r.lessThan}`); if (e.length === 0) return; return `#{${e.join(",")}}`; }, toDescription: (r) => { let e = []; if (r.exact?.length) e.push(`Count dice equal to ${r.exact.join(", ")}`); if (r.greaterThanOrEqual !== undefined) e.push(`Count dice greater than or equal to ${r.greaterThanOrEqual}`); if (r.greaterThan !== undefined) e.push(`Count dice greater than ${r.greaterThan}`); if (r.lessThanOrEqual !== undefined) if (r.deduct) e.push(`deduct dice less than or equal to ${r.lessThanOrEqual}`); else e.push(`Count dice less than or equal to ${r.lessThanOrEqual}`); if (r.lessThan !== undefined) if (r.deduct) e.push(`deduct dice less than ${r.lessThan}`); else e.push(`Count dice less than ${r.lessThan}`); if (e.length === 0) return []; if (r.deduct && e.length > 1) return [e.join(", ")]; return e; } }); var Vr = /[Hh](\d+)?/g; var Br = /(?<![Kk])[Ll](\d+)?/g; var Jr = /[Dd]\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\}/; var B = h({ name: "drop", priority: 65, pattern: /([Hh](\d+)?|(?<![Kk])[Ll](\d+)?|[Dd]\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\})/, parse: (r) => { let e = {}, t = Array.from(r.matchAll(Vr)); if (t.length > 0) e.highest = t.reduce((f, n) => { return f + (n[1] ? Number(n[1]) : 1); }, 0); let u = Array.from(r.matchAll(Br)); if (u.length > 0) e.lowest = u.reduce((f, n) => { return f + (n[1] ? Number(n[1]) : 1); }, 0); let m = Jr.exec(r); if (m?.[1]) { let f = O(m[1]); if (f.greaterThan !== undefined) e.greaterThan = f.greaterThan; if (f.greaterThanOrEqual !== undefined) e.greaterThanOrEqual = f.greaterThanOrEqual; if (f.lessThan !== undefined) e.lessThan = f.lessThan; if (f.lessThanOrEqual !== undefined) e.lessThanOrEqual = f.lessThanOrEqual; if (f.exact) e.exact = f.exact; } return a(e) || e.highest !== undefined || e.lowest !== undefined ? { drop: e } : {}; }, toNotation: (r) => { let { highest: e, lowest: t, greaterThan: u, greaterThanOrEqual: m, lessThan: f, lessThanOrEqual: n, exact: N } = r, $ = []; if (e) $.push(e === 1 ? "H" : `H${e}`); if (t) $.push(t === 1 ? "L" : `L${t}`); let b = []; if (m !== undefined) b.push(`>=${m}`); if (u !== undefined) b.push(`>${u}`); if (n !== undefined) b.push(`<=${n}`); if (f !== undefined) b.push(`<${f}`); if (N) N.forEach((g) => b.push(`${g}`)); if (b.length > 0) $.push(`D{${b.join(",")}}`); return $.length ? $.join("") : undefined; }, toDescription: (r) => { let { highest: e, lowest: t, greaterThan: u, greaterThanOrEqual: m, lessThan: f, lessThanOrEqual: n, exact: N } = r, $ = []; if (e) $.push(e > 1 ? `Drop highest ${e}` : "Drop highest"); if (t) $.push(t > 1 ? `Drop lowest ${t}` : "Drop lowest"); if (N) $.push(`Drop ${q(N)}`); if (m !== undefined) $.push(`Drop greater than or equal to ${m}`); if (u !== undefined) $.push(`Drop greater than ${u}`); if (n !== undefined) $.push(`Drop less than or equal to ${n}`); if (f !== undefined) $.push(`Drop less than ${f}`); return $; } }); var Qr = /(?<!!)!(?!!|[pPsSiIrR])(\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\})?/; var J2 = h({ name: "explode", priority: 50, pattern: /(?<!!)!(?!!|[pPsSiIrR])(\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\})?/, parse: (r) => { let e = Qr.exec(r); if (!e) return {}; let t = e[2]; if (t) { let u = O(t); if (a(u)) return { explode: u }; } return { explode: true }; }, toNotation: (r) => { if (r === true) return "!"; if (typeof r === "object") { let e = C(r); if (!e.length) return "!"; return `!{${e.join(",")}}`; } return; }, toDescription: (r) => { if (!r) return []; if (r === true) return ["Exploding Dice"]; if (typeof r === "object") { let e = K2(r); if (e.length === 0) return ["Exploding Dice"]; return [`Exploding Dice on ${e.join(" or ")}`]; } return ["Exploding Dice"]; } }); var zr = /![sS]\{[\d,]+\}/; var Q = h({ name: "explodeSequence", priority: 53, pattern: /![sS]\{[\d,]+\}|![iI]|![rR]/, parse: (r) => { let e = zr.exec(r); if (!e) return {}; return { explodeSequence: e[0].slice(3, -1).split(",").map(Number) }; }, toNotation: (r) => { if (!Array.isArray(r) || r.length === 0) return; return `!s{${r.join(",")}}`; }, toDescription: (r) => { if (!Array.isArray(r) || r.length === 0) return []; return [`Explode through sequence: ${r.map((t) => `d${t}`).join(", ")}`]; } }); var S = /\/\/(\d+)/; var z2 = h({ name: "integerDivide", priority: 93, pattern: S, parse: (r) => { let e = S.exec(r); if (!e) return {}; return { integerDivide: Number(e[1]) }; }, toNotation: (r) => { return `//${r}`; }, toDescription: (r) => { return [`Integer divide by ${r}`]; } }); var Ur = /[Kk][Mm](\d+)?/; var Zr = /[Kk](?![LlMm])(\d+)?/; var Pr = /[Kk][Ll](\d+)?/i; var U = h({ name: "keep", priority: 66, pattern: /[Kk]([LlMm])?(\d+)?/, parse: (r) => { let e = Ur.exec(r); if (e) { let f = e[1] ? Number(e[1]) : 1; return { drop: { lowest: f, highest: f } }; } let t = {}, u = Pr.exec(r); if (u) return t.lowest = u[1] ? Number(u[1]) : 1, { keep: t }; let m = Zr.exec(r); if (m) return t.highest = m[1] ? Number(m[1]) : 1, { keep: t }; return {}; }, toNotation: (r) => { let { highest: e, lowest: t } = r, u = []; if (e) u.push(e === 1 ? "K" : `K${e}`); if (t) u.push(t === 1 ? "kl" : `kl${t}`); return u.length ? u.join("") : undefined; }, toDescription: (r) => { let { highest: e, lowest: t } = r, u = []; if (e) u.push(e > 1 ? `Keep highest ${e}` : "Keep highest"); if (t) u.push(t > 1 ? `Keep lowest ${t}` : "Keep lowest"); return u; } }); function A2(r) { let { name: e, priority: t, operator: u, verb: m } = r, f = u === "+" ? "\\+" : "-", n = new RegExp(`${f}(\\d+)`), N = new RegExp(`${f}(\\d+)`, "g"); return h({ name: e, priority: t, pattern: n, parse: ($) => { let b = Array.from($.matchAll(N)); if (b.length === 0) return {}; let g = b.reduce((p, d) => p + Number(d[1]), 0); return { [e]: g }; }, toNotation: ($) => { if (e === "plus" && $ < 0) return `-${Math.abs($)}`; return `${u}${$}`; }, toDescription: ($) => { return [`${m} ${$}`]; } }); } var Z = A2({ name: "minus", priority: 91, operator: "-", verb: "Subtract" }); var k = /%(\d+)/; var P = h({ name: "modulo", priority: 94, pattern: k, parse: (r) => { let e = k.exec(r); if (!e) return {}; return { modulo: Number(e[1]) }; }, toNotation: (r) => { return `%${r}`; }, toDescription: (r) => { return [`Modulo ${r}`]; } }); var _ = /(?<!\*)\*(?!\*)(\d+)/; var X = h({ name: "multiply", priority: 85, pattern: _, parse: (r) => { let e = _.exec(r); if (!e) return {}; return { multiply: Number(e[1]) }; }, toNotation: (r) => { return `*${r}`; }, toDescription: (r) => { return [`Multiply dice by ${r}`]; } }); var i = /\*\*(\d+)/; var H2 = h({ name: "multiplyTotal", priority: 100, pattern: i, parse: (r) => { let e = i.exec(r); if (!e) return {}; return { multiplyTotal: Number(e[1]) }; }, toNotation: (r) => { return `**${r}`; }, toDescription: (r) => { return [`Multiply total by ${r}`]; } }); var s = /!p(\d+)?(\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\})?/i; var Y = h({ name: "penetrate", priority: 52, pattern: s, parse: (r) => { let e = s.exec(r); if (!e) return {}; let t = e[1], u = e[3]; if (u) { let m = O(u); if (a(m)) return { penetrate: m }; } if (t !== undefined) return { penetrate: Number(t) }; return { penetrate: true }; }, toNotation: (r) => { if (r === true) return "!p"; if (typeof r === "number") return `!p${r}`; if (typeof r === "object") { let e = C(r); if (!e.length) return "!p"; return `!p{${e.join(",")}}`; } return; }, toDescription: (r) => { if (r === true) return ["Penetrating Dice"]; if (r === 0) return ["Penetrating Dice (unlimited)"]; if (typeof r === "number") return [`Penetrating Dice (max ${r} times)`]; if (typeof r === "object") { let e = K2(r); if (e.length === 0) return ["Penetrating Dice"]; return [`Penetrating Dice on ${e.join(" or ")}`]; } return []; } }); var c = A2({ name: "plus", priority: 90, operator: "+", verb: "Add" }); var rr = /[Vv]\{((?:>=|<=|>|<)?\d+=\d+(?:,(?:>=|<=|>|<)?\d+=\d+)*)\}/; var G = h({ name: "replace", priority: 30, pattern: rr, parse: (r) => { let e = rr.exec(r); if (!e) return {}; let t = e[1]; if (!t) return {}; return { replace: t.split(",").map((f) => f.trim()).map((f) => { let n = /^((?:>=|<=|>|<)?\d+)=(\d+)$/.exec(f); if (!n?.[1] || !n[2]) return { from: 0, to: 0 }; let [, N, $] = n; return { from: N.startsWith(">=") ? { greaterThanOrEqual: Number(N.slice(2)) } : N.startsWith("<=") ? { lessThanOrEqual: Number(N.slice(2)) } : N.startsWith(">") ? { greaterThan: Number(N.slice(1)) } : N.startsWith("<") ? { lessThan: Number(N.slice(1)) } : Number(N), to: Number($) }; }) }; }, toNotation: (r) => { let t = (Array.isArray(r) ? r : [r]).map(({ from: u, to: m }) => { if (typeof u === "object") return C(u).map((n) => `${n}=${m}`).join(","); return `${u}=${m}`; }); return t.length ? `V{${t.join(",")}}` : undefined; }, toDescription: (r) => { return (Array.isArray(r) ? r : [r]).map(({ from: t, to: u }) => { if (typeof t === "object") return `Replace ${K2(t).join(" and ")} with ${u}`; return `Replace ${t} with ${u}`; }); } }); var er = "((?:>=|<=|>|<|=)?\\d+(?:,(?:>=|<=|>|<|=)?\\d+)*)"; var Xr = new RegExp(`[Rr][Oo]\\{${er}\\}|[Rr]\\{${er}\\}(\\d+)?`, "g"); var L = h({ name: "reroll", priority: 40, pattern: /[Rr]([Oo])?\{((?:>=|<=|>|<|=)?\d+(?:,(?:>=|<=|>|<|=)?\d+)*)\}(\d+)?/, parse: (r) => { let e = Array.from(r.matchAll(Xr)); if (e.length === 0) return {}; let t = {}; for (let u of e) { let m = u[1] !== undefined, f = m ? u[1] : u[2], n = m ? 1 : u[3] ? Number(u[3]) : undefined; if (n !== undefined) t.max = n; if (f) { let N = O(f); if (N.greaterThan !== undefined) t.greaterThan = N.greaterThan; if (N.greaterThanOrEqual !== undefined) t.greaterThanOrEqual = N.greaterThanOrEqual; if (N.lessThan !== undefined) t.lessThan = N.lessThan; if (N.lessThanOrEqual !== undefined) t.lessThanOrEqual = N.lessThanOrEqual; if (N.exact) t.exact = [...t.exact ?? [], ...N.exact]; } } return a(t) || t.max !== undefined ? { reroll: t } : {}; }, toNotation: (r) => { let e = C(r); if (!e.length) return; if (r.max === 1) return `ro{${e.join(",")}}`; let t = r.max ? `${r.max}` : ""; return `R{${e.join(",")}}${t}`; }, toDescription: (r) => { let { exact: e, greaterThan: t, greaterThanOrEqual: u, lessThan: m, lessThanOrEqual: f, max: n } = r, N = []; if (e) e.forEach((d) => N.push(`${d}`)); let $ = []; if (u !== undefined) $.push(`greater than or equal to ${u}`); if (t !== undefined) $.push(`greater than ${t}`); if (f !== undefined) $.push(`less than or equal to ${f}`); if (m !== undefined) $.push(`less than ${m}`); let b = q(N.map(Number)), g = $.join(" and "), j = [b, g].filter(Boolean).join(", "); if (!j) return []; if (n === 1) return [`Reroll once ${j}`]; let p = n !== undefined ? ` (up to ${n} times)` : ""; return [`Reroll ${j}${p}`]; } }); var tr = /[Ss]([Aa]|[Dd])(?![{\d])/; var v = h({ name: "sort", priority: 95, pattern: tr, parse: (r) => { let e = tr.exec(r); if (!e) return {}; let t = e[1]; if (t === "d" || t === "D") return { sort: "desc" }; return { sort: "asc" }; }, toNotation: (r) => { return r === "desc" ? "sd" : "sa"; }, toDescription: (r) => { return [r === "desc" ? "Sort descending" : "Sort ascending"]; } }); var ur = /[Uu](?:\{([^}]{1,50})\})?/; var F = h({ name: "unique", priority: 60, pattern: ur, parse: (r) => { let e = ur.exec(r); if (!e) return {}; if (!e[1]) return { unique: true }; return { unique: { notUnique: e[1].split(",").map((u) => Number(u.trim())).filter((u) => !isNaN(u)) } }; }, toNotation: (r) => { if (r === true) return "U"; if (typeof r === "object") return `U{${r.notUnique.join(",")}}`; return; }, toDescription: (r) => { if (r === true) return ["No Duplicate Rolls"]; if (typeof r === "object") return [`No Duplicates (except ${q(r.notUnique)})`]; return []; } }); var fr = /[Ww](?![{])/; var M = h({ name: "wildDie", priority: 55, pattern: fr, parse: (r) => { if (!fr.exec(r)) return {}; return { wildDie: true }; }, toNotation: (r) => { if (r) return "W"; return; }, toDescription: (r) => { if (r) return ["Wild Die (compound on max, penalty on 1)"]; return []; } }); var mr = [w, B, U, G, L, J2, W, Y, Q, F, M, X, c, Z, v, z2, P, V, H2]; function Jt(r) { if (!r) return ""; return mr.map((e) => { let t = r[e.name]; if (t === undefined) return; return e.toNotation(t); }).filter((e) => typeof e === "string").join(""); } function nr(r) { if (!r) return []; return mr.flatMap((e) => { let t = r[e.name]; if (t === undefined) return []; return e.toDescription(t); }).filter((e) => typeof e === "string" && e.length > 0); } function Nr({ sides: r }) { if (Array.isArray(r)) return { sides: r.length, faces: r }; return { sides: r }; } function Hr(r, e, t) { switch (t.dieType) { case "fate": return `Roll ${r}dF${t.fateVariant === 2 ? ".2" : ""}`; case "zeroBias": return `Roll ${r}z${e}`; case "custom": return `Roll ${r}d{${(t.customFaces ?? []).join(",")}}`; case "draw": return `Draw ${r} from d${e}`; case "geometric": return `Roll g${e} (geometric: roll d${e} until 1)`; default: return null; } } function Pt(r) { let { modifiers: e, quantity: t = 1, arithmetic: u } = r, { sides: m, faces: f = [] } = Nr(r), n = Hr(t, m, r); if (n !== null) return [n]; let $ = `Roll ${t} ${m}-sided ${t === 1 ? "die" : "dice"}`, b = `Roll ${t} Dice with the following sides: ${f.join(", ")}`, g = nr(e), j = u === "subtract" ? "and Subtract the result" : ""; return [f.length ? b : $, ...g, j].filter(Boolean); } var D = Object.freeze([4, 6, 8, 10, 12, 20, 100]); var $r = "[Dd]%"; var hr = "[Dd][Ff](?:\\.[12])?"; var br = "[Dd]\\{[^}]+\\}"; var gr = "[Dd][Dd]\\d+"; var yr = "[Gg]\\d+"; var jr = "[Zz]\\d+"; var Or = /[Ff]\{(\d+)\}/; var l = h({ name: "count", priority: 80, pattern: Or, parse: (r) => { let e = Or.exec(r); if (!e) return {}; return { count: { lessThanOrEqual: Number(e[1]) } }; }, toNotation: (r) => { if (r.lessThanOrEqual === undefined) return; return `F{${r.lessThanOrEqual}}`; }, toDescription: (r) => { if (r.lessThanOrEqual === undefined) return []; return [`Count failures at or below ${r.lessThanOrEqual}`]; } }); var pr = /(?<!!)[Ss]\{(\d+)(?:,(\d+))?\}/; var o = h({ name: "count", priority: 80, pattern: pr, parse: (r) => { let e = pr.exec(r); if (!e) return {}; let t = Number(e[1]), u = e[2] ? Number(e[2]) : undefined; if (u !== undefined) return { count: { greaterThanOrEqual: t, lessThanOrEqual: u, deduct: true } }; return { count: { greaterThanOrEqual: t } }; }, toNotation: (r) => { if (r.greaterThanOrEqual === undefined) return; if (r.deduct && r.lessThanOrEqual !== undefined) return `S{${r.greaterThanOrEqual},${r.lessThanOrEqual}}`; return `S{${r.greaterThanOrEqual}}`; }, toDescription: (r) => { if (r.greaterThanOrEqual === undefined) return []; if (r.deduct && r.lessThanOrEqual !== undefined) return [`Count successes >= ${r.greaterThanOrEqual}, botches <= ${r.lessThanOrEqual}`]; return [`Count successes >= ${r.greaterThanOrEqual}`]; } }); function y(r) { let e = r.flags.replace(/[gy]/g, ""); return new RegExp(r.source, `${e.includes("i") ? e : `${e}i`}y`); } var Yr = String.raw`[Mm][Ss]\{\d+\}`; var Cr = [{ key: "C{..}", category: "Clamp", matcher: y(w.pattern) }, { key: "V{..}", category: "Map", matcher: y(G.pattern) }, { key: "R{..}", category: "Substitute", matcher: y(L.pattern) }, { key: "!", category: "Generate", matcher: y(J2.pattern) }, { key: "!!", category: "Accumulate", matcher: y(W.pattern) }, { key: "!p", category: "Accumulate", matcher: y(Y.pattern) }, { key: "!s", category: "Generate", matcher: y(Q.pattern) }, { key: "W", category: "Dispatch", matcher: y(M.pattern) }, { key: "U", category: "Substitute", matcher: y(F.pattern) }, { key: "drop", category: "Filter", matcher: y(B.pattern) }, { key: "K", category: "Filter", matcher: y(U.pattern) }, { key: "#{..}", category: "Reinterpret", matcher: y(V.pattern) }, { key: "S{..}", category: "Reinterpret", matcher: y(o.pattern) }, { key: "F{..}", category: "Reinterpret", matcher: y(l.pattern) }, { key: "ms{..}", category: "Scale", matcher: new RegExp(Yr, "iy") }, { key: "*", category: "Scale", matcher: y(X.pattern) }, { key: "+", category: "Scale", matcher: y(c.pattern) }, { key: "-", category: "Scale", matcher: y(Z.pattern) }, { key: "//", category: "Scale", matcher: y(z2.pattern) }, { key: "%", category: "Scale", matcher: y(P.pattern) }, { key: "sort", category: "Order", matcher: y(v.pattern) }, { key: "**", category: "Scale", matcher: y(H2.pattern) }]; var ar = [{ key: "DDN", kind: "draw", matcher: new RegExp(`(\\d*)${gr}`, "iy") }, { key: "d%", kind: "percentile", matcher: new RegExp(`(\\d*)${$r}`, "iy") }, { key: "dF", kind: "fate", matcher: new RegExp(`(\\d*)${hr}`, "iy") }, { key: "d{...}", kind: "custom", matcher: new RegExp(`(\\d*)${br}`, "iy") }, { key: "gN", kind: "geometric", matcher: new RegExp(`(\\d*)${yr}`, "iy") }, { key: "zN", kind: "zeroBias", matcher: new RegExp(`(\\d*)${jr}`, "iy") }, { key: "xDN", kind: "standard", matcher: /(\d*)[Dd](\d+)/y }]; function cr(r, e, t) { let u = r[e], m = u === "+" || u === "-"; if (!m && !t) return null; let f = m ? u : "", n = m ? e + 1 : e; for (let N of ar) if (N.matcher.lastIndex = n, N.matcher.exec(r)?.index === n) { let b = N.matcher.lastIndex; return { text: r.slice(e, b), key: N.key, kind: N.kind, sign: f, end: b }; } return null; } function Gr(r, e) { for (let t of Cr) { t.matcher.lastIndex = e; let u = t.matcher.exec(r); if (u?.index === e) return { text: u[0], key: t.key, category: t.category, end: t.matcher.lastIndex }; } return null; } var Lr = /[Xx][1-9]\d*/y; function vr(r, e, t) { if (r.charCodeAt(e) !== 91) return null; if (e >= t.noCloseBracketFrom) return null; let u = r.indexOf("]", e + 1); if (u === -1) return t.noCloseBracketFrom = e, null; if (u === e + 1) return null; return r.slice(e, u + 1); } function Fr(r, e, t) { r.lastIndex = t; let u = r.exec(e); return u?.index === t ? u[0] : null; } function Mr(r, e, t) { let u = r[r.length - 1]; if (u?.role === "unknown") r[r.length - 1] = { ...u, text: u.text + e, end: t + 1 }; else r.push({ text: e, key: "unknown", category: "unknown", start: t, end: t + 1, role: "unknown" }); } function dr(r, e, t, u) { let m = e === 0, f = r[e] === "+" || r[e] === "-"; if (m || f) { let b = cr(r, e, m); if (b) return t.push({ text: b.text, key: b.kind === "standard" ? "xDN" : b.key, category: b.kind === "standard" ? "Core" : "Special", start: e, end: b.end, role: "pool", poolKind: b.kind, sign: b.sign }), b.end; } let n = Gr(r, e); if (n) return t.push({ text: n.text, key: n.key, category: n.category, start: e, end: n.end, role: "modifier" }), n.end; let N = Fr(Lr, r, e); if (N) return t.push({ text: N, key: "xN", category: "Special", start: e, end: e + N.length, role: "repeat" }), e + N.length; let $ = vr(r, e, u); if ($) return t.push({ text: $, key: "label", category: "Special", start: e, end: e + $.length, role: "annotation" }), e + $.length; return Mr(t, r[e] ?? "", e), e + 1; } function Kr(r) { if (r.length === 0) return []; let e = [], t = { pos: 0 }, u = { noCloseBracketFrom: Number.POSITIVE_INFINITY }; while (t.pos < r.length) t.pos = dr(r, t.pos, e, u); return e; } var E2 = 1000; var lr = new Set(["#{..}", "S{..}", "F{..}"]); var or = /^\d+/; var Rr = /^\d*[Dd]([1-9]\d*)$/; function Ar(r, e) { let t = or.exec(e)?.[0]; if (t !== undefined && !/^[1-9]/.test(t)) return false; if (r === "standard") return Rr.test(e); return true; } function x(r, e) { return { valid: false, pools: [], error: { message: r, position: e } }; } function Er(r, e) { let t = e.filter((m) => m.role === "modifier"), u = e.find((m) => m.role === "annotation")?.text.slice(1, -1); return { kind: r.poolKind ?? "standard", sign: r.sign ?? "", text: r.text, body: r.text.replace(/^[+-]/, ""), modifiersText: t.map((m) => m.text).join(""), hasModifiers: t.length > 0, ...u !== undefined ? { label: u } : {} }; } function bu(r) { let e = r.length - r.trimStart().length, t = r.trim(); if (t.length === 0) return x("Empty notation", 0); if (t.length > E2) return x(`Notation exceeds ${E2} characters`, E2 + e); let u = Kr(t), m = u.find((g) => g.role === "unknown"); if (m) return x(`Unexpected "${m.text}"`, m.start + e); let f = u[0]; if (!f) return x("No die expression found", 0); if (f.role !== "pool") return x(`Expected a die before "${f.text}"`, f.start + e); let n = u.find((g, j) => g.role === "repeat" && u.slice(j + 1).some((p) => p.role !== "repeat")); if (n) return x(`Repeat "${n.text}" must be at the end of the notation`, n.start + e); let N = u.filter((g) => g.role === "modifier" && lr.has(g.key)); if (N.length > 1) return x("Only one Count-family modifier (#{}, S{}, F{}) is permitted", (N[1]?.start ?? 0) + e); let $ = u.find((g) => g.role === "pool" && !Ar(g.poolKind ?? "standard", g.text.replace(/^[+-]/, ""))); if ($) return x(`Invalid die "${$.text}"`, $.start + e); return { valid: true, pools: u.flatMap((g, j) => { if (g.role !== "pool") return []; let p = u.slice(j + 1).findIndex((Wr) => Wr.role === "pool"), d = p === -1 ? u.length : j + 1 + p; return [Er(g, u.slice(j + 1, d))]; }) }; } var Dr = /[+-]?[1-9]\d*[Dd][1-9]\d*|[+-][Dd][1-9]\d*|(?<![\s\S])[Dd][1-9]\d*/; var Ir = [w, B, U, G, L, J2, W, Y, Q, F, M, X, c, Z, v, z2, P, V, H2]; var Tr = [o, l]; var Sr = /[Mm][Ss]\{(\d+)\}/g; function kr(r) { return r.replace(Sr, (e, t) => `-${t}`); } var _r = [...Ir, ...Tr]; var ir = [R, o.pattern, l.pattern]; function sr(r) { return ir.flatMap((e) => { let t = e.flags.includes("g") ? e.flags : `${e.flags}g`, u = new RegExp(e.source, t); return [...r.matchAll(u)].map((m) => m.index); }).sort((e, t) => e - t); } function xr(r) { let e = {}, t = kr(r), u = sr(t); if (u.length > 1) { let m = u[1]; throw new I("count", "Multiple Count modifiers are not permitted: only one of #{...}, S{...}, or F{...} may appear per notation string. Combine them into a single #{...} or S{n,b}.", { notation: r, ...m !== undefined ? { position: m } : {} }); } for (let m of _r) if (m.pattern.test(t)) m.pattern.lastIndex = 0, Object.assign(e, m.parse(t)); return e; } var wr = /\[([^\]]+)\]/; function re(r) { let e = wr.exec(r); if (!e) return { cleaned: r }; let t = r.replace(wr, ""), u = e[1]; if (u === undefined) return { cleaned: t }; return { cleaned: t, label: u }; } var ee = /![iI]/; var te = /![rR]/; function ue(r) { let e = D.indexOf(r); if (e !== -1) return D.slice(e + 1); let t = D.findIndex((u) => u >= r); if (t === -1) return []; return D.slice(t); } function fe(r) { let e = D.indexOf(r); if (e !== -1) { if (e === 0) return []; return [...D.slice(0, e)].reverse(); } let t = me(D, (m) => m <= r); if (t === -1) return []; return [...D.slice(0, t + 1)].reverse(); } function me(r, e) { for (let t of Array.from({ length: r.length }, (u, m) => r.length - 1 - m)) { let u = r[t]; if (u !== undefined && e(u)) return t; } return -1; } function Fu(r) { let e = r.trim(), { cleaned: t, label: u } = re(e), m = t.match(Dr)?.at(0) ?? "", f = t.replace(m, ""), [n = "", N = ""] = m.split(/[Dd]/), $ = n.startsWith("-"), b = n.replace(/^[+-]/, ""), j = { quantity: b === "" ? N === "" ? 0 : 1 : Number(b), arithmetic: $ ? "subtract" : "add", sides: Number(N) }; if (u !== undefined) j.label = u; if (f.length === 0) return j; let p = xr(f); if (ee.test(f)) p.explodeSequence = ue(j.sides); else if (te.test(f)) p.explodeSequence = fe(j.sides); return { ...j, modifiers: p }; } // ../roller/dist/shared/chunk-a20vbn0c.js var _2 = /^([+-]?)(\d*)[Dd]%$/; var P2 = /^([+-]?)(\d*)[Gg](\d+)$/; var f = /^([+-]?)(\d*)[Dd][Dd](\d+)$/; var N = /^([+-]?)(\d*)[Dd][Ff](?:\.([12]))?$/; var E3 = /^([+-]?)(\d*)[Dd]\{([^}]+)\}$/; var M2 = /^([+-]?)(\d*)[Zz](\d+)$/; function B2(j) { return j === "-" ? "subtract" : "add"; } function G2(j) { return j !== undefined && j.length > 0 ? Number(j) : 1; } function b(j) { let J3 = j.trim(), K3 = _2.exec(J3); if (K3) return { quantity: G2(K3[2]), sides: 100, arithmetic: B2(K3[1]), kind: "percentile" }; let $ = f.exec(J3); if ($) return { quantity: G2($[2]), sides: Number($[3]), arithmetic: B2($[1]), kind: "draw" }; let W2 = P2.exec(J3); if (W2) return { quantity: G2(W2[2]), sides: Number(W2[3]), arithmetic: B2(W2[1]), kind: "geometric" }; let z3 = M2.exec(J3); if (z3) return { quantity: G2(z3[2]), sides: Number(z3[3]), arithmetic: B2(z3[1]), kind: "zeroBias" }; let Z2 = N.exec(J3); if (Z2) { let F2 = Z2[3] === "2" ? 2 : 1; return { quantity: G2(Z2[2]), sides: F2 === 2 ? 5 : 3, arithmetic: B2(Z2[1]), kind: "fate", fateVariant: F2 }; } let q2 = E3.exec(J3); if (q2) { let F2 = q2[3]; if (F2 === undefined) return null; let V2 = F2.split(",").map((O2) => O2.trim()); return { quantity: G2(q2[2]), sides: V2.length, arithmetic: B2(q2[1]), kind: "custom", customFaces: V2 }; } return null; } var L2 = 1000; var Q2 = 10; var S2 = /[Xx]([1-9]\d*)$/; function v2(j) { let J3 = S2.exec(j); if (!J3) return null; return { base: j.slice(0, J3.index), count: Number(J3[1]), position: J3.index }; } function X2(j) { return `${j.body}${j.modifiersText}${j.label !== undefined ? `[${j.label}]` : ""}`; } function T2(j) { let J3 = b(j.text); if (J3 === null) return Fu(X2(j)); let K3 = J3.kind, $ = { quantity: J3.quantity, arithmetic: J3.arithmetic, sides: J3.sides, dieType: K3 }; if (J3.fateVariant !== undefined) $.fateVariant = J3.fateVariant; if (J3.customFaces !== undefined) $.customFaces = J3.customFaces; if (j.label !== undefined) $.label = j.label; return $; } function h2(j) { if (j.kind === "percentile" && !j.hasModifiers) { let K3 = b(j.text); if (K3 !== null) { let $ = { quantity: K3.quantity, arithmetic: K3.arithmetic, sides: 100, dieType: "percentile" }; if (j.label !== undefined) $.label = j.label; return $; } } if (j.kind !== "standard" && j.kind !== "percentile" && !j.hasModifiers) return T2(j); let J3 = Fu(X2(j)); if (j.sign === "-") J3.arithmetic = "subtract"; return J3; } function w2(j, J3) { if (j.length > E2) throw new H(j, `notation exceeds maximum length of ${E2} characters`, undefined, { position: E2 }); let K3 = v2(j); if (K3) { if (J3 >= Q2) throw new H(j, `repeat nesting depth exceeds maximum of ${Q2}`, undefined, { position: K3.position }); if (K3.count > L2) throw new H(j, `repeat count ${K3.count} exceeds maximum of ${L2}`, undefined, { position: K3.position, value: K3.count }); let W2 = w2(K3.base, J3 + 1); return Array.from({ length: K3.count }, () => W2).flat(); } let $ = bu(j); if (!$.valid) return [Fu(j)]; return $.pools.map(h2); } function r(j) { return w2(j, 0); } function g(j) { let J3 = /^(\d+)(\d+)/.exec(j); if (J3?.[1] && J3[2]) { let K3 = J3[1], $ = J3[2]; if (Number.parseInt(K3, 10) <= 100 && Number.parseInt($, 10) >= 2 && Number.parseInt($, 10) <= 1000) return `${K3}d${$}`; } return; } function u(j) { if (/^[dD]\d+/.test(j)) return j.replace(/^[dD]/, "1d"); return; } function l2(j) { let J3 = j.replace(/\s+/g, ""); if (J3 !== j && /^\d+[dD]\d+/.test(J3)) return J3; return; } function I3(j) { let J3 = j.trim(), K3 = u(J3); if (K3) return K3; let $ = l2(J3); if ($) return $; let W2 = g(J3); if (W2) return W2; let Z2 = /^(\d+)d(\d+)/i.exec(J3); if (Z2?.[0]) return Z2[0]; if (/^\d+/.test(J3) && !J3.includes("d") && !J3.includes("D")) { let q2 = /^(\d+)(\d+)/.exec(J3); if (q2?.[1] && q2[2]) return `${q2[1]}d${q2[2]}`; } return; } function y2(j) { if (typeof j !== "string") return false; return bu(j).valid; } function Wj(j) { let { modifiers: J3, quantity: K3 = 1, arithmetic: $ } = j, { sides: W2 } = Nr(j), z3 = $ === "subtract" ? "-" : "", Z2 = Jt(J3), q2 = `${z3}${K3}d${W2}${Z2}`; if (!y2(q2)) throw new H(q2, "Generated notation is invalid", undefined, { value: j }); return q2; } var x2 = 1e4; var A3 = 1e6; function Yj(j, J3) { if (!Number.isInteger(j)) throw new J(`${J3} must be an integer, received: ${j}`, { path: J3, value: j }); } function zj(j) { if (j > x2) throw new J(`quantity ${j} exceeds maximum of ${x2}`, { path: "quantity", value: j }); } function Bj(j) { if (j > A3) throw new J(`sides ${j} exceeds maximum of ${A3}`, { path: "sides", value: j }); } function Gj(j, J3, K3, $) { if (j < J3 || j > K3) throw new J(`${$} must be between ${J3} and ${K3}, received: ${j}`, { path: $, value: j }); } function Hj(j, J3) { if (!Number.isFinite(j)) throw new J(`${J3} must be a finite number, received: ${j}`, { path: J3, value: j }); } function Cj(j, J3, K3) { if (j <= J3) throw new J(`${K3} must be greater than ${J3}, received: ${j}`, { path: K3, value: j }); } // ../roller/dist/shared/chunk-44dqqc75.js var d = { ...w, apply: ($, K3) => { let { greaterThan: J3, greaterThanOrEqual: Y2, lessThan: Z2, lessThanOrEqual: Q3, exact: G3 } = K3; return { rolls: $.map((H3) => { let W2 = J3 !== undefined && H3 > J3 ? J3 : Y2 !== undefined && H3 >= Y2 ? Y2 : H3, j = (G3 ?? []).reduce((B3, k2) => B3 > k2 ? k2 : B3, W2); return Z2 !== undefined && j < Z2 ? Z2 : Q3 !== undefined && j <= Q3 ? Q3 : j; }) }; }, validate: ($) => {} }; var F2 = 99; var P3 = 1000; function p($) { if ($.rollOne === undefined) throw Error("Internal error: rollOne function required but not provided"); return $; } function r2($) { if ($.parameters === undefined) throw Error("Internal error: parameters required but not provided"); return $; } function N2($) { if ($.rollOne === undefined) throw Error("Internal error: rollOne function required but not provided"); if ($.parameters === undefined) throw Error("Internal error: parameters required but not provided"); return $; } function U2($, { greaterThan: K3, greaterThanOrEqual: J3, lessThan: Y2, lessThanOrEqual: Z2, exact: Q3 }) { if (Q3?.includes($)) return true; if (K3 !== undefined && $ > K3) return true; if (J3 !== undefined && $ >= J3) return true; if (Y2 !== undefined && $ < Y2) return true; if (Z2 !== undefined && $ <= Z2) return true; return false; } function w3($) { if ($ === true) return (K3, J3) => K3 === J3; if ($ === false) return () => false; return (K3, J3) => U2(K3, $); } var D2 = { compound: { accumulate: ($, K3) => $ + K3 }, penetrate: { accumulate: ($, K3) => $ + Math.max(1, K3 - 1) } }; function m$($, K3 = 1) { if (typeof $ === "object") return K3; if ($ === true) return K3; if ($ === false) return 0; if ($ === 0) return P3; return $; } function T3($, K3, J3, Y2, Z2, Q3) { let G3 = Q3 ?? Z2.shouldContinue ?? ((H3, W2) => H3 === W2), z3 = (H3, W2) => { if (W2 >= Y2) return H3; let j = J3(), X3 = Z2.accumulate(H3, j, W2); if (!G3(j, K3)) return X3; return z3(X3, W2 + 1); }; return z3($, 0); } function O2($) { return (K3, J3, Y2) => { let { rollOne: Z2, parameters: Q3 } = N2(Y2), { sides: G3 } = Q3, z3 = m$(J3), H3 = w3(typeof J3 === "number" ? true : J3); return { rolls: K3.map((j) => H3(j, G3) ? T3(j, G3, Z2, z3, $, H3) : j) }; }; } var n = { ...W, requiresRollFn: true, requiresParameters: true, apply: O2(D2.compound) }; var s2 = { ...V, mutatesRolls: false, validate: ($) => { if ($.deduct && $.lessThanOrEqual !== undefined && $.greaterThanOrEqual !== undefined && $.lessThanOrEqual >= $.greaterThanOrEqual) throw new I("count", `botchThreshold (${$.lessThanOrEqual}) must be less than threshold (${$.greaterThanOrEqual})`, { path: "modifiers.count", value: $ }); }, apply: ($, K3) => { return { rolls: $, transformTotal: (J3, Y2) => { if (K3.deduct) { let Z2 = { ...K3.greaterThan !== undefined ? { greaterThan: K3.greaterThan } : {}, ...K3.greaterThanOrEqual !== undefined ? { greaterThanOrEqual: K3.greaterThanOrEqual } : {}, ...K3.exact !== undefined ? { exact: K3.exact } : {} }, Q3 = { ...K3.lessThan !== undefined ? { lessThan: K3.lessThan } : {}, ...K3.lessThanOrEqual !== undefined ? { lessThanOrEqual: K3.lessThanOrEqual } : {} }, G3 = Y2.filter((H3) => U2(H3, Z2)).length, z3 = Y2.filter((H3) => U2(H3, Q3)).length; return G3 - z3; } return Y2.filter((Z2) => U2(Z2, K3)).length; } }; } }; var t = { ...B, apply: ($, K3) => { let { highest: J3, lowest: Y2 } = K3, Z2 = $.filter((j) => !U2(j, K3)); if (J3 === undefined && Y2 === undefined) return { rolls: Z2 }; let Q3 = Z2.map((j, X3) => ({ roll: j, index: X3 })); Q3.sort((j, X3) => j.roll - X3.roll); let G3 = Y2 !== undefined ? new Set(Q3.slice(0, Math.min(Y2, Q3.length)).map((j) => j.index)) : new Set, z3 = J3 !== undefined ? new Set(Q3.slice(Math.max(0, Q3.length - J3)).map((j) => j.index)) : new Set, H3 = new Set([...G3, ...z3]), W2 = Z2.filter((j, X3) => !H3.has(X3)); if (Y2 !== undefined && J3 === undefined) return { rolls: [...W2].sort((j, X3) => j - X3) }; return { rolls: W2 }; }, validate: ($, { quantity: K3 }) => { let J3 = ($.lowest ?? 0) + ($.highest ?? 0); if (J3 >= K3) throw new I("drop", `Cannot drop ${J3} dice from a pool of ${K3}`, { path: "modifiers.drop", value: $ }); } }; var o2 = { ...J2, requiresRollFn: true, requiresParameters: true, apply: ($, K3, J3) => { let { rollOne: Y2, parameters: Z2 } = N2(J3), Q3 = w3(K3), G3 = $.filter((z3) => Q3(z3, Z2.sides)).map(() => Y2()); return { rolls: [...$, ...G3] }; } }; function L3($, K3 = Math.random) { return Math.floor(K3() * $); } function q2($, K3, J3) { if ($ <= 0) return []; return Array.from({ length: $ }, () => L3(K3, J3) + 1); } function c$($, K3) { let J3 = [], Y2 = $[$.length - 1]; if (Y2 === undefined) return J3; let Z2 = $.length + P3, Q3 = [...$]; for (let G3 of Array.from({ length: Z2 })) { let z3 = Q3.shift() ?? Y2, H3 = K3(z3); if (J3.push(H3), H3 !== z3) break; } return J3; } var K$ = { ...Q, requiresParameters: true, requiresRandomFn: true, apply: ($, K3, J3) => { let { parameters: Y2 } = r2(J3); if (!Array.isArray(K3) || K3.length === 0) return { rolls: $ }; let { sides: Z2 } = Y2, Q3 = J3.randomFn; if (Q3 === undefined) throw new I("explodeSequence", "randomFn function required for explodeSequence modifier"); let G3 = (H3) => L3(H3, Q3) + 1, z3 = []; for (let H3 of $) { if (H3 !== Z2) continue; let W2 = c$(K3, G3); z3.push(...W2); } return { rolls: [...$, ...z3] }; } }; function _3($) { return { mutatesRolls: false, apply: (K3, J3) => ({ rolls: K3, transformTotal: (Y2) => $(Y2, J3) }) }; } var Y$ = { ...z2, ..._3(($, K3) => Math.trunc($ / K3)) }; function v3($, K3, J3) { let Y2 = $.map((Z2, Q3) => ({ value: Z2, index: Q3 })); if (J3 === "lowest") Y2.sort((Z2, Q3) => Z2.value - Q3.value); else Y2.sort((Z2, Q3) => Q3.value - Z2.value); return new Set(Y2.slice(0, K3).map((Z2) => Z2.index)); } var G$ = { ...U, apply: ($, K3) => { let { highest: J3, lowest: Y2 } = K3, Z2 = $.length; if (J3 !== undefined) { let Q3 = Z2 - J3; if (Q3 <= 0) return { rolls: $ }; let G3 = v3($, Q3, "lowest"); return { rolls: $.filter((z3, H3) => !G3.has(H3)) }; } if (Y2 !== undefined) { let Q3 = Z2 - Y2; if (Q3 <= 0) return { rolls: $ }; let G3 = v3($, Q3, "highest"); return { rolls: $.filter((z3, H3) => !G3.has(H3)) }; } return { rolls: $ }; }, validate: ($, { quantity: K3 }) => { if ($.highest !== undefined) { if ($.highest > K3 || $.highest < 1) throw new I("keep", `Cannot keep ${$.highest} highest dice from a pool of ${K3}`, { path: "modifiers.keep.highest", value: $.highest }); } if ($.lowest !== undefined) { if ($.lowest > K3 || $.lowest < 1) throw new I("keep", `Cannot keep ${$.lowest} lowest dice from a pool of ${K3}`, { path: "modifiers.keep.lowest", value: $.lowest }); } } }; var j$ = { ...Z, ..._3(($, K3) => $ - K3) }; var z$ = { ...P, ..._3(($, K3) => $ % K3) }; var X$ = { ...X, ..._3(($, K3) => $ * K3) }; var k$ = { ...H2, ..._3(($, K3) => $ * K3) }; var U$ = { ...Y, requiresRollFn: true, requiresParameters: true, apply: O2(D2.penetrate) }; var L$ = { ...c, ..._3(($, K3) => $ + K3) }; function C2($, K3) { let { greaterThan: J3, greaterThanOrEqual: Y2, lessThan: Z2, lessThanOrEqual: Q3 } = K3, G3 = u$(Y2, J3), z3 = d$(Q3, Z2); if (G3 !== undefined && z3 !== undefined && G3 > z3) throw new I($, `Impossible comparison: condition requires value >= ${G3} AND <= ${z3}`, { path: `modifiers.${$}`, value: K3 }); } function u$($, K3) { if ($ !== undefined) return $; if (K3 !== undefined) return K3 + 1; return; } function d$($, K3) { if ($ !== undefined) return $; if (K3 !== undefined) return K3 - 1; return; } var P$ = { ...G, apply: ($, K3) => { let J3 = Array.isArray(K3) ? K3 : [K3], Y2 = [], Z2 = (G3, z3) => { let { from: H3, to: W2 } = z3; return G3.map((j) => { if ((typeof H3 === "object" ? U2(j, H3) : j === H3) && j !== W2) return Y2.push({ from: j, to: W2 }), W2; return j; }); }; return { rolls: J3.reduce((G3, z3) => Z2(G3, z3), $), replacements: Y2 }; }, validate: ($) => { let K3 = Array.isArray($) ? $ : [$]; for (let { from: J3 } of K3) if (typeof J3 === "object") C2("replace", J3); } }; function I$($, K3, J3, Y2 = 0) { if (Y2 >= F2) return $; if (U2($, K3)) return I$(J3(), K3, J3, Y2 + 1); return $; } var F$ = { ...L, requiresRollFn: true, apply: ($, K3, J3) => { let { rollOne: Y2 } = p(J3), { max: Z2 } = K3, Q3 = [], G3 = []; for (let z3 of $) { if (Z2 !== undefined && G3.length >= Z2) { Q3.push(z3); continue; } let H3 = I$(z3, K3, Y2); if (H3 !== z3) G3.push({ from: z3, to: H3 }); Q3.push(H3); } return { rolls: Q3, replacements: G3 }; }, validate: ($, { sides: K3 }) => { if ($.exact) { for (let J3 of $.exact) if (J3 < 1 || J3 > K3) throw new I("reroll", `Reroll value ${J3} is outside valid range [1, ${K3}]`, { path: "modifiers.reroll.exact", value: J3 }); } C2("reroll", $); } }; var A$ = { ...v, apply: ($, K3) => { return { rolls: [...$].sort((Y2, Z2) => K3 === "desc" ? Z2 - Y2 : Y2 - Z2) }; } }; var S$ = { ...F, requiresRollFn: true, requiresParameters: true, apply: ($, K3, J3) => { let { rollOne: Y2, parameters: Z2 } = N2(J3), { sides: Q3, quantity: G3 } = Z2; if (G3 > Q3) throw new I("unique", "Cannot have more rolls than sides when unique is enabled", { path: "modifiers.unique", value: { quantity: G3, sides: Q3 } }); let z3 = new Set(typeof K3 === "object" ? K3.notUnique : []), H3 = (B3, k2) => { let b2 = (E4, c2) => { if (c2 >= F2) throw new I("unique", `Could not find a unique value after ${F2} attempts`); if (!k2.has(E4) && !z3.has(E4)) return E4; return b2(Y2(), c2 + 1); }; return b2(B3, 0); }, W2 = [], j = new Set, X3 = []; for (let B3 of $) { if (z3.has(B3)) { W2.push(B3); continue; } if (j.has(B3)) { let k2 = H3(B3, j); j.add(k2), W2.push(k2), X3.push({ from: B3, to: k2 }); continue; } j.add(B3), W2.push(B3); } return { rolls: W2, replacements: X3 }; }, validate: ($, { sides: K3, quantity: J3 }) => { let Y2 = typeof $ === "object" ? $.notUnique.length : 0, Z2 = J3 - Y2; if (Z2 > K3) throw new I("unique", `Cannot have ${Z2} unique values with only ${K3} sides`, { path: "modifiers.unique", value: $ }); } }; var w$ = { ...M, requiresRollFn: true, requiresParameters: true, apply: ($, K3, J3) => { let { rollOne: Y2, parameters: Z2 } = N2(J3), { sides: Q3 } = Z2; if ($.length === 0) return { rolls: [] }; let G3 = $.length - 1, z3 = $[G3]; if (z3 === undefined) return { rolls: $ }; if (z3 === Q3) { let H3 = [...$], W2 = T3(z3, Q3, Y2, P3, D2.compound); return H3[G3] = W2, { rolls: H3 }; } if (z3 === 1) { let H3 = $.slice(0, G3); if (H3.length === 0) return { rolls: [] }; let W2 = Math.max(...H3), j = H3.indexOf(W2); return { rolls: H3.filter((B3, k2) => k2 !== j) }; } return { rolls: [...$] }; } }; var A4 = Object.freeze([d, P$, F$, o2, n, U$, K$, w$, S$, t, G$, s2, X$, L$, j$, Y$, z$, A$, k$]); function O$($, K3) { return { modifier: $, options: K3, added: [], removed: [] }; } function f$($, K3, J3, Y2, Z2) { let Q3 = { modifier: $, options: K3 }; if (J3 === Y2) return { ...Q3, added: [], removed: [] }; if (J3.length === 0) return { ...Q3, added: [...Y2], removed: [] }; if (Y2.length === 0) return { ...Q3, added: [], removed: [...J3] }; let G3 = [...J3].sort((B3, k2) => B3 - k2), z3 = [...Y2].sort((B3, k2) => B3 - k2), H3 = [], W2 = [], j = { i: 0, j: 0 }; while (j.i < G3.length || j.j < z3.length) { let B3 = G3[j.i], k2 = z3[j.j]; if (B3 === undefined && k2 !== undefined) H3.push(k2), j.j++; else if (k2 === undefined && B3 !== undefined) W2.push(B3), j.i++; else if (B3 !== undefined && k2 !== undefined) if (B3 === k2) j.i++, j.j++; else if (B3 < k2) W2.push(B3), j.i++; else H3.push(k2), j.j++; } let X3 = { ...Q3, added: H3, removed: W2 }; if (Z2 !== undefined && Z2.length > 0) X3.replacements = Z2; return X3; } var p$ = new Map(A4.map(($) => [$.name, $])); var M3 = Object.freeze(A4.map(($) => $.name)); function r$($, K3, J3, Y2) { if (K3 === undefined) return { rolls: J3, log: null }; let Z2 = p$.get($); if (!Z2) throw new I($, `Unknown modifier type: ${$}`, { path: `modifiers.${$}`, value: K3 }); if (Z2.requiresRollFn && Y2.rollOne === undefined) throw new I($, `rollOne function required for ${$} modifier`); if (Z2.requiresParameters && Y2.parameters === undefined) throw new I($, `roll parameters required for ${$} modifier`); if (Z2.requiresRandomFn && Y2.randomFn === undefined) throw new I($, `randomFn function required for ${$} modifier`); let Q3 = [...J3]; try { let G3 = Z2.apply(J3, K3, Y2), z3 = Z2.mutatesRolls === false ? O$($, K3) : f$($, K3, Q3, G3.rolls, G3.replacements); if (G3.transformTotal) return { rolls: G3.rolls, log: z3, transformTotal: G3.transformTotal }; return { rolls: G3.rolls, log: z3 }; } catch (G3) { if (G3 instanceof Error) t