|
@@ -11,7 +11,7 @@ pub struct SearchControl<'a> {
|
|
pub nodes: usize,
|
|
pub nodes: usize,
|
|
|
|
|
|
pub pv: Vec<Move>,
|
|
pub pv: Vec<Move>,
|
|
- pub killer_moves: [Move; 3],
|
|
|
|
|
|
+ pub killer_moves: Vec<[Move; 2]>,
|
|
|
|
|
|
/// function to check if the search should be exited
|
|
/// function to check if the search should be exited
|
|
pub check: &'a mut dyn FnMut() -> bool,
|
|
pub check: &'a mut dyn FnMut() -> bool,
|
|
@@ -34,7 +34,7 @@ impl<'a> SearchControl<'a> {
|
|
SearchControl {
|
|
SearchControl {
|
|
nodes: 0,
|
|
nodes: 0,
|
|
pv: Vec::with_capacity(depth as usize),
|
|
pv: Vec::with_capacity(depth as usize),
|
|
- killer_moves: [Move::Nullmove; 3],
|
|
|
|
|
|
+ killer_moves: vec![[Move::Nullmove; 2]; depth as usize],
|
|
check,
|
|
check,
|
|
stopping: false,
|
|
stopping: false,
|
|
move_history,
|
|
move_history,
|
|
@@ -42,15 +42,25 @@ impl<'a> SearchControl<'a> {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn insert_killer(&mut self, killer: Move) {
|
|
|
|
- for i in 1..self.killer_moves.len() {
|
|
|
|
- self.killer_moves[i - 1] = self.killer_moves[i];
|
|
|
|
|
|
+ pub fn set_depth(&mut self, depth: i32) {
|
|
|
|
+ self.initial_depth = depth;
|
|
|
|
+ self.killer_moves = vec![[Move::Nullmove; 2]; depth as usize];
|
|
|
|
+ self.pv = vec![Move::Nullmove; depth as _];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn insert_killer(&mut self, ply_depth: usize, killer: Move) {
|
|
|
|
+ if self.is_killer(ply_depth, &killer) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ let nkm = self.killer_moves[ply_depth].len();
|
|
|
|
+ for i in 1..nkm {
|
|
|
|
+ self.killer_moves[ply_depth][i - 1] = self.killer_moves[ply_depth][i];
|
|
}
|
|
}
|
|
- self.killer_moves[self.killer_moves.len() - 1] = killer;
|
|
|
|
|
|
+ self.killer_moves[ply_depth][nkm - 1] = killer;
|
|
}
|
|
}
|
|
|
|
|
|
- pub fn is_killer(&self, killer: &Move) -> bool {
|
|
|
|
- self.killer_moves.contains(killer)
|
|
|
|
|
|
+ pub fn is_killer(&self, ply_depth: usize, killer: &Move) -> bool {
|
|
|
|
+ self.killer_moves[ply_depth].contains(killer)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -65,7 +75,8 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
|
|
|
|
|
|
let mut moves = generate_legal_moves(game, game.turn);
|
|
let mut moves = generate_legal_moves(game, game.turn);
|
|
let mut rng = rand::thread_rng();
|
|
let mut rng = rand::thread_rng();
|
|
- sort_moves(game, hash, &sc.killer_moves, &mut moves);
|
|
|
|
|
|
+ let ply_depth = (sc.initial_depth - depth) as usize;
|
|
|
|
+ sort_moves(game, hash, &sc.killer_moves[ply_depth], &mut moves);
|
|
|
|
|
|
info!("moves: {:?}", moves.iter().map(|mv| mv.to_string()).collect::<Vec<String>>());
|
|
info!("moves: {:?}", moves.iter().map(|mv| mv.to_string()).collect::<Vec<String>>());
|
|
|
|
|
|
@@ -168,8 +179,8 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- let mut moves = generate_legal_moves(game, game.turn);
|
|
|
|
|
|
+ let ply_depth = (sc.initial_depth - depth) as usize;
|
|
|
|
+ let moves = generate_legal_sorted_moves(game, hash, &sc.killer_moves[ply_depth], game.turn);
|
|
//info!("nega moves: {:?}", moves.iter().map(|mv| mv.to_string()).collect::<Vec<String>>());
|
|
//info!("nega moves: {:?}", moves.iter().map(|mv| mv.to_string()).collect::<Vec<String>>());
|
|
|
|
|
|
let check = is_check(game, game.turn);
|
|
let check = is_check(game, game.turn);
|
|
@@ -204,7 +215,7 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- sort_moves(game, hash, &sc.killer_moves, &mut moves);
|
|
|
|
|
|
+ //sort_moves(game, hash, &sc.killer_moves, &mut moves);
|
|
//moves.sort_by_cached_key(|m| if sc.is_killer(*m) { -1 } else { 0 });
|
|
//moves.sort_by_cached_key(|m| if sc.is_killer(*m) { -1 } else { 0 });
|
|
|
|
|
|
let mut alpha_is_exact = false;
|
|
let mut alpha_is_exact = false;
|
|
@@ -231,7 +242,9 @@ pub fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut al
|
|
hash.cache(game, CacheEntry::new_upper(depth, val));
|
|
hash.cache(game, CacheEntry::new_upper(depth, val));
|
|
//println!("but ret {}: {}", depth, beta);
|
|
//println!("but ret {}: {}", depth, beta);
|
|
//info!("{} causes beta cutoff at {} ", mov.to_string(), val);
|
|
//info!("{} causes beta cutoff at {} ", mov.to_string(), val);
|
|
- sc.insert_killer(mov);
|
|
|
|
|
|
+ if !mov.is_capture() {
|
|
|
|
+ sc.insert_killer(ply_depth, mov);
|
|
|
|
+ }
|
|
return beta;
|
|
return beta;
|
|
}
|
|
}
|
|
if increase_mate_in(val) > alpha {
|
|
if increase_mate_in(val) > alpha {
|