dice-table
v1.0.5
Published
CLI and SDK for tabletop RPG dice rolling
Maintainers
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-tableLibrary Installation
npm install dice-tableQuick 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 --jsonLibrary 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 appsdice 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 analysisdice help [command]
Show help information.
Examples:
dice help # General help
dice help roll # Help for roll command
dice help stats # Help for stats commandError 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 5Library 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 invaliddice.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 APIsUse 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 testRunning 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 onlyProject 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.jsonAdding Features
- Add functionality to appropriate module in
lib/ - Export new functions from
index.js - Add comprehensive tests
- Update documentation
- 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 --helpfor CLI usage - Use
dice <command> --helpfor command-specific help - Check error messages for helpful hints
- Review examples in this README
Dice Table - Roll with confidence. 🎲
