Skip to content

Commit 1d85d08

Browse files
committed
TIPeSTOPSQT tapering properly accounts for material changing over time
Still fails to actually perform though. Might be another bug present.
1 parent f9543ac commit 1d85d08

File tree

3 files changed

+117
-65
lines changed

3 files changed

+117
-65
lines changed

src/algorithms/the_algorithm.rs

+113-61
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,20 @@ impl Algorithm {
5757
stats: &mut Stats,
5858
num_extensions: u32,
5959
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,
6162
) -> Evaluation {
6263
if depth == 0 {
6364
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);
6566
if module_enabled(self.modules, TRANSPOSITION_TABLE) {
6667
let start = Instant::now();
6768
self.transposition_table
6869
.insert(*board, TranspositionEntry::new(depth, eval, None));
6970
stats.time_for_transposition_access += Instant::now() - start;
7071
stats.transposition_table_entries += 1
7172
}
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));
7374
}
7475

7576
// Whether we should try to maximise the eval
@@ -163,7 +164,7 @@ impl Algorithm {
163164
Some(transposition_entry.unwrap().eval),
164165
transposition_entry.unwrap().next_action,
165166
None,
166-
Some(incremental_psqt_eval),
167+
Some(mg_incremental_psqt_eval + eg_incremental_psqt_eval),
167168
)
168169
} else {
169170
board_played_times_prediction.insert(
@@ -180,7 +181,8 @@ impl Algorithm {
180181
stats,
181182
num_extensions + extend_by,
182183
board_played_times_prediction,
183-
incremental_psqt_eval,
184+
mg_incremental_psqt_eval,
185+
eg_incremental_psqt_eval
184186
);
185187
board_played_times_prediction.insert(
186188
new_board,
@@ -241,50 +243,64 @@ impl Algorithm {
241243
fn calc_increment(
242244
piece_type: Piece,
243245
location: usize,
244-
material_each_side: (u32, u32),
246+
mg_eg: bool
245247
) -> 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+
}
252253
}
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();
254255

255256
let multiplier = if board.side_to_move() == Color::White {
256257
1
257258
} else {
258259
-1
259260
};
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);
264278
} else {
265279
//Remove the eval from the previous square we stood on.
266280
let source: usize = (56 - chess_move.get_source().to_int()
267281
+ 2 * (chess_move.get_source().to_int() % 8))
268282
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);
271285

272286
//Increase the eval at the destination
273287
let dest: usize = (56 - chess_move.get_dest().to_int()
274288
+ 2 * (chess_move.get_dest().to_int() % 8))
275289
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);
278292

279293
//Decrement enemy eval from potetntial capture
280294
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);
283297
}
284298
}
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;
286301
}
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);
288304
}
289305

290306
if module_enabled(self.modules, TRANSPOSITION_TABLE) && depth >= 3 {
@@ -327,6 +343,7 @@ impl Algorithm {
327343
0,
328344
&mut HashMap::new(),
329345
0.,
346+
0.,
330347
);
331348
let analyzer_data = out.debug_data.unwrap_or_default();
332349
(out.next_action, analyzer_data, stats)
@@ -393,7 +410,8 @@ impl Algorithm {
393410
&mut self,
394411
board: &Board,
395412
board_played_times_prediction: &HashMap<Board, u32>,
396-
incremental_psqt_eval: f32,
413+
mg_incremental_psqt_eval: f32,
414+
eg_incremental_psqt_eval: f32
397415
) -> f32 {
398416
let board_status = board.status();
399417
if board_status == BoardStatus::Stalemate {
@@ -492,9 +510,27 @@ impl Algorithm {
492510
);
493511
}
494512

513+
let mut mg_tapered_pesto: f32 = 0.;
514+
let mut eg_tapered_pesto: f32 = 0.;
495515
let mut tapered_pesto: f32 = 0.;
496516
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.;
498534
}
499535

500536
let mut pawn_structure: f32 = 0.;
@@ -509,8 +545,8 @@ impl Algorithm {
509545
let king_bitboard: usize = (all_king_bitboard & color_bitboard).to_size(0);
510546
//pawn chain, awarding 0.5 eval for each pawn protected by another pawn. Constants should in theory cover an (literal) edge case... I hope.
511547
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())
514550
as f32;
515551

516552
//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 {
521557
.max(0.);
522558
}
523559

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())
527563
as f32;
528564
bonus
529565
}
@@ -541,6 +577,12 @@ impl Algorithm {
541577
pawn_structure = *self.pawn_hash.get(&pawn_bitboard).unwrap();
542578
}
543579

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+
544586
let evaluation: f32 = controlled_squares as f32 / 20.
545587
+ diff_material as f32
546588
+ naive_psqt
@@ -550,52 +592,62 @@ impl Algorithm {
550592
evaluation
551593
}
552594

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 {
554596
fn tapered_psqt_calc(
555597
piece_bitboard: &BitBoard,
556598
color_bitboard: &BitBoard,
557-
material: (u32, u32),
558599
piece_index: usize,
600+
mg_eg: bool
559601
) -> f32 {
560602
// Essentially, gets the dot product between a "vector" of the bitboard (containing 64 0s and 1s) and the table with NAIVE_PSQT bonus constants.
561603
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
577627
}
578-
bonus / 78.
579-
}
580628

629+
}
630+
581631
macro_rules! tapered_psqt_calc {
582-
($board: tt, $piece: tt, $material: tt, $index: tt) => {
632+
($board: tt, $piece: tt, $index: tt, $mg_eg: tt) => {
583633
tapered_psqt_calc(
584634
$board.pieces(Piece::$piece),
585635
$board.color_combined($board.side_to_move()),
586-
$material,
587636
$index,
637+
$mg_eg
588638
)
589639
};
590640
}
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+
599651
}
600652

601653
pub(crate) fn reset(&mut self) {

src/common/utils.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,4 @@ pub(crate) fn passed_deadline(deadline: Instant) -> bool {
154154

155155
pub(crate) fn module_enabled(modules: u32, module_to_test: u32) -> bool {
156156
modules & module_to_test != 0
157-
}
157+
}

src/main.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ mod common;
1515
mod pitter;
1616

1717
//If we should print the moves played and results of each game.
18-
pub(crate) const PRINT_GAME: bool = true;
18+
pub(crate) const PRINT_GAME: bool = false;
1919

2020
#[tokio::main]
2121
async fn main() {
22-
//ALPHA_BETA | ANALYZE | SEARCH_EXTENSIONS | SKIP_BAD_MOVES | SQUARE_CONTROL_METRIC | TRANSPOSITION_TABLE | NAIVE_PSQT | PAWN_STRUCTURE | TAPERED_EVERY_PRESTO_PSQT | TAPERED_INCREMENTAL_PESTO_PSQT
22+
//ALPHA_BETA | ANALYZE | SEARCH_EXTENSIONS | SKIP_BAD_MOVES | SQUARE_CONTROL_METRIC | TRANSPOSITION_TABLE | NAIVE_PSQT | PAWN_STRUCTURE | TAPERED_EVERY_PESTO_PSQT | TAPERED_INCREMENTAL_PESTO_PSQT
2323
//Put 0 for no modules.
2424
let modules1 = ALPHA_BETA | TAPERED_INCREMENTAL_PESTO_PSQT;
25-
let modules2 = 0;
25+
let modules2 = ALPHA_BETA;
2626
let time_per_move1 = Duration::from_micros(2000);
2727
let time_per_move2 = Duration::from_micros(2000);
2828

0 commit comments

Comments
 (0)