// uci.rs use crate::position::Position; use crate::types::{Move, Square, PieceType}; use crate::search::Searcher; use crate::timeman::TimeManager; use crate::perft::divide; pub fn handle_command(line: &str, pos: &mut Position, searcher: &mut Searcher) { let tokens: Vec<&str> = line.split_whitespace().collect(); if tokens.is_empty() { return; } match tokens[0] { "uci" => { println!("id name VeloCT Ultimate"); println!("id author Vasireddy Tejdeep"); println!("uciok"); } "isready" => { println!("readyok"); } "ucinewgame" => { searcher.tt.clear(); pos.set_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); } "position" => { if tokens.len() > 1 && tokens[1] == "startpos" { pos.set_fen("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"); if let Some(idx) = tokens.iter().position(|&x| x == "moves") { parse_and_do_moves(pos, &tokens[idx+1..]); } } else if tokens.len() > 1 && tokens[1] == "fen" { let fen_end = tokens.iter().position(|&x| x == "moves").unwrap_or(tokens.len()); if fen_end > 2 { let fen_parts = tokens[2..fen_end].join(" "); pos.set_fen(&fen_parts); } if fen_end < tokens.len() { parse_and_do_moves(pos, &tokens[fen_end+1..]); } } } "go" => { let mut wtime = 300000; let mut btime = 300000; let mut winc = 0; let mut binc = 0; let mut depth = 6; let mut i = 1; while i < tokens.len() { match tokens[i] { "wtime" => if let Ok(v) = tokens[i+1].parse() { wtime = v; i += 1; }, "btime" => if let Ok(v) = tokens[i+1].parse() { btime = v; i += 1; }, "winc" => if let Ok(v) = tokens[i+1].parse() { winc = v; i += 1; }, "binc" => if let Ok(v) = tokens[i+1].parse() { binc = v; i += 1; }, "depth" => if let Ok(v) = tokens[i+1].parse() { depth = v; i += 1; }, "perft" => { if let Ok(v) = tokens[i+1].parse() { divide(pos, v); return; } } _ => {} } i += 1; } let mut tm = TimeManager::new(wtime, btime, winc, binc, pos.side_to_move); let best = searcher.search_best(pos, &mut tm, depth); if best != Move::NONE { println!("bestmove {}{}{}", sq_to_str(best.from()), sq_to_str(best.to()), promo_to_str(best.promotion())); } else { println!("bestmove 0000"); } } _ => {} } } fn parse_and_do_moves(pos: &mut Position, moves: &[&str]) { for m_str in moves { if m_str.len() < 4 { continue; } let f_file = (m_str.as_bytes()[0] - b'a') as u8; let f_rank = (m_str.as_bytes()[1] - b'1') as u8; let t_file = (m_str.as_bytes()[2] - b'a') as u8; let t_rank = (m_str.as_bytes()[3] - b'1') as u8; let from = Square::from_u8(f_rank * 8 + f_file); let to = Square::from_u8(t_rank * 8 + t_file); let mut promo = PieceType::None; if m_str.len() == 5 { promo = match m_str.as_bytes()[4] { b'q' => PieceType::Queen, b'r' => PieceType::Rook, b'b' => PieceType::Bishop, b'n' => PieceType::Knight, _ => PieceType::None, }; } let target_move = Move::new(from, to, promo); let mut pseudo_legal = Vec::new(); crate::movegen::generate_moves(pos, &mut pseudo_legal); for m in pseudo_legal { if m.from() == target_move.from() && m.to() == target_move.to() && m.promotion() == target_move.promotion() { pos.do_move(m); break; } } } } pub fn sq_to_str(sq: Square) -> String { if sq == Square::None { return "-".to_string(); } let f = (sq as u8) % 8; let r = (sq as u8) / 8; format!("{}{}", (b'a' + f) as char, (b'1' + r) as char) } fn promo_to_str(p: PieceType) -> &'static str { match p { PieceType::Queen => "q", PieceType::Rook => "r", PieceType::Bishop => "b", PieceType::Knight => "n", _ => "", } }