Skip to content

Commit 56ce430

Browse files
authored
Generalize a castling rights parser and add some (D)FRC positions in bench (#891)
No functional change. Bench: 3126459
1 parent d8f9f78 commit 56ce430

5 files changed

Lines changed: 45 additions & 79 deletions

File tree

src/board/parser.rs

Lines changed: 29 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::Board;
22
use crate::{
3-
lookup::between,
4-
types::{CastlingKind, Color, Piece, PieceType, Square},
3+
lookup::{between, ray_pass},
4+
types::{CastlingKind, Color, HOME_RANK, KING_TO_FILE, Piece, PieceType, ROOK_TO_FILE, Square},
55
};
66

77
#[derive(Debug)]
@@ -67,81 +67,34 @@ impl Board {
6767

6868
fn set_castling(&mut self, rights: &str) {
6969
for right in rights.chars() {
70-
match right {
71-
'K' => {
72-
let mut rook_from = Square::H1;
73-
while self.piece_on(rook_from).piece_type() != PieceType::Rook {
74-
rook_from = rook_from.shift(-1);
75-
}
76-
77-
let king_from = self.king_square(Color::White);
78-
self.set_castling_for(CastlingKind::WhiteKingside, king_from, Square::G1, rook_from, Square::F1);
79-
}
80-
'Q' => {
81-
let mut rook_from = Square::A1;
82-
while self.piece_on(rook_from).piece_type() != PieceType::Rook {
83-
rook_from = rook_from.shift(1);
84-
}
85-
86-
let king_from = self.king_square(Color::White);
87-
self.set_castling_for(CastlingKind::WhiteQueenside, king_from, Square::C1, rook_from, Square::D1);
88-
}
89-
'k' => {
90-
let mut rook_from = Square::H8;
91-
while self.piece_on(rook_from).piece_type() != PieceType::Rook {
92-
rook_from = rook_from.shift(-1);
93-
}
94-
95-
let king_from = self.king_square(Color::Black);
96-
self.set_castling_for(CastlingKind::BlackKingside, king_from, Square::G8, rook_from, Square::F8);
97-
}
98-
'q' => {
99-
let mut rook_from = Square::A8;
100-
while self.piece_on(rook_from).piece_type() != PieceType::Rook {
101-
rook_from = rook_from.shift(1);
102-
}
103-
104-
let king_from = self.king_square(Color::Black);
105-
self.set_castling_for(CastlingKind::BlackQueenside, king_from, Square::C8, rook_from, Square::D8);
106-
}
107-
token @ 'A'..='H' => {
108-
let king_from = self.king_square(Color::White);
109-
let rook_from = Square::from_rank_file(0, token as u8 - b'A');
110-
111-
let kind = if king_from.file() < rook_from.file() {
112-
CastlingKind::WhiteKingside
113-
} else {
114-
CastlingKind::WhiteQueenside
115-
};
116-
117-
let (king_to, rook_to) = match kind {
118-
CastlingKind::WhiteKingside => (Square::G1, Square::F1),
119-
CastlingKind::WhiteQueenside => (Square::C1, Square::D1),
120-
_ => unreachable!(),
121-
};
122-
123-
self.set_castling_for(kind, king_from, king_to, rook_from, rook_to);
124-
}
125-
token @ 'a'..='h' => {
126-
let king_from = self.king_square(Color::Black);
127-
let rook_from = Square::from_rank_file(7, token as u8 - b'a');
128-
129-
let kind = if king_from.file() < rook_from.file() {
130-
CastlingKind::BlackKingside
131-
} else {
132-
CastlingKind::BlackQueenside
133-
};
134-
135-
let (king_to, rook_to) = match kind {
136-
CastlingKind::BlackKingside => (Square::G8, Square::F8),
137-
CastlingKind::BlackQueenside => (Square::C8, Square::D8),
138-
_ => unreachable!(),
139-
};
140-
141-
self.set_castling_for(kind, king_from, king_to, rook_from, rook_to);
142-
}
143-
_ => continue,
70+
if !matches!(right.to_ascii_uppercase(), 'A'..='H' | 'K' | 'Q') {
71+
continue;
14472
}
73+
74+
let color = if right.is_uppercase() { Color::White } else { Color::Black };
75+
let king_from = self.king_square(color);
76+
let mut search_step = right.to_ascii_uppercase() as i8 - b'A' as i8 - king_from.file() as i8;
77+
78+
if right.eq_ignore_ascii_case(&'K') {
79+
search_step = Square::RIGHT;
80+
}
81+
if right.eq_ignore_ascii_case(&'Q') {
82+
search_step = Square::LEFT;
83+
}
84+
85+
let rook_from =
86+
(ray_pass(king_from, king_from.shift(search_step)) & self.colored_pieces(color, PieceType::Rook)).lsb();
87+
88+
let king_side = rook_from > king_from;
89+
90+
let rights = if king_side { CastlingKind::KINGSIDE[color] } else { CastlingKind::QUEENSIDE[color] };
91+
92+
let king_to =
93+
Square::from_rank_file(HOME_RANK[color].clone() as u8, KING_TO_FILE[king_side as usize].clone() as u8);
94+
let rook_to =
95+
Square::from_rank_file(HOME_RANK[color].clone() as u8, ROOK_TO_FILE[king_side as usize].clone() as u8);
96+
97+
self.set_castling_for(rights, king_from, king_to, rook_from, rook_to);
14598
}
14699
}
147100

src/tools/bench.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ const POSITIONS: &[&str] = &[
6363
"8/8/1k1r2p1/p1p2nPp/P3RN1P/8/4KP2/8 b - - 13 55",
6464
"5r1k/1p3p1p/2p2p2/1q2bP1Q/3p1P2/1PP1R1P1/6KP/2N5 w - - 0 25",
6565
"8/8/5pk1/5Nn1/R3r1P1/8/6K1/8 w - - 4 65",
66+
"rbbnkqrn/pppppppp/8/8/8/8/PPPPPPPP/RBBNKQRN w AGag - 0 1",
67+
"nbrknrbq/pppppppp/8/8/8/8/PPPPPPPP/NBRKNRBQ w CFcf - 0 1",
68+
"nqnbbrkr/pppppppp/8/8/8/8/PPPPPPPP/NQNBBRKR w FHfh - 0 1",
69+
"nqrnbkrb/pppppppp/8/8/8/8/PPPPPPPP/NQRNBKRB w KQkq - 0 1",
70+
"rqkbbnnr/pppppppp/8/8/8/8/PPPPPPPP/BBNNRKRQ w GEha - 0 1",
6671
];
6772

6873
const DEFAULT_DEPTH: i32 = 12;

src/types/bitboard.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ impl Bitboard {
4545
Square::new(self.0.trailing_zeros() as u8)
4646
}
4747

48+
pub const fn msb(self) -> Square {
49+
Square::new(63 - self.0.leading_zeros() as u8)
50+
}
51+
4852
pub const fn shift(self, offset: i8) -> Self {
4953
if offset > 0 { Self(self.0 << offset) } else { Self(self.0 >> -offset) }
5054
}

src/types/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,21 @@ pub const MAX_MOVES: usize = 256;
3030

3131
#[rustfmt::skip]
3232
#[repr(u8)]
33-
#[derive(PartialEq, PartialOrd)]
33+
#[derive(Clone, PartialEq, PartialOrd)]
3434
pub enum Rank { R1, R2, R3, R4, R5, R6, R7, R8 }
3535

3636
pub const PROMO_RANK: [Rank; 2] = [Rank::R8, Rank::R1];
37+
pub const HOME_RANK: [Rank; 2] = [Rank::R1, Rank::R8];
3738
pub const PAWN_HOME_RANK: [Rank; 2] = [Rank::R2, Rank::R7];
3839

3940
#[rustfmt::skip]
4041
#[repr(u8)]
41-
#[derive(PartialEq, PartialOrd)]
42+
#[derive(Clone, PartialEq, PartialOrd)]
4243
pub enum File { A, B, C, D, E, F, G, H }
4344

45+
pub const KING_TO_FILE: [File; 2] = [File::C, File::G];
46+
pub const ROOK_TO_FILE: [File; 2] = [File::D, File::F];
47+
4448
impl File {
4549
pub fn is_kingside(&self) -> bool {
4650
*self >= File::E

src/types/square.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::types::{Color, File, Rank};
66
/// Represents a square on a bitboard corresponding to the [Little-Endian Rank-File Mapping][LERFM].
77
///
88
/// [LERFM]: https://www.chessprogramming.org/Square_Mapping_Considerations#Little-Endian_Rank-File_Mapping
9-
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
9+
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Debug, Default)]
1010
#[repr(u8)]
1111
#[rustfmt::skip]
1212
pub enum Square {

0 commit comments

Comments
 (0)