|
@@ -21,17 +21,16 @@ enum MoveUndo {
|
|
|
}
|
|
|
|
|
|
|
|
|
-pub struct SearchInfo {
|
|
|
- pub nodes: usize
|
|
|
+pub struct SearchControl<'a> {
|
|
|
+ pub nodes: usize,
|
|
|
+ pub check: &'a dyn Fn() -> bool,
|
|
|
}
|
|
|
|
|
|
|
|
|
-pub fn search(game: &Game, depth: i32) -> (Move, SearchInfo) {
|
|
|
-
|
|
|
- let mut si = SearchInfo { nodes: 0 };
|
|
|
+pub fn search(game: &Game, sc: &mut SearchControl, depth: i32) -> Move {
|
|
|
|
|
|
if depth == 0 {
|
|
|
- return (Move::default(), si);
|
|
|
+ return Move::default();
|
|
|
}
|
|
|
|
|
|
let mut moves = generate_legal_moves(game, game.turn);
|
|
@@ -60,7 +59,7 @@ pub fn search(game: &Game, depth: i32) -> (Move, SearchInfo) {
|
|
|
let mut valued_moves = moves.iter().map(|mov| {
|
|
|
let new_game = apply_move(game, *mov);
|
|
|
//info!("searching {}", mov.to_string());
|
|
|
- let val = -negamax(&new_game, &mut si, -beta, -alpha, depth - 1);
|
|
|
+ let val = -negamax(&new_game, sc, -beta, -alpha, depth - 1);
|
|
|
info!("searched {} -> {}", mov.to_string(), val);
|
|
|
|
|
|
if val > alpha {
|
|
@@ -81,16 +80,16 @@ pub fn search(game: &Game, depth: i32) -> (Move, SearchInfo) {
|
|
|
let best_moves = valued_moves.iter().filter(|mv| mv.1 == min_val).map(|(mov, _)| *mov).collect::<Vec<Move>>();
|
|
|
|
|
|
//info!("bestmove value {}", -min_val);
|
|
|
- return (best_moves[(rng.next_u64() % best_moves.len() as u64) as usize], si);
|
|
|
+ return best_moves[(rng.next_u64() % best_moves.len() as u64) as usize];
|
|
|
}
|
|
|
else {
|
|
|
- return (Move::Default{ mov: SimpleMove{ from: 0, to: 0 }, piece_type: PAWN }, si);
|
|
|
+ return Move::Default{ mov: SimpleMove{ from: 0, to: 0 }, piece_type: PAWN };
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn negamax(game: &Game, si: &mut SearchInfo, mut alpha: i32, beta: i32, depth: i32) -> i32 {
|
|
|
+fn negamax(game: &Game, sc: &mut SearchControl, mut alpha: i32, beta: i32, depth: i32) -> i32 {
|
|
|
if depth == 0 {
|
|
|
- return quiescence_search(game, si, alpha, beta, 7);
|
|
|
+ return quiescence_search(game, sc, alpha, beta, 7);
|
|
|
let eval = evaluate(game);
|
|
|
if eval != 0 {
|
|
|
//info!("eval: {}", eval);
|
|
@@ -100,7 +99,7 @@ fn negamax(game: &Game, si: &mut SearchInfo, mut alpha: i32, beta: i32, depth: i
|
|
|
|
|
|
const MIN_VALUE: i32 = i32::min_value() + 1;
|
|
|
|
|
|
- si.nodes += 1;
|
|
|
+ sc.nodes += 1;
|
|
|
|
|
|
let mut best = MIN_VALUE;
|
|
|
//let mut best_move = Move::default();
|
|
@@ -122,12 +121,12 @@ fn negamax(game: &Game, si: &mut SearchInfo, mut alpha: i32, beta: i32, depth: i
|
|
|
}
|
|
|
for mov in moves {
|
|
|
let new_game = apply_move(game, mov);
|
|
|
- let val = -negamax(&new_game, si, -beta, -alpha, depth - 1);
|
|
|
+ let val = -negamax(&new_game, sc, -beta, -alpha, depth - 1);
|
|
|
if val >= beta {
|
|
|
return beta;
|
|
|
}
|
|
|
if val > alpha {
|
|
|
- alpha = val;
|
|
|
+ alpha = (val as f64 * 0.95) as i32;
|
|
|
}
|
|
|
//info!(" -> negamaxed {} -> {}", mov.to_string(), depth - 1);
|
|
|
if val > best {
|
|
@@ -140,7 +139,7 @@ fn negamax(game: &Game, si: &mut SearchInfo, mut alpha: i32, beta: i32, depth: i
|
|
|
return (best as f64 * 0.99) as i32;
|
|
|
}
|
|
|
|
|
|
-fn quiescence_search(game: &Game, si: &mut SearchInfo, mut alpha: i32, beta: i32, depth: i32) -> i32 {
|
|
|
+fn quiescence_search(game: &Game, si: &mut SearchControl, mut alpha: i32, beta: i32, depth: i32) -> i32 {
|
|
|
const MIN_VALUE: i32 = i32::min_value() + 1;
|
|
|
|
|
|
let val = evaluate(game);
|