Keep/Drop Function #92
12
README.md
12
README.md
|
@ -118,8 +118,16 @@ expressions.
|
||||||
!r 3d12 - 5d2 + 3 - 7d3 + 20d20
|
!r 3d12 - 5d2 + 3 - 7d3 + 20d20
|
||||||
```
|
```
|
||||||
|
|
||||||
This system does not yet have the capability to handle things like D&D
|
#### Keep/Drop Dice
|
||||||
5e advantage or disadvantage.
|
The bot supports either keeping the highest dice in a roll, or
|
||||||
|
dropping the highest dice in a roll. This allows the bot to handle
|
||||||
|
things like D&D 5e advantage or disadvantage.
|
||||||
|
|
||||||
|
```
|
||||||
|
!roll 2d20k1
|
||||||
|
!r 2d20dh1 + 5
|
||||||
|
!r 10d10k5 + 10d10dh5 - 2
|
||||||
|
```
|
||||||
|
|
||||||
### Storytelling System
|
### Storytelling System
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,29 @@ use std::ops::{Deref, DerefMut};
|
||||||
pub struct Dice {
|
pub struct Dice {
|
||||||
pub(crate) count: u32,
|
pub(crate) count: u32,
|
||||||
pub(crate) sides: u32,
|
pub(crate) sides: u32,
|
||||||
|
pub(crate) keep_drop: KeepOrDrop,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Dice {
|
impl fmt::Display for Dice {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}d{}", self.count, self.sides)
|
match self.keep_drop {
|
||||||
|
KeepOrDrop::Keep(keep) => write!(f, "{}d{}k{}", self.count, self.sides, keep),
|
||||||
|
KeepOrDrop::Drop(drop) => write!(f, "{}d{}dh{}", self.count, self.sides, drop),
|
||||||
|
KeepOrDrop::None => write!(f, "{}d{}", self.count, self.sides),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum KeepOrDrop {
|
||||||
|
Keep (u32),
|
||||||
|
Drop (u32),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
impl Dice {
|
impl Dice {
|
||||||
pub fn new(count: u32, sides: u32) -> Dice {
|
pub fn new(count: u32, sides: u32, keep_drop: KeepOrDrop) -> Dice {
|
||||||
Dice { count, sides }
|
Dice { count, sides, keep_drop }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,53 @@ enum Sign {
|
||||||
Minus,
|
Minus,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse a dice expression. Does not eat whitespace
|
/// Parse a dice expression. Does not eat whitespace
|
||||||
fn parse_dice(input: &str) -> IResult<&str, Dice> {
|
fn parse_dice(input: &str) -> IResult<&str, Dice> {
|
||||||
|
// parse main dice expression
|
||||||
let (input, (count, _, sides)) = tuple((digit1, tag("d"), digit1))(input)?;
|
let (input, (count, _, sides)) = tuple((digit1, tag("d"), digit1))(input)?;
|
||||||
|
|
||||||
|
// check for keep expression to keep highest dice (2d20k1)
|
||||||
|
let (keep, input) = match tuple::<&str, _, (_, _), _>((tag("k"), digit1))(input) {
|
||||||
|
// if ok, keep expression is present
|
||||||
|
Ok((rest, (_, keep_amount))) => (keep_amount, rest),
|
||||||
|
// otherwise absent and keep all dice
|
||||||
|
Err(_) => ("", input)
|
||||||
|
};
|
||||||
|
|
||||||
|
// check for drop expression to drop highest dice (2d20dh1)
|
||||||
|
let (drop, input) = match tuple::<&str, _, (_, _), _>((tag("dh"), digit1))(input) {
|
||||||
|
// if ok, keep expression is present
|
||||||
|
Ok((rest, (_, drop_amount))) => (drop_amount, rest),
|
||||||
|
// otherwise absent and keep all dice
|
||||||
|
Err(_) => ("", input)
|
||||||
|
};
|
||||||
|
|
||||||
|
let count: u32 = count.parse().unwrap();
|
||||||
|
|
||||||
|
// don't allow keep greater than number of dice, and don't allow keep zero
|
||||||
|
let keep_drop = match keep.parse::<u32>() {
|
||||||
|
// Ok, there's a keep value, check and create Keep
|
||||||
|
Ok(i) => match i {
|
||||||
|
_i if _i > count || _i == 0 => KeepOrDrop::None,
|
||||||
|
i => KeepOrDrop::Keep(i),
|
||||||
|
},
|
||||||
|
// Err, check if drop works
|
||||||
|
Err(_) => {
|
||||||
|
match drop.parse::<u32>() {
|
||||||
|
// Ok, there's a drop value, check and create Drop
|
||||||
|
Ok(i) => match i {
|
||||||
|
_i if i >= count => KeepOrDrop::None,
|
||||||
|
i => KeepOrDrop::Drop(i),
|
||||||
|
},
|
||||||
|
// Err, there's neither keep nor drop
|
||||||
|
Err(_) => KeepOrDrop::None,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Dice::new(count.parse().unwrap(), sides.parse().unwrap()),
|
Dice::new(count, sides.parse().unwrap(), keep_drop),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,16 +149,29 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn dice_test() {
|
fn dice_test() {
|
||||||
assert_eq!(parse_dice("2d4"), Ok(("", Dice::new(2, 4))));
|
assert_eq!(parse_dice("2d4"), Ok(("", Dice::new(2, 4, KeepOrDrop::None))));
|
||||||
assert_eq!(parse_dice("20d40"), Ok(("", Dice::new(20, 40))));
|
assert_eq!(parse_dice("20d40"), Ok(("", Dice::new(20, 40, KeepOrDrop::None))));
|
||||||
assert_eq!(parse_dice("8d7"), Ok(("", Dice::new(8, 7))));
|
assert_eq!(parse_dice("8d7"), Ok(("", Dice::new(8, 7, KeepOrDrop::None))));
|
||||||
|
assert_eq!(parse_dice("2d20k1"), Ok(("", Dice::new(2, 20, KeepOrDrop::Keep(1)))));
|
||||||
|
assert_eq!(parse_dice("100d10k90"), Ok(("", Dice::new(100, 10, KeepOrDrop::Keep(90)))));
|
||||||
|
assert_eq!(parse_dice("11d10k10"), Ok(("", Dice::new(11, 10, KeepOrDrop::Keep(10)))));
|
||||||
|
assert_eq!(parse_dice("12d10k11"), Ok(("", Dice::new(12, 10, KeepOrDrop::Keep(11)))));
|
||||||
|
assert_eq!(parse_dice("12d10k13"), Ok(("", Dice::new(12, 10, KeepOrDrop::None))));
|
||||||
|
assert_eq!(parse_dice("12d10k0"), Ok(("", Dice::new(12, 10, KeepOrDrop::None))));
|
||||||
|
assert_eq!(parse_dice("20d40dh5"), Ok(("", Dice::new(20, 40, KeepOrDrop::Drop(5)))));
|
||||||
|
assert_eq!(parse_dice("8d7dh9"), Ok(("", Dice::new(8, 7, KeepOrDrop::None))));
|
||||||
|
assert_eq!(parse_dice("8d7dh8"), Ok(("", Dice::new(8, 7, KeepOrDrop::None))));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn element_test() {
|
fn element_test() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_element(" \t\n\r\n 8d7 \n"),
|
parse_element(" \t\n\r\n 8d7 \n"),
|
||||||
Ok((" \n", Element::Dice(Dice::new(8, 7))))
|
Ok((" \n", Element::Dice(Dice::new(8, 7, KeepOrDrop::None))))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_element(" \t\n\r\n 3d20k2 \n"),
|
||||||
|
Ok((" \n", Element::Dice(Dice::new(3, 20, KeepOrDrop::Keep(2)))))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_element(" \t\n\r\n 8 \n"),
|
parse_element(" \t\n\r\n 8 \n"),
|
||||||
|
@ -139,14 +193,21 @@ mod tests {
|
||||||
parse_signed_element(" \t\n\r\n- 8d4 \n"),
|
parse_signed_element(" \t\n\r\n- 8d4 \n"),
|
||||||
Ok((
|
Ok((
|
||||||
" \n",
|
" \n",
|
||||||
SignedElement::Negative(Element::Dice(Dice::new(8, 4)))
|
SignedElement::Negative(Element::Dice(Dice::new(8, 4, KeepOrDrop::None)))
|
||||||
|
))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_signed_element(" \t\n\r\n- 8d4k4 \n"),
|
||||||
|
Ok((
|
||||||
|
" \n",
|
||||||
|
SignedElement::Negative(Element::Dice(Dice::new(8, 4, KeepOrDrop::Keep(4))))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_signed_element(" \t\n\r\n+ 8d4 \n"),
|
parse_signed_element(" \t\n\r\n+ 8d4 \n"),
|
||||||
Ok((
|
Ok((
|
||||||
" \n",
|
" \n",
|
||||||
SignedElement::Positive(Element::Dice(Dice::new(8, 4)))
|
SignedElement::Positive(Element::Dice(Dice::new(8, 4, KeepOrDrop::None)))
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -158,29 +219,39 @@ mod tests {
|
||||||
Ok((
|
Ok((
|
||||||
"",
|
"",
|
||||||
ElementExpression(vec![SignedElement::Positive(Element::Dice(Dice::new(
|
ElementExpression(vec![SignedElement::Positive(Element::Dice(Dice::new(
|
||||||
8, 4
|
8, 4, KeepOrDrop::None
|
||||||
)))])
|
)))])
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
parse_element_expression("\t2d20k1 + 5"),
|
||||||
|
Ok((
|
||||||
|
"",
|
||||||
|
ElementExpression(vec![
|
||||||
|
SignedElement::Positive(Element::Dice(Dice::new(2, 20, KeepOrDrop::Keep(1)))),
|
||||||
|
SignedElement::Positive(Element::Bonus(5)),
|
||||||
|
])
|
||||||
|
))
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_element_expression(" - 8d4 \n "),
|
parse_element_expression(" - 8d4 \n "),
|
||||||
Ok((
|
Ok((
|
||||||
" \n ",
|
" \n ",
|
||||||
ElementExpression(vec![SignedElement::Negative(Element::Dice(Dice::new(
|
ElementExpression(vec![SignedElement::Negative(Element::Dice(Dice::new(
|
||||||
8, 4
|
8, 4, KeepOrDrop::None
|
||||||
)))])
|
)))])
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_element_expression("\t3d4 + 7 - 5 - 6d12 + 1d1 + 53 1d5 "),
|
parse_element_expression("\t3d4k2 + 7 - 5 - 6d12dh3 + 1d1 + 53 1d5 "),
|
||||||
Ok((
|
Ok((
|
||||||
" 1d5 ",
|
" 1d5 ",
|
||||||
ElementExpression(vec![
|
ElementExpression(vec![
|
||||||
SignedElement::Positive(Element::Dice(Dice::new(3, 4))),
|
SignedElement::Positive(Element::Dice(Dice::new(3, 4, KeepOrDrop::Keep(2)))),
|
||||||
SignedElement::Positive(Element::Bonus(7)),
|
SignedElement::Positive(Element::Bonus(7)),
|
||||||
SignedElement::Negative(Element::Bonus(5)),
|
SignedElement::Negative(Element::Bonus(5)),
|
||||||
SignedElement::Negative(Element::Dice(Dice::new(6, 12))),
|
SignedElement::Negative(Element::Dice(Dice::new(6, 12, KeepOrDrop::Drop(3)))),
|
||||||
SignedElement::Positive(Element::Dice(Dice::new(1, 1))),
|
SignedElement::Positive(Element::Dice(Dice::new(1, 1, KeepOrDrop::None))),
|
||||||
SignedElement::Positive(Element::Bonus(53)),
|
SignedElement::Positive(Element::Bonus(53)),
|
||||||
])
|
])
|
||||||
))
|
))
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* project.
|
* project.
|
||||||
*/
|
*/
|
||||||
use crate::basic::dice;
|
use crate::basic::dice;
|
||||||
|
use crate::basic::dice::KeepOrDrop;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
@ -19,15 +20,27 @@ pub trait Rolled {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct DiceRoll(pub Vec<u32>);
|
/// array of rolls in order, how many dice to keep, and how many to drop
|
||||||
|
/// keep indicates how many of the highest dice to keep
|
||||||
|
/// drop indicates how many of the highest dice to drop
|
||||||
|
pub struct DiceRoll (pub Vec<u32>, usize, usize);
|
||||||
|
|
||||||
impl DiceRoll {
|
impl DiceRoll {
|
||||||
pub fn rolls(&self) -> &[u32] {
|
pub fn rolls(&self) -> &[u32] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn keep(&self) -> usize {
|
||||||
|
self.1
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop(&self) -> usize {
|
||||||
|
self.2
|
||||||
|
}
|
||||||
|
|
||||||
|
// only count kept dice in total
|
||||||
pub fn total(&self) -> u32 {
|
pub fn total(&self) -> u32 {
|
||||||
self.0.iter().sum()
|
self.0[self.2..self.1].iter().sum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,11 +54,21 @@ impl fmt::Display for DiceRoll {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{}", self.rolled_value())?;
|
write!(f, "{}", self.rolled_value())?;
|
||||||
let rolls = self.rolls();
|
let rolls = self.rolls();
|
||||||
let mut iter = rolls.iter();
|
let keep = self.keep();
|
||||||
|
let drop = self.drop();
|
||||||
|
let mut iter = rolls.iter().enumerate();
|
||||||
if let Some(first) = iter.next() {
|
if let Some(first) = iter.next() {
|
||||||
write!(f, " ({}", first)?;
|
if drop != 0 {
|
||||||
|
write!(f, " ([{}]", first.1)?;
|
||||||
|
} else {
|
||||||
|
write!(f, " ({}", first.1)?;
|
||||||
|
}
|
||||||
for roll in iter {
|
for roll in iter {
|
||||||
write!(f, " + {}", roll)?;
|
if roll.0 >= keep || roll.0 < drop {
|
||||||
|
write!(f, " + [{}]", roll.1)?;
|
||||||
|
} else {
|
||||||
|
write!(f, " + {}", roll.1)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
write!(f, ")")?;
|
write!(f, ")")?;
|
||||||
}
|
}
|
||||||
|
@ -58,11 +81,17 @@ impl Roll for dice::Dice {
|
||||||
|
|
||||||
fn roll(&self) -> DiceRoll {
|
fn roll(&self) -> DiceRoll {
|
||||||
let mut rng = rand::thread_rng();
|
let mut rng = rand::thread_rng();
|
||||||
let rolls: Vec<_> = (0..self.count)
|
let mut rolls: Vec<_> = (0..self.count)
|
||||||
.map(|_| rng.gen_range(1..=self.sides))
|
.map(|_| rng.gen_range(1..=self.sides))
|
||||||
.collect();
|
.collect();
|
||||||
|
// sort rolls in descending order
|
||||||
|
rolls.sort_by(|a, b| b.cmp(a));
|
||||||
|
|
||||||
DiceRoll(rolls)
|
match self.keep_drop {
|
||||||
|
KeepOrDrop::Keep(k) => DiceRoll(rolls,k as usize, 0),
|
||||||
|
KeepOrDrop::Drop(dh) => DiceRoll(rolls,self.count as usize, dh as usize),
|
||||||
|
KeepOrDrop::None => DiceRoll(rolls,self.count as usize, 0),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,18 +227,26 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn dice_roll_display_test() {
|
fn dice_roll_display_test() {
|
||||||
assert_eq!(DiceRoll(vec![1, 3, 4]).to_string(), "8 (1 + 3 + 4)");
|
assert_eq!(DiceRoll(vec![1, 3, 4], 3, 0).to_string(), "8 (1 + 3 + 4)");
|
||||||
assert_eq!(DiceRoll(vec![]).to_string(), "0");
|
assert_eq!(DiceRoll(vec![], 0, 0).to_string(), "0");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
DiceRoll(vec![4, 7, 2, 10]).to_string(),
|
DiceRoll(vec![4, 7, 2, 10], 4, 0).to_string(),
|
||||||
"23 (4 + 7 + 2 + 10)"
|
"23 (4 + 7 + 2 + 10)"
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
DiceRoll(vec![20, 13, 11, 10], 3, 0).to_string(),
|
||||||
|
"44 (20 + 13 + 11 + [10])"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
DiceRoll(vec![20, 13, 11, 10], 4, 1).to_string(),
|
||||||
|
"34 ([20] + 13 + 11 + 10)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn element_roll_display_test() {
|
fn element_roll_display_test() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ElementRoll::Dice(DiceRoll(vec![1, 3, 4])).to_string(),
|
ElementRoll::Dice(DiceRoll(vec![1, 3, 4], 3, 0)).to_string(),
|
||||||
"8 (1 + 3 + 4)"
|
"8 (1 + 3 + 4)"
|
||||||
);
|
);
|
||||||
assert_eq!(ElementRoll::Bonus(7).to_string(), "7");
|
assert_eq!(ElementRoll::Bonus(7).to_string(), "7");
|
||||||
|
@ -218,11 +255,11 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn signed_element_roll_display_test() {
|
fn signed_element_roll_display_test() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 3, 4]))).to_string(),
|
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 3, 4], 3, 0))).to_string(),
|
||||||
"8 (1 + 3 + 4)"
|
"8 (1 + 3 + 4)"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 3, 4]))).to_string(),
|
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 3, 4], 3, 0))).to_string(),
|
||||||
"-8 (1 + 3 + 4)"
|
"-8 (1 + 3 + 4)"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -239,14 +276,14 @@ mod tests {
|
||||||
fn element_expression_roll_display_test() {
|
fn element_expression_roll_display_test() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ElementExpressionRoll(vec![SignedElementRoll::Positive(ElementRoll::Dice(
|
ElementExpressionRoll(vec![SignedElementRoll::Positive(ElementRoll::Dice(
|
||||||
DiceRoll(vec![1, 3, 4])
|
DiceRoll(vec![1, 3, 4], 3, 0)
|
||||||
)),])
|
)),])
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"8 (1 + 3 + 4)"
|
"8 (1 + 3 + 4)"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ElementExpressionRoll(vec![SignedElementRoll::Negative(ElementRoll::Dice(
|
ElementExpressionRoll(vec![SignedElementRoll::Negative(ElementRoll::Dice(
|
||||||
DiceRoll(vec![1, 3, 4])
|
DiceRoll(vec![1, 3, 4], 3, 0)
|
||||||
)),])
|
)),])
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"-8 (1 + 3 + 4)"
|
"-8 (1 + 3 + 4)"
|
||||||
|
@ -263,8 +300,8 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ElementExpressionRoll(vec![
|
ElementExpressionRoll(vec![
|
||||||
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 3, 4]))),
|
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 3, 4], 3, 0))),
|
||||||
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 2]))),
|
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 2], 2, 0))),
|
||||||
SignedElementRoll::Positive(ElementRoll::Bonus(4)),
|
SignedElementRoll::Positive(ElementRoll::Bonus(4)),
|
||||||
SignedElementRoll::Negative(ElementRoll::Bonus(7)),
|
SignedElementRoll::Negative(ElementRoll::Bonus(7)),
|
||||||
])
|
])
|
||||||
|
@ -273,13 +310,33 @@ mod tests {
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
ElementExpressionRoll(vec![
|
ElementExpressionRoll(vec![
|
||||||
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 3, 4]))),
|
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![1, 3, 4], 3, 0))),
|
||||||
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 2]))),
|
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![1, 2], 2, 0))),
|
||||||
SignedElementRoll::Negative(ElementRoll::Bonus(4)),
|
SignedElementRoll::Negative(ElementRoll::Bonus(4)),
|
||||||
SignedElementRoll::Positive(ElementRoll::Bonus(7)),
|
SignedElementRoll::Positive(ElementRoll::Bonus(7)),
|
||||||
])
|
])
|
||||||
.to_string(),
|
.to_string(),
|
||||||
"-2 (-8 (1 + 3 + 4) + 3 (1 + 2) - 4 + 7)"
|
"-2 (-8 (1 + 3 + 4) + 3 (1 + 2) - 4 + 7)"
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ElementExpressionRoll(vec![
|
||||||
|
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![4, 3, 1], 3, 0))),
|
||||||
|
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![12, 2], 1, 0))),
|
||||||
|
SignedElementRoll::Negative(ElementRoll::Bonus(4)),
|
||||||
|
SignedElementRoll::Positive(ElementRoll::Bonus(7)),
|
||||||
|
])
|
||||||
|
.to_string(),
|
||||||
|
"7 (-8 (4 + 3 + 1) + 12 (12 + [2]) - 4 + 7)"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ElementExpressionRoll(vec![
|
||||||
|
SignedElementRoll::Negative(ElementRoll::Dice(DiceRoll(vec![4, 3, 1], 3, 1))),
|
||||||
|
SignedElementRoll::Positive(ElementRoll::Dice(DiceRoll(vec![12, 2], 2, 0))),
|
||||||
|
SignedElementRoll::Negative(ElementRoll::Bonus(4)),
|
||||||
|
SignedElementRoll::Positive(ElementRoll::Bonus(7)),
|
||||||
|
])
|
||||||
|
.to_string(),
|
||||||
|
"13 (-4 ([4] + 3 + 1) + 14 (12 + 2) - 4 + 7)"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue