Nicolas Winkler 3 jaren geleden
bovenliggende
commit
9c5e4d4a2d
4 gewijzigde bestanden met toevoegingen van 195 en 40 verwijderingen
  1. 187 33
      src/engine.rs
  2. 3 4
      src/interface.rs
  3. 3 1
      src/main.rs
  4. 2 2
      src/movegen.rs

+ 187 - 33
src/engine.rs

@@ -7,14 +7,13 @@ use log::{info};
 use std::time::{Duration, Instant};
 use std::collections::VecDeque;
 
-
-
+use std::thread::sleep_ms;
 use std::sync::mpsc::{Receiver, Sender};
 
 pub enum EngineMsg {
     SetBoard(Game),
     SetPiece(Bitboard),
-    Search(i32),
+    Search(SearchInfo),
     Ping,
     Stop,
     NewGame,
@@ -22,19 +21,136 @@ pub enum EngineMsg {
     GetInfo,
 }
 
+pub enum SearchInfo {
+    Depth(isize),
+    Movetime(isize),
+    Time {
+        wtime: isize,
+        btime: isize,
+        winc: isize,
+        binc: isize,
+        movestogo: isize
+    },
+    Infinite,
 
-pub enum EngineState {
-    Idle,
-    Searching
 }
 
-
 pub enum InterfaceMsg {
-    BestMove(Move),
-    State(EngineState)
 }
 
 
+pub struct Engine {
+    game: Game,
+    messages: VecDeque<EngineMsg>,
+    r: Receiver<EngineMsg>,
+    s: Sender<InterfaceMsg>
+}
+
+impl Engine {
+    pub fn new(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) -> Self {
+        Engine {
+            game: Game::default(),
+            messages: VecDeque::new(),
+            r, s
+        }
+    }
+
+    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 best_move = search(&self.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 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();
+                loop {
+                    let bm = search(&mut self.game, &mut sc, depth as i32);
+                    if bm != Move::default() {
+                        best_move = bm;
+                    }
+                    else {
+                        break;
+                    }
+                    depth += 1;
+                }
+
+                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()
@@ -44,7 +160,7 @@ fn dequeue_message(queue: &mut VecDeque<EngineMsg>, r: &Receiver<EngineMsg>) ->
     }
 }
 
-pub fn run_engine(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) {
+pub fn run_engine(r: Receiver<EngineMsg>, _s: Sender<InterfaceMsg>) {
     let mut game = Game::default();
     let mut messages: VecDeque<EngineMsg> = VecDeque::new();
     loop {
@@ -52,34 +168,71 @@ pub fn run_engine(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) {
 
         match msg {
             EngineMsg::SetBoard(g) => {
-                //println!("SetBoard");
                 game = g;
             },
             EngineMsg::SetPiece(_) => { println!("SetPiece") },
-            EngineMsg::Search(depth) => {
-                //info!("searching in pos\n {}", game.beautiful_print());
-                //println!("Search {}", depth);
-
-                let mut check_fn = || -> bool {
-                    if let Ok(msg) = r.try_recv() {
-                        if let EngineMsg::Stop = msg {
-                            return true;
+            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;
                         }
-                        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);
-                let time = before.elapsed();
-                println!("bestmove {}", best_move.to_string());
-                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!("bestmove {}", best_move.to_string());
+                    },
+                    _ => {}
+                }
             },
             EngineMsg::Ping => { println!("Ping") },
             EngineMsg::Stop => { println!("Stop") },
@@ -96,3 +249,4 @@ pub fn run_engine(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) {
     }
 }
 
+*/

+ 3 - 4
src/interface.rs

@@ -5,7 +5,7 @@ use std::sync::mpsc::{Receiver, Sender};
 
 use std::process::exit;
 
-use engine::{EngineMsg, InterfaceMsg};
+use engine::{EngineMsg, InterfaceMsg, SearchInfo};
 use game::{Game};
 
 use std::thread::sleep_ms;
@@ -24,7 +24,6 @@ pub fn run(r: Receiver<InterfaceMsg>, s: Sender<EngineMsg>) {
         let split = line.split_whitespace().collect::<Vec<&str>>();
         run_command(split, &r, &s);
     }
-    sleep_ms(2000);
 }
 
 fn run_command(mut cmd: Vec<&str>, r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {
@@ -80,8 +79,8 @@ fn cmd_position(mut args: Vec<&str>, r: &Receiver<InterfaceMsg>, s: &Sender<Engi
     s.send(EngineMsg::SetBoard(game)).unwrap();
 }
 
-fn cmd_go(_args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {
-    s.send(EngineMsg::Search(4)).unwrap();
+fn cmd_go(args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {
+    s.send(EngineMsg::Search(SearchInfo::Movetime(1000))).unwrap();
 }
 
 fn cmd_stop(_args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {

+ 3 - 1
src/main.rs

@@ -15,6 +15,7 @@ use simplelog::*;
 use std::sync::mpsc;
 use std::{thread, fs::File};
 use log::*;
+use engine::Engine;
 
 fn main() {
     /*let mut builder = Builder::from_default_env();
@@ -33,7 +34,8 @@ fn main() {
 
     // spawn engine thread
     thread::spawn(move || {
-        engine::run_engine(erecv, isend);
+        let mut engine = Engine::new(erecv, isend);
+        engine.run();
     });
 
     interface::run(irecv, esend);

+ 2 - 2
src/movegen.rs

@@ -19,13 +19,13 @@ pub const ROOK: PieceType = 3;
 pub const QUEEN: PieceType = 4;
 pub const KING: PieceType = 5;
 
-#[derive(Copy, Clone, Debug)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct SimpleMove {
     pub from: Square,
     pub to: Square,
 }
 
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum Move {
     Default { mov: SimpleMove, piece_type: PieceType },
     Castling { side: Side, left: bool },