general code improvements

This commit is contained in:
Simon Gardling 2025-02-10 14:21:06 -05:00
parent cb5f9d075d
commit bd5cc2ea52
Signed by: titaniumtown
GPG Key ID: 9AB28AC10ECE533D
3 changed files with 43 additions and 60 deletions

View File

@ -68,12 +68,10 @@ impl Board {
self
}
pub fn possible_moves(&self, color: Piece) -> Box<dyn Iterator<Item = (usize, usize)> + '_> {
Box::new(
(0..BOARD_SIZE)
.flat_map(|i| (0..BOARD_SIZE).map(move |j| (i, j)))
.filter(move |(i, j)| self.would_prop(*i, *j, color)),
)
pub fn possible_moves(&self, color: Piece) -> impl Iterator<Item = (usize, usize)> + use<'_> {
(0..BOARD_SIZE)
.flat_map(|i| (0..BOARD_SIZE).map(move |j| (i, j)))
.filter(move |(i, j)| self.would_prop(*i, *j, color))
}
/// Returns a mutable reference to a place on the [`Board`]
@ -137,8 +135,8 @@ impl Board {
/// DO NOT USE THIS ALONE, this should be called as a part of
/// [`Board::place`] or [`Board::place_and_prop_unchecked`]
// TODO! this function is responsible for approx 64% of the time spent computing moves in `ComplexAgent`
// IDEAS: early-exit from each chain so we don't have to call `diag` (which allocs a lot and uses a lot of cycles)
// NOTE! got it down to 24.86% (61.1% decrease) with allocator optimizations
// IDEAS: early-exit from each chain so we don't have to call `diag` (which allocs a lot and uses a lot of cycles)
fn propegate_from_dry(&self, i: usize, j: usize, starting_color: Piece) -> Vec<(usize, usize)> {
// Create all chains from the piece being propegated from in `i` and `j` coordinates
let (i_chain, j_chain) = (

View File

@ -104,28 +104,27 @@ impl FutureMoves {
board: &Board,
color: Piece,
) -> Vec<usize> {
let children: Vec<_> = board
.possible_moves(color)
.flat_map(|(i, j)| board.what_if(i, j, color).map(|x| (i, j, x)))
.map(|(i, j, (new_board, captured))| {
let winner = new_board.game_winner(color);
Move {
i,
j,
captured,
color,
board: new_board,
winner,
parent,
children: Vec::new(),
value: 0,
}
})
.collect();
let parent_idx = parent;
let start_idx = self.arena.len();
self.arena.extend(children);
self.arena.extend(
board
.possible_moves(color)
.flat_map(|(i, j)| board.what_if(i, j, color).map(|x| (i, j, x)))
.map(|(i, j, (new_board, captured))| {
let winner = new_board.game_winner(color);
Move {
i,
j,
captured,
color,
board: new_board,
winner,
parent,
children: Vec::new(),
value: 0,
}
}),
);
let new_indices: Vec<usize> = (start_idx..self.arena.len()).collect();
if let Some(parent_idx) = parent_idx {
@ -249,7 +248,7 @@ pub struct ComplexAgent {
impl ComplexAgent {
pub fn new(color: Piece) -> Self {
const MAX_DEPTH: usize = 7;
const MAX_DEPTH: usize = 6;
Self {
color,
future_moves: FutureMoves::new(color, MAX_DEPTH),

View File

@ -6,22 +6,23 @@ where
RangeInclusive<T>: Iterator<Item = T> + DoubleEndedIterator,
Rev<RangeInclusive<T>>: Iterator<Item = T>,
{
let mut output = [const { Vec::new() }; 2];
// check that x is in range
if min > x || x > max {
return output;
return [const { Vec::new() }; 2];
}
if x > min + T::one() {
let x_lower = x - T::one();
output[0] = (min..=x_lower).rev().collect();
}
if x + T::one() < max {
output[1] = ((x + T::one())..=max).collect();
}
output
[
if x > min + T::one() {
(min..=(x - T::one())).rev().collect()
} else {
Vec::new()
},
if x + T::one() < max {
((x + T::one())..=max).collect()
} else {
Vec::new()
},
]
}
pub fn diag<T>(i: T, j: T, min_i: T, min_j: T, max_i: T, max_j: T) -> [Vec<(T, T)>; 4]
@ -33,28 +34,13 @@ where
let i_chains = split_from(min_i, max_i, i);
let j_chains = split_from(min_j, max_j, j);
[
i_chains[0]
[(0, 0), (1, 1), (1, 0), (0, 1)].map(|(a, b)| {
i_chains[a]
.iter()
.cloned()
.zip(j_chains[0].clone())
.collect(),
i_chains[1]
.iter()
.cloned()
.zip(j_chains[1].clone())
.collect(),
i_chains[1]
.iter()
.cloned()
.zip(j_chains[0].clone())
.collect(),
i_chains[0]
.iter()
.cloned()
.zip(j_chains[1].clone())
.collect(),
]
.zip(j_chains[b].clone())
.collect()
})
}
#[cfg(test)]