aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author简律纯 <i@jyunko.cn>2025-09-12 18:06:17 +0800
committer简律纯 <i@jyunko.cn>2025-09-12 18:06:17 +0800
commit183e39d9ebfe6e48e5ce666dee36b5347d47f53e (patch)
tree88a512d05a49d805be392a1113054297d3461188 /src
parentb8fa77736a3c3b9c9d898e7ffa87e057cfab005d (diff)
downloadOneRoll-183e39d9ebfe6e48e5ce666dee36b5347d47f53e.tar.gz
OneRoll-183e39d9ebfe6e48e5ce666dee36b5347d47f53e.zip
feat: add unique modifier to dice calculations and parsing
Diffstat (limited to 'src')
-rw-r--r--src/calculator.rs14
-rw-r--r--src/oneroll/grammar.pest2
-rw-r--r--src/parser.rs3
-rw-r--r--src/types.rs1
4 files changed, 19 insertions, 1 deletions
diff --git a/src/calculator.rs b/src/calculator.rs
index 9611a2b..7289921 100644
--- a/src/calculator.rs
+++ b/src/calculator.rs
@@ -61,7 +61,7 @@ impl DiceCalculator {
rolls.push(final_rolls);
}
- // handle high/low and discard high/low
+ // handle high/low, discard high/low and unique deduplication
let mut final_rolls = rolls;
for modifier in &dice.modifiers {
match modifier {
@@ -89,6 +89,17 @@ impl DiceCalculator {
sorted.sort();
final_rolls = sorted.iter().skip(*n as usize).map(|&v| vec![v]).collect();
}
+ DiceModifier::Unique => {
+ use std::collections::HashSet;
+ let mut seen = HashSet::new();
+ let mut uniques: Vec<i32> = Vec::new();
+ for v in final_rolls.iter().flatten() {
+ if seen.insert(*v) {
+ uniques.push(*v);
+ }
+ }
+ final_rolls = uniques.into_iter().map(|v| vec![v]).collect();
+ }
_ => {}
}
}
@@ -204,6 +215,7 @@ impl DiceCalculator {
DiceModifier::KeepLow(n) => result.push_str(&format!("kl{}", n)),
DiceModifier::DropHigh(n) => result.push_str(&format!("dh{}", n)),
DiceModifier::DropLow(n) => result.push_str(&format!("dl{}", n)),
+ DiceModifier::Unique => result.push('u'),
}
}
result
diff --git a/src/oneroll/grammar.pest b/src/oneroll/grammar.pest
index 01b97e9..27d1c5e 100644
--- a/src/oneroll/grammar.pest
+++ b/src/oneroll/grammar.pest
@@ -28,6 +28,7 @@ modifier = {
| keep_low
| drop_high
| drop_low
+ | unique
}
explode = { "!" }
@@ -37,6 +38,7 @@ keep_high = { "kh" ~ number }
keep_low = { "kl" ~ number }
drop_high = { "dh" ~ number }
drop_low = { "dl" ~ number }
+unique = { "u" }
op = { "+" | "-" | "*" | "/" | "^" }
diff --git a/src/parser.rs b/src/parser.rs
index 8f4633e..a1800a2 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -140,6 +140,9 @@ impl DiceParser {
.map_err(|_| DiceError::ParseError("无效的丢弃低数值".to_string()))?;
Ok(DiceModifier::DropLow(num))
}
+ Rule::unique => {
+ Ok(DiceModifier::Unique)
+ }
_ => Err(DiceError::ParseError("未知的修饰符".to_string())),
}
}
diff --git a/src/types.rs b/src/types.rs
index a88cbab..6f4c54c 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -26,6 +26,7 @@ pub enum DiceModifier {
KeepLow(i32), // klX
DropHigh(i32), // dhX
DropLow(i32), // dlX
+ Unique, // u
}