Can check if shooting a location is worthwhile or not
This commit is contained in:
parent
6832aebedb
commit
977345fb81
@ -65,7 +65,8 @@ pub struct CurrentGameStatus {
|
||||
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)
|
||||
location.is_valid(&self.rules)
|
||||
&& !self.opponent_map.successful_strikes.contains(&location)
|
||||
&& !self.opponent_map.failed_strikes.contains(&location)
|
||||
}
|
||||
|
||||
@ -211,6 +212,35 @@ impl CurrentGameStatus {
|
||||
boats_size.first().cloned()
|
||||
}
|
||||
|
||||
fn get_unshoot_room(&self, start: Coordinates, diff_x: i32, diff_y: i32) -> usize {
|
||||
let mut size = 0;
|
||||
|
||||
let mut c = start;
|
||||
|
||||
loop {
|
||||
c = c.add_x(diff_x).add_y(diff_y);
|
||||
if !self.can_fire_at_location(c) {
|
||||
break;
|
||||
}
|
||||
size += 1;
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
/// Check whether it is relevant to fire a location or not
|
||||
pub fn should_fire_at_location(&self, c: Coordinates) -> bool {
|
||||
if !self.can_fire_at_location(c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let smallest_boat = self.get_size_of_smallest_un_sunk_boat().unwrap_or_default();
|
||||
|
||||
(self.get_unshoot_room(c, -1, 0) + 1 + self.get_unshoot_room(c, 0, 1)) >= smallest_boat
|
||||
|| (self.get_unshoot_room(c, 0, -1) + 1 + self.get_unshoot_room(c, 0, 1))
|
||||
>= smallest_boat
|
||||
}
|
||||
|
||||
pub fn get_your_map(&self) -> String {
|
||||
PrintableCurrentGameMapStatus(self.rules.clone(), self.your_map.clone()).get_map()
|
||||
}
|
||||
@ -353,4 +383,64 @@ mod test {
|
||||
status.get_size_of_smallest_un_sunk_boat().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relevant_fire_location_empty_game() {
|
||||
let status = CurrentGameStatus::default();
|
||||
assert!(status.can_fire_at_location(Coordinates::new(0, 0)));
|
||||
assert!(status.should_fire_at_location(Coordinates::new(0, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relevant_fire_location_two_failed_attempt_around() {
|
||||
let mut status = CurrentGameStatus::default();
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(0, 1));
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(1, 0));
|
||||
assert!(status.can_fire_at_location(Coordinates::new(0, 0)));
|
||||
assert!(!status.should_fire_at_location(Coordinates::new(0, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relevant_fire_location_two_failed_attempt_smallest_boat_not_sunk() {
|
||||
let mut status = CurrentGameStatus::default();
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(0, 2));
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(2, 0));
|
||||
assert!(status.can_fire_at_location(Coordinates::new(0, 0)));
|
||||
assert!(status.should_fire_at_location(Coordinates::new(0, 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn relevant_fire_location_two_failed_attempt_smallest_boat_sunk() {
|
||||
let mut status = CurrentGameStatus::default();
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(0, 2));
|
||||
status
|
||||
.opponent_map
|
||||
.failed_strikes
|
||||
.push(Coordinates::new(2, 0));
|
||||
status.opponent_map.sunk_boats.push(BoatPosition {
|
||||
start: Coordinates::new(
|
||||
status.rules.map_width as i32 - 1,
|
||||
status.rules.map_height as i32 - 1,
|
||||
),
|
||||
len: 2,
|
||||
direction: BoatDirection::Left,
|
||||
});
|
||||
assert!(status.can_fire_at_location(Coordinates::new(0, 0)));
|
||||
assert!(!status.should_fire_at_location(Coordinates::new(0, 0)));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user