- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- for (Square s = SQ_A1; s <= SQ_H8; ++s)
- Zobrist::psq[make_piece(c, pt)][s] = rng.rand<Key>();
+ for (Piece pc : Pieces)
+ for (Square s = SQ_A1; s <= SQ_H8; ++s)
+ Zobrist::psq[pc][s] = rng.rand<Key>();
- si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE));
- si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK));
+ si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinnersForKing[WHITE]);
+ si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinnersForKing[BLACK]);
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- for (int cnt = 0; cnt < pieceCount[make_piece(c, pt)]; ++cnt)
- si->materialKey ^= Zobrist::psq[make_piece(c, pt)][cnt];
+ for (Piece pc : Pieces)
+ {
+ if (type_of(pc) != PAWN && type_of(pc) != KING)
+ si->nonPawnMaterial[color_of(pc)] += pieceCount[pc] * PieceValue[MG][pc];
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt)
- si->nonPawnMaterial[c] += pieceCount[make_piece(c, pt)] * PieceValue[MG][pt];
+ for (int cnt = 0; cnt < pieceCount[pc]; ++cnt)
+ si->materialKey ^= Zobrist::psq[pc][cnt];
+ }
-/// 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.
- // 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;
+ // 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;
- b = between_bb(s, pop_lsb(&pinners)) & 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;
+ }
+ occupied ^= to; // For the case when captured piece is a pinner
+
+ // 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];
+
// The destination square is defended, which makes things rather more
// difficult to compute. We proceed by building up a "swap list" containing
// The destination square is defended, which makes things rather more
// difficult to compute. We proceed by building up a "swap list" containing
// 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.
// 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 = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
+ nextVictim = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
// 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.
// 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.
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- {
- Piece pc = make_piece(c, pt);
+ for (Piece pc : Pieces)
+ {
+ if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))))
+ return false;