@randsum/dice
Version:
A flexible, type-safe dice roller for tabletop RPGs, game development, and probability simulations
2 lines (1 loc) • 5.22 kB
JavaScript
function W(R,A=0){if(R.every((N)=>typeof N==="number"))return R.reduce((N,K)=>N+K,A);return R.flat().join(", ")}function Y(R){return Math.random()*R|0}var $=new Map;function _(R){let A=Number(R);if($.has(A)){let K=$.get(A);if(K===void 0)throw new Error("Faces cache is empty");return K}let N=Array.from({length:A},(K,C)=>C+1);if(A<=100||[4,6,8,10,12,20,100].includes(A))$.set(A,N);return N}function X(R,A,N){let K=N??_(A),C=new Array(R);for(let E=0;E<R;E++){let H=Y(A),J=K[H];if(J)C[E]=J}return C}function z(){return Math.random().toString(36).substring(2,15)}import{CapModifier as G,DropModifier as v,ExplodeModifier as V,MinusModifier as w,PlusModifier as T,ReplaceModifier as D,RerollModifier as k,UniqueModifier as g,optionsConverter as O}from"@randsum/core";import{coreNotationPattern as S,isDiceNotation as b}from"@randsum/notation";function M(R){return R instanceof x}function Z(R){let A=U(R);return{argument:R,options:A,die:B(R),notation:O.toNotation(A),description:O.toDescription(A)}}function U(R){if(R instanceof x)return R.toOptions;if(b(R)){let N=(R.match(S)??"")[0],K=R.replace(N,""),[C,E=""]=N.split(/[Dd]/);if(E.includes("{"))return{quantity:Number(C),sides:[...E.replaceAll(/{|}/g,"")]};return{quantity:Number(C),sides:Number(E),...{modifiers:{...v.parse(K),...V.parse(K),...g.parse(K),...D.parse(K),...k.parse(K),...G.parse(K),...T.parse(K),...w.parse(K)}}}}if(Array.isArray(R))return{quantity:1,sides:R.map(String)};if(typeof R==="string"||typeof R==="number")return{quantity:1,sides:Number(R)};return R}function B(R){if(M(R))return R;let A=U(R);return new x(A.sides)}import{CapModifier as q,DropModifier as h,ExplodeModifier as P,ReplaceModifier as y,RerollModifier as f,UniqueModifier as m}from"@randsum/core";function p(R){return typeof R.sides==="number"}function F(R){let A=o(R.dicePools),N=u(R,A),K=Object.values(N);return{...R,rawRolls:A,modifiedRolls:N,rawResult:Object.values(A).flat(),result:K.map((C)=>C.rolls).flat(),type:n(R.dicePools),total:W(K.map((C)=>C.total))}}function n(R){let A=Object.values(R);if(A.every((N)=>typeof N.options.sides==="number"))return"numerical";if(A.every((N)=>Array.isArray(N.options.sides)))return"custom";return"mixed"}function c(R){return Array.isArray(R.options.sides)}function Q(R,A,N,K){let C=A[R];if(C===void 0)return N;switch(R){case"plus":return{...N,simpleMathModifier:C};case"minus":return{...N,simpleMathModifier:-C};case"reroll":return new f(A.reroll).apply(N,void 0,K.rollOne);case"unique":return new m(A.unique).apply(N,{sides:K.sides,quantity:K.quantity},K.rollOne);case"replace":return new y(A.replace).apply(N);case"cap":return new q(A.cap).apply(N);case"drop":return new h(A.drop).apply(N);case"explode":return new P(A.explode).apply(N,{sides:K.sides,quantity:K.quantity},K.rollOne);default:throw new Error(`Unknown modifier: ${String(R)}`)}}function u(R,A){let N={};for(let[K,C]of Object.entries(R.dicePools)){let E=A[K]??[];if(c(C)){N[K]={total:W(E),rolls:E};continue}let{sides:H,quantity:J=1,modifiers:t={}}=C.options;if(Object.keys(t).length===0){N[K]={total:W(E),rolls:E};continue}let L=()=>Y(H),j={simpleMathModifier:0,rolls:E};if(t.reroll)j=Q("reroll",t,j,{sides:H,quantity:J,rollOne:L});if(t.replace)j=Q("replace",t,j,{sides:H,quantity:J,rollOne:L});if(t.cap)j=Q("cap",t,j,{sides:H,quantity:J,rollOne:L});if(t.explode)j=Q("explode",t,j,{sides:H,quantity:J,rollOne:L});if(t.unique)j=Q("unique",t,j,{sides:H,quantity:J,rollOne:L});if(t.drop)j=Q("drop",t,j,{sides:H,quantity:J,rollOne:L});if(t.plus)j=Q("plus",t,j,{sides:H,quantity:J,rollOne:L});if(t.minus)j=Q("minus",t,j,{sides:H,quantity:J,rollOne:L});N[K]={rolls:j.rolls,total:W(j.rolls,j.simpleMathModifier)}}return N}function o(R){let A={};for(let[N,K]of Object.entries(R)){let{options:C}=K,E=C.quantity??1;if(p(C))A[N]=X(E,C.sides);else A[N]=X(E,C.sides.length,C.sides)}return A}function I(...R){let A={dicePools:Object.fromEntries(R.map((N)=>[z(),Z(N)]))};return F(A)}class x{sides;faces;type;isCustom;constructor(R){if(typeof R==="number"){if(!Number.isInteger(R)||R<1)throw new Error("Die must have at least one side with a positive integer value");this.sides=R,this.faces=_(R),this.type="numerical",this.isCustom=!1}else{if(!R.length)throw new Error("Custom die must have at least one face");this.sides=R.length,this.faces=[...R],this.type="custom",this.isCustom=!0}}roll(R=1){let A=this.rollSpread(R);if(this.type==="numerical")return A.reduce((N,K)=>N+K,0);return A.join(", ")}rollSpread(R=1){return X(R,this.sides,this.faces)}rollModified(R=1,A={}){return I({...this.toOptions,quantity:R,modifiers:A})}get toOptions(){if(this.type==="numerical")return{quantity:1,sides:this.sides};return{quantity:1,sides:[...this.faces]}}}var i=new x(4),l=new x(6),d=new x(8),r=new x(10),a=new x(12),s=new x(20),e=new x(100),RR=new x(["Heads","Tails"]),AR=new x(["+","+","+","-"," "," "]),NR=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9"],KR=new x(NR);export{I as roll,AR as fudgeDice,RR as coin,KR as alphaNumDie,d as D8,l as D6,i as D4,s as D20,a as D12,e as D100,r as D10,x as D};