summaryrefslogtreecommitdiff
path: root/src/strategy.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/strategy.rs')
-rw-r--r--src/strategy.rs35
1 files changed, 23 insertions, 12 deletions
diff --git a/src/strategy.rs b/src/strategy.rs
index 4c86dfd..46cb2cd 100644
--- a/src/strategy.rs
+++ b/src/strategy.rs
@@ -131,8 +131,11 @@ fn mcts(node: &mut Node) -> Score {
let mut new_state = node.state.clone();
new_state.simulate(commands);
let score = rollout(&new_state);
- // TODO: This could overshoot, trying to estimate from concluded game
- let unexplored = mcts_move_combo(&new_state);
+ let unexplored = if new_state.outcome == SimulationOutcome::Continue {
+ mcts_move_combo(&new_state)
+ } else {
+ Vec::new()
+ };
let new_node = Node {
state: new_state,
@@ -166,7 +169,7 @@ fn mcts_move_combo(state: &GameBoard) -> Vec<[Command; 2]> {
let mut result = Vec::with_capacity(player_moves.len() * opponent_moves.len());
for p in &player_moves {
for o in &opponent_moves {
- result.push([p.clone(), o.clone()]);
+ result.push([*p, *o]);
}
}
@@ -178,7 +181,7 @@ fn best_player_move(node: &Node) -> Command {
.iter()
.max_by_key(|(_command, score_sum)| score_sum.avg())
.map(|(command, _score_sum)| *command)
- .unwrap_or(Command::new(Action::DoNothing))
+ .unwrap_or_else(|| Command::new(Action::DoNothing))
}
fn score(state: &GameBoard) -> Score {
@@ -202,11 +205,11 @@ fn rollout(state: &GameBoard) -> Score {
player_moves
.choose(&mut rng)
.cloned()
- .unwrap_or(Command::new(Action::DoNothing)),
+ .unwrap_or_else(|| Command::new(Action::DoNothing)),
opponent_moves
.choose(&mut rng)
.cloned()
- .unwrap_or(Command::new(Action::DoNothing)),
+ .unwrap_or_else(|| Command::new(Action::DoNothing)),
]);
}
@@ -228,29 +231,30 @@ fn choose_one_existing(node: &Node, player_index: usize) -> Command {
as i32
})
.map(|(command, _score_sum)| *command)
- .unwrap_or(Command::new(Action::DoNothing))
+ .unwrap_or_else(|| Command::new(Action::DoNothing))
}
fn update(node: &mut Node, commands: [Command; 2], score: Score) {
*node.player_score_sums[0]
.entry(commands[0])
- .or_insert(ScoreSum::new()) += score;
+ .or_insert_with(ScoreSum::new) += score;
*node.player_score_sums[1]
.entry(commands[1])
- .or_insert(ScoreSum::new()) += score;
+ .or_insert_with(ScoreSum::new) += score;
node.score_sum += score;
}
fn rollout_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 8]> {
+ // TODO: Have this return one move, chosen randomly?
+ // TODO: Allow new select / bomb moves
if let Some(worm) = state.players[player_index].active_worm() {
- let shoots = state.valid_shoot_commands(player_index, worm.position, worm.weapon_range);
+ let shoots = state.sensible_shoot_commands(player_index, worm.position, worm.weapon_range);
if !shoots.is_empty() {
return shoots;
}
- // TODO: More directed destruction movements?
state.valid_move_commands(player_index)
} else {
[Command::new(Action::DoNothing)].into_iter().cloned().collect()
@@ -258,11 +262,18 @@ fn rollout_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 8
}
fn valid_moves(state: &GameBoard, player_index: usize) -> ArrayVec<[Command; 17]> {
+ // TODO: Move / Dig, Shoot, Bomb, Select to another worm and repeat
+ // 24 move/digs
+ // 24 shoots
+ // 109 bombs (sub those out of range)
+ // 1 nothing
+ // TOTAL: 158 possible moves
if let Some(worm) = state.players[player_index].active_worm() {
- state.valid_shoot_commands(player_index, worm.position, worm.weapon_range)
+ state.valid_shoot_commands()
.iter()
.chain(state.valid_move_commands(player_index).iter())
+ .chain(state.valid_bomb_commands(player_index).iter())
.cloned()
.collect()
} else {