aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Strapp <matt@mattstrapp.net>2024-12-13 09:16:42 -0600
committerMatt Strapp <matt@mattstrapp.net>2024-12-13 09:16:42 -0600
commit1598e7d21b5a4571db2d8d0be985b767056e267e (patch)
treeac25b90a9a57a0b88955843d6e80d6bdfbf6325b
parentput game loop in its own function (diff)
downloadwwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar.gz
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar.bz2
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar.lz
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar.xz
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.tar.zst
wwb-1598e7d21b5a4571db2d8d0be985b767056e267e.zip
add saving game state
Signed-off-by: Matt Strapp <matt@mattstrapp.net>
-rw-r--r--.gitignore5
-rw-r--r--wwb/Cargo.toml1
-rw-r--r--wwb/src/lib.rs8
-rw-r--r--wwb/src/main.rs50
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<String> = 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;