/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2020 The Stockfish developers (see AUTHORS file)
+ Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
std::memset(this, 0, sizeof(Position));
std::memset(si, 0, sizeof(StateInfo));
- std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
st = si;
ss >> std::noskipws;
// En passant captures are a tricky special case. Because they are rather
// uncommon, we do it simply by testing whether the king is attacked after
// the move is made.
- if (type_of(m) == ENPASSANT)
+ if (type_of(m) == EN_PASSANT)
{
Square ksq = square<KING>(us);
Square capsq = to - pawn_push(us);
if (attackers_to(s) & pieces(~us))
return false;
- // In case of Chess960, verify that when moving the castling rook we do
- // not discover some hidden checker.
+ // In case of Chess960, verify if the Rook blocks some checks
// For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
- return !chess960
- || !(attacks_bb<ROOK>(to, pieces() ^ to_sq(m)) & pieces(~us, ROOK, QUEEN));
+ return !chess960 || !(blockers_for_king(us) & to_sq(m));
}
// If the moving piece is a king, check whether the destination square is
Piece pc = moved_piece(m);
// Use a slower but simpler function for uncommon cases
+ // yet we skip the legality check of MoveList<LEGAL>().
if (type_of(m) != NORMAL)
- return MoveList<LEGAL>(*this).contains(m);
+ return checkers() ? MoveList< EVASIONS>(*this).contains(m)
+ : MoveList<NON_EVASIONS>(*this).contains(m);
// Is not a promotion, so promotion piece must be empty
if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE)
// of direct checks and ordinary discovered check, so the only case we
// need to handle is the unusual case of a discovered check through
// the captured pawn.
- case ENPASSANT:
+ case EN_PASSANT:
{
Square capsq = make_square(file_of(to), rank_of(from));
Bitboard b = (pieces() ^ from ^ capsq) | to;
return (attacks_bb< ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
| (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
}
- case CASTLING:
+ default: //CASTLING
{
- Square kfrom = from;
- Square rfrom = to; // Castling is encoded as 'king captures the rook'
- Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1);
- Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1);
+ // Castling is encoded as 'king captures the rook'
+ Square ksq = square<KING>(~sideToMove);
+ Square rto = relative_square(sideToMove, to > from ? SQ_F1 : SQ_D1);
- return (attacks_bb<ROOK>(rto) & square<KING>(~sideToMove))
- && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
+ return (attacks_bb<ROOK>(rto) & ksq)
+ && (attacks_bb<ROOK>(rto, pieces() ^ from ^ to) & ksq);
}
- default:
- assert(false);
- return false;
}
}
Square from = from_sq(m);
Square to = to_sq(m);
Piece pc = piece_on(from);
- Piece captured = type_of(m) == ENPASSANT ? make_piece(them, PAWN) : piece_on(to);
+ Piece captured = type_of(m) == EN_PASSANT ? make_piece(them, PAWN) : piece_on(to);
assert(color_of(pc) == us);
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
// update non-pawn material.
if (type_of(captured) == PAWN)
{
- if (type_of(m) == ENPASSANT)
+ if (type_of(m) == EN_PASSANT)
{
capsq -= pawn_push(us);
// Update board and piece lists
remove_piece(capsq);
- if (type_of(m) == ENPASSANT)
+ if (type_of(m) == EN_PASSANT)
board[capsq] = NO_PIECE;
// Update material hash key and prefetch access to materialTable
// If the moving piece is a pawn do some special extra work
if (type_of(pc) == PAWN)
{
- // Set en-passant square if the moved pawn can be captured
+ // Set en passant square if the moved pawn can be captured
if ( (int(to) ^ int(from)) == 16
&& (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
{
{
Square capsq = to;
- if (type_of(m) == ENPASSANT)
+ if (type_of(m) == EN_PASSANT)
{
capsq -= pawn_push(us);
}
st->key ^= Zobrist::side;
- prefetch(TT.first_entry(st->key));
+ prefetch(TT.first_entry(key()));
++st->rule50;
st->pliesFromNull = 0;
/// Position::key_after() computes the new hash key after the given move. Needed
/// for speculative prefetch. It doesn't recognize special moves like castling,
-/// en-passant and promotions.
+/// en passant and promotions.
Key Position::key_after(Move m) const {
assert(is_ok(m));
- // Only deal with normal moves, assume others pass a simple see
+ // Only deal with normal moves, assume others pass a simple SEE
if (type_of(m) != NORMAL)
return VALUE_ZERO >= threshold;
assert(0 && "pos_is_ok: State");
for (Piece pc : Pieces)
- {
if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc)))
|| pieceCount[pc] != std::count(board, board + SQUARE_NB, pc))
assert(0 && "pos_is_ok: Pieces");
- for (int i = 0; i < pieceCount[pc]; ++i)
- if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i)
- assert(0 && "pos_is_ok: Index");
- }
-
for (Color c : { WHITE, BLACK })
for (CastlingRights cr : {c & KING_SIDE, c & QUEEN_SIDE})
{