diff options
Diffstat (limited to '2020-overdrive/src/json.rs')
-rw-r--r-- | 2020-overdrive/src/json.rs | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/2020-overdrive/src/json.rs b/2020-overdrive/src/json.rs new file mode 100644 index 0000000..82fc9fc --- /dev/null +++ b/2020-overdrive/src/json.rs @@ -0,0 +1,185 @@ +use std::convert::TryInto; +use std::fs::File; +use std::io::prelude::*; +use std::rc::Rc; + +use anyhow::Result; +use serde::{Deserialize, Serialize}; +use serde_json; +use serde_repr::{Deserialize_repr, Serialize_repr}; + +use crate::state::*; + +pub fn read_state_from_json_file(filename: &str) -> Result<GameState> { + let mut file = File::open(filename)?; + let mut content = String::new(); + file.read_to_string(&mut content)?; + let json_state: JsonState = serde_json::from_str(content.as_ref())?; + json_state.to_game_state() +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct JsonState { + // pub current_round: usize, + // pub max_rounds: usize, + pub player: JsonPlayer, + pub opponent: JsonOpponent, + pub world_map: Vec<Vec<JsonWorldMapCell>>, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct JsonPlayer { + // id: usize, + position: JsonPosition, + speed: u16, + // state: JsonPlayerState, + powerups: Vec<JsonPowerup>, + // boosting: bool, + boost_counter: u8, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct JsonOpponent { + // id: usize, + position: JsonPosition, + speed: u16, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct JsonWorldMapCell { + position: JsonPosition, + surface_object: JsonSurfaceObject, + // occupied_by_player_id: usize, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +pub struct JsonPosition { + y: u8, + x: u16, +} + +// #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +// #[serde(rename_all = "SCREAMING_SNAKE_CASE")] +// pub enum JsonPlayerState { +// Ready, +// Nothing, +// TurningLeft, +// TurningRight, +// Accelerating, +// Decelarating, +// PickedUpPowerup, +// UsedBoost, +// UsedOil, +// HitMud, +// HitOil, +// Finishing, +// } + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +pub enum JsonPowerup { + Boost, + Oil, +} + +#[derive(Serialize_repr, Deserialize_repr, Clone, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase")] +#[repr(u8)] +pub enum JsonSurfaceObject { + Empty = 0, + Mud = 1, + OilSpill = 2, + OilItem = 3, + FinishLine = 4, + Boost = 5, +} + +impl JsonState { + fn to_game_state(&self) -> Result<GameState> { + Ok(GameState { + status: GameStatus::Continue, + players: [self.player.to_player()?, self.opponent.to_player()], + muds: Rc::new( + self.world_map + .iter() + .flatten() + .filter(|cell| cell.surface_object == JsonSurfaceObject::Mud) + .map(|cell| cell.position.to_position()) + .collect(), + ), + oil_spills: Rc::new( + self.world_map + .iter() + .flatten() + .filter(|cell| cell.surface_object == JsonSurfaceObject::OilSpill) + .map(|cell| cell.position.to_position()) + .collect(), + ), + powerup_oils: Rc::new( + self.world_map + .iter() + .flatten() + .filter(|cell| cell.surface_object == JsonSurfaceObject::OilItem) + .map(|cell| cell.position.to_position()) + .collect(), + ), + powerup_boosts: Rc::new( + self.world_map + .iter() + .flatten() + .filter(|cell| cell.surface_object == JsonSurfaceObject::Boost) + .map(|cell| cell.position.to_position()) + .collect(), + ), + }) + } +} + +impl JsonPlayer { + fn to_player(&self) -> Result<Player> { + Ok(Player { + position: self.position.to_position(), + speed: self.speed, + boost_remaining: self.boost_counter, + oils: self + .powerups + .iter() + .filter(|powerup| **powerup == JsonPowerup::Oil) + .count() + .try_into()?, + boosts: self + .powerups + .iter() + .filter(|powerup| **powerup == JsonPowerup::Boost) + .count() + .try_into()?, + }) + } +} + +impl JsonOpponent { + // TODO: Track opponent powerups from round to round? + fn to_player(&self) -> Player { + Player { + position: self.position.to_position(), + speed: self.speed, + boost_remaining: 0, + oils: 0, + boosts: 0, + } + } +} + +impl JsonPosition { + fn to_position(&self) -> Position { + Position { + x: self.x, + y: self.y, + } + } +} |