summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2019-07-08 22:31:41 +0200
committerJustin Worthe <justin@worthe-it.co.za>2019-07-08 22:31:41 +0200
commit770f14609849552d965b4e9101bfb5c0870c08d0 (patch)
tree170ebb08b86ccc5027752f37bf0dda4be516a2b7
parent2d4647a618234ef496899d875f75d57b5af1a6e5 (diff)
Command filtering to avoid wasting the selects
-rw-r--r--src/game.rs4
-rw-r--r--src/geometry/direction.rs25
-rw-r--r--src/strategy.rs7
-rw-r--r--src/strategy/minimax.rs37
4 files changed, 47 insertions, 26 deletions
diff --git a/src/game.rs b/src/game.rs
index 4e074ea..c31f64f 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -458,7 +458,7 @@ impl GameBoard {
}
pub fn valid_moves_for_worm(&self, worm: &Worm) -> ArrayVec<[Action; 8]> {
- Direction::all()
+ Direction::ALL
.iter()
.map(Direction::as_vec)
.map(|d| worm.position + d)
@@ -491,7 +491,7 @@ impl GameBoard {
}
pub fn valid_shoot_commands(&self, player_index: usize) -> ArrayVec<[Command; 24]> {
- let all_dirs = Direction::all();
+ let all_dirs = Direction::ALL;
let no_select = all_dirs.iter().map(|d| Command::new(Action::Shoot(*d)));
self.valid_selects(player_index)
diff --git a/src/geometry/direction.rs b/src/geometry/direction.rs
index 737bd00..d3f3b20 100644
--- a/src/geometry/direction.rs
+++ b/src/geometry/direction.rs
@@ -1,5 +1,5 @@
-use std::fmt;
use crate::geometry::vec::Vec2d;
+use std::fmt;
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Direction {
@@ -54,17 +54,14 @@ impl Direction {
}
}
- pub fn all() -> [Direction; 8] {
- use Direction::*;
- [
- North,
- NorthEast,
- East,
- SouthEast,
- South,
- SouthWest,
- West,
- NorthWest,
- ]
- }
+ pub const ALL: [Direction; 8] = [
+ Direction::North,
+ Direction::NorthEast,
+ Direction::East,
+ Direction::SouthEast,
+ Direction::South,
+ Direction::SouthWest,
+ Direction::West,
+ Direction::NorthWest,
+ ];
}
diff --git a/src/strategy.rs b/src/strategy.rs
index 9c79d60..b6069a1 100644
--- a/src/strategy.rs
+++ b/src/strategy.rs
@@ -1,4 +1,5 @@
-mod mcts;
-mod minimax;
+//mod mcts;
+//pub use mcts::{choose_move, Node};
-pub use mcts::{choose_move, Node};
+mod minimax;
+pub use minimax::{choose_move, Node};
diff --git a/src/strategy/minimax.rs b/src/strategy/minimax.rs
index 2ed84b2..31e58a0 100644
--- a/src/strategy/minimax.rs
+++ b/src/strategy/minimax.rs
@@ -23,7 +23,7 @@ pub fn choose_move(
.children
.drain()
.map(|(_k, n)| n)
- .find(|n| false) // TODO: Identify the last opponent move to use this cache
+ .find(|_n| false) // TODO: Identify the last opponent move to use this cache
.unwrap_or_else(|| {
eprintln!("Previous round did not appear in the cache");
Node {
@@ -227,14 +227,37 @@ fn update(node: &mut Node, commands: [Command; 2], score: Score) {
}
fn pruned_moves(state: &GameBoard, player_index: usize) -> Vec<Command> {
- // TODO: Play one move into the future and make sure this doesn't
- // hurt me or do something dumb? Should I rather specialize this
- // to each type of move?
+ let sim_with_idle_opponent = |cmd| {
+ let mut idle_commands = [
+ Command::new(Action::DoNothing),
+ Command::new(Action::DoNothing),
+ ];
+ idle_commands[player_index] = cmd;
+ let mut state_cpy = state.clone();
+ state_cpy.simulate(idle_commands);
+ state_cpy
+ };
+
+ let opponent_index = GameBoard::opponent(player_index);
+ let my_starting_health = state.players[player_index].health();
+ let opponent_starting_health = state.players[opponent_index].health();
- // TODO: Ensure that there are at least some moves left here. If
- // there's nothing, at least return a vector that contains a
- // nothing move.
valid_moves(state, player_index)
+ .into_iter()
+ .filter(|command| {
+ //NB: These rules should pass for doing nothing, otherwise
+ // we need some other mechanism for sticking in a do
+ // nothing option
+
+ let idle_opponent_state = sim_with_idle_opponent(*command);
+ let hurt_self = idle_opponent_state.players[player_index].health() < my_starting_health;
+ let hurt_opponent =
+ idle_opponent_state.players[opponent_index].health() < opponent_starting_health;
+ let is_select = command.worm.is_some();
+
+ !hurt_self && (!is_select || hurt_opponent)
+ })
+ .collect()
}
fn valid_moves(state: &GameBoard, player_index: usize) -> Vec<Command> {