Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING,
B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING };
Position p;
p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread());
Position p;
p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread());
// Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition"
// situations. Description of the algorithm in the following paper:
// Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition"
// situations. Description of the algorithm in the following paper:
// First and second hash functions for indexing the cuckoo tables
inline int H1(Key h) { return h & 0x1fff; }
// First and second hash functions for indexing the cuckoo tables
inline int H1(Key h) { return h & 0x1fff; }
// Prepare the cuckoo tables
std::memset(cuckoo, 0, sizeof(cuckoo));
std::memset(cuckooMove, 0, sizeof(cuckooMove));
// Prepare the cuckoo tables
std::memset(cuckoo, 0, sizeof(cuckoo));
std::memset(cuckooMove, 0, sizeof(cuckooMove));
Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1);
Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
Square kto = relative_square(c, cr & KING_SIDE ? SQ_G1 : SQ_C1);
Square rto = relative_square(c, cr & KING_SIDE ? SQ_F1 : SQ_D1);
- si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinners[BLACK]);
- si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinners[WHITE]);
+ st->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), st->pinners[BLACK]);
+ st->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), st->pinners[WHITE]);
- si->checkSquares[PAWN] = pawn_attacks_bb(~sideToMove, ksq);
- si->checkSquares[KNIGHT] = attacks_bb<KNIGHT>(ksq);
- si->checkSquares[BISHOP] = attacks_bb<BISHOP>(ksq, pieces());
- si->checkSquares[ROOK] = attacks_bb<ROOK>(ksq, pieces());
- si->checkSquares[QUEEN] = si->checkSquares[BISHOP] | si->checkSquares[ROOK];
- si->checkSquares[KING] = 0;
+ st->checkSquares[PAWN] = pawn_attacks_bb(~sideToMove, ksq);
+ st->checkSquares[KNIGHT] = attacks_bb<KNIGHT>(ksq);
+ st->checkSquares[BISHOP] = attacks_bb<BISHOP>(ksq, pieces());
+ st->checkSquares[ROOK] = attacks_bb<ROOK>(ksq, pieces());
+ st->checkSquares[QUEEN] = st->checkSquares[BISHOP] | st->checkSquares[ROOK];
+ st->checkSquares[KING] = 0;
/// The function is only used when a new position is set up, and to verify
/// the correctness of the StateInfo data when running in debug mode.
/// The function is only used when a new position is set up, and to verify
/// the correctness of the StateInfo data when running in debug mode.
- si->key = si->materialKey = 0;
- si->pawnKey = Zobrist::noPawns;
- si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO;
- si->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
+ st->key = st->materialKey = 0;
+ st->pawnKey = Zobrist::noPawns;
+ st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO;
+ st->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
/// Position::fen() returns a FEN representation of the position. In case of
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
/// Position::fen() returns a FEN representation of the position. In case of
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
Bitboard b = between_bb(s, sniperSq) & occupancy;
if (b && !more_than_one(b))
Bitboard b = between_bb(s, sniperSq) & occupancy;
if (b && !more_than_one(b))
// 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.
// 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 the moving piece is a king, check whether the destination square is
// attacked by the opponent.
if (type_of(piece_on(from)) == KING)
}
// If the moving piece is a king, check whether the destination square is
// attacked by the opponent.
if (type_of(piece_on(from)) == KING)
// 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.
// 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.
- return !(blockers_for_king(us) & from)
- || aligned(from, to, square<KING>(us));
+ return !(blockers_for_king(us) & from)
+ || aligned(from, to, square<KING>(us));
// If the 'from' square is not occupied by a piece belonging to the side to
// move, the move is obviously not legal.
// If the 'from' square is not occupied by a piece belonging to the side to
// move, the move is obviously not legal.
- // Our move must be a blocking evasion or a capture of the checking piece
- if (!((between_bb(lsb(checkers()), square<KING>(us)) | checkers()) & to))
+ // Our move must be a blocking interposition or a capture of the checking piece
+ if (!(between_bb(square<KING>(us), lsb(checkers())) & to))
// 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.
// 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.
{
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>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
| (attacks_bb<BISHOP>(square<KING>(~sideToMove), 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 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);
assert(color_of(pc) == us);
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
assert(color_of(pc) == us);
assert(captured == NO_PIECE || color_of(captured) == (type_of(m) != CASTLING ? them : us));
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
// Update material hash key and prefetch access to materialTable
k ^= Zobrist::psq[captured][capsq];
st->materialKey ^= Zobrist::psq[captured][pieceCount[captured]];
if ( (int(to) ^ int(from)) == 16
&& (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
{
if ( (int(to) ^ int(from)) == 16
&& (pawn_attacks_bb(us, to - pawn_push(us)) & pieces(them, PAWN)))
{
// Calculate the repetition info. It is the ply distance from the previous
// occurrence of the same position, negative in the 3-fold case, or zero
// Calculate the repetition info. It is the ply distance from the previous
// occurrence of the same position, negative in the 3-fold case, or zero
/// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt) {
/// the side to move without executing any move on the board.
void Position::do_null_move(StateInfo& newSt) {
st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
st->dirtyPiece.dirty_num = 0;
st->dirtyPiece.piece[0] = NO_PIECE; // Avoid checks in UpdateAccumulator()
/// Position::key_after() computes the new hash key after the given move. Needed
/// for speculative prefetch. It doesn't recognize special moves like castling,
/// Position::key_after() computes the new hash key after the given move. Needed
/// for speculative prefetch. It doesn't recognize special moves like castling,
/// SEE value of move is greater or equal to the given threshold. We'll use an
/// algorithm similar to alpha-beta pruning with a null window.
/// SEE value of move is greater or equal to the given threshold. We'll use an
/// algorithm similar to alpha-beta pruning with a null window.
- Bitboard occupied = pieces() ^ from ^ to;
- Color stm = color_of(piece_on(from));
+ assert(color_of(piece_on(from)) == sideToMove);
+ occupied = pieces() ^ from ^ to; // xoring to is important for pinned piece logic
+ Color stm = sideToMove;
Bitboard attackers = attackers_to(to, occupied);
Bitboard stmAttackers, bb;
int res = 1;
Bitboard attackers = attackers_to(to, occupied);
Bitboard stmAttackers, bb;
int res = 1;
- // Don't allow pinned pieces to attack (except the king) as long as
- // there are pinners on their original square.
+ // Don't allow pinned pieces to attack as long as there are
+ // pinners on their original square.
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(KNIGHT)))
{
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(KNIGHT)))
{
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(ROOK)))
{
attackers |= attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN);
}
else if ((bb = stmAttackers & pieces(ROOK)))
{
attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
}
else if ((bb = stmAttackers & pieces(QUEEN)))
{
attackers |= attacks_bb<ROOK>(to, occupied) & pieces(ROOK, QUEEN);
}
else if ((bb = stmAttackers & pieces(QUEEN)))
{
attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
| (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
}
attackers |= (attacks_bb<BISHOP>(to, occupied) & pieces(BISHOP, QUEEN))
| (attacks_bb<ROOK >(to, occupied) & pieces(ROOK , QUEEN));
}
- StateInfo si = *st;
- ASSERT_ALIGNED(&si, Eval::NNUE::kCacheLineSize);
-
- set_state(&si);
- if (std::memcmp(&si, st, sizeof(StateInfo)))
- assert(0 && "pos_is_ok: State");