This made the code so fast, that the `board` benchmark became completely useless. So that benchmark was removed. Overall, we're looking at a futher 20% performance increase in `future_moves`
67 lines
2.6 KiB
Rust
67 lines
2.6 KiB
Rust
use super::{
|
|
misc::{diag_raw, split_from},
|
|
Board, CoordPair,
|
|
};
|
|
use arrayvec::ArrayVec;
|
|
use std::collections::HashSet;
|
|
|
|
/// A chain of positions across the board
|
|
type Chain = ArrayVec<CoordPair, { (Board::BOARD_SIZE - 1) as usize }>;
|
|
|
|
/// A collection of chains (up vert, down vert, left horiz, right horiz, diagonals....)
|
|
pub type ChainCollection = ArrayVec<Chain, 8>;
|
|
|
|
/// Creates a lookup map for adjacencies and chains from each position on the board
|
|
pub fn gen_adj_lookup() -> PosMap<ChainCollection> {
|
|
PosMap(
|
|
Board::all_positions()
|
|
.map(|coord| {
|
|
let (i, j) = coord.into();
|
|
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))
|
|
.filter(|x: &Vec<(u8, u8)>| !x.is_empty()) // PERF! filter out empty chains +~5% perf boost (in [`Board::place`])
|
|
.map(|x: Vec<(u8, u8)>| x.into_iter().map(|x| x.into()).collect()),
|
|
);
|
|
|
|
// make sure all chains are in the proper range so we can ignore bounds checking later
|
|
assert!(
|
|
chains
|
|
.iter()
|
|
.flatten()
|
|
.map(|&x| x.into())
|
|
.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(),
|
|
)
|
|
}
|