4 stable releases
1.1.1 | Oct 9, 2023 |
---|---|
1.0.1 | Oct 9, 2023 |
#474 in Text processing
Used in twas
31KB
544 lines
DiceXp - The RPG Dice eXpression interpreter
DiceXp is a library and command-line interface (CLI) app for parsing and rolling role-playing game style dice notations (e.g. "2d8+5").
There are two components to this crate: the CLI app and the library module. The CLI app can be installed with cargo install dicexp --features app
and then used in the terminal to roll dice. The library provides a DiceBag
struct which you initialize with a random number generator (RNG) from the rand crate and then call DiceBag.eval(...)
on each dice expression you wish to evaluate.
Roll dice with standard RPG dice notation
DiceXp supports standard RPG dice notation, such as "1d20+3" or "3d6", where the number in front of the 'd' is the number of dice to roll and the number after the 'd' is the number of sides per die. You can use as many different kinds of dice as you like, such as "1d4+1d6+1d8-1d12".
Arithmetic (+, -, *, /)
DiceXp supports basic arithmetic, specifically addition (+), subtraction (-), multiplication (* or x), and division (/). Note that division is integer division, (unless computing the average, see below), meaning that it always rounds down to a whole number. DiceXp also supports nested parentheses. Thus all of the following are valid dicexp
expressions:
- "1d4*1d20"
- "-3*(1+2)"
- "(1d10+5)x10+(1d20-10)"
- "4d6/10-5"
- "4(9(10/2-6-3x8+1x4/2)x8/2x5+4)x5+4(7+7-3x8)x3-10x(10)-1"
Average, min, and max values
When DiceXp evaluates a dice expression, it also computes what the statistical mean average result of the dice rolls would be, as well as the largest and smallest possible values (ie what if all dice rolled their maximum value or rolled all 1's).
Alternatives to DiceXp
DiceXp was designed for standard dice notation and designed to handle relatively complex mathematical dice formulas. It does not support all RPG systems or dice rolling mechanics (eg roll two dice and keep the higher one). The best alternative to DiceXp is the ndm crate, which better supports table-top RPGs. Here's a side-by-side feature comparison to ndm:
Feature | DiceXp | ndm |
---|---|---|
CLI App | ✔ | ✔ |
Roll standard dice | ✔ | ✔ |
Add and substract | ✔ | ✔ |
Multiply | ✔ | ~ |
Divide | ✔ | |
Nested parentheses | ✔ | |
Exploding dice | ✔ | |
Keep N highest/lowest | ✔ | |
Average, min, and max | ✔ |
*~ ndm can only multiply dice by constants, not by other dice*
DiceXp CLI App
The dicexp
CLI app evaluates dice expressions provided as arguments on the commandline. For example:
$ dicexp 1d6x10+1d10
>>> 1d6x10+1d10 => 64
Multiple expressions may be provided at once:
$ dicexp 1d6 1d6 1d6 1d6
>>> 1d6 => 2
>>> 1d6 => 5
>>> 1d6 => 3
>>> 1d6 => 1
You can also print the range of possible values for the dice expressions with the -r/--range
option and the average result with the -a/--average
option:
$ dicexp -a -r 3d6
>>> 3d6 => 12 (3-18, 10.5 ave.)
Installation
To install the dicexp
app, simply run the following command:
cargo install dicexp --features app
Usage
dicexp [OPTIONS] [DICE_EXPRESSIONS]...
Options
-a
,--average
: Show the average result for each dice expression-r
,--range
: Show the minimum and maximum possible result for each dice expression-q
,--quiet
: Show only the roll results and nothing more (incompatible with-a/--average
and-r/--range
)-s
,--seed
: Optional seed for random number generator-h
,--help
: Print help-V
,--version
: Print version
DiceXp Rust Library
The DiceXp library module provides three structs: DiceBag
, DiceRoll
, and SyntaxError
. It also provides two utility functions to simplify instantiating a new RNG: simple_rng(u64) -> StdRng
and new_simple_rng() -> StdRng
.
Struct DiceBag
Most of the time, you only need to use the DiceBag
struct. DiceBag
is instantiated with the RNG of your choice via DiceBag::new(Rng)
and then is ready to use. To evaluate a dice expression, use the eval(&str)
method, or to only evaluate the min, max, or average result, use the matching eval_...(&str)
method.
Struct DiceRoll
This is returned by DiceBag.eval(&str)
and holds the rolled total, as well as the min, max, and average for the expression.
Struct SyntaxError
This error type is the Err()
result whenever a DiceBag
method fails to evaluate a dice expression.
Examples
Roll dice from user input
This example prompts the user to enter a dice expression, then evaluates it. If the roll total is greater than the expected average, it tells prints "That's a good roll!", but if not then it prints "That's not a good roll :("
fn main() {
use dicexp::{DiceBag, new_simple_rng};
use std::io;
let mut dice_bag = DiceBag::new(new_simple_rng());
println!("What would you like to roll? ");
let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("failed to read from stdin");
let dice_roll = dice_bag.eval(input.as_str()).expect("invalid dice expression");
println!("You rolled a {}", dice_roll);
if dice_roll.total >= dice_roll.average as i64 {
println!("That's a good roll!");
} else {
println!("That's not a good roll :(");
}
}
Calculate average damage for various D&D weapons
This example compares the average damage for various weapons from the table-top RPG Dungeons & Dragons (aka D&D).
fn main() {
use dicexp::{DiceBag, new_simple_rng};
let mut dice_bag = DiceBag::new(new_simple_rng());
let armory = vec![
("great axe", "1d12"),
("great sword", "2d6"),
("heavy crossbow", "1d10+2"),
("firebolt", "1d10"),
("magic missile", "3d4+3")
];
println!("Average Damage:");
for (name, dmg) in armory {
println!("{}\t{}", dice_bag.eval_ave(dmg).unwrap(), name)
}
}
Dependencies
~0.4–9MB
~93K SLoC