summaryrefslogtreecommitdiff
path: root/src/knowledge.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2017-05-20 18:01:43 +0200
committerJustin Worthe <justin.worthe@gmail.com>2017-05-20 18:01:43 +0200
commit7dd0fe43fe7e72e5f56a8a61bbaec3a78399e6c8 (patch)
tree4b1cfd0375609019c0e1a07f34bf8e5574ffce84 /src/knowledge.rs
parent10c8ceb168e86a58e38086691ddd519bac63ff03 (diff)
Moved ship placement knowledge out to be one per ship
Diffstat (limited to 'src/knowledge.rs')
-rw-r--r--src/knowledge.rs147
1 files changed, 135 insertions, 12 deletions
diff --git a/src/knowledge.rs b/src/knowledge.rs
index 3b0c61a..20c982f 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -1,27 +1,42 @@
use actions::*;
use ships::*;
+use state::*;
+use math::*;
+
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Knowledge {
- pub last_action: Option<Action>,
+ pub last_action: Action,
pub opponent_map: OpponentMapKnowledge
}
impl Knowledge {
- pub fn new() -> Knowledge {
+ pub fn new(map_size: u16, action: Action) -> Knowledge {
Knowledge {
- last_action: None,
- opponent_map: OpponentMapKnowledge::new()
+ last_action: action,
+ opponent_map: OpponentMapKnowledge::new(map_size)
}
}
pub fn with_action(&self, action: Action) -> Knowledge {
Knowledge {
- last_action: Some(action),
+ last_action: action,
opponent_map: self.opponent_map.clone()
}
}
+
+ pub fn resolve_last_action(&self, state: &State) -> Knowledge {
+ let mut new_knowledge = self.clone();
+ match self.last_action {
+ Action::PlaceShips(_) => {},
+ Action::Shoot(p) => {
+ new_knowledge.opponent_map.update_from_shot(p, &state);
+ }
+ };
+
+ new_knowledge
+ }
}
#[derive(Serialize, Deserialize, Clone, Debug)]
@@ -31,24 +46,132 @@ pub struct OpponentMapKnowledge {
}
impl OpponentMapKnowledge {
- pub fn new() -> OpponentMapKnowledge {
+ pub 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));
+ for y in 0..map_size {
+ cells[x as usize].push(KnowledgeCell::new(x, y));
+ }
+ }
+
+ let ships = Ship::all_types().iter()
+ .map(|s| (s.clone(), OpponentShipKnowledge::new(s.clone(), map_size)))
+ .collect::<HashMap<_, _>>();
+
OpponentMapKnowledge {
- ships: HashMap::new(),
- cells: Vec::new()
+ ships: ships,
+ cells: cells
}
}
+
+ fn update_from_shot(&mut self, p: Point, state: &State) {
+ 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)
+ .filter(|&(s, _)| state.opponent_map.ships.get(s).map(|x| x.destroyed) == Some(true))
+ .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];
+ if shot_cell.missed {
+ knowledge_cell.missed = true;
+ // knowledge_cell.possible_ship_uses.clear();
+ }
+ else {
+ knowledge_cell.hit = true;
+ knowledge_cell.known_ship = sunk_ship;
+ // knowledge_cell.reduce_possibilities_to_known_ship();
+ }
+
+ }
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct OpponentShipKnowledge {
- pub destroyed: bool
+ pub ship: Ship,
+ pub destroyed: bool,
+ pub possible_placements: Vec<PossibleShipPlacement>
+}
+
+impl OpponentShipKnowledge {
+ pub fn new(ship: Ship, map_size: u16) -> OpponentShipKnowledge {
+ OpponentShipKnowledge {
+ ship: ship,
+ destroyed: false,
+ possible_placements: PossibleShipPlacement::enumerate(ship, map_size)
+ }
+ }
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct KnowledgeCell {
- pub shot_attempted: bool,
- pub possible_ship_uses: HashMap<Ship, u16>,
- pub known_ship: Option<Ship>
+ 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,
+ pub position: Point
+}
+
+impl PossibleShipPlacement {
+ pub 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!(
+ PossibleShipPlacement {
+ ship: ship,
+ direction: Direction::East,
+ position: Point::new(par, per)
+ },
+ PossibleShipPlacement {
+ ship: ship,
+ direction: Direction::South,
+ position: Point::new(per, par)
+ }
+ )
+ })
+ }).collect()
+ }
+
+ pub fn touches_point(&self, p: Point) -> bool {
+ p.check_for_ship_collision(self.position, self.direction, self.ship.length())
+ }
+}
+
+impl KnowledgeCell {
+ pub fn new(x: u16, y: u16) -> KnowledgeCell {
+ KnowledgeCell {
+ missed: false,
+ hit: false,
+ position: Point::new(x, y),
+ known_ship: None
+ }
+ }
+
+ pub fn shot_attempted(&self) -> bool {
+ self.missed || self.hit
+ }
+
+ pub fn unknown_hit(&self) -> bool {
+ self.hit && self.known_ship.is_none()
+ }
+
}