161 lines
4.5 KiB
Rust
Raw Normal View History

2022-09-13 17:25:14 +02:00
use crate::data::boats_layout::{BoatsLayout, Coordinates};
2022-09-15 20:13:06 +02:00
use crate::data::{BoatPosition, CurrentGameMapStatus, EndGameMap, GameRules};
2022-09-12 16:38:14 +02:00
2022-09-15 17:37:26 +02:00
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum FireResult {
Missed,
Hit,
Sunk,
Rejected,
AlreadyTargetedPosition,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
pub enum MapCellContent {
2022-09-12 16:38:14 +02:00
Invalid,
Nothing,
TouchedBoat,
2022-09-15 17:37:26 +02:00
SunkBoat,
2022-09-12 16:38:14 +02:00
Boat,
FailedStrike,
}
impl MapCellContent {
2022-09-15 17:37:26 +02:00
pub fn letter(&self) -> &'static str {
2022-09-12 16:38:14 +02:00
match self {
MapCellContent::Invalid => "!",
2022-09-13 17:25:14 +02:00
MapCellContent::Nothing => ".",
2022-09-12 16:38:14 +02:00
MapCellContent::TouchedBoat => "T",
2022-09-15 17:37:26 +02:00
MapCellContent::SunkBoat => "S",
2022-09-12 16:38:14 +02:00
MapCellContent::Boat => "B",
2022-09-15 17:37:26 +02:00
MapCellContent::FailedStrike => "x",
2022-09-12 16:38:14 +02:00
}
}
}
pub struct GameMap {
rules: GameRules,
boats_config: BoatsLayout,
2022-09-15 17:37:26 +02:00
failed_strikes: Vec<Coordinates>,
successful_strikes: Vec<Coordinates>,
sunk_boats: Vec<BoatPosition>,
2022-09-12 16:38:14 +02:00
}
impl GameMap {
pub fn new(rules: GameRules, boats_config: BoatsLayout) -> Self {
Self {
rules,
boats_config,
2022-09-15 17:37:26 +02:00
failed_strikes: vec![],
successful_strikes: vec![],
sunk_boats: vec![],
2022-09-12 16:38:14 +02:00
}
}
2022-09-13 17:25:14 +02:00
pub fn get_cell_content(&self, c: Coordinates) -> MapCellContent {
2022-09-15 17:37:26 +02:00
if !c.is_valid(&self.rules) {
return MapCellContent::Invalid;
}
if self.failed_strikes.contains(&c) {
return MapCellContent::FailedStrike;
}
if let Some(b) = self.boats_config.find_boat_at_position(c) {
if !self.successful_strikes.contains(&c) {
return MapCellContent::Boat;
}
2022-09-13 17:25:14 +02:00
2022-09-15 17:37:26 +02:00
if self.sunk_boats.contains(b) {
return MapCellContent::SunkBoat;
}
return MapCellContent::TouchedBoat;
2022-09-13 17:25:14 +02:00
}
MapCellContent::Nothing
2022-09-12 16:38:14 +02:00
}
2022-09-15 17:37:26 +02:00
pub fn fire(&mut self, c: Coordinates) -> FireResult {
if !c.is_valid(&self.rules) {
return FireResult::Rejected;
}
if self.failed_strikes.contains(&c) || self.successful_strikes.contains(&c) {
return FireResult::AlreadyTargetedPosition;
}
match self.boats_config.find_boat_at_position(c) {
None => {
self.failed_strikes.push(c);
FireResult::Missed
}
Some(b) => {
self.successful_strikes.push(c);
if !b
.all_coordinates()
.iter()
.all(|c| self.successful_strikes.contains(c))
{
return FireResult::Hit;
}
self.sunk_boats.push(*b);
if !self.rules.boats_can_touch {
for c in b.neighbor_coordinates(&self.rules) {
if !self.failed_strikes.contains(&c) {
self.failed_strikes.push(c);
}
}
}
FireResult::Sunk
}
}
}
pub fn are_all_boat_sunk(&self) -> bool {
self.sunk_boats.len() == self.boats_config.number_of_boats()
}
2022-09-12 16:38:14 +02:00
pub fn print_map(&self) {
for y in 0..self.rules.map_height {
for x in 0..self.rules.map_width {
2022-09-13 17:25:14 +02:00
print!(
"{} ",
self.get_cell_content(Coordinates::new(x as i32, y as i32))
.letter()
);
2022-09-12 16:38:14 +02:00
}
println!();
}
}
2022-09-15 17:37:26 +02:00
2022-09-15 20:13:06 +02:00
pub fn current_map_status(&self, for_opponent: bool) -> CurrentGameMapStatus {
CurrentGameMapStatus {
boats: match for_opponent {
true => BoatsLayout::new_invalid(),
false => self.boats_config.clone(),
},
successful_strikes: self.successful_strikes.clone(),
failed_strikes: self.failed_strikes.clone(),
sunk_boats: self.sunk_boats.clone(),
}
}
2022-09-15 17:37:26 +02:00
pub fn final_map(&self) -> EndGameMap {
EndGameMap {
boats: self.boats_config.clone(),
grid: (0..self.rules.map_height)
.map(|y| {
(0..self.rules.map_width)
.map(|x| self.get_cell_content(Coordinates::new(x as i32, y as i32)))
.collect::<Vec<_>>()
})
.collect::<Vec<_>>(),
}
}
2022-09-12 16:38:14 +02:00
}