- 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[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>();
std::memset(this, 0, sizeof(Position));
std::memset(si, 0, sizeof(StateInfo));
std::memset(this, 0, sizeof(Position));
std::memset(si, 0, sizeof(StateInfo));
- ci->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE));
- ci->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]);
- ci->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove);
- ci->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
- ci->checkSquares[BISHOP] = attacks_from<BISHOP>(ksq);
- ci->checkSquares[ROOK] = attacks_from<ROOK>(ksq);
- ci->checkSquares[QUEEN] = ci->checkSquares[BISHOP] | ci->checkSquares[ROOK];
- ci->checkSquares[KING] = 0;
+ si->checkSquares[PAWN] = attacks_from<PAWN>(ksq, ~sideToMove);
+ si->checkSquares[KNIGHT] = attacks_from<KNIGHT>(ksq);
+ si->checkSquares[BISHOP] = attacks_from<BISHOP>(ksq);
+ si->checkSquares[ROOK] = attacks_from<ROOK>(ksq);
+ si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK];
+ si->checkSquares[KING] = 0;
- for (Color c = WHITE; c <= BLACK; ++c)
- for (PieceType pt = PAWN; pt <= KING; ++pt)
- for (int cnt = 0; cnt < pieceCount[c][pt]; ++cnt)
- si->materialKey ^= Zobrist::psq[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[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;
+ }
// En passant capture with check? We have already handled the case
// of direct checks and ordinary discovered check, so the only case we
// En passant capture with check? We have already handled the case
// of direct checks and ordinary discovered check, so the only case we
Square capsq = make_square(file_of(to), rank_of(from));
Bitboard b = (pieces() ^ from ^ capsq) | to;
Square capsq = make_square(file_of(to), rank_of(from));
Bitboard b = (pieces() ^ from ^ capsq) | to;
- return (attacks_bb< ROOK>(st->ci.ksq, b) & pieces(sideToMove, QUEEN, ROOK))
- | (attacks_bb<BISHOP>(st->ci.ksq, b) & pieces(sideToMove, QUEEN, BISHOP));
+ return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
+ | (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
- return (PseudoAttacks[ROOK][rto] & st->ci.ksq)
- && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & st->ci.ksq);
+ return (PseudoAttacks[ROOK][rto] & square<KING>(~sideToMove))
+ && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
- PieceType pt = type_of(piece_on(from));
- PieceType captured = type_of(m) == ENPASSANT ? PAWN : type_of(piece_on(to));
+ Piece pc = piece_on(from);
+ Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
- assert(color_of(piece_on(from)) == us);
- assert(piece_on(to) == NO_PIECE || color_of(piece_on(to)) == (type_of(m) != CASTLING ? them : us));
- assert(captured != KING);
+ assert(color_of(pc) == us);
+ assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
+ assert(type_of(captured) != KING);
Square rfrom, rto;
do_castling<true>(us, from, to, rfrom, rto);
Square rfrom, rto;
do_castling<true>(us, from, to, rfrom, rto);
- captured = NO_PIECE_TYPE;
- st->psq += PSQT::psq[us][ROOK][rto] - PSQT::psq[us][ROOK][rfrom];
- k ^= Zobrist::psq[us][ROOK][rfrom] ^ Zobrist::psq[us][ROOK][rto];
+ st->psq += PSQT::psq[captured][rto] - PSQT::psq[captured][rfrom];
+ k ^= Zobrist::psq[captured][rfrom] ^ Zobrist::psq[captured][rto];
+ captured = NO_PIECE;
// If the captured piece is a pawn, update pawn hash key, otherwise
// update non-pawn material.
// If the captured piece is a pawn, update pawn hash key, otherwise
// update non-pawn material.
assert(to == st->epSquare);
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(to) == NO_PIECE);
assert(to == st->epSquare);
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(to) == NO_PIECE);
- k ^= Zobrist::psq[them][captured][capsq];
- st->materialKey ^= Zobrist::psq[them][captured][pieceCount[them][captured]];
+ k ^= Zobrist::psq[captured][capsq];
+ st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
- remove_piece(us, PAWN, to);
- put_piece(us, promotion, to);
+ remove_piece(pc, to);
+ put_piece(promotion, to);
- k ^= Zobrist::psq[us][PAWN][to] ^ Zobrist::psq[us][promotion][to];
- st->pawnKey ^= Zobrist::psq[us][PAWN][to];
- st->materialKey ^= Zobrist::psq[us][promotion][pieceCount[us][promotion]-1]
- ^ Zobrist::psq[us][PAWN][pieceCount[us][PAWN]];
+ k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
+ st->pawnKey ^= Zobrist::psq[pc][to];
+ st->materialKey ^= Zobrist::psq[promotion][pieceCount[promotion]-1]
+ ^ Zobrist::psq[pc][pieceCount[pc]];
// Update material
st->nonPawnMaterial[us] += PieceValue[MG][promotion];
}
// Update pawn hash key and prefetch access to pawnsTable
// Update material
st->nonPawnMaterial[us] += PieceValue[MG][promotion];
}
// Update pawn hash key and prefetch access to pawnsTable
if (type_of(m) == PROMOTION)
{
assert(relative_rank(us, to) == RANK_8);
if (type_of(m) == PROMOTION)
{
assert(relative_rank(us, to) == RANK_8);
- remove_piece(us, pt, to);
- put_piece(us, PAWN, to);
- pt = PAWN;
+ remove_piece(pc, to);
+ pc = make_piece(us, PAWN);
+ put_piece(pc, to);
- move_piece(us, pt, to, from); // Put the piece back at the source square
+ move_piece(pc, to, from); // Put the piece back at the source square
assert(to == st->previous->epSquare);
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(capsq) == NO_PIECE);
assert(to == st->previous->epSquare);
assert(relative_rank(us, to) == RANK_6);
assert(piece_on(capsq) == NO_PIECE);
template<bool Do>
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
template<bool Do>
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
// Remove both pieces first since squares could overlap in Chess960
to = relative_square(us, kingSide ? SQ_G1 : SQ_C1);
// Remove both pieces first since squares could overlap in Chess960
- remove_piece(us, KING, Do ? from : to);
- remove_piece(us, ROOK, Do ? rfrom : rto);
+ remove_piece(make_piece(us, KING), Do ? from : to);
+ remove_piece(make_piece(us, ROOK), Do ? rfrom : rto);
- put_piece(us, KING, Do ? to : from);
- put_piece(us, ROOK, Do ? rto : rfrom);
+ put_piece(make_piece(us, KING), Do ? to : from);
+ put_piece(make_piece(us, ROOK), Do ? rto : rfrom);
+ 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)
- {
- if (pieceCount[c][pt] != popcount(pieces(c, pt)))
- return false;
+ for (Piece pc : Pieces)
+ {
+ if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))))
+ return false;
- for (int i = 0; i < pieceCount[c][pt]; ++i)
- if ( board[pieceList[c][pt][i]] != make_piece(c, pt)
- || index[pieceList[c][pt][i]] != i)
- return false;
- }
+ for (int i = 0; i < pieceCount[pc]; ++i)
+ if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
+ return false;
+ }