use rand::RngCore; use crate::data::{BoatPosition, BoatsLayout, Coordinates, GameRules}; #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct CurrentGameMapStatus { pub boats: BoatsLayout, pub successful_strikes: Vec, pub failed_strikes: Vec, pub sunk_boats: Vec, } #[derive(Debug, serde::Serialize, serde::Deserialize)] pub struct CurrentGameStatus { pub rules: GameRules, pub your_map: CurrentGameMapStatus, pub opponent_map: CurrentGameMapStatus, } impl CurrentGameStatus { /// 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) } /// 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; } } } }