From 786e70fe9adbe439be35356c919963df60e41b25 Mon Sep 17 00:00:00 2001 From: Mark Date: Wed, 6 Mar 2024 10:38:02 -0800 Subject: [PATCH] brutus tweaks --- src/agents/brutus.rs | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/agents/brutus.rs b/src/agents/brutus.rs index 74b143f..bac10d3 100644 --- a/src/agents/brutus.rs +++ b/src/agents/brutus.rs @@ -2,6 +2,7 @@ use std::{cmp::Ordering, iter}; use anyhow::Result; use itertools::Itertools; +use rand::{seq::SliceRandom, thread_rng}; use rayon::iter::{ParallelBridge, ParallelIterator}; use super::{Agent, Chase, MaximizerAgent, MinimizerAgent}; @@ -27,14 +28,20 @@ impl Brutus { .collect_vec(); if symbols.is_empty() { - return Chase::new(self.player).step_max(board); + return if minimize { + Chase::new(self.player).step_min(board) + } else { + Chase::new(self.player).step_max(board) + }; } // Number of free slots let n_free = board.get_board().iter().filter(|x| x.is_none()).count(); // Number of slots we need to fill with numbers - let n_fill = n_free - symbols.len(); + // Add one if we have two or fewer symbols available, so that we can + // account for one unused symbol while keeping a reasonable runtime + let n_fill = n_free - symbols.len() + if symbols.len() <= 2 { 1 } else { 0 }; let mut items = iter::repeat(None) .take(n_fill) @@ -70,7 +77,7 @@ impl Brutus { .collect::>(); if minimize { - // Sort from smallest midpoint to biggest midpoint + // Sort from smallest to biggest midpoint items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(Ordering::Equal)); } else { items.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(Ordering::Equal)); @@ -88,15 +95,27 @@ impl Brutus { let (t, _) = items.first().unwrap(); - for (i, s) in t.get_board().iter().enumerate() { - if let Some(s) = s { - if s.is_op() && board.get_board()[i].is_none() { - return Ok(PlayerAction { pos: i, symb: *s }); + let mut symbols = symbols.clone(); + symbols.shuffle(&mut thread_rng()); + + // Place a random unused symbol + for target_s in symbols { + for (i, s) in t.get_board().iter().enumerate() { + if let Some(s) = s { + if board.get_board()[i].is_none() && target_s == *s { + return Ok(PlayerAction { pos: i, symb: *s }); + } } } } - unreachable!() + // Final escape hatch, if we didn't decide to place any symbols + // (which is possible, since we add one to free_spots above!) + if minimize { + Chase::new(self.player).step_min(board) + } else { + Chase::new(self.player).step_max(board) + } } }