From e9a514409565c17a4a86e8c6402be8d7a4f399ae Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Wed, 22 May 2019 20:38:47 +0200 Subject: Added a strategy cache for reusing previous round data --- src/bin/benchmark.rs | 2 +- src/game.rs | 12 ++++++------ src/main.rs | 8 ++++++-- src/strategy.rs | 39 ++++++++++++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/bin/benchmark.rs b/src/bin/benchmark.rs index 794ba4e..20f74d0 100644 --- a/src/bin/benchmark.rs +++ b/src/bin/benchmark.rs @@ -13,7 +13,7 @@ fn main() { match json::read_state_from_json_file(&Path::new(&format!("./tests/example-state.json"))) { Ok(json_state) => { let new_board = game::GameBoard::new(json_state); - let _ = choose_move(&new_board, &start_time, max_time); + let _ = choose_move(&new_board, None, &start_time, max_time); }, Err(e) => { eprintln!("WARN: State file could not be parsed: {}", e); diff --git a/src/game.rs b/src/game.rs index e3fb5c0..fe54f40 100644 --- a/src/game.rs +++ b/src/game.rs @@ -80,7 +80,7 @@ impl GameBoard { } pub fn update(&mut self, json: json::State) { - for w in json.my_player.worms { + for w in &json.my_player.worms { if let Some(worm) = self.players[0].find_worm_mut(w.id) { worm.health = w.health; worm.position = Point2d::new(w.position.x, w.position.y); @@ -105,15 +105,15 @@ impl GameBoard { self.map.clear(Point2d::new(cell.x, cell.y)) } } - - self.round += 1; - debug_assert_eq!(json.current_round, self.round); - - // Remove dead worms and update active worm + for player in &mut self.players { player.clear_dead_worms(); player.next_active_worm(); } + debug_assert_eq!(json.active_worm_index().unwrap(), self.players[0].active_worm); + + self.round += 1; + debug_assert_eq!(json.current_round, self.round); } pub fn simulate(&mut self, moves: [Command; 2]) { diff --git a/src/main.rs b/src/main.rs index c24565a..b898fb5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use steam_powered_wyrm::game; fn main() { let max_time = Duration::milliseconds(950); let mut game_board = None; + let mut strategy_cache = None; for line in stdin().lock().lines() { let start_time = PreciseTime::now(); @@ -23,13 +24,16 @@ fn main() { match &mut game_board { None => { let new_board = game::GameBoard::new(json_state); - let command = choose_move(&new_board, &start_time, max_time); + let (command, cache) = choose_move(&new_board, strategy_cache, &start_time, max_time); + strategy_cache = Some(cache); game_board = Some(new_board); command }, Some(game_board) => { game_board.update(json_state); - choose_move(&game_board, &start_time, max_time) + let (command, cache) = choose_move(&game_board, strategy_cache, &start_time, max_time); + strategy_cache = Some(cache); + command } } }, diff --git a/src/strategy.rs b/src/strategy.rs index 8d2eea5..39bbe66 100644 --- a/src/strategy.rs +++ b/src/strategy.rs @@ -11,13 +11,30 @@ use rand; use rand::prelude::*; use arrayvec::ArrayVec; -pub fn choose_move(state: &GameBoard, start_time: &PreciseTime, max_time: Duration) -> Command { - let mut root_node = Node { - state: state.clone(), - score_sum: ScoreSum::new(), - player_score_sums: [HashMap::new(), HashMap::new()], - unexplored: mcts_move_combo(state), - children: HashMap::new(), +pub fn choose_move(state: &GameBoard, previous_root: Option, start_time: &PreciseTime, max_time: Duration) -> (Command, Node) { + let mut root_node = match previous_root { + None => Node { + state: state.clone(), + score_sum: ScoreSum::new(), + player_score_sums: [HashMap::new(), HashMap::new()], + unexplored: mcts_move_combo(state), + children: HashMap::new(), + }, + Some(mut node) => { + node.children.drain() + .map(|(_k, n)| n) + .find(|n| n.state == *state) + .unwrap_or_else(|| { + eprintln!("Previous round did not appear in the cache"); + Node { + state: state.clone(), + score_sum: ScoreSum::new(), + player_score_sums: [HashMap::new(), HashMap::new()], + unexplored: mcts_move_combo(state), + children: HashMap::new(), + } + }) + } }; while start_time.to(PreciseTime::now()) < max_time { @@ -34,10 +51,14 @@ pub fn choose_move(state: &GameBoard, start_time: &PreciseTime, max_time: Durati ); } - best_player_move(&root_node) + let chosen_command = best_player_move(&root_node); + + root_node.children.retain(|[c1, _], _| *c1 == chosen_command); + + (chosen_command, root_node) } -struct Node { +pub struct Node { state: GameBoard, score_sum: ScoreSum, player_score_sums: [HashMap; 2], -- cgit v1.2.3