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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
use crate::RollExpression; use crate::{Attack, Check, Damage}; pub use rolloutcome::RollOutcome; mod rolloutcome; mod rollparse; /// Any kind of roll—either a check, damage, or attack roll. /// /// This struct is useful when parsing a roll expression if you don't /// know what type of roll expression it will be. /// /// ``` /// 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" /// ``` #[derive(PartialEq, Debug, Clone)] pub enum Roll { /// A `Roll` containing a `Check` roll. Check(Check), /// A `Roll` containing a `Damage` roll. Damage(Damage), /// A `Roll` containing an `Attack` roll. Attack(Attack), } impl RollExpression for Roll { type Outcome = RollOutcome; fn roll(&self) -> Self::Outcome { match self { Roll::Check(c) => c.roll().into(), Roll::Damage(d) => d.roll().into(), Roll::Attack(a) => a.roll().into(), } } } impl Roll { /// Return true if this `Roll` is a check roll. /// /// ``` /// use critfail::{RollExpression, Roll}; /// /// assert_eq!(Roll::new("r+3").unwrap().is_check(), true); /// assert_eq!(Roll::new("2d8+5").unwrap().is_check(), false); /// assert_eq!(Roll::new("r+3?2d8+5").unwrap().is_check(), false); /// ``` pub fn is_check(&self) -> bool { match self { Self::Check(_) => true, _ => false, } } /// Return true if this `Roll` is a damage roll. /// /// ``` /// use critfail::{RollExpression, Roll}; /// /// assert_eq!(Roll::new("r+3").unwrap().is_damage(), false); /// assert_eq!(Roll::new("2d8+5").unwrap().is_damage(), true); /// assert_eq!(Roll::new("r+3?2d8+5").unwrap().is_damage(), false); /// ``` pub fn is_damage(&self) -> bool { match self { Self::Damage(_) => true, _ => false, } } /// Return true if this `Roll` is an attack roll. /// /// ``` /// use critfail::{RollExpression, Roll}; /// /// assert_eq!(Roll::new("r+3").unwrap().is_attack(), false); /// assert_eq!(Roll::new("2d8+5").unwrap().is_attack(), false); /// assert_eq!(Roll::new("r+3?2d8+5").unwrap().is_attack(), true); /// ``` pub fn is_attack(&self) -> bool { match self { Self::Attack(_) => true, _ => false, } } } impl From<Check> for Roll { fn from(check: Check) -> Self { Self::Check(check) } } impl From<Damage> for Roll { fn from(damage: Damage) -> Self { Self::Damage(damage) } } impl From<Attack> for Roll { fn from(attack: Attack) -> Self { Self::Attack(attack) } }