Key Position::zobCastle[16];
Key Position::zobMaterial[2][8][16];
Key Position::zobSideToMove;
+Key Position::zobExclusion;
Score Position::PieceSquareTable[16][64];
while (fen[i] == ' ')
i++;
- // En passant square
+ // En passant square -- ignore if no capture is possible
if ( i <= fen.length() - 2
&& (fen[i] >= 'a' && fen[i] <= 'h')
&& (fen[i+1] == '3' || fen[i+1] == '6'))
- st->epSquare = square_from_string(fen.substr(i, 2));
+ {
+ Square fenEpSquare = square_from_string(fen.substr(i, 2));
+ Color them = opposite_color(sideToMove);
+ if (attacks_from<PAWN>(fenEpSquare, them) & this->pieces(PAWN, sideToMove))
+ st->epSquare = square_from_string(fen.substr(i, 2));
+ }
// Various initialisation
for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
/// king) pieces for the given color and for the given pinner type. Or, when
/// template parameter FindPinned is false, the pieces of the given color
/// candidate for a discovery check against the enemy king.
-/// Note that checkersBB bitboard must be already updated.
+/// Bitboard checkersBB must be already updated when looking for pinners.
template<bool FindPinned>
Bitboard Position::hidden_checkers(Color c) const {
- Bitboard pinners, result = EmptyBoardBB;
+ Bitboard result = EmptyBoardBB;
+ Bitboard pinners = pieces_of_color(FindPinned ? opposite_color(c) : c);
// Pinned pieces protect our king, dicovery checks attack
// the enemy king.
Square ksq = king_square(FindPinned ? c : opposite_color(c));
- // Pinners are sliders, not checkers, that give check when
- // candidate pinned is removed.
- pinners = (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
- | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
+ // Pinners are sliders, not checkers, that give check when candidate pinned is removed
+ pinners &= (pieces(ROOK, QUEEN) & RookPseudoAttacks[ksq]) | (pieces(BISHOP, QUEEN) & BishopPseudoAttacks[ksq]);
if (FindPinned && pinners)
pinners &= ~st->checkersBB;
/// Position:pinned_pieces() returns a bitboard of all pinned (against the
-/// king) pieces for the given color.
+/// king) pieces for the given color. Note that checkersBB bitboard must
+/// be already updated.
Bitboard Position::pinned_pieces(Color c) const {
/// Position:discovered_check_candidates() returns a bitboard containing all
/// pieces for the given side which are candidates for giving a discovered
-/// check.
+/// check. Contrary to pinned_pieces() here there is no need of checkersBB
+/// to be already updated.
Bitboard Position::discovered_check_candidates(Color c) const {
}
-/// Position::update_checkers() udpates chekers info given the move. It is called
-/// in do_move() and is faster then find_checkers().
-
-template<PieceType Piece>
-inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square from,
- Square to, Bitboard dcCandidates) {
-
- const bool Bishop = (Piece == QUEEN || Piece == BISHOP);
- const bool Rook = (Piece == QUEEN || Piece == ROOK);
- const bool Slider = Bishop || Rook;
-
- assert(*pCheckersBB == EmptyBoardBB);
-
- // Direct checks
- if ( ( !Slider // try to early skip slide piece attacks
- || (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
- || (Rook && bit_is_set(RookPseudoAttacks[ksq], to)))
- && bit_is_set(Piece == PAWN ? attacks_from<PAWN>(ksq, opposite_color(sideToMove)) : attacks_from<Piece>(ksq) , to))
- {
- *pCheckersBB = SetMaskBB[to];
- }
- // Discovery checks
- if (Piece != QUEEN && dcCandidates && bit_is_set(dcCandidates, from))
- {
- if (Piece != ROOK)
- (*pCheckersBB) |= (attacks_from<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
-
- if (Piece != BISHOP)
- (*pCheckersBB) |= (attacks_from<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
- }
-}
-
-
/// Position::do_move() makes a move, and saves all information necessary
/// to a StateInfo object. The move is assumed to be legal.
/// Pseudo-legal moves should be filtered out before this function is called.
void Position::do_move(Move m, StateInfo& newSt) {
- do_move(m, newSt, discovered_check_candidates(side_to_move()));
+ CheckInfo ci(*this);
+ do_move(m, newSt, ci, move_is_check(m, ci));
}
-void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates, bool moveCanBeCheck) {
+void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveIsCheck) {
assert(is_ok());
assert(move_is_ok(m));
Key pawnKey, materialKey;
int castleRights, rule50, pliesFromNull;
Square epSquare;
- Value value;
+ Score value;
Value npMaterial[2];
};
// Update checkers bitboard, piece must be already moved
st->checkersBB = EmptyBoardBB;
- if (moveCanBeCheck)
+ if (moveIsCheck)
{
if (ep | pm)
st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
else
{
- Square ksq = king_square(them);
- switch (pt)
+ // Direct checks
+ if (bit_is_set(ci.checkSq[pt], to))
+ st->checkersBB = SetMaskBB[to];
+
+ // Discovery checks
+ if (ci.dcCandidates && bit_is_set(ci.dcCandidates, from))
{
- case PAWN: update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- case BISHOP: update_checkers<BISHOP>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- case ROOK: update_checkers<ROOK>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- case QUEEN: update_checkers<QUEEN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- case KING: update_checkers<KING>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
- default: assert(false); break;
+ if (pt != ROOK)
+ st->checkersBB |= (attacks_from<ROOK>(ci.ksq) & pieces(ROOK, QUEEN, us));
+
+ if (pt != BISHOP)
+ st->checkersBB |= (attacks_from<BISHOP>(ci.ksq) & pieces(BISHOP, QUEEN, us));
}
}
}
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);
assert(piece_on(kto) == piece_of_color_and_type(us, KING));
assert(piece_on(rto) == piece_of_color_and_type(us, ROOK));
-
+
// Remove pieces from destination squares:
clear_bit(&(byColorBB[us]), kto);
clear_bit(&(byTypeBB[KING]), kto);
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);
for (int i = 0; i < 16; i++)
zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL);
+
+ zobExclusion = genrand_int64();
}