Add depth limit on quiescence, add node/timer measurements

This commit is contained in:
stefiosif
2024-10-16 21:36:48 +03:00
parent b2df931d48
commit ff6bbafc50
6 changed files with 64 additions and 25 deletions

View File

@@ -10,7 +10,7 @@ use crate::movegen::move_generator::{
bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves, bishop_pseudo_moves, king_pseudo_moves, knight_pseudo_moves, pawn_pseudo_moves,
queen_pseudo_moves, rook_pseudo_moves, queen_pseudo_moves, rook_pseudo_moves,
}; };
use crate::movegen::r#move::{Move, Promote}; use crate::movegen::r#move::{Move, MoveType, Promote};
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct Board { pub struct Board {
@@ -120,6 +120,18 @@ impl Board {
moves moves
} }
pub fn pseudo_moves_all_captures(&self) -> Vec<Move> {
self.pseudo_moves_all()
.into_iter()
.filter(|m| {
matches!(
m.move_type,
MoveType::Capture | MoveType::PromotionCapture(_)
)
})
.collect()
}
pub fn pseudo_moves(&self, color: Color, piece_type: PieceType) -> Vec<Move> { pub fn pseudo_moves(&self, color: Color, piece_type: PieceType) -> Vec<Move> {
let all_occupancies = self.all_occupancies(); let all_occupancies = self.all_occupancies();
let (pieces, opponent_occupancies, own_occupancies) = match color { let (pieces, opponent_occupancies, own_occupancies) = match color {

View File

@@ -89,9 +89,13 @@ mod tests {
init_attacks(); init_attacks();
let mut game = from_fen(FEN)?; let mut game = from_fen(FEN)?;
let mut tt = TranspositionTable::new(1000000); let mut tt = TranspositionTable::new(1000000);
let mut nodes = 0;
let time_now = std::time::Instant::now();
// fill Transposition Table // fill Transposition Table
search::negamax::negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &mut tt); search::negamax::negamax(&mut game, MIN_SCORE, MAX_SCORE, 4, 0, &mut tt, &mut nodes);
dbg!(nodes);
dbg!(time_now.elapsed());
let will_be_hash = from_fen(FEN_WILL_BE)?.hash; let will_be_hash = from_fen(FEN_WILL_BE)?.hash;
let tt_entry = tt.lookup(will_be_hash); let tt_entry = tt.lookup(will_be_hash);

View File

@@ -150,6 +150,7 @@ pub fn uci_go(go: &mut SplitWhitespace, game: &mut Game) -> Result<Move, String>
params.depth.unwrap_or(MAX_DEPTH), params.depth.unwrap_or(MAX_DEPTH),
0, 0,
&mut tt, &mut tt,
&mut 0,
) )
.0 .0
.expect("No move selected")) .expect("No move selected"))

View File

@@ -9,6 +9,8 @@ use crate::{
use super::{move_ordering::score_by_mvv_lva, quiescence::quiescence}; use super::{move_ordering::score_by_mvv_lva, quiescence::quiescence};
const QUIESCENCE_DEPTH: u8 = 3;
pub fn negamax( pub fn negamax(
game: &mut Game, game: &mut Game,
mut alpha: i32, mut alpha: i32,
@@ -16,9 +18,13 @@ pub fn negamax(
depth: u8, depth: u8,
plies: u8, plies: u8,
tt: &mut TranspositionTable, tt: &mut TranspositionTable,
nodes: &mut u64,
) -> (Option<Move>, i32) { ) -> (Option<Move>, i32) {
*nodes += 1;
if depth == 0 { if depth == 0 {
return (None, quiescence(game, alpha, beta).1); let q = quiescence(game, alpha, beta, nodes, QUIESCENCE_DEPTH).1;
return (None, q);
} }
if let Some(entry) = tt.lookup(game.hash) { if let Some(entry) = tt.lookup(game.hash) {
@@ -44,9 +50,9 @@ pub fn negamax(
game.unmake_move(); game.unmake_move();
continue; continue;
} }
legal_moves += 1;
let move_score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, tt).1; legal_moves += 1;
let move_score = -negamax(game, -beta, -alpha, depth - 1, plies + 1, tt, nodes).1;
game.unmake_move(); game.unmake_move();
if move_score > best_score { if move_score > best_score {
@@ -117,9 +123,11 @@ mod tests {
let mut tt = TranspositionTable::new(1000000); let mut tt = TranspositionTable::new(1000000);
let e3f2 = Move::new(Square::E3, Square::F2); let e3f2 = Move::new(Square::E3, Square::F2);
let anointed_move = negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &mut tt) let mut nodes = 0;
let anointed_move = negamax(&mut game, MIN_SCORE, MAX_SCORE, 2, 0, &mut tt, &mut nodes)
.0 .0
.unwrap(); .unwrap();
dbg!(nodes);
assert_eq!(e3f2, anointed_move); assert_eq!(e3f2, anointed_move);

View File

@@ -73,13 +73,30 @@ mod tests {
fn perft(fen: &str, depth: u8) -> Result<u64, String> { fn perft(fen: &str, depth: u8) -> Result<u64, String> {
init_attacks(); init_attacks();
let time_now = std::time::Instant::now();
let mut game = from_fen(fen)?; let mut game = from_fen(fen)?;
let mut nodes = 0; let mut nodes = 0;
driver(&mut game, &mut nodes, depth); driver(&mut game, &mut nodes, depth);
dbg!(time_now.elapsed());
Ok(nodes) Ok(nodes)
} }
const FEN: &str = "1r2k2r/2P1pq1p/2npb3/1p3ppP/p3P3/P2B1Q2/1P1PNPP1/R3K2R w KQk g6 0 1";
#[ignore]
#[test]
fn test_nodes() -> Result<(), String> {
init_attacks();
assert_eq!(perft(FEN, 6)?, 0);
Ok(())
}
#[test] #[test]
fn test_perft_1() -> Result<(), String> { fn test_perft_1() -> Result<(), String> {
init_attacks(); init_attacks();

View File

@@ -1,12 +1,20 @@
use crate::{ use crate::{board::game::Game, evaluation::evaluation::evaluate_position, movegen::r#move::Move};
board::game::Game,
evaluation::evaluation::evaluate_position,
movegen::r#move::{Move, MoveType},
};
use super::move_ordering::score_by_mvv_lva; use super::move_ordering::score_by_mvv_lva;
pub fn quiescence(game: &mut Game, mut alpha: i32, beta: i32) -> (Option<Move>, i32) { pub fn quiescence(
game: &mut Game,
mut alpha: i32,
beta: i32,
nodes: &mut u64,
depth: u8,
) -> (Option<Move>, i32) {
*nodes += 1;
if depth == 0 {
return (None, evaluate_position(&game.board));
}
let color = game.current_player(); let color = game.current_player();
let stand_pat = evaluate_position(&game.board); let stand_pat = evaluate_position(&game.board);
@@ -18,18 +26,7 @@ pub fn quiescence(game: &mut Game, mut alpha: i32, beta: i32) -> (Option<Move>,
alpha = stand_pat; alpha = stand_pat;
} }
let mut captures: Vec<_> = game let mut captures: Vec<_> = game.board.pseudo_moves_all_captures();
.board
.pseudo_moves_all()
.into_iter()
.filter(|m| {
matches!(
m.move_type,
MoveType::Capture | MoveType::PromotionCapture(_)
)
})
.collect();
captures.sort_unstable_by_key(|mv| score_by_mvv_lva(&game.mailbox, *mv)); captures.sort_unstable_by_key(|mv| score_by_mvv_lva(&game.mailbox, *mv));
for mv in captures { for mv in captures {
@@ -40,7 +37,7 @@ pub fn quiescence(game: &mut Game, mut alpha: i32, beta: i32) -> (Option<Move>,
continue; continue;
} }
let move_score = -quiescence(game, -beta, -alpha).1; let move_score = -quiescence(game, -beta, -alpha, nodes, depth - 1).1;
game.unmake_move(); game.unmake_move();
if move_score >= beta { if move_score >= beta {