|
@@ -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);
|
|
|
}
|