diff --git a/Cargo.lock b/Cargo.lock index 698d7af..d7404b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,7 @@ dependencies = [ name = "othello" version = "0.1.0" dependencies = [ + "either", "num", "rand", "rayon", diff --git a/Cargo.toml b/Cargo.toml index b00ab1d..a29ee79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" debug = true [dependencies] +either = "1.13.0" num = "0.4" rand = "0.9" rayon = "1.10" diff --git a/src/board.rs b/src/board.rs index 1ce912f..ee96cc4 100644 --- a/src/board.rs +++ b/src/board.rs @@ -151,7 +151,7 @@ impl Board { chains.extend(j_chain.map(|range| range.into_iter().map(|j| (i, j)).collect())); // handle diagonals - chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1)); + chains.extend(diag(i, j, 0, 0, BOARD_SIZE - 1, BOARD_SIZE - 1).map(Iterator::collect)); let mut fill: Vec<(usize, usize)> = Vec::with_capacity(chains.iter().map(Vec::len).sum()); diff --git a/src/complexagent.rs b/src/complexagent.rs index 9803a98..8fe81e2 100644 --- a/src/complexagent.rs +++ b/src/complexagent.rs @@ -248,7 +248,7 @@ pub struct ComplexAgent { impl ComplexAgent { pub fn new(color: Piece) -> Self { - const MAX_DEPTH: usize = 6; + const MAX_DEPTH: usize = 7; Self { color, future_moves: FutureMoves::new(color, MAX_DEPTH), diff --git a/src/misc.rs b/src/misc.rs index 3f6cbe7..147efff 100644 --- a/src/misc.rs +++ b/src/misc.rs @@ -1,31 +1,38 @@ +use either::Either; use std::{iter::Rev, ops::RangeInclusive}; -pub fn split_from(min: T, max: T, x: T) -> [Vec; 2] +pub fn split_from(min: T, max: T, x: T) -> [impl Iterator + Clone; 2] where T: num::Integer + Copy, RangeInclusive: Iterator + DoubleEndedIterator, Rev>: Iterator, { - // check that x is in range - if min > x || x > max { - return [const { Vec::new() }; 2]; - } + let in_range = (x >= min) && (x <= max); + // RangeInclusive (1..=0), has 0 elements + let base = Either::Right(T::one()..=T::zero()); [ - if x > min + T::one() { - (min..=(x - T::one())).rev().collect() + if in_range && x > min + T::one() { + Either::Left((min..=(x - T::one())).rev()) } else { - Vec::new() + base.clone() }, - if x + T::one() < max { - ((x + T::one())..=max).collect() + if in_range && x + T::one() < max { + Either::Right((x + T::one())..=max) } else { - Vec::new() + base }, ] } -pub fn diag(i: T, j: T, min_i: T, min_j: T, max_i: T, max_j: T) -> [Vec<(T, T)>; 4] +pub fn diag( + i: T, + j: T, + min_i: T, + min_j: T, + max_i: T, + max_j: T, +) -> [impl Iterator; 4] where T: num::Integer + Copy, RangeInclusive: Iterator + DoubleEndedIterator, @@ -34,13 +41,7 @@ where let i_chains = split_from(min_i, max_i, i); let j_chains = split_from(min_j, max_j, j); - [(0, 0), (1, 1), (1, 0), (0, 1)].map(|(a, b)| { - i_chains[a] - .iter() - .cloned() - .zip(j_chains[b].clone()) - .collect() - }) + [(0, 0), (1, 1), (1, 0), (0, 1)].map(|(a, b)| i_chains[a].clone().zip(j_chains[b].clone())) } #[cfg(test)] @@ -49,15 +50,24 @@ mod test { #[test] fn split_test() { - assert_eq!(split_from(0, 6, 2), [vec![1, 0], vec![3, 4, 5, 6]]); + assert_eq!( + split_from(0, 6, 2).map(Iterator::collect::>), + [vec![1, 0], vec![3, 4, 5, 6]] + ); - assert_eq!(split_from(0, 6, 0), [vec![], vec![1, 2, 3, 4, 5, 6]]); + assert_eq!( + split_from(0, 6, 0).map(Iterator::collect::>), + [vec![], vec![1, 2, 3, 4, 5, 6]] + ); - assert_eq!(split_from(0, 6, 6), [vec![5, 4, 3, 2, 1, 0], vec![]]); + assert_eq!( + split_from(0, 6, 6).map(Iterator::collect::>), + [vec![5, 4, 3, 2, 1, 0], vec![]] + ); // test out-of-bounds and also generics assert_eq!( - split_from::(-1i16, 4i16, 10i16), + split_from::(-1i16, 4i16, 10i16).map(Iterator::collect::>), [const { Vec::new() }; 2] ); } @@ -65,7 +75,7 @@ mod test { #[test] fn diag_test() { assert_eq!( - diag(2, 3, 0, 0, 7, 7), + diag(2, 3, 0, 0, 7, 7).map(Iterator::collect::>), [ vec![(1, 2), (0, 1)], vec![(3, 4), (4, 5), (5, 6), (6, 7)],