2022-09-14 18:30:33 +02:00
|
|
|
use rand::RngCore;
|
|
|
|
|
2022-09-15 20:13:06 +02:00
|
|
|
use crate::data::{BoatPosition, BoatsLayout, Coordinates, GameRules};
|
|
|
|
|
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
|
|
pub struct CurrentGameMapStatus {
|
|
|
|
pub boats: BoatsLayout,
|
|
|
|
pub successful_strikes: Vec<Coordinates>,
|
|
|
|
pub failed_strikes: Vec<Coordinates>,
|
|
|
|
pub sunk_boats: Vec<BoatPosition>,
|
|
|
|
}
|
|
|
|
|
2022-09-14 18:30:33 +02:00
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|