@randsum/dice
Version:
A flexible, type-safe dice roller for tabletop RPGs, game development, and probability simulations
159 lines (158 loc) • 3.23 kB
JavaScript
import { RandsumError } from '@randsum/core';
import { roll } from './roll';
import { coreSpreadRolls } from './utils/coreSpreadRolls';
import { generateNumericFaces } from './utils/generateNumericFaces';
class DieBase {
sides;
constructor(sides) {
this.sides = sides;
}
}
class NumericDieImpl extends DieBase {
type = 'numeric';
faces;
isCustom = false;
constructor(sides) {
super(sides);
this.faces = generateNumericFaces(sides);
}
roll(quantity = 1) {
const rolls = this.rollSpread(quantity);
return rolls.reduce((acc, roll) => acc + roll, 0);
}
rollSpread(quantity = 1) {
return coreSpreadRolls(quantity, this.sides, this.faces);
}
rollModified(quantity = 1, modifiers = {}) {
const options = { ...this.toOptions, quantity, modifiers };
return roll(options);
}
get toOptions() {
return {
quantity: 1,
sides: this.sides
};
}
}
class CustomDieImpl extends DieBase {
type = 'custom';
faces;
isCustom = true;
constructor(faces) {
if (!faces.length) {
throw new RandsumError('Custom die must have at least one face', 'INVALID_DIE_CONFIG', {
input: faces,
expected: 'Array with at least one face value'
}, [
'Provide at least one face value: ["H", "T"] for a coin',
'Use standard dice like D6 if you need numbered faces',
'Custom faces must be non-empty strings'
]);
}
super(faces.length);
this.faces = [...faces];
}
roll(quantity = 1) {
const rolls = this.rollSpread(quantity);
return rolls.join(', ');
}
rollSpread(quantity = 1) {
return coreSpreadRolls(quantity, this.sides, this.faces);
}
rollModified(quantity = 1, modifiers = {}) {
return roll({
...this.toOptions,
quantity,
modifiers
});
}
get toOptions() {
return {
quantity: 1,
sides: [...this.faces]
};
}
}
function D(arg) {
if (typeof arg === 'number') {
return new NumericDieImpl(arg);
}
else {
return new CustomDieImpl(arg);
}
}
export const D4 = D(4);
export const D6 = D(6);
export const D8 = D(8);
export const D10 = D(10);
export const D12 = D(12);
export const D20 = D(20);
export const D100 = D(100);
export const coin = D(['Heads', 'Tails']);
export const fudgeDice = D(['+', '+', '+', '-', ' ', ' ']);
const alphanumFaces = [
'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'
];
export const alphaNumDie = D(alphanumFaces);
export { D };