othello/src/repr/chains.rs
Simon Gardling 204ba85202
overhaul chain system
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`
2025-03-04 13:29:18 -05:00

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(),
)
}