|
@@ -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 {
|