diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 92 | ||||
-rw-r--r-- | Cargo.toml | 5 | ||||
-rw-r--r-- | src/actions.rs | 4 | ||||
-rw-r--r-- | src/files.rs | 21 | ||||
-rw-r--r-- | src/knowledge.rs | 54 | ||||
-rw-r--r-- | src/lib.rs | 25 | ||||
-rw-r--r-- | src/math.rs | 4 | ||||
-rw-r--r-- | src/ships.rs | 19 | ||||
-rw-r--r-- | src/state.rs | 30 |
10 files changed, 244 insertions, 11 deletions
@@ -1,2 +1,3 @@ /target +/knowledge-state.json @@ -4,9 +4,22 @@ version = "0.1.0" dependencies = [ "json 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] +name = "dtoa" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itoa" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "json" version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -17,6 +30,16 @@ version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "num-traits" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "rand" version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -24,7 +47,76 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_derive_internals" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] +"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90" +"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c" "checksum json 0.11.6 (registry+https://github.com/rust-lang/crates.io-index)" = "27600e8bb3b71bcc6213fb36b66b8dce60adc17a624257687ef5d1d4facafba7" "checksum libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "babb8281da88cba992fa1f4ddec7d63ed96280a1a53ec9b919fd37b53d71e502" +"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99" +"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" +"checksum serde 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "991ef6be409a3b7a46cb9ee701d86156ce851825c65dbee7f16dbd5c4e7e2d47" +"checksum serde_derive 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd81eef9f0b4ec341b11095335b6a4b28ed85581b12dd27585dee1529df35e0" +"checksum serde_derive_internals 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "021c338d22c7e30f957a6ab7e388cb6098499dda9fd4ba1661ee074ca7a180d1" +"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" @@ -5,4 +5,7 @@ authors = ["Justin Worthe <justin.worthe@gmail.com>"] [dependencies] rand = "0.3" -json = "0.11.6"
\ No newline at end of file +json = "0.11.6" +serde = "1.0.4" +serde_json = "1.0.2" +serde_derive = "1.0.4"
\ No newline at end of file diff --git a/src/actions.rs b/src/actions.rs index 1b6400d..9009099 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -5,7 +5,7 @@ use std::fmt; use std::collections::HashSet; -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub enum Action { PlaceShips(Vec<ShipPlacement>), Shoot(Point) @@ -22,7 +22,7 @@ impl fmt::Display for Action { } } -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] pub struct ShipPlacement { ship_type: Ship, point: Point, diff --git a/src/files.rs b/src/files.rs index 7f3daed..0810a4e 100644 --- a/src/files.rs +++ b/src/files.rs @@ -1,15 +1,21 @@ use json; +use serde_json; + use std::io::prelude::*; use std::fs::File; use std::path::PathBuf; use actions::*; +use knowledge::*; const STATE_FILE: &'static str = "state.json"; const COMMAND_FILE: &'static str = "command.txt"; const PLACE_FILE: &'static str = "place.txt"; +const KNOWLEDGE_FILE: &'static str = "knowledge-state.json"; + + pub fn read_file(working_dir: &PathBuf) -> Result<json::JsonValue, String> { let state_path = working_dir.join(STATE_FILE); let mut file = File::open(state_path.as_path()).map_err(|e| e.to_string())?; @@ -34,3 +40,18 @@ pub fn write_action(working_dir: &PathBuf, is_place_phase: bool, action: Action) Ok(()) } + +pub fn read_knowledge() -> Result<Knowledge, String> { + let mut file = File::open(KNOWLEDGE_FILE).map_err(|e| e.to_string())?; + let mut content = String::new(); + file.read_to_string(&mut content).map_err(|e| e.to_string())?; + serde_json::from_str(content.as_ref()).map_err(|e| e.to_string()) +} + +pub fn write_knowledge(knowledge: &Knowledge) -> Result<(), String> { + let json = serde_json::to_string(knowledge).map_err(|e| e.to_string())?; + let mut file = File::create(KNOWLEDGE_FILE).map_err(|e| e.to_string())?; + write!(file, "{}", json).map_err(|e| e.to_string())?; + + Ok(()) +} diff --git a/src/knowledge.rs b/src/knowledge.rs new file mode 100644 index 0000000..3b0c61a --- /dev/null +++ b/src/knowledge.rs @@ -0,0 +1,54 @@ +use actions::*; +use ships::*; +use std::collections::HashMap; + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct Knowledge { + pub last_action: Option<Action>, + pub opponent_map: OpponentMapKnowledge +} + +impl Knowledge { + pub fn new() -> Knowledge { + Knowledge { + last_action: None, + opponent_map: OpponentMapKnowledge::new() + } + } + + pub fn with_action(&self, action: Action) -> Knowledge { + Knowledge { + last_action: Some(action), + opponent_map: self.opponent_map.clone() + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct OpponentMapKnowledge { + pub ships: HashMap<Ship, OpponentShipKnowledge>, + pub cells: Vec<Vec<KnowledgeCell>> +} + +impl OpponentMapKnowledge { + pub fn new() -> OpponentMapKnowledge { + OpponentMapKnowledge { + ships: HashMap::new(), + cells: Vec::new() + } + } +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct OpponentShipKnowledge { + pub destroyed: bool +} + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct KnowledgeCell { + pub shot_attempted: bool, + pub possible_ship_uses: HashMap<Ship, u16>, + pub known_ship: Option<Ship> +} + + @@ -1,5 +1,9 @@ extern crate json; extern crate rand; +extern crate serde; +extern crate serde_json; +#[macro_use] +extern crate serde_derive; mod actions; mod math; @@ -8,6 +12,7 @@ mod ships; mod placement; mod shooting; mod state; +mod knowledge; use math::*; use files::*; @@ -15,17 +20,23 @@ use ships::*; use placement::*; use shooting::*; use state::*; +use knowledge::*; use std::path::PathBuf; pub fn write_move(working_dir: PathBuf) -> Result<(), String> { let state_json = read_file(&working_dir)?; - println!("\n\n{}\n\n", state_json.pretty(2)); - let is_place_phase = state_json["Phase"] == 1; let map_size = State::map_size_from_json(&state_json)?; + let starting_knowledge = if is_place_phase { + Knowledge::new() + } + else { + read_knowledge()? + }; + let action = if is_place_phase { place_ships_randomly(map_size) } @@ -34,8 +45,18 @@ pub fn write_move(working_dir: PathBuf) -> Result<(), String> { shoot_randomly(&state) }; + let ending_knowledge = starting_knowledge + .with_action(action.clone()); + + write_knowledge(&ending_knowledge) + .map_err(|e| format!("Failed to write knowledge to file. Error: {}", e))?; + write_action(&working_dir, is_place_phase, action) .map_err(|e| format!("Failed to write action to file. Error: {}", e))?; + + println!("Input state:\n{}\n\n", state_json); + println!("Existing knowledge:\n{}\n\n", serde_json::to_string(&starting_knowledge).unwrap_or(String::from(""))); + println!("End of turn knowledge:\n{}\n\n", serde_json::to_string(&ending_knowledge).unwrap_or(String::from(""))); Ok(()) } diff --git a/src/math.rs b/src/math.rs index 8e81348..3d8a976 100644 --- a/src/math.rs +++ b/src/math.rs @@ -2,7 +2,7 @@ use std::fmt; use rand; use rand::distributions::{IndependentSample, Range}; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] pub enum Direction { North, East, @@ -40,7 +40,7 @@ impl Direction { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] pub struct Point { pub x: u16, pub y: u16 diff --git a/src/ships.rs b/src/ships.rs index e21b20e..344f9ed 100644 --- a/src/ships.rs +++ b/src/ships.rs @@ -1,6 +1,7 @@ use std::fmt; +use std::str; -#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] pub enum Ship { Battleship, Carrier, @@ -25,6 +26,22 @@ impl fmt::Display for Ship { } } +impl str::FromStr for Ship { + type Err = String; + fn from_str(s: &str) -> Result<Self, Self::Err> { + use Ship::*; + + match s { + "Battleship" => Ok(Battleship), + "Carrier" => Ok(Carrier), + "Cruiser" => Ok(Cruiser), + "Destroyer" => Ok(Destroyer), + "Submarine" => Ok(Submarine), + _ => Err(String::from("ship type is not known")) + } + } +} + impl Ship { pub fn length(&self) -> u16 { use Ship::*; diff --git a/src/state.rs b/src/state.rs index df66ec9..8c176e1 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1,4 +1,6 @@ use json; +use std::collections::HashMap; +use ships::*; pub struct State { pub map_size: u16, @@ -25,7 +27,8 @@ impl State { } pub struct OpponentMap { - pub cells: Vec<Vec<Cell>> + pub cells: Vec<Vec<Cell>>, + pub ships: HashMap<Ship, OpponentShip>, } impl OpponentMap { @@ -38,7 +41,7 @@ impl OpponentMap { } cells.push(row); } - + for json_cell in json["Cells"].members() { let x = json_cell["X"] .as_u16() @@ -56,13 +59,34 @@ impl OpponentMap { cells[x as usize][y as usize].damaged = damaged; cells[x as usize][y as usize].missed = missed; } + + let mut ships = HashMap::new(); + for json_ship in json["Ships"].members() { + let ship_type_string = json_ship["ShipType"] + .as_str() + .ok_or(String::from("Failed to read ShipType value of opponent map ship in json file"))?; + let ship_type = ship_type_string.parse::<Ship>()?; + + let destroyed = json_ship["Destroyed"] + .as_bool() + .ok_or(String::from("Failed to read Destroyed value of opponent map ship in json file"))?; + ships.insert(ship_type, OpponentShip { + destroyed: destroyed + }); + } + Ok(OpponentMap { - cells: cells + cells: cells, + ships: ships }) } } +pub struct OpponentShip { + pub destroyed: bool +} + pub struct Cell { pub damaged: bool, pub missed: bool |