brutus tweaks

master
Mark 2024-03-06 10:38:02 -08:00
parent 00270569db
commit 786e70fe9a
Signed by: Mark
GPG Key ID: C6D63995FE72FD80
1 changed files with 27 additions and 8 deletions

View File

@ -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::<Vec<_>>();
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)
}
}
}