diff --git a/src/repr/board.rs b/src/repr/board.rs index a9074aa..f5917c5 100644 --- a/src/repr/board.rs +++ b/src/repr/board.rs @@ -1,106 +1,11 @@ use super::{ bitboard::BitBoard, - misc::get_index, - misc::{diag_raw, split_from}, + chains::{gen_adj_lookup, ChainCollection, PosMap}, piece::Piece, }; -use arrayvec::ArrayVec; use const_fn::const_fn; use lazy_static::lazy_static; -use std::{cmp::Ordering, collections::HashSet, fmt}; - -/// A chain of positions across the board -type Chain = ArrayVec<(usize, usize), { Board::BOARD_SIZE - 1 }>; - -/// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....) -type ChainCollection = ArrayVec; - -/// Map of all points on the board against some type T -/// Used to index like so: example[i][j] -/// with each coordinate -pub struct PosMap(ArrayVec); - -impl PosMap { - #[allow(clippy::new_without_default)] - pub fn new() -> Self { - Self(ArrayVec::from_iter( - (0..Board::BOARD_AREA).map(|_| Default::default()), - )) - } - - pub fn get(&self, row: usize, col: usize) -> &T { - let index = get_index(row, col); - - debug_assert!( - Board::BOARD_AREA + 1 >= index, - "index out of range, was: {}", - index - ); - - unsafe { self.0.get_unchecked(index) } - } - - pub fn set(&mut self, row: usize, col: usize, value: T) { - let index = get_index(row, col); - debug_assert!( - Board::BOARD_AREA + 1 >= index, - "index out of range, was: {}", - index - ); - - self.0[index] = value; - } -} - -/// Creates a lookup map for adjacencies and chains from each position on the board -fn gen_adj_lookup() -> PosMap { - PosMap( - Board::all_positions() - .map(|(i, j)| { - let (i_chain, j_chain) = ( - split_from(0..=Board::BOARD_SIZE - 1, i), - split_from(0..=Board::BOARD_SIZE - 1, j), - ); - - let chains: ChainCollection = ArrayVec::from_iter( - i_chain - .clone() - .into_iter() - .map(|range| range.map(move |i| (i, j))) - .map(Iterator::collect) - .chain( - j_chain - .clone() - .into_iter() - .map(|range| range.map(move |j| (i, j))) - .map(Iterator::collect), - ) - .chain(diag_raw(i_chain, j_chain).map(Iterator::collect)), - ); - - // make sure all chains are in the proper range so we can ignore bounds checking later - assert!( - chains - .iter() - .flatten() - .flat_map(|(i, j)| [i, j]) // flatten to just numbers - .all(|x| (0..Board::BOARD_SIZE).contains(x)), - "chains go out-of-bounds" - ); - - // SAFETY! ensure all nodes in all chains are unique across chains, ensures beavior in - // [`Board::propegate_from`] - let mut uniq = HashSet::new(); - assert!( - chains.iter().flatten().all(move |x| uniq.insert(x)), - "there are duplicate nodes in chain" - ); - - chains - }) - .collect(), - ) -} +use std::{cmp::Ordering, fmt}; #[derive(PartialEq, Eq, Copy, Clone, Debug)] pub enum Winner { diff --git a/src/repr/chains.rs b/src/repr/chains.rs new file mode 100644 index 0000000..ed67200 --- /dev/null +++ b/src/repr/chains.rs @@ -0,0 +1,99 @@ +use super::{ + misc::{diag_raw, get_index, split_from}, + Board, +}; +use arrayvec::ArrayVec; +use std::collections::HashSet; + +/// A chain of positions across the board +type Chain = ArrayVec<(usize, usize), { Board::BOARD_SIZE - 1 }>; + +/// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....) +pub type ChainCollection = ArrayVec; + +/// Map of all points on the board against some type T +/// Used to index like so: example[i][j] +/// with each coordinate +pub struct PosMap(ArrayVec); + +impl PosMap { + #[allow(clippy::new_without_default)] + pub fn new() -> Self { + Self(ArrayVec::from_iter( + (0..Board::BOARD_AREA).map(|_| Default::default()), + )) + } + + pub fn get(&self, row: usize, col: usize) -> &T { + let index = get_index(row, col); + + debug_assert!( + Board::BOARD_AREA + 1 >= index, + "index out of range, was: {}", + index + ); + + unsafe { self.0.get_unchecked(index) } + } + + pub fn set(&mut self, row: usize, col: usize, value: T) { + let index = get_index(row, col); + debug_assert!( + Board::BOARD_AREA + 1 >= index, + "index out of range, was: {}", + index + ); + + self.0[index] = value; + } +} + +/// Creates a lookup map for adjacencies and chains from each position on the board +pub fn gen_adj_lookup() -> PosMap { + PosMap( + Board::all_positions() + .map(|(i, j)| { + let (i_chain, j_chain) = ( + split_from(0..=Board::BOARD_SIZE - 1, i), + split_from(0..=Board::BOARD_SIZE - 1, j), + ); + + let chains: ChainCollection = ArrayVec::from_iter( + i_chain + .clone() + .into_iter() + .map(|range| range.map(move |i| (i, j))) + .map(Iterator::collect) + .chain( + j_chain + .clone() + .into_iter() + .map(|range| range.map(move |j| (i, j))) + .map(Iterator::collect), + ) + .chain(diag_raw(i_chain, j_chain).map(Iterator::collect)), + ); + + // make sure all chains are in the proper range so we can ignore bounds checking later + assert!( + chains + .iter() + .flatten() + .flat_map(|(i, j)| [i, j]) // flatten to just numbers + .all(|x| (0..Board::BOARD_SIZE).contains(x)), + "chains go out-of-bounds" + ); + + // SAFETY! ensure all nodes in all chains are unique across chains, ensures beavior in + // [`Board::propegate_from`] + let mut uniq = HashSet::new(); + assert!( + chains.iter().flatten().all(move |x| uniq.insert(x)), + "there are duplicate nodes in chain" + ); + + chains + }) + .collect(), + ) +} diff --git a/src/repr/mod.rs b/src/repr/mod.rs index 110720a..377a812 100644 --- a/src/repr/mod.rs +++ b/src/repr/mod.rs @@ -1,7 +1,9 @@ mod bitboard; mod board; +mod chains; mod misc; mod piece; -pub use board::{Board, PosMap, Winner}; +pub use board::{Board, Winner}; +pub use chains::PosMap; pub use piece::Piece;