From 90aa5bbecfaac59d2e58577a7015aad14ebd57a9 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sat, 1 Sep 2018 12:37:23 +0200 Subject: Optimized creation of heuristic weighting It's still 4 times slower, but it's probably decent to start filling in a heuristic. --- src/strategy/monte_carlo.rs | 142 ++++++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 52 deletions(-) (limited to 'src/strategy/monte_carlo.rs') diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs index af22cd7..4ebe90c 100644 --- a/src/strategy/monte_carlo.rs +++ b/src/strategy/monte_carlo.rs @@ -170,70 +170,108 @@ fn simulate_to_endstate(command_score: &mut CommandScore, state: &Bitwis #[cfg(feature = "heuristic-random")] fn random_move(player: &Player, _state: &BitwiseGameState, rng: &mut R) -> Command { lazy_static! { - static ref MOVES: Vec = { - let mut m = Vec::with_capacity(NUMBER_OF_POSSIBLE_MOVES); - m.push(Command::IronCurtain); + static ref MOVES: [Command; NUMBER_OF_POSSIBLE_MOVES] = { + let mut m = [Command::Nothing; NUMBER_OF_POSSIBLE_MOVES]; + m[1] = Command::IronCurtain; + let mut i = 2; for b in [BuildingType::Energy, BuildingType::Defence, BuildingType::Attack, BuildingType::Tesla].iter() { for p in 0..NUMBER_OF_MAP_POSITIONS as u8 { let point = Point::new_index(p); - m.push(Command::Build(point, *b)); + m[i] = Command::Build(point, *b); + i += 1; } } m }; } - - let mut cdf = Vec::with_capacity(NUMBER_OF_POSSIBLE_MOVES); + + let mut cdf = [0; NUMBER_OF_POSSIBLE_MOVES]; let mut cumulative_distribution: u32 = 0; - for m in MOVES.iter() { - let weight = match m { - Command::Nothing => { - 0 - }, - Command::Build(p, BuildingType::Energy) => { - if player.energy < ENERGY_PRICE || player.occupied & p.to_either_bitfield() != 0 { - 0 - } else { - //TODO: This needs to be more complex - 1 - } - }, - Command::Build(p, BuildingType::Defence) => { - if player.energy < DEFENCE_PRICE || player.occupied & p.to_either_bitfield() != 0 { - 0 - } else { - //TODO: This needs to be more complex - 1 - } - }, - Command::Build(p, BuildingType::Attack) => { - if player.energy < MISSILE_PRICE || player.occupied & p.to_either_bitfield() != 0 { - 0 - } else { - //TODO: This needs to be more complex - 1 - } - }, - Command::Build(p, BuildingType::Tesla) => { - if player.has_max_teslas() || player.energy < TESLA_PRICE || player.occupied & p.to_either_bitfield() != 0 { - 0 - } else { - //TODO: This needs to be more complex - 1 - } - }, - Command::IronCurtain => { - if player.can_build_iron_curtain() && player.energy >= IRON_CURTAIN_PRICE { - 20 - } else { - 0 - } - } + let mut i = 0; + + // Nothing + { + let weight = 0; + cumulative_distribution += weight; + cdf[i] = cumulative_distribution; + i += 1; + } + + // Iron Curtain + { + let weight = if player.can_build_iron_curtain() && player.energy >= IRON_CURTAIN_PRICE { + 20 + } else { + 0 }; - cumulative_distribution += weight; - cdf.push(cumulative_distribution); + cdf[i] = cumulative_distribution; + i += 1; + } + + // Energy + for p in 0..NUMBER_OF_MAP_POSITIONS as u8 { + let point = Point::new_index(p); + let weight = if player.energy < ENERGY_PRICE || player.occupied & point.to_either_bitfield() != 0 { + 0 + } else { + //TODO: This needs to be more complex + 1 + }; + + cumulative_distribution += weight; + cdf[i] = cumulative_distribution; + i += 1; } + + // Defence + for p in 0..NUMBER_OF_MAP_POSITIONS as u8 { + let point = Point::new_index(p); + let weight = if player.energy < DEFENCE_PRICE || player.occupied & point.to_either_bitfield() != 0 { + 0 + } else { + //TODO: This needs to be more complex + 1 + }; + + cumulative_distribution += weight; + cdf[i] = cumulative_distribution; + i += 1; + } + + // Attack + for p in 0..NUMBER_OF_MAP_POSITIONS as u8 { + let point = Point::new_index(p); + let weight = if player.energy < MISSILE_PRICE || player.occupied & point.to_either_bitfield() != 0 { + 0 + } else { + //TODO: This needs to be more complex + 1 + }; + + cumulative_distribution += weight; + cdf[i] = cumulative_distribution; + i += 1; + } + + // Tesla + let cant_tesla = player.has_max_teslas() || player.energy < TESLA_PRICE; + for p in 0..NUMBER_OF_MAP_POSITIONS as u8 { + let point = Point::new_index(p); + let weight = if cant_tesla || player.occupied & point.to_either_bitfield() != 0 { + 0 + } else { + //TODO: This needs to be more complex + 1 + }; + + cumulative_distribution += weight; + cdf[i] = cumulative_distribution; + i += 1; + } + + assert_eq!(MOVES.len(), i); + if cumulative_distribution == 0 { return Command::Nothing; } -- cgit v1.2.3