use position::Position;
use movelist::MoveList;
use uci::Uci;
pub fn perft<P: Position + Clone>(pos: &P, depth: u8) -> u64 {
if depth < 1 {
1
} else {
let mut moves = MoveList::new();
pos.legal_moves(&mut moves);
if depth == 1 {
moves.len() as u64
} else {
moves.drain(..).map(|m| {
let mut child = pos.clone();
child.play_unchecked(&m);
perft(&child, depth - 1)
}).sum()
}
}
}
#[allow(unused)]
pub fn debug_perft<P: Position + Clone>(pos: &P, depth: u8) -> u64 {
if depth < 1 {
1
} else {
let mut moves = MoveList::new();
pos.legal_moves(&mut moves);
moves.iter().map(|m| {
let child = pos.clone().play(m).expect("legal move");
let nodes = perft(&child, depth - 1);
let uci = Uci::from_move(pos, m);
println!("{} {} {}: {}", uci, m, depth - 1, nodes);
nodes
}).sum()
}
}
#[cfg(test)]
mod tests {
use super::*;
use position::Chess;
#[test]
fn test_perft() {
let pos = Chess::default();
assert_eq!(perft(&pos, 0), 1);
assert_eq!(perft(&pos, 1), 20);
}
}