SeaBattle/sea_battle_backend/src/data/current_game_status.rs

104 lines
3.2 KiB
Rust
Raw Normal View History

2022-09-14 18:30:33 +02:00
use rand::RngCore;
2022-09-17 12:02:13 +02:00
use crate::data::{
BoatPosition, BoatsLayout, Coordinates, GameRules, MapCellContent, PrintableMap,
};
2022-09-15 20:13:06 +02:00
2022-09-17 12:02:13 +02:00
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
2022-09-15 20:13:06 +02:00
pub struct CurrentGameMapStatus {
pub boats: BoatsLayout,
pub successful_strikes: Vec<Coordinates>,
pub failed_strikes: Vec<Coordinates>,
pub sunk_boats: Vec<BoatPosition>,
}
2022-09-17 12:02:13 +02:00
impl CurrentGameMapStatus {
pub fn did_fire_at_location(&self, c: Coordinates) -> bool {
self.successful_strikes.contains(&c) || self.failed_strikes.contains(&c)
}
}
struct PrintableCurrentGameMapStatus(GameRules, CurrentGameMapStatus);
impl PrintableMap for PrintableCurrentGameMapStatus {
fn map_cell_content(&self, c: Coordinates) -> MapCellContent {
if !c.is_valid(&self.0) {
return MapCellContent::Invalid;
}
if self.1.failed_strikes.contains(&c) {
return MapCellContent::FailedStrike;
}
if self
.1
.sunk_boats
.iter()
.any(|b| b.all_coordinates().contains(&c))
{
return MapCellContent::SunkBoat;
}
if self.1.successful_strikes.contains(&c) {
return MapCellContent::TouchedBoat;
}
if self.1.boats.find_boat_at_position(c).is_some() {
return MapCellContent::Boat;
}
MapCellContent::Nothing
}
}
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
2022-09-14 18:30:33 +02:00
pub struct CurrentGameStatus {
pub rules: GameRules,
2022-09-15 20:13:06 +02:00
pub your_map: CurrentGameMapStatus,
pub opponent_map: CurrentGameMapStatus,
2022-09-14 18:30:33 +02:00
}
impl CurrentGameStatus {
2022-09-15 20:13:06 +02:00
/// Check if opponent can fire at a given location
pub fn can_fire_at_location(&self, location: Coordinates) -> bool {
!self.opponent_map.successful_strikes.contains(&location)
&& !self.opponent_map.failed_strikes.contains(&location)
2022-09-14 18:30:33 +02:00
}
/// Find valid random fire location. Loop until one is found
pub fn find_valid_random_fire_location(&self) -> Coordinates {
let mut rng = rand::thread_rng();
loop {
let coordinates = Coordinates::new(
(rng.next_u32() % self.rules.map_width as u32) as i32,
(rng.next_u32() % self.rules.map_height as u32) as i32,
);
if coordinates.is_valid(&self.rules) && self.can_fire_at_location(coordinates) {
return coordinates;
}
}
}
2022-09-17 12:02:13 +02:00
/// Find valid linear fire location. Loop until one is found
pub fn find_first_valid_fire_location(&self) -> Coordinates {
for y in 0..self.rules.map_height {
for x in 0..self.rules.map_width {
let coordinates = Coordinates::new(x as i32, y as i32);
if self.can_fire_at_location(coordinates) {
return coordinates;
}
}
}
panic!("Could not find fire location!")
}
pub fn print_your_map(&self) {
PrintableCurrentGameMapStatus(self.rules.clone(), self.your_map.clone()).print_map()
}
pub fn print_opponent_map(&self) {
PrintableCurrentGameMapStatus(self.rules.clone(), self.opponent_map.clone()).print_map()
}
2022-09-14 18:30:33 +02:00
}