Skip to content

Commit

Permalink
Add more details to some dice documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Gawdl3y committed Mar 12, 2024
1 parent af02e11 commit 4c98d48
Showing 1 changed file with 53 additions and 35 deletions.
88 changes: 53 additions & 35 deletions src/dice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use fastrand::Rng;

use crate::term::Describe;

/// A single set of rollable dice and a collection of modifiers to apply to any [Rolled] results produced by it.
/// `Dice` are a single set of one or more rollable dice of a specific number of sides,
/// along with a collection of modifiers to apply to any resulting rolls from them.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Dice {
/// Number of dice to roll
Expand All @@ -18,12 +19,12 @@ pub struct Dice {
}

impl Dice {
/// Rolls the dice using the default Rng
/// Rolls the dice and applies all of its modifiers to the rolls using the default Rng.
pub fn roll(&self) -> Result<Rolled, Error> {
self.roll_using_rng(&mut Rng::new())
}

/// Rolls the dice with the given Rng
/// Rolls the dice and applies all of its modifiers to the rolls using the given Rng.
pub fn roll_using_rng(&self, rng: &mut Rng) -> Result<Rolled, Error> {
// Roll the dice!
let mut rolls = Vec::with_capacity(self.count as usize);
Expand All @@ -40,22 +41,28 @@ impl Dice {
Ok(rolls)
}

/// Rolls a single die of this type with no modifiers using the default Rng
/// Rolls a single die (with the same number of sides as the dice in this set)
/// with no modifiers using the default Rng.
#[must_use]
pub fn roll_single(&self) -> DieRoll {
DieRoll::new_rand(self.sides)
}

/// Rolls a single die of this type with no modifiers using the given Rng
/// Rolls a single die (with the same number of sides as the dice in this set)
/// with no modifiers using the given Rng.
#[must_use]
pub fn roll_single_using_rng(&self, rng: &mut Rng) -> DieRoll {
DieRoll::new_rand_using_rng(self.sides, rng)
}

/// Gets a new set of Dice matching this one but without any modifiers
/// Creates a new set of dice matching this one but without any modifiers.
#[must_use]
pub fn plain(&self) -> Self {
Self::new(self.count, self.sides)
}

/// Creates a new set of dice with a given count and number of sides
/// Creates a new set of dice with a given count and number of sides.
#[must_use]
pub fn new(count: u8, sides: u8) -> Self {
Self {
count,
Expand All @@ -64,7 +71,8 @@ impl Dice {
}
}

/// Creates a new dice builder
/// Creates a new dice builder.
#[must_use]
pub fn builder() -> Builder {
Builder::default()
}
Expand Down Expand Up @@ -92,7 +100,8 @@ impl fmt::Display for Dice {
}
}

/// A modifier that can be applied to a set of [Dice] to manipulate resulting [Rolled] dice sets from them
/// A `Modifier` is a routine that can be applied to a set of [Dice] to automatically manipulate resulting
/// [Rolled] dice sets from them as a part of their rolling process.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Modifier {
/// Rerolls (drops original and adds a newly-rolled die) dice that meet a condition.
Expand Down Expand Up @@ -136,12 +145,12 @@ pub enum Modifier {
}

impl Modifier {
/// Applies the modifier to a set of rolls using the default Rng where needed
/// Applies the modifier to a set of rolls using the default Rng where needed.
pub fn apply<'rolled, 'modifier: 'rolled>(&'modifier self, rolls: &mut Rolled<'rolled>) -> Result<(), Error> {
self.apply_using_rng(rolls, &mut Rng::new())
}

/// Applies the modifier to a set of rolls using a given Rng where needed
/// Applies the modifier to a set of rolls using a given Rng where needed.
pub fn apply_using_rng<'rolled, 'modifier: 'rolled>(
&'modifier self,
rolled: &mut Rolled<'rolled>,
Expand Down Expand Up @@ -309,7 +318,7 @@ impl fmt::Display for Modifier {
}
}

/// Conditions that die values can be tested against
/// A `Condition` is a test that die values can be checked against.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Condition {
Eq(u8),
Expand All @@ -320,7 +329,7 @@ pub enum Condition {
}

impl Condition {
/// Creates a Condition from its corresponding symbol and a value
/// Creates a condition from its corresponding symbol and a given value.
pub fn from_symbol_and_val(symbol: &str, val: u8) -> Result<Self, Error> {
Ok(match symbol {
"=" => Self::Eq(val),
Expand All @@ -332,7 +341,7 @@ impl Condition {
})
}

/// Checks a value against the condition
/// Checks a value against the condition.
pub fn check(&self, val: u8) -> bool {
match self {
Self::Eq(expected) => val == *expected,
Expand All @@ -343,7 +352,7 @@ impl Condition {
}
}

/// Gets the symbol that represents this condition
/// Gets the symbol that represents the condition.
pub fn symbol(&self) -> &'static str {
match self {
Self::Eq(..) => "=",
Expand Down Expand Up @@ -372,31 +381,34 @@ impl fmt::Display for Condition {
}
}

/// Represents a single rolled die
/// A `DieRoll` is a single die resulting from rolling [Dice] and optionally applying modifiers.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct DieRoll<'a> {
/// Value that was rolled
pub val: u8,

/// Modifier that caused the addition of this die
/// Modifier that caused the addition of this die, if any
pub added_by: Option<&'a Modifier>,

/// Modifier that caused the drop of this die
/// Modifier that caused the drop of this die, if any
pub dropped_by: Option<&'a Modifier>,
}

impl DieRoll<'_> {
/// Checks whether this die roll was part of the original set, not from a modifier
/// Indicates whether this die roll was part of the original set (not added by a modifier).
#[inline]
pub fn is_original(&self) -> bool {
self.added_by.is_none()
}

/// Checks whether this die roll has been dropped by a modifier
/// Indicates whether this die roll was been dropped by a modifier.
#[inline]
pub fn is_dropped(&self) -> bool {
self.dropped_by.is_some()
}

/// Creates a new DieRoll with the given value
/// Creates a new DieRoll with the given value.
#[must_use]
pub fn new(val: u8) -> Self {
Self {
val,
Expand All @@ -405,13 +417,15 @@ impl DieRoll<'_> {
}
}

/// Creates a new DieRoll with a random value using the default Rng
/// Creates a new DieRoll with a random value using the default Rng.
#[must_use]
pub fn new_rand(max: u8) -> Self {
let mut rng = Rng::new();
Self::new_rand_using_rng(rng.u8(1..=max), &mut rng)
}

/// Creates a new DieRoll with a random value using the given Rng
/// Creates a new DieRoll with a random value using the given Rng.
#[must_use]
pub fn new_rand_using_rng(max: u8, rng: &mut Rng) -> Self {
Self::new(if max > 0 { rng.u8(1..=max) } else { 0 })
}
Expand All @@ -435,18 +449,18 @@ impl fmt::Display for DieRoll<'_> {
}
}

/// Representation of the result from rolling a single set of [Dice]
/// A representation of the result from rolling a single set of [Dice]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Rolled<'a> {
/// Each individual die roll
/// Each individual die roll that was made
pub rolls: Vec<DieRoll<'a>>,

/// Dice that were rolled to obtain this
/// Dice that were rolled to produce this
pub dice: &'a Dice,
}

impl Rolled<'_> {
/// Sums all rolls and explosions
/// Totals all roll values.
pub fn total(&self) -> Result<u16, Error> {
let mut sum: u16 = 0;

Expand All @@ -461,9 +475,13 @@ impl Rolled<'_> {

impl Describe for Rolled<'_> {
/// Builds a string of the dice expression the roll is from and all of the individual rolled dice.
/// If max_rolls is specified and there are more rolls than it, the output will be truncated and appended with
///
/// Rolls that have been dropped are suffixed with `(d)`.
///
/// If `max_rolls`` is specified and there are more rolls than it, the output will be truncated and appended with
/// "X more..." (where X is the remaining roll count past the max).
/// Example output: `3d6[6, 2, 5]`
///
/// Example output: `3d6kh2[6, 2 (d), 5]`
fn describe(&self, max_rolls: Option<usize>) -> String {
let max_rolls = max_rolls.unwrap_or(usize::MAX);
let total_rolls = self.rolls.len();
Expand Down Expand Up @@ -511,37 +529,37 @@ pub enum Error {
pub struct Builder(Dice);

impl Builder {
/// Sets the number of dice to roll
/// Sets the number of dice to roll.
pub fn count(mut self, count: u8) -> Self {
self.0.count = count;
self
}

/// Sets the number of sides per die
/// Sets the number of sides per die.
pub fn sides(mut self, sides: u8) -> Self {
self.0.sides = sides;
self
}

/// Adds the exploding modifier to the dice
/// Adds an exploding modifier to the dice.
pub fn explode(mut self, cond: Option<Condition>, recurse: bool) -> Self {
self.0.modifiers.push(Modifier::Explode(cond, recurse));
self
}

/// Adds the keep highest modifier to the dice
/// Adds a keep highest modifier to the dice.
pub fn keep_high(mut self, count: u8) -> Self {
self.0.modifiers.push(Modifier::KeepHigh(count));
self
}

/// Adds the keep lowest modifier to the dice
/// Adds a keep lowest modifier to the dice.
pub fn keep_low(mut self, count: u8) -> Self {
self.0.modifiers.push(Modifier::KeepLow(count));
self
}

/// Finalizes the dice
/// Finalizes the dice.
pub fn build(self) -> Dice {
self.0
}
Expand Down

0 comments on commit 4c98d48

Please sign in to comment.