diff --git a/rust/cli_player/src/ui_screens/set_boats_layout.rs b/rust/cli_player/src/ui_screens/set_boats_layout.rs index 6693694..b0c1bea 100644 --- a/rust/cli_player/src/ui_screens/set_boats_layout.rs +++ b/rust/cli_player/src/ui_screens/set_boats_layout.rs @@ -133,16 +133,36 @@ fn ui( ) -> CoordinatesMapper { let errors = model.layout.errors(rules); + // Color of current boat let current_boat = ColoredCells { color: Color::Green, cells: model.layout.0[model.curr_boat].all_coordinates(), }; + // Color of invalid boats + let mut invalid_coordinates = vec![]; + for (idx, pos) in model.layout.boats().iter().enumerate() { + if idx == model.curr_boat { + continue; + } + + if !model + .layout + .check_present_boat_position(idx, rules) + .is_empty() + { + invalid_coordinates.append(&mut pos.all_coordinates()); + } + } + let invalid_boats = ColoredCells { + color: Color::Red, + cells: invalid_coordinates, + }; + + // Color of other boats let mut other_boats_cells = vec![]; for boat in &model.layout.0 { - for pos in boat.all_coordinates() { - other_boats_cells.push(pos); - } + other_boats_cells.append(&mut boat.all_coordinates()); } let other_boats = ColoredCells { @@ -163,6 +183,7 @@ fn ui( let mut game_map_widget = GameMapWidget::new(rules) .set_default_empty_char(' ') .add_colored_cells(current_boat) + .add_colored_cells(invalid_boats) .add_colored_cells(other_boats) .set_title("Choose your boat layout") .set_yield_func(|c, r| { @@ -174,7 +195,7 @@ fn ui( }) .set_legend(legend); - // Colorate neighbors if boats can not touch + // Color of neighbors if boats can not touch if !rules.boats_can_touch { let mut boats_neighbors_cells = vec![]; for boat in &model.layout.0 { diff --git a/rust/sea_battle_backend/src/data/boats_layout.rs b/rust/sea_battle_backend/src/data/boats_layout.rs index 7d79fe2..fc3e45f 100644 --- a/rust/sea_battle_backend/src/data/boats_layout.rs +++ b/rust/sea_battle_backend/src/data/boats_layout.rs @@ -276,6 +276,39 @@ impl BoatsLayout { true } + /// Check a boat already present in the layout has a valid position + pub fn check_present_boat_position(&self, boat: usize, rules: &GameRules) -> Vec<&'static str> { + let mut errors = vec![]; + + // Check boat coordinates + let boat_i_coordinates = self.0[boat].all_coordinates(); + if boat_i_coordinates.iter().any(|c| !c.is_valid(rules)) { + errors.push("A boat goes outside the game map!"); + } + + for boat_j in 0..self.0.len() { + if boat == boat_j { + continue; + } + + let boat_j_coords = self.0[boat_j].all_coordinates(); + if boat_i_coordinates.iter().any(|c| boat_j_coords.contains(c)) { + errors.push("A collision between two boats has been detected!"); + } + + if !rules.boats_can_touch + && self.0[boat] + .neighbor_coordinates(rules) + .iter() + .any(|c| boat_j_coords.contains(c)) + { + errors.push("Two boats are touching!"); + } + } + + errors + } + /// Check if this boats layout is valid or not pub fn errors(&self, rules: &GameRules) -> Vec<&'static str> { let mut errors = vec![]; @@ -296,31 +329,7 @@ impl BoatsLayout { } for boat_i in 0..self.0.len() { - // Check boat coordinates - let boat_i_coordinates = self.0[boat_i].all_coordinates(); - if boat_i_coordinates.iter().any(|c| !c.is_valid(rules)) { - errors.push("A boat goes outside the game map!"); - } - - for boat_j in 0..self.0.len() { - if boat_i == boat_j { - continue; - } - - let boat_j_coords = self.0[boat_j].all_coordinates(); - if boat_i_coordinates.iter().any(|c| boat_j_coords.contains(c)) { - errors.push("A collision between two boats has been detected!"); - } - - if !rules.boats_can_touch - && self.0[boat_i] - .neighbor_coordinates(rules) - .iter() - .any(|c| boat_j_coords.contains(c)) - { - errors.push("Two boats are touching!"); - } - } + errors.append(&mut self.check_present_boat_position(boat_i, rules)); } errors @@ -330,6 +339,11 @@ impl BoatsLayout { self.errors(rules).is_empty() } + /// Get the list of boats + pub fn boats(&self) -> &[BoatPosition] { + &self.0 + } + pub fn find_boat_at_position(&self, pos: Coordinates) -> Option<&BoatPosition> { self.0.iter().find(|f| f.all_coordinates().contains(&pos)) }