summaryrefslogtreecommitdiff
path: root/src/knowledge.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2017-06-24 17:49:35 +0200
committerJustin Worthe <justin@worthe-it.co.za>2017-06-24 17:49:35 +0200
commit7355491e14081c6dff749d6c536e876cfebc5d0d (patch)
tree197c135c7c7d04f539c4ca7c0ecdb8c72e9173d8 /src/knowledge.rs
parentd7a5ae25a5a15064f695d79e2b510c9c305fb841 (diff)
Implemented knowledge updates based on all weapon types
Diffstat (limited to 'src/knowledge.rs')
-rw-r--r--src/knowledge.rs113
1 files changed, 104 insertions, 9 deletions
diff --git a/src/knowledge.rs b/src/knowledge.rs
index 4ade5f5..f271dbe 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -53,21 +53,57 @@ impl Knowledge {
.map(|weapon| (weapon.clone(), weapon.single_shot_rounds_to_ready(energy, state.map_size)))
.collect();
- let points = match self.last_action {
+ let (hits, misses, _) = match self.last_action {
Action::PlaceShips(_) => {
- vec!()
+ (vec!(), vec!(), vec!())
},
Action::Shoot(Weapon::SingleShot, p) => {
- vec!(p)
+ Knowledge::to_hits_and_misses(vec!(Some(p)), &state)
},
- Action::Shoot(w, p) => {
- vec!()
- //TODO
+ Action::Shoot(Weapon::DoubleShotVertical, p) => {
+ Knowledge::to_hits_and_misses(vec!(
+ p.move_point(Direction::North, 1, state.map_size),
+ p.move_point(Direction::South, 1, state.map_size)
+ ), &state)
+ },
+ Action::Shoot(Weapon::DoubleShotHorizontal, p) => {
+ Knowledge::to_hits_and_misses(vec!(
+ p.move_point(Direction::East, 1, state.map_size),
+ p.move_point(Direction::West, 1, state.map_size)
+ ), &state)
+ },
+ Action::Shoot(Weapon::CornerShot, p) => {
+ Knowledge::to_hits_and_misses(vec!(
+ p.move_point(Direction::NorthEast, 1, state.map_size),
+ p.move_point(Direction::SouthEast, 1, state.map_size),
+ p.move_point(Direction::NorthWest, 1, state.map_size),
+ p.move_point(Direction::SouthWest, 1, state.map_size),
+ ), &state)
+ },
+ Action::Shoot(Weapon::CrossShotDiagonal, p) => {
+ Knowledge::to_hits_and_misses(vec!(
+ p.move_point(Direction::NorthEast, 1, state.map_size),
+ p.move_point(Direction::SouthEast, 1, state.map_size),
+ p.move_point(Direction::NorthWest, 1, state.map_size),
+ p.move_point(Direction::SouthWest, 1, state.map_size),
+ Some(p)
+ ), &state)
+ },
+ Action::Shoot(Weapon::CrossShotHorizontal, p) => {
+ Knowledge::to_hits_and_misses(vec!(
+ p.move_point(Direction::North, 1, state.map_size),
+ p.move_point(Direction::East, 1, state.map_size),
+ p.move_point(Direction::South, 1, state.map_size),
+ p.move_point(Direction::West, 1, state.map_size),
+ Some(p)
+ ), &state)
+ },
+
+ Action::Shoot(Weapon::SeekerMissle, p) => {
+ Knowledge::seeker_hits_and_misses(p, &state)
}
};
-
- let misses = points.iter().filter(|p| state.opponent_map.cells[p.x as usize][p.y as usize].missed).cloned().collect();
- let hits = points.iter().filter(|p| !state.opponent_map.cells[p.x as usize][p.y as usize].missed).cloned().collect();
+
let sunk_ships = new_knowledge.opponent_map.update_sunk_ships(&state);
new_knowledge.opponent_map.update_from_shot(hits, misses, sunk_ships);
@@ -75,6 +111,65 @@ impl Knowledge {
new_knowledge
}
+ fn to_hits_and_misses(points: Vec<Option<Point>>, state: &State) -> (Vec<Point>, Vec<Point>, Vec<Point>) {
+ let points = points.iter().filter_map(|&p| p).collect::<Vec<_>>();
+
+ let hits = points.iter().filter(|p| !state.opponent_map.cells[p.x as usize][p.y as usize].damaged).cloned().collect();
+ let misses = points.iter().filter(|p| state.opponent_map.cells[p.x as usize][p.y as usize].missed).cloned().collect();
+ let unknown = points.iter().filter(|p| !state.opponent_map.cells[p.x as usize][p.y as usize].missed && !state.opponent_map.cells[p.x as usize][p.y as usize].damaged).cloned().collect();
+
+ (hits, misses, unknown)
+ }
+
+ fn seeker_hits_and_misses(p: Point, state: &State) -> (Vec<Point>, Vec<Point>, Vec<Point>) {
+ let mut misses: Vec<Point> = Vec::new();
+ let mut hits: Vec<Point> = Vec::new();
+
+ let rings = vec!(
+ vec!(
+ //0
+ Some(p)
+ ),
+ vec!(
+ //1
+ p.move_point(Direction::North, 1, state.map_size),
+ p.move_point(Direction::East, 1, state.map_size),
+ p.move_point(Direction::South, 1, state.map_size),
+ p.move_point(Direction::West, 1, state.map_size),
+ ),
+ vec!(
+ //1.44
+ p.move_point(Direction::NorthEast, 1, state.map_size),
+ p.move_point(Direction::SouthEast, 1, state.map_size),
+ p.move_point(Direction::NorthWest, 1, state.map_size),
+ p.move_point(Direction::SouthWest, 1, state.map_size)
+ ),
+ vec!(
+ //2
+ p.move_point(Direction::North, 2, state.map_size),
+ p.move_point(Direction::East, 2, state.map_size),
+ p.move_point(Direction::South, 2, state.map_size),
+ p.move_point(Direction::West, 2, state.map_size),
+ )
+ );
+
+ //start in the center. Add rings, until I find a hit
+ //don't add more after a hit is found
+ for ring in rings {
+ if hits.is_empty() {
+ let (mut new_hits, mut new_misses, mut unknown) = Knowledge::to_hits_and_misses(ring, &state);
+ misses.append(&mut new_misses);
+ if !new_hits.is_empty() {
+ hits.append(&mut new_hits);
+ } else {
+ misses.append(&mut unknown);
+ }
+ }
+ }
+
+ (hits, misses, vec!())
+ }
+
pub fn has_unknown_hits(&self) -> bool {
self.opponent_map.cells.iter().fold(false, |acc, x| {
x.iter().fold(acc, |acc, y| acc || y.unknown_hit())