From: Guenther Demetz Date: Mon, 12 Sep 2016 06:47:19 +0000 (+0200) Subject: Pinned aware SEE X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=90ce24b11ea080f923e1b5d37470e2ca98f4d98b Pinned aware SEE Don't allow pinned pieces to attack the exchange-square as long all pinners (this includes also potential ones) are on their original square. As soon a pinner moves to the exchange-square or get captured on it, we fall back to standard SEE behaviour. This correctly handles the majority of cases with absolute pins. bench: 6883133 --- diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 5e4f4bdd..259a5bc5 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -360,7 +360,8 @@ namespace { if (Pt == QUEEN) { // Penalty if any relative pin or discovered attack against the queen - if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s)) + Bitboard pinners; + if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s, pinners)) score -= WeakQueen; } } diff --git a/src/position.cpp b/src/position.cpp index 26e8e1ce..e51c1ba7 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -291,8 +291,8 @@ void Position::set_castling_right(Color c, Square rfrom) { void Position::set_check_info(StateInfo* si) const { - si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE)); - si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK)); + si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE), si->pinnersForKing[WHITE]); + si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK), si->pinnersForKing[BLACK]); Square ksq = square(~sideToMove); @@ -415,24 +415,25 @@ Phase Position::game_phase() const { } -/// Position::slider_blockers() returns a bitboard of all the pieces (both colors) that -/// are blocking attacks on the square 's' from 'sliders'. A piece blocks a slider -/// if removing that piece from the board would result in a position where square 's' -/// is attacked. For example, a king-attack blocking piece can be either a pinned or -/// a discovered check piece, according if its color is the opposite or the same of -/// the color of the slider. +/// Position::slider_blockers() returns a bitboard of all the pieces (both colors) +/// that are blocking attacks on the square 's' from 'sliders'. A piece blocks a +/// slider if removing that piece from the board would result in a position where +/// square 's' is attacked. For example, a king-attack blocking piece can be either +/// a pinned or a discovered check piece, according if its color is the opposite +/// or the same of the color of the slider. The pinners bitboard get filled with +/// real and potential pinners. -Bitboard Position::slider_blockers(Bitboard sliders, Square s) const { +Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { - Bitboard b, pinners, result = 0; + Bitboard b, p, result = 0; // Pinners are sliders that attack 's' when a pinned piece is removed - pinners = ( (PseudoAttacks[ROOK ][s] & pieces(QUEEN, ROOK)) - | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; + pinners = p = ( (PseudoAttacks[ROOK ][s] & pieces(QUEEN, ROOK)) + | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; - while (pinners) + while (p) { - b = between_bb(s, pop_lsb(&pinners)) & pieces(); + b = between_bb(s, pop_lsb(&p)) & pieces(); if (!more_than_one(b)) result |= b; @@ -999,6 +1000,18 @@ Value Position::see(Move m) const { if (!stmAttackers) return swapList[0]; + // Don't allow pinned pieces to attack as long all pinners (this includes also + // potential ones) are on their original square. When a pinner moves to the + // exchange-square or get captured on it, we fall back to standard SEE behaviour. + else if ( (stmAttackers & st->blockersForKing[stm]) + && ((st->pinnersForKing[stm] & (occupied ^ (occupied & to))) == st->pinnersForKing[stm])) + { + // Pinned pieces can't attack so remove them from attackers + stmAttackers ^= (stmAttackers & st->blockersForKing[stm]); + if (!stmAttackers) + return swapList[0]; + } + // The destination square is defended, which makes things rather more // difficult to compute. We proceed by building up a "swap list" containing // the material gain or loss at each stop in a sequence of captures to the @@ -1017,6 +1030,11 @@ Value Position::see(Move m) const { captured = min_attacker(byTypeBB, to, stmAttackers, occupied, attackers); stm = ~stm; stmAttackers = attackers & pieces(stm); + if ( stmAttackers + && (stmAttackers & st->blockersForKing[stm]) + && ((st->pinnersForKing[stm] & (occupied ^ (occupied & to))) == st->pinnersForKing[stm])) + stmAttackers ^= (stmAttackers & st->blockersForKing[stm]); + ++slIndex; } while (stmAttackers && (captured != KING || (--slIndex, false))); // Stop before a king capture diff --git a/src/position.h b/src/position.h index 68fc508e..c322ab99 100644 --- a/src/position.h +++ b/src/position.h @@ -64,6 +64,7 @@ struct StateInfo { Piece capturedPiece; StateInfo* previous; Bitboard blockersForKing[COLOR_NB]; + Bitboard pinnersForKing[COLOR_NB]; Bitboard checkSquares[PIECE_TYPE_NB]; }; @@ -121,7 +122,7 @@ public: Bitboard attacks_from(Piece pc, Square s) const; template Bitboard attacks_from(Square s) const; template Bitboard attacks_from(Square s, Color c) const; - Bitboard slider_blockers(Bitboard sliders, Square s) const; + Bitboard slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const; // Properties of moves bool legal(Move m) const;