return hidden_checkers<false>(c);
}
-/// Position::attacks_to() computes a bitboard containing all pieces which
+/// Position::attackers_to() computes a bitboard containing all pieces which
/// attacks a given square.
-Bitboard Position::attacks_to(Square s) const {
+Bitboard Position::attackers_to(Square s) const {
- return (pawn_attacks(BLACK, s) & pieces(PAWN, WHITE))
- | (pawn_attacks(WHITE, s) & pieces(PAWN, BLACK))
- | (piece_attacks<KNIGHT>(s) & pieces(KNIGHT))
- | (piece_attacks<ROOK>(s) & pieces(ROOK, QUEEN))
- | (piece_attacks<BISHOP>(s) & pieces(BISHOP, QUEEN))
- | (piece_attacks<KING>(s) & pieces(KING));
+ return (attacks_from<PAWN>(s, BLACK) & pieces(PAWN, WHITE))
+ | (attacks_from<PAWN>(s, WHITE) & pieces(PAWN, BLACK))
+ | (attacks_from<KNIGHT>(s) & pieces(KNIGHT))
+ | (attacks_from<ROOK>(s) & pieces(ROOK, QUEEN))
+ | (attacks_from<BISHOP>(s) & pieces(BISHOP, QUEEN))
+ | (attacks_from<KING>(s) & pieces(KING));
}
-/// Position::piece_attacks_square() tests whether the piece on square f
-/// attacks square t.
+/// Position::attacks_from() computes a bitboard of all attacks
+/// of a given piece put in a given square.
-bool Position::piece_attacks_square(Piece p, Square f, Square t) const {
+Bitboard Position::attacks_from(Piece p, Square s) const {
- assert(square_is_ok(f));
- assert(square_is_ok(t));
+ assert(square_is_ok(s));
switch (p)
{
- case WP: return pawn_attacks_square(WHITE, f, t);
- case BP: return pawn_attacks_square(BLACK, f, t);
- case WN: case BN: return piece_attacks_square<KNIGHT>(f, t);
- case WB: case BB: return piece_attacks_square<BISHOP>(f, t);
- case WR: case BR: return piece_attacks_square<ROOK>(f, t);
- case WQ: case BQ: return piece_attacks_square<QUEEN>(f, t);
- case WK: case BK: return piece_attacks_square<KING>(f, t);
+ case WP: return attacks_from<PAWN>(s, WHITE);
+ case BP: return attacks_from<PAWN>(s, BLACK);
+ case WN: case BN: return attacks_from<KNIGHT>(s);
+ case WB: case BB: return attacks_from<BISHOP>(s);
+ case WR: case BR: return attacks_from<ROOK>(s);
+ case WQ: case BQ: return attacks_from<QUEEN>(s);
+ case WK: case BK: return attacks_from<KING>(s);
default: break;
}
return false;
assert(square_is_occupied(f));
- if (piece_attacks_square(piece_on(f), t, s))
+ if (bit_is_set(attacks_from(piece_on(f), t), s))
return true;
// Move the piece and scan for X-ray attacks behind it
// If we have attacks we need to verify that are caused by our move
// and are not already existent ones.
- return xray && (xray ^ (xray & piece_attacks<QUEEN>(s)));
+ return xray && (xray ^ (xray & attacks_from<QUEEN>(s)));
}
/// Position::find_checkers() computes the checkersBB bitboard, which
/// contains a nonzero bit for each checking piece (0, 1 or 2). It
-/// currently works by calling Position::attacks_to, which is probably
+/// currently works by calling Position::attackers_to, which is probably
/// inefficient. Consider rewriting this function to use the last move
/// played, like in non-bitboard versions of Glaurung.
void Position::find_checkers() {
Color us = side_to_move();
- st->checkersBB = attacks_to(king_square(us), opposite_color(us));
+ st->checkersBB = attackers_to(king_square(us)) & pieces_of_color(opposite_color(us));
}
// If the moving piece is a king, check whether the destination
// square is attacked by the opponent.
if (type_of_piece_on(from) == KING)
- return !(square_is_attacked(move_to(m), opposite_color(us)));
+ return !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us)));
// A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king.
{
case PAWN:
- if (bit_is_set(pawn_attacks(them, ksq), to)) // Normal check?
+ if (bit_is_set(attacks_from<PAWN>(ksq, them), to)) // Normal check?
return true;
if ( dcCandidates // Discovered check?
switch (move_promotion_piece(m))
{
case KNIGHT:
- return bit_is_set(piece_attacks<KNIGHT>(to), ksq);
+ return bit_is_set(attacks_from<KNIGHT>(to), ksq);
case BISHOP:
return bit_is_set(bishop_attacks_bb(to, b), ksq);
case ROOK:
// Test discovered check and normal check according to piece type
case KNIGHT:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || bit_is_set(piece_attacks<KNIGHT>(ksq), to);
+ || bit_is_set(attacks_from<KNIGHT>(ksq), to);
case BISHOP:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks<BISHOP>(ksq), to));
+ || (direction_is_diagonal(ksq, to) && bit_is_set(attacks_from<BISHOP>(ksq), to));
case ROOK:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || (direction_is_straight(ksq, to) && bit_is_set(piece_attacks<ROOK>(ksq), to));
+ || (direction_is_straight(ksq, to) && bit_is_set(attacks_from<ROOK>(ksq), to));
case QUEEN:
// Discovered checks are impossible!
assert(!bit_is_set(dcCandidates, from));
- return ( (direction_is_straight(ksq, to) && bit_is_set(piece_attacks<ROOK>(ksq), to))
- || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks<BISHOP>(ksq), to)));
+ return ( (direction_is_straight(ksq, to) && bit_is_set(attacks_from<ROOK>(ksq), to))
+ || (direction_is_diagonal(ksq, to) && bit_is_set(attacks_from<BISHOP>(ksq), to)));
case KING:
// Discovered check?
// Direct checks
if ( ( (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
|| (Rook && bit_is_set(RookPseudoAttacks[ksq], to)))
- && bit_is_set(piece_attacks<Piece>(ksq), to)) // slow, try to early skip
+ && bit_is_set(attacks_from<Piece>(ksq), to)) // slow, try to early skip
set_bit(pCheckersBB, to);
else if ( Piece != KING
&& !Slider
- && bit_is_set(Piece == PAWN ? pawn_attacks(opposite_color(sideToMove), ksq) : piece_attacks<Piece>(ksq), to))
+ && bit_is_set(Piece == PAWN ? attacks_from<PAWN>(ksq, opposite_color(sideToMove))
+ : attacks_from<Piece>(ksq), to))
set_bit(pCheckersBB, to);
// Discovery checks
if (Piece != QUEEN && bit_is_set(dcCandidates, from))
{
if (Piece != ROOK)
- (*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
+ (*pCheckersBB) |= (attacks_from<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
if (Piece != BISHOP)
- (*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
+ (*pCheckersBB) |= (attacks_from<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
}
}
board[to] = board[from];
board[from] = EMPTY;
- // If the moving piece was a king, update the king square
- if (pt == KING)
- kingSquare[us] = to;
-
// Update piece lists, note that index[from] is not updated and
// becomes stale. This works as long as index[] is accessed just
// by known occupied squares.
// Set en passant square, only if moved pawn can be captured
if (abs(int(to) - int(from)) == 16)
{
- if (pawn_attacks(us, from + (us == WHITE ? DELTA_N : DELTA_S)) & pieces(PAWN, them))
+ if (attacks_from<PAWN>(from + (us == WHITE ? DELTA_N : DELTA_S), us) & pieces(PAWN, them))
{
st->epSquare = Square((int(from) + int(to)) / 2);
key ^= zobEp[st->epSquare];
Square lastPawnSquare = pieceList[us][PAWN][pieceCount[us][PAWN]];
index[lastPawnSquare] = index[to];
pieceList[us][PAWN][index[lastPawnSquare]] = lastPawnSquare;
+ pieceList[us][PAWN][pieceCount[us][PAWN]] = SQ_NONE;
index[to] = pieceCount[us][promotion] - 1;
pieceList[us][promotion][index[to]] = to;
// Update checkers bitboard, piece must be already moved
if (ep | pm)
- st->checkersBB = attacks_to(king_square(them), us);
+ st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
else
{
st->checkersBB = EmptyBoardBB;
// Update hash key
key ^= zobrist[them][capture][capsq];
- // If the captured piece was a pawn, update pawn hash key
- if (capture == PAWN)
- st->pawnKey ^= zobrist[them][PAWN][capsq];
-
// Update incremental scores
st->mgValue -= pst<MidGame>(them, capture, capsq);
st->egValue -= pst<EndGame>(them, capture, capsq);
- // Update material
- if (capture != PAWN)
+ // If the captured piece was a pawn, update pawn hash key,
+ // otherwise update non-pawn material.
+ if (capture == PAWN)
+ st->pawnKey ^= zobrist[them][PAWN][capsq];
+ else
st->npMaterial[them] -= piece_value_midgame(capture);
// Update material hash key
Square lastPieceSquare = pieceList[them][capture][pieceCount[them][capture]];
index[lastPieceSquare] = index[capsq];
pieceList[them][capture][index[lastPieceSquare]] = lastPieceSquare;
+ pieceList[them][capture][pieceCount[them][capture]] = SQ_NONE;
// Reset rule 50 counter
st->rule50 = 0;
rto = relative_square(us, SQ_D1);
}
- // Move the pieces
- Bitboard kmove_bb = make_move_bb(kfrom, kto);
- do_move_bb(&(byColorBB[us]), kmove_bb);
- do_move_bb(&(byTypeBB[KING]), kmove_bb);
- do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares
-
- Bitboard rmove_bb = make_move_bb(rfrom, rto);
- do_move_bb(&(byColorBB[us]), rmove_bb);
- do_move_bb(&(byTypeBB[ROOK]), rmove_bb);
- do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares
-
+ // Remove pieces from source squares:
+ clear_bit(&(byColorBB[us]), kfrom);
+ clear_bit(&(byTypeBB[KING]), kfrom);
+ clear_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares
+ clear_bit(&(byColorBB[us]), rfrom);
+ clear_bit(&(byTypeBB[ROOK]), rfrom);
+ clear_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares
+
+ // Put pieces on destination squares:
+ set_bit(&(byColorBB[us]), kto);
+ set_bit(&(byTypeBB[KING]), kto);
+ set_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares
+ set_bit(&(byColorBB[us]), rto);
+ set_bit(&(byTypeBB[ROOK]), rto);
+ set_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
+
// Update board array
Piece king = piece_of_color_and_type(us, KING);
Piece rook = piece_of_color_and_type(us, ROOK);
board[kto] = king;
board[rto] = rook;
- // Update king square
- kingSquare[us] = kto;
-
// Update piece lists
pieceList[us][KING][index[kfrom]] = kto;
pieceList[us][ROOK][index[rfrom]] = rto;
st->rule50 = 0;
// Update checkers BB
- st->checkersBB = attacks_to(king_square(them), us);
+ st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
// Finish
sideToMove = opposite_color(sideToMove);
Square lastPromotionSquare = pieceList[us][promotion][pieceCount[us][promotion]];
index[lastPromotionSquare] = index[to];
pieceList[us][promotion][index[lastPromotionSquare]] = lastPromotionSquare;
+ pieceList[us][promotion][pieceCount[us][promotion]] = SQ_NONE;
index[to] = pieceCount[us][PAWN] - 1;
pieceList[us][PAWN][index[to]] = to;
}
+
// Put the piece back at the source square
Bitboard move_bb = make_move_bb(to, from);
do_move_bb(&(byColorBB[us]), move_bb);
board[from] = piece_of_color_and_type(us, pt);
board[to] = EMPTY;
- // If the moving piece was a king, update the king square
- if (pt == KING)
- kingSquare[us] = from;
-
// Update piece list
index[from] = index[to];
pieceList[us][pt][index[from]] = from;
assert(piece_on(kto) == piece_of_color_and_type(us, KING));
assert(piece_on(rto) == piece_of_color_and_type(us, ROOK));
-
- // Put the pieces back at the source square
- Bitboard kmove_bb = make_move_bb(kto, kfrom);
- do_move_bb(&(byColorBB[us]), kmove_bb);
- do_move_bb(&(byTypeBB[KING]), kmove_bb);
- do_move_bb(&(byTypeBB[0]), kmove_bb); // HACK: byTypeBB[0] == occupied squares
-
- Bitboard rmove_bb = make_move_bb(rto, rfrom);
- do_move_bb(&(byColorBB[us]), rmove_bb);
- do_move_bb(&(byTypeBB[ROOK]), rmove_bb);
- do_move_bb(&(byTypeBB[0]), rmove_bb); // HACK: byTypeBB[0] == occupied squares
+
+ // Remove pieces from destination squares:
+ clear_bit(&(byColorBB[us]), kto);
+ clear_bit(&(byTypeBB[KING]), kto);
+ clear_bit(&(byTypeBB[0]), kto); // HACK: byTypeBB[0] == occupied squares
+ clear_bit(&(byColorBB[us]), rto);
+ clear_bit(&(byTypeBB[ROOK]), rto);
+ clear_bit(&(byTypeBB[0]), rto); // HACK: byTypeBB[0] == occupied squares
+
+ // Put pieces on source squares:
+ set_bit(&(byColorBB[us]), kfrom);
+ set_bit(&(byTypeBB[KING]), kfrom);
+ set_bit(&(byTypeBB[0]), kfrom); // HACK: byTypeBB[0] == occupied squares
+ set_bit(&(byColorBB[us]), rfrom);
+ set_bit(&(byTypeBB[ROOK]), rfrom);
+ set_bit(&(byTypeBB[0]), rfrom); // HACK: byTypeBB[0] == occupied squares
// Update board
board[rto] = board[kto] = EMPTY;
board[rfrom] = piece_of_color_and_type(us, ROOK);
board[kfrom] = piece_of_color_and_type(us, KING);
- // Update king square
- kingSquare[us] = kfrom;
-
// Update piece lists
pieceList[us][KING][index[kto]] = kfrom;
pieceList[us][ROOK][index[rto]] = rfrom;
0, 0
};
- Bitboard attackers, stmAttackers, occ, b;
+ Bitboard attackers, stmAttackers, b;
assert(square_is_ok(from) || from == SQ_NONE);
assert(square_is_ok(to));
// Initialize pieces
Piece piece = piece_on(from);
Piece capture = piece_on(to);
-
- // Find all attackers to the destination square, with the moving piece
- // removed, but possibly an X-ray attacker added behind it.
- occ = occupied_squares();
+ Bitboard occ = occupied_squares();
// Handle en passant moves
if (st->epSquare == to && type_of_piece_on(from) == PAWN)
while (true)
{
+ // Find all attackers to the destination square, with the moving piece
+ // removed, but possibly an X-ray attacker added behind it.
clear_bit(&occ, from);
- attackers = (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN))
- | (piece_attacks<KNIGHT>(to) & pieces(KNIGHT))
- | (piece_attacks<KING>(to) & pieces(KING))
- | (pawn_attacks(WHITE, to) & pieces(PAWN, BLACK))
- | (pawn_attacks(BLACK, to) & pieces(PAWN, WHITE));
+ attackers = (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
+ | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN))
+ | (attacks_from<KNIGHT>(to) & pieces(KNIGHT))
+ | (attacks_from<KING>(to) & pieces(KING))
+ | (attacks_from<PAWN>(to, WHITE) & pieces(PAWN, BLACK))
+ | (attacks_from<PAWN>(to, BLACK) & pieces(PAWN, WHITE));
if (from != SQ_NONE)
break;
set_bit(&byTypeBB[0], s); // HACK: byTypeBB[0] contains all occupied squares.
pieceCount[c][pt]++;
-
- if (pt == KING)
- kingSquare[c] = s;
}
Color us = side_to_move();
Color them = opposite_color(us);
Square ksq = king_square(them);
- if (square_is_attacked(ksq, us))
+ if (attackers_to(ksq) & pieces_of_color(us))
return false;
}
for(PieceType pt = PAWN; pt <= KING; pt++)
for(int i = 0; i < pieceCount[c][pt]; i++)
{
- if (piece_on(piece_list(c, pt, i)) != (pieces(pt, c)))
+ if (piece_on(piece_list(c, pt, i)) != piece_of_color_and_type(c, pt))
return false;
if (index[piece_list(c, pt, i)] != i)