summaryrefslogtreecommitdiff
path: root/src/strategy.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2019-05-26 00:28:28 +0200
committerJustin Worthe <justin@worthe-it.co.za>2019-05-26 00:28:28 +0200
commitd37be51f196eebdb8df57c87e8ab5bb684e1dcd9 (patch)
tree9625bf847698fd4072682839ede1f917c74bebbd /src/strategy.rs
parent7b3fe83b4bdb943d3d44ed036150d017279cfe05 (diff)
Score based MCTS
Diffstat (limited to 'src/strategy.rs')
-rw-r--r--src/strategy.rs146
1 files changed, 81 insertions, 65 deletions
diff --git a/src/strategy.rs b/src/strategy.rs
index 39bbe66..8e004cf 100644
--- a/src/strategy.rs
+++ b/src/strategy.rs
@@ -159,8 +159,8 @@ fn mcts(node: &mut Node) -> Score {
}
fn mcts_move_combo(state: &GameBoard) -> Vec<[Command; 2]> {
- let player_moves = heuristic_moves(state, 0);
- let opponent_moves = heuristic_moves(state, 1);
+ let player_moves = valid_moves(state, 0);
+ let opponent_moves = valid_moves(state, 1);
debug_assert!(player_moves.len() > 0, "No player moves");
debug_assert!(player_moves.len() > 0, "No opponent moves");
@@ -183,12 +183,12 @@ fn best_player_move(node: &Node) -> Command {
}
fn score(state: &GameBoard) -> Score {
- let mutiplier = match state.outcome {
- SimulationOutcome::PlayerWon(_) => 1000.,
- _ => 1.,
- };
Score {
- val: mutiplier * (state.players[0].health() - state.players[1].health()) as f32,
+ val: match state.outcome {
+ SimulationOutcome::PlayerWon(0) => 10000.,
+ SimulationOutcome::PlayerWon(1) => -10000.,
+ _ => (state.players[0].score() - state.players[1].score()) as f32,
+ }
}
}
@@ -242,71 +242,87 @@ fn update(node: &mut Node, commands: [Command; 2], score: Score) {
node.score_sum += score;
}
-fn heuristic_moves(state: &GameBoard, player_index: usize) -> Vec<Command> {
- let worm = state.players[player_index].active_worm();
+// fn heuristic_moves(state: &GameBoard, player_index: usize) -> Vec<Command> {
+// let worm = state.players[player_index].active_worm();
+
+// let shoots = state
+// .valid_shoot_commands(player_index, worm.position, worm.weapon_range);
+
+// let closest_powerup = state.powerups
+// .iter()
+// .min_by_key(|p| (p.position - worm.position).walking_distance());
+
+// let average_player_position = Point2d {
+// x: state.players[player_index].worms
+// .iter()
+// .map(|w| w.position.x)
+// .sum::<i8>() / state.players[player_index].worms.len() as i8,
+// y: state.players[player_index].worms
+// .iter()
+// .map(|w| w.position.y)
+// .sum::<i8>() / state.players[player_index].worms.len() as i8
+// };
+
+// let closest_opponent = state.players[GameBoard::opponent(player_index)].worms
+// .iter()
+// .min_by_key(|w| (w.position - average_player_position).walking_distance());
+
+// let mut commands = if !shoots.is_empty() {
+// // we're in combat now. Feel free to move anywhere.
+// let moves = state.valid_move_commands(player_index);
+// moves.iter().chain(shoots.iter()).cloned().collect()
+// } else if let Some(powerup) = closest_powerup {
+// // there are powerups! Let's go grab the closest one.
+// moves_towards(state, player_index, powerup.position)
+// } else if let Some(opponent) = closest_opponent {
+// // we're not currently in combat. Let's go find the closest worm.
+// moves_towards(state, player_index, opponent.position)
+// } else {
+// // this shouldn't happen
+// debug_assert!(false, "No valid heuristic moves");
+// vec!()
+// };
+// commands.push(Command::DoNothing);
+// commands
+// }
+
+// fn moves_towards(state: &GameBoard, player_index: usize, to: Point2d<i8>) -> Vec<Command> {
+// let distance = (to - state.players[player_index].active_worm().position).walking_distance();
+// state.valid_move_commands(player_index)
+// .iter()
+// .filter(|c| match c {
+// Command::Move(p) | Command::Dig(p) => (to - *p).walking_distance() < distance,
+// _ => false
+// })
+// .cloned()
+// .collect()
+// }
- let shoots = state
- .valid_shoot_commands(player_index, worm.position, worm.weapon_range);
+fn rollout_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 8]> {
+ if let Some(worm) = state.players[player_index].active_worm() {
- let closest_powerup = state.powerups
- .iter()
- .min_by_key(|p| (p.position - worm.position).walking_distance());
+ let shoots = state.valid_shoot_commands(player_index, worm.position, worm.weapon_range);
- let average_player_position = Point2d {
- x: state.players[player_index].worms
- .iter()
- .map(|w| w.position.x)
- .sum::<i8>() / state.players[player_index].worms.len() as i8,
- y: state.players[player_index].worms
- .iter()
- .map(|w| w.position.y)
- .sum::<i8>() / state.players[player_index].worms.len() as i8
- };
+ if !shoots.is_empty() {
+ return shoots;
+ }
- let closest_opponent = state.players[GameBoard::opponent(player_index)].worms
- .iter()
- .min_by_key(|w| (w.position - average_player_position).walking_distance());
-
- let mut commands = if !shoots.is_empty() {
- // we're in combat now. Feel free to move anywhere.
- let moves = state.valid_move_commands(player_index);
- moves.iter().chain(shoots.iter()).cloned().collect()
- } else if let Some(powerup) = closest_powerup {
- // there are powerups! Let's go grab the closest one.
- moves_towards(state, player_index, powerup.position)
- } else if let Some(opponent) = closest_opponent {
- // we're not currently in combat. Let's go find the closest worm.
- moves_towards(state, player_index, opponent.position)
+ // TODO: More directed destruction movements?
+ state.valid_move_commands(player_index)
} else {
- // this shouldn't happen
- debug_assert!(false, "No valid heuristic moves");
- vec!()
- };
- commands.push(Command::DoNothing);
- commands
+ [Command::DoNothing].iter().cloned().collect()
+ }
}
-fn moves_towards(state: &GameBoard, player_index: usize, to: Point2d<i8>) -> Vec<Command> {
- let distance = (to - state.players[player_index].active_worm().position).walking_distance();
- state.valid_move_commands(player_index)
- .iter()
- .filter(|c| match c {
- Command::Move(p) | Command::Dig(p) => (to - *p).walking_distance() < distance,
- _ => false
- })
- .cloned()
- .collect()
-}
+fn valid_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 17]> {
+ if let Some(worm) = state.players[player_index].active_worm() {
-fn rollout_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 8]> {
- let worm = state.players[player_index].active_worm();
-
- let shoots = state.valid_shoot_commands(player_index, worm.position, worm.weapon_range);
-
- if !shoots.is_empty() {
- return shoots;
+ state.valid_shoot_commands(player_index, worm.position, worm.weapon_range)
+ .iter()
+ .chain(state.valid_move_commands(player_index).iter())
+ .cloned()
+ .collect()
+ } else {
+ [Command::DoNothing].iter().cloned().collect()
}
-
- // TODO: More directed destruction movements?
- state.valid_move_commands(player_index)
}