summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2017-05-13 19:19:06 +0200
committerJustin Worthe <justin.worthe@gmail.com>2017-05-13 19:19:06 +0200
commit36b72bfef7b7b8dea94546d11704ec529091bce1 (patch)
tree4a8cdae81db3ab44aa946046bbfbb87f96c360c5 /src
parent27682d0ab246af8d0375853fdea44c38de2c2db4 (diff)
Split into smaller portions
Diffstat (limited to 'src')
-rw-r--r--src/actions.rs22
-rw-r--r--src/files.rs32
-rw-r--r--src/lib.rs55
-rw-r--r--src/main.rs118
-rw-r--r--src/math.rs49
-rw-r--r--src/ships.rs38
6 files changed, 205 insertions, 109 deletions
diff --git a/src/actions.rs b/src/actions.rs
new file mode 100644
index 0000000..a7f61b5
--- /dev/null
+++ b/src/actions.rs
@@ -0,0 +1,22 @@
+use math::*;
+use ships::*;
+
+use std::fmt;
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub enum Action {
+ PlaceShips(Vec<(Ship, Point, Orientation)>),
+ Shoot(Point)
+}
+
+impl fmt::Display for Action {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ &Action::Shoot(p) => writeln!(f, "1,{},{}", p.x, p.y),
+ &Action::PlaceShips(ref ships) => ships.iter().map(|&(ref ship_type, p, orientation)| {
+ writeln!(f, "{} {} {} {}", ship_type, p.x, p.y, orientation)
+ }).fold(Ok(()), |acc, next| acc.and(next))
+ }
+ }
+}
+
diff --git a/src/files.rs b/src/files.rs
new file mode 100644
index 0000000..87d295f
--- /dev/null
+++ b/src/files.rs
@@ -0,0 +1,32 @@
+use json;
+use std::io::prelude::*;
+use std::fs::File;
+use std::path::PathBuf;
+
+use actions::*;
+
+const COMMAND_FILE: &'static str = "command.txt";
+const PLACE_FILE: &'static str = "place.txt";
+const STATE_FILE: &'static str = "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())?;
+ let mut content = String::new();
+ file.read_to_string(&mut content).map_err(|e| e.to_string())?;
+ json::parse(content.as_ref()).map_err(|e| e.to_string())
+}
+
+pub fn write_action(working_dir: &PathBuf, is_place_phase: bool, action: Action) -> Result<(), String> {
+ let filename = if is_place_phase {
+ PLACE_FILE
+ }
+ else {
+ COMMAND_FILE
+ };
+
+ let full_filename = working_dir.join(filename);
+ let mut file = File::create(full_filename.as_path()).map_err(|e| e.to_string())?;
+ writeln!(file, "{}", action).map_err(|e| e.to_string())?;
+ Ok(())
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..5ea9ecc
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,55 @@
+extern crate json;
+extern crate rand;
+
+mod actions;
+mod math;
+mod files;
+mod ships;
+
+use actions::*;
+use math::*;
+use files::*;
+use ships::*;
+
+use std::path::PathBuf;
+
+pub fn write_move(working_dir: PathBuf) -> Result<(), String> {
+ let state = read_file(&working_dir)?;
+
+ let is_place_phase = state["Phase"] == 1;
+ let map_dimension = state["MapDimension"]
+ .as_u16()
+ .ok_or("Did not find the map dimension in the state json file")?;
+
+ let action = if is_place_phase {
+ place_ships()
+ }
+ else {
+ shoot_randomly(map_dimension)
+ };
+
+ write_action(&working_dir, is_place_phase, action)
+ .map_err(|e| format!("Failed to write action to file. Error: {}", e))?;
+
+ Ok(())
+}
+
+
+fn place_ships() -> Action {
+ let ships = vec!(
+ (Ship::Battleship, Point::new(1, 0), Orientation::North),
+ (Ship::Carrier, Point::new(3, 1), Orientation::East),
+ (Ship::Cruiser, Point::new(4, 2), Orientation::North),
+ (Ship::Destroyer, Point::new(7, 3), Orientation::North),
+ (Ship::Submarine, Point::new(1, 8), Orientation::East)
+ );
+
+ Action::PlaceShips(ships)
+}
+
+fn shoot_randomly(map_dimension: u16) -> Action {
+ Action::Shoot(random_point(map_dimension))
+}
+
+
+
diff --git a/src/main.rs b/src/main.rs
index 7c904d6..ee0ba59 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,119 +1,19 @@
-extern crate json;
-extern crate rand;
+extern crate worthebot_battleships;
+use worthebot_battleships as bot;
use std::env;
-use std::path::Path;
use std::path::PathBuf;
-use std::io::prelude::*;
-use std::fs::File;
-use std::fmt;
-use rand::distributions::{IndependentSample, Range};
-
-const COMMAND_FILE: &'static str = "command.txt";
-const PLACE_FILE: &'static str = "place.txt";
-const STATE_FILE: &'static str = "state.json";
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-enum Orientation {
- North,
- East,
- South,
- West,
-}
-
-impl fmt::Display for Orientation {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str(
- match self {
- &Orientation::North => "North",
- &Orientation::East => "East",
- &Orientation::South => "South",
- &Orientation::West => "West"
- }
- )
- }
-}
-
-#[derive(Clone, PartialEq, Eq, Debug)]
-enum Action {
- PlaceShips(Vec<(String, u32, u32, Orientation)>),
- Shoot(u32, u32)
-}
-
-impl fmt::Display for Action {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- &Action::Shoot(x, y) => writeln!(f, "1,{},{}", x, y),
- &Action::PlaceShips(ref ships) => ships.iter().map(|&(ref ship_type, x, y, orientation)| {
- writeln!(f, "{} {} {} {}", ship_type, x, y, orientation)
- }).fold(Ok(()), |acc, next| acc.and(next))
- }
- }
-}
-
-fn main() {
+fn main() {
let working_dir = env::args()
.nth(2)
- .map(|pwd| PathBuf::from(pwd))
- .expect("Requires game state folder to be passed as the second parameter");
+ .map(|x| PathBuf::from(x))
+ .ok_or(String::from("Requires game state folder to be passed as the second parameter"));
- // The state file is read here. Chances are, you'll want to read
- // more values out of it than the sample bot currently does.
- let state = read_file(&working_dir).expect("Failed to read state.json");
-
- let is_place_phase = state["Phase"] == 1;
- let map_dimension = state["MapDimension"].as_u32().expect("Could not read map dimension from the state");
-
- let action = if is_place_phase {
- place_ships()
- }
- else {
- shoot_randomly(map_dimension)
- };
-
-
- write_action(&working_dir, is_place_phase, action).expect("Failed to write action to file");
-}
-
-fn read_file(working_dir: &Path) -> 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())?;
- let mut content = String::new();
- file.read_to_string(&mut content).map_err(|e| e.to_string())?;
- json::parse(content.as_ref()).map_err(|e| e.to_string())
-}
-
-fn place_ships() -> Action {
- let ships = vec!(
- (String::from("Battleship"), 1, 0, Orientation::North),
- (String::from("Carrier"), 3, 1, Orientation::East),
- (String::from("Cruiser"), 4, 2, Orientation::North),
- (String::from("Destroyer"), 7, 3, Orientation::North),
- (String::from("Submarine"), 1, 8, Orientation::East)
- );
-
- Action::PlaceShips(ships)
-}
-
-fn shoot_randomly(map_dimension: u32) -> Action {
- let mut rng = rand::thread_rng();
- let between = Range::new(0, map_dimension);
- let x = between.ind_sample(&mut rng);
- let y = between.ind_sample(&mut rng);
- Action::Shoot(x, y)
-}
+ let result = working_dir.and_then(|working_dir| bot::write_move(working_dir));
-fn write_action(working_dir: &Path, is_place_phase: bool, action: Action) -> Result<(), String> {
- let filename = if is_place_phase {
- PLACE_FILE
+ match result {
+ Ok(()) => println!("Bot terminated successfully"),
+ Err(e) => println!("Error in bot execution: {}", e)
}
- else {
- COMMAND_FILE
- };
-
- let full_filename = working_dir.join(filename);
- let mut file = File::create(full_filename.as_path()).map_err(|e| e.to_string())?;
- writeln!(file, "{}", action).map_err(|e| e.to_string())?;
- Ok(())
}
diff --git a/src/math.rs b/src/math.rs
new file mode 100644
index 0000000..665d4d0
--- /dev/null
+++ b/src/math.rs
@@ -0,0 +1,49 @@
+use std::fmt;
+use rand;
+use rand::distributions::{IndependentSample, Range};
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum Orientation {
+ North,
+ East,
+ South,
+ West,
+}
+
+impl fmt::Display for Orientation {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use Orientation::*;
+
+ f.write_str(
+ match self {
+ &North => "North",
+ &East => "East",
+ &South => "South",
+ &West => "West"
+ }
+ )
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub struct Point {
+ pub x: u16,
+ pub y: u16
+}
+
+impl Point {
+ pub fn new(x: u16, y: u16) -> Point {
+ Point {
+ x: x,
+ y: y
+ }
+ }
+}
+
+pub fn random_point(map_dimension: u16) -> Point {
+ let mut rng = rand::thread_rng();
+ let between = Range::new(0, map_dimension);
+ let x = between.ind_sample(&mut rng);
+ let y = between.ind_sample(&mut rng);
+ Point::new(x, y)
+}
diff --git a/src/ships.rs b/src/ships.rs
new file mode 100644
index 0000000..8058d4a
--- /dev/null
+++ b/src/ships.rs
@@ -0,0 +1,38 @@
+use std::fmt;
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum Ship {
+ Battleship,
+ Carrier,
+ Cruiser,
+ Destroyer,
+ Submarine
+}
+
+impl fmt::Display for Ship {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use Ship::*;
+
+ f.write_str(
+ match self {
+ &Battleship => "Battleship",
+ &Carrier => "Carrier",
+ &Cruiser => "Cruiser",
+ &Destroyer => "Destroyer",
+ &Submarine => "Submarine"
+ }
+ )
+ }
+}
+
+impl Ship {
+ pub fn length(&self) -> u16 {
+ match self {
+ &Battleship => 4,
+ &Carrier => 5,
+ &Cruiser => 3,
+ &Destroyer => 2,
+ &Submarine => 3
+ }
+ }
+}