1
0
Fork 0

make RawMove public

This commit is contained in:
Paul-Nicolas Madelaine 2025-12-01 23:39:31 +01:00
parent 6de44c64a7
commit 22098bbfff
3 changed files with 93 additions and 60 deletions

View file

@ -293,6 +293,15 @@ impl Position {
}
}
/// Plays a move without checking for its legality.
///
/// **Safety:** if `m` is not legal on `self` then this might cause undefined behavior, see
/// [`RawMove`] for details.
#[inline]
pub unsafe fn play_unchecked(&mut self, m: RawMove) {
unsafe { play_move(self, m) };
}
pub(crate) fn move_from_uci<'l>(&'l self, uci: UciMove) -> Result<Move<'l>, InvalidUciMove> {
struct MoveGenImpl<const ROLE: u8> {
role: Role,
@ -352,7 +361,7 @@ impl Position {
.generate_moves(&mut moves)
.break_value()
.ok_or(InvalidUciMove::Illegal)?;
Ok(unsafe { Move::new_unchecked(position, raw) })
Ok(unsafe { Move::new(position, raw) })
}
let promotion = if role == Role::Pawn {
promotion.unwrap_or(Role::Pawn)
@ -463,7 +472,7 @@ impl Position {
None => Err(InvalidSan::Illegal),
Some(raw) => match moves.found_other {
true => Err(InvalidSan::Ambiguous),
false => Ok(unsafe { Move::new_unchecked(position, raw) }),
false => Ok(unsafe { Move::new(position, raw) }),
},
}
}
@ -486,12 +495,19 @@ impl Default for Position {
}
}
/// The raw data of a move.
///
/// The [`Move<'l>`](crate::moves::Move) type should usually be preferred for playing moves, but
/// this type allows accessing the unsafe interface [`Position::play_unchecked`].
///
/// When playing this move ([`Position::play_unchecked`]) or converting to a legal move
/// ([`RawMove::to_move`]) it is the caller's responsability to ensure legality. The only w
#[derive(Clone, Copy)]
pub(crate) struct RawMove {
pub kind: MoveType,
pub role: Role,
pub from: Square,
pub to: Square,
pub struct RawMove {
pub(crate) kind: MoveType,
pub(crate) role: Role,
pub(crate) from: Square,
pub(crate) to: Square,
}
#[derive(Clone, Copy, PartialEq, Eq)]
@ -510,16 +526,9 @@ pub(crate) enum MoveType {
}
impl RawMove {
/// Returns the type of piece that moves.
#[inline]
pub fn from(&self) -> Square {
self.from
}
#[inline]
pub fn to(&self) -> Square {
self.to
}
#[inline]
pub fn role(&self) -> Role {
pub fn role(self) -> Role {
match self.kind {
MoveType::CastleShort | MoveType::CastleLong | MoveType::KingMove => Role::King,
MoveType::PieceMove => self.role,
@ -531,15 +540,33 @@ impl RawMove {
| MoveType::EnPassant => Role::Pawn,
}
}
/// Returns the origin square of the move.
#[inline]
pub fn promotion(&self) -> Option<Role> {
pub fn from(self) -> Square {
self.from
}
/// Returns the target square of the move.
#[inline]
pub fn to(self) -> Square {
self.to
}
/// Returns the type of piece that the pawn is promoted to, if the move is a promotion.
#[inline]
pub fn promotion(self) -> Option<Role> {
match self.kind {
MoveType::PawnAdvancePromotion | MoveType::PawnAttackPromotion => Some(self.role),
_ => None,
}
}
/// Converts the move to a [`Move<'l>`] bound to the given position, without checking for the
/// legality of the move.
/// **Safety:**
#[inline]
pub fn uci(&self) -> UciMove {
pub unsafe fn to_move<'l>(self, position: &'l Position) -> Move<'l> {
unsafe { Move::new(position, self) }
}
#[inline]
pub fn to_uci(self) -> UciMove {
UciMove {
from: self.from(),
to: self.to(),
@ -914,51 +941,51 @@ impl Position {
ControlFlow::Continue(())
}
}
#[inline]
pub(crate) unsafe fn play_unchecked(&mut self, m: RawMove) {
let Self(setup) = self;
#[inline]
pub(crate) unsafe fn play_move(position: &mut Position, m: RawMove) {
let Position(setup) = position;
setup.en_passant = None;
setup.en_passant = None;
let RawMove {
kind,
from,
to,
role,
} = m;
let RawMove {
kind,
from,
to,
role,
} = m;
match kind {
MoveType::CastleShort => aux_play_castle(setup, CastlingSide::Short),
MoveType::CastleLong => aux_play_castle(setup, CastlingSide::Long),
MoveType::KingMove => aux_play_normal(setup, Role::King, from, to),
MoveType::PieceMove => aux_play_normal(setup, role, from, to),
MoveType::PawnAdvance => aux_play_pawn_advance(setup, Role::Pawn, from, to),
MoveType::PawnAttack => aux_play_normal(setup, Role::Pawn, from, to),
MoveType::PawnAdvancePromotion => aux_play_pawn_advance(setup, role, from, to),
MoveType::PawnAttackPromotion => aux_play_normal(setup, role, from, to),
MoveType::PawnDoubleAdvance => {
aux_play_pawn_advance(setup, Role::Pawn, from, to);
setup.en_passant = Some(Square::from_coords(
from.file(),
match setup.turn {
Color::White => Rank::Third,
Color::Black => Rank::Sixth,
},
));
}
MoveType::EnPassant => {
let direction = !setup.turn.forward();
let x = (unsafe { to.trans_unchecked(direction) }).bitboard();
let [p_b_q, _, _, black] = &mut setup.bitboards;
*p_b_q ^= x;
*black &= !x;
aux_play_pawn_advance(setup, Role::Pawn, from, to);
}
match kind {
MoveType::CastleShort => aux_play_castle(setup, CastlingSide::Short),
MoveType::CastleLong => aux_play_castle(setup, CastlingSide::Long),
MoveType::KingMove => aux_play_normal(setup, Role::King, from, to),
MoveType::PieceMove => aux_play_normal(setup, role, from, to),
MoveType::PawnAdvance => aux_play_pawn_advance(setup, Role::Pawn, from, to),
MoveType::PawnAttack => aux_play_normal(setup, Role::Pawn, from, to),
MoveType::PawnAdvancePromotion => aux_play_pawn_advance(setup, role, from, to),
MoveType::PawnAttackPromotion => aux_play_normal(setup, role, from, to),
MoveType::PawnDoubleAdvance => {
aux_play_pawn_advance(setup, Role::Pawn, from, to);
setup.en_passant = Some(Square::from_coords(
from.file(),
match setup.turn {
Color::White => Rank::Third,
Color::Black => Rank::Sixth,
},
));
}
MoveType::EnPassant => {
let direction = !setup.turn.forward();
let x = (unsafe { to.trans_unchecked(direction) }).bitboard();
let [p_b_q, _, _, black] = &mut setup.bitboards;
*p_b_q ^= x;
*black &= !x;
aux_play_pawn_advance(setup, Role::Pawn, from, to);
}
setup.turn = !setup.turn;
}
setup.turn = !setup.turn;
}
#[inline]