summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2017-05-20 22:46:00 +0200
committerJustin Worthe <justin.worthe@gmail.com>2017-05-20 22:46:00 +0200
commitb6a295a9eaf5fec16f72870baae84e6eadd1be33 (patch)
tree6ebe3b0c388d74b4ef48babd00a09cb9a5413dc0 /src
parent6b8c71c635539a8609f82aa6eb52ea56c2c41c0c (diff)
Implemented lattice restricted battleship searching
Diffstat (limited to 'src')
-rw-r--r--src/knowledge.rs53
-rw-r--r--src/math.rs20
-rw-r--r--src/shooting.rs20
3 files changed, 81 insertions, 12 deletions
diff --git a/src/knowledge.rs b/src/knowledge.rs
index f009c10..5e45f07 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -51,10 +51,7 @@ impl Knowledge {
let unknown_hits = self.opponent_map.cells_with_unknown_hits();
let adjacent_cells = self.opponent_map.adjacent_unshot_cells(&unknown_hits);
- let possible_placements = self.opponent_map
- .ships
- .values()
- .flat_map(|knowledge| knowledge.possible_placements.clone());
+ let possible_placements = self.opponent_map.possible_placements();
let mut max_score = 1;
let mut best_cells = Vec::new();
@@ -74,6 +71,39 @@ impl Knowledge {
best_cells
}
+
+ pub fn get_most_possibility_shots_on_lattice(&self) -> Vec<Point> {
+ let on_lattice = self.opponent_map.cells_on_lattice(self.lattice_size());
+ let possible_placements = self.opponent_map.possible_placements();
+
+ let mut max_possibilities = 1;
+ let mut best_cells = Vec::new();
+
+ for cell in on_lattice {
+ let possibilities = possible_placements.iter()
+ .filter(|placement| placement.touches_point(cell)).count();
+ if possibilities > max_possibilities {
+ max_possibilities = possibilities;
+ best_cells = vec!(cell);
+ }
+ else if possibilities == max_possibilities {
+ best_cells.push(cell);
+ }
+ }
+
+ best_cells
+ }
+
+ fn lattice_size(&self) -> u16 {
+ let any_long_ships = self.opponent_map.ships.iter()
+ .any(|(ship, knowledge)| ship.length() >= 4 && !knowledge.destroyed);
+ if any_long_ships {
+ 4
+ }
+ else {
+ 2
+ }
+ }
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -173,6 +203,21 @@ impl OpponentMapKnowledge {
.filter(|&y| cells.iter().any(|z| z.is_adjacent(y)))
}).collect()
}
+
+ fn cells_on_lattice(&self, lattice_size: u16) -> Vec<Point> {
+ self.cells.iter().flat_map(|x| {
+ x.iter()
+ .filter(|y| !y.shot_attempted() && y.position.is_on_lattice(lattice_size))
+ .map(|y| y.position)
+ }).collect()
+ }
+
+ fn possible_placements(&self) -> Vec<PossibleShipPlacement> {
+ self.ships
+ .values()
+ .flat_map(|knowledge| knowledge.possible_placements.clone())
+ .collect()
+ }
}
#[derive(Serialize, Deserialize, Clone, Debug)]
diff --git a/src/math.rs b/src/math.rs
index ce9d885..da06622 100644
--- a/src/math.rs
+++ b/src/math.rs
@@ -131,4 +131,24 @@ impl Point {
(dx == 1 && dy == 0)
}
+
+ pub fn is_on_lattice(&self, lattice_size: u16) -> bool {
+ (self.x + self.y) % lattice_size == 0
+ }
+}
+
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn point_on_lattice_works() {
+ assert_eq!(true, Point::new(0,0).is_on_lattice(4));
+ assert_eq!(true, Point::new(4,0).is_on_lattice(4));
+ assert_eq!(true, Point::new(0,4).is_on_lattice(4));
+ assert_eq!(true, Point::new(4,4).is_on_lattice(4));
+ assert_eq!(true, Point::new(1,3).is_on_lattice(4));
+ assert_eq!(true, Point::new(3,1).is_on_lattice(4));
+ }
}
diff --git a/src/shooting.rs b/src/shooting.rs
index 616ebf3..4d87d86 100644
--- a/src/shooting.rs
+++ b/src/shooting.rs
@@ -17,14 +17,18 @@ pub fn shoot_smartly(knowledge: &Knowledge) -> Action {
}
fn seek_shoot(knowledge: &Knowledge) -> Point {
- let mut shot: Point;
-
- while {
- shot = Point::random(knowledge.map_size);
- let ref target = knowledge.opponent_map.cells[shot.x as usize][shot.y as usize];
- target.shot_attempted()
- } {}
- shot
+ let possibilities = knowledge.get_most_possibility_shots_on_lattice();
+ if possibilities.is_empty() {
+ println!("All possible shots on the current lattice have been tried!");
+ Point::new(0,0)
+ }
+ else {
+ let mut rng = rand::thread_rng();
+ let between = Range::new(0, possibilities.len());
+ let i = between.ind_sample(&mut rng);
+
+ possibilities[i as usize]
+ }
}
fn destroy_shoot(knowledge: &Knowledge) -> Point {