initial commit
commit
02bd016c8f
|
@ -0,0 +1,56 @@
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/nova,rust,macos
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=nova,rust,macos
|
||||||
|
|
||||||
|
### macOS ###
|
||||||
|
# General
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
|
||||||
|
# Icon must end with two \r
|
||||||
|
Icon
|
||||||
|
|
||||||
|
|
||||||
|
# Thumbnails
|
||||||
|
._*
|
||||||
|
|
||||||
|
# Files that might appear in the root of a volume
|
||||||
|
.DocumentRevisions-V100
|
||||||
|
.fseventsd
|
||||||
|
.Spotlight-V100
|
||||||
|
.TemporaryItems
|
||||||
|
.Trashes
|
||||||
|
.VolumeIcon.icns
|
||||||
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
|
# Directories potentially created on remote AFP share
|
||||||
|
.AppleDB
|
||||||
|
.AppleDesktop
|
||||||
|
Network Trash Folder
|
||||||
|
Temporary Items
|
||||||
|
.apdisk
|
||||||
|
|
||||||
|
### macOS Patch ###
|
||||||
|
# iCloud generated files
|
||||||
|
*.icloud
|
||||||
|
|
||||||
|
### nova ###
|
||||||
|
.nova/*
|
||||||
|
|
||||||
|
### Rust ###
|
||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/nova,rust,macos
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "dice-roll"
|
||||||
|
authors = ["Alina Marquardt <lastfuture@lastfuture.de>"]
|
||||||
|
version = "0.2.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rand = "0.8.5"
|
||||||
|
regex = "1"
|
||||||
|
dialoguer = { version = "0.10.3", features = ["history"] }
|
|
@ -0,0 +1,133 @@
|
||||||
|
use dialoguer::{theme::ColorfulTheme, Input, History};
|
||||||
|
use std::collections::VecDeque;
|
||||||
|
use rand::prelude::*;
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
struct Die {
|
||||||
|
sides: u32,
|
||||||
|
roll: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*impl Die {
|
||||||
|
fn crit(&self) -> bool {
|
||||||
|
self.sides == self.roll
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fn parse_dice(dice_string: &str) -> (Vec<Die>, String) {
|
||||||
|
let mut dice: Vec<Die> = vec![];
|
||||||
|
let re = Regex::new(r"(\d+)d(\d+)").unwrap();
|
||||||
|
let mut parsed_string = String::new();
|
||||||
|
for die in re.captures_iter(dice_string) {
|
||||||
|
let dice_num: u32 = die[1].parse().unwrap();
|
||||||
|
let sides: u32 = die[2].parse().unwrap();
|
||||||
|
if dice_num > 0 && sides > 0 {
|
||||||
|
parsed_string.push_str(&format!("{}d{} + ", dice_num, sides));
|
||||||
|
for _ in 0..dice_num {
|
||||||
|
dice.push(Die {
|
||||||
|
sides,
|
||||||
|
roll: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let parsed_string = &parsed_string;
|
||||||
|
let mut parsed_string = parsed_string.chars();
|
||||||
|
for _ in 0..3 {
|
||||||
|
parsed_string.next_back();
|
||||||
|
}
|
||||||
|
let mut parsed_string = parsed_string.as_str();
|
||||||
|
if dice.is_empty() {
|
||||||
|
parsed_string = "nothing";
|
||||||
|
}
|
||||||
|
(dice, parsed_string.to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roll_dice(dice_to_roll: Vec<Die>) -> Vec<Die> {
|
||||||
|
let mut dice: Vec<Die> = vec![];
|
||||||
|
for die in dice_to_roll {
|
||||||
|
dice.push(roll_die(die));
|
||||||
|
}
|
||||||
|
dice
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roll_die(die_to_roll: Die) -> Die {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
Die {
|
||||||
|
sides: die_to_roll.sides,
|
||||||
|
roll: rng.gen_range(1..=die_to_roll.sides),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!();
|
||||||
|
println!("Use the Up/Down arrows to scroll through history");
|
||||||
|
let mut history = MyHistory::default();
|
||||||
|
loop {
|
||||||
|
println!();
|
||||||
|
|
||||||
|
let input: String = Input::<String>::with_theme(&ColorfulTheme::default())
|
||||||
|
.with_prompt("Roll dice (ex. \"2d8 3d4\") or \"q\"")
|
||||||
|
.history_with(&mut history)
|
||||||
|
.interact_text()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let dice_string: &str = &input.trim().to_lowercase(); // trim and lowercase
|
||||||
|
|
||||||
|
if dice_string.eq("q") { break; }
|
||||||
|
|
||||||
|
let (mut dice, dice_string) = parse_dice(dice_string);
|
||||||
|
|
||||||
|
print!("Rolling {}", dice_string);
|
||||||
|
dice = roll_dice(dice);
|
||||||
|
|
||||||
|
let mut last = 0;
|
||||||
|
let mut sum = 0;
|
||||||
|
for die in dice {
|
||||||
|
if last != die.sides {
|
||||||
|
println!();
|
||||||
|
print!("d{}: ", die.sides);
|
||||||
|
} else {
|
||||||
|
print!(" + ");
|
||||||
|
}
|
||||||
|
print!("{}", die.roll);
|
||||||
|
sum += die.roll;
|
||||||
|
last = die.sides;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!();
|
||||||
|
println!("--==--");
|
||||||
|
println!("SUM: {}", sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("bye.");
|
||||||
|
|
||||||
|
//println!("{} ({} sided die) was a {} {}", die.name, die.sides, die.roll, {if die.crit() {"and A CRIT!"} else {""}});
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MyHistory {
|
||||||
|
max: usize,
|
||||||
|
history: VecDeque<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for MyHistory {
|
||||||
|
fn default() -> Self {
|
||||||
|
MyHistory {
|
||||||
|
max: 20,
|
||||||
|
history: VecDeque::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ToString> History<T> for MyHistory {
|
||||||
|
fn read(&self, pos: usize) -> Option<String> {
|
||||||
|
self.history.get(pos).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, val: &T) {
|
||||||
|
if self.history.len() == self.max {
|
||||||
|
self.history.pop_back();
|
||||||
|
}
|
||||||
|
self.history.push_front(val.to_string());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue