diff --git a/Cargo.lock b/Cargo.lock index 0c74ca3..4b6dafc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "bitflags" @@ -202,7 +202,7 @@ dependencies = [ "crossterm_winapi", "libc", "mio", - "parking_lot", + "parking_lot 0.11.2", "signal-hook", "signal-hook-mio", "winapi", @@ -393,10 +393,11 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" dependencies = [ + "autocfg", "scopeguard", ] @@ -494,6 +495,12 @@ dependencies = [ "libc", ] +[[package]] +name = "once_cell" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" + [[package]] name = "oorandom" version = "11.1.3" @@ -517,7 +524,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.3", ] [[package]] @@ -534,6 +551,19 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + [[package]] name = "pipes-rs" version = "1.4.7" @@ -689,8 +719,9 @@ checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" name = "rng" version = "0.0.0" dependencies = [ - "getrandom", + "once_cell", "oorandom", + "parking_lot 0.12.1", ] [[package]] @@ -1059,3 +1090,46 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" diff --git a/crates/model/src/direction.rs b/crates/model/src/direction.rs index a122e7e..ae46986 100644 --- a/crates/model/src/direction.rs +++ b/crates/model/src/direction.rs @@ -1,5 +1,3 @@ -use rng::Rng; - #[derive(Clone, Copy, PartialEq)] pub(crate) enum Direction { Up, @@ -9,11 +7,11 @@ pub(crate) enum Direction { } impl Direction { - pub(crate) fn maybe_turn(&mut self, rng: &mut Rng, turn_chance: f32) { - let will_turn = rng.gen_bool(turn_chance); + pub(crate) fn maybe_turn(&mut self, turn_chance: f32) { + let will_turn = rng::gen_bool(turn_chance); if will_turn { - let random_turn_dir = TurnDirection::gen(rng); + let random_turn_dir = TurnDirection::gen(); self.turn(random_turn_dir); } } @@ -50,8 +48,8 @@ enum TurnDirection { } impl TurnDirection { - fn gen(rng: &mut Rng) -> Self { - if rng.gen_bool(0.5) { + fn gen() -> Self { + if rng::gen_bool(0.5) { Self::Left } else { Self::Right @@ -60,8 +58,8 @@ impl TurnDirection { } impl Direction { - pub(crate) fn gen(rng: &mut Rng) -> Self { - match rng.gen_range(0..4) { + pub(crate) fn gen() -> Self { + match rng::gen_range(0..4) { 0 => Direction::Up, 1 => Direction::Down, 2 => Direction::Left, diff --git a/crates/model/src/pipe.rs b/crates/model/src/pipe.rs index 24ad7aa..c598fc6 100644 --- a/crates/model/src/pipe.rs +++ b/crates/model/src/pipe.rs @@ -8,7 +8,6 @@ pub use kind::{Kind, KindSet}; use crate::direction::Direction; use crate::position::{InScreenBounds, Position}; -use rng::Rng; pub struct Pipe { dir: HistoryKeeper, @@ -18,15 +17,9 @@ pub struct Pipe { } impl Pipe { - pub fn new( - size: (u16, u16), - rng: &mut Rng, - color_mode: ColorMode, - palette: Palette, - kind: Kind, - ) -> Self { - let color = color::gen_random_color(rng, color_mode, palette); - let (dir, pos) = Self::gen_rand_dir_and_pos(size, rng); + pub fn new(size: (u16, u16), color_mode: ColorMode, palette: Palette, kind: Kind) -> Self { + let color = color::gen_random_color(color_mode, palette); + let (dir, pos) = Self::gen_rand_dir_and_pos(size); Self { dir: HistoryKeeper::new(dir), @@ -36,8 +29,8 @@ impl Pipe { } } - pub fn dup(&self, size: (u16, u16), rng: &mut Rng) -> Self { - let (dir, pos) = Self::gen_rand_dir_and_pos(size, rng); + pub fn dup(&self, size: (u16, u16)) -> Self { + let (dir, pos) = Self::gen_rand_dir_and_pos(size); Self { dir: HistoryKeeper::new(dir), @@ -47,14 +40,14 @@ impl Pipe { } } - pub fn tick(&mut self, size: (u16, u16), rng: &mut Rng, turn_chance: f32) -> InScreenBounds { + pub fn tick(&mut self, size: (u16, u16), turn_chance: f32) -> InScreenBounds { let InScreenBounds(in_screen_bounds) = self.pos.move_in(self.dir.current(), size); if !in_screen_bounds { return InScreenBounds(false); } - self.dir.update(|dir| dir.maybe_turn(rng, turn_chance)); + self.dir.update(|dir| dir.maybe_turn(turn_chance)); InScreenBounds(true) } @@ -84,24 +77,24 @@ impl Pipe { } } - fn gen_rand_dir_and_pos((columns, rows): (u16, u16), rng: &mut Rng) -> (Direction, Position) { - let dir = Direction::gen(rng); + fn gen_rand_dir_and_pos((columns, rows): (u16, u16)) -> (Direction, Position) { + let dir = Direction::gen(); let pos = match dir { Direction::Up => Position { - x: rng.gen_range_16(0..columns), + x: rng::gen_range_16(0..columns), y: rows - 1, }, Direction::Down => Position { - x: rng.gen_range_16(0..columns), + x: rng::gen_range_16(0..columns), y: 0, }, Direction::Left => Position { x: columns - 1, - y: rng.gen_range_16(0..rows), + y: rng::gen_range_16(0..rows), }, Direction::Right => Position { x: 0, - y: rng.gen_range_16(0..rows), + y: rng::gen_range_16(0..rows), }, }; diff --git a/crates/model/src/pipe/color.rs b/crates/model/src/pipe/color.rs index 96663e3..0314b7e 100644 --- a/crates/model/src/pipe/color.rs +++ b/crates/model/src/pipe/color.rs @@ -1,22 +1,17 @@ -use rng::Rng; use std::ops::Range; use std::str::FromStr; use tincture::ColorSpace; -pub(super) fn gen_random_color( - rng: &mut Rng, - color_mode: ColorMode, - palette: Palette, -) -> Option { +pub(super) fn gen_random_color(color_mode: ColorMode, palette: Palette) -> Option { match color_mode { - ColorMode::Ansi => Some(gen_random_ansi_color(rng)), - ColorMode::Rgb => Some(gen_random_rgb_color(rng, palette)), + ColorMode::Ansi => Some(gen_random_ansi_color()), + ColorMode::Rgb => Some(gen_random_rgb_color(palette)), ColorMode::None => None, } } -fn gen_random_ansi_color(rng: &mut Rng) -> terminal::Color { - let num = rng.gen_range(0..12); +fn gen_random_ansi_color() -> terminal::Color { + let num = rng::gen_range(0..12); match num { 0 => terminal::Color::Red, @@ -35,9 +30,9 @@ fn gen_random_ansi_color(rng: &mut Rng) -> terminal::Color { } } -fn gen_random_rgb_color(rng: &mut Rng, palette: Palette) -> terminal::Color { - let hue = rng.gen_range_float(palette.get_hue_range()); - let lightness = rng.gen_range_float(palette.get_lightness_range()); +fn gen_random_rgb_color(palette: Palette) -> terminal::Color { + let hue = rng::gen_range_float(palette.get_hue_range()); + let lightness = rng::gen_range_float(palette.get_lightness_range()); let oklch = tincture::Oklch { l: lightness, diff --git a/crates/model/src/pipe/kind.rs b/crates/model/src/pipe/kind.rs index 4308c14..3363ad0 100644 --- a/crates/model/src/pipe/kind.rs +++ b/crates/model/src/pipe/kind.rs @@ -1,4 +1,3 @@ -use rng::Rng; use std::num::NonZeroUsize; use std::str::FromStr; @@ -130,8 +129,8 @@ impl KindSet { Self(vec![kind]) } - pub fn choose_random(&self, rng: &mut Rng) -> Kind { - let idx = rng.gen_range(0..self.0.len() as u32); + pub fn choose_random(&self) -> Kind { + let idx = rng::gen_range(0..self.0.len() as u32); self.0[idx as usize] } diff --git a/crates/pipes-rs/src/lib.rs b/crates/pipes-rs/src/lib.rs index efc4d69..aa10572 100644 --- a/crates/pipes-rs/src/lib.rs +++ b/crates/pipes-rs/src/lib.rs @@ -3,13 +3,11 @@ pub use config::Config; use model::pipe::{KindSet, Pipe}; use model::position::InScreenBounds; -use rng::Rng; use std::thread; use terminal::{Backend, Event, Terminal}; pub struct App { terminal: Terminal, - rng: Rng, config: Config, kinds: KindSet, } @@ -21,11 +19,8 @@ impl App { let largest_custom_width = kinds.custom_widths().max(); let terminal = Terminal::new(backend, kinds.chars(), largest_custom_width)?; - let rng = Rng::new()?; - Ok(Self { terminal, - rng, config, kinds, }) @@ -91,15 +86,12 @@ impl App { } fn tick_pipe(&mut self, pipe: &mut Pipe) { - let InScreenBounds(stayed_onscreen) = pipe.tick( - self.terminal.size(), - &mut self.rng, - self.config.turn_chance(), - ); + let InScreenBounds(stayed_onscreen) = + pipe.tick(self.terminal.size(), self.config.turn_chance()); if !stayed_onscreen { *pipe = if self.config.inherit_style() { - pipe.dup(self.terminal.size(), &mut self.rng) + pipe.dup(self.terminal.size()) } else { self.create_pipe() }; @@ -113,7 +105,7 @@ impl App { self.terminal.set_text_color(color)?; } - self.terminal.print(if self.rng.gen_bool(0.99999) { + self.terminal.print(if rng::gen_bool(0.99999) { pipe.to_char() } else { '🦀' @@ -129,11 +121,10 @@ impl App { } fn create_pipe(&mut self) -> Pipe { - let kind = self.kinds.choose_random(&mut self.rng); + let kind = self.kinds.choose_random(); Pipe::new( self.terminal.size(), - &mut self.rng, self.config.color_mode(), self.config.palette(), kind, diff --git a/crates/rng/Cargo.toml b/crates/rng/Cargo.toml index 5128c65..da88a76 100644 --- a/crates/rng/Cargo.toml +++ b/crates/rng/Cargo.toml @@ -5,5 +5,6 @@ name = "rng" version = "0.0.0" [dependencies] -getrandom = "0.2.2" +once_cell = "1.13.0" oorandom = "11.1" +parking_lot = "0.12.1" diff --git a/crates/rng/src/lib.rs b/crates/rng/src/lib.rs index 236e966..590b09f 100644 --- a/crates/rng/src/lib.rs +++ b/crates/rng/src/lib.rs @@ -1,42 +1,39 @@ +use once_cell::sync::Lazy; +use parking_lot::Mutex; use std::ops::Range; -pub struct Rng { - rand_32: oorandom::Rand32, -} - -impl Rng { - pub fn new() -> Result { - let seed_64 = gen_seed()?; - - Ok(Self { - rand_32: oorandom::Rand32::new(seed_64), - }) - } +static RNG: Lazy> = Lazy::new(|| { + let seed = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .expect("system time cannot be before unix epoch") + .as_millis() as u64; - pub fn gen_range(&mut self, range: Range) -> u32 { - self.rand_32.rand_range(range) - } + Mutex::new(Rng { + rand_32: oorandom::Rand32::new(seed), + }) +}); - pub fn gen_range_float(&mut self, range: Range) -> f32 { - self.rand_32.rand_float() * (range.end - range.start) + range.start - } +struct Rng { + rand_32: oorandom::Rand32, +} - pub fn gen_range_16(&mut self, range: Range) -> u16 { - self.rand_32 - .rand_range(range.start as u32..range.end as u32) as u16 - } +pub fn gen_range(range: Range) -> u32 { + RNG.lock().rand_32.rand_range(range) +} - pub fn gen_bool(&mut self, probability: f32) -> bool { - assert!(probability >= 0.0); - assert!(probability <= 1.0); +pub fn gen_range_float(range: Range) -> f32 { + RNG.lock().rand_32.rand_float() * (range.end - range.start) + range.start +} - self.rand_32.rand_float() < probability - } +pub fn gen_range_16(range: Range) -> u16 { + RNG.lock() + .rand_32 + .rand_range(range.start as u32..range.end as u32) as u16 } -fn gen_seed() -> Result { - let mut seed_64 = [0; 8]; - getrandom::getrandom(&mut seed_64)?; +pub fn gen_bool(probability: f32) -> bool { + assert!(probability >= 0.0); + assert!(probability <= 1.0); - Ok(u64::from_le_bytes(seed_64)) + RNG.lock().rand_32.rand_float() < probability }