c4_e5_chess/engine/
pvs.rs1use super::constants::MIN_INT;
2use super::{constants::*, history::History, move_gen::MoveGenPrime, store::Store};
3use crate::eval::{evaluation::Evaluation, simple::Simple};
4use crate::misc::types::*;
5use cozy_chess::{Board, GameStatus, Move};
6use std::sync::{
7 atomic::{AtomicBool, Ordering},
8 Arc,
9};
10
11pub struct Pvs {
13 pub history: History,
14 pub node_count: u64,
15 pub store: Store,
16}
17
18impl Pvs {
19 pub fn new() -> Self {
21 Self {
22 history: History::new(),
23 node_count: 0,
24 store: Store::new(),
25 }
26 }
27
28 pub fn execute(
30 &mut self,
31 board: &Board,
32 depth: Depth,
33 mut alpha: MoveScore,
34 beta: MoveScore,
35 playing: &Arc<AtomicBool>,
36 _capture: bool,
37 ) -> MoveScore {
38 let mut best_move: Option<Move> = None;
39 let mut best_value: MoveScore = MIN_INT;
40
41 if !playing.load(Ordering::Relaxed) {
42 return 0;
43 }
44
45 if board.status() != GameStatus::Ongoing {
46 if board.status() == GameStatus::Won {
47 return -MATE - i32::from(depth);
48 }
49 return 0;
50 }
51
52 if self.history.get(board) > 2 {
53 return 0;
54 }
55
56 if depth < 1 {
57 self.node_count += 1;
58 return Simple::evaluate(board);
59 }
60
61 let children: Vec<AnnotatedMove> = match self.store.get(depth, board) {
62 Some((_, v, true)) => return v,
63 Some((mv, _, false)) => board.get_legal_sorted(Some(mv)),
64 None => board.get_legal_sorted(None),
65 };
66
67 for (i, child) in children.iter().enumerate() {
68 let mut b1 = board.clone();
69 b1.play_unchecked(child.mv);
70 self.history.inc(&b1);
71
72 let value = if i == 0 {
73 -self.execute(&b1, depth - 1, -beta, -alpha, playing, child.cp)
74 } else {
75 let mut value =
76 -self.execute(&b1, depth - 1, -alpha - 1, -alpha, playing, child.cp);
77 if value > alpha && value < beta {
78 value = -self.execute(&b1, depth - 1, -beta, -value, playing, child.cp);
79 }
80 value
81 };
82
83 self.history.dec(&b1);
84
85 if value > best_value {
86 best_value = value;
87 best_move = Some(child.mv);
88 }
89
90 if best_value >= beta {
91 break;
92 }
93
94 if best_value > alpha {
95 alpha = best_value;
96 }
97 }
98
99 if let Some(bm) = best_move {
100 self.store.put(depth - 1, best_value, board, &bm);
101 }
102 best_value
103 }
104}
105
106impl Default for Pvs {
107 fn default() -> Self {
108 Self::new()
109 }
110}