123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- use search::apply_move;
- use bitboard::Bitboard;
- use game::Game;
- use search::*;
- use movegen::*;
- use evaluate::PosValue;
- use log::{info};
- use std::time::{Duration, Instant};
- use std::collections::{VecDeque, HashMap};
- use zobrist::ZobristTable;
- use hash::Cache;
- use std::thread::sleep_ms;
- use std::sync::mpsc::{Receiver, Sender};
- pub enum EngineMsg {
- SetBoard(Game),
- SetPiece(Bitboard),
- Search(SearchInfo),
- Ping,
- Stop,
- NewGame,
- GetState,
- GetInfo,
- }
- pub enum SearchInfo {
- Depth(isize),
- Movetime(isize),
- Time {
- wtime: isize,
- btime: isize,
- winc: isize,
- binc: isize,
- movestogo: isize
- },
- Infinite,
- }
- pub enum InterfaceMsg {
- }
- pub struct Engine {
- game: Game,
- messages: VecDeque<EngineMsg>,
- r: Receiver<EngineMsg>,
- s: Sender<InterfaceMsg>,
- hash: Cache,
- zobrist_table: ZobristTable
- }
- impl Engine {
- pub fn new(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) -> Self {
- let mut eng = Engine {
- game: Game::default(),
- messages: VecDeque::new(),
- r, s,
- hash: Cache::new(),
- zobrist_table: ZobristTable::new()
- };
- eng.game.zobrist = Some(eng.game.calculate_zobrist(&eng.zobrist_table));
- eng
- }
- pub fn run(&mut self) {
- while let Some(msg) = self.dequeue_message() {
- match msg {
- EngineMsg::SetBoard(g) => {
- self.game = g;
- },
- EngineMsg::Search(ref info) => {
- self.start_search(info);
- }
- _ => {}
- }
- }
- }
- /**
- * blocks until a message is available
- */
- fn dequeue_message(&mut self) -> Option<EngineMsg> {
- if self.messages.is_empty() {
- self.r.recv().ok()
- }
- else {
- self.messages.pop_front()
- }
- }
- fn start_search(&mut self, si: &SearchInfo) {
- match si {
- SearchInfo::Depth(depth) => {
- let receiver = &mut self.r;
- let messages = &mut self.messages;
- let mut check_fn = || -> bool {
- if let Ok(msg) = receiver.try_recv() {
- if let EngineMsg::Stop = msg {
- return true;
- }
- else {
- messages.push_back(msg);
- }
- }
- return false;
- };
- let mut sc = SearchControl{ nodes: 0, check: &mut check_fn };
- let before = Instant::now();
- let search_result = search(&self.game, &mut sc, &mut self.hash, *depth as i32);
- if let SearchResult::Finished(best_move, best_val) = search_result {
- let time = before.elapsed();
- let nps = (sc.nodes as f64 / time.as_millis() as f64 * 1000.0) as i64;
- info!("bestmove {}", best_move.to_string());
- info!("searched {} nodes in {} ms ({} nodes/s)", sc.nodes, time.as_millis(), (sc.nodes as f64 / time.as_millis() as f64 * 1000.0) as i64);
-
- println!("info nps {}", nps.to_string());
- println!("bestmove {}", best_move.to_string());
- }
- },
- SearchInfo::Movetime(millis) => {
- let before = Instant::now();
- let mut depth = 1;
- let receiver = &mut self.r;
- let messages = &mut self.messages;
- let mut check_fn = || -> bool {
- if let Ok(msg) = receiver.try_recv() {
- if let EngineMsg::Stop = msg {
- return true;
- }
- else {
- messages.push_back(msg);
- }
- }
- if before.elapsed() > Duration::from_millis(*millis as _) {
- return true;
- }
- return false;
- };
- let mut sc = SearchControl{ nodes: 0, check: &mut check_fn };
- let mut best_move = Move::default();
- let mut best_val: PosValue = i32::max_value() as _;
- loop {
- let search_result = search(&mut self.game, &mut sc, &mut self.hash, depth as i32);
- if let SearchResult::Finished(bm, bv) = search_result {
- info!("depth: {} bm: {}, bv: {}", depth, bm.to_string(), bv);
- best_move = bm;
- best_val = bv;
-
- let elapsed = before.elapsed();
- let nodes = sc.nodes;
- let nps = (nodes as f64 / elapsed.as_nanos() as f64 * 1000000000.0) as i64;
- let cp = best_val as i64;
- println!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, best_move.to_string());
- info!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, best_move.to_string());
- depth += 1;
- }
- else if let SearchResult::Mate(bm, in_turns) = search_result {
- best_move = bm;
- let elapsed = before.elapsed();
- let nodes = sc.nodes;
- let nps = (nodes as f64 / elapsed.as_nanos() as f64 * 1000000000.0) as i64;
- let pv = best_val as i64;
- println!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, in_turns, elapsed.as_millis(), nodes, nps, bm.to_string());
- info!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, pv, elapsed.as_millis(), nodes, nps, bm.to_string());
- break;
- }
- else {
- break;
- }
- }
- info!("bestmove {}", best_move.to_string());
- println!("bestmove {}", best_move.to_string());
- },
- _ => {}
- }
- }
- }
- /*
- fn dequeue_message(queue: &mut VecDeque<EngineMsg>, r: &Receiver<EngineMsg>) -> Option<EngineMsg> {
- if queue.is_empty() {
- r.recv().ok()
- }
- else {
- queue.pop_front()
- }
- }
- pub fn run_engine(r: Receiver<EngineMsg>, _s: Sender<InterfaceMsg>) {
- let mut game = Game::default();
- let mut messages: VecDeque<EngineMsg> = VecDeque::new();
- loop {
- let msg = dequeue_message(&mut messages, &r).unwrap();
- match msg {
- EngineMsg::SetBoard(g) => {
- game = g;
- },
- EngineMsg::SetPiece(_) => { println!("SetPiece") },
- EngineMsg::Search(info) => {
- match info {
- SearchInfo::Depth(depth) => {
- let mut check_fn = || -> bool {
- if let Ok(msg) = r.try_recv() {
- if let EngineMsg::Stop = msg {
- return true;
- }
- else {
- messages.push_back(msg);
- }
- }
- return false;
- };
- let mut sc = SearchControl{ nodes: 0, check: &mut check_fn };
- let before = Instant::now();
- let best_move = search(&game, &mut sc, depth as i32);
- let time = before.elapsed();
- let nps = (sc.nodes as f64 / time.as_millis() as f64 * 1000.0) as i64;
- info!("bestmove {}", best_move.to_string());
- info!("searched {} nodes in {} ms ({} nodes/s)", sc.nodes, time.as_millis(), (sc.nodes as f64 / time.as_millis() as f64 * 1000.0) as i64);
- println!("info nps {}", nps.to_string());
- println!("bestmove {}", best_move.to_string());
- },
- SearchInfo::Movetime(millis) => {
- let before = Instant::now();
- let mut depth = 1;
- let mut check_fn = || -> bool {
- if let Ok(msg) = r.try_recv() {
- if let EngineMsg::Stop = msg {
- return true;
- }
- else {
- messages.push_back(msg);
- }
- }
- if before.elapsed() > Duration::from_millis(millis as _) {
- return true;
- }
- return false;
- };
- let mut sc = SearchControl{ nodes: 0, check: &mut check_fn };
- let mut best_move = Move::default();
- loop {
- let bm = search(&game, &mut sc, depth as i32);
- if bm != Move::default() {
- best_move = bm;
- }
- else {
- break;
- }
- depth += 1;
- }
- println!("bestmove {}", best_move.to_string());
- },
- _ => {}
- }
- },
- EngineMsg::Ping => { println!("Ping") },
- EngineMsg::Stop => { println!("Stop") },
- EngineMsg::NewGame => {
- //println!("NewGame")
- },
- EngineMsg::GetState => { println!("GetState") },
- EngineMsg::GetInfo => { println!("GetInfo") },
- }
- //println!("{}", game.beautiful_print());
- //let moves = generate_moves(&game, WHITE);
- }
- }
- */
|