1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
//! Evaluation and rolling of D&D 5e die roll expressions.
//!
//! The `RollExpression` trait provides methods for dealing with the
//! various kinds of rolls. `Roll` provides the simplest text-in,
//! text-out interface for rolling expressions an printing the result
//! regardless of the type of roll.
//!
//! ```
//! use critfail::{RollExpression, Roll};
//!
//! let check = Roll::new("r-3").unwrap();
//! let check_outcome = check.roll();
//! print!("{}", check_outcome); // eg. "11"
//! print!("{:?}", check_outcome); // eg. "(14)-3"
//!
//! let damage = Roll::new("2d8+6").unwrap();
//! let damage_outcome = damage.roll();
//! print!("{}", damage_outcome); // eg. "13"
//! print!("{:?}", damage_outcome); // eg. "[2+5]+6"
//!
//! let attack = Roll::new("r+1?2d6+4").unwrap();
//! let attack_outcome = attack.roll();
//! print!("{}", attack_outcome); // eg. "10 ? 16"
//! print!("{:?}", attack_outcome); // eg. "(9)+1 ? [6+6]+4"
//! ```
//!
//! In order to handle the outcome of a `Roll` programatically, roll
//! expressions are split into `Check` rolls, `Damage` rolls, and
//! `Attack` rolls, each with their own outcome type which provides
//! methods for determining the score and makeup of the results for
//! each.
//!
//! # Features
//! * `wasm-bindgen`: Enable this when compiling for wasm32 targets, or
//!   random number generation won't work.
#![warn(missing_docs)]
#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(unused_variables, unused_mut)))
)]

#[macro_use]
extern crate lazy_static;

use std::fmt;
use std::str::FromStr;

mod attack;
mod check;
mod damage;
mod error;
mod modifier;
mod roll;
mod util;

pub use attack::{Attack, AttackOutcome, AttackOutcomeBuilder};
pub use check::{AdvState, Check, CheckOutcome, CheckOutcomeBuilder, CritScore};
pub use damage::{Damage, DamageOutcome, DamageOutcomeBuilder};
pub use error::ParseError;
pub(crate) use modifier::ModifiersOutcome;
pub use modifier::OutcomePart;
pub use roll::{Roll, RollOutcome};

/// The number type that is used when reporting the score of a roll
pub type Score = i32;
/// The number type that is used for specifying the number of sides on a
/// die
pub type Sides = i32;

/// Used for structs defining a set of dice that can be rolled.
pub trait RollExpression: Sized + FromStr<Err = ParseError> {
    /// The roll result type should implement both Display and Debug.
    /// Display should print out a consise result for the roll, and
    /// Debug should print out the details (eg the value for each rolled
    /// die).
    type Outcome: fmt::Display + fmt::Debug;

    /// Create a new roll expression by parsing the given string.
    fn new(expression: &str) -> Result<Self, ParseError> {
        expression.parse()
    }

    /// Roll the dice and return an outcome.
    fn roll(&self) -> Self::Outcome;

    // TODO: Add an error type for parsing rollexps
    // TODO: Add with_options() and builder() methods.
}