diff options
author | Justin Worthe <justin.worthe@gmail.com> | 2017-05-20 18:01:43 +0200 |
---|---|---|
committer | Justin Worthe <justin.worthe@gmail.com> | 2017-05-20 18:01:43 +0200 |
commit | 7dd0fe43fe7e72e5f56a8a61bbaec3a78399e6c8 (patch) | |
tree | 4b1cfd0375609019c0e1a07f34bf8e5574ffce84 /src/knowledge.rs | |
parent | 10c8ceb168e86a58e38086691ddd519bac63ff03 (diff) |
Moved ship placement knowledge out to be one per ship
Diffstat (limited to 'src/knowledge.rs')
-rw-r--r-- | src/knowledge.rs | 147 |
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() + } + } |