use crate::board::*; use std::iter::ExactSizeIterator; use std::iter::FusedIterator; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Bitboard(pub(crate) u64); impl Bitboard { #[inline] pub fn new() -> Self { Self(0) } #[inline] pub fn is_empty(&self) -> bool { self.0 == 0 } #[inline] pub fn first(&self) -> Option { let mask = self.0; match mask { 0 => None, _ => Some(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }), } } #[inline] pub fn pop(&mut self) -> Option { let Self(ref mut mask) = self; let square = match mask { 0 => None, _ => Some(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }), }; *mask &= mask.wrapping_sub(1); square } #[inline] pub fn insert(&mut self, square: Square) { self.0 |= 1 << square as u8; } #[inline] pub fn trans(&self, direction: Direction) -> Self { match direction { Direction::North => Self(self.0 << 8), Direction::NorthEast => Self(self.0 << 9) & !File::A.bitboard(), Direction::East => Self(self.0 << 1) & !File::A.bitboard(), Direction::SouthEast => Self(self.0 >> 7) & !File::A.bitboard(), Direction::South => Self(self.0 >> 8), Direction::SouthWest => Self(self.0 >> 9) & !File::H.bitboard(), Direction::West => Self(self.0 >> 1) & !File::H.bitboard(), Direction::NorthWest => Self(self.0 << 7) & !File::H.bitboard(), } } #[inline] pub fn contains(&self, square: Square) -> bool { self.0 & (1 << square as u8) != 0 } #[inline] pub fn mirror(self) -> Bitboard { let [a, b, c, d, e, f, g, h] = self.0.to_le_bytes(); Self(u64::from_le_bytes([h, g, f, e, d, c, b, a])) } } impl std::ops::BitOr for Bitboard { type Output = Self; #[inline] fn bitor(self, rhs: Self) -> Self::Output { Self(self.0 | rhs.0) } } impl std::ops::BitAnd for Bitboard { type Output = Self; #[inline] fn bitand(self, rhs: Self) -> Self::Output { Self(self.0 & rhs.0) } } impl std::ops::BitXor for Bitboard { type Output = Self; #[inline] fn bitxor(self, rhs: Self) -> Self::Output { Self(self.0 ^ rhs.0) } } impl std::ops::BitOrAssign for Bitboard { #[inline] fn bitor_assign(&mut self, rhs: Self) { self.0 |= rhs.0; } } impl std::ops::BitAndAssign for Bitboard { #[inline] fn bitand_assign(&mut self, rhs: Self) { self.0 &= rhs.0; } } impl std::ops::BitXorAssign for Bitboard { #[inline] fn bitxor_assign(&mut self, rhs: Self) { self.0 ^= rhs.0; } } impl std::ops::Not for Bitboard { type Output = Self; #[inline] fn not(self) -> Self::Output { Self(!self.0) } } impl Iterator for Bitboard { type Item = Square; #[inline] fn next(&mut self) -> Option { self.pop() } #[inline] fn size_hint(&self) -> (usize, Option) { let len = self.len(); (len, Some(len)) } #[inline] fn for_each(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { let mut mask = self.0; while mask != 0 { f(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }); mask &= mask.wrapping_sub(1); } } #[inline] fn fold(self, init: B, mut f: F) -> B where Self: Sized, F: FnMut(B, Self::Item) -> B, { let mut mask = self.0; let mut acc = init; while mask != 0 { acc = f(acc, unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }); mask &= mask.wrapping_sub(1); } acc } } impl FusedIterator for Bitboard {} impl ExactSizeIterator for Bitboard { #[inline] fn len(&self) -> usize { self.0.count_ones() as usize } } pub(crate) trait BitboardIterExt { fn reduce_or(self) -> Bitboard; } impl BitboardIterExt for T where T: Iterator, { #[inline] fn reduce_or(self) -> Bitboard { self.fold(Bitboard(0), |a, b| a | b) } }