From 1598e7d21b5a4571db2d8d0be985b767056e267e Mon Sep 17 00:00:00 2001 From: Matt Strapp Date: Fri, 13 Dec 2024 09:16:42 -0600 Subject: add saving game state Signed-off-by: Matt Strapp --- .gitignore | 5 ++++- wwb/Cargo.toml | 1 + wwb/src/lib.rs | 8 +++++--- wwb/src/main.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 57 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index d01bd1a..41767ab 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,7 @@ Cargo.lock # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # and can be added to the global gitignore or merged into this file. For a more nuclear # option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file +#.idea/ + +output.log +game.bin \ No newline at end of file diff --git a/wwb/Cargo.toml b/wwb/Cargo.toml index 58095a2..12b2d26 100644 --- a/wwb/Cargo.toml +++ b/wwb/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +bincode = "=2.0.0-rc.3" chrono = "0.4.39" ctrlc = "3.4.5" env_logger = "0.11.5" diff --git a/wwb/src/lib.rs b/wwb/src/lib.rs index 84838c6..7815efc 100644 --- a/wwb/src/lib.rs +++ b/wwb/src/lib.rs @@ -1,8 +1,10 @@ +use bincode::{Decode, Encode}; + /// WWB is a 2-player game at heart. Hardcode 2 players only so no one else has to suffer pub const PLAYER_COUNT: usize = 2; -pub const BOARD_SIZE: u16 = 100 ; +pub const BOARD_SIZE: u16 = 100; -#[derive(Debug, Default)] +#[derive(Encode, Decode, Debug, Default, PartialEq)] pub struct Game { /// We're going to need an insanely large number for the turn count. Previous attempts crashed at trillions of turns. pub turn_count: u128, @@ -10,7 +12,7 @@ pub struct Game { pub players: [Player; PLAYER_COUNT], } -#[derive(Debug, Default)] +#[derive(Encode, Decode, Debug, Default, PartialEq)] pub struct Player { // name: String, /// The current space the player is on. The default game board is a 1D array of 100 spaces. diff --git a/wwb/src/main.rs b/wwb/src/main.rs index 08f0aba..2399e73 100644 --- a/wwb/src/main.rs +++ b/wwb/src/main.rs @@ -1,18 +1,59 @@ +use bincode::config; use chrono::Local; use env_logger::{Builder, Env, Target}; use locusts::introduce_locusts; +use std::fs; use std::io::Write; use std::process::exit; use std::sync::{Arc, Mutex}; use wwb::*; +static BINCODE_COFNIG: config::Configuration = config::standard(); + /// Roll a d6 and return the result. fn roll_d6() -> u8 { fastrand::u8(1..=6) } +/// Save the game state to a file. +/// +/// Note: If there is no path, the game will not be saved. +fn save_game(game: &Game, path: &str) { + if path.is_empty() { + return; + } + let serialized_game = bincode::encode_to_vec(game, BINCODE_COFNIG).unwrap(); + fs::write(path, serialized_game).unwrap(); +} + +/// Load the game state from a file. +/// Note: If there is no path, the game will not be loaded. +fn load_game(path: &str) -> Game { + if path.is_empty() { + return Game::default(); + } + match fs::read(path) { + Ok(serialized_game) => { + let (game, _): (Game, usize) = + bincode::decode_from_slice(&serialized_game, BINCODE_COFNIG).unwrap(); + game + } + Err(_) => { + Game::default() + } + } +} + fn main() { introduce_locusts(); + + let args: Vec = std::env::args().collect(); + let path = if args.len() > 1 { + args[1].clone() + } else { + "".to_string() + }; + let env = Env::new().filter_or("RUST_LOG", "info"); // Create logger Builder::from_env(env) @@ -27,18 +68,20 @@ fn main() { .target(Target::Stdout) .init(); - game_loop(); + game_loop(path); } -fn game_loop() { - let game = Arc::new(Mutex::new(Game::default())); +fn game_loop(path: String) { + let game = Arc::new(Mutex::new(load_game(&path))); // Set up Ctrl-C handler to print the game state before exiting. let game_clone = Arc::clone(&game); + let path_clone = path.clone(); ctrlc::set_handler(move || { let game = game_clone.lock().unwrap(); println!("Game state at exit:"); log::error!("{:#?}", *game); + save_game(&game, &path_clone); exit(0); }) .expect("Error setting Ctrl-C handler"); @@ -99,6 +142,7 @@ fn game_loop() { .join(",") ); game.players[current_player_number].high_score = current_space; + save_game(&game, &path); } let mut collision: bool = false; -- cgit v1.2.3