@@ -57,19 +57,20 @@ impl Algorithm {
57
57
stats : & mut Stats ,
58
58
num_extensions : u32 ,
59
59
board_played_times_prediction : & mut HashMap < Board , u32 > ,
60
- mut incremental_psqt_eval : f32 ,
60
+ mut mg_incremental_psqt_eval : f32 ,
61
+ mut eg_incremental_psqt_eval : f32 ,
61
62
) -> Evaluation {
62
63
if depth == 0 {
63
64
stats. leaves_visited += 1 ;
64
- let eval = self . eval ( board, board_played_times_prediction, incremental_psqt_eval ) ;
65
+ let eval = self . eval ( board, board_played_times_prediction, mg_incremental_psqt_eval , eg_incremental_psqt_eval ) ;
65
66
if module_enabled ( self . modules , TRANSPOSITION_TABLE ) {
66
67
let start = Instant :: now ( ) ;
67
68
self . transposition_table
68
69
. insert ( * board, TranspositionEntry :: new ( depth, eval, None ) ) ;
69
70
stats. time_for_transposition_access += Instant :: now ( ) - start;
70
71
stats. transposition_table_entries += 1
71
72
}
72
- return Evaluation :: new ( Some ( eval) , None , None , Some ( incremental_psqt_eval ) ) ;
73
+ return Evaluation :: new ( Some ( eval) , None , None , Some ( mg_incremental_psqt_eval + eg_incremental_psqt_eval ) ) ;
73
74
}
74
75
75
76
// Whether we should try to maximise the eval
@@ -163,7 +164,7 @@ impl Algorithm {
163
164
Some ( transposition_entry. unwrap ( ) . eval ) ,
164
165
transposition_entry. unwrap ( ) . next_action ,
165
166
None ,
166
- Some ( incremental_psqt_eval ) ,
167
+ Some ( mg_incremental_psqt_eval + eg_incremental_psqt_eval ) ,
167
168
)
168
169
} else {
169
170
board_played_times_prediction. insert (
@@ -180,7 +181,8 @@ impl Algorithm {
180
181
stats,
181
182
num_extensions + extend_by,
182
183
board_played_times_prediction,
183
- incremental_psqt_eval,
184
+ mg_incremental_psqt_eval,
185
+ eg_incremental_psqt_eval
184
186
) ;
185
187
board_played_times_prediction. insert (
186
188
new_board,
@@ -241,50 +243,64 @@ impl Algorithm {
241
243
fn calc_increment (
242
244
piece_type : Piece ,
243
245
location : usize ,
244
- material_each_side : ( u32 , u32 ) ,
246
+ mg_eg : bool
245
247
) -> f32 {
246
- ( material_each_side. 0 + material_each_side. 1 - 2 * piece_value ( Piece :: King ) )
247
- as f32
248
- * TAPERED_MG_PESTO [ piece_type. to_index ( ) ] [ location]
249
- + ( 78 - material_each_side. 0 + material_each_side. 1
250
- - 2 * piece_value ( Piece :: King ) ) as f32
251
- * TAPERED_EG_PESTO [ piece_type. to_index ( ) ] [ location]
248
+ if mg_eg {
249
+ TAPERED_MG_PESTO [ piece_type. to_index ( ) ] [ location]
250
+ } else {
251
+ TAPERED_EG_PESTO [ piece_type. to_index ( ) ] [ location]
252
+ }
252
253
}
253
- let moved_piece_type = board. piece_on ( chess_move. get_source ( ) ) . unwrap ( ) ;
254
+ let moved_piece_type= board. piece_on ( chess_move. get_source ( ) ) . unwrap ( ) ;
254
255
255
256
let multiplier = if board. side_to_move ( ) == Color :: White {
256
257
1
257
258
} else {
258
259
-1
259
260
} ;
260
- let mut incremental_psqt_eval_change = 0. ;
261
- if incremental_psqt_eval_change == 0. {
262
- incremental_psqt_eval_change +=
263
- Self :: calc_tapered_psqt_eval ( board, material_each_side) ;
261
+ let mut mg_incremental_psqt_eval_change = 0. ;
262
+ let mut eg_incremental_psqt_eval_change = 0. ;
263
+ if mg_incremental_psqt_eval_change == 0. || eg_incremental_psqt_eval_change == 0. {
264
+ mg_incremental_psqt_eval_change +=
265
+ Self :: calc_tapered_psqt_eval ( board, material_each_side, 0 , true )
266
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 1 , true )
267
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 2 , true )
268
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 3 , true )
269
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 4 , true )
270
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 5 , true ) ;
271
+ eg_incremental_psqt_eval_change +=
272
+ Self :: calc_tapered_psqt_eval ( board, material_each_side, 0 , false )
273
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 1 , false )
274
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 2 , false )
275
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 3 , false )
276
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 4 , false )
277
+ + Self :: calc_tapered_psqt_eval ( board, material_each_side, 5 , false ) ;
264
278
} else {
265
279
//Remove the eval from the previous square we stood on.
266
280
let source: usize = ( 56 - chess_move. get_source ( ) . to_int ( )
267
281
+ 2 * ( chess_move. get_source ( ) . to_int ( ) % 8 ) )
268
282
as usize ;
269
- incremental_psqt_eval_change -=
270
- calc_increment ( moved_piece_type, source, material_each_side ) ;
283
+ mg_incremental_psqt_eval_change += calc_increment ( moved_piece_type , source , true ) ;
284
+ eg_incremental_psqt_eval_change += calc_increment ( moved_piece_type, source, false ) ;
271
285
272
286
//Increase the eval at the destination
273
287
let dest: usize = ( 56 - chess_move. get_dest ( ) . to_int ( )
274
288
+ 2 * ( chess_move. get_dest ( ) . to_int ( ) % 8 ) )
275
289
as usize ;
276
- incremental_psqt_eval_change +=
277
- calc_increment ( moved_piece_type, dest, material_each_side ) ;
290
+ mg_incremental_psqt_eval_change += calc_increment ( moved_piece_type , dest , true ) ;
291
+ eg_incremental_psqt_eval_change += calc_increment ( moved_piece_type, dest, false ) ;
278
292
279
293
//Decrement enemy eval from potetntial capture
280
294
if let Some ( attacked_piece_type) = board. piece_on ( chess_move. get_dest ( ) ) {
281
- incremental_psqt_eval_change +=
282
- calc_increment ( attacked_piece_type, dest, material_each_side ) ;
295
+ mg_incremental_psqt_eval_change += calc_increment ( attacked_piece_type , dest , true ) ;
296
+ eg_incremental_psqt_eval_change += calc_increment ( attacked_piece_type, dest, false ) ;
283
297
}
284
298
}
285
- incremental_psqt_eval += incremental_psqt_eval_change * multiplier as f32 ;
299
+ mg_incremental_psqt_eval += mg_incremental_psqt_eval_change * multiplier as f32 ;
300
+ eg_incremental_psqt_eval += eg_incremental_psqt_eval_change * multiplier as f32 ;
286
301
}
287
- best_evaluation. incremental_psqt_eval = Some ( incremental_psqt_eval) ;
302
+ best_evaluation. incremental_psqt_eval =
303
+ Some ( mg_incremental_psqt_eval + eg_incremental_psqt_eval) ;
288
304
}
289
305
290
306
if module_enabled ( self . modules , TRANSPOSITION_TABLE ) && depth >= 3 {
@@ -327,6 +343,7 @@ impl Algorithm {
327
343
0 ,
328
344
& mut HashMap :: new ( ) ,
329
345
0. ,
346
+ 0. ,
330
347
) ;
331
348
let analyzer_data = out. debug_data . unwrap_or_default ( ) ;
332
349
( out. next_action , analyzer_data, stats)
@@ -393,7 +410,8 @@ impl Algorithm {
393
410
& mut self ,
394
411
board : & Board ,
395
412
board_played_times_prediction : & HashMap < Board , u32 > ,
396
- incremental_psqt_eval : f32 ,
413
+ mg_incremental_psqt_eval : f32 ,
414
+ eg_incremental_psqt_eval : f32
397
415
) -> f32 {
398
416
let board_status = board. status ( ) ;
399
417
if board_status == BoardStatus :: Stalemate {
@@ -492,9 +510,27 @@ impl Algorithm {
492
510
) ;
493
511
}
494
512
513
+ let mut mg_tapered_pesto: f32 = 0. ;
514
+ let mut eg_tapered_pesto: f32 = 0. ;
495
515
let mut tapered_pesto: f32 = 0. ;
496
516
if utils:: module_enabled ( self . modules , modules:: TAPERED_EVERY_PESTO_PSQT ) {
497
- tapered_pesto = Self :: calc_tapered_psqt_eval ( board, material_each_side)
517
+ tapered_pesto = Self :: calc_tapered_psqt_eval ( board, material_each_side, 0 , true ) ;
518
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 0 , true ) ;
519
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 1 , true ) ;
520
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 2 , true ) ;
521
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 3 , true ) ;
522
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 4 , true ) ;
523
+ mg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 5 , true ) ;
524
+
525
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 0 , false ) ;
526
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 1 , false ) ;
527
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 2 , false ) ;
528
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 3 , false ) ;
529
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 4 , false ) ;
530
+ eg_tapered_pesto += Self :: calc_tapered_psqt_eval ( board, material_each_side, 5 , false ) ;
531
+ tapered_pesto = ( ( material_each_side. 0 + material_each_side. 1 - 2 * piece_value ( Piece :: King ) ) as f32 * mg_tapered_pesto +
532
+ ( 78 - ( material_each_side. 0 + material_each_side. 1 - 2 * piece_value ( Piece :: King ) ) ) as f32 * eg_tapered_pesto)
533
+ / 78. ;
498
534
}
499
535
500
536
let mut pawn_structure: f32 = 0. ;
@@ -509,8 +545,8 @@ impl Algorithm {
509
545
let king_bitboard: usize = ( all_king_bitboard & color_bitboard) . to_size ( 0 ) ;
510
546
//pawn chain, awarding 0.5 eval for each pawn protected by another pawn. Constants should in theory cover an (literal) edge case... I hope.
511
547
bonus += 0.5
512
- * ( ( pawn_bitboard & ( 0xFEFEFEFEFEFEFEFE & pawn_bitboard << 7 ) ) . count_ones ( )
513
- + ( pawn_bitboard & ( 0x7F7F7F7F7F7F7F7F & pawn_bitboard << 9 ) ) . count_ones ( ) )
548
+ * ( ( pawn_bitboard & 0xFEFEFEFEFEFEFEFE & ( pawn_bitboard << 9 ) ) . count_ones ( )
549
+ + ( pawn_bitboard & 0x7F7F7F7F7F7F7F7F & ( pawn_bitboard << 7 ) ) . count_ones ( ) )
514
550
as f32 ;
515
551
516
552
//stacked pawns. -0.5 points per rank containing >1 pawns. By taking the pawn bitboard and operating bitwise AND for another bitboard (integer) where the leftmost rank is filled. This returns all pawns in that rank. By bitshifting we can choose rank. Additionally by counting we get number of pawns. We then remove 1 as we only want to know if there are >1 pawn. If there is, subtract 0.5 points per extra pawn.
@@ -521,9 +557,9 @@ impl Algorithm {
521
557
. max ( 0. ) ;
522
558
}
523
559
524
- //king safety. Outer 3 pawns get +1 eval bonus per pawn if king is behind them. King naive_psqt required is either ..X..... or ......X.
525
- bonus += ( ( king_bitboard & 0x2 ) . count_ones ( ) * ( pawn_bitboard & 0x107 ) . count_ones ( )
526
- + ( king_bitboard & 0x20 ) . count_ones ( ) * ( pawn_bitboard & 0x80E000 ) . count_ones ( ) )
560
+ //king safety. Outer 3 pawns get +1 eval bonus per pawn if king is behind them. King bitboard required is either ..X..... or ......X.
561
+ bonus += ( ( king_bitboard & 0x40 ) . count_ones ( ) * ( pawn_bitboard & 0x80E000 ) . count_ones ( )
562
+ + ( king_bitboard & 0x4 ) . count_ones ( ) * ( pawn_bitboard & 0x1070000 ) . count_ones ( ) )
527
563
as f32 ;
528
564
bonus
529
565
}
@@ -541,6 +577,12 @@ impl Algorithm {
541
577
pawn_structure = * self . pawn_hash . get ( & pawn_bitboard) . unwrap ( ) ;
542
578
}
543
579
580
+ let mut incremental_psqt_eval: f32 = 0. ;
581
+ if utils:: module_enabled ( self . modules , modules:: TAPERED_INCREMENTAL_PESTO_PSQT ) {
582
+ incremental_psqt_eval = ( material_each_side. 0 + material_each_side. 1 - 2 * piece_value ( Piece :: King ) ) as f32 * mg_incremental_psqt_eval
583
+ + ( 78 - material_each_side. 0 + material_each_side. 1 - 2 * piece_value ( Piece :: King ) ) as f32 * eg_incremental_psqt_eval
584
+ }
585
+
544
586
let evaluation: f32 = controlled_squares as f32 / 20.
545
587
+ diff_material as f32
546
588
+ naive_psqt
@@ -550,52 +592,62 @@ impl Algorithm {
550
592
evaluation
551
593
}
552
594
553
- fn calc_tapered_psqt_eval ( board : & Board , material_each_side : ( u32 , u32 ) ) -> f32 {
595
+ fn calc_tapered_psqt_eval ( board : & Board , material_each_side : ( u32 , u32 ) , piece : u8 , mg_eg : bool ) -> f32 {
554
596
fn tapered_psqt_calc (
555
597
piece_bitboard : & BitBoard ,
556
598
color_bitboard : & BitBoard ,
557
- material : ( u32 , u32 ) ,
558
599
piece_index : usize ,
600
+ mg_eg : bool
559
601
) -> f32 {
560
602
// Essentially, gets the dot product between a "vector" of the bitboard (containing 64 0s and 1s) and the table with NAIVE_PSQT bonus constants.
561
603
let mut bonus: f32 = 0. ;
562
- // Gets the bitboard with all piece positions, and runs bitwise and for the board having one's own colors.
563
- // Iterates over all 64 squares on the board.
564
- for i in 0 ..63 {
565
- // The psqt tables and bitboards are flipped vertically, hence .reverse_colors().
566
- // Reverse colors is for some reason faster than replacing i with 56-i+2*(i%8).
567
- // By being tapered, it means that we have an (opening + middlegame) and an endgame PSQT,
568
- // and we (hopefully?) linerarly transition from one to the other, depending on material value.
569
- bonus += ( ( piece_bitboard & color_bitboard)
570
- . reverse_colors ( )
571
- . to_size ( i as u8 )
572
- & 1 ) as f32
573
- * ( ( material. 0 + material. 1 - 2 * piece_value ( Piece :: King ) ) as f32
574
- * TAPERED_MG_PESTO [ piece_index] [ i]
575
- + ( 78 - ( material. 0 + material. 1 - 2 * piece_value ( Piece :: King ) ) ) as f32
576
- * TAPERED_EG_PESTO [ piece_index] [ i] ) ;
604
+
605
+ if mg_eg {
606
+ // Gets the bitboard with all piece positions, and runs bitwise and for the board having one's own colors.
607
+ // Iterates over all 64 squares on the board.
608
+ for i in 0 ..63 {
609
+ // The psqt tables and bitboards are flipped vertically, hence .reverse_colors().
610
+ // Reverse colors is for some reason faster than replacing i with 56-i+2*(i%8).
611
+ // By being tapered, it means that we have an (opening + middlegame) and an endgame PSQT,
612
+ // and we (hopefully?) linerarly transition from one to the other, depending on material value.
613
+ bonus += ( ( piece_bitboard & color_bitboard)
614
+ . reverse_colors ( )
615
+ . to_size ( i as u8 ) & 1 ) as f32
616
+ * TAPERED_MG_PESTO [ piece_index] [ i] ;
617
+ }
618
+ bonus
619
+ } else {
620
+ for i in 0 ..63 {
621
+ bonus += ( ( piece_bitboard & color_bitboard)
622
+ . reverse_colors ( )
623
+ . to_size ( i as u8 ) & 1 ) as f32
624
+ * TAPERED_EG_PESTO [ piece_index] [ i] ;
625
+ }
626
+ bonus
577
627
}
578
- bonus / 78.
579
- }
580
628
629
+ }
630
+
581
631
macro_rules! tapered_psqt_calc {
582
- ( $board: tt, $piece: tt, $material : tt, $index : tt) => {
632
+ ( $board: tt, $piece: tt, $index : tt, $mg_eg : tt) => {
583
633
tapered_psqt_calc(
584
634
$board. pieces( Piece :: $piece) ,
585
635
$board. color_combined( $board. side_to_move( ) ) ,
586
- $material,
587
636
$index,
637
+ $mg_eg
588
638
)
589
639
} ;
590
640
}
591
- let mut tapered_pesto = 0. ;
592
- tapered_pesto += tapered_psqt_calc ! ( board, Pawn , material_each_side, 0 ) ;
593
- tapered_pesto += tapered_psqt_calc ! ( board, Rook , material_each_side, 3 ) ;
594
- tapered_pesto += tapered_psqt_calc ! ( board, King , material_each_side, 5 ) ;
595
- tapered_pesto += tapered_psqt_calc ! ( board, Queen , material_each_side, 4 ) ;
596
- tapered_pesto += tapered_psqt_calc ! ( board, Bishop , material_each_side, 2 ) ;
597
- tapered_pesto += tapered_psqt_calc ! ( board, Knight , material_each_side, 1 ) ;
598
- tapered_pesto
641
+ match piece {
642
+ 0 => tapered_psqt_calc ! ( board, Pawn , 0 , mg_eg) ,
643
+ 1 => tapered_psqt_calc ! ( board, Knight , 1 , mg_eg) ,
644
+ 2 => tapered_psqt_calc ! ( board, Bishop , 2 , mg_eg) ,
645
+ 3 => tapered_psqt_calc ! ( board, Rook , 3 , mg_eg) ,
646
+ 4 => tapered_psqt_calc ! ( board, Queen , 4 , mg_eg) ,
647
+ 5 => tapered_psqt_calc ! ( board, King , 5 , mg_eg) ,
648
+ 6_u8 ..=u8:: MAX => unimplemented ! ( )
649
+ }
650
+
599
651
}
600
652
601
653
pub ( crate ) fn reset ( & mut self ) {
0 commit comments