X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=9fe5f893c9da5f199577abeb283fa7942d4bee6e;hp=e51c1ba70296a7149460da078c1032b1582a3b88;hb=0162fb83c21b9ac4d5ed302d4bc5a12b7a0cfc43;hpb=90ce24b11ea080f923e1b5d37470e2ca98f4d98b diff --git a/src/position.cpp b/src/position.cpp index e51c1ba7..9fe5f893 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -20,7 +20,8 @@ #include #include -#include // For std::memset, std::memcmp +#include // For offsetof() +#include // For std::memset, std::memcmp #include #include @@ -34,6 +35,10 @@ using std::string; +namespace PSQT { + extern Score psq[PIECE_NB][SQUARE_NB]; +} + namespace Zobrist { Key psq[PIECE_NB][SQUARE_NB]; @@ -420,23 +425,28 @@ Phase Position::game_phase() const { /// 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. +/// or the same of the color of the slider. Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { - Bitboard b, p, result = 0; + Bitboard result = 0; + pinners = 0; - // Pinners are sliders that attack 's' when a pinned piece is removed - pinners = p = ( (PseudoAttacks[ROOK ][s] & pieces(QUEEN, ROOK)) - | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; + // Snipers are sliders that attack 's' when a piece is removed + Bitboard snipers = ( (PseudoAttacks[ROOK ][s] & pieces(QUEEN, ROOK)) + | (PseudoAttacks[BISHOP][s] & pieces(QUEEN, BISHOP))) & sliders; - while (p) + while (snipers) { - b = between_bb(s, pop_lsb(&p)) & pieces(); - - if (!more_than_one(b)) - result |= b; + Square sniperSq = pop_lsb(&snipers); + Bitboard b = between_bb(s, sniperSq) & pieces(); + + if (!more_than_one(b)) + { + result |= b; + if (b & pieces(color_of(piece_on(s)))) + pinners |= sniperSq; + } } return result; } @@ -967,7 +977,7 @@ Value Position::see(Move m) const { Bitboard occupied, attackers, stmAttackers; Value swapList[32]; int slIndex = 1; - PieceType captured; + PieceType nextVictim; Color stm; assert(is_ok(m)); @@ -997,20 +1007,15 @@ Value Position::see(Move m) const { // If the opponent has no attackers we are finished stm = ~stm; stmAttackers = attackers & pieces(stm); - if (!stmAttackers) - return swapList[0]; + occupied ^= to; // For the case when captured piece is a pinner - // 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]; - } + // Don't allow pinned pieces to attack pieces except the king as long all + // pinners are on their original square. + if (!(st->pinnersForKing[stm] & ~occupied)) + 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 @@ -1018,26 +1023,27 @@ Value Position::see(Move m) const { // destination square, where the sides alternately capture, and always // capture with the least valuable piece. After each capture, we look for // new X-ray attacks from behind the capturing piece. - captured = type_of(piece_on(from)); + nextVictim = type_of(piece_on(from)); do { assert(slIndex < 32); // Add the new entry to the swap list - swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][captured]; + swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][nextVictim]; // Locate and remove the next least valuable attacker - captured = min_attacker(byTypeBB, to, stmAttackers, occupied, attackers); + nextVictim = 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]); + + // Don't allow pinned pieces to attack pieces except the king + if ( nextVictim != KING + && !(st->pinnersForKing[stm] & ~occupied)) + stmAttackers &= ~st->blockersForKing[stm]; ++slIndex; - } while (stmAttackers && (captured != KING || (--slIndex, false))); // Stop before a king capture + } while (stmAttackers && (nextVictim != KING || (--slIndex, false))); // Stop before a king capture // Having built the swap list, we negamax through it to find the best // achievable score from the point of view of the side to move.