Add depth limit on quiescence, add node/timer measurements
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user