UNPKG

@randsum/roller

Version:

A flexible, type-safe dice roller for tabletop RPGs, game development, and probability simulations

4 lines (2 loc) 13.1 kB
var Lt=require("node:module");var{defineProperty:B,getOwnPropertyNames:Et,getOwnPropertyDescriptor:Ct}=Object,At=Object.prototype.hasOwnProperty;var Z=new WeakMap,qt=(t)=>{var o=Z.get(t),r;if(o)return o;if(o=B({},"__esModule",{value:!0}),t&&typeof t==="object"||typeof t==="function")Et(t).map((e)=>!At.call(o,e)&&B(o,e,{get:()=>t[e],enumerable:!(r=Ct(t,e))||r.enumerable}));return Z.set(t,o),o};var Ht=(t,o)=>{for(var r in o)B(t,r,{get:o[r],enumerable:!0,configurable:!0,set:(e)=>o[r]=()=>e})};var wt={};Ht(wt,{validateNotation:()=>$t,roll:()=>Tt,optionsToSidesFaces:()=>R,optionsToNotation:()=>N,optionsToDescription:()=>M,isDiceNotation:()=>y});module.exports=qt(wt);function W(t,{greaterThan:o,lessThan:r,exact:e}){if(e?.includes(t))return!0;if(o!==void 0&&t>o)return!0;if(r!==void 0&&t<r)return!0;return!1}function d(t){if(!t.length)return"";if(t.length===1)return`[${t[0]}]`;let o=t.map((e)=>`[${e}]`),r=o.pop();return`${o.join(" ")} and ${r}`}function D({greaterThan:t,lessThan:o,exact:r}){let e=[];if(r?.length)e.push(d(r));if(t!==void 0)e.push(`greater than [${t}]`);if(o!==void 0)e.push(`less than [${o}]`);return e}function h({greaterThan:t,lessThan:o,exact:r}){let e=[];if(r?.length)e.push(...r.map(String));if(t!==void 0)e.push(`>${t}`);if(o!==void 0)e.push(`<${o}`);return e}function P(t,{greaterThan:o,lessThan:r},e){let n=t;if(o!==void 0&&n>o)n=e??o;if(r!==void 0&&n<r)n=e??r;return n}function v({highest:t,lowest:o,greaterThan:r,lessThan:e,exact:n}){let i=[];if(t)if(t>1)i.push(`Drop highest ${t}`);else i.push("Drop highest");if(o)if(o>1)i.push(`Drop lowest ${o}`);else i.push("Drop lowest");if(n)i.push(`Drop ${d(n)}`);if(r!==void 0)i.push(`Drop greater than [${r}]`);if(e!==void 0)i.push(`Drop less than [${e}]`);return i}function tt({exact:t,greaterThan:o,lessThan:r,max:e}){let n=[];if(t)t.forEach((f)=>n.push(`${f}`));let i=[];if(o!==void 0)i.push(`greater than [${o}]`);if(r!==void 0)i.push(`less than [${r}]`);let s=d(n.map(Number)),p=i.join(" and "),a=[s,p].filter(Boolean).join(", ");if(!a)return[];let m=e!==void 0?` (up to ${e} times)`:"";return[`Reroll ${a}${m}`]}function ot(t){return(Array.isArray(t)?t:[t]).map(({from:r,to:e})=>{if(typeof r==="object")return`Replace ${D(r).join(" and ")} with [${e}]`;return`Replace [${r}] with [${e}]`})}var rt=new Map([["plus",(t)=>[`Add ${t}`]],["minus",(t)=>[`Subtract ${t}`]],["cap",(t)=>D(t).map((o)=>`No Rolls ${o}`)],["drop",(t)=>v(t)],["reroll",(t)=>tt(t)],["explode",()=>["Exploding Dice"]],["unique",(t)=>{if(typeof t==="boolean")return["No Duplicate Rolls"];return[`No Duplicates (except ${d(t.notUnique)})`]}],["replace",(t)=>ot(t)]]);function _(t,o){if(o===void 0)return;let r=rt.get(t);return r?r(o):void 0}function et({highest:t,lowest:o,greaterThan:r,lessThan:e,exact:n}){let i=[];if(t)i.push(t===1?"H":`H${t}`);if(o)i.push(o===1?"L":`L${o}`);let s=[];if(r!==void 0)s.push(`>${r}`);if(e!==void 0)s.push(`<${e}`);if(n)n.forEach((p)=>s.push(`${p}`));if(s.length>0)i.push(`D{${s.join(",")}}`);return i.length?i.join(""):void 0}function it(t){let o=h(t);if(!o.length)return;let r=t.max?`${t.max}`:"";return`R{${o.join(",")}}${r}`}function nt(t){let r=(Array.isArray(t)?t:[t]).map(({from:e,to:n})=>{if(typeof e==="object")return h(e).map((s)=>`${s}=${n}`).join(",");return`${e}=${n}`});return r.length?`V{${r.join(",")}}`:void 0}var st=new Map([["plus",(t)=>{let o=t;if(o<0)return`-${Math.abs(o)}`;return`+${o}`}],["minus",(t)=>`-${t}`],["cap",(t)=>{let o=h(t);return o.length?`C{${o.join(",")}}`:void 0}],["drop",(t)=>et(t)],["reroll",(t)=>it(t)],["explode",()=>"!"],["unique",(t)=>{if(typeof t==="boolean")return"U";return`U{${t.notUnique.join(",")}}`}],["replace",(t)=>nt(t)]]);function F(t,o){if(o===void 0)return;let r=st.get(t);return r?r(o):void 0}function pt(t,o){return t.map((r)=>P(r,o))}function mt(t,o){let{highest:r,lowest:e,greaterThan:n,lessThan:i,exact:s}=o,p=s?new Set(s):null,a=t.filter((m)=>{if(n!==void 0&&m>n)return!1;if(i!==void 0&&m<i)return!1;if(p?.has(m))return!1;return!0});if(r!==void 0||e!==void 0){let m=a.map((c,l)=>({roll:c,index:l}));m.sort((c,l)=>c.roll-l.roll);let f=new Set;if(e!==void 0)for(let c=0;c<Math.min(e,m.length);c++){let l=m[c];if(l)f.add(l.index)}if(r!==void 0)for(let c=m.length-1;c>=Math.max(0,m.length-r);c--){let l=m[c];if(l)f.add(l.index)}if(a=a.filter((c,l)=>!f.has(l)),e!==void 0&&r===void 0)a.sort((c,l)=>c-l)}return a}function at(t,{sides:o},r){let e=0;for(let i of t)if(i===o)e++;if(e===0)return t;let n=[...t];for(let i=0;i<e;i++)n.push(r());return n}function ft(t,o){let r=Array.isArray(o)?o:[o],e=[...t];for(let{from:n,to:i}of r)e=e.map((s)=>{if(typeof n==="object")return P(s,n,i);else return s===n?i:s});return e}function ct(t,o,r){let{max:e}=o,n=0;return t.map((i)=>{if(e!==void 0&&n>=e)return i;let s=lt(i,o,r);if(s!==i)n++;return s})}function lt(t,o,r,e=0){if(e>=99)return t;if(W(t,o))return lt(r(),o,r,e+1);return t}function ut(t,o,{sides:r},e){if(t.length>r)throw new Error("Cannot have more rolls than sides when unique is enabled");let n=typeof o==="object"?o.notUnique:[],i=new Set(n),s=new Set,p=[];for(let a of t)if(i.has(a)||!s.has(a))p.push(a),s.add(a);else{let m,f=0,c=r*10;do if(m=e(),f++,f>c){m=a;break}while(s.has(m)&&!i.has(m));p.push(m),s.add(m)}return p}function V(t){let o=new Map;for(let r of t)o.set(r,(o.get(r)??0)+1);return o}function O(t,o,r,e){let n={modifier:t,options:o};if(r===e)return{...n,added:[],removed:[]};if(r.length===0)return{...n,added:[...e],removed:[]};if(e.length===0)return{...n,added:[],removed:[...r]};let i=V(r),s=V(e),p=[],a=[],m=new Set([...r,...e]);for(let f of m){let c=i.get(f)??0,I=(s.get(f)??0)-c;if(I>0)for(let b=0;b<I;b++)p.push(f);else if(I<0)for(let b=0;b<Math.abs(I);b++)a.push(f)}return{...n,added:p,removed:a}}function x(t,o){return[...t,o]}var dt=new Map([["plus",(t,o)=>({rolls:t.rolls,simpleMathModifier:Number(o),logs:t.logs})],["minus",(t,o)=>({rolls:t.rolls,simpleMathModifier:-Number(o),logs:t.logs})],["cap",(t,o)=>{let r=[...t.rolls],e=pt(t.rolls,o),n=O("cap",o,r,e);return{rolls:e,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,n)}}],["drop",(t,o)=>{let r=[...t.rolls],e=mt(t.rolls,o),n=O("drop",o,r,e);return{rolls:e,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,n)}}],["reroll",(t,o,r)=>{if(!r)throw new Error("rollOne function required for reroll modifier");let e=[...t.rolls],n=ct(t.rolls,o,r),i=O("reroll",o,e,n);return{rolls:n,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,i)}}],["explode",(t,o,r,e)=>{if(!r||!e)throw new Error("rollOne and context required for explode modifier");let n=[...t.rolls],i=at(t.rolls,e,r),s=O("explode",o,n,i);return{rolls:i,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,s)}}],["unique",(t,o,r,e)=>{if(!r||!e)throw new Error("rollOne and context required for unique modifier");let n=[...t.rolls],i=ut(t.rolls,o,e,r),s=O("unique",o,n,i);return{rolls:i,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,s)}}],["replace",(t,o)=>{let r=[...t.rolls],e=ft(t.rolls,o),n=O("replace",o,r,e);return{rolls:e,simpleMathModifier:t.simpleMathModifier,logs:x(t.logs,n)}}]]);function K(t,o,r,e,n){if(o===void 0)return r;let i=dt.get(t);if(!i)throw new Error(`Unknown modifier type: ${t}`);return i(r,o,n,e)}var g=["cap","drop","replace","reroll","explode","unique","plus","minus"];var T=/[Hh](\d+)?/,$=/[Ll](\d+)?/,E=/[Dd]\{([^}]{1,50})\}/,C=/!/,A=/[Uu](\{([^}]{1,50})\})?/,q=/[Vv]\{([^}]{1,50})\}/,H=/[Rr]\{([^}]{1,50})\}(\d+)?/,L=/[Cc]\{([^}]{1,50})\}/,k=/\+(\d+)/,j=/-(\d+)/;function Rt(t){let o={},r=Array.from(t.matchAll(new RegExp(k.source,"g")));if(r.length>0){let n=r.reduce((i,s)=>i+Number(s[1]),0);o.plus=n}let e=Array.from(t.matchAll(new RegExp(j.source,"g")));if(e.length>0){let n=e.reduce((i,s)=>i+Number(s[1]),0);o.minus=n}return o}function gt(t){let o=t.match(L);if(!o)return{};let r={},e=o[1];if(!e)return{};let n=e.split(",").map((i)=>i.trim());for(let i of n)if(i.startsWith(">"))r.greaterThan=Number(i.slice(1));else if(i.startsWith("<"))r.lessThan=Number(i.slice(1));return{cap:r}}function yt(t){let o={},r=t.match(T);if(r)o.highest=r[1]?Number(r[1]):1;let e=t.match($);if(e)o.lowest=e[1]?Number(e[1]):1;let n=t.match(E);if(n){let i=n[1];if(i){let s=i.split(",").map((p)=>p.trim());for(let p of s)if(p.startsWith(">"))o.greaterThan=Number(p.slice(1));else if(p.startsWith("<"))o.lessThan=Number(p.slice(1));else if(/^\d+$/.test(p))o.exact??=[],o.exact.push(Number(p))}}return Object.keys(o).length>0?{drop:o}:{}}function ht(t){return C.test(t)?{explode:!0}:{}}function Ot(t){let o=t.match(q);if(!o)return{};let r=o[1];if(!r)return{};return{replace:r.split(",").map((i)=>i.trim()).map((i)=>{let[s,p]=i.split("=");if(!s||!p)return{from:0,to:0};let a;if(s.startsWith(">"))a={greaterThan:Number(s.slice(1))};else if(s.startsWith("<"))a={lessThan:Number(s.slice(1))};else a=Number(s);return{from:a,to:Number(p)}})}}function xt(t){let o=Array.from(t.matchAll(new RegExp(H.source,"g")));if(o.length===0)return{};let r={};for(let e of o){let n=e[1],i=e[2]?Number(e[2]):void 0;if(i)r.max=i;if(n){let s=n.split(",").map((p)=>p.trim());for(let p of s)if(p.startsWith(">"))r.greaterThan=Number(p.slice(1));else if(p.startsWith("<"))r.lessThan=Number(p.slice(1));else if(/^\d+$/.test(p))r.exact??=[],r.exact.push(Number(p))}}return Object.keys(r).length>0?{reroll:r}:{}}function Mt(t){let o=t.match(A);if(!o)return{};if(!o[2])return{unique:!0};return{unique:{notUnique:o[2].split(",").map((e)=>Number(e.trim()))}}}function z(t){return{...yt(t),...ht(t),...Mt(t),...Ot(t),...xt(t),...gt(t),...Rt(t)}}function G(t){if(!t)return[];return g.map((o)=>_(o,t[o])).flat().filter((o)=>typeof o==="string").filter((o)=>o.length>0)}function J(t){if(!t)return"";return g.map((o)=>F(o,t[o])).filter((o)=>typeof o==="string").join("")}function R({sides:t}){if(Array.isArray(t))return{sides:t.length,faces:t};return{sides:t}}function M(t){let{modifiers:o,quantity:r=1,arithmetic:e}=t,{sides:n,faces:i=[]}=R(t),p=`Roll ${r} ${n}-sided ${r===1?"die":"dice"}`,a=`Roll ${r} Dice with the following sides: ${i.join(", ")}`,m=G(o),f=e==="subtract"?"and Subtract the result":"";return[i.length?a:p,...m,f].filter(Boolean)}var u=/[+-]?\d+[Dd]\d+/;var kt=[u.source,T.source,$.source,E.source,C.source,A.source,q.source,H.source,L.source,k.source,j.source].join("|"),Q=new RegExp(kt,"g");function y(t){if(typeof t!=="string")return!1;let o=t.trim();if(!u.test(o))return!1;return o.replace(/\s/g,"").replaceAll(Q,"").length===0}function N(t){let{modifiers:o,quantity:r=1,arithmetic:e}=t,{sides:n}=R(t),i=e==="subtract"?"-":"",s=J(o),p=`${i}${r}d${n}${s}`;if(!y(p))throw new Error(`Invalid notation generated: ${p}`);return p}function X(t,o){let r=[];for(let[e,n]of o.entries()){let i=o[e+1];if(n.index===void 0)continue;let s;if(e===0)s=0;else{let m=o[e-1],f=m?Number(m.index)+m[0].length:0,c=t.slice(f,n.index),l=/([+-])/.exec(c);if(l?.[1])s=f+c.indexOf(l[1]);else s=n.index}let p=i?.index??t.length,a=t.slice(s,p).trim();if(a)r.push(a)}return r}function U(t){let o=t.trim(),r=o.match(u)?.at(0)??"",e=o.replace(r,""),[n,i=""]=r.split(/[Dd]/),s={quantity:Math.abs(Number(n)),arithmetic:Number(n)<0?"subtract":"add",sides:Number(i)};if(e.length===0)return s;return{...s,modifiers:z(e)}}var jt=new RegExp(u.source,"g");function w(t){let o=Array.from(t.matchAll(jt));if(o.length<=1)return[U(t)];return X(t,o).map(U)}function Nt(t){if(y(t))return[...w(t)];if(typeof t==="string"||typeof t==="number")return[{quantity:1,sides:Number(t)}];return[t]}function bt(t,o){return Nt(t).map((e,n)=>{let i=n===0?"":`-${n+1}`,{quantity:s=1,arithmetic:p="add",modifiers:a={},key:m=`Roll ${o}${i}`}=e;return{...e,...R(e),key:m,modifiers:a,quantity:s,arithmetic:p,argument:t,notation:N(e),description:M(e)}})}function S(t){return Math.random()*t|0}function Y(t,o){if(t<=0)return[];return Array.from({length:t},()=>S(o)+1)}function Dt({sides:t,quantity:o=1,modifiers:r={}},e){if(!g.some((m)=>r[m]!==void 0)){let m=Array.from(e,(f)=>Number(f));return{total:e.reduce((f,c)=>Number(f)+c,0),initialRolls:e,modifiedRolls:m,logs:[]}}let i=()=>S(t),s={sides:t,quantity:o},a={simpleMathModifier:0,rolls:Array.from(e,(m)=>Number(m)),logs:[]};for(let m of g)if(r[m]){let f=K(m,r[m],a,s,i);a.rolls=f.rolls,a.simpleMathModifier=f.simpleMathModifier,a.logs=f.logs}return{modifiedRolls:a.rolls,initialRolls:e,total:a.rolls.reduce((m,f)=>Number(m)+f,a.simpleMathModifier),logs:a.logs}}function Pt(t){let{sides:o,quantity:r=1,faces:e,arithmetic:n,description:i}=t,s=Y(r,o),p=n==="subtract",a=e?{customResults:s.map((f)=>e[f-1])}:{},m=Dt(t,s);return{...a,parameters:t,description:i,modifierHistory:m,rolls:m.modifiedRolls,appliedTotal:p?-m.total:m.total,total:m.total}}function Tt(...t){let r=t.flatMap((s,p)=>bt(s,p+1)).map((s)=>Pt(s)),e=r.reduce((s,p)=>{let a=p.parameters.arithmetic==="subtract"?-1:1;return s+p.total*a},0),n=r.every((s)=>s.customResults),i=r.flatMap((s)=>n?s.customResults??[]:s.rolls.map(String));return{rolls:r,result:i,total:e}}function $t(t){if(!y(t))return{valid:!1,argument:t};let o=w(t);return{valid:!0,argument:t,options:o,notation:o.map((r)=>N(r)),description:o.map((r)=>M(r))}} //# debugId=4161FEC724E1BB1164756E2164756E21