@@ -33,7 +33,6 @@ pub struct Bot {
3333 positions_searched : u128 ,
3434 quiescence_searched : u128 ,
3535 transposition_hits : u128 ,
36- null_move_prunes : u128 ,
3736}
3837
3938impl Bot {
@@ -60,7 +59,6 @@ impl Bot {
6059 positions_searched : 0 ,
6160 quiescence_searched : 0 ,
6261 transposition_hits : 0 ,
63- null_move_prunes : 0 ,
6462 }
6563 }
6664
@@ -93,18 +91,18 @@ impl Bot {
9391 self . positions_searched = 0 ;
9492 self . quiescence_searched = 0 ;
9593 self . transposition_hits = 0 ;
96- self . null_move_prunes = 0 ;
9794
9895 self . move_sorter . clear ( ) ;
9996
97+ let mut window = 40 ;
98+
10099 self . think_timer = Instant :: now ( ) ;
101100 for depth in 1 ..=( 255 - MAX_SEARCH_EXTENSIONS ) {
102101 self . searched_one_move = false ;
103102 self . best_move_this_iteration = NULL_MOVE ;
104103 self . evaluation_this_iteration = 0 ;
105104
106105
107- let mut window = 40 ;
108106 loop {
109107 let ( alpha, beta) = ( last_evaluation - window, last_evaluation + window) ;
110108
@@ -124,7 +122,7 @@ impl Bot {
124122 self . evaluation = self . evaluation_this_iteration ;
125123 }
126124
127- println ! ( "Depth: {}, Window: {}, Evaluation: {}, Best move: {}, Positions searched: {}, Quiescence positions searched: {}, Total: {}, Transposition Hits: {}, Null move prunes : {}" ,
125+ println ! ( "Depth: {}, Window: {}, Evaluation: {}, Best move: {}, Positions searched: {} + Quiescence positions searched: {} = {}, Transposition Hits: {}" ,
128126 depth,
129127 window,
130128 self . evaluation * board. perspective( ) ,
@@ -133,7 +131,6 @@ impl Bot {
133131 self . quiescence_searched,
134132 self . positions_searched + self . quiescence_searched,
135133 self . transposition_hits,
136- self . null_move_prunes,
137134 ) ;
138135
139136 if evaluation_is_mate ( self . evaluation ) {
@@ -196,37 +193,45 @@ impl Bot {
196193 return data. evaluation ;
197194 }
198195
199- // Razoring
200- if depth_left == 3
196+ let is_pv = alpha != beta - 1 ;
197+
198+ if !is_pv
201199 && depth > 0
202- && board . get_last_move ( ) . capture == NO_PIECE as u8
200+ && depth_left > 0
203201 && !board. king_in_check ( board. white_to_move ) {
204- let evaluation = board . evaluate ( ) ;
205- if evaluation + QUEEN_WORTH < alpha {
206- depth_left -= 1 ;
207- }
208- }
202+ // Null Move Pruning
203+ if depth_left >= 3
204+ && board . try_null_move ( ) {
205+ // let reduction = 3 - (depth_left - 3) / 2;
206+ let evaluation = - self . alpha_beta_search ( board , depth + 1 , depth_left - 3 , -beta , -beta + 1 , number_of_extensions ) ;
209207
210- if depth_left == 0 {
211- return self . quiescence_search ( board, alpha, beta) ;
212- }
208+ board. undo_null_move ( ) ;
213209
214- let is_pv = alpha != beta - 1 ;
210+ if evaluation >= beta {
211+ return evaluation;
212+ }
213+ }
215214
216- if !is_pv
217- && depth > 0
218- && depth_left >= 3
219- && board. try_null_move ( ) {
220- let evaluation = -self . alpha_beta_search ( board, depth + 1 , depth_left - 3 , -beta, -beta + 1 , number_of_extensions) ;
215+ let static_eval = board. evaluate ( ) ;
221216
222- board. undo_null_move ( ) ;
217+ // Reverse Futility Pruning
218+ if depth_left <= 4
219+ && static_eval - ( 70 * depth_left as i32 ) >= beta {
220+ return static_eval;
221+ }
223222
224- if evaluation >= beta {
225- self . null_move_prunes += 1 ;
226- return evaluation;
223+ // Razoring
224+ if depth_left <= 3
225+ && board. get_last_move ( ) . capture == NO_PIECE as u8
226+ && static_eval + QUEEN_WORTH < alpha {
227+ depth_left -= 1 ;
227228 }
228229 }
229230
231+ if depth_left == 0 {
232+ return self . quiescence_search ( board, alpha, beta) ;
233+ }
234+
230235 let mut best_move_this_search = NULL_MOVE ;
231236 let mut node_type = NodeType :: UpperBound ;
232237
@@ -270,6 +275,7 @@ impl Bot {
270275
271276
272277
278+ // Late Move Reduction / (Kind of) Principal Variation Search
273279 let mut evaluation = 0 ;
274280 let mut needs_full_search = true ;
275281
@@ -346,7 +352,9 @@ impl Bot {
346352 return evaluation;
347353 }
348354
349- let sorted_moves = self . move_sorter . sort_moves ( board, legal_moves, NULL_MOVE , 0 ) ;
355+ // Depth is set to u8::MAX because it's only used for killer moves, and we don't need that here
356+ let sorted_moves = self . move_sorter . sort_moves ( board, legal_moves, NULL_MOVE , u8:: MAX ) ;
357+
350358 for m in sorted_moves {
351359 board. make_move ( m) ;
352360 let evaluation = -self . quiescence_search ( board, -beta, -alpha) ;
0 commit comments