board optimizations
This commit is contained in:
parent
7863e0324f
commit
16eb6a1259
@ -79,18 +79,6 @@ impl BitBoard {
|
||||
self.south(n).west(n)
|
||||
}
|
||||
|
||||
/// All direction methods
|
||||
pub const DIRECTIONS: [fn(&Self, usize) -> Self; 8] = [
|
||||
BitBoard::east,
|
||||
BitBoard::west,
|
||||
BitBoard::north,
|
||||
BitBoard::south,
|
||||
BitBoard::northeast,
|
||||
BitBoard::northwest,
|
||||
BitBoard::southeast,
|
||||
BitBoard::southwest,
|
||||
];
|
||||
|
||||
// Mask for a specific column (e.g., col_mask(7) = 0x8080808080808080)
|
||||
const fn col_mask(col: CoordAxis) -> Self {
|
||||
let mut mask = 0;
|
||||
@ -110,12 +98,16 @@ impl BitBoard {
|
||||
pub const fn intersects(self, other: Self) -> bool {
|
||||
(self.0 & other.0) > 0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Not for BitBoard {
|
||||
type Output = BitBoard;
|
||||
pub const fn bitor_assign(&mut self, other: Self) {
|
||||
self.0 = self.0 | other.0;
|
||||
}
|
||||
|
||||
fn not(self) -> Self::Output {
|
||||
pub const fn bitand_assign(&mut self, other: Self) {
|
||||
self.0 = self.0 & other.0;
|
||||
}
|
||||
|
||||
pub const fn not(self) -> Self {
|
||||
Self(!self.0)
|
||||
}
|
||||
}
|
||||
@ -136,18 +128,6 @@ impl std::ops::BitOr for BitBoard {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitAndAssign for BitBoard {
|
||||
fn bitand_assign(&mut self, rhs: Self) {
|
||||
*self = *self & rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::BitOrAssign for BitBoard {
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
*self = *self | rhs;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
@ -227,22 +227,26 @@ impl Board {
|
||||
|
||||
/// Return a modified [`Board`] with the piece placed at a position
|
||||
/// Returns None if the move was invalid
|
||||
pub fn what_if(&self, coord: CoordPair, piece: Piece) -> Result<Self, &'static str> {
|
||||
pub const fn what_if(&self, coord: CoordPair, piece: Piece) -> Option<Self> {
|
||||
// extract check here to avoid copy
|
||||
if self.get(coord).is_some() {
|
||||
return Err("position is occupied");
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut self_copy = *self;
|
||||
self_copy.place(coord, piece).map(|_| self_copy)
|
||||
if let Ok(_) = self_copy.place(coord, piece) {
|
||||
Some(self_copy)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a bool which represents whether or not a move would propegate and be valid
|
||||
pub fn would_prop(&self, coord: CoordPair, piece: Piece) -> bool {
|
||||
pub const fn would_prop(&self, coord: CoordPair, piece: Piece) -> bool {
|
||||
self.get(coord).is_none() && !self.propegate_from_dry(coord, piece).is_empty()
|
||||
}
|
||||
|
||||
pub fn place(&mut self, coord: CoordPair, piece: Piece) -> Result<(), &'static str> {
|
||||
pub const fn place(&mut self, coord: CoordPair, piece: Piece) -> Result<(), &'static str> {
|
||||
if self.get(coord).is_some() {
|
||||
return Err("position is occupied");
|
||||
}
|
||||
@ -257,7 +261,7 @@ impl Board {
|
||||
|
||||
/// Propegate the board and captures starting from a specific position
|
||||
/// returns true if flips occurred
|
||||
fn propegate_from(&mut self, coord: CoordPair, starting_color: Piece) -> bool {
|
||||
const fn propegate_from(&mut self, coord: CoordPair, starting_color: Piece) -> bool {
|
||||
let flip_mask = self.propegate_from_dry(coord, starting_color);
|
||||
let did_flip = !flip_mask.is_empty();
|
||||
|
||||
@ -267,40 +271,52 @@ impl Board {
|
||||
did_flip
|
||||
}
|
||||
|
||||
fn apply_flip_mask(&mut self, color: Piece, flip_mask: BitBoard) {
|
||||
const fn apply_flip_mask(&mut self, color: Piece, flip_mask: BitBoard) {
|
||||
// did some investigation, seems using xor actually decreases
|
||||
// performance over the branchfull impl? 3.2-3.5% slower
|
||||
get_board!(mut self, color).bitor_assign(flip_mask);
|
||||
get_board!(mut self, color.flip()).bitand_assign(!flip_mask);
|
||||
get_board!(mut self, color.flip()).bitand_assign(flip_mask.not());
|
||||
}
|
||||
|
||||
/// Propegate piece captures originating from (i, j)
|
||||
/// DO NOT USE THIS ALONE, this should be called as a part of
|
||||
/// [`Board::place`] or [`Board::place_and_prop_unchecked`]
|
||||
fn propegate_from_dry(&self, coords: CoordPair, starting_color: Piece) -> BitBoard {
|
||||
const fn propegate_from_dry(&self, coords: CoordPair, starting_color: Piece) -> BitBoard {
|
||||
let player_board = get_board!(self, starting_color);
|
||||
let opponent_board = get_board!(self, starting_color.flip());
|
||||
|
||||
let mut flip_mask = BitBoard::new();
|
||||
let seed = BitBoard::from_coord(coords);
|
||||
|
||||
for dir in BitBoard::DIRECTIONS {
|
||||
let mut current = seed;
|
||||
let mut temp_flips = BitBoard::new();
|
||||
macro_rules! apply_dir {
|
||||
($base:expr, $sum_mask:expr, $dir:expr) => {
|
||||
let mut current = $base;
|
||||
let mut temp_flips = BitBoard::new();
|
||||
|
||||
// Expand in direction until edge or non-opponent piece
|
||||
loop {
|
||||
current = dir(¤t, 1);
|
||||
if current.is_empty() || !current.intersects(*opponent_board) {
|
||||
break;
|
||||
// Expand in direction until edge or non-opponent piece
|
||||
loop {
|
||||
current = $dir(¤t, 1);
|
||||
if current.is_empty() || !current.intersects(*opponent_board) {
|
||||
break;
|
||||
}
|
||||
temp_flips.bitor_assign(current);
|
||||
}
|
||||
temp_flips |= current;
|
||||
}
|
||||
|
||||
// If terminated on a player piece, keep the flips
|
||||
if current.intersects(*player_board) {
|
||||
flip_mask |= temp_flips;
|
||||
}
|
||||
// If terminated on a player piece, keep the flips
|
||||
if current.intersects(*player_board) {
|
||||
$sum_mask.bitor_assign(temp_flips);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
apply_dir!(seed, flip_mask, BitBoard::east);
|
||||
apply_dir!(seed, flip_mask, BitBoard::west);
|
||||
apply_dir!(seed, flip_mask, BitBoard::north);
|
||||
apply_dir!(seed, flip_mask, BitBoard::south);
|
||||
apply_dir!(seed, flip_mask, BitBoard::northeast);
|
||||
apply_dir!(seed, flip_mask, BitBoard::northwest);
|
||||
apply_dir!(seed, flip_mask, BitBoard::southeast);
|
||||
apply_dir!(seed, flip_mask, BitBoard::southwest);
|
||||
flip_mask
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user