Skip to content

Commit 6174933

Browse files
Add is_legal perft generator (#874)
Bench: 2798043 Co-Authored-By: 87 <dev@87flowers.com>
1 parent 06241a3 commit 6174933

4 files changed

Lines changed: 48 additions & 8 deletions

File tree

src/board.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ impl Board {
367367
Square::C1 => CastlingKind::WhiteQueenside,
368368
Square::G8 => CastlingKind::BlackKingside,
369369
Square::C8 => CastlingKind::BlackQueenside,
370-
_ => unreachable!(),
370+
_ => return false,
371371
};
372372

373373
return self.castling().is_allowed(kind)

src/tools/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ mod bench;
22
mod perft;
33

44
pub use bench::bench;
5+
pub use perft::is_legal_perft;
56
pub use perft::perft;
67
pub use perft::simple_perft;

src/tools/perft.rs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
66
use std::time::Instant;
77

8-
use crate::board::{Board, NullBoardObserver};
8+
use crate::{
9+
board::{Board, NullBoardObserver},
10+
types::{Move, MoveList},
11+
};
912

1013
pub fn perft(depth: usize, board: &mut Board) {
1114
println!("{}", "-".repeat(60));
@@ -24,7 +27,7 @@ pub fn perft(depth: usize, board: &mut Board) {
2427

2528
board.make_move(mv, &mut NullBoardObserver);
2629

27-
let count = perft_internal(depth - 1, board);
30+
let count = perft_internal(&|board| board.generate_all_moves(), depth - 1, board);
2831
nodes += count;
2932
index += 1;
3033

@@ -52,7 +55,7 @@ pub fn simple_perft(depth: usize, board: &mut Board) {
5255

5356
board.make_move(mv, &mut NullBoardObserver);
5457

55-
let count = perft_internal(depth - 1, board);
58+
let count = perft_internal(&|board| board.generate_all_moves(), depth - 1, board);
5659
nodes += count;
5760

5861
board.undo_move(mv);
@@ -63,23 +66,57 @@ pub fn simple_perft(depth: usize, board: &mut Board) {
6366
println!("total: {nodes}");
6467
}
6568

66-
fn perft_internal(depth: usize, board: &mut Board) -> u64 {
69+
pub fn is_legal_perft(depth: usize, board: &mut Board) {
70+
let mut nodes = 0;
71+
72+
for entry in is_legal_movegen(board).iter() {
73+
let mv = entry.mv;
74+
75+
board.make_move(mv, &mut NullBoardObserver);
76+
77+
let count = perft_internal(&is_legal_movegen, depth - 1, board);
78+
nodes += count;
79+
80+
board.undo_move(mv);
81+
82+
println!("{}: {count}", mv.to_uci(board));
83+
}
84+
85+
println!("total: {nodes}");
86+
}
87+
88+
fn perft_internal<F: Fn(&Board) -> MoveList>(move_gen: &F, depth: usize, board: &mut Board) -> u64 {
6789
if depth == 0 {
6890
return 1;
6991
}
7092

7193
if depth == 1 {
72-
return board.generate_all_moves().len() as u64;
94+
return move_gen(board).len() as u64;
7395
}
7496

7597
let mut nodes = 0;
7698

77-
for entry in board.generate_all_moves().iter() {
99+
for entry in move_gen(board).iter() {
78100
let mv = entry.mv;
79101
board.make_move(mv, &mut NullBoardObserver);
80-
nodes += perft_internal(depth - 1, board);
102+
nodes += perft_internal(move_gen, depth - 1, board);
81103
board.undo_move(mv);
82104
}
83105

84106
nodes
85107
}
108+
109+
fn is_legal_movegen(board: &Board) -> MoveList {
110+
let mut moves = MoveList::new();
111+
for i in 0..0x10000 {
112+
let j = i >> 12;
113+
if j == 0b0011 || j == 0b0110 || j == 0b0111 {
114+
continue;
115+
}
116+
let mv: Move = unsafe { std::mem::transmute(i as u16) };
117+
if mv.is_present() && board.is_legal(mv) {
118+
moves.push(mv.from(), mv.to(), mv.kind());
119+
}
120+
}
121+
moves
122+
}

src/uci.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ pub fn message_loop(mut buffer: VecDeque<String>) {
9090
["perft"] => eprintln!("Usage: perft <depth>"),
9191
["simpleperft", depth] => tools::simple_perft(depth.parse().unwrap(), &mut threads.main_thread().board),
9292
["simpleperft"] => eprintln!("Usage: simpleperft <depth>"),
93+
["islegalperft", depth] => tools::is_legal_perft(depth.parse().unwrap(), &mut threads.main_thread().board),
94+
["islegalperft"] => eprintln!("Usage: islegalperft <depth>"),
9395

9496
// Ignore empty lines
9597
[] => (),

0 commit comments

Comments
 (0)