1
0
Fork 0

new constructor for squares

This commit is contained in:
Paul-Nicolas Madelaine 2025-11-03 16:20:47 +01:00
parent c28c40186e
commit 263bb0ddb6
7 changed files with 59 additions and 44 deletions

View file

@ -22,7 +22,7 @@ impl Bitboard {
let mask = self.0;
match mask {
0 => None,
_ => Some(unsafe { Square::transmute(mask.trailing_zeros() as u8) }),
_ => Some(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }),
}
}
@ -31,9 +31,9 @@ impl Bitboard {
let mask = self.0;
match mask {
0 => None,
_ => {
Some(unsafe { Square::transmute(63_u8.unchecked_sub(mask.leading_zeros() as u8)) })
}
_ => Some(unsafe {
Square::new_unchecked(63_u8.unchecked_sub(mask.leading_zeros() as u8))
}),
}
}
@ -42,7 +42,7 @@ impl Bitboard {
let Self(ref mut mask) = self;
let square = match mask {
0 => None,
_ => Some(unsafe { Square::transmute(mask.trailing_zeros() as u8) }),
_ => Some(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) }),
};
*mask &= mask.wrapping_sub(1);
square
@ -145,7 +145,7 @@ impl Iterator for Bitboard {
{
let mut mask = self.0;
while mask != 0 {
f(unsafe { Square::transmute(mask.trailing_zeros() as u8) });
f(unsafe { Square::new_unchecked(mask.trailing_zeros() as u8) });
mask &= mask.wrapping_sub(1);
}
}
@ -159,7 +159,7 @@ impl Iterator for Bitboard {
let mut acc = init;
while mask != 0 {
acc = f(acc, unsafe {
Square::transmute(mask.trailing_zeros() as u8)
Square::new_unchecked(mask.trailing_zeros() as u8)
});
mask &= mask.wrapping_sub(1);
}

View file

@ -264,17 +264,26 @@ impl Square {
]
}
pub(crate) const fn from_index(index: u8) -> Option<Self> {
pub const fn new(index: u8) -> Option<Self> {
if index < 64 {
Some(unsafe { Self::transmute(index) })
Some(unsafe { Self::new_unchecked(index) })
} else {
None
}
}
/// ## Safety
///
/// The caller must ensure that `index < 64`.
#[inline]
pub fn new(file: File, rank: Rank) -> Self {
unsafe { Self::transmute(((rank as u8) << 3) | file as u8) }
pub const unsafe fn new_unchecked(index: u8) -> Self {
debug_assert!(index < 64);
std::mem::transmute(index)
}
#[inline]
pub fn from_coords(file: File, rank: Rank) -> Self {
unsafe { Self::new_unchecked(((rank as u8) << 3) | file as u8) }
}
#[inline]
@ -290,7 +299,7 @@ impl Square {
#[inline]
pub fn mirror(self) -> Self {
let sq = self as u8;
unsafe { Self::transmute(sq & 0b000111 | (!sq & 0b111000)) }
unsafe { Self::new_unchecked(sq & 0b000111 | (!sq & 0b111000)) }
}
#[inline]
@ -324,7 +333,10 @@ impl Square {
#[inline]
pub(crate) fn from_ascii(s: &[u8; 2]) -> Option<Self> {
let [f, r] = *s;
Some(Self::new(File::from_ascii(f)?, Rank::from_ascii(r)?))
Some(Self::from_coords(
File::from_ascii(f)?,
Rank::from_ascii(r)?,
))
}
#[inline]
@ -342,7 +354,7 @@ impl Square {
debug_assert!(self.check_trans(direction));
let i = self as u8;
unsafe {
Self::transmute(match direction {
Self::new_unchecked(match direction {
Direction::East => i.unchecked_add(1),
Direction::NorthEast => i.unchecked_add(9),
Direction::North => i.unchecked_add(8),
@ -371,12 +383,6 @@ impl Square {
Direction::West => file > 0,
}
}
#[inline]
pub(crate) const unsafe fn transmute(value: u8) -> Self {
debug_assert!(value < 64);
std::mem::transmute(value)
}
}
impl std::fmt::Display for Square {
@ -434,7 +440,7 @@ impl OptionSquare {
unsafe {
match self {
Self::None => None,
_ => Some(Square::transmute(self as u8)),
_ => Some(Square::new_unchecked(self as u8)),
}
}
}

View file

@ -36,7 +36,7 @@ macro_rules! by_square {
let mut $sq: u8 = 0;
while $sq < 64 {
res[$sq as usize] = {
let $sq = Square::from_index($sq).unwrap();
let $sq = Square::new($sq).unwrap();
$e
};
$sq += 1;

View file

@ -420,14 +420,14 @@ impl Position {
SanInner::Castle(CastlingSide::Short) => (
Role::King,
Role::King,
Square::new(File::E, self.turn().home_rank()).bitboard(),
Square::new(File::G, self.turn().home_rank()).bitboard(),
Square::from_coords(File::E, self.turn().home_rank()).bitboard(),
Square::from_coords(File::G, self.turn().home_rank()).bitboard(),
),
SanInner::Castle(CastlingSide::Long) => (
Role::King,
Role::King,
Square::new(File::E, self.turn().home_rank()).bitboard(),
Square::new(File::C, self.turn().home_rank()).bitboard(),
Square::from_coords(File::E, self.turn().home_rank()).bitboard(),
Square::from_coords(File::C, self.turn().home_rank()).bitboard(),
),
SanInner::Normal {
role,
@ -1278,7 +1278,7 @@ impl Position {
MoveType::PawnAttackPromotion => aux_play_normal(setup, role, from, to),
MoveType::PawnDoubleAdvance => {
aux_play_pawn_advance(setup, Role::Pawn, from, to);
setup.en_passant = OptionSquare::new(Some(Square::new(
setup.en_passant = OptionSquare::new(Some(Square::from_coords(
from.file(),
match setup.turn {
Color::White => Rank::Third,
@ -1308,12 +1308,12 @@ fn aux_play_normal(setup: &mut Setup, role: Role, from: Square, target: Square)
setup.p_b_q &= mask;
setup.n_b_k &= mask;
setup.r_q_k &= mask;
if target == Square::new(File::H, setup.turn.promotion_rank()) {
if target == Square::from_coords(File::H, setup.turn.promotion_rank()) {
setup
.castling_rights
.unset(!setup.turn, CastlingSide::Short);
}
if target == Square::new(File::A, setup.turn.promotion_rank()) {
if target == Square::from_coords(File::A, setup.turn.promotion_rank()) {
setup.castling_rights.unset(!setup.turn, CastlingSide::Long);
}
match role {
@ -1336,10 +1336,10 @@ fn aux_play_normal(setup: &mut Setup, role: Role, from: Square, target: Square)
}
Role::Rook => {
setup.r_q_k |= to;
if from == Square::new(File::H, setup.turn.home_rank()).bitboard() {
if from == Square::from_coords(File::H, setup.turn.home_rank()).bitboard() {
setup.castling_rights.unset(setup.turn, CastlingSide::Short);
}
if from == Square::new(File::A, setup.turn.home_rank()).bitboard() {
if from == Square::from_coords(File::A, setup.turn.home_rank()).bitboard() {
setup.castling_rights.unset(setup.turn, CastlingSide::Long);
}
}
@ -1386,12 +1386,16 @@ fn aux_play_castle(setup: &mut Setup, side: CastlingSide) {
let rank = setup.turn.home_rank();
let (king_flip, rook_flip) = match side {
CastlingSide::Short => (
Square::new(File::E, rank).bitboard() | Square::new(File::G, rank).bitboard(),
Square::new(File::H, rank).bitboard() | Square::new(File::F, rank).bitboard(),
Square::from_coords(File::E, rank).bitboard()
| Square::from_coords(File::G, rank).bitboard(),
Square::from_coords(File::H, rank).bitboard()
| Square::from_coords(File::F, rank).bitboard(),
),
CastlingSide::Long => (
Square::new(File::E, rank).bitboard() | Square::new(File::C, rank).bitboard(),
Square::new(File::A, rank).bitboard() | Square::new(File::D, rank).bitboard(),
Square::from_coords(File::E, rank).bitboard()
| Square::from_coords(File::C, rank).bitboard(),
Square::from_coords(File::A, rank).bitboard()
| Square::from_coords(File::D, rank).bitboard(),
),
};

View file

@ -179,7 +179,7 @@ impl San {
}
let target_rank = Rank::from_ascii(cur)?;
let target_file = File::from_ascii(r.next()?)?;
let target = Square::new(target_file, target_rank);
let target = Square::from_coords(target_file, target_rank);
let mut cur = r.next();
let capture = cur == Some(b'x');
if capture {

View file

@ -91,7 +91,9 @@ impl Setup {
};
(file < 8).then_some(())?;
setup.set(
unsafe { Square::new(File::transmute(file), Rank::transmute(rank)) },
unsafe {
Square::from_coords(File::transmute(file), Rank::transmute(rank))
},
Some(Piece { role, color }),
);
file += 1;
@ -126,7 +128,7 @@ impl Setup {
match s.next()? {
b'-' => (),
file => setup.set_en_passant_target_square(Some(Square::new(
file => setup.set_en_passant_target_square(Some(Square::from_coords(
File::from_ascii(file)?,
Rank::from_ascii(s.next()?)?,
))),
@ -154,7 +156,7 @@ impl Setup {
for rank in Rank::all().into_iter().rev() {
let mut count = 0;
for file in File::all() {
match self.get(Square::new(file, rank)) {
match self.get(Square::from_coords(file, rank)) {
Some(piece) => {
if count > 0 {
w.write_char(char::from_u32('0' as u32 + count).unwrap())?;
@ -411,11 +413,14 @@ impl Setup {
&& !(pieces
.get(color)
.get(Role::King)
.contains(Square::new(File::E, color.home_rank()))
.contains(Square::from_coords(File::E, color.home_rank()))
&& pieces
.get(color)
.get(Role::Rook)
.contains(Square::new(side.rook_origin_file(), color.home_rank())))
.contains(Square::from_coords(
side.rook_origin_file(),
color.home_rank(),
)))
})
}) {
reasons.add(IllegalPositionReason::InvalidCastlingRights);
@ -426,7 +431,7 @@ impl Setup {
Color::White => (Rank::Sixth, Rank::Fifth),
Color::Black => (Rank::Third, Rank::Fourth),
};
let pawn_square = Square::new(en_passant.file(), pawn_rank);
let pawn_square = Square::from_coords(en_passant.file(), pawn_rank);
en_passant.rank() != target_rank
|| blockers.contains(en_passant)
|| !pieces.get(!self.turn).get(Role::Pawn).contains(pawn_square)

View file

@ -81,8 +81,8 @@ impl UciMove {
pub fn from_ascii(s: &[u8]) -> Option<Self> {
match s {
[a, b, c, d, s @ ..] => Some(Self {
from: Square::new(File::from_ascii(*a)?, Rank::from_ascii(*b)?),
to: Square::new(File::from_ascii(*c)?, Rank::from_ascii(*d)?),
from: Square::from_coords(File::from_ascii(*a)?, Rank::from_ascii(*b)?),
to: Square::from_coords(File::from_ascii(*c)?, Rank::from_ascii(*d)?),
promotion: match s {
[] => None,
[c] => Some(Role::from_ascii(*c)?),