|
@@ -5,6 +5,7 @@ use evaluate::*;
|
|
|
use log::info;
|
|
|
use rand::prelude::*;
|
|
|
use std::collections::HashMap;
|
|
|
+use zobrist::ZobristTable;
|
|
|
use hash::*;
|
|
|
|
|
|
enum MoveUndo {
|
|
@@ -26,6 +27,7 @@ enum MoveUndo {
|
|
|
pub struct SearchControl<'a> {
|
|
|
pub nodes: usize,
|
|
|
pub check: &'a mut dyn FnMut() -> bool,
|
|
|
+ pub zt: &'a ZobristTable
|
|
|
}
|
|
|
|
|
|
pub enum SearchResult {
|
|
@@ -71,7 +73,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, mov);
|
|
|
+ let new_game = apply_move(game, sc.zt, mov);
|
|
|
|
|
|
let hash_entry = hash.lookup(&new_game);
|
|
|
if let Some(he) = hash_entry {
|
|
@@ -179,7 +181,7 @@ fn negamax(game: &Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: Pos
|
|
|
}
|
|
|
}
|
|
|
for mov in moves {
|
|
|
- let new_game = apply_move(game, mov);
|
|
|
+ let new_game = apply_move(game, sc.zt, mov);
|
|
|
let (mut val, ret) = negamax(&new_game, sc, hash, -beta, -alpha, depth - 1);
|
|
|
val = -val;
|
|
|
|
|
@@ -204,9 +206,9 @@ fn negamax(game: &Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: Pos
|
|
|
return ((alpha as f64 * 0.99) as _, false);
|
|
|
}
|
|
|
|
|
|
-fn quiescence_search(game: &Game, si: &mut SearchControl, mut alpha: PosValue, beta: PosValue, depth: i32) -> PosValue {
|
|
|
+fn quiescence_search(game: &Game, sc: &mut SearchControl, mut alpha: PosValue, beta: PosValue, depth: i32) -> PosValue {
|
|
|
let val = evaluate(game);
|
|
|
- si.nodes += 1;
|
|
|
+ sc.nodes += 1;
|
|
|
|
|
|
if val >= beta {
|
|
|
return beta;
|
|
@@ -223,8 +225,8 @@ fn quiescence_search(game: &Game, si: &mut SearchControl, mut alpha: PosValue, b
|
|
|
|
|
|
let moves = generate_attacking_moves(game, game.turn);
|
|
|
for mov in moves {
|
|
|
- let new_game = apply_move(game, mov);
|
|
|
- let val = -quiescence_search(&new_game, si, -beta, -alpha, depth - 1);
|
|
|
+ let new_game = apply_move(game, sc.zt, mov);
|
|
|
+ let val = -quiescence_search(&new_game, sc, -beta, -alpha, depth - 1);
|
|
|
if val >= beta {
|
|
|
return beta;
|
|
|
}
|
|
@@ -245,7 +247,7 @@ pub fn undo(game: &mut Game, mov: Move) {
|
|
|
|
|
|
}
|
|
|
|
|
|
-pub fn apply_move(game: &Game, mov: Move) -> Game {
|
|
|
+pub fn apply_move(game: &Game, zt: &ZobristTable, mov: Move) -> Game {
|
|
|
let mut new_game = game.clone();
|
|
|
|
|
|
let side = game.turn;
|
|
@@ -274,11 +276,18 @@ pub fn apply_move(game: &Game, mov: Move) -> Game {
|
|
|
new_game.castling_rights[3] = false;
|
|
|
}
|
|
|
|
|
|
+ // if it is a capture
|
|
|
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);
|
|
|
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);
|
|
|
},
|
|
|
Move::Castling { side, left } => {
|
|
|
// invalidate future castling rights
|
|
@@ -328,6 +337,6 @@ pub fn apply_move(game: &Game, mov: Move) -> Game {
|
|
|
new_game.turn = !new_game.turn;
|
|
|
|
|
|
|
|
|
-
|
|
|
+ info!("applied {}, zobrist now {}", mov.to_string(), new_game.zobrist.unwrap_or(u64::MAX));
|
|
|
return new_game;
|
|
|
}
|