Nicolas Winkler 3 gadi atpakaļ
vecāks
revīzija
f866bea60c
3 mainītis faili ar 59 papildinājumiem un 30 dzēšanām
  1. 20 9
      src/engine.rs
  2. 5 6
      src/interface.rs
  3. 34 15
      src/search.rs

+ 20 - 9
src/engine.rs

@@ -2,10 +2,10 @@ use search::apply_move;
 use bitboard::Bitboard;
 use game::Game;
 use search::*;
-use std::io::Write;
 use movegen::*;
 use log::{info};
 use std::time::{Duration, Instant};
+use std::collections::VecDeque;
 
 
 
@@ -35,14 +35,20 @@ pub enum InterfaceMsg {
 }
 
 
+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 {
-        //game.pieces[0] = 0x00ff_0000_0000_0100;
-        //game.pieces[QUEEN as usize] = 0x0000_0000_0000_0080;
-        //game.pieces[10] = 0x4000_0000_0000_0000;
-
-        let msg = r.recv().unwrap();
+        let msg = dequeue_message(&mut messages, &r).unwrap();
 
         match msg {
             EngineMsg::SetBoard(g) => {
@@ -54,14 +60,19 @@ pub fn run_engine(r: Receiver<EngineMsg>, s: Sender<InterfaceMsg>) {
                 //info!("searching in pos\n {}", game.beautiful_print());
                 //println!("Search {}", depth);
 
-                let check_fn = || -> bool {
+                let mut check_fn = || -> bool {
                     if let Ok(msg) = r.try_recv() {
-                        return true;
+                        if let EngineMsg::Stop = msg {
+                            return true;
+                        }
+                        else {
+                            messages.push_back(msg);
+                        }
                     }
                     return false;
                 };
 
-                let mut sc = SearchControl{ nodes: 0, check: &check_fn };
+                let mut sc = SearchControl{ nodes: 0, check: &mut check_fn };
 
                 let before = Instant::now();
                 let best_move = search(&game, &mut sc, depth);

+ 5 - 6
src/interface.rs

@@ -8,12 +8,6 @@ use std::process::exit;
 use engine::{EngineMsg, InterfaceMsg};
 use game::{Game};
 
-use std::fs::File;
-use std::io::Write;
-use std::sync::Mutex;
-use std::cell::RefCell;
-use std::sync::Arc;
-
 use std::thread::sleep_ms;
 use log::info;
 
@@ -42,6 +36,7 @@ fn run_command(mut cmd: Vec<&str>, r: &Receiver<InterfaceMsg>, s: &Sender<Engine
             "isready" => cmd_isready(cmd),
             "position" => cmd_position(cmd, r, s),
             "go" => cmd_go(cmd, r, s),
+            "stop" => cmd_stop(cmd, r, s),
             "ucinewgame" => cmd_newgame(cmd, r, s),
             "quit" | "exit" => cmd_quit(cmd, r, s),
             cmd => { println!("unknown command: {}", cmd); }
@@ -89,6 +84,10 @@ fn cmd_go(_args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>)
     s.send(EngineMsg::Search(4)).unwrap();
 }
 
+fn cmd_stop(_args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {
+    s.send(EngineMsg::Stop).unwrap();
+}
+
 fn cmd_newgame(_args: Vec<&str>, _r: &Receiver<InterfaceMsg>, s: &Sender<EngineMsg>) {
     s.send(EngineMsg::NewGame).unwrap();
 }

+ 34 - 15
src/search.rs

@@ -23,7 +23,7 @@ enum MoveUndo {
 
 pub struct SearchControl<'a> {
     pub nodes: usize,
-    pub check: &'a dyn Fn() -> bool,
+    pub check: &'a mut dyn FnMut() -> bool,
 }
 
 
@@ -56,10 +56,17 @@ pub fn search(game: &Game, sc: &mut SearchControl, depth: i32) -> Move {
     // determine possibly multiple good moves
     const ALPHA_OFFSET: i32 = 50;
 
-    let mut valued_moves = moves.iter().map(|mov| {
-        let new_game = apply_move(game, *mov);
+    let mut valued_moves: Vec<(Move, i32)> = Vec::with_capacity(moves.len());
+    for mov in moves {
+        let new_game = apply_move(game, mov);
         //info!("searching {}", mov.to_string());
-        let val = -negamax(&new_game, sc, -beta, -alpha, depth - 1);
+        let (mut val, ret) = negamax(&new_game, sc, -beta, -alpha, depth - 1);
+        val = -val;
+
+        if ret {
+            return Move::default();
+        }
+
         info!("searched {} -> {}", mov.to_string(), val);
 
         if val > alpha {
@@ -67,8 +74,9 @@ pub fn search(game: &Game, sc: &mut SearchControl, depth: i32) -> Move {
             //info!("updated alpha to {}", alpha);
         }
 
-        (*mov, -val)
-    }).collect::<Vec<(Move, i32)>>();
+        valued_moves.push((mov, -val));
+    }
+
     //info!("movvalues: {:?}", valued_moves.iter().map(|mv| mv.0.to_string() + " - " + &mv.1.to_string()).collect::<Vec<String>>());
 
     valued_moves.sort_by_key(|mv| mv.1);
@@ -87,43 +95,54 @@ pub fn search(game: &Game, sc: &mut SearchControl, depth: i32) -> Move {
     }
 }
 
-fn negamax(game: &Game, sc: &mut SearchControl, mut alpha: i32, beta: i32, depth: i32) -> i32 {
+fn negamax(game: &Game, sc: &mut SearchControl, mut alpha: i32, beta: i32, depth: i32) -> (i32, bool) {
     if depth == 0 {
-        return quiescence_search(game, sc, alpha, beta, 7);
+        return (quiescence_search(game, sc, alpha, beta, 7), false);
         let eval = evaluate(game);
         if eval != 0 {
             //info!("eval: {}", eval);
         }
-        return eval;
+        //return eval;
     }
 
     const MIN_VALUE: i32 = i32::min_value() + 1;
 
     sc.nodes += 1;
+    if sc.nodes % 128 == 0 {
+        if (sc.check)() {
+            return (0, true);
+        }
+    }
 
     let mut best = MIN_VALUE;
     //let mut best_move = Move::default();
     //info!(" -> generate_legal_moves");
 
-    if game.get_piece(KING, game.turn) == 0 { return MIN_VALUE; }
+    if game.get_piece(KING, game.turn) == 0 { return (MIN_VALUE, false); }
 
     let moves = generate_legal_moves(game, game.turn);
 
     if moves.len() == 0 {
         if is_check(game, game.turn) {
             // mate
-            return MIN_VALUE;
+            return (MIN_VALUE, false);
         }
         else {
             // stalemate
-            return 0;
+            return (0, false);
         }
     }
     for mov in moves {
         let new_game = apply_move(game, mov);
-        let val = -negamax(&new_game, sc, -beta, -alpha, depth - 1);
+        let (mut val, ret) = negamax(&new_game, sc, -beta, -alpha, depth - 1);
+        val = -val;
+
+        if ret {
+            return (alpha, ret)
+        }
+
         if val >= beta {
-            return beta;
+            return (beta, false);
         }
         if val > alpha {
             alpha = (val as f64 * 0.95) as i32;
@@ -136,7 +155,7 @@ fn negamax(game: &Game, sc: &mut SearchControl, mut alpha: i32, beta: i32, depth
         }
     }
     //info!("best alpha {}", best);
-    return (best as f64 * 0.99) as i32;
+    return ((best as f64 * 0.99) as i32, false);
 }
 
 fn quiescence_search(game: &Game, si: &mut SearchControl, mut alpha: i32, beta: i32, depth: i32) -> i32 {