summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin.worthe@gmail.com>2017-06-18 15:15:11 +0200
committerJustin Worthe <justin.worthe@gmail.com>2017-06-18 15:15:11 +0200
commit862897ea1d183810c2783eaeeaf40f648ef3dc2d (patch)
treefb168f1122fa2839b52443c54555593045262a2a /src
parent29181fce4797b6e4833ab56d1fa7ff9fa865965b (diff)
Added knowledge of weapons
Next step: knowledge of weapon's effects.
Diffstat (limited to 'src')
-rw-r--r--src/actions.rs4
-rw-r--r--src/knowledge.rs35
-rw-r--r--src/ships.rs69
-rw-r--r--src/shooting.rs6
-rw-r--r--src/state.rs44
5 files changed, 149 insertions, 9 deletions
diff --git a/src/actions.rs b/src/actions.rs
index 2291de6..ae1f6ce 100644
--- a/src/actions.rs
+++ b/src/actions.rs
@@ -8,13 +8,13 @@ use std::collections::HashSet;
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum Action {
PlaceShips(Vec<ShipPlacement>),
- Shoot(Point)
+ Shoot(Weapon, Point)
}
impl fmt::Display for Action {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
- &Action::Shoot(p) => writeln!(f, "1,{},{}", p.x, p.y),
+ &Action::Shoot(w, p) => writeln!(f, "{},{},{}", w, p.x, p.y),
&Action::PlaceShips(ref ships) => ships.iter().map(|ref ship| {
writeln!(f, "{} {} {} {}", ship.ship_type, ship.point.x, ship.point.y, ship.direction)
}).fold(Ok(()), |acc, next| acc.and(next))
diff --git a/src/knowledge.rs b/src/knowledge.rs
index 5e45f07..e12a8b2 100644
--- a/src/knowledge.rs
+++ b/src/knowledge.rs
@@ -9,7 +9,9 @@ use std::collections::HashMap;
pub struct Knowledge {
pub last_action: Action,
pub opponent_map: OpponentMapKnowledge,
- pub map_size: u16
+ pub map_size: u16,
+ pub available_weapons: Vec<Weapon>,
+ pub charging_weapons: HashMap<Weapon, u16>
}
impl Knowledge {
@@ -17,24 +19,47 @@ impl Knowledge {
Knowledge {
last_action: action,
opponent_map: OpponentMapKnowledge::new(map_size),
- map_size: map_size
+ map_size: map_size,
+ available_weapons: Vec::new(),
+ charging_weapons: HashMap::new()
}
}
pub fn with_action(&self, action: Action) -> Knowledge {
Knowledge {
last_action: action,
- opponent_map: self.opponent_map.clone(),
- map_size: self.map_size
+ ..self.clone()
}
}
pub fn resolve_last_action(&self, state: &State) -> Knowledge {
let mut new_knowledge = self.clone();
+
+ let energy = state.player_map.energy;
+ let mut available_weapons: Vec<_> = state.player_map.ships.iter()
+ .filter(|&(_, ship_data)| !ship_data.destroyed)
+ .flat_map(|(ship, _)| ship.weapons())
+ .collect();
+
+ available_weapons.sort_by_key(|weapon| format!("{}",weapon));
+ available_weapons.dedup();
+ new_knowledge.available_weapons = available_weapons.iter()
+ .filter(|weapon| weapon.energy_cost(state.map_size) <= energy)
+ .cloned()
+ .collect();
+
+ new_knowledge.charging_weapons = available_weapons.iter()
+ .filter(|weapon| weapon.energy_cost(state.map_size) > energy)
+ .map(|weapon| (weapon.clone(), weapon.energy_cost(state.map_size) - energy))
+ .collect();
+
match self.last_action {
Action::PlaceShips(_) => {},
- Action::Shoot(p) => {
+ Action::Shoot(Weapon::SingleShot, p) => {
new_knowledge.opponent_map.update_from_shot(p, &state);
+ },
+ Action::Shoot(w, p) => {
+ //TODO
}
};
diff --git a/src/ships.rs b/src/ships.rs
index ef29fe9..e37fe33 100644
--- a/src/ships.rs
+++ b/src/ships.rs
@@ -2,6 +2,62 @@ use std::fmt;
use std::str;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
+pub enum Weapon {
+ SingleShot,
+ DoubleShotVertical,
+ DoubleShotHorizontal,
+ CornerShot,
+ CrossShotDiagonal,
+ CrossShotHorizontal,
+ SeekerMissle
+}
+
+impl fmt::Display for Weapon {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ use Weapon::*;
+
+ f.write_str(
+ match self {
+ &SingleShot => "1",
+ &DoubleShotVertical => "2",
+ &DoubleShotHorizontal => "3",
+ &CornerShot => "4",
+ &CrossShotDiagonal => "5",
+ &CrossShotHorizontal => "6",
+ &SeekerMissle => "7"
+ }
+ )
+ }
+}
+
+impl Weapon {
+ pub fn energy_per_round(map_size: u16) -> u16 {
+ if map_size < 10 {
+ 2
+ }
+ else if map_size < 14 {
+ 3
+ }
+ else {
+ 4
+ }
+ }
+ pub fn energy_cost(&self, map_size: u16) -> u16 {
+ use Weapon::*;
+ let epr = Weapon::energy_per_round(map_size);
+ match self {
+ &SingleShot => 1,
+ &DoubleShotVertical | &DoubleShotHorizontal => 8*epr,
+ &CornerShot => 10*epr,
+ &CrossShotDiagonal => 12*epr,
+ &CrossShotHorizontal => 14*epr,
+ &SeekerMissle => 10*epr
+ }
+ }
+}
+
+
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
pub enum Ship {
Battleship,
Carrier,
@@ -55,6 +111,19 @@ impl Ship {
}
}
+ pub fn weapons(&self) -> Vec<Weapon> {
+ use Ship::*;
+ use Weapon::*;
+
+ match self {
+ &Battleship => vec!(SingleShot, CrossShotDiagonal),
+ &Carrier => vec!(SingleShot, CornerShot),
+ &Cruiser => vec!(SingleShot, CrossShotHorizontal),
+ &Destroyer => vec!(SingleShot, DoubleShotVertical, DoubleShotHorizontal),
+ &Submarine => vec!(SingleShot, SeekerMissle)
+ }
+ }
+
pub fn all_types() -> Vec<Ship> {
use Ship::*;
diff --git a/src/shooting.rs b/src/shooting.rs
index 4d87d86..bcdf783 100644
--- a/src/shooting.rs
+++ b/src/shooting.rs
@@ -4,6 +4,7 @@ use rand::distributions::{IndependentSample, Range};
use actions::*;
use math::*;
use knowledge::*;
+use ships::*;
pub fn shoot_smartly(knowledge: &Knowledge) -> Action {
let shot = if knowledge.has_unknown_hits() {
@@ -12,8 +13,9 @@ pub fn shoot_smartly(knowledge: &Knowledge) -> Action {
else {
seek_shoot(&knowledge)
};
-
- Action::Shoot(shot)
+
+ //TODO shoot other weapons
+ Action::Shoot(Weapon::SingleShot, shot)
}
fn seek_shoot(knowledge: &Knowledge) -> Point {
diff --git a/src/state.rs b/src/state.rs
index 8c176e1..1756ad0 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -4,17 +4,23 @@ use ships::*;
pub struct State {
pub map_size: u16,
+ pub player_map: PlayerMap,
pub opponent_map: OpponentMap
}
impl State {
pub fn new(json: &json::JsonValue) -> Result<State, String> {
let map_size = State::map_size_from_json(&json)?;
+
+ let ref player_map_json = json["PlayerMap"];
+ let player_map = PlayerMap::new(&player_map_json)?;
+
let ref opponent_map_json = json["OpponentMap"];
let opponent_map = OpponentMap::new(&opponent_map_json, map_size)?;
Ok(State {
map_size: map_size,
+ player_map: player_map,
opponent_map: opponent_map
})
}
@@ -100,3 +106,41 @@ impl Cell {
}
}
}
+
+pub struct PlayerMap {
+ pub ships: HashMap<Ship, PlayerShip>,
+ pub energy: u16
+}
+
+impl PlayerMap {
+ fn new(json: &json::JsonValue) -> Result<PlayerMap, String> {
+ let mut ships = HashMap::new();
+ for json_ship in json["Owner"]["Ships"].members() {
+ let ship_type_string = json_ship["ShipType"]
+ .as_str()
+ .ok_or(String::from("Failed to read ShipType value of player map ship in json file"))?;
+ let ship_type = ship_type_string.parse::<Ship>()?;
+
+ let destroyed = json_ship["Destroyed"]
+ .as_bool()
+ .ok_or(String::from("Failed to read Destroyed value of player map ship in json file"))?;
+ ships.insert(ship_type, PlayerShip {
+ destroyed: destroyed
+ });
+ }
+
+ let energy = json["Owner"]["Energy"]
+ .as_u16()
+ .ok_or(String::from("Did not find the energy in the state json file"))?;
+
+ Ok(PlayerMap {
+ ships: ships,
+ energy: energy
+ })
+ }
+}
+
+
+pub struct PlayerShip {
+ pub destroyed: bool
+}