refactor: use Index/IndexMut instead of helper functions
This commit is contained in:
parent
8d5ea3de31
commit
60d084886f
@ -41,8 +41,8 @@ impl Eval for Board {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for pc in [Rook, Queen, Pawn, Knight, Bishop, King] {
|
for pc in [Rook, Queen, Pawn, Knight, Bishop, King] {
|
||||||
let tally_white = self.pl(Color::White).board(pc).0.count_ones();
|
let tally_white = self[Color::White][pc].0.count_ones();
|
||||||
let tally_black = self.pl(Color::Black).board(pc).0.count_ones();
|
let tally_black = self[Color::Black][pc].0.count_ones();
|
||||||
let tally =
|
let tally =
|
||||||
EvalInt::try_from(tally_white).unwrap() - EvalInt::try_from(tally_black).unwrap();
|
EvalInt::try_from(tally_white).unwrap() - EvalInt::try_from(tally_black).unwrap();
|
||||||
|
|
||||||
|
99
src/lib.rs
99
src/lib.rs
@ -14,6 +14,7 @@ Copyright © 2024 dogeystamp <dogeystamp@disroot.org>
|
|||||||
#![deny(rust_2018_idioms)]
|
#![deny(rust_2018_idioms)]
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
pub mod eval;
|
pub mod eval;
|
||||||
@ -372,23 +373,11 @@ impl Mailbox {
|
|||||||
///
|
///
|
||||||
/// Default is all empty.
|
/// Default is all empty.
|
||||||
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
struct Player {
|
pub struct PlayerBoards {
|
||||||
/// Bitboards for individual pieces. Piece -> locations.
|
/// Bitboards for individual pieces. Piece -> locations.
|
||||||
bit: [Bitboard; N_PIECES],
|
bit: [Bitboard; N_PIECES],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
|
||||||
/// Get board (non-mutable) for a specific piece.
|
|
||||||
fn board(&self, pc: Piece) -> &Bitboard {
|
|
||||||
&self.bit[pc as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get board (mutable) for a specific piece.
|
|
||||||
fn board_mut(&mut self, pc: Piece) -> &mut Bitboard {
|
|
||||||
&mut self.bit[pc as usize]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Castling rights for one player
|
/// Castling rights for one player
|
||||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct CastlePlayer {
|
pub struct CastlePlayer {
|
||||||
@ -402,9 +391,9 @@ pub struct CastlePlayer {
|
|||||||
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, Default, PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct CastleRights([CastlePlayer; N_COLORS]);
|
pub struct CastleRights([CastlePlayer; N_COLORS]);
|
||||||
|
|
||||||
impl ToString for CastleRights {
|
impl Display for CastleRights {
|
||||||
/// Convert to FEN castling rights format.
|
/// Convert to FEN castling rights format.
|
||||||
fn to_string(&self) -> String {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut ret = String::with_capacity(4);
|
let mut ret = String::with_capacity(4);
|
||||||
for (val, ch) in [
|
for (val, ch) in [
|
||||||
(self.0[Color::White as usize].k, 'K'),
|
(self.0[Color::White as usize].k, 'K'),
|
||||||
@ -419,7 +408,7 @@ impl ToString for CastleRights {
|
|||||||
if ret.is_empty() {
|
if ret.is_empty() {
|
||||||
ret.push('-')
|
ret.push('-')
|
||||||
}
|
}
|
||||||
ret
|
write!(f, "{}", ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,7 +418,7 @@ impl ToString for CastleRights {
|
|||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Board {
|
pub struct Board {
|
||||||
/// Player bitboards
|
/// Player bitboards
|
||||||
players: [Player; N_COLORS],
|
players: [PlayerBoards; N_COLORS],
|
||||||
|
|
||||||
/// Mailbox (array) board. Location -> piece.
|
/// Mailbox (array) board. Location -> piece.
|
||||||
mail: Mailbox,
|
mail: Mailbox,
|
||||||
@ -458,26 +447,6 @@ impl Board {
|
|||||||
Board::from_fen(START_POSITION).unwrap()
|
Board::from_fen(START_POSITION).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get mutable reference to a player.
|
|
||||||
fn pl_mut(&mut self, col: Color) -> &mut Player {
|
|
||||||
&mut self.players[col as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get immutable reference to a player.
|
|
||||||
fn pl(&self, col: Color) -> &Player {
|
|
||||||
&self.players[col as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get immutable reference to castling rights.
|
|
||||||
pub fn pl_castle(&self, col: Color) -> &CastlePlayer {
|
|
||||||
&self.castle.0[col as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get mutable reference to castling rights.
|
|
||||||
fn pl_castle_mut(&mut self, col: Color) -> &mut CastlePlayer {
|
|
||||||
&mut self.castle.0[col as usize]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get iterator over all squares.
|
/// Get iterator over all squares.
|
||||||
pub fn squares() -> impl Iterator<Item = Square> {
|
pub fn squares() -> impl Iterator<Item = Square> {
|
||||||
(0..N_SQUARES).map(Square::try_from).map(|x| x.unwrap())
|
(0..N_SQUARES).map(Square::try_from).map(|x| x.unwrap())
|
||||||
@ -486,8 +455,8 @@ impl Board {
|
|||||||
/// Create a new piece in a location, and pop any existing piece in the destination.
|
/// Create a new piece in a location, and pop any existing piece in the destination.
|
||||||
pub fn set_piece(&mut self, idx: Square, pc: ColPiece) -> Option<ColPiece> {
|
pub fn set_piece(&mut self, idx: Square, pc: ColPiece) -> Option<ColPiece> {
|
||||||
let dest_pc = self.del_piece(idx);
|
let dest_pc = self.del_piece(idx);
|
||||||
let pl = self.pl_mut(pc.col);
|
let pl = &mut self[pc.col];
|
||||||
pl.board_mut(pc.into()).on_sq(idx);
|
pl[pc.into()].on_sq(idx);
|
||||||
*self.mail.sq_mut(idx) = Some(pc);
|
*self.mail.sq_mut(idx) = Some(pc);
|
||||||
dest_pc
|
dest_pc
|
||||||
}
|
}
|
||||||
@ -503,8 +472,8 @@ impl Board {
|
|||||||
/// Delete the piece in a location, and return ("pop") that piece.
|
/// Delete the piece in a location, and return ("pop") that piece.
|
||||||
pub fn del_piece(&mut self, idx: Square) -> Option<ColPiece> {
|
pub fn del_piece(&mut self, idx: Square) -> Option<ColPiece> {
|
||||||
if let Some(pc) = *self.mail.sq_mut(idx) {
|
if let Some(pc) = *self.mail.sq_mut(idx) {
|
||||||
let pl = self.pl_mut(pc.col);
|
let pl = &mut self[pc.col];
|
||||||
pl.board_mut(pc.into()).off_sq(idx);
|
pl[pc.into()].off_sq(idx);
|
||||||
*self.mail.sq_mut(idx) = None;
|
*self.mail.sq_mut(idx) = None;
|
||||||
Some(pc)
|
Some(pc)
|
||||||
} else {
|
} else {
|
||||||
@ -555,7 +524,7 @@ impl Board {
|
|||||||
|
|
||||||
/// Is a given player in check?
|
/// Is a given player in check?
|
||||||
pub fn is_check(&self, pl: Color) -> bool {
|
pub fn is_check(&self, pl: Color) -> bool {
|
||||||
for src in self.pl(pl).board(Piece::King).into_iter() {
|
for src in self[pl][Piece::King] {
|
||||||
macro_rules! detect_checker {
|
macro_rules! detect_checker {
|
||||||
($dirs: ident, $pc: pat, $keep_going: expr) => {
|
($dirs: ident, $pc: pat, $keep_going: expr) => {
|
||||||
for dir in $dirs.into_iter() {
|
for dir in $dirs.into_iter() {
|
||||||
@ -606,6 +575,48 @@ impl Board {
|
|||||||
const MAX_MOVES: usize = 9_999;
|
const MAX_MOVES: usize = 9_999;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Index<Color> for Board {
|
||||||
|
type Output = PlayerBoards;
|
||||||
|
|
||||||
|
fn index(&self, col: Color) -> &Self::Output {
|
||||||
|
&self.players[col as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<Color> for Board {
|
||||||
|
fn index_mut(&mut self, col: Color) -> &mut Self::Output {
|
||||||
|
&mut self.players[col as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<Color> for CastleRights {
|
||||||
|
type Output = CastlePlayer;
|
||||||
|
|
||||||
|
fn index(&self, col: Color) -> &Self::Output {
|
||||||
|
&self.0[col as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<Color> for CastleRights {
|
||||||
|
fn index_mut(&mut self, col: Color) -> &mut Self::Output {
|
||||||
|
&mut self.0[col as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<Piece> for PlayerBoards {
|
||||||
|
type Output = Bitboard;
|
||||||
|
|
||||||
|
fn index(&self, pc: Piece) -> &Self::Output {
|
||||||
|
&self.bit[pc as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<Piece> for PlayerBoards {
|
||||||
|
fn index_mut(&mut self, pc: Piece) -> &mut Self::Output {
|
||||||
|
&mut self.bit[pc as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for Board {
|
impl core::fmt::Display for Board {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
let mut str = String::with_capacity(N_SQUARES + BOARD_HEIGHT);
|
let mut str = String::with_capacity(N_SQUARES + BOARD_HEIGHT);
|
||||||
@ -693,9 +704,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let board = Board::from_fen("8/4p3/1q1Q1p2/4p3/1p1r4/8/8/8 w - - 0 1").unwrap();
|
let board = Board::from_fen("8/4p3/1q1Q1p2/4p3/1p1r4/8/8/8 w - - 0 1").unwrap();
|
||||||
let white_queens = board
|
let white_queens = board[Color::White][Piece::Queen]
|
||||||
.pl(Color::White)
|
|
||||||
.board(Piece::Queen)
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<Square>>();
|
.collect::<Vec<Square>>();
|
||||||
assert_eq!(white_queens, vec![Square::from_str("d6").unwrap()])
|
assert_eq!(white_queens, vec![Square::from_str("d6").unwrap()])
|
||||||
|
@ -296,7 +296,7 @@ impl Move {
|
|||||||
pos.half_moves = 0;
|
pos.half_moves = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let castle = &mut pos.pl_castle_mut(pc_src.col);
|
let castle = &mut pos.castle[pc_src.col];
|
||||||
if matches!(pc_src.pc, Piece::King) {
|
if matches!(pc_src.pc, Piece::King) {
|
||||||
// forfeit castling rights
|
// forfeit castling rights
|
||||||
castle.k = false;
|
castle.k = false;
|
||||||
@ -564,10 +564,10 @@ fn is_legal(board: &mut Board, mv: Move) -> bool {
|
|||||||
impl MoveGen for Board {
|
impl MoveGen for Board {
|
||||||
fn gen_moves(&mut self, gen_type: MoveGenType) -> impl IntoIterator<Item = Move> {
|
fn gen_moves(&mut self, gen_type: MoveGenType) -> impl IntoIterator<Item = Move> {
|
||||||
let mut ret = Vec::new();
|
let mut ret = Vec::new();
|
||||||
let pl = self.pl(self.turn);
|
let pl = self[self.turn];
|
||||||
macro_rules! squares {
|
macro_rules! squares {
|
||||||
($pc: ident) => {
|
($pc: ident) => {
|
||||||
pl.board(Piece::$pc).into_iter()
|
pl[Piece::$pc].into_iter()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +583,7 @@ impl MoveGen for Board {
|
|||||||
for src in squares!(King) {
|
for src in squares!(King) {
|
||||||
move_slider(self, src, &mut ret, SliderDirection::Star, false);
|
move_slider(self, src, &mut ret, SliderDirection::Star, false);
|
||||||
let (r, c) = src.to_row_col_signed();
|
let (r, c) = src.to_row_col_signed();
|
||||||
let rights = self.pl_castle(self.turn);
|
let rights = self.castle[self.turn];
|
||||||
let castle_sides = [(rights.k, 2, BOARD_WIDTH as isize - 1), (rights.q, -2, 0)];
|
let castle_sides = [(rights.k, 2, BOARD_WIDTH as isize - 1), (rights.q, -2, 0)];
|
||||||
for (is_allowed, move_offset, endpoint) in castle_sides {
|
for (is_allowed, move_offset, endpoint) in castle_sides {
|
||||||
if !is_allowed {
|
if !is_allowed {
|
||||||
@ -784,8 +784,8 @@ mod tests {
|
|||||||
use std::collections::hash_set::HashSet;
|
use std::collections::hash_set::HashSet;
|
||||||
use Piece::*;
|
use Piece::*;
|
||||||
for pc in [Rook, Bishop, Knight, Queen, King, Pawn] {
|
for pc in [Rook, Bishop, Knight, Queen, King, Pawn] {
|
||||||
let white: HashSet<_> = pos.pl(Color::White).board(pc).into_iter().collect();
|
let white: HashSet<_> = pos[Color::White][pc].into_iter().collect();
|
||||||
let black: HashSet<_> = pos.pl(Color::Black).board(pc).into_iter().collect();
|
let black: HashSet<_> = pos[Color::Black][pc].into_iter().collect();
|
||||||
let intersect = white.intersection(&black).collect::<Vec<_>>();
|
let intersect = white.intersection(&black).collect::<Vec<_>>();
|
||||||
assert!(
|
assert!(
|
||||||
intersect.is_empty(),
|
intersect.is_empty(),
|
||||||
|
Loading…
Reference in New Issue
Block a user