Nicolas Winkler 3 年之前
父节点
当前提交
0893d9470f
共有 6 个文件被更改,包括 44 次插入16 次删除
  1. 8 5
      src/engine.rs
  2. 2 2
      src/game.rs
  3. 6 5
      src/hash.rs
  4. 2 2
      src/main.rs
  5. 4 0
      src/movegen.rs
  6. 22 2
      src/search.rs

+ 8 - 5
src/engine.rs

@@ -196,7 +196,7 @@ impl Engine {
                 return false;
             };
 
-        let mut sc = SearchControl{ nodes: 0, check: &mut check_fn, move_history: &mut self.move_history, initial_depth: 0 };
+        let mut sc = SearchControl::new(&mut check_fn, &mut self.move_history, 0);
         let mut best_move = Move::default();
         let mut best_val: PosValue;
 
@@ -220,6 +220,7 @@ impl Engine {
         loop {
 
             sc.initial_depth = depth;
+            sc.pv = vec![Move::Nullmove; depth as _];
 
             let search_result = search(&mut self.game, &mut sc, &mut self.hash, alpha, beta, depth as i32);
 
@@ -244,15 +245,17 @@ impl Engine {
                 let nodes = sc.nodes;
                 let nps = (nodes as f64 / elapsed.as_nanos() as f64 * 1000000000.0) as i64;
                 let cp = best_val as i64;
+                let pv = &sc.pv.iter().filter(|&m| !m.is_null()).map(|m| m.to_string()).fold(String::new(), |a, b| a + " " + &b)[1..];
+
                 if let Some(plies) = crate::evaluate::is_mate_in_p1(bv) {
                     let turns = plies / 2;
-                    println!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, best_move.to_string());
-                    info!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, best_move.to_string());
+                    println!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
+                    info!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
                     break;
                 }
                 else {
-                    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());
+                    println!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
+                    info!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
                 }
                 depth += 1;
             }

+ 2 - 2
src/game.rs

@@ -59,7 +59,7 @@ impl Default for Game {
     }
 }
 
-/*
+
 impl std::hash::Hash for Game {
     fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
         if let Some((ref _zt, ref zb)) = &self.zobrist {
@@ -79,7 +79,7 @@ impl PartialEq for Game {
 
 impl Eq for Game {
 }
-*/
+
 
 impl Game {
     pub fn empty() -> Game {

+ 6 - 5
src/hash.rs

@@ -15,7 +15,7 @@ pub enum EntryType {
 pub struct CacheEntry {
     pub entry_type: EntryType,
     pub depth: i32,
-    pub value: PosValue
+    pub value: PosValue,
 }
 
 impl CacheEntry {
@@ -23,7 +23,7 @@ impl CacheEntry {
         CacheEntry {
             entry_type: EntryType::Value,
             depth,
-            value
+            value,
         }
     }
 
@@ -31,7 +31,7 @@ impl CacheEntry {
         CacheEntry {
             entry_type: EntryType::UpperBound,
             depth,
-            value: beta
+            value: beta,
         }
     }
 
@@ -39,7 +39,7 @@ impl CacheEntry {
         CacheEntry {
             entry_type: EntryType::LowerBound,
             depth,
-            value: alpha
+            value: alpha,
         }
     }
 }
@@ -72,7 +72,8 @@ impl Cache {
             //self.hashmap.remove(&first_key);
             self.hashmap.clear();
         }
-        self.hashmap.insert(game_pos.zobrist.clone().unwrap().1, ce);
+        let key = game_pos.zobrist.as_ref().unwrap().1;
+        self.hashmap.insert(key, ce);
         if self.hashmap.len() % (1024 * 32) == 0 {
             info!("hash contains {} items", self.hashmap.len());
         }

+ 2 - 2
src/main.rs

@@ -39,8 +39,8 @@ fn main() {
         println!("t: {}", t);
     }*/
 
-    //let logfile = File::create("C:\\Users\\Nicolas\\debug.log").unwrap();
-    //simplelog::WriteLogger::init(LevelFilter::Info, Config::default(), logfile).unwrap();
+    let logfile = File::create("/home/nicolas/debug.log").unwrap();
+    simplelog::WriteLogger::init(LevelFilter::Info, Config::default(), logfile).unwrap();
 
     let (esend, erecv) = mpsc::channel();
     let (isend, irecv) = mpsc::channel();

+ 4 - 0
src/movegen.rs

@@ -71,6 +71,10 @@ impl Move {
         chars.iter().collect()
     }
 
+    pub fn is_null(&self) -> bool {
+        *self == Move::Nullmove
+    }
+
     pub fn to_string(&self) -> String {
         match self {
             Move::Default{ mov, piece_type: _pt, captured: _c } => {

+ 22 - 2
src/search.rs

@@ -10,9 +10,11 @@ pub struct SearchControl<'a> {
     /// node counter
     pub nodes: usize,
 
+    pub pv: Vec<Move>,
+
     /// function to check if the search should be exited
     pub check: &'a mut dyn FnMut() -> bool,
-    pub move_history: &'a RepetitionTable,
+    pub move_history: &'a mut RepetitionTable,
 
     /// depth the search was started at
     pub initial_depth: i32,
@@ -25,6 +27,19 @@ pub enum SearchResult {
 }
 
 
+impl<'a> SearchControl<'a> {
+    pub fn new(check: &'a mut dyn FnMut() -> bool, move_history: &'a mut RepetitionTable, depth: i32) -> Self {
+        SearchControl {
+            nodes: 0,
+            pv: Vec::with_capacity(depth as usize),
+            check,
+            move_history,
+            initial_depth: depth
+        }
+    }
+}
+
+
 /**
  * searches for moves and returns the best move found plus its value
  */
@@ -119,6 +134,7 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
         }
         else {
             hash.cache(game, CacheEntry::new_value(depth, chosen_mov.1));
+            sc.pv[0] = chosen_mov.0;
             return SearchResult::Finished(chosen_mov.0, -chosen_mov.1);
         }
     }
@@ -193,6 +209,7 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
     sort_moves(game, hash, &mut moves);
 
     let mut alpha_is_exact = false;
+    let mut best_move = Move::Nullmove;
 
     for mov in moves {
         let undo = game.apply(mov);
@@ -216,6 +233,7 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
         if val > alpha {
             alpha = val;//(val as f64 * 0.95) as _;
             alpha_is_exact = true;
+            best_move = mov;
         }
         game.undo_move(undo);
     }
@@ -223,6 +241,8 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
 
     if alpha_is_exact {
         hash.cache(game, CacheEntry::new_value(depth, alpha));
+        let cur_depth = (sc.initial_depth - depth) as usize;
+        sc.pv[cur_depth] = best_move;
     }
     else {
         hash.cache(game, CacheEntry::new_lower(depth, alpha));
@@ -329,7 +349,7 @@ mod tests {
             let mut game = Game::from_fen_str(position).unwrap();
             for (j, &p_res) in perft_results[i].iter().enumerate() {
                 let depth = j + 1;
-                let mut sc = SearchControl{ nodes: 0, check: &mut (|| false), move_history: &mut RepetitionTable::new(), initial_depth: depth as _ };
+                let mut sc = SearchControl::new(&mut || false, &mut RepetitionTable::new(), depth as _);
                 perft(&mut game, &mut sc, depth as _);
                 assert_eq!(sc.nodes, p_res);
             }