Compare commits
2 commits
0843c77473
...
e2649ce6ed
| Author | SHA1 | Date | |
|---|---|---|---|
| e2649ce6ed | |||
| 7cce361c73 |
5 changed files with 84 additions and 82 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
|
@ -1420,7 +1420,7 @@ dependencies = [
|
||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1570,7 +1570,7 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serenity"
|
name = "serenity"
|
||||||
version = "0.12.5"
|
version = "0.12.5"
|
||||||
source = "git+https://github.com/serenity-rs/serenity.git?rev=refs%2Fheads%2Fnext#37b9f433ada8b9ccc5f93f04826403b175855f86"
|
source = "git+https://github.com/serenity-rs/serenity.git?branch=next#37b9f433ada8b9ccc5f93f04826403b175855f86"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aformat",
|
"aformat",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
serenity = { git = "https://github.com/serenity-rs/serenity.git", rev = "refs/heads/next" , features = ["collector"] }
|
serenity = { version = "0.12.5" }
|
||||||
tokio = { version = "1.53.1", features = ["rt-multi-thread"] }
|
tokio = { version = "1.53.1", features = ["rt-multi-thread"] }
|
||||||
tracing = "0.1.44"
|
tracing = "0.1.44"
|
||||||
tracing-subscriber = "0.3.23"
|
tracing-subscriber = "0.3.23"
|
||||||
|
|
@ -15,3 +15,6 @@ thiserror = "2.0.20"
|
||||||
nom-language = "0.1.0"
|
nom-language = "0.1.0"
|
||||||
rand_xoshiro = "0.8.1"
|
rand_xoshiro = "0.8.1"
|
||||||
rand = "0.10.2"
|
rand = "0.10.2"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
serenity = { git = "https://github.com/serenity-rs/serenity.git", branch = "next" }
|
||||||
|
|
|
||||||
89
src/dice.rs
89
src/dice.rs
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::limits::{MAX_DICE_COUNT_PER_ROLL, MAX_DISPLAYED_DICE_PER_MESSAGE, RESULT_CULL_CHARACTER_THRESHOLD};
|
use crate::limits::{
|
||||||
|
MAX_DICE_COUNT_PER_ROLL, MAX_DISPLAYED_DICE_PER_MESSAGE, RESULT_CULL_CHARACTER_THRESHOLD,
|
||||||
|
};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use rand::{Rng, RngExt};
|
use rand::{Rng, RngExt};
|
||||||
use std::convert::Infallible;
|
use std::convert::Infallible;
|
||||||
|
|
@ -116,27 +118,23 @@ impl Expression {
|
||||||
// Exploding dice are early, they add rolls
|
// Exploding dice are early, they add rolls
|
||||||
if let Some(fragments) = x {
|
if let Some(fragments) = x {
|
||||||
write!(w, "x")?;
|
write!(w, "x")?;
|
||||||
let mut comparers = Vec::with_capacity(fragments.len());
|
let comparers = fragments
|
||||||
for fragment in fragments {
|
.iter()
|
||||||
comparers.push(fragment.comparer(rng, w)?);
|
.map(|fragment| fragment.comparer(rng, w))
|
||||||
}
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < rolls.len() {
|
while i < rolls.len() {
|
||||||
if i > MAX_DICE_COUNT_PER_ROLL {
|
if i > MAX_DICE_COUNT_PER_ROLL {
|
||||||
bail!("Explosion added too many dice.")
|
bail!("Explosion added too many dice.")
|
||||||
}
|
}
|
||||||
if comparers.len() == 0 {
|
if comparers.is_empty() {
|
||||||
// Explode on max size dice
|
// Explode on max size dice
|
||||||
if rolls[i] == size {
|
if rolls[i] == size {
|
||||||
rolls.push(rng.random_range(1..=size));
|
rolls.push(rng.random_range(1..=size));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Explode based on comparers provided
|
if comparers.iter().any(|comparer| comparer(rolls[i] as f64)) {
|
||||||
for comparer in comparers.iter() {
|
rolls.push(rng.random_range(1..=size));
|
||||||
if comparer(rolls[i] as f64) {
|
|
||||||
rolls.push(rng.random_range(1..=size));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
@ -187,25 +185,25 @@ impl Expression {
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
let roll = rolls[idx];
|
let roll = rolls[idx];
|
||||||
let rank = ranks[idx];
|
let rank = ranks[idx];
|
||||||
if let Some(kh) = kh {
|
if let Some(kh) = kh
|
||||||
if rolls.len() - 1 - rank >= kh {
|
&& rolls.len() - 1 - rank >= kh
|
||||||
skip = true;
|
{
|
||||||
}
|
skip = true;
|
||||||
}
|
}
|
||||||
if let Some(dh) = dh {
|
if let Some(dh) = dh
|
||||||
if rolls.len() - 1 - rank < dh {
|
&& rolls.len() - 1 - rank < dh
|
||||||
skip = true;
|
{
|
||||||
}
|
skip = true;
|
||||||
}
|
}
|
||||||
if let Some(kl) = kl {
|
if let Some(kl) = kl
|
||||||
if rank >= kl {
|
&& rank >= kl
|
||||||
skip = true;
|
{
|
||||||
}
|
skip = true;
|
||||||
}
|
}
|
||||||
if let Some(dl) = dl {
|
if let Some(dl) = dl
|
||||||
if rank < dl {
|
&& rank < dl
|
||||||
skip = true;
|
{
|
||||||
}
|
skip = true;
|
||||||
}
|
}
|
||||||
if !skip {
|
if !skip {
|
||||||
result_set.push(roll as f64);
|
result_set.push(roll as f64);
|
||||||
|
|
@ -300,19 +298,19 @@ impl Expression {
|
||||||
bail!("Invalid die size.")
|
bail!("Invalid die size.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(_) = x {
|
if x.is_some() {
|
||||||
bail!("Not implemented yet");
|
bail!("Not implemented yet");
|
||||||
}
|
}
|
||||||
if let Some(_) = kh {
|
if kh.is_some() {
|
||||||
bail!("Not implemented yet");
|
bail!("Not implemented yet");
|
||||||
};
|
};
|
||||||
if let Some(_) = kl {
|
if kl.is_some() {
|
||||||
bail!("Not implemented yet");
|
bail!("Not implemented yet");
|
||||||
};
|
};
|
||||||
if let Some(_) = dh {
|
if dh.is_some() {
|
||||||
bail!("Not implemented yet");
|
bail!("Not implemented yet");
|
||||||
};
|
};
|
||||||
if let Some(_) = dl {
|
if dl.is_some() {
|
||||||
bail!("Not implemented yet");
|
bail!("Not implemented yet");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -454,12 +452,15 @@ pub(crate) enum DiscordMdWitnessError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DiscordMd {
|
impl DiscordMd {
|
||||||
pub(crate) fn create_witness(md: &Arc<RwLock<Self>>) -> DiscordMdWitness {
|
pub(crate) fn create_witness(md: Arc<RwLock<Self>>) -> DiscordMdWitness {
|
||||||
let mut parent = md.write().unwrap();
|
let buffer_idx = {
|
||||||
parent.buffers.push(String::new());
|
let mut md = md.write().unwrap();
|
||||||
|
md.buffers.push(String::new());
|
||||||
|
md.buffers.len() - 1
|
||||||
|
};
|
||||||
DiscordMdWitness {
|
DiscordMdWitness {
|
||||||
parent: md.clone(),
|
parent: md,
|
||||||
buffer_idx: parent.buffers.len() - 1,
|
buffer_idx,
|
||||||
result: None,
|
result: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +470,6 @@ impl DiscordMd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl DiscordMdWitness {
|
impl DiscordMdWitness {
|
||||||
pub(crate) fn end(self) {
|
pub(crate) fn end(self) {
|
||||||
let mut parent = self.parent.write().unwrap();
|
let mut parent = self.parent.write().unwrap();
|
||||||
|
|
@ -477,10 +477,9 @@ impl DiscordMdWitness {
|
||||||
parent.buffers[self.buffer_idx] = self
|
parent.buffers[self.buffer_idx] = self
|
||||||
.result
|
.result
|
||||||
.map(|result| format!("**{result} = …**"))
|
.map(|result| format!("**{result} = …**"))
|
||||||
.unwrap_or_else(|| String::new());
|
.unwrap_or_default();
|
||||||
} else if let Some(result) = self.result {
|
} else if let Some(result) = self.result {
|
||||||
parent.buffers[self.buffer_idx]
|
parent.buffers[self.buffer_idx].insert_str(0, &format!("**{result}** = "));
|
||||||
.insert_str(0, &format!("**{result}** = "));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -510,7 +509,6 @@ impl Witness for DiscordMdWitness {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a> WitnessSet for DiscordMdWitnessSet<'a> {
|
impl<'a> WitnessSet for DiscordMdWitnessSet<'a> {
|
||||||
type Ok = ();
|
type Ok = ();
|
||||||
type Error = DiscordMdWitnessError;
|
type Error = DiscordMdWitnessError;
|
||||||
|
|
@ -519,10 +517,7 @@ impl<'a> WitnessSet for DiscordMdWitnessSet<'a> {
|
||||||
let mut parent = self.witness.parent.write().unwrap();
|
let mut parent = self.witness.parent.write().unwrap();
|
||||||
if parent.dice_written >= MAX_DISPLAYED_DICE_PER_MESSAGE {
|
if parent.dice_written >= MAX_DISPLAYED_DICE_PER_MESSAGE {
|
||||||
if !self.dice_elided {
|
if !self.dice_elided {
|
||||||
write!(
|
write!(parent.buffers[self.witness.buffer_idx], "…")?;
|
||||||
parent.buffers[self.witness.buffer_idx],
|
|
||||||
"…"
|
|
||||||
)?;
|
|
||||||
self.dice_elided = true;
|
self.dice_elided = true;
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
||||||
66
src/main.rs
66
src/main.rs
|
|
@ -137,8 +137,7 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.unwrap_or(1)
|
.unwrap_or(1)
|
||||||
.min(MAX_ROLL_REPEATS as i64)
|
.clamp(1, MAX_ROLL_REPEATS as i64) as usize;
|
||||||
.max(1) as usize;
|
|
||||||
let private = options
|
let private = options
|
||||||
.iter()
|
.iter()
|
||||||
.find(|option| option.name == "private")
|
.find(|option| option.name == "private")
|
||||||
|
|
@ -170,9 +169,10 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.and_then(|s| s.parse::<u64>().ok());
|
.map(|s| s.parse::<u64>().context("Seed could not be parsed. Make sure it is a 64 bit integer between 0 and 2^64-1."))
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
let expression = parsing::parse(&formula).context("Dice formula could not be parsed.")?;
|
let expression = parsing::parse(formula).context("Dice formula could not be parsed.")?;
|
||||||
|
|
||||||
let seed = fixed_seed.unwrap_or_else(|| 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 mut rng = rand_xoshiro::Xoshiro256PlusPlus::seed_from_u64(seed);
|
||||||
|
|
@ -193,13 +193,13 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
|
|
||||||
let surrounding_par_count = pre_paragraphs.len() + post_paragraphs.len();
|
let surrounding_par_count = pre_paragraphs.len() + post_paragraphs.len();
|
||||||
|
|
||||||
let paragraphs = if repeat <= 40 - surrounding_par_count {
|
let roll_paragraphs = if repeat <= 40 - surrounding_par_count {
|
||||||
let discord_md = Arc::new(std::sync::RwLock::new(DiscordMd {
|
let discord_md = Arc::new(std::sync::RwLock::new(DiscordMd {
|
||||||
buffers: Vec::with_capacity(repeat),
|
buffers: Vec::with_capacity(repeat),
|
||||||
dice_written: 0,
|
dice_written: 0,
|
||||||
}));
|
}));
|
||||||
for _ in 0..repeat {
|
for _ in 0..repeat {
|
||||||
let mut witness = DiscordMd::create_witness(&discord_md);
|
let mut witness = DiscordMd::create_witness(discord_md.clone());
|
||||||
let result = expression.evaluate(&mut rng, &mut witness, i64::MAX)?;
|
let result = expression.evaluate(&mut rng, &mut witness, i64::MAX)?;
|
||||||
witness.witness_total_result(result)?;
|
witness.witness_total_result(result)?;
|
||||||
witness.end();
|
witness.end();
|
||||||
|
|
@ -208,7 +208,7 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
|
|
||||||
discord_md.buffers
|
discord_md.buffers
|
||||||
} else {
|
} else {
|
||||||
let mut par = String::new();
|
let mut par = String::with_capacity(8 * repeat);
|
||||||
for i in 0..repeat {
|
for i in 0..repeat {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
write!(par, ", ")?;
|
write!(par, ", ")?;
|
||||||
|
|
@ -222,9 +222,11 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
vec![par]
|
vec![par]
|
||||||
};
|
};
|
||||||
|
|
||||||
pre_paragraphs.extend(paragraphs);
|
let paragraphs = {
|
||||||
pre_paragraphs.extend(post_paragraphs);
|
pre_paragraphs.extend(roll_paragraphs);
|
||||||
let paragraphs = pre_paragraphs;
|
pre_paragraphs.extend(post_paragraphs);
|
||||||
|
pre_paragraphs
|
||||||
|
};
|
||||||
|
|
||||||
if paragraphs.iter().map(|s| s.chars().count()).sum::<usize>() > 4000
|
if paragraphs.iter().map(|s| s.chars().count()).sum::<usize>() > 4000
|
||||||
|| paragraphs.len() > 40
|
|| paragraphs.len() > 40
|
||||||
|
|
@ -253,27 +255,29 @@ pub async fn roll(ctx: &Context, command: &CommandInteraction) -> anyhow::Result
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(_) = inner(ctx, command).await {
|
match inner(ctx, command).await {
|
||||||
} else if let Err(err) = inner(ctx, command).await {
|
Ok(_) => {}
|
||||||
warn!("Error encountered: {err:?}");
|
Err(err) => {
|
||||||
command
|
warn!("Error encountered: {err:?}");
|
||||||
.create_response(
|
command
|
||||||
&ctx.http,
|
.create_response(
|
||||||
CreateInteractionResponse::Message(
|
&ctx.http,
|
||||||
CreateInteractionResponseMessage::new()
|
CreateInteractionResponse::Message(
|
||||||
.components(vec![CreateComponent::Container(CreateContainer::new(
|
CreateInteractionResponseMessage::new()
|
||||||
vec![CreateContainerComponent::TextDisplay(
|
.components(vec![CreateComponent::Container(CreateContainer::new(
|
||||||
CreateTextDisplay::new(err.to_string()),
|
vec![CreateContainerComponent::TextDisplay(
|
||||||
)],
|
CreateTextDisplay::new(err.to_string()),
|
||||||
))])
|
)],
|
||||||
// flags needs to be called before ephemeral for correct ordering
|
))])
|
||||||
.flags(
|
// flags needs to be called before ephemeral for correct ordering
|
||||||
MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS,
|
.flags(
|
||||||
)
|
MessageFlags::IS_COMPONENTS_V2 | MessageFlags::SUPPRESS_NOTIFICATIONS,
|
||||||
.ephemeral(true),
|
)
|
||||||
),
|
.ephemeral(true),
|
||||||
)
|
),
|
||||||
.await?
|
)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ fn expr<'c, 'i>(
|
||||||
)
|
)
|
||||||
.map(|(count, size, (kh, kl, dh, dl, x))| {
|
.map(|(count, size, (kh, kl, dh, dl, x))| {
|
||||||
Dice(DiceFormula {
|
Dice(DiceFormula {
|
||||||
count: count.map(|n| Box::new(n)),
|
count: count.map(Box::new),
|
||||||
size: Box::new(size),
|
size: Box::new(size),
|
||||||
kh: kh.map(|n| Box::new(n.unwrap_or(Const(1f64)))),
|
kh: kh.map(|n| Box::new(n.unwrap_or(Const(1f64)))),
|
||||||
kl: kl.map(|n| Box::new(n.unwrap_or(Const(1f64)))),
|
kl: kl.map(|n| Box::new(n.unwrap_or(Const(1f64)))),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue