new constructors
This commit is contained in:
parent
808cde1c42
commit
494de58804
6 changed files with 92 additions and 56 deletions
|
|
@ -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,7 +31,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
|
||||
|
|
@ -134,7 +134,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -148,7 +148,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);
|
||||
}
|
||||
|
|
|
|||
84
src/board.rs
84
src/board.rs
|
|
@ -110,6 +110,17 @@ impl File {
|
|||
]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(index: u8) -> Option<Self> {
|
||||
(index < 8).then(|| unsafe { Self::new_unchecked(index) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(index: u8) -> Self {
|
||||
debug_assert!(index < 8);
|
||||
std::mem::transmute(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_char(self) -> char {
|
||||
self.to_ascii() as char
|
||||
|
|
@ -128,7 +139,10 @@ impl File {
|
|||
#[inline]
|
||||
pub(crate) fn from_ascii(c: u8) -> Option<Self> {
|
||||
(c <= b'h')
|
||||
.then(|| c.checked_sub(b'a').map(|i| unsafe { Self::transmute(i) }))
|
||||
.then(|| {
|
||||
c.checked_sub(b'a')
|
||||
.map(|i| unsafe { Self::new_unchecked(i) })
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
|
|
@ -136,12 +150,6 @@ impl File {
|
|||
pub(crate) fn bitboard(self) -> Bitboard {
|
||||
Bitboard(0x0101010101010101 << (self as u8))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn transmute(value: u8) -> Self {
|
||||
debug_assert!(value < 8);
|
||||
std::mem::transmute(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for File {
|
||||
|
|
@ -182,6 +190,17 @@ impl Rank {
|
|||
]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(index: u8) -> Option<Self> {
|
||||
(index < 8).then(|| unsafe { Self::new_unchecked(index) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn new_unchecked(index: u8) -> Self {
|
||||
debug_assert!(index < 8);
|
||||
std::mem::transmute(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_char(self) -> char {
|
||||
self.to_ascii() as char
|
||||
|
|
@ -194,7 +213,7 @@ impl Rank {
|
|||
|
||||
#[inline]
|
||||
pub fn mirror(self) -> Self {
|
||||
unsafe { Self::transmute(7_u8.unchecked_sub(self as u8)) }
|
||||
unsafe { Self::new_unchecked(7_u8.unchecked_sub(self as u8)) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -205,19 +224,16 @@ impl Rank {
|
|||
#[inline]
|
||||
pub(crate) fn from_ascii(c: u8) -> Option<Self> {
|
||||
(c <= b'8')
|
||||
.then(|| c.checked_sub(b'1').map(|i| unsafe { Self::transmute(i) }))
|
||||
.then(|| {
|
||||
c.checked_sub(b'1')
|
||||
.map(|i| unsafe { Self::new_unchecked(i) })
|
||||
})
|
||||
.flatten()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn bitboard(self) -> Bitboard {
|
||||
Bitboard(0xFF << ((self as u64) << 3))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn transmute(value: u8) -> Self {
|
||||
debug_assert!(value < 8);
|
||||
std::mem::transmute(value)
|
||||
Bitboard(0xFF << ((self as u8) << 3))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -262,23 +278,34 @@ impl Square {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new(file: File, rank: Rank) -> Self {
|
||||
unsafe { Self::transmute(((rank as u8) << 3) | file as u8) }
|
||||
pub fn new(index: u8) -> Option<Self> {
|
||||
(index < 64).then(|| unsafe { Self::new_unchecked(index) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub 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]
|
||||
pub fn file(self) -> File {
|
||||
unsafe { File::transmute((self as u8) & 7) }
|
||||
unsafe { File::new_unchecked((self as u8) & 7) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn rank(self) -> Rank {
|
||||
unsafe { Rank::transmute((self as u8) >> 3) }
|
||||
unsafe { Rank::new_unchecked((self as u8) >> 3) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mirror(self) -> Self {
|
||||
Self::new(self.file(), self.rank().mirror())
|
||||
Self::from_coords(self.file(), self.rank().mirror())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -312,7 +339,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]
|
||||
|
|
@ -329,7 +359,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),
|
||||
|
|
@ -356,12 +386,6 @@ impl Square {
|
|||
Direction::West => self.file() > File::A,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) unsafe fn transmute(value: u8) -> Self {
|
||||
debug_assert!(value < 64);
|
||||
std::mem::transmute(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Square {
|
||||
|
|
@ -419,7 +443,7 @@ impl OptionSquare {
|
|||
unsafe {
|
||||
match self {
|
||||
Self::None => None,
|
||||
_ => Some(Square::transmute(self as u8)),
|
||||
_ => Some(Square::new_unchecked(self as u8)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -426,14 +426,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,
|
||||
|
|
@ -1275,7 +1275,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,
|
||||
|
|
@ -1305,12 +1305,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 {
|
||||
|
|
@ -1333,10 +1333,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1383,12 +1383,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(),
|
||||
),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
20
src/setup.rs
20
src/setup.rs
|
|
@ -76,7 +76,12 @@ impl Setup {
|
|||
};
|
||||
(file < 8).then_some(())?;
|
||||
setup.set(
|
||||
unsafe { Square::new(File::transmute(file), Rank::transmute(rank)) },
|
||||
unsafe {
|
||||
Square::from_coords(
|
||||
File::new_unchecked(file),
|
||||
Rank::new_unchecked(rank),
|
||||
)
|
||||
},
|
||||
Some(Piece { role, color }),
|
||||
);
|
||||
file += 1;
|
||||
|
|
@ -118,7 +123,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()?)?,
|
||||
))),
|
||||
|
|
@ -319,11 +324,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);
|
||||
|
|
@ -334,7 +342,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)
|
||||
|
|
@ -430,7 +438,7 @@ impl std::fmt::Display for 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 {
|
||||
f.write_char(char::from_u32('0' as u32 + count).unwrap())?;
|
||||
|
|
|
|||
|
|
@ -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)?),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue