Start to build cli player
This commit is contained in:
117
rust/sea_battle_backend/src/data/game_map.rs
Normal file
117
rust/sea_battle_backend/src/data/game_map.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
use crate::data::boats_layout::{BoatsLayout, Coordinates};
|
||||
use crate::data::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum FireResult {
|
||||
Missed,
|
||||
Hit,
|
||||
Sunk(BoatPosition),
|
||||
Rejected,
|
||||
AlreadyTargetedPosition,
|
||||
}
|
||||
|
||||
pub struct GameMap {
|
||||
rules: GameRules,
|
||||
boats_config: BoatsLayout,
|
||||
failed_strikes: Vec<Coordinates>,
|
||||
successful_strikes: Vec<Coordinates>,
|
||||
sunk_boats: Vec<BoatPosition>,
|
||||
}
|
||||
|
||||
impl GameMap {
|
||||
pub fn new(rules: GameRules, boats_config: BoatsLayout) -> Self {
|
||||
Self {
|
||||
rules,
|
||||
boats_config,
|
||||
failed_strikes: vec![],
|
||||
successful_strikes: vec![],
|
||||
sunk_boats: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_cell_content(&self, c: Coordinates) -> MapCellContent {
|
||||
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;
|
||||
}
|
||||
|
||||
if self.sunk_boats.contains(b) {
|
||||
return MapCellContent::SunkBoat;
|
||||
}
|
||||
|
||||
return MapCellContent::TouchedBoat;
|
||||
}
|
||||
|
||||
MapCellContent::Nothing
|
||||
}
|
||||
|
||||
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(*b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn are_all_boat_sunk(&self) -> bool {
|
||||
self.sunk_boats.len() == self.boats_config.number_of_boats()
|
||||
}
|
||||
|
||||
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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PrintableMap for GameMap {
|
||||
fn map_cell_content(&self, c: Coordinates) -> MapCellContent {
|
||||
self.get_cell_content(c)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user