Nicolas Winkler 3 năm trước cách đây
mục cha
commit
150ab392eb
4 tập tin đã thay đổi với 76 bổ sung46 xóa
  1. 6 6
      src/engine.rs
  2. 37 13
      src/game.rs
  3. 15 0
      src/movegen.rs
  4. 18 27
      src/search.rs

+ 6 - 6
src/engine.rs

@@ -10,7 +10,7 @@ use std::collections::{VecDeque, HashMap};
 use zobrist::ZobristTable;
 use hash::Cache;
 
-use std::thread::sleep_ms;
+use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender};
 
 pub enum EngineMsg {
@@ -47,7 +47,7 @@ pub struct Engine {
     r: Receiver<EngineMsg>,
     s: Sender<InterfaceMsg>,
     hash: Cache,
-    zobrist_table: ZobristTable
+    zobrist_table: Arc<ZobristTable>
 }
 
 impl Engine {
@@ -57,9 +57,9 @@ impl Engine {
             messages: VecDeque::new(),
             r, s,
             hash: Cache::new(),
-            zobrist_table: ZobristTable::new()
+            zobrist_table: Arc::new(ZobristTable::new())
         };
-        eng.game.zobrist = Some(eng.game.calculate_zobrist(&eng.zobrist_table));
+        eng.game.zobrist = Some((eng.zobrist_table.clone(), eng.game.calculate_zobrist(&eng.zobrist_table)));
         eng
     }
 
@@ -105,7 +105,7 @@ impl Engine {
                     }
                     return false;
                 };
-                let mut sc = SearchControl{ nodes: 0, check: &mut check_fn, zt: &self.zobrist_table };
+                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);
 
@@ -139,7 +139,7 @@ impl Engine {
                     return false;
                 };
 
-                let mut sc = SearchControl{ nodes: 0, check: &mut check_fn, zt: &self.zobrist_table };
+                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 {

+ 37 - 13
src/game.rs

@@ -1,10 +1,11 @@
 use bitboard::*;
 use movegen::*;
 use log::info;
+use std::sync::Arc;
 use zobrist::{ZobristTable};
 use zobrist;
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone)]
 pub struct Game
 {
     pub pieces: [Bitboard; 12],
@@ -19,9 +20,16 @@ pub struct Game
     /// white kingside, white queenside, black kingside, black queenside
     /// 
     pub castling_rights: [bool; 4],
-    pub halfmoves_since_last_event: i32,
 
-    pub zobrist: Option<zobrist::Hash>
+    
+    //
+    // non-hashed part
+    // vvv
+
+
+    pub turn_number: i32,
+    pub halfmoves_since_last_event: i32,
+    pub zobrist: Option<(Arc<ZobristTable>, zobrist::Hash)>
 }
 
 impl Default for Game {
@@ -45,12 +53,33 @@ impl Default for Game {
             en_passant: None,
             castling_rights: [true; 4],
             halfmoves_since_last_event: 0,
-            //turn_number: 0,
+            turn_number: 0,
             zobrist: None
         }
     }
 }
 
+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 {
+            zb.hash(state);
+        }
+    }
+}
+
+impl PartialEq for Game {
+    fn eq(&self, other: &Self) -> bool {
+        self.pieces == other.pieces &&
+        self.turn == other.turn &&
+        self.en_passant == other.en_passant &&
+        self.castling_rights == other.castling_rights
+    }
+}
+
+impl Eq for Game {
+}
+
+
 impl Game {
     pub fn empty() -> Game {
         Game {
@@ -59,7 +88,7 @@ impl Game {
             en_passant: None,
             castling_rights: [true; 4],
             halfmoves_since_last_event: 0,
-            //turn_number: 0,
+            turn_number: 0,
             zobrist: None
         }
     }
@@ -423,8 +452,8 @@ impl Game {
     }
 
     pub fn update_zobrist(&mut self, h: zobrist::Hash) {
-        if let Some(mut zh) = self.zobrist {
-            zh ^= h;
+        if let Some((ref _zt, ref mut zh)) = self.zobrist {
+            *zh ^= h;
         }
     }
 
@@ -457,13 +486,8 @@ impl Game {
 
         return hash;
     }
-}
 
+    pub fn apply(&mut self, mov: Move) -> MoveUndo {
 
-impl std::hash::Hash for Game {
-    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
-        if let Some(zb) = self.zobrist {
-            zb.hash(state);
-        }
     }
 }

+ 15 - 0
src/movegen.rs

@@ -34,6 +34,21 @@ pub enum Move {
     Promotion { mov: SimpleMove, promote_to: PieceType },
 }
 
+enum MoveUndo {
+    Default {
+        piece_type: PieceType,
+        before: Bitboard,
+        captured_type: PieceType,
+        captured_before: Bitboard,
+    },
+    Castling { rooks_before: Bitboard, king_before: Bitboard },
+    Promotion {
+        promoted_to: PieceType,
+        promoted_to_before: Bitboard,
+        pawns_before: Bitboard
+    }
+}
+
 impl Default for Move {
     fn default() -> Move {
         Move::Default{ mov: SimpleMove { from: 0, to: 0 }, piece_type: NO_PIECE }

+ 18 - 27
src/search.rs

@@ -8,26 +8,10 @@ use std::collections::HashMap;
 use zobrist::ZobristTable;
 use hash::*;
 
-enum MoveUndo {
-    Default {
-        piece_type: PieceType,
-        before: Bitboard,
-        captured_type: PieceType,
-        captured_before: Bitboard,
-    },
-    Castling { rooks_before: Bitboard, king_before: Bitboard },
-    Promotion {
-        promoted_to: PieceType,
-        promoted_to_before: Bitboard,
-        pawns_before: Bitboard
-    }
-}
-
 
 pub struct SearchControl<'a> {
     pub nodes: usize,
-    pub check: &'a mut dyn FnMut() -> bool,
-    pub zt: &'a ZobristTable
+    pub check: &'a mut dyn FnMut() -> bool
 }
 
 pub enum SearchResult {
@@ -73,7 +57,7 @@ pub fn search(game: &Game, sc: &mut SearchControl, hash: &mut Cache, depth: i32)
     let mut valued_moves: Vec<(Move, PosValue)> = Vec::with_capacity(moves.len());
     let mut cancelled = false;
     for mov in moves {
-        let new_game = apply_move(game, sc.zt, mov);
+        let new_game = apply_move(game, mov);
 
         let hash_entry = hash.lookup(&new_game);
         if let Some(he) = hash_entry {
@@ -181,7 +165,7 @@ fn negamax(game: &Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: Pos
         }
     }
     for mov in moves {
-        let new_game = apply_move(game, sc.zt, mov);
+        let new_game = apply_move(game, mov);
         let (mut val, ret) = negamax(&new_game, sc, hash, -beta, -alpha, depth - 1);
         val = -val;
 
@@ -225,7 +209,7 @@ fn quiescence_search(game: &Game, sc: &mut SearchControl, mut alpha: PosValue, b
 
     let moves = generate_attacking_moves(game, game.turn);
     for mov in moves {
-        let new_game = apply_move(game, sc.zt, mov);
+        let new_game = apply_move(game, mov);
         let val = -quiescence_search(&new_game, sc, -beta, -alpha, depth - 1);
         if val >= beta {
             return beta;
@@ -247,7 +231,7 @@ pub fn undo(game: &mut Game, mov: Move) {
     
 }
 
-pub fn apply_move(game: &Game, zt: &ZobristTable, mov: Move) -> Game {
+pub fn apply_move(game: &Game, mov: Move) -> Game {
     let mut new_game = game.clone();
 
     let side = game.turn;
@@ -277,17 +261,22 @@ pub fn apply_move(game: &Game, zt: &ZobristTable, mov: Move) -> Game {
             }
 
             // if it is a capture
-            if from_square(mov.to) | others != 0 {
+            if from_square(mov.to) & others != 0 {
                 let (other_piece, other_side) = game.get_square(mov.to);
-                let hup = zt.piece_hash(other_piece, other_side, mov.to);
-                new_game.update_zobrist(hup);
+                if let Some((ref zt, ref _zv)) = game.zobrist {
+                    let hup = zt.piece_hash(other_piece, other_side, mov.to);
+                    new_game.update_zobrist(hup);
+                }
                 new_game.apply_mask(!from_square(mov.to));
             }
+
             let moved_piece = mov.apply_to(new_game.get_piece(pt, side));
             new_game.set_piece(pt, side, moved_piece);
 
-            let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
-            new_game.update_zobrist(hup);
+            if let Some((ref zt, ref _zv)) = game.zobrist {
+                let hup = zt.piece_hash(pt, side, mov.from) ^ zt.piece_hash(pt, side, mov.to);
+                new_game.update_zobrist(hup);
+            }
         },
         Move::Castling { side, left } => {
             // invalidate future castling rights
@@ -337,6 +326,8 @@ pub fn apply_move(game: &Game, zt: &ZobristTable, mov: Move) -> Game {
     new_game.turn = !new_game.turn;
 
 
-    info!("applied {}, zobrist now {}", mov.to_string(), new_game.zobrist.unwrap_or(u64::MAX));
+    if let Some((ref zt, ref zv)) = new_game.zobrist {
+        info!("applied {}, zobrist now {}", mov.to_string(), *zv);
+    }
     return new_game;
 }