|
@@ -59,7 +59,7 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
|
|
|
|
|
|
// use a slight offset for the alpha value in the root node in order to
|
|
|
// determine possibly multiple good moves
|
|
|
- const ALPHA_OFFSET: PosValue = 50 as _;
|
|
|
+ const ALPHA_OFFSET: PosValue = 50 as PosValue;
|
|
|
|
|
|
let mut valued_moves: Vec<(Move, PosValue)> = Vec::with_capacity(moves.len());
|
|
|
let mut cancelled = false;
|
|
@@ -69,55 +69,36 @@ 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, -beta, -alpha, depth - 1);
|
|
|
+ let (mut val, ret) = negamax(game, sc, hash, decrease_mate_in(-beta), decrease_mate_in(-alpha), depth - 1);
|
|
|
+ game.undo_move(undo);
|
|
|
val = -val;
|
|
|
|
|
|
- if let Some(turns) = is_mate_in_p1(val) {
|
|
|
- if turns < 0 {
|
|
|
- val = mate_in_p1(turns - 1);
|
|
|
- }
|
|
|
- if turns > 0 {
|
|
|
- val = mate_in_p1(turns + 1);
|
|
|
- }
|
|
|
- if turns == 0 {
|
|
|
- if val < 0 {
|
|
|
- val = mate_in_p1(-1);
|
|
|
- }
|
|
|
- else {
|
|
|
- val = mate_in_p1(1);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ val = increase_mate_in(val);
|
|
|
|
|
|
if ret {
|
|
|
//return (Move::default(), 0);
|
|
|
cancelled = true;
|
|
|
- game.undo_move(undo);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- if val >= mate() {
|
|
|
+ /*if val >= mate_in_p1(1) {
|
|
|
// mate in 1 --- can't get better than that
|
|
|
info!("yay mate!");
|
|
|
- game.undo_move(undo);
|
|
|
- return SearchResult::Finished(mov, val);
|
|
|
- }
|
|
|
+ return SearchResult::Finished(mov, increase_mate_in(val));
|
|
|
+ }*/
|
|
|
|
|
|
//info!("searched {} -> {}", mov.to_string(), val);
|
|
|
|
|
|
if val > alpha {
|
|
|
alpha = val - ALPHA_OFFSET;
|
|
|
- //info!("updated alpha to {}", alpha);
|
|
|
}
|
|
|
|
|
|
valued_moves.push((mov, -val));
|
|
|
-
|
|
|
- game.undo_move(undo);
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- //info!("movvalues: {:?}", valued_moves.iter().map(|mv| mv.0.to_string() + " - " + &mv.1.to_string()).collect::<Vec<String>>());
|
|
|
+ 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);
|
|
|
|
|
@@ -150,10 +131,16 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
//println!("TABLE HIT!");
|
|
|
match e.entry_type {
|
|
|
EntryType::Value => { return (e.value, false); },
|
|
|
+ //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 { alpha = e.value; } },
|
|
|
+ EntryType::LowerBound => {
|
|
|
+ if e.value < alpha { return (alpha, false); }
|
|
|
+ //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); } },
|
|
|
+ EntryType::UpperBound => {
|
|
|
+ if e.value >= beta { return (beta, false); }
|
|
|
+ },
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -171,6 +158,7 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
|
|
|
|
|
|
let mut moves = generate_legal_moves(game, game.turn);
|
|
|
+ //info!("nega moves: {:?}", moves.iter().map(|mv| mv.to_string()).collect::<Vec<String>>());
|
|
|
|
|
|
let check = is_check(game, game.turn);
|
|
|
if moves.len() == 0 {
|
|
@@ -185,25 +173,22 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
}
|
|
|
|
|
|
// 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);
|
|
|
+ game.undo_move(undo);
|
|
|
val = -val;
|
|
|
- val = increase_mate_in(val);
|
|
|
|
|
|
if ret {
|
|
|
- game.undo_move(undo);
|
|
|
return (alpha, ret);
|
|
|
}
|
|
|
|
|
|
if val >= beta {
|
|
|
- game.undo_move(undo);
|
|
|
return (beta, false);
|
|
|
}
|
|
|
- game.undo_move(undo);
|
|
|
- }
|
|
|
+ }*/
|
|
|
|
|
|
|
|
|
sort_moves(game, hash, &mut moves);
|
|
@@ -214,28 +199,29 @@ 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, -beta, -alpha, depth - 1);
|
|
|
+ let (mut val, ret) = 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 {
|
|
|
- game.undo_move(undo);
|
|
|
return (alpha, ret)
|
|
|
}
|
|
|
|
|
|
if val >= beta {
|
|
|
- game.undo_move(undo);
|
|
|
- hash.cache(game, CacheEntry::new_upper(depth, val));
|
|
|
+ //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);
|
|
|
}
|
|
|
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);
|
|
|
+ }
|
|
|
alpha_is_exact = true;
|
|
|
best_move = mov;
|
|
|
}
|
|
|
- game.undo_move(undo);
|
|
|
}
|
|
|
|
|
|
|
|
@@ -247,7 +233,7 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
|
|
|
else {
|
|
|
hash.cache(game, CacheEntry::new_lower(depth, alpha));
|
|
|
}
|
|
|
- //info!("best alpha {}", best);
|
|
|
+ //info!("best alpha {}", alpha);
|
|
|
return (alpha, false);
|
|
|
}
|
|
|
|
|
@@ -280,23 +266,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, -beta, -alpha, depth - 1);
|
|
|
+ let (mut val, ret) = 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 {
|
|
|
- game.undo_move(undo);
|
|
|
return (alpha, ret)
|
|
|
}
|
|
|
|
|
|
if val >= beta {
|
|
|
- game.undo_move(undo);
|
|
|
return (beta, false);
|
|
|
}
|
|
|
if val > alpha {
|
|
|
alpha = val;
|
|
|
}
|
|
|
- game.undo_move(undo);
|
|
|
}
|
|
|
return (alpha, false);
|
|
|
}
|
|
@@ -319,11 +303,11 @@ pub fn perft(game: &mut Game, sc: &mut SearchControl, depth: i32) -> bool {
|
|
|
for mov in moves {
|
|
|
let undo = game.apply(mov);
|
|
|
let do_return = perft(game, sc, depth - 1);
|
|
|
+ game.undo_move(undo);
|
|
|
+
|
|
|
if do_return {
|
|
|
- game.undo_move(undo);
|
|
|
return true;
|
|
|
}
|
|
|
- game.undo_move(undo);
|
|
|
}
|
|
|
|
|
|
return false;
|
|
@@ -349,7 +333,9 @@ 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::new(&mut || false, &mut RepetitionTable::new(), depth as _);
|
|
|
+ let mut check_fn = || false;
|
|
|
+ let mut rt = RepetitionTable::new();
|
|
|
+ let mut sc = SearchControl::new(&mut check_fn, &mut rt, depth as _);
|
|
|
perft(&mut game, &mut sc, depth as _);
|
|
|
assert_eq!(sc.nodes, p_res);
|
|
|
}
|