From a866bde485c7d8bc82820f2def70af7b6c70a066 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Tue, 19 Apr 2022 21:25:36 +0200 Subject: Refile for merging repos --- 2017-battleships/src/actions.rs | 90 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 2017-battleships/src/actions.rs (limited to '2017-battleships/src/actions.rs') diff --git a/2017-battleships/src/actions.rs b/2017-battleships/src/actions.rs new file mode 100644 index 0000000..cf0059a --- /dev/null +++ b/2017-battleships/src/actions.rs @@ -0,0 +1,90 @@ +use math::*; +use ships::*; + +use std::fmt; + +use std::collections::HashSet; + +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] +pub enum Action { + PlaceShips(Vec), + Shoot(Weapon, Point) +} + +impl fmt::Display for Action { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &Action::Shoot(w, p) => writeln!(f, "{},{},{}", w, p.x, p.y), + &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, Serialize, Deserialize)] +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() as i32, map_size); + start.x < map_size && start.y < map_size && end.is_some() + } + pub fn valid_placements(placements: &Vec, map_size: u16) -> bool { + let mut occupied = HashSet::new(); + + let individuals_valid = placements.iter().all(|p| p.valid(map_size)); + + let mut no_overlaps = true; + for placement in placements { + for i in 0..placement.ship_type.length() as i32 { + 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 + } + } + } + + //block out the area around the current ship to prevent adjacent ships + for i in 0..placement.ship_type.length() as i32 { + match placement.point.move_point(placement.direction, i, map_size) { + Some(current_block) => { + if let Some(p) = current_block.move_point(Direction::North, 1, map_size) { + occupied.insert(p); + } + if let Some(p) = current_block.move_point(Direction::South, 1, map_size) { + occupied.insert(p); + } + if let Some(p) = current_block.move_point(Direction::East, 1, map_size) { + occupied.insert(p); + } + if let Some(p) = current_block.move_point(Direction::West, 1, map_size) { + occupied.insert(p); + } + }, + None => { + //invalid case here is handled above + } + } + } + } + individuals_valid && no_overlaps + } +} -- cgit v1.2.3