summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bot.json2
-rw-r--r--src/actions.rs52
-rw-r--r--src/files.rs5
-rw-r--r--src/lib.rs30
-rw-r--r--src/math.rs58
-rw-r--r--src/placement.rs24
-rw-r--r--src/ships.rs2
-rw-r--r--src/shooting.rs6
8 files changed, 138 insertions, 41 deletions
diff --git a/bot.json b/bot.json
index 04c2127..eca72f5 100644
--- a/bot.json
+++ b/bot.json
@@ -4,5 +4,5 @@
"NickName" :"Admiral Worthebot",
"BotType": 8,
"ProjectLocation" : "",
- "RunFile" : "target\\release\\100k_worthebot_battleships"
+ "RunFile" : "target\\release\\worthebot_battleships"
}
diff --git a/src/actions.rs b/src/actions.rs
index a7f61b5..1b6400d 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -3,9 +3,11 @@ use ships::*;
use std::fmt;
+use std::collections::HashSet;
+
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Action {
- PlaceShips(Vec<(Ship, Point, Orientation)>),
+ PlaceShips(Vec<ShipPlacement>),
Shoot(Point)
}
@@ -13,10 +15,54 @@ 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)
+ &Action::PlaceShips(ref ships) => ships.iter().map(|ref ship| {
+ writeln!(f, "{} {} {} {}", ship.ship_type, ship.point.x, ship.point.y, ship.direction)
}).fold(Ok(()), |acc, next| acc.and(next))
}
}
}
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct ShipPlacement {
+ ship_type: Ship,
+ point: Point,
+ direction: Direction
+}
+
+impl ShipPlacement {
+ pub fn new(ship_type: Ship, point: Point, direction: Direction) -> ShipPlacement {
+ ShipPlacement {
+ ship_type: ship_type,
+ point: point,
+ direction: direction
+ }
+ }
+
+ pub fn valid(&self, map_size: u16) -> bool {
+ let start = self.point;
+ let end = start.move_point(self.direction, self.ship_type.length(), map_size);
+ start.x < map_size && start.y < map_size && end.is_some()
+ }
+ pub fn valid_placements(placements: &Vec<ShipPlacement>, map_size: u16) -> bool {
+ let mut occupied = HashSet::new();
+ let mut individuals_valid = true;
+ let mut no_overlaps = true;
+
+ for placement in placements {
+ individuals_valid = individuals_valid && placement.valid(map_size);
+
+ for i in 0..placement.ship_type.length() {
+ match placement.point.move_point(placement.direction, i, map_size) {
+ Some(block) => {
+ no_overlaps = no_overlaps && !occupied.contains(&block);
+ occupied.insert(block);
+ },
+ None => {
+ //invalid case here is handled above
+ }
+ }
+ }
+ }
+ individuals_valid && no_overlaps
+ }
+}
diff --git a/src/files.rs b/src/files.rs
index 87d295f..99dca8c 100644
--- a/src/files.rs
+++ b/src/files.rs
@@ -27,6 +27,9 @@ pub fn write_action(working_dir: &PathBuf, is_place_phase: bool, action: Action)
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())?;
+ write!(file, "{}", action).map_err(|e| e.to_string())?;
+
+ println!("Making move: {}", action);
+
Ok(())
}
diff --git a/src/lib.rs b/src/lib.rs
index 5ea9ecc..f3c1a00 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -5,11 +5,14 @@ mod actions;
mod math;
mod files;
mod ships;
+mod placement;
+mod shooting;
-use actions::*;
use math::*;
use files::*;
use ships::*;
+use placement::*;
+use shooting::*;
use std::path::PathBuf;
@@ -17,15 +20,15 @@ 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"]
+ let map_size = 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()
+ place_ships_randomly(map_size)
}
else {
- shoot_randomly(map_dimension)
+ shoot_randomly(map_size)
};
write_action(&working_dir, is_place_phase, action)
@@ -34,22 +37,3 @@ pub fn write_move(working_dir: PathBuf) -> Result<(), String> {
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/math.rs b/src/math.rs
index 665d4d0..8e81348 100644
--- a/src/math.rs
+++ b/src/math.rs
@@ -2,18 +2,18 @@ use std::fmt;
use rand;
use rand::distributions::{IndependentSample, Range};
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum Orientation {
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+pub enum Direction {
North,
East,
South,
West,
}
-impl fmt::Display for Orientation {
+use Direction::*;
+
+impl fmt::Display for Direction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use Orientation::*;
-
f.write_str(
match self {
&North => "North",
@@ -25,7 +25,22 @@ impl fmt::Display for Orientation {
}
}
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+impl Direction {
+ pub fn random() -> Direction {
+ let mut rng = rand::thread_rng();
+ let between = Range::new(0, 4);
+ let dir = between.ind_sample(&mut rng);
+ match dir {
+ 0 => North,
+ 1 => East,
+ 2 => South,
+ 3 => West,
+ _ => panic!("Invalid number generated by random number generator")
+ }
+ }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Point {
pub x: u16,
pub y: u16
@@ -38,12 +53,29 @@ impl Point {
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)
+ pub fn random(map_size: u16) -> Point {
+ let mut rng = rand::thread_rng();
+ let between = Range::new(0, map_size);
+ let x = between.ind_sample(&mut rng);
+ let y = between.ind_sample(&mut rng);
+ Point::new(x, y)
+ }
+
+
+ pub fn move_point(&self, direction: Direction, distance: u16, map_size: u16) -> Option<Point> {
+ let x = self.x;
+ let y = self.y;
+
+ match direction {
+ South if y < distance => None,
+ West if x < distance => None,
+ North if y + distance >= map_size => None,
+ East if x + distance >= map_size => None,
+ South => Some(Point::new(x, y-distance)),
+ West => Some(Point::new(x-distance, y)),
+ North => Some(Point::new(x, y+distance)),
+ East => Some(Point::new(x+distance, y))
+ }
+ }
}
diff --git a/src/placement.rs b/src/placement.rs
new file mode 100644
index 0000000..faa340e
--- /dev/null
+++ b/src/placement.rs
@@ -0,0 +1,24 @@
+use actions::*;
+use math::*;
+use ships::*;
+
+pub fn place_ships_randomly(map_size: u16) -> Action {
+ let mut current_placement: Vec<ShipPlacement>;
+
+ while {
+ current_placement = create_random_placement(map_size);
+ !ShipPlacement::valid_placements(&current_placement, map_size)
+ } {}
+
+ Action::PlaceShips(current_placement)
+}
+
+fn create_random_placement(map_size: u16) -> Vec<ShipPlacement> {
+ vec!(
+ ShipPlacement::new(Ship::Battleship, Point::random(map_size), Direction::random()),
+ ShipPlacement::new(Ship::Carrier, Point::random(map_size), Direction::random()),
+ ShipPlacement::new(Ship::Cruiser, Point::random(map_size), Direction::random()),
+ ShipPlacement::new(Ship::Destroyer, Point::random(map_size), Direction::random()),
+ ShipPlacement::new(Ship::Submarine, Point::random(map_size), Direction::random())
+ )
+}
diff --git a/src/ships.rs b/src/ships.rs
index 8058d4a..e21b20e 100644
--- a/src/ships.rs
+++ b/src/ships.rs
@@ -27,6 +27,8 @@ impl fmt::Display for Ship {
impl Ship {
pub fn length(&self) -> u16 {
+ use Ship::*;
+
match self {
&Battleship => 4,
&Carrier => 5,
diff --git a/src/shooting.rs b/src/shooting.rs
new file mode 100644
index 0000000..14f2b81
--- /dev/null
+++ b/src/shooting.rs
@@ -0,0 +1,6 @@
+use actions::*;
+use math::*;
+
+pub fn shoot_randomly(map_size: u16) -> Action {
+ Action::Shoot(Point::random(map_size))
+}