Просмотр исходного кода

Merge branch 'master' of https://git.winfor.ch/nicolas/bishop

Nicolas Winkler 3 лет назад
Родитель
Сommit
d99f43a8f9
4 измененных файлов с 93 добавлено и 60 удалено
  1. 8 6
      src/engine.rs
  2. 1 1
      src/hash.rs
  3. 30 1
      src/movegen.rs
  4. 54 52
      src/search.rs

+ 8 - 6
src/engine.rs

@@ -216,7 +216,7 @@ impl Engine {
 
         let mut alpha = crate::evaluate::MIN_VALUE;
         let mut beta = crate::evaluate::MAX_VALUE;
-        let window_size = 50;
+        let window_size = 100;
         loop {
 
             sc.initial_depth = depth;
@@ -234,6 +234,8 @@ impl Engine {
                     continue;
                 }
                 else {
+                    alpha = crate::evaluate::MIN_VALUE;
+                    beta = crate::evaluate::MAX_VALUE;
                     //alpha = bv - window_size;
                     //beta = bv + window_size;
                 }
@@ -245,12 +247,12 @@ impl Engine {
                 let nodes = sc.nodes;
                 let nps = (nodes as f64 / elapsed.as_nanos() as f64 * 1000000000.0) as i64;
                 let cp = best_val as i64;
-                let pv = &sc.pv.iter().filter(|&m| !m.is_null()).map(|m| m.to_string()).fold(String::new(), |a, b| a + " " + &b)[1..];
+                let pv = &sc.pv.iter().filter(|&m| !m.is_null()).map(|m| m.to_string()).fold(String::new(), |a, b| a + " " + &b)[0..];
 
                 if let Some(plies) = crate::evaluate::is_mate_in_p1(bv) {
                     let turns = plies / 2;
-                    println!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
-                    info!("info depth {} score mate {} time {} nodes {} nps {} pv {}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
+                    println!("info depth {} score mate {} time {} nodes {} nps {} pv{}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
+                    info!("info depth {} score mate {} time {} nodes {} nps {} pv{}", depth, turns, elapsed.as_millis(), nodes, nps, pv);
                     
                     /*if depth > 3 {
                         break;
@@ -260,8 +262,8 @@ impl Engine {
                     }*/
                 }
                 else {
-                    println!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
-                    info!("info depth {} score cp {} time {} nodes {} nps {} pv {}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
+                    println!("info depth {} score cp {} time {} nodes {} nps {} pv{}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
+                    info!("info depth {} score cp {} time {} nodes {} nps {} pv{}", depth, cp, elapsed.as_millis(), nodes, nps, pv);
                 }
                 depth += 1;
             }

+ 1 - 1
src/hash.rs

@@ -58,7 +58,7 @@ impl Cache {
     pub fn new() -> Self {
         Cache {
             hashmap: HashMap::new(),
-            max_capacity: 10000000
+            max_capacity: 40000000
         }
     }
 

+ 30 - 1
src/movegen.rs

@@ -219,7 +219,7 @@ pub fn sort_moves(game: &mut Game, hash: &mut Cache, move_list: &mut Vec<Move>)
                 return e.value + 1000;
             }
             else {
-                return 0;
+                return crate::evaluate::evaluate(game);
             }
         }
         else {
@@ -239,6 +239,35 @@ pub fn sort_moves_no_hash(game: &mut Game, move_list: &mut Vec<Move>) {
     });
 }
 
+pub fn sort_quiescence(game: &mut Game, move_list: &mut Vec<Move>) {
+    let value_piece = |pt| {
+        match pt {
+            PAWN => 1,
+            KNIGHT => 2,
+            BISHOP => 3,
+            ROOK => 4,
+            QUEEN => 5,
+            KING => 6,
+            _ => 0,
+        }
+    };
+
+    move_list.sort_by_cached_key(|mov| {
+        match *mov {
+            Move::Default{ mov: _, piece_type, captured: Some(c) } => {
+                value_piece(piece_type) - value_piece(c)
+            },
+            Move::Promotion{ mov: _, promote_to: _, captured: Some(c) } => {
+                value_piece(PAWN) - value_piece(c)
+            },
+            Move::EnPassant{ mov: _, beaten } => {
+                value_piece(PAWN) - value_piece(game.get_square(beaten).0)
+            },
+            _ => 0
+        }
+    });
+}
+
 
 fn generate_pawn_pushes(game: &Game, side: Side, move_list: &mut Vec<Move>) {
     let pawns = game.pawns(side);

+ 54 - 52
src/search.rs

@@ -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,10 @@ 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 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;
@@ -84,14 +83,14 @@ pub fn search(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alp
         if val >= mate_in_p1(1) {
             // mate in 1 --- can't get better than that
             info!("yay mate!");
-            return SearchResult::Finished(mov, increase_mate_in(val));
+            //return SearchResult::Finished(mov, increase_mate_in(val));
         }
 
         //info!("searched {} -> {}", mov.to_string(), val);
 
-        if val > alpha {
-            alpha = val - ALPHA_OFFSET;
-            valued_moves.push((mov, -val));
+        if increase_mate_in(val) > alpha {
+            alpha = increase_mate_in(val) - ALPHA_OFFSET;
+            valued_moves.push((mov, -alpha));
         }
     }
 
@@ -123,22 +122,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) {
+pub 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 >= beta { return (beta, 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 < alpha { return (alpha, false); }
+                    if e.value >= beta { return beta; }
                 },
             }
         }
@@ -151,7 +150,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;
         }
     }
 
@@ -163,31 +163,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 false && !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);
@@ -195,29 +196,31 @@ fn negamax(game: &mut Game, sc: &mut SearchControl, hash: &mut Cache, mut alpha:
     let mut alpha_is_exact = false;
     let mut best_move = Move::Nullmove;
 
+    // we can't beat an alpha this good
+    if alpha >= mate() {
+        return 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 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);
+        //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));
+            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;
         }
@@ -233,31 +236,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);
 
@@ -265,23 +269,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;
 }