summaryrefslogtreecommitdiff
path: root/src/knowledge.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2017-07-15 19:17:49 +0200
committerJustin Worthe <justin@worthe-it.co.za>2017-07-15 19:17:49 +0200
commit6379c1252e8ec51e607865638ff7d5ae79bd9c96 (patch)
treeae9dab9d7e9fa557c60835fc933e5b34e66a718a /src/knowledge.rs
parentc14a74190d72ced3e6fdbf718fce25b4a0e8cc8f (diff)
Adding shooting of new weapons
Diffstat (limited to 'src/knowledge.rs')
-rw-r--r--src/knowledge.rs134
1 files changed, 71 insertions, 63 deletions
diff --git a/src/knowledge.rs b/src/knowledge.rs
index 44693e5..4fe60da 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -11,6 +11,7 @@ pub struct Knowledge {
pub opponent_map: OpponentMapKnowledge,
pub map_size: u16,
pub available_weapons: Vec<Weapon>,
+ pub shootable_weapons: Vec<Weapon>,
pub charging_weapons: HashMap<Weapon, u16>
}
@@ -21,6 +22,7 @@ impl Knowledge {
opponent_map: OpponentMapKnowledge::new(map_size),
map_size: map_size,
available_weapons: Vec::new(),
+ shootable_weapons: Vec::new(),
charging_weapons: HashMap::new()
}
}
@@ -43,12 +45,14 @@ impl Knowledge {
available_weapons.sort_by_key(|weapon| format!("{}",weapon));
available_weapons.dedup();
- new_knowledge.available_weapons = available_weapons.iter()
+ new_knowledge.available_weapons = available_weapons;
+
+ new_knowledge.shootable_weapons = new_knowledge.available_weapons.iter()
.filter(|weapon| weapon.energy_cost(state.map_size) <= energy)
.cloned()
.collect();
- new_knowledge.charging_weapons = available_weapons.iter()
+ new_knowledge.charging_weapons = new_knowledge.available_weapons.iter()
.filter(|weapon| weapon.energy_cost(state.map_size) > energy)
.map(|weapon| (weapon.clone(), weapon.single_shot_rounds_to_ready(energy, state.map_size)))
.collect();
@@ -57,51 +61,13 @@ impl Knowledge {
Action::PlaceShips(_) => {
(vec!(), vec!(), vec!())
},
- Action::Shoot(Weapon::SingleShot, p) => {
- Knowledge::to_hits_and_misses(vec!(Some(p)), &state)
- },
- 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)
}
+
+ Action::Shoot(w, p) => {
+ Knowledge::to_hits_and_misses(w.affected_cells(p, state.map_size), &state)
+ }
};
let sunk_ships = new_knowledge.opponent_map.update_sunk_ships(&state);
@@ -111,9 +77,7 @@ 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<_>>();
-
+ fn to_hits_and_misses(points: Vec<Point>, state: &State) -> (Vec<Point>, Vec<Point>, Vec<Point>) {
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();
@@ -157,7 +121,7 @@ impl Knowledge {
//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);
+ let (mut new_hits, mut new_misses, mut unknown) = Knowledge::to_hits_and_misses(ring.iter().filter_map(|&p| p).collect::<Vec<_>>(), &state);
misses.append(&mut new_misses);
if !new_hits.is_empty() {
hits.append(&mut new_hits);
@@ -201,26 +165,64 @@ 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());
+ pub fn get_best_seek_shots(&self) -> (Weapon, Vec<Point>) {
let possible_placements = self.opponent_map.possible_placements();
+ // let lattice = self.lattice_size(); //TODO use the lattice still?
- 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);
+ let mut best_shots: HashMap<Weapon, (Vec<Point>, usize)> = HashMap::new();
+
+ for &weapon in self.available_weapons.iter() {
+ let mut current_best_score = 1;
+ let mut best_cells = Vec::new();
+
+ for target in self.opponent_map.flat_cell_position_list() {
+ let cells = if weapon == Weapon::SeekerMissle {
+ let full_range = weapon.affected_cells(target, self.map_size);
+ let has_hits = full_range.iter().any(|p| self.opponent_map.cells[p.x as usize][p.y as usize].hit);
+ if has_hits {
+ vec!()
+ }
+ else {
+ full_range
+ }
+ }
+ else {
+ weapon.affected_cells(target, self.map_size)
+ };
+
+ let possibilities = possible_placements.iter()
+ .filter(|placement| placement.touches_any_point(&cells))
+ .count();
+
+ if possibilities > current_best_score {
+ current_best_score = possibilities;
+ best_cells = vec!(target);
+ }
+ else if possibilities == current_best_score {
+ best_cells.push(target);
+ }
}
+
+ best_shots.insert(weapon, (best_cells, current_best_score));
}
- best_cells
+ let best_single: Option<(Weapon, (Vec<Point>, usize))> =
+ best_shots.get(&Weapon::SingleShot).map(|x| (Weapon::SingleShot, x.clone()));
+
+ let best: (Weapon, (Vec<Point>, usize)) =
+ best_shots.iter()
+ .max_by_key(|&(_, &(_, score))| score)
+ .and_then(|(&weapon, x)| {
+ if self.shootable_weapons.contains(&weapon) {
+ Some((weapon, x.clone()))
+ } else {
+ best_single
+ }
+ })
+ .unwrap_or((Weapon::SingleShot, (vec!(), 0)));
+
+
+ (best.0.clone(), (best.1).0)
}
fn lattice_size(&self) -> u16 {
@@ -344,6 +346,12 @@ impl OpponentMapKnowledge {
}).collect()
}
+ fn flat_cell_position_list(&self) -> Vec<Point> {
+ self.cells.iter().flat_map(|x| {
+ x.iter().map(|y| y.position)
+ }).collect()
+ }
+
fn cells_on_lattice(&self, lattice_size: u16) -> Vec<Point> {
self.cells.iter().flat_map(|x| {
x.iter()