use super::Position;
use super::types::{BoardArray, Ply};
use crate::board::bitboard_set::BitboardSet;
use crate::board::zobrist::ZobristKey;
use crate::types::{
Bitboard, Color, File, Hand, Move, Move32, Move32Metadata, MoveBase, Piece, PieceType, Square,
};
impl Position {
#[inline]
#[must_use]
pub fn piece_on(&self, sq: Square) -> Piece {
if sq.is_none() {
return Piece::NONE;
}
self.board.get(sq)
}
#[inline]
#[must_use]
pub(crate) unsafe fn piece_on_unchecked(&self, sq: Square) -> Piece {
unsafe {
self.board.get_unchecked(sq)
}
}
#[inline]
#[must_use]
pub fn is_square_empty(&self, sq: Square) -> bool {
self.piece_on(sq) == Piece::NONE
}
#[inline]
#[must_use]
pub fn empties(&self) -> Bitboard {
!self.bitboards().occupied()
}
#[inline]
#[must_use]
pub const fn hand(&self, color: Color) -> Hand {
self.hands[color.to_index()]
}
#[inline]
#[must_use]
pub(crate) fn hand_mut(&mut self, color: Color) -> &mut Hand {
&mut self.hands[color.to_index()]
}
#[inline]
#[must_use]
pub const fn turn(&self) -> Color {
self.side_to_move
}
#[inline]
pub(crate) fn set_side_to_move(&mut self, color: Color) {
self.side_to_move = color;
}
#[inline]
pub(crate) fn flip_side_to_move(&mut self) {
self.side_to_move = self.side_to_move.flip();
}
#[inline]
#[must_use]
pub const fn king_square(&self, color: Color) -> Square {
self.king_square[color.to_index()]
}
#[inline]
pub(crate) fn set_king_square(&mut self, color: Color, sq: Square) {
self.king_square[color.to_index()] = sq;
}
#[must_use]
pub fn square(&self, color: Color, piece_type: PieceType) -> Square {
debug_assert!(
piece_type == PieceType::KING,
"Position::square only supports KING in shogi mode"
);
self.king_square(color)
}
#[must_use]
pub fn has_pawn_on_file(&self, color: Color, file: File) -> bool {
use crate::types::PieceType;
let pawns = self.bitboards.pieces_for(PieceType::PAWN, color);
let file_mask = Bitboard::file_mask(file);
!(pawns & file_mask).is_empty()
}
#[inline]
#[must_use]
pub const fn game_ply(&self) -> Ply {
self.ply
}
#[inline]
#[must_use]
pub fn board_array(&self) -> BoardArray {
self.board
}
#[inline]
#[must_use]
pub fn hands_array(&self) -> [Hand; Color::COUNT] {
self.hands
}
#[inline]
#[must_use]
pub const fn key(&self) -> ZobristKey {
self.zobrist
}
#[must_use]
#[inline]
pub fn moved_piece_before(&self, mv: Move32) -> Piece {
self.moved_piece_before_impl(mv)
}
#[must_use]
#[inline]
pub fn moved_piece_before_move(&self, mv: Move) -> Piece {
self.moved_piece_before_impl(mv)
}
#[inline]
fn moved_piece_before_impl(&self, mv: impl MoveBase) -> Piece {
let m = mv.to_move();
if m.is_drop() {
let Some(pt) = m.dropped_piece() else {
return Piece::NONE;
};
return Piece::from_parts(self.turn(), pt);
}
let from = m.from_sq();
if from.is_none() {
return Piece::NONE;
}
self.piece_on(from)
}
#[must_use]
#[inline]
pub fn moved_piece_after(&self, mv: Move32) -> Piece {
self.moved_piece_after_impl(mv)
}
#[must_use]
#[inline]
pub fn moved_piece_after_move(&self, mv: Move) -> Piece {
self.moved_piece_after_impl(mv)
}
#[inline]
fn moved_piece_after_impl(&self, mv: impl MoveBase) -> Piece {
let m = mv.to_move();
if m.is_drop() {
let Some(pt) = m.dropped_piece() else {
return Piece::NONE;
};
return Piece::from_parts(self.turn(), pt);
}
let from = m.from_sq();
if from.is_none() {
return Piece::NONE;
}
let piece = self.piece_on(from);
if m.is_promotion() { piece.promote() } else { piece }
}
#[must_use]
#[inline]
pub fn moved_piece(&self, mv: Move32) -> Piece {
self.moved_piece_after(mv)
}
#[must_use]
#[inline]
pub fn move32_metadata(&self, mv: Move32) -> Move32Metadata {
let piece_after =
if mv.has_piece_info() { mv.piece_after_move() } else { self.moved_piece_after(mv) };
let captured_piece = if mv.is_drop() {
Piece::NONE
} else {
let piece = self.piece_on(mv.to_sq());
if piece == Piece::NONE || piece.color() == self.turn() { Piece::NONE } else { piece }
};
Move32Metadata::with_from_to_index(
piece_after,
captured_piece,
captured_piece != Piece::NONE,
mv.is_promotion(),
mv.is_drop(),
mv.from_to_index(),
)
}
#[must_use]
#[inline]
pub fn classify_move32(&self, mv: Move32) -> Move32Metadata {
self.move32_metadata(mv)
}
#[must_use]
#[inline]
pub fn captured_piece(&self) -> Piece {
self.current_cold().captured_piece()
}
#[must_use]
#[inline]
pub fn last_move(&self) -> Move32 {
self.current_cold().last_move()
}
#[must_use]
#[inline]
pub fn last_moved_piece_type(&self) -> PieceType {
self.current_cold().last_moved_piece_type()
}
#[must_use]
pub fn repetition_counter(&self) -> i32 {
self.current_hot().repetition_counter
}
#[must_use]
pub fn repetition_distance(&self) -> i32 {
self.current_hot().repetition_distance
}
#[must_use]
pub fn repetition_times(&self) -> i32 {
self.current_hot().repetition_times()
}
#[must_use]
pub fn repetition_type(&self) -> crate::types::RepetitionState {
self.current_hot().repetition_type()
}
#[must_use]
pub fn plies_from_null(&self) -> Ply {
self.current_hot().plies_from_null()
}
#[must_use]
pub fn continuous_checks(&self) -> [u16; Color::COUNT] {
self.current_hot().continuous_checks()
}
#[inline]
#[must_use]
pub const fn bitboards(&self) -> &BitboardSet {
&self.bitboards
}
#[inline]
#[must_use]
pub const fn pieces(&self) -> Bitboard {
self.bitboards().occupied()
}
#[inline]
#[must_use]
pub const fn pieces_by_type(&self, piece_type: PieceType) -> Bitboard {
self.bitboards().pieces(piece_type)
}
#[must_use]
pub fn pieces_by_types(&self, piece_types: &[PieceType]) -> Bitboard {
let mut out = Bitboard::EMPTY;
for &piece_type in piece_types {
out |= self.bitboards().pieces(piece_type);
}
out
}
#[must_use]
pub fn pieces_by_types_array<const N: usize>(&self, piece_types: [PieceType; N]) -> Bitboard {
let mut out = Bitboard::EMPTY;
for &piece_type in &piece_types {
out |= self.bitboards().pieces(piece_type);
}
out
}
#[inline]
#[must_use]
pub const fn pieces_by_color(&self, color: Color) -> Bitboard {
self.bitboards().color_pieces(color)
}
#[inline]
#[must_use]
pub fn pieces_for(&self, piece_type: PieceType, color: Color) -> Bitboard {
self.bitboards().pieces_for(piece_type, color)
}
#[inline]
#[must_use]
pub fn golds(&self) -> Bitboard {
self.bitboards().golds()
}
#[inline]
#[must_use]
pub fn horse_dragon_king(&self) -> Bitboard {
self.bitboards().horse_dragon_king()
}
#[inline]
#[must_use]
pub fn bishop_horse(&self) -> Bitboard {
self.bitboards().bishop_horse()
}
#[inline]
#[must_use]
pub fn rook_dragon(&self) -> Bitboard {
self.bitboards().rook_dragon()
}
#[must_use]
pub fn pieces_for_types(&self, piece_types: &[PieceType], color: Color) -> Bitboard {
let mut out = Bitboard::EMPTY;
for &piece_type in piece_types {
out |= self.bitboards().pieces_for(piece_type, color);
}
out
}
#[must_use]
pub fn pieces_for_types_array<const N: usize>(
&self,
piece_types: [PieceType; N],
color: Color,
) -> Bitboard {
let mut out = Bitboard::EMPTY;
for &piece_type in &piece_types {
out |= self.bitboards().pieces_for(piece_type, color);
}
out
}
}