|
@@ -14,6 +14,7 @@ pub struct SearchControl<'a> {
|
|
|
|
|
|
/// function to check if the search should be exited
|
|
|
pub check: &'a mut dyn FnMut() -> bool,
|
|
|
+ pub stopping: bool,
|
|
|
pub move_history: &'a mut RepetitionTable,
|
|
|
|
|
|
/// depth the search was started at
|
|
@@ -33,6 +34,7 @@ impl<'a> SearchControl<'a> {
|
|
|
nodes: 0,
|
|
|
pv: Vec::with_capacity(depth as usize),
|
|
|
check,
|
|
|
+ stopping: false,
|
|
|
move_history,
|
|
|
initial_depth: depth
|
|
|
}
|
|
@@ -69,13 +71,12 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
|
|
|
//assert_eq!(new_game, *game, );
|
|
|
|
|
|
//info!("searching {}", mov.to_string());
|
|
|
- let (mut val, ret) = negamax(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
+ let mut val = -negamax(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
game.undo_move(undo);
|
|
|
- val = -val;
|
|
|
|
|
|
val = increase_mate_in(val);
|
|
|
|
|
|
- if ret {
|
|
|
+ if sc.stopping {
|
|
|
//return (Move::default(), 0);
|
|
|
cancelled = true;
|
|
|
break;
|
|
@@ -124,22 +125,22 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: PosValue, beta: PosValue, depth: i32) -> (PosValue, bool) {
|
|
|
+fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: PosValue, beta: PosValue, depth: i32) -> PosValue {
|
|
|
|
|
|
if let Some(e) = hash.lookup(game) {
|
|
|
if e.depth >= depth {
|
|
|
//println!("TABLE HIT!");
|
|
|
match e.entry_type {
|
|
|
- EntryType::Value => { return (e.value, false); },
|
|
|
+ EntryType::Value => { /*return e.value;*/ },
|
|
|
//EntryType::Value => { if e.value >= alpha { return (e.value, false); } else { return (alpha, false); } },
|
|
|
//EntryType::LowerBound => { if e.value > alpha { return (e.value, false) } },
|
|
|
EntryType::LowerBound => {
|
|
|
- if e.value < alpha { return (alpha, false); }
|
|
|
+ if e.value < alpha { return alpha; }
|
|
|
//if e.value >= beta { return (beta, false); }
|
|
|
},
|
|
|
//EntryType::UpperBound => { if e.value >= beta { return (beta, false); } },
|
|
|
EntryType::UpperBound => {
|
|
|
- if e.value >= beta { return (beta, false); }
|
|
|
+ if e.value >= beta { return beta; }
|
|
|
},
|
|
|
}
|
|
|
}
|
|
@@ -152,7 +153,8 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
sc.nodes += 1;
|
|
|
if sc.nodes % 1024 == 0 {
|
|
|
if (sc.check)() {
|
|
|
- return (0 as _, true);
|
|
|
+ sc.stopping = true;
|
|
|
+ return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -164,31 +166,32 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
if moves.len() == 0 {
|
|
|
if check {
|
|
|
// mate
|
|
|
- return (-mate(), false);
|
|
|
+ return -mate();
|
|
|
}
|
|
|
else {
|
|
|
// stalemate
|
|
|
- return (0 as _, false);
|
|
|
+ return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// Nullmove
|
|
|
- /*if !check && depth >= 4 && game_lateness(game) < 80 {
|
|
|
+ if !check && depth >= 4 && game_lateness(game) < 80 {
|
|
|
let nmov = Move::Nullmove;
|
|
|
let undo = game.apply(nmov);
|
|
|
|
|
|
- let (mut val, ret) = negamax(game, sc, hash, -beta, -alpha, depth / 2 - 1);
|
|
|
+ let val = -negamax(game, sc, hash, -beta, -alpha, depth / 2 - 1);
|
|
|
game.undo_move(undo);
|
|
|
- val = -val;
|
|
|
-
|
|
|
- if ret {
|
|
|
- return (alpha, ret);
|
|
|
+
|
|
|
+ if sc.stopping {
|
|
|
+ return alpha;
|
|
|
}
|
|
|
|
|
|
- if val >= beta {
|
|
|
- return (beta, false);
|
|
|
+ if is_mate_in_p1(val).is_none() {
|
|
|
+ if val >= beta {
|
|
|
+ return beta;
|
|
|
+ }
|
|
|
}
|
|
|
- }*/
|
|
|
+ }
|
|
|
|
|
|
|
|
|
sort_moves(game, hash, &mut moves);
|
|
@@ -199,26 +202,23 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
for mov in moves {
|
|
|
let undo = game.apply(mov);
|
|
|
|
|
|
- let (mut val, ret) = negamax(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
+ let mut val = -negamax(game, sc, hash, -beta, -alpha, depth - 1);
|
|
|
game.undo_move(undo);
|
|
|
- val = -val;
|
|
|
- val = increase_mate_in(val);
|
|
|
+ //val = increase_mate_in(val);
|
|
|
|
|
|
- if ret {
|
|
|
- return (alpha, ret)
|
|
|
+ // return if the search has been cancelled
|
|
|
+ if sc.stopping {
|
|
|
+ return alpha;
|
|
|
}
|
|
|
|
|
|
if val >= beta {
|
|
|
//hash.cache(game, CacheEntry::new_upper(depth, val));
|
|
|
//println!("but ret {}: {}", depth, beta);
|
|
|
//info!("{} causes beta cutoff at {} ", mov.to_string(), val);
|
|
|
- return (beta, false);
|
|
|
+ return beta;
|
|
|
}
|
|
|
- if val > alpha {
|
|
|
- alpha = val;//(val as f64 * 0.95) as _;
|
|
|
- if let Some(p) = is_mate_in_p1(val) {
|
|
|
- //info!("{} is mate in {} plies: {}", mov.to_string(), p, val);
|
|
|
- }
|
|
|
+ if increase_mate_in(val) > alpha {
|
|
|
+ alpha = increase_mate_in(val);
|
|
|
alpha_is_exact = true;
|
|
|
best_move = mov;
|
|
|
}
|
|
@@ -234,31 +234,32 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
hash.cache(game, CacheEntry::new_lower(depth, alpha));
|
|
|
}
|
|
|
//info!("best alpha {}", alpha);
|
|
|
- return (alpha, false);
|
|
|
+ return alpha;
|
|
|
}
|
|
|
|
|
|
-fn quiescence_search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: PosValue, beta: PosValue, depth: i32) -> (PosValue, bool) {
|
|
|
+fn quiescence_search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha: PosValue, beta: PosValue, depth: i32) -> PosValue {
|
|
|
|
|
|
sc.nodes += 1;
|
|
|
if sc.nodes % 1024 == 0 {
|
|
|
if (sc.check)() {
|
|
|
- return (0 as _, true);
|
|
|
+ sc.stopping = true;
|
|
|
+ return 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
let val = evaluate(game);
|
|
|
if val >= beta {
|
|
|
- return (beta, false);
|
|
|
+ return beta;
|
|
|
}
|
|
|
if val > alpha {
|
|
|
alpha = val;
|
|
|
}
|
|
|
|
|
|
if depth <= 0 {
|
|
|
- return (alpha, false);
|
|
|
+ return alpha;
|
|
|
}
|
|
|
|
|
|
- if game.get_piece(KING, game.turn) == 0 { return (-mate(), false); }
|
|
|
+ if game.get_piece(KING, game.turn) == 0 { return -mate(); }
|
|
|
|
|
|
let mut moves = generate_attacking_moves(game, game.turn);
|
|
|
|
|
@@ -266,23 +267,21 @@ fn quiescence_search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache,
|
|
|
|
|
|
for mov in moves {
|
|
|
let undo = game.apply(mov);
|
|
|
- let (mut val, ret) = quiescence_search(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
+ let mut val = -quiescence_search(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
game.undo_move(undo);
|
|
|
- val = -val;
|
|
|
- val = increase_mate_in(val);
|
|
|
|
|
|
- if ret {
|
|
|
- return (alpha, ret)
|
|
|
+ if sc.stopping {
|
|
|
+ return alpha
|
|
|
}
|
|
|
|
|
|
if val >= beta {
|
|
|
- return (beta, false);
|
|
|
+ return beta;
|
|
|
}
|
|
|
- if val > alpha {
|
|
|
- alpha = val;
|
|
|
+ if increase_mate_in(val) > alpha {
|
|
|
+ alpha = increase_mate_in(val);
|
|
|
}
|
|
|
}
|
|
|
- return (alpha, false);
|
|
|
+ return alpha;
|
|
|
}
|
|
|
|
|
|
|