1
1
use std:: { collections:: HashMap , cmp} ;
2
2
use tokio:: time:: { Duration , Instant } ;
3
- use rustc_hash:: FxHasher ;
4
3
5
- use chess:: { Action , Board , BoardStatus , ChessMove , Color , MoveGen , Piece , BitBoard } ;
4
+ use chess:: { Action , Board , BoardStatus , ChessMove , Color , MoveGen , Piece , BitBoard , Square } ;
6
5
7
6
use crate :: common:: constants:: { modules:: { self , * } , naive_psqt_tables:: * , tapered_pesto_psqt_tables:: * } ;
8
7
use crate :: common:: utils:: { self , module_enabled, Stats } ;
@@ -55,25 +54,31 @@ impl Algorithm {
55
54
stats : & mut Stats ,
56
55
num_extensions : u32 ,
57
56
board_played_times_prediction : & mut HashMap < Board , u32 > ,
57
+ mut white_incremental_psqt_eval : f32 ,
58
+ mut black_incremental_psqt_eval : f32 ,
58
59
) -> Evaluation {
59
60
60
61
61
62
if depth == 0 {
62
63
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) ;
64
65
// if module_enabled(self.modules, TRANSPOSITION_TABLE) {
65
66
// let start = Instant::now();
66
67
// self.transposition_table
67
68
// .insert(*board, TranspositionEntry::new(depth, eval, None));
68
69
// stats.time_for_transposition_access += Instant::now() - start;
69
70
// stats.transposition_table_entries += 1
70
71
// }
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) ) ;
72
77
}
73
78
74
79
// Whether we should try to maximise the eval
75
80
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 ) ;
77
82
78
83
let legal_moves = MoveGen :: new_legal ( board) ;
79
84
let num_legal_moves = legal_moves. len ( ) ;
@@ -162,6 +167,8 @@ impl Algorithm {
162
167
Some ( transposition_entry. unwrap ( ) . eval ) ,
163
168
transposition_entry. unwrap ( ) . next_action ,
164
169
None ,
170
+ Some ( white_incremental_psqt_eval) ,
171
+ Some ( black_incremental_psqt_eval)
165
172
)
166
173
} else {
167
174
board_played_times_prediction. insert (
@@ -178,6 +185,8 @@ impl Algorithm {
178
185
stats,
179
186
num_extensions + extend_by,
180
187
board_played_times_prediction,
188
+ white_incremental_psqt_eval,
189
+ black_incremental_psqt_eval,
181
190
) ;
182
191
board_played_times_prediction. insert (
183
192
new_board,
@@ -232,6 +241,106 @@ impl Algorithm {
232
241
break ;
233
242
}
234
243
}
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) ;
235
344
}
236
345
237
346
if module_enabled ( self . modules , TRANSPOSITION_TABLE ) && depth >= 3 {
@@ -273,6 +382,8 @@ impl Algorithm {
273
382
& mut stats,
274
383
0 ,
275
384
& mut HashMap :: new ( ) ,
385
+ 0. ,
386
+ 0.
276
387
) ;
277
388
let analyzer_data = out. debug_data . unwrap_or_default ( ) ;
278
389
( out. next_action , analyzer_data, stats)
@@ -331,9 +442,7 @@ impl Algorithm {
331
442
}
332
443
self . board_played_times . insert ( new_board, old_value + 1 ) ;
333
444
334
- if utils:: module_enabled ( self . modules , modules:: TAPERED_INCREMENTAL_PESTO_PSQT ) {
335
-
336
- }
445
+
337
446
}
338
447
339
448
( action, deepest_complete_output. 1 , deepest_complete_output. 2 )
@@ -343,8 +452,7 @@ impl Algorithm {
343
452
& mut self ,
344
453
board : & Board ,
345
454
board_played_times_prediction : & HashMap < Board , u32 > ,
346
- incremental_eval : f32 ,
347
- ) -> f32 {
455
+ ) -> f32 {
348
456
let board_status = board. status ( ) ;
349
457
if board_status == BoardStatus :: Stalemate {
350
458
return 0. ;
@@ -417,34 +525,35 @@ impl Algorithm {
417
525
418
526
let mut tapered_pesto: f32 = 0. ;
419
527
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 {
421
529
//Essentially, gets the dot product between a "vector" of the bitboard (containing 64 0s and 1s) and the table with NAIVE_PSQT bonus constants.
422
530
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.
424
533
for i in 0 ..63 {
425
534
//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.
427
536
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 ;
429
538
}
430
- return bonus;
539
+ return bonus / 78. ;
431
540
}
432
541
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
+ }
448
557
}
449
558
450
559
let mut pawn_structure: f32 = 0. ;
0 commit comments