JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 5
  • Score
    100M100P100Q37312F
  • License ISC

CLI and SDK for tabletop RPG dice rolling

Package Exports

  • dice-table
  • dice-table/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (dice-table) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Dice Table

A powerful, fast, and secure dice rolling utility for tabletop RPGs. Works both as a CLI tool and an importable library for Node.js projects.

Features

  • Zero Dependencies - Core engine uses only Node.js built-ins
  • Cryptographic Randomness - Uses crypto.randomInt() for fair, secure rolls
  • Complete Notation Support - All standard tabletop RPG dice notation including shorthand
  • CLI & Library - Use from command line or integrate into your projects
  • Dual Output Modes - Human-readable and JSON output for applications
  • Comprehensive Error Handling - Helpful hints for humans, structured errors for apps
  • Fast & Lightweight - Optimized for high performance

Installation

Global CLI Installation

npm install -g dice-table

Library Installation

npm install dice-table

Quick Start

Command Line Usage

# Basic roll
dice roll 1d20

# Roll with modifier
dice roll 1d20+5

# Advantage roll (D&D 5e) - shorthand notation
dice roll 2d20kh

# Generate ability scores
dice roll 4d6kh3 --times 6

# Statistical analysis
dice stats 3d6 --iterations 10000

# JSON output for applications
dice roll 2d6+5 --json

Library Usage

const dice = require('dice-table');

// Simple roll
const result = dice.roll('2d6+5');
console.log(result.total); // 7-17

// Multiple rolls
const results = dice.rollMany('1d20+5', 6);

// Statistical analysis
const stats = dice.stats('4d6kh3', { iterations: 10000 });

// Error handling
if (result.valid) {
  console.log(`Rolled: ${result.total}`);
} else {
  console.error(`Error: ${result.error}`);
}

Dice Notation Reference

Basic Notation

Expression Description
1d6 Roll one six-sided die
2d20 Roll two twenty-sided dice
3d8+5 Roll three d8s and add 5
1d20-2 Roll one d20 and subtract 2

Keep/Drop Mechanics

Expression Description
2d20kh Roll 2d20, keep highest 1 (advantage - shorthand)
2d20kh1 Roll 2d20, keep highest 1 (advantage - explicit)
2d20kl1 Roll 2d20, keep lowest 1 (disadvantage)
4d6kh3 Roll 4d6, keep highest 3 (ability scores)
4d6dh1 Roll 4d6, drop highest 1
4d6dl1 Roll 4d6, drop lowest 1

Complex Expressions

Expression Description
1d20+1d8+5 Attack roll with weapon damage
2d20kh1+1d6+3 Advantage attack with sneak attack
3d6+2d4-1 Multiple dice types with modifier

Supported Die Types

  • Standard RPG Dice: d4, d6, d8, d10, d12, d20, d100

CLI Reference

Commands

dice roll <expression> [options]

Roll dice using standard RPG notation.

Options:

  • --times, -t <N> - Roll the expression N times (max: 1000)
  • --json - Output result in JSON format for applications
  • --help, -h - Show help for this command

Examples:

dice roll 1d20                 # Single d20
dice roll 2d6+5                # 2d6 with +5 modifier
dice roll 4d6kh3               # 4d6 keep highest 3
dice roll 2d20kh+5             # Advantage with modifier (shorthand)
dice roll 3d6 --times 6        # Roll 6 times for stats
dice roll 1d20+5 --json        # JSON output for apps

dice stats <expression> [options]

Analyze the statistical distribution of a dice expression.

Options:

  • --iterations <N> - Number of simulations (default: 10000, range: 100-100000)
  • --json - Output result in JSON format for applications
  • --help, -h - Show help for this command

Examples:

dice stats 3d6                 # Basic 3d6 analysis
dice stats 4d6kh3              # Ability score generation
dice stats 1d20+5 --iterations 50000  # High-precision analysis
dice stats 2d20kh --json       # JSON output for analysis

dice help [command]

Show help information.

Examples:

dice help                      # General help
dice help roll                 # Help for roll command
dice help stats                # Help for stats command

Error Handling

Dice Table provides comprehensive error handling for both human users and applications:

CLI Error Handling

# Human-readable errors with helpful hints
$ dice roll invalid
Error: Invalid dice expression format. Use format like "2d6", "1d20+5", or "4d6kh3"
Hint: Use format like "2d6", "1d20+5", or "4d6kh3"

# JSON errors for applications
$ dice roll invalid --json
{"success":false,"error":"Invalid dice expression format. Use format like \\"2d6\\", \\"1d20+5\\", or \\"4d6kh3\\"","hint":"Use format like \\"2d6\\", \\"1d20+5\\", or \\"4d6kh3\\""}

# Parameter validation
$ dice roll 1d20 --times -1
Error: --times must be at least 1, got: -1
Hint: Use a positive number: --times 5

Library Error Handling

const result = dice.roll('invalid expression');

if (result.valid) {
  console.log(`Result: ${result.total}`);
} else {
  console.error(`Error: ${result.error}`);
}

Library API

Core Functions

dice.roll(expression)

Execute a single dice roll.

const result = dice.roll('2d6+5');

// Result structure:
{
  expression: '2d6+5',
  dice: [
    { type: 'd6', value: 4, kept: true, dropped: false },
    { type: 'd6', value: 3, kept: true, dropped: false }
  ],
  modifier: 5,
  total: 12,
  details: '[4, 3] + 5 = 12',
  valid: true
}

// Error handling:
const invalid = dice.roll('invalid');
// Returns: { error: 'Error message', expression: 'invalid', valid: false }

dice.rollMany(expression, times)

Roll multiple times and return array of results.

const results = dice.rollMany('1d20+5', 6);
// Returns array of 6 roll results

// Error handling:
const invalid = dice.rollMany('bad', 5);
// Returns array with error objects if expression is invalid

dice.parse(expression)

Parse a dice expression without rolling.

const parsed = dice.parse('4d6kh3');

// Returns parsed structure:
{
  valid: true,
  expression: '4d6kh3',
  parts: [
    {
      count: 4,
      sides: 6,
      keep: { type: 'highest', count: 3 }
    }
  ]
}

dice.validate(expression)

Validate a dice expression.

const validation = dice.validate('2d20kh1');

// Returns:
{ valid: true }

// Or for invalid expressions:
{ valid: false, error: 'Error message' }

dice.stats(expression, options)

Get statistical analysis of a dice expression.

const stats = dice.stats('3d6', { iterations: 10000 });

// Returns comprehensive statistics:
{
  expression: '3d6',
  iterations: 10000,
  theoretical: { min: 3, max: 18 },
  actualRange: { min: 3, max: 18 },
  statistics: {
    mean: 10.5,
    median: 11,
    mode: 10,
    standardDeviation: 2.96
  },
  percentiles: {
    p5: 6,
    p25: 8,
    p50: 11,
    p75: 13,
    p95: 15
  }
}

Utility Functions

dice.rollCli(expression, options)

Roll dice and format for CLI display.

const output = dice.rollCli('2d6+5');
console.log(output);
// "Rolling 2d6+5: [4, 3] + 5 = 12"

dice.rollData(expression)

Roll dice and return structured data for APIs.

const data = dice.rollData('1d20+5');
// Returns clean data structure suitable for JSON APIs

Use Cases

Discord Bot

const dice = require('dice-table');

bot.on('message', msg => {
  if (msg.content.startsWith('!roll ')) {
    const expression = msg.content.slice(6);
    const result = dice.roll(expression);

    if (result.valid) {
      msg.reply(`🎲 ${result.details}`);
    } else {
      msg.reply(`${result.error}`);
    }
  }
});

Game Engine

const dice = require('dice-table');

class Character {
  rollAttack() {
    const result = dice.roll(`1d20+${this.attackBonus}`);
    return result.total >= this.target.ac;
  }

  rollDamage() {
    return dice.roll(`${this.weapon.damage}+${this.strengthMod}`);
  }

  rollAbilityScores() {
    return dice.rollMany('4d6kh3', 6);
  }

  // Advantage/disadvantage
  rollWithAdvantage() {
    return dice.roll('2d20kh'); // Shorthand notation
  }
}

Web API

const express = require('express');
const dice = require('dice-table');

app.post('/api/roll', (req, res) => {
  const { expression } = req.body;
  const result = dice.rollData(expression);
  res.json(result);
});

app.get('/api/stats/:expression', (req, res) => {
  const stats = dice.stats(req.params.expression);
  res.json(stats);
});

Campaign Management

const dice = require('dice-table');

// Generate NPC stats
function generateNPC() {
  const stats = dice.rollMany('4d6kh3', 6);
  const hp = dice.roll('8d8+16'); // For a high-level character

  return {
    abilities: stats.map(r => r.total),
    hitPoints: hp.total
  };
}

// Mass combat simulation
function simulateBattle(rounds = 10) {
  const results = [];

  for (let i = 0; i < rounds; i++) {
    const attack = dice.roll('1d20+8');
    const damage = attack.total >= 15 ? dice.roll('2d6+4') : null;
    results.push({ attack: attack.total, damage: damage?.total || 0 });
  }

  return results;
}

Advanced Features

Statistical Analysis

The stats function provides comprehensive analysis:

const analysis = dice.stats('4d6kh3', { iterations: 100000 });

console.log(`Mean: ${analysis.statistics.mean}`);
console.log(`Standard Deviation: ${analysis.statistics.standardDeviation}`);
console.log(`95th Percentile: ${analysis.percentiles.p95}`);

Input Validation

function safeRoll(expression) {
  const validation = dice.validate(expression);

  if (!validation.valid) {
    throw new Error(`Invalid dice expression: ${validation.error}`);
  }

  return dice.roll(expression);
}

Performance & Constraints

Performance

  • Single Roll: < 1ms
  • 10,000 Rolls: < 100ms
  • Complex Expression (2d20kh1+1d8+5): < 2ms
  • Statistical Analysis (10k iterations): < 500ms

Constraints & Limits

  • Dice Count: 1-999 dice per component
  • Die Sides: d4, d6, d8, d10, d12, d20, d100 only
  • Modifiers: -9999 to +9999
  • CLI Times: 1-1000 rolls
  • CLI Iterations: 100-100,000 for stats
  • Total Dice: Maximum 999 dice across all components

Memory Usage

  • Zero Dependencies: No external packages
  • Lightweight: Small package size
  • Efficient: Minimal memory footprint

Security

  • Cryptographic Randomness: Uses crypto.randomInt() for true randomness
  • Input Validation: All expressions validated before execution
  • No Eval: Parser doesn't use eval() or similar unsafe functions
  • Bounded: All inputs have reasonable limits to prevent abuse

Contributing

Development Setup

git clone https://github.com/yourusername/dice-table.git
cd dice-table
npm install
npm test

Running Tests

npm test                    # Run all tests
npm run test:parser         # Test parser only
npm run test:roller         # Test roller only
npm run test:cli            # Test CLI only

Project Structure

dice-table/
   index.js                # Library entry point
   cli.js                  # CLI entry point
   lib/                    # Core modules
      parser.js           # Expression parser
      roller.js           # Random number generation
      validator.js        # Input validation
      formatter.js        # Output formatting
      stats.js            # Statistical analysis
   package.json

Adding Features

  1. Add functionality to appropriate module in lib/
  2. Export new functions from index.js
  3. Add comprehensive tests
  4. Update documentation
  5. Submit pull request

Changelog

v1.0.0

  • Initial release
  • Complete dice notation support including shorthand (2d20kh)
  • CLI interface with dual output modes (human/JSON)
  • Library API with comprehensive error handling
  • Statistical analysis with Monte Carlo simulation
  • Cryptographic randomness using crypto.randomInt()
  • Parameter validation with helpful error messages

License

ISC License - see LICENSE file for details.

Support

For help and support:

  • Use dice --help for CLI usage
  • Use dice <command> --help for command-specific help
  • Check error messages for helpful hints
  • Review examples in this README

Dice Table - Roll with confidence. 🎲