From 28f927e153d03a46af009c39b5e70a6350dc2cd4 Mon Sep 17 00:00:00 2001 From: Jay Oster Date: Sat, 2 Nov 2019 15:29:09 -0700 Subject: [PATCH] Switch from rand_core to randomize (#31) - For #7 --- Cargo.lock | 19 +++++++++-------- Cargo.toml | 2 ++ examples/invaders/main.rs | 17 ++++++++++++++- simple-invaders/Cargo.toml | 6 +++++- simple-invaders/src/lib.rs | 42 ++++++++++++++++++++++++++++++-------- 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcedc6b..d333bde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,7 +329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -791,7 +791,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "pixels" version = "0.0.1" dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "gilrs 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pixels-mocks 0.1.0", @@ -851,12 +853,9 @@ dependencies = [ ] [[package]] -name = "rand_core" -version = "0.5.1" +name = "randomize" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "range-alloc" @@ -1047,9 +1046,11 @@ dependencies = [ name = "simple-invaders" version = "0.1.0" dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "line_drawing 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "pcx 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "randomize 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1579,7 +1580,7 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum gfx-backend-dx11 0.3.0 (git+https://github.com/gfx-rs/gfx?rev=3d5db15661127c8cad8d85522a68ec36c82f6e69)" = "" "checksum gfx-backend-dx12 0.3.0 (git+https://github.com/gfx-rs/gfx?rev=3d5db15661127c8cad8d85522a68ec36c82f6e69)" = "" "checksum gfx-backend-empty 0.3.0 (git+https://github.com/gfx-rs/gfx?rev=3d5db15661127c8cad8d85522a68ec36c82f6e69)" = "" @@ -1633,7 +1634,7 @@ dependencies = [ "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +"checksum randomize 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c38c99b51f33c9fcc655252bf02ac8048eb70f35244e4697b0de9c473e940a" "checksum range-alloc 0.1.0 (git+https://github.com/gfx-rs/gfx?rev=3d5db15661127c8cad8d85522a68ec36c82f6e69)" = "" "checksum raw-window-handle 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e815b85b31e4d397ca9dd8eb1d692e9cb458b9f6ae8ac2232c995dca8236f87" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" diff --git a/Cargo.toml b/Cargo.toml index 43b41ee..7a3cd14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,9 @@ license = "MIT" wgpu = { git = "https://github.com/gfx-rs/wgpu-rs", rev = "012d08d64de924da93289c2b51fb06b22d7348cf" } [dev-dependencies] +byteorder = "1.3" env_logger = "0.7" +getrandom = "0.1" gilrs = "0.7" log = { version = "0.4", features = ["release_max_level_warn"] } pixels-mocks = { path = "pixels-mocks" } diff --git a/examples/invaders/main.rs b/examples/invaders/main.rs index 7d72f11..8b5ae31 100644 --- a/examples/invaders/main.rs +++ b/examples/invaders/main.rs @@ -26,7 +26,7 @@ fn main() -> Result<(), Error> { create_window("pixel invaders", &event_loop); let surface_texture = SurfaceTexture::new(width, height, surface); let mut pixels = Pixels::new(SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32, surface_texture)?; - let mut invaders = World::new(debug); + let mut invaders = World::new(generate_seed(), debug); let mut time = Instant::now(); let mut gamepad = None; @@ -169,3 +169,18 @@ fn create_window( hidpi_factor, ) } + +/// Generate a pseudorandom seed for the game's PRNG. +fn generate_seed() -> (u64, u64) { + use byteorder::{ByteOrder, NativeEndian}; + use getrandom::getrandom; + + let mut seed = [0_u8; 16]; + + getrandom(&mut seed).expect("failed to getrandom"); + + ( + NativeEndian::read_u64(&seed[0..8]), + NativeEndian::read_u64(&seed[8..16]), + ) +} diff --git a/simple-invaders/Cargo.toml b/simple-invaders/Cargo.toml index 4413b62..0b3c63c 100644 --- a/simple-invaders/Cargo.toml +++ b/simple-invaders/Cargo.toml @@ -7,4 +7,8 @@ edition = "2018" [dependencies] line_drawing = "0.8" pcx = "0.2" -rand_core = { version = "0.5", features = ["std"] } +randomize = "3.0" + +[dev-dependencies] +byteorder = "1.3" +getrandom = "0.1" diff --git a/simple-invaders/src/lib.rs b/simple-invaders/src/lib.rs index d92a55c..f05df65 100644 --- a/simple-invaders/src/lib.rs +++ b/simple-invaders/src/lib.rs @@ -4,14 +4,14 @@ //! this in practice. That said, the game is fully functional, and it should not be too difficult //! to understand the code. -use rand_core::{OsRng, RngCore}; use std::time::Duration; +use crate::collision::Collision; pub use crate::controls::{Controls, Direction}; use crate::geo::Point; use crate::loader::{load_assets, Assets}; use crate::sprites::{blit, Animation, Drawable, Frame, Sprite, SpriteRef}; -use collision::Collision; +use randomize::PCG32; mod collision; mod controls; @@ -50,7 +50,7 @@ pub struct World { assets: Assets, dt: Duration, gameover: bool, - random: OsRng, + prng: PCG32, debug: bool, } @@ -118,7 +118,30 @@ struct Bullet { impl World { /// Create a new simple-invaders `World`. - pub fn new(debug: bool) -> World { + /// + /// # Arguments + /// + /// * `debug` - Enable debug visualizations. + /// * `seed` - Inputs for the pseudorandom number generator. + /// + /// # Example + /// + /// ``` + /// use byteorder::{ByteOrder, NativeEndian}; + /// use getrandom::getrandom; + /// use simple_invaders::World; + /// + /// // Create a seed for the PRNG + /// let mut seed = [0_u8; 16]; + /// getrandom(&mut seed).expect("failed to getrandom"); + /// let seed = ( + /// NativeEndian::read_u64(&seed[0..8]), + /// NativeEndian::read_u64(&seed[8..16]), + /// ); + /// + /// let world = World::new(seed, false); + /// ``` + pub fn new(seed: (u64, u64), debug: bool) -> World { use Frame::*; // Load assets first @@ -150,7 +173,7 @@ impl World { let dt = Duration::default(); let gameover = false; - let random = OsRng; + let prng = PCG32::seed(seed.0, seed.1); World { invaders, @@ -163,7 +186,7 @@ impl World { assets, dt, gameover, - random, + prng, debug, } } @@ -353,7 +376,7 @@ impl World { invader.sprite.step_frame(&self.assets); // They also shoot lasers at random with a 1:50 chance - let r = self.random.next_u32() as usize; + let r = self.prng.next_u32() as usize; let chance = r % 50; if self.lasers.len() < 3 && chance == 0 { // Pick a random column to begin searching for an invader that can fire a laser @@ -400,9 +423,12 @@ impl World { } } +/// Create a default `World` with a static PRNG seed. impl Default for World { fn default() -> Self { - World::new(false) + let seed = (6_364_136_223_846_793_005, 1); + + World::new(seed, false) } }