From b3d48c9924a2502ba7e93bafb0a8afcd096bec76 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sun, 11 Aug 2019 12:28:38 +0200 Subject: Replaced hashmaps with deterministic hashmaps I'm not worried about ddos attacks here, and this also has better perf for small keys. --- src/strategy/minimax.rs | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'src/strategy/minimax.rs') diff --git a/src/strategy/minimax.rs b/src/strategy/minimax.rs index b34d2f8..55abcec 100644 --- a/src/strategy/minimax.rs +++ b/src/strategy/minimax.rs @@ -2,8 +2,8 @@ use crate::command::{Action, Command}; use crate::constants::*; use crate::game::{GameBoard, SimulationOutcome}; +use fnv::FnvHashMap; use std::cmp; -use std::collections::HashMap; use std::ops::*; use time::{Duration, PreciseTime}; @@ -45,9 +45,9 @@ pub fn choose_move( ) -> Command { let mut root_node = Node { score_sum: ScoreSum::new(), - player_score_sums: [HashMap::new(), HashMap::new()], + player_score_sums: [FnvHashMap::default(), FnvHashMap::default()], unexplored: move_combos(state), - children: HashMap::new(), + children: FnvHashMap::default(), }; while start_time.to(PreciseTime::now()) < max_time { @@ -75,23 +75,33 @@ pub fn choose_move_with_normalized_perf( ) -> Command { let mut root_node = Node { score_sum: ScoreSum::new(), - player_score_sums: [HashMap::new(), HashMap::new()], + player_score_sums: [FnvHashMap::default(), FnvHashMap::default()], unexplored: move_combos(state), - children: HashMap::new(), + children: FnvHashMap::default(), }; for _ in 0..iterations { let _ = expand_tree(&mut root_node, state.clone(), config); } + eprintln!("Number of simulations: {}", root_node.score_sum.visit_count); + for (command, score_sum) in &root_node.player_score_sums[player_index] { + eprintln!( + "{} = {} ({} visits)", + command, + score_sum.avg().val, + score_sum.visit_count + ); + } + best_player_move(&root_node, player_index) } pub struct Node { score_sum: ScoreSum, - player_score_sums: [HashMap; 2], + player_score_sums: [FnvHashMap; 2], unexplored: Vec<[Command; 2]>, - children: HashMap<[Command; 2], Node>, + children: FnvHashMap<[Command; 2], Node>, } #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] @@ -177,9 +187,9 @@ fn expand_tree(node: &mut Node, mut state: GameBoard, config: &ScoreConfig) -> S let new_node = Node { score_sum: ScoreSum::with_initial(score), - player_score_sums: [HashMap::new(), HashMap::new()], + player_score_sums: [FnvHashMap::default(), FnvHashMap::default()], unexplored, - children: HashMap::new(), + children: FnvHashMap::default(), }; node.children.insert(commands, new_node); update(node, commands, score); @@ -243,6 +253,7 @@ fn score(state: &GameBoard, config: &ScoreConfig) -> Score { let snowballs = state.players[0].snowballs() as f32 - state.players[1].snowballs() as f32; let bombs = state.players[0].bombs() as f32 - state.players[1].bombs() as f32; + // TODO: None of these attributes give any signal early on. // TODO: Try adding new features here. Something about board position? Score { val: max_health * config.max_health_weight -- cgit v1.2.3