brutus tweaks
This commit is contained in:
		| @ -2,6 +2,7 @@ use std::{cmp::Ordering, iter}; | |||||||
|  |  | ||||||
| use anyhow::Result; | use anyhow::Result; | ||||||
| use itertools::Itertools; | use itertools::Itertools; | ||||||
|  | use rand::{seq::SliceRandom, thread_rng}; | ||||||
| use rayon::iter::{ParallelBridge, ParallelIterator}; | use rayon::iter::{ParallelBridge, ParallelIterator}; | ||||||
|  |  | ||||||
| use super::{Agent, Chase, MaximizerAgent, MinimizerAgent}; | use super::{Agent, Chase, MaximizerAgent, MinimizerAgent}; | ||||||
| @ -27,14 +28,20 @@ impl Brutus { | |||||||
| 			.collect_vec(); | 			.collect_vec(); | ||||||
|  |  | ||||||
| 		if symbols.is_empty() { | 		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 | 		// Number of free slots | ||||||
| 		let n_free = board.get_board().iter().filter(|x| x.is_none()).count(); | 		let n_free = board.get_board().iter().filter(|x| x.is_none()).count(); | ||||||
|  |  | ||||||
| 		// Number of slots we need to fill with numbers | 		// 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) | 		let mut items = iter::repeat(None) | ||||||
| 			.take(n_fill) | 			.take(n_fill) | ||||||
| @ -70,7 +77,7 @@ impl Brutus { | |||||||
| 			.collect::<Vec<_>>(); | 			.collect::<Vec<_>>(); | ||||||
|  |  | ||||||
| 		if minimize { | 		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)); | 			items.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(Ordering::Equal)); | ||||||
| 		} else { | 		} else { | ||||||
| 			items.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(Ordering::Equal)); | 			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(); | 		let (t, _) = items.first().unwrap(); | ||||||
|  |  | ||||||
| 		for (i, s) in t.get_board().iter().enumerate() { | 		let mut symbols = symbols.clone(); | ||||||
| 			if let Some(s) = s { | 		symbols.shuffle(&mut thread_rng()); | ||||||
| 				if s.is_op() && board.get_board()[i].is_none() { |  | ||||||
| 					return Ok(PlayerAction { pos: i, symb: *s }); | 		// 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) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user