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
use rand::Rng; use crate::Damage; use crate::RollExpression; pub use checkoutcome::{CheckOutcome, CheckOutcomeBuilder, CritScore}; mod checkoutcome; mod checkparse; /// The advantage state of an ability check. #[derive(PartialEq, Debug, Clone, Copy)] pub enum AdvState { /// Check rolled with advantage (roll twice, take the higher value). Advantage, /// Check rolled with no advantage (only roll once). Neutral, /// Check rolled with disadvantage (roll twice, take the lower value). Disadvantage, } impl Default for AdvState { fn default() -> Self { Self::Neutral } } /// An ability check - roll a d20, potentially with modifiers or /// advantage. /// /// ``` /// use critfail::{RollExpression, Check}; /// /// let check = Check::new("r+4").unwrap(); /// /// let outcome = check.roll(); /// /// print!("{}", outcome); // Prints something like "16" /// print!("{:?}", outcome); // Prints something like "(12)+4" /// ``` #[derive(PartialEq, Debug, Clone)] pub struct Check { adv: AdvState, // TODO: the modifier should be a Vec<Modifier> instead of a Damage modifier: Damage, } impl Check { /// Roll this check using `adv` to override the advantage state. /// /// ``` /// use critfail::{RollExpression, Check, AdvState}; /// let check = Check::new("r+3").unwrap(); /// /// check.roll(); // Roll without advantage /// check.roll_with_advantage(AdvState::Advantage); // Roll with advantage /// check.roll_with_advantage(AdvState::Neutral); // Roll without advantage /// check.roll_with_advantage(AdvState::Disadvantage); // Roll with disadvantage /// ``` pub fn roll_with_advantage(&self, adv: AdvState) -> CheckOutcome { let r1 = rand::thread_rng().gen_range(1, 21); let r2 = rand::thread_rng().gen_range(1, 21); let mods = self.modifier.roll(); CheckOutcome::new(adv, r1, r2, mods.into_modifiers().into_inner()) } } impl RollExpression for Check { type Outcome = CheckOutcome; fn roll(&self) -> Self::Outcome { self.roll_with_advantage(self.adv) } }