UNPKG

@randsum/dice

Version:

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

243 lines (242 loc) 9.86 kB
import { CustomRollOptions as CustomRollOptions3, ModifierOptions as ModifierOptions3, NumericRollOptions as NumericRollOptions3 } from "@randsum/core"; import { CustomRollOptions, ModifierOptions, NumericRollOptions } from "@randsum/core"; import { CustomDiceNotation, NumericDiceNotation } from "@randsum/notation"; import { RollOptions } from "@randsum/core"; interface BaseD<T extends number | string[]> { readonly sides: number; readonly faces: T extends number ? number[] : string[]; readonly type: T extends number ? "numerical" : "custom"; readonly isCustom: T extends number ? false : true; roll: (quantity?: number) => T extends number ? number : string; rollSpread: (quantity?: number) => T extends number ? number[] : string[]; rollModified: (quantity: number, modifiers?: ModifierOptions) => T extends number ? NumericRollResult : CustomRollResult; toOptions: T extends number ? NumericRollOptions : CustomRollOptions; } type NumericRollArgument = BaseD<number> | NumericRollOptions | NumericDiceNotation | number | `${number}`; type CustomRollArgument = BaseD<string[]> | CustomRollOptions | CustomDiceNotation | string[]; type RollArgument = NumericRollArgument | CustomRollArgument; interface BaseRollParams { description: string[]; } interface NumericRollParams extends BaseRollParams { argument: NumericRollArgument; options: NumericRollOptions; die: BaseD<number>; notation: NumericDiceNotation; } interface CustomRollParams extends BaseRollParams { argument: CustomRollArgument; options: CustomRollOptions; die: BaseD<string[]>; notation: CustomDiceNotation; } type RollParams = NumericRollParams | CustomRollParams; interface DicePool<P extends RollParams = RollParams> { dicePools: Record<string, P>; } interface BaseRollResult<P extends RollParams = RollParams> extends DicePool<P> { rawResult: (number | string)[]; type: "numerical" | "custom" | "mixed"; rawRolls: Record<string, number[] | string[]>; modifiedRolls: Record<string, { rolls: string[] | number[] total: string | number }>; result: (string | number)[]; total: string | number; } interface NumericRollResult extends BaseRollResult<NumericRollParams> { type: "numerical"; rawRolls: Record<string, number[]>; rawResult: number[]; modifiedRolls: Record<string, { rolls: number[] total: number }>; result: number[]; total: number; } interface CustomRollResult extends BaseRollResult<CustomRollParams> { type: "custom"; rawRolls: Record<string, string[]>; rawResult: string[]; modifiedRolls: Record<string, { rolls: string[] total: string }>; result: string[]; total: string; } interface MixedRollResult extends BaseRollResult { type: "mixed"; rawRolls: Record<string, number[] | string[]>; modifiedRolls: Record<string, { rolls: string[] | number[] total: string | number }>; result: (string | number)[]; total: string; } type RollResult = NumericRollResult | CustomRollResult | MixedRollResult; declare class D<T extends number | string[]> implements BaseD<T> { /** * Number of sides on the die * * For numeric dice, this is the highest possible roll value. * For custom dice, this is the number of unique faces. */ readonly sides: number; /** * Array of all possible face values * * For numeric dice, this is an array of numbers from 1 to sides. * For custom dice, this is the array of string values provided at creation. */ readonly faces: T extends number ? number[] : string[]; /** * Type of die: 'numerical' for standard dice, 'custom' for string-faced dice * * This property helps determine how rolls should be processed and displayed. */ readonly type: T extends number ? "numerical" : "custom"; /** * Whether this is a custom die with string faces * * Convenience boolean property that's true for custom dice, false for numeric dice. */ readonly isCustom: T extends number ? false : true; /** * Creates a new die instance * * @param arg - For numeric dice, the number of sides (e.g., 6 for a d6). * For custom dice, an array of string faces (e.g., ['Heads', 'Tails'] for a coin). * @throws {Error} If a numeric die has less than 1 side or a non-integer number of sides * @throws {Error} If a custom die has no faces */ constructor(arg: T); roll(quantity?: number): T extends number ? number : string; /** * Rolls the die multiple times and returns an array of individual results * * Unlike roll(), this method returns the individual values of each die rolled * rather than combining them into a sum or string. * * @param quantity - Number of dice to roll (default: 1) * @returns Array of individual roll results * * @example * // Roll 3d6 and get individual results * const d6 = new D(6); * const results = d6.rollSpread(3); // Returns e.g., [4, 2, 6] * * @example * // Roll a custom die multiple times * const colorDie = new D(['Red', 'Green', 'Blue']); * const results = colorDie.rollSpread(2); // Returns e.g., ['Red', 'Blue'] */ rollSpread(quantity?: number): T extends number ? number[] : string[]; /** * Rolls the die with modifiers and returns a detailed result object * * This method provides access to the full range of dice modifiers and returns * a comprehensive result object with detailed information about the roll. * * @param quantity - Number of dice to roll (default: 1) * @param modifiers - Modifiers to apply to the roll (default: {}) * @returns Detailed roll result object * * @example * // Roll with advantage (drop lowest) * const d20 = new D(20); * const result = d20.rollModified(2, { drop: { lowest: 1 } }); * * @example * // Roll with exploding dice * const d6 = new D(6); * const result = d6.rollModified(3, { explode: true }); */ rollModified(quantity?: number, modifiers?: ModifierOptions3): T extends number ? NumericRollResult : CustomRollResult; /** * Converts the die to roll options format * * This getter returns an options object that can be used with the roll() function. * It's useful for creating complex rolls or when you need to manipulate the * options before rolling. * * @returns Roll options object for this die * * @example * // Get options for a d20 * const d20 = new D(20); * const options = d20.toOptions; * // Result: { quantity: 1, sides: 20 } * * @example * // Use options with roll function * import { roll } from '@randsum/dice'; * const d6 = new D(6); * const options = { ...d6.toOptions, quantity: 3, modifiers: { plus: 2 } }; * const result = roll(options); // Roll 3d6+2 */ get toOptions(): T extends number ? NumericRollOptions3 : CustomRollOptions3; } /** * A four-sided die (tetrahedron) * Commonly used in tabletop RPGs for small damage values */ declare const D4: BaseD<number>; /** * A six-sided die (cube) * The most common die type, used in many games */ declare const D6: BaseD<number>; /** * An eight-sided die (octahedron) * Often used for medium weapon damage in tabletop RPGs */ declare const D8: BaseD<number>; /** * A ten-sided die (pentagonal trapezohedron) * Used in many RPGs and for percentile rolls when paired with another D10 */ declare const D10: BaseD<number>; /** * A twelve-sided die (dodecahedron) * Used in many RPGs for larger weapons and special abilities */ declare const D12: BaseD<number>; /** * A twenty-sided die (icosahedron) * The iconic die for Dungeons & Dragons and many other RPGs * Used for attack rolls, saving throws, and skill checks */ declare const D20: BaseD<number>; /** * A percentile die (simulated with two D10s) * Used for percentage checks and random tables * Generates a number between 1-100 */ declare const D100: BaseD<number>; /** * A two-sided coin with "Heads" and "Tails" faces * Used for binary decisions or simple 50/50 probability */ declare const coin: BaseD<string[]>; /** * Fudge/Fate dice with plus, minus, and blank faces * Used in Fate RPG system and its derivatives * Has 3 '+' faces, 2 blank faces, and 1 '-' face */ declare const fudgeDice: BaseD<string[]>; /** * A 62-sided die with all alphanumeric characters * Contains uppercase letters (A-Z), lowercase letters (a-z), and digits (0-9) * Useful for generating random characters, IDs, or for games requiring letter/number selection */ declare const alphaNumDie: BaseD<string[]>; declare function roll(...args: NumericRollArgument[]): NumericRollResult; declare function roll(...args: CustomRollArgument[]): CustomRollResult; declare function roll(...args: (NumericRollArgument | CustomRollArgument)[]): RollResult; import { BaseRollOptions, ComparisonOptions as ComparisonOptions2, CustomRollOptions as CustomRollOptions4, DropOptions as DropOptions2, ModifierOptions as ModifierOptions4, NumericRollOptions as NumericRollOptions4, ReplaceOptions as ReplaceOptions2, RerollOptions as RerollOptions2, UniqueOptions as UniqueOptions2 } from "@randsum/core"; import { CustomDiceNotation as CustomDiceNotation3, CustomValidationResult, DiceNotation as DiceNotation2, InvalidValidationResult, NumericDiceNotation as NumericDiceNotation3, NumericValidationResult, ValidationResult } from "@randsum/notation"; export { roll, fudgeDice, coin, alphaNumDie, ValidationResult, UniqueOptions2 as UniqueOptions, RollResult, RollParams, RollOptions, RollArgument, RerollOptions2 as RerollOptions, ReplaceOptions2 as ReplaceOptions, NumericValidationResult, NumericRollResult, NumericRollParams, NumericRollOptions4 as NumericRollOptions, NumericRollArgument, NumericDiceNotation3 as NumericDiceNotation, ModifierOptions4 as ModifierOptions, MixedRollResult, InvalidValidationResult, DropOptions2 as DropOptions, DicePool, DiceNotation2 as DiceNotation, D8, D6, D4, D20, D12, D100, D10, D, CustomValidationResult, CustomRollResult, CustomRollParams, CustomRollOptions4 as CustomRollOptions, CustomRollArgument, CustomDiceNotation3 as CustomDiceNotation, ComparisonOptions2 as ComparisonOptions, BaseRollOptions, BaseD };