pub mod board8 {
use crate::bits::Bits;
#[inline]
#[must_use]
pub fn transpose(x: u64) -> u64 {
let x = x.delta_swap(0x00AA_00AA_00AA_00AA, 7);
let x = x.delta_swap(0x0000_CCCC_0000_CCCC, 14);
x.delta_swap(0x0000_0000_F0F0_F0F0, 28)
}
#[inline]
#[must_use]
pub const fn flip_vertical(x: u64) -> u64 {
x.swap_bytes()
}
#[inline]
#[must_use]
pub fn mirror_horizontal(x: u64) -> u64 {
let x = x.delta_swap(0x5555_5555_5555_5555, 1);
let x = x.delta_swap(0x3333_3333_3333_3333, 2);
x.delta_swap(0x0F0F_0F0F_0F0F_0F0F, 4)
}
#[inline]
#[must_use]
pub fn rotate_90_cw(x: u64) -> u64 {
flip_vertical(transpose(x))
}
#[inline]
#[must_use]
pub fn rotate_90_ccw(x: u64) -> u64 {
transpose(flip_vertical(x))
}
#[inline]
#[must_use]
pub const fn rotate_180(x: u64) -> u64 {
x.reverse_bits()
}
const FILE_A: u64 = 0x0101_0101_0101_0101;
const FILE_H: u64 = FILE_A << 7;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Dir {
North,
South,
East,
West,
NorthEast,
NorthWest,
SouthEast,
SouthWest,
}
impl Dir {
pub const ALL: [Self; 8] = [
Self::North,
Self::South,
Self::East,
Self::West,
Self::NorthEast,
Self::NorthWest,
Self::SouthEast,
Self::SouthWest,
];
const fn step(self) -> (u32, bool, u64) {
match self {
Self::North => (8, true, u64::MAX),
Self::South => (8, false, u64::MAX),
Self::East => (1, true, !FILE_A),
Self::West => (1, false, !FILE_H),
Self::NorthEast => (9, true, !FILE_A),
Self::NorthWest => (7, true, !FILE_H),
Self::SouthEast => (7, false, !FILE_A),
Self::SouthWest => (9, false, !FILE_H),
}
}
#[inline]
#[must_use]
pub const fn shift(self, x: u64) -> u64 {
let (s, up, keep) = self.step();
(if up { x << s } else { x >> s }) & keep
}
}
#[inline]
#[must_use]
pub fn slide(pieces: u64, empty: u64, dir: Dir) -> u64 {
let (s, up, keep) = dir.step();
let propagate = empty & keep;
let filled = if up {
pieces.fill_up(propagate, s)
} else {
pieces.fill_down(propagate, s)
};
dir.shift(filled)
}
}