dice_trio

The Unix philosophy applied to dice rolling: do one thing exceptionally well.

Package Version Hex Docs

A minimal, bulletproof dice rolling library for Gleam that focuses on standard dice notation with maximum API approachability.

Philosophy

dice_trio embodies the Unix philosophy - it does one thing (parse and roll standard dice expressions) and does it exceptionally well. No exotic mechanics, no complex features, just rock-solid dice math that game developers can depend on.

Features

Installation

gleam add dice_trio

Usage

Basic Rolling

import dice_trio

// Simple dice roll with your RNG function
let rng = fn(max) { // your random 1-to-max implementation }

dice_trio.roll("d6", rng)        // Ok(4)
dice_trio.roll("2d6+3", rng)     // Ok(11)
dice_trio.roll("d20-1", rng)     // Ok(14)

// Detailed rolling with individual die results
dice_trio.detailed_roll("2d6+3", rng)
// Ok(DetailedRoll(
//   basic_roll: BasicRoll(2, 6, 3),
//   individual_rolls: [4, 5],
//   total: 12
// ))

Recommended RNG Library

For production use, we recommend the prng library by Gleam core team member Jak (Giacomo Cavalieri). It’s extensively tested in our E2E test suite and provides excellent performance with cross-platform compatibility:

gleam add prng
import dice_trio
import prng/random

pub fn game_roll() {
  let rng_fn = fn(max: Int) {
    let generator = random.int(1, max)
    random.random_sample(generator)
  }

  dice_trio.roll("3d6+2", rng_fn)  // Ok(14)
}

Parsing Only

import dice_trio

// Parse dice expression into structured data
dice_trio.parse("2d6+3")
// Ok(BasicRoll(roll_count: 2, side_count: 6, modifier: 3))

dice_trio.parse("invalid")
// Error(MissingSeparator)

Error Handling

import dice_trio

dice_trio.roll("garbage", rng)
// Error(MissingSeparator)

dice_trio.roll("0d6", rng)  
// Error(InvalidCount("0"))

dice_trio.roll("d-5", rng)
// Error(InvalidSides("-5"))

API Reference

Types

pub type BasicRoll {
  BasicRoll(roll_count: Int, side_count: Int, modifier: Int)
}

pub type DetailedRoll {
  DetailedRoll(basic_roll: BasicRoll, individual_rolls: List(Int), total: Int)
}

pub type DiceError {
  MissingSeparator
  InvalidCount(String)
  InvalidSides(String)
  InvalidModifier(String)
  MalformedInput
}

Functions

roll(dice_expression: String, rng_fn: fn(Int) -> Int) -> Result(Int, DiceError)

Parses and rolls a dice expression, returning the total result.

parse(input: String) -> Result(BasicRoll, DiceError)

Parses dice expression into structured data without rolling.

detailed_roll(dice_expression: String, rng_fn: fn(Int) -> Int) -> Result(DetailedRoll, DiceError)

Parses and rolls a dice expression, returning detailed results with individual die values.

Supported Notation

ExpressionDescriptionExample Result
"d6"Single six-sided dieOk(4)
"2d6"Two six-sided diceOk(9)
"d6+2"Six-sided die plus 2Ok(6)
"d20-1"Twenty-sided die minus 1Ok(18)
"3d6+5"Three dice plus modifierOk(14)

Input Validation

dice_trio validates all input and provides clear error messages:

Performance

Validated under extreme conditions:

Testing

dice_trio has 60 comprehensive tests:

gleam test  # All tests should pass

Design Principles

Unix Philosophy

Do one thing exceptionally well. dice_trio handles standard dice notation and nothing else.

Maximum API Approachability

Game system modules should be simple to write:

pub fn attack_roll(modifier: Int) {
  dice_trio.roll("1d20+" <> int.to_string(modifier))
  |> handle_game_logic
}

RNG Injection Pattern

Bring your own randomness for testing, determinism, or custom distributions:

import prng/random

// Testing with fixed results
let test_rng = fn(_) { 3 }
dice_trio.roll("2d6", test_rng)  // Always returns Ok(6)

// Production with real randomness using prng
let prng_rng = fn(max: Int) {
  let generator = random.int(1, max)
  random.random_sample(generator)
}
dice_trio.roll("2d6", prng_rng)  // Real randomness

Ecosystem Vision

dice_trio is designed as the foundation for a modular ecosystem:

Each extension builds on the bulletproof core while maintaining focused responsibilities.

Development

gleam run   # Run the project
gleam test  # Run the tests (39 comprehensive tests)
gleam check # Type checking
gleam format # Code formatting

Contributing

This library follows strict TDD and focuses on reliability over features. Before adding functionality:

  1. Ensure it aligns with standard dice notation
  2. Add comprehensive tests (both unit and integration)
  3. Maintain zero external dependencies
  4. Preserve the simple, approachable API

dice_trio: The reliable foundation for dice-based game systems. 🎲

Further documentation can be found at https://hexdocs.pm/dice_trio.

Search Document