send uci info
This commit is contained in:
parent
d5b679b6bf
commit
711569b8e5
8 changed files with 118 additions and 59 deletions
|
|
@ -1,5 +1,5 @@
|
|||
use chess_engine::board::Board;
|
||||
use chess_engine::movegen::picker::MoveGenerator;
|
||||
use chess_engine::movegen::picker::MovePicker;
|
||||
use chess_engine::movegen::legal_check::is_other_king_attacked;
|
||||
use criterion::{criterion_group, criterion_main, Criterion};
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ fn count_legal_moves_recursive(board: &mut Board, depth: u8) -> u64 {
|
|||
return 1_u64;
|
||||
}
|
||||
|
||||
let mut generator = MoveGenerator::new();
|
||||
let mut generator = MovePicker::new();
|
||||
let mut leaf_nodes = 0_u64;
|
||||
|
||||
while let Some(mv) = generator.next(board) {
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ def main():
|
|||
|
||||
try:
|
||||
# The suite_score is still a raw float, e.g., 95.5
|
||||
suite_score = float(suite_result.stdout.strip())
|
||||
suite_score = float(suite_result.stdout.strip().splitlines()[-1].strip())
|
||||
except ValueError:
|
||||
print(f"Error: Could not convert suite output to a number.")
|
||||
print(f"Received: '{suite_result.stdout}'")
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::r#move::Move;
|
|||
use crate::search::alpha_beta;
|
||||
use crate::tt::TranspositionTable; // Import TT
|
||||
use std::time::{Instant, Duration};
|
||||
use crate::uci::UCI;
|
||||
|
||||
pub struct Engine {
|
||||
pub name: String,
|
||||
|
|
@ -44,6 +45,7 @@ impl Engine {
|
|||
|
||||
let mut nodes = 0;
|
||||
|
||||
// Initial search at depth 1
|
||||
let (mut opt_move, mut _score) = alpha_beta(
|
||||
&mut self.board,
|
||||
1,
|
||||
|
|
@ -56,8 +58,12 @@ impl Engine {
|
|||
&mut self.tt
|
||||
);
|
||||
|
||||
// If we timed out immediately at depth 1 (very rare), opt_move might be None.
|
||||
// But usually, we have at least one move here.
|
||||
|
||||
let mut depth = 2;
|
||||
|
||||
// Iterative Deepening
|
||||
while start_time.elapsed() < time_limit {
|
||||
let (new_move, new_score) = alpha_beta(
|
||||
&mut self.board,
|
||||
|
|
@ -71,19 +77,27 @@ impl Engine {
|
|||
&mut self.tt
|
||||
);
|
||||
|
||||
if start_time.elapsed() > time_limit {
|
||||
// FIX: Only update if we actually got a move back (didn't timeout)
|
||||
if let Some(mv) = new_move {
|
||||
opt_move = Some(mv);
|
||||
_score = new_score;
|
||||
|
||||
// Optional: Move send_info here to update the GUI after every completed depth
|
||||
UCI::send_info(Some(depth as usize), Some(nodes), None, None, None, None);
|
||||
} else {
|
||||
// If new_move is None, the search was aborted due to time.
|
||||
// We discard the partial results and stop increasing depth.
|
||||
break;
|
||||
}
|
||||
|
||||
opt_move = new_move;
|
||||
_score = new_score;
|
||||
|
||||
depth += 1;
|
||||
}
|
||||
|
||||
if let Some(mv) = opt_move {
|
||||
mv.to_algebraic()
|
||||
} else {
|
||||
// Fallback: If even depth 1 failed (e.g. 0ms time limit), try to return *any* legal move
|
||||
// or just return null if truly nothing works.
|
||||
"null".to_string()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use chess_engine::engine::Engine;
|
||||
use chess_engine::uci::uci_mainloop;
|
||||
use chess_engine::uci::UCI;
|
||||
|
||||
fn main() {
|
||||
let mut engine = Engine::new("Yakari".to_string(), "EiSiMo".to_string());
|
||||
uci_mainloop(&mut engine);
|
||||
let mut uci = UCI { engine };
|
||||
uci.uci_mainloop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::board::Board;
|
||||
use crate::movegen::non_sliders::{generate_king_moves, generate_knight_moves};
|
||||
use crate::movegen::pawns::generate_pawn_moves;
|
||||
use crate::movegen::non_sliders::*;
|
||||
use crate::movegen::pawns::*;
|
||||
use crate::movegen::sliders::*;
|
||||
use crate::r#move::{Move, MoveList};
|
||||
|
||||
|
|
@ -30,12 +30,12 @@ impl GenStage {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct MoveGenerator {
|
||||
pub struct MovePicker {
|
||||
buffer: MoveList,
|
||||
stage: GenStage,
|
||||
}
|
||||
|
||||
impl MoveGenerator {
|
||||
impl MovePicker {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
buffer: MoveList::new(),
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use crate::board::{Board, Color};
|
|||
use crate::eval::evaluate_board;
|
||||
use crate::movegen::legal_check::*;
|
||||
use crate::r#move::Move;
|
||||
use crate::movegen::picker::MoveGenerator;
|
||||
use crate::movegen::picker::MovePicker;
|
||||
use crate::tt::{TranspositionTable, NodeType};
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
|
|
@ -90,7 +90,7 @@ pub fn alpha_beta(
|
|||
let mut legal_moves_found = false;
|
||||
let alpha_orig = alpha;
|
||||
|
||||
let mut picker = MoveGenerator::new();
|
||||
let mut picker = MovePicker::new();
|
||||
let mut moves_tried = 0;
|
||||
|
||||
loop {
|
||||
|
|
|
|||
58
src/uci.rs
58
src/uci.rs
|
|
@ -1,7 +1,13 @@
|
|||
use std::io::{self, BufRead};
|
||||
use crate::engine::Engine;
|
||||
|
||||
pub fn uci_mainloop(engine: &mut Engine) {
|
||||
pub struct UCI {
|
||||
// TODO lifetime specifier
|
||||
pub engine: Engine,
|
||||
}
|
||||
|
||||
impl UCI {
|
||||
pub fn uci_mainloop(&mut self) {
|
||||
loop {
|
||||
for line in io::stdin().lock().lines() {
|
||||
let input = line.unwrap_or_else(|_| "quit".to_string());
|
||||
|
|
@ -13,8 +19,8 @@ pub fn uci_mainloop(engine: &mut Engine) {
|
|||
|
||||
match tokens[0] {
|
||||
"uci" => {
|
||||
println!("id name {}", engine.name);
|
||||
println!("id author {}", engine.author);
|
||||
println!("id name {}", self.engine.name);
|
||||
println!("id author {}", self.engine.author);
|
||||
println!("uciok");
|
||||
}
|
||||
"isready" => {
|
||||
|
|
@ -27,18 +33,18 @@ pub fn uci_mainloop(engine: &mut Engine) {
|
|||
if tokens.len() > 1 {
|
||||
if tokens[1] == "fen" {
|
||||
let fen = tokens[2..].join(" ");
|
||||
engine.setpos_fen(&fen);
|
||||
self.engine.setpos_fen(&fen);
|
||||
} else if tokens[1] == "startpos" {
|
||||
if tokens.len() > 2 && tokens[2] == "moves" {
|
||||
engine.setpos_startpos(&tokens[3..]);
|
||||
self.engine.setpos_startpos(&tokens[3..]);
|
||||
} else {
|
||||
engine.setpos_startpos(&[]);
|
||||
self.engine.setpos_startpos(&[]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"go" => {
|
||||
println!("bestmove {}", engine.search(1000_u64));
|
||||
println!("bestmove {}", self.engine.search(1000_u64));
|
||||
}
|
||||
"stop" => {
|
||||
// TODO stop search as soon as possible
|
||||
|
|
@ -52,4 +58,42 @@ pub fn uci_mainloop(engine: &mut Engine) {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_info(
|
||||
depth: Option<usize>,
|
||||
nodes: Option<u64>,
|
||||
time: Option<u64>,
|
||||
nps: Option<u64>,
|
||||
score_cp: Option<i32>,
|
||||
pv: Option<&str>
|
||||
) {
|
||||
let mut output = String::from("info");
|
||||
|
||||
if let Some(d) = depth {
|
||||
output.push_str(&format!(" depth {}", d));
|
||||
}
|
||||
|
||||
if let Some(s) = score_cp {
|
||||
output.push_str(&format!(" score cp {}", s));
|
||||
}
|
||||
|
||||
if let Some(n) = nodes {
|
||||
output.push_str(&format!(" nodes {}", n));
|
||||
}
|
||||
|
||||
if let Some(n) = nps {
|
||||
output.push_str(&format!(" nps {}", n));
|
||||
}
|
||||
|
||||
if let Some(t) = time {
|
||||
output.push_str(&format!(" time {}", t));
|
||||
}
|
||||
|
||||
if let Some(p) = pv {
|
||||
output.push_str(&format!(" pv {}", p));
|
||||
}
|
||||
|
||||
println!("{}", output);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
use chess_engine::board::Board;
|
||||
use chess_engine::movegen::legal_check::is_other_king_attacked;
|
||||
use chess_engine::movegen::picker::MoveGenerator;
|
||||
use chess_engine::movegen::picker::MovePicker;
|
||||
|
||||
fn count_legal_moves_recursive(board: &mut Board, depth: u8) -> u64 {
|
||||
if depth == 0 {
|
||||
return 1_u64;
|
||||
}
|
||||
|
||||
let mut generator = MoveGenerator::new();
|
||||
let mut generator = MovePicker::new();
|
||||
let mut leaf_nodes = 0_u64;
|
||||
|
||||
while let Some(mv) = generator.next(board) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue