From 242c566c1a80c7f3d95774eac513935fcee0cf0d Mon Sep 17 00:00:00 2001 From: Miguel Lahoz Date: Fri, 25 Jan 2019 14:37:03 +0800 Subject: [PATCH] Change pinning logic in Static Exchange Evaluation (SEE) This changes 2 parts with regards to static exchange evaluation. Currently, we do not allow pinned pieces to recapture if *all* opponent pinners are still in their starting squares. This changes that to having a less strict requirement, checking if *any* pinners are still in their starting square. This makes our SEE give more respect to the pinning side with regards to exchanges, which makes sense because it helps our search explore more tactical options. Furthermore, we change the logic for saving pinners into our state variable when computing slider_blockers. We will include double pinners, where two sliders may be looking at the same blocker, a similar concept to our mobility calculation for sliders in our evaluation section. Interestingly, I think SEE is the only place where the pinners bitboard is actually used, so as far as I know there are no other side effects to this change. An example and some insights: White Bf2, Kg1 Black Qe3, Bc5 The move Qg3 will be given the correct value of 0. (Previously < 0) The move Qd4 will be incorrectly given a value of 0. (Previously < 0) It seems the tradeoff in search is worth it. Qd4 will likely be pruned soon by something like probcut anyway, while Qg3 could help us spot tactics at an earlier depth. STC: LLR: 2.96 (-2.94,2.94) [0.50,4.50] Total: 62162 W: 13879 L: 13408 D: 34875 http://tests.stockfishchess.org/tests/view/5c4ba1a70ebc593af5d49c55 LTC: (Thanks to @alayant) LLR: 3.40 (-2.94,2.94) [0.00,3.50] Total: 140285 W: 23416 L: 22825 D: 94044 http://tests.stockfishchess.org/tests/view/5c4bcfba0ebc593af5d49ea8 Bench: 3937213 --- src/position.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 21eff88c..812eabca 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -498,14 +498,15 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners Bitboard blockers = 0; pinners = 0; - // Snipers are sliders that attack 's' when a piece is removed + // Snipers are sliders that attack 's' when a piece and other snipers are removed Bitboard snipers = ( (PseudoAttacks[ ROOK][s] & pieces(QUEEN, ROOK)) | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; + Bitboard occupancy = pieces() & ~snipers; while (snipers) { Square sniperSq = pop_lsb(&snipers); - Bitboard b = between_bb(s, sniperSq) & pieces(); + Bitboard b = between_bb(s, sniperSq) & occupancy; if (b && !more_than_one(b)) { @@ -1076,8 +1077,8 @@ bool Position::see_ge(Move m, Value threshold) const { stmAttackers = attackers & pieces(stm); // Don't allow pinned pieces to attack (except the king) as long as - // all pinners are on their original square. - if (!(st->pinners[~stm] & ~occupied)) + // any pinners are on their original square. + if (st->pinners[~stm] & occupied) stmAttackers &= ~st->blockersForKing[stm]; // If stm has no more attackers then give up: stm loses -- 2.39.5