summaryrefslogtreecommitdiff
path: root/src/knowledge.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2017-05-20 20:58:18 +0200
committerJustin Worthe <justin.worthe@gmail.com>2017-05-20 20:58:18 +0200
commit973f7be695f7c3308d384e1ee30066547e4a07c7 (patch)
treebb6b6ee2ca9971a4d9b2c052e9e537ce5a287d21 /src/knowledge.rs
parent7dd0fe43fe7e72e5f56a8a61bbaec3a78399e6c8 (diff)
Eliminated more possibilities when ships are sunk
Diffstat (limited to 'src/knowledge.rs')
-rw-r--r--src/knowledge.rs112
1 files changed, 81 insertions, 31 deletions
diff --git a/src/knowledge.rs b/src/knowledge.rs
index 20c982f..01c098d 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -37,6 +37,8 @@ impl Knowledge {
new_knowledge
}
+
+
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -46,7 +48,7 @@ pub struct OpponentMapKnowledge {
}
impl OpponentMapKnowledge {
- pub fn new(map_size: u16) -> OpponentMapKnowledge {
+ fn new(map_size: u16) -> OpponentMapKnowledge {
let mut cells = Vec::with_capacity(map_size as usize);
for x in 0..map_size {
cells.push(Vec::with_capacity(map_size as usize));
@@ -66,6 +68,7 @@ impl OpponentMapKnowledge {
}
fn update_from_shot(&mut self, p: Point, state: &State) {
+ let cells_copy = self.cells.clone();
let ref shot_cell = state.opponent_map.cells[p.x as usize][p.y as usize];
let sunk_ship = self.ships.iter()
.filter(|&(_, x)| !x.destroyed)
@@ -73,27 +76,52 @@ impl OpponentMapKnowledge {
.map(|(s, _)| s.clone())
.next(); //only one ship can be sunk at a time
- match sunk_ship {
- None => {},
- Some(ship) => {
- match self.ships.get_mut(&ship) {
- Some(ref mut ship_knowledge) => {ship_knowledge.destroyed = true},
- None => {}
- }
- }
- }
-
- let ref mut knowledge_cell = self.cells[p.x as usize][p.y as usize];
+
+ sunk_ship
+ .and_then(|ship| self.ships.get_mut(&ship))
+ .map(|ref mut ship_knowledge| ship_knowledge.destroyed = true);
+
if shot_cell.missed {
- knowledge_cell.missed = true;
- // knowledge_cell.possible_ship_uses.clear();
+ self.cells[p.x as usize][p.y as usize].missed = true;
+ for knowledge in self.ships.values_mut() {
+ knowledge.possible_placements.retain(|x| !x.touches_point(p));
+ }
}
else {
- knowledge_cell.hit = true;
- knowledge_cell.known_ship = sunk_ship;
- // knowledge_cell.reduce_possibilities_to_known_ship();
+ self.cells[p.x as usize][p.y as usize].hit = true;
+ self.cells[p.x as usize][p.y as usize].known_ship = sunk_ship;
+
+ if sunk_ship.is_some() {
+ for knowledge in self.ships.values_mut() {
+ knowledge.possible_placements.retain(|x| {
+ (sunk_ship != Some(x.ship) && !x.touches_point(p)) ||
+ (sunk_ship == Some(x.ship) && x.touches_point(p) && x.all_are_hits(&cells_copy))
+
+ });
+ }
+ }
}
+ self.derive_ship_positions();
+ }
+
+ fn derive_ship_positions(&mut self) {
+ for knowledge in self.ships.values() {
+ if knowledge.possible_placements.len() == 1 {
+ let ref true_placement = knowledge.possible_placements[0];
+ for p in true_placement.points_on_ship() {
+ self.cells[p.x as usize][p.y as usize].known_ship = Some(true_placement.ship);
+ }
+ }
+ }
+ self.clear_impossible_placements();
+ }
+
+ fn clear_impossible_placements(&mut self) {
+ let ref cells = self.cells;
+ for knowledge in self.ships.values_mut() {
+ knowledge.possible_placements.retain(|x| x.all_could_be_hits(&cells));
+ }
}
}
@@ -105,7 +133,7 @@ pub struct OpponentShipKnowledge {
}
impl OpponentShipKnowledge {
- pub fn new(ship: Ship, map_size: u16) -> OpponentShipKnowledge {
+ fn new(ship: Ship, map_size: u16) -> OpponentShipKnowledge {
OpponentShipKnowledge {
ship: ship,
destroyed: false,
@@ -115,14 +143,6 @@ impl OpponentShipKnowledge {
}
#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct KnowledgeCell {
- pub missed: bool,
- pub hit: bool,
- pub known_ship: Option<Ship>,
- pub position: Point
-}
-
-#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct PossibleShipPlacement {
pub ship: Ship,
pub direction: Direction,
@@ -130,7 +150,7 @@ pub struct PossibleShipPlacement {
}
impl PossibleShipPlacement {
- pub fn enumerate(ship: Ship, map_size: u16) -> Vec<PossibleShipPlacement> {
+ fn enumerate(ship: Ship, map_size: u16) -> Vec<PossibleShipPlacement> {
(0..(map_size-ship.length()+1)).flat_map(move |par| {
(0..map_size).flat_map(move |per| {
vec!(
@@ -149,13 +169,43 @@ impl PossibleShipPlacement {
}).collect()
}
- pub fn touches_point(&self, p: Point) -> bool {
+ fn touches_point(&self, p: Point) -> bool {
p.check_for_ship_collision(self.position, self.direction, self.ship.length())
}
+
+ fn points_on_ship(&self) -> Vec<Point> {
+ (0..self.ship.length() as i32).map(|i| {
+ self.position.move_point_no_bounds_check(self.direction, i)
+ }).collect()
+ }
+
+ fn all_are_hits(&self, cells: &Vec<Vec<KnowledgeCell>>) -> bool {
+ self.points_on_ship()
+ .iter()
+ .fold(true, |acc, p| acc && cells[p.x as usize][p.y as usize].hit)
+ }
+
+ fn all_could_be_hits(&self, cells: &Vec<Vec<KnowledgeCell>>) -> bool {
+ self.points_on_ship()
+ .iter()
+ .fold(true, |acc, p| {
+ let ref cell = cells[p.x as usize][p.y as usize];
+ acc && !cell.missed &&
+ cell.known_ship.map(|ship| ship == self.ship).unwrap_or(true)
+ })
+ }
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct KnowledgeCell {
+ pub missed: bool,
+ pub hit: bool,
+ pub known_ship: Option<Ship>,
+ pub position: Point
}
impl KnowledgeCell {
- pub fn new(x: u16, y: u16) -> KnowledgeCell {
+ fn new(x: u16, y: u16) -> KnowledgeCell {
KnowledgeCell {
missed: false,
hit: false,
@@ -164,11 +214,11 @@ impl KnowledgeCell {
}
}
- pub fn shot_attempted(&self) -> bool {
+ fn shot_attempted(&self) -> bool {
self.missed || self.hit
}
- pub fn unknown_hit(&self) -> bool {
+ fn unknown_hit(&self) -> bool {
self.hit && self.known_ship.is_none()
}