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/ships.rs | 216 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 2017-battleships/src/ships.rs (limited to '2017-battleships/src/ships.rs') diff --git a/2017-battleships/src/ships.rs b/2017-battleships/src/ships.rs new file mode 100644 index 0000000..422f24e --- /dev/null +++ b/2017-battleships/src/ships.rs @@ -0,0 +1,216 @@ +use std::fmt; +use std::str; + +use math::*; + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] +pub enum Weapon { + SingleShot, + DoubleShotVertical, + DoubleShotHorizontal, + CornerShot, + CrossShotDiagonal, + CrossShotHorizontal, + SeekerMissle +} + +impl fmt::Display for Weapon { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use Weapon::*; + + f.write_str( + match self { + &SingleShot => "1", + &DoubleShotVertical => "2", + &DoubleShotHorizontal => "3", + &CornerShot => "4", + &CrossShotDiagonal => "5", + &CrossShotHorizontal => "6", + &SeekerMissle => "7" + } + ) + } +} + +impl Weapon { + pub fn energy_per_round(map_size: u16) -> u16 { + if map_size < 10 { + 2 + } + else if map_size < 14 { + 3 + } + else { + 4 + } + } + pub fn energy_cost(&self, map_size: u16) -> u16 { + use Weapon::*; + let epr = Weapon::energy_per_round(map_size); + match self { + &SingleShot => 1, + &DoubleShotVertical | &DoubleShotHorizontal => 8*epr, + &CornerShot => 10*epr, + &CrossShotDiagonal => 12*epr, + &CrossShotHorizontal => 14*epr, + &SeekerMissle => 10*epr + } + } + pub fn single_shot_rounds_to_ready(&self, current_energy: u16, map_size: u16) -> u16 { + let single_shot_cost = Weapon::SingleShot.energy_cost(map_size); + let energy_per_round = Weapon::energy_per_round(map_size) - single_shot_cost; + let required_energy = self.energy_cost(map_size) - current_energy; + //weird plus is to make the integer rounding up instead of down + (required_energy + energy_per_round - 1) / energy_per_round + } + + pub fn affected_cells(&self, target: Point, map_size: u16) -> Vec { + use Weapon::*; + + let p = target; + match self { + &SingleShot => { + vec!(Some(p)) + }, + &DoubleShotVertical => { + vec!( + p.move_point(Direction::North, 1, map_size), + p.move_point(Direction::South, 1, map_size) + ) + }, + &DoubleShotHorizontal => { + vec!( + p.move_point(Direction::East, 1, map_size), + p.move_point(Direction::West, 1, map_size) + ) + }, + &CornerShot => { + vec!( + p.move_point(Direction::NorthEast, 1, map_size), + p.move_point(Direction::SouthEast, 1, map_size), + p.move_point(Direction::NorthWest, 1, map_size), + p.move_point(Direction::SouthWest, 1, map_size), + ) + }, + &CrossShotDiagonal => { + vec!( + p.move_point(Direction::NorthEast, 1, map_size), + p.move_point(Direction::SouthEast, 1, map_size), + p.move_point(Direction::NorthWest, 1, map_size), + p.move_point(Direction::SouthWest, 1, map_size), + Some(p) + ) + }, + &CrossShotHorizontal => { + vec!( + p.move_point(Direction::North, 1, map_size), + p.move_point(Direction::East, 1, map_size), + p.move_point(Direction::South, 1, map_size), + p.move_point(Direction::West, 1, map_size), + Some(p) + ) + }, + &SeekerMissle => { + vec!( + Some(p), + + p.move_point(Direction::North, 1, map_size), + p.move_point(Direction::East, 1, map_size), + p.move_point(Direction::South, 1, map_size), + p.move_point(Direction::West, 1, map_size), + + p.move_point(Direction::NorthEast, 1, map_size), + p.move_point(Direction::SouthEast, 1, map_size), + p.move_point(Direction::NorthWest, 1, map_size), + p.move_point(Direction::SouthWest, 1, map_size), + + p.move_point(Direction::North, 2, map_size), + p.move_point(Direction::East, 2, map_size), + p.move_point(Direction::South, 2, map_size), + p.move_point(Direction::West, 2, map_size) + ) + } + }.iter().filter_map(|&p| p).collect::>() + } +} + + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)] +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 str::FromStr for Ship { + type Err = String; + fn from_str(s: &str) -> Result { + 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::*; + + match self { + &Battleship => 4, + &Carrier => 5, + &Cruiser => 3, + &Destroyer => 2, + &Submarine => 3 + } + } + + pub fn weapons(&self) -> Vec { + use Ship::*; + use Weapon::*; + + match self { + &Battleship => vec!(SingleShot, CrossShotDiagonal), + &Carrier => vec!(SingleShot, CornerShot), + &Cruiser => vec!(SingleShot, CrossShotHorizontal), + &Destroyer => vec!(SingleShot, DoubleShotVertical, DoubleShotHorizontal), + &Submarine => vec!(SingleShot, SeekerMissle) + } + } + + pub fn all_types() -> Vec { + use Ship::*; + + vec!( + Battleship, + Carrier, + Cruiser, + Destroyer, + Submarine + ) + } +} -- cgit v1.2.3