nicer looking output
This commit is contained in:
parent
0ebe9e3be3
commit
b437cefe5c
2 changed files with 51 additions and 31 deletions
30
src/dice.rs
30
src/dice.rs
|
|
@ -33,6 +33,8 @@ pub struct DiceFormula {
|
|||
pub(crate) x: bool,
|
||||
}
|
||||
|
||||
const DICE_POOL_LIMIT: usize = 100_000;
|
||||
|
||||
impl Expression {
|
||||
pub fn evaluate(&self, mut rng: impl Rng) -> anyhow::Result<String> {
|
||||
let mut result = String::new();
|
||||
|
|
@ -85,7 +87,7 @@ impl Expression {
|
|||
} else {
|
||||
1
|
||||
};
|
||||
if count > 1_000_000 {
|
||||
if count > DICE_POOL_LIMIT {
|
||||
bail!("Too many dice.")
|
||||
};
|
||||
output.push_str("d");
|
||||
|
|
@ -102,7 +104,7 @@ impl Expression {
|
|||
if size < 2 {
|
||||
bail!("Infinite explosion.")
|
||||
}
|
||||
for i in 0..1_000_000 {
|
||||
for i in 0..DICE_POOL_LIMIT {
|
||||
if i >= rolls.len() {
|
||||
break;
|
||||
}
|
||||
|
|
@ -148,7 +150,7 @@ impl Expression {
|
|||
let print_all_rolls = rolls.len() <= 100;
|
||||
|
||||
if print_all_rolls {
|
||||
output.push_str(" [ ");
|
||||
output.push_str(" ‹ ");
|
||||
}
|
||||
for idx in 0..rolls.len() {
|
||||
let mut skip = false;
|
||||
|
|
@ -174,27 +176,25 @@ impl Expression {
|
|||
skip = true;
|
||||
}
|
||||
}
|
||||
if skip {
|
||||
if print_all_rolls {
|
||||
write!(output, "~~`{}`~~", roll)?;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if !skip {
|
||||
result_set.push(roll as f64);
|
||||
}
|
||||
if print_all_rolls {
|
||||
let bold = size > 2 && (roll == 1 || roll == size);
|
||||
if bold {
|
||||
if skip {
|
||||
write!(output, "~~`{}`~~", roll)?;
|
||||
} else if size > 2 && (roll == 1 || roll == size) {
|
||||
write!(output, "**`{}`**", roll)?;
|
||||
} else {
|
||||
write!(output, "`{}`", roll)?;
|
||||
}
|
||||
|
||||
if idx != rolls.len() - 1 {
|
||||
output.push_str(", ");
|
||||
output.push_str(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
if print_all_rolls {
|
||||
output.push_str(" ]");
|
||||
output.push_str(" ›");
|
||||
}
|
||||
|
||||
result_set.iter().sum()
|
||||
|
|
@ -253,7 +253,7 @@ impl Expression {
|
|||
} else {
|
||||
1
|
||||
};
|
||||
if count > 1_000_000 {
|
||||
if count > DICE_POOL_LIMIT {
|
||||
bail!("Too many dice.")
|
||||
};
|
||||
let size = self.node_sample(rng, *size)? as i64;
|
||||
|
|
@ -268,7 +268,7 @@ impl Expression {
|
|||
if size < 2 {
|
||||
bail!("Infinite explosion.")
|
||||
}
|
||||
for i in 0..1_000_000 {
|
||||
for i in 0..DICE_POOL_LIMIT {
|
||||
if i >= rolls.len() {
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
48
src/main.rs
48
src/main.rs
|
|
@ -5,7 +5,8 @@ use anyhow::bail;
|
|||
use dotenv::dotenv;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use serenity::all::{
|
||||
Command, CommandInteraction, CommandOptionType, CreateCommandOption, CreateComponent, FullEvent, Interaction, MessageFlags, ResolvedOption, ResolvedValue,
|
||||
Command, CommandInteraction, CommandOptionType, CreateCommandOption, CreateComponent,
|
||||
FullEvent, Interaction, MessageFlags, ResolvedOption, ResolvedValue,
|
||||
};
|
||||
use serenity::builder::{
|
||||
CreateCommand, CreateContainer, CreateContainerComponent, CreateInteractionResponse,
|
||||
|
|
@ -80,7 +81,7 @@ impl EventHandler for Handler {
|
|||
).required(true))
|
||||
.add_option(CreateCommandOption::new(
|
||||
CommandOptionType::Integer,
|
||||
"multi",
|
||||
"repeat",
|
||||
"Repeat the rolled formula this many times. Useful if you're controlling too many units!",
|
||||
))
|
||||
.add_option(CreateCommandOption::new(
|
||||
|
|
@ -92,6 +93,11 @@ impl EventHandler for Handler {
|
|||
CommandOptionType::Boolean,
|
||||
"private",
|
||||
"Keep the roll private and hidden, only for yourself.",
|
||||
))
|
||||
.add_option(CreateCommandOption::new(
|
||||
CommandOptionType::String,
|
||||
"seed",
|
||||
"Roll with a fixed seed. This bot uses xoshiro256++.",
|
||||
)),
|
||||
)
|
||||
.await;
|
||||
|
|
@ -114,12 +120,12 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
|||
else {
|
||||
bail!("Formula was not provided.")
|
||||
};
|
||||
let multi = options
|
||||
let repeat = options
|
||||
.iter()
|
||||
.find(|option| option.name == "multi")
|
||||
.find(|option| option.name == "repeat")
|
||||
.and_then(|option| {
|
||||
if let ResolvedValue::Integer(multi) = option.value {
|
||||
Some(multi)
|
||||
if let ResolvedValue::Integer(repeat) = option.value {
|
||||
Some(repeat)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -147,6 +153,17 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
|||
None
|
||||
}
|
||||
});
|
||||
let fixed_seed = options
|
||||
.iter()
|
||||
.find(|option| option.name == "seed")
|
||||
.and_then(|option| {
|
||||
if let ResolvedValue::String(fixed_seed) = option.value {
|
||||
Some(fixed_seed)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.and_then(|s| s.parse::<u64>().ok());
|
||||
|
||||
let result = parsing::parse(&formula);
|
||||
let expression = match result {
|
||||
|
|
@ -171,24 +188,27 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
|||
command.defer(&ctx.http).await?;
|
||||
}
|
||||
|
||||
let seed = rand::rng().next_u64();
|
||||
let seed = fixed_seed.unwrap_or_else(|| rand::rng().next_u64());
|
||||
let mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(seed);
|
||||
|
||||
let ev = (expression.average(&mut rng)? * 10.0).round() / 10.0;
|
||||
|
||||
let mut text_components = Vec::with_capacity((multi + 2) as usize);
|
||||
let mut text_components = Vec::with_capacity((repeat + 2) as usize);
|
||||
if let Some(description) = description {
|
||||
text_components.push(CreateContainerComponent::TextDisplay(
|
||||
CreateTextDisplay::new(if let Some(description) = description {
|
||||
format!("### {} rolled: *{description}*\n", command.user.mention())
|
||||
} else {
|
||||
format!("### {} rolled\n", command.user.mention())
|
||||
}),
|
||||
CreateTextDisplay::new(format!(">>> {description}\n")),
|
||||
));
|
||||
for _ in 0..multi {
|
||||
}
|
||||
for _ in 0..repeat {
|
||||
text_components.push(CreateContainerComponent::TextDisplay(
|
||||
CreateTextDisplay::new(format!("{}\n", expression.evaluate(&mut rng)?)),
|
||||
));
|
||||
}
|
||||
if fixed_seed.is_some() {
|
||||
text_components.push(CreateContainerComponent::TextDisplay(
|
||||
CreateTextDisplay::new("***⚠️ This is not a fair roll. The result was generated based on a fixed seed and is thus fully reproducible.***".to_string()),
|
||||
));
|
||||
}
|
||||
text_components.push(CreateContainerComponent::TextDisplay(
|
||||
CreateTextDisplay::new(format!("-# Expected value: {ev} | Seed: {seed}")),
|
||||
));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue