11use std:: { collections:: HashMap , cmp} ;
22use tokio:: time:: { Duration , Instant } ;
3- use rustc_hash:: FxHasher ;
43
5- use chess:: { Action , Board , BoardStatus , ChessMove , Color , MoveGen , Piece , BitBoard } ;
4+ use chess:: { Action , Board , BoardStatus , ChessMove , Color , MoveGen , Piece , BitBoard , Square } ;
65
76use crate :: common:: constants:: { modules:: { self , * } , naive_psqt_tables:: * , tapered_pesto_psqt_tables:: * } ;
87use crate :: common:: utils:: { self , module_enabled, Stats } ;
@@ -55,25 +54,31 @@ impl Algorithm {
5554 stats : & mut Stats ,
5655 num_extensions : u32 ,
5756 board_played_times_prediction : & mut HashMap < Board , u32 > ,
57+ mut white_incremental_psqt_eval : f32 ,
58+ mut black_incremental_psqt_eval : f32 ,
5859 ) -> Evaluation {
5960
6061
6162 if depth == 0 {
6263 stats. leaves_visited += 1 ;
63- let eval = self . eval ( board, board_played_times_prediction, 0. ) ;
64+ let eval = self . eval ( board, board_played_times_prediction) ;
6465 // if module_enabled(self.modules, TRANSPOSITION_TABLE) {
6566 // let start = Instant::now();
6667 // self.transposition_table
6768 // .insert(*board, TranspositionEntry::new(depth, eval, None));
6869 // stats.time_for_transposition_access += Instant::now() - start;
6970 // stats.transposition_table_entries += 1
7071 // }
71- return Evaluation :: new ( Some ( eval) , None , None ) ;
72+ let incremental_psqt_eval = white_incremental_psqt_eval;
73+ if board. side_to_move ( ) == Color :: Black {
74+ let incremental_psqt_eval = black_incremental_psqt_eval;
75+ }
76+ return Evaluation :: new ( Some ( eval + incremental_psqt_eval) , None , None , Some ( white_incremental_psqt_eval) , Some ( black_incremental_psqt_eval) ) ;
7277 }
7378
7479 // Whether we should try to maximise the eval
7580 let maximise: bool = board. side_to_move ( ) == Color :: White ;
76- let mut best_evaluation = Evaluation :: new ( None , None , None ) ;
81+ let mut best_evaluation = Evaluation :: new ( None , None , None , None , None ) ;
7782
7883 let legal_moves = MoveGen :: new_legal ( board) ;
7984 let num_legal_moves = legal_moves. len ( ) ;
@@ -162,6 +167,8 @@ impl Algorithm {
162167 Some ( transposition_entry. unwrap ( ) . eval ) ,
163168 transposition_entry. unwrap ( ) . next_action ,
164169 None ,
170+ Some ( white_incremental_psqt_eval) ,
171+ Some ( black_incremental_psqt_eval)
165172 )
166173 } else {
167174 board_played_times_prediction. insert (
@@ -178,6 +185,8 @@ impl Algorithm {
178185 stats,
179186 num_extensions + extend_by,
180187 board_played_times_prediction,
188+ white_incremental_psqt_eval,
189+ black_incremental_psqt_eval,
181190 ) ;
182191 board_played_times_prediction. insert (
183192 new_board,
@@ -232,6 +241,106 @@ impl Algorithm {
232241 break ;
233242 }
234243 }
244+
245+ if utils:: module_enabled ( self . modules , modules:: TAPERED_INCREMENTAL_PESTO_PSQT ) {
246+
247+
248+ fn match_piece_to_int ( input : Option < Piece > ) -> usize {
249+ match input {
250+ Some ( Piece :: Pawn ) => 0 ,
251+ Some ( Piece :: Knight ) => 1 ,
252+ Some ( Piece :: Bishop ) => 2 ,
253+ Some ( Piece :: Rook ) => 3 ,
254+ Some ( Piece :: Queen ) => 4 ,
255+ Some ( Piece :: King ) => 5 ,
256+ //Note: Returning a 6 is not intended, and must be handled on a case-by-case basis.
257+ None => 6
258+ }
259+ }
260+
261+ fn match_int_to_piece ( input : u8 ) -> Piece {
262+ match input {
263+ 0 => Piece :: Pawn ,
264+ 1 => Piece :: Knight ,
265+ 2 => Piece :: Bishop ,
266+ 3 => Piece :: Rook ,
267+ 4 => Piece :: Queen ,
268+ 5 => Piece :: King ,
269+ //Any other input to the function besides 0..5 is terrible behaviour from the input case, and should not happen. I'm simply going to *not* handle that case. Good luck!
270+ 6_u8 ..=u8:: MAX => unimplemented ! ( )
271+ }
272+ }
273+
274+ let material_each_side = utils:: material_each_side ( board) ;
275+ fn calc_increment ( piece_type : usize , location : usize , material_each_side : ( u32 , u32 ) ) -> f32 {
276+ return ( ( material_each_side. 0 + material_each_side. 1 - 2000 ) as f32 * TAPERED_MG_PESTO [ piece_type] [ location] + ( material_each_side. 0 + material_each_side. 1 - 2000 + 78 ) as f32 * TAPERED_EG_PESTO [ piece_type] [ location] ) as f32 ;
277+ }
278+
279+ fn calc_increment_all ( board : & Board , color_bitboard : & BitBoard , material_each_side : ( u32 , u32 ) ) -> f32 {
280+ let mut incremental_psqt_eval: f32 = 0. ;
281+ //Essentially, gets the dot product between a "vector" of the bitboard (containing 64 0s and 1s) and the table with NAIVE_PSQT bonus constants.
282+ //Get's the bitboard with all piece positions, and runs bitwise and for the board having one's own colors.
283+ //Iterates over all types of squares
284+ for j in 0 ..5 {
285+ //Iterates over all 64 squares on the board.
286+ for i in 0 ..63 {
287+ //The psqt tables and bitboards are flipped vertically, hence .reverse_colors(). Reverse colors is for some reason faster than replacing i with 56-i+2*(i%8).
288+ //By being tapered, it means that we have an (opening + middlgame) and an endgame PSQT, and we (hopefully?) linerarly transition from one to the other, depending on material value.
289+ incremental_psqt_eval += ( ( board. pieces ( match_int_to_piece ( j) ) & color_bitboard) . reverse_colors ( ) . to_size ( 0 ) >> i & 1 ) as f32 *
290+ ( ( material_each_side. 0 + material_each_side. 1 - 2000 ) as f32 * TAPERED_MG_PESTO [ j as usize ] [ i as usize ] + ( material_each_side. 0 + material_each_side. 1 - 2000 + 78 ) as f32 * TAPERED_EG_PESTO [ j as usize ] [ i as usize ] ) as f32 / 78. ;
291+ }
292+ }
293+ return incremental_psqt_eval;
294+ }
295+ let moved_piece_type: usize = match_piece_to_int ( board. piece_on ( chess_move. get_source ( ) ) ) ;
296+
297+ let mut is_attacked: bool = true ;
298+ if match_piece_to_int ( board. piece_on ( chess_move. get_dest ( ) ) ) == 6 {
299+ is_attacked = false ;
300+ }
301+ let attacked_piece_type: usize = match_piece_to_int ( board. piece_on ( chess_move. get_dest ( ) ) ) ;
302+
303+ if board. side_to_move ( ) == Color :: White {
304+ let color_bitboard: & BitBoard = & board. color_combined ( Color :: White ) ;
305+ if white_incremental_psqt_eval == 0. {
306+ white_incremental_psqt_eval += calc_increment_all ( board, color_bitboard, material_each_side)
307+ } else {
308+
309+ //Remove the eval from the previous square we stood on.
310+ let source: usize = ( 56 - chess_move. get_source ( ) . to_int ( ) + 2 * ( chess_move. get_source ( ) . to_int ( ) % 8 ) ) as usize ;
311+ white_incremental_psqt_eval -= calc_increment ( moved_piece_type, source, material_each_side) ;
312+
313+ //Increase the eval at the destination
314+ let dest: usize = ( 56 - chess_move. get_dest ( ) . to_int ( ) + 2 * ( chess_move. get_dest ( ) . to_int ( ) % 8 ) ) as usize ;
315+ white_incremental_psqt_eval += calc_increment ( moved_piece_type, dest, material_each_side) ;
316+
317+ //Decrement enemy eval from potetntial capture
318+ if is_attacked {
319+ black_incremental_psqt_eval -= calc_increment ( attacked_piece_type, dest, material_each_side) ;
320+ }
321+ }
322+ } else {
323+ let color_bitboard: & BitBoard = & board. color_combined ( Color :: Black ) ;
324+ if black_incremental_psqt_eval == 0. {
325+ black_incremental_psqt_eval += calc_increment_all ( board, color_bitboard, material_each_side)
326+ } else {
327+ //Remove the eval from the previous square we stood on.
328+ let source: usize = ( 56 - chess_move. get_source ( ) . to_int ( ) + 2 * ( chess_move. get_source ( ) . to_int ( ) % 8 ) ) as usize ;
329+ black_incremental_psqt_eval -= calc_increment ( moved_piece_type, source, material_each_side) ;
330+
331+ //Increase the eval at the destination
332+ let dest: usize = ( 56 - chess_move. get_dest ( ) . to_int ( ) + 2 * ( chess_move. get_dest ( ) . to_int ( ) % 8 ) ) as usize ;
333+ black_incremental_psqt_eval += calc_increment ( moved_piece_type, dest, material_each_side) ;
334+
335+ //Decrement enemy eval from potetntial capture
336+ if is_attacked {
337+ white_incremental_psqt_eval -= calc_increment ( attacked_piece_type, dest, material_each_side) ;
338+ }
339+ }
340+ }
341+ }
342+ best_evaluation. white_incremental_psqt_eval = Some ( white_incremental_psqt_eval) ;
343+ best_evaluation. black_incremental_psqt_eval = Some ( black_incremental_psqt_eval) ;
235344 }
236345
237346 if module_enabled ( self . modules , TRANSPOSITION_TABLE ) && depth >= 3 {
@@ -273,6 +382,8 @@ impl Algorithm {
273382 & mut stats,
274383 0 ,
275384 & mut HashMap :: new ( ) ,
385+ 0. ,
386+ 0.
276387 ) ;
277388 let analyzer_data = out. debug_data . unwrap_or_default ( ) ;
278389 ( out. next_action , analyzer_data, stats)
@@ -331,9 +442,7 @@ impl Algorithm {
331442 }
332443 self . board_played_times . insert ( new_board, old_value + 1 ) ;
333444
334- if utils:: module_enabled ( self . modules , modules:: TAPERED_INCREMENTAL_PESTO_PSQT ) {
335-
336- }
445+
337446 }
338447
339448 ( action, deepest_complete_output. 1 , deepest_complete_output. 2 )
@@ -343,8 +452,7 @@ impl Algorithm {
343452 & mut self ,
344453 board : & Board ,
345454 board_played_times_prediction : & HashMap < Board , u32 > ,
346- incremental_eval : f32 ,
347- ) -> f32 {
455+ ) -> f32 {
348456 let board_status = board. status ( ) ;
349457 if board_status == BoardStatus :: Stalemate {
350458 return 0. ;
@@ -417,34 +525,35 @@ impl Algorithm {
417525
418526 let mut tapered_pesto: f32 = 0. ;
419527 if utils:: module_enabled ( self . modules , modules:: TAPERED_EVERY_PRESTO_PSQT ) {
420- fn tapered_psqt_calc ( piece_bitboard : & BitBoard , color_bitboard : & BitBoard , material : ( u32 , u32 ) , tapered_table_mg : [ f32 ; 64 ] , tapered_table_eg : [ f32 ; 64 ] ) -> f32 {
528+ fn tapered_psqt_calc ( piece_bitboard : & BitBoard , color_bitboard : & BitBoard , material : ( u32 , u32 ) , piece_index : usize ) -> f32 {
421529 //Essentially, gets the dot product between a "vector" of the bitboard (containing 64 0s and 1s) and the table with NAIVE_PSQT bonus constants.
422530 let mut bonus: f32 = 0. ;
423- //Get's the bitboard with all piece NAIVE_PSQTs, and runs bitwise and for the board having one's own colors.
531+ //Get's the bitboard with all piece positions, and runs bitwise and for the board having one's own colors.
532+ //Iterates over all 64 squares on the board.
424533 for i in 0 ..63 {
425534 //The psqt tables and bitboards are flipped vertically, hence .reverse_colors(). Reverse colors is for some reason faster than replacing i with 56-i+2*(i%8).
426- //By being tapered, it means that we have an opening + middlgame and an endgame PSQT, and we (hopefully?) linerarly transition from one to the other, depending on material value.
535+ //By being tapered, it means that we have an ( opening + middlgame) and an endgame PSQT, and we (hopefully?) linerarly transition from one to the other, depending on material value.
427536 bonus += ( ( piece_bitboard & color_bitboard) . reverse_colors ( ) . to_size ( 0 ) >> i & 1 ) as f32 *
428- ( ( material. 0 + material. 1 - 2000 ) as f32 / 78. * tapered_table_mg [ i] + ( material. 0 + material. 1 - 2000 + 78 ) as f32 / 78. * tapered_table_eg [ i] ) as f32 ;
537+ ( ( material. 0 + material. 1 - 2000 ) as f32 * TAPERED_MG_PESTO [ piece_index ] [ i] + ( material. 0 + material. 1 - 2000 + 78 ) as f32 * TAPERED_EG_PESTO [ piece_index ] [ i] ) as f32 ;
429538 }
430- return bonus;
539+ return bonus / 78. ;
431540 }
432541
433- if board. side_to_move ( ) == Color :: White {
434- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Pawn ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_PAWN , TAPERED_EG_PESTO_PAWN ) ;
435- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Rook ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_ROOK , TAPERED_EG_PESTO_ROOK ) ;
436- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: King ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_KING , TAPERED_EG_PESTO_KING ) ;
437- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Queen ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_QUEEN , TAPERED_EG_PESTO_QUEEN ) ;
438- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Bishop ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_BISHOP , TAPERED_EG_PESTO_BISHOP ) ;
439- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Knight ) , board. color_combined ( Color :: White ) , material_each_side, TAPERED_MG_PESTO_KNIGHT , TAPERED_EG_PESTO_KNIGT ) ;
440- } else {
441- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Pawn ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_PAWN , TAPERED_EG_PESTO_PAWN ) ;
442- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Rook ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_ROOK , TAPERED_EG_PESTO_ROOK ) ;
443- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: King ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_KING , TAPERED_EG_PESTO_KING ) ;
444- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Queen ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_QUEEN , TAPERED_EG_PESTO_QUEEN ) ;
445- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Bishop ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_BISHOP , TAPERED_EG_PESTO_BISHOP ) ;
446- tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Knight ) , board. color_combined ( Color :: Black ) , material_each_side, TAPERED_MG_PESTO_KNIGHT , TAPERED_EG_PESTO_KNIGT ) ;
447- }
542+ if board. side_to_move ( ) == Color :: White {
543+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Pawn ) , board. color_combined ( Color :: White ) , material_each_side, 0 ) ;
544+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Rook ) , board. color_combined ( Color :: White ) , material_each_side, 3 ) ;
545+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: King ) , board. color_combined ( Color :: White ) , material_each_side, 5 ) ;
546+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Queen ) , board. color_combined ( Color :: White ) , material_each_side, 4 ) ;
547+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Bishop ) , board. color_combined ( Color :: White ) , material_each_side, 2 ) ;
548+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Knight ) , board. color_combined ( Color :: White ) , material_each_side, 1 ) ;
549+ } else {
550+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Pawn ) , board. color_combined ( Color :: Black ) , material_each_side, 0 ) ;
551+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Rook ) , board. color_combined ( Color :: Black ) , material_each_side, 3 ) ;
552+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: King ) , board. color_combined ( Color :: Black ) , material_each_side, 5 ) ;
553+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Queen ) , board. color_combined ( Color :: Black ) , material_each_side, 4 ) ;
554+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Bishop ) , board. color_combined ( Color :: Black ) , material_each_side, 2 ) ;
555+ tapered_pesto += tapered_psqt_calc ( board. pieces ( Piece :: Knight ) , board. color_combined ( Color :: Black ) , material_each_side, 1 ) ;
556+ }
448557 }
449558
450559 let mut pawn_structure: f32 = 0. ;
0 commit comments