X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=c26ab1b6884abe0c17066dac51ada332f900033c;hp=318f0f2c51ad94fb98c9648aa269f4fd19d4319f;hb=3361ad42420e578362dcafb94b639738609bf7d7;hpb=676b2c8435502409145491f2f86454f11f99dae8 diff --git a/src/position.cpp b/src/position.cpp index 318f0f2c..c26ab1b6 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -62,15 +62,8 @@ const Value PieceValueEndgame[17] = { RookValueEndgame, QueenValueEndgame }; - -namespace { - - // Bonus for having the side to move (modified by Joona Kiiski) - const Score Tempo = make_score(48, 22); - - // To convert a Piece to and from a FEN char - const string PieceToChar(" PNBRQK pnbrqk ."); -} +// To convert a Piece to and from a FEN char +static const string PieceToChar(" PNBRQK pnbrqk"); /// CheckInfo c'tor @@ -161,7 +154,7 @@ void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) { sq += Square(token - '0'); // Advance the given number of files else if (token == '/') - sq = make_square(FILE_A, rank_of(sq) - Rank(2)); + sq -= Square(16); else if ((p = PieceToChar.find(token)) != string::npos) { @@ -208,7 +201,7 @@ void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) { { st->epSquare = make_square(File(col - 'a'), Rank(row - '1')); - if (!(attackers_to(st->epSquare) & pieces(PAWN, sideToMove))) + if (!(attackers_to(st->epSquare) & pieces(sideToMove, PAWN))) st->epSquare = SQ_NONE; } @@ -239,24 +232,24 @@ void Position::from_fen(const string& fenStr, bool isChess960, Thread* th) { void Position::set_castle_right(Color c, Square rfrom) { Square kfrom = king_square(c); - bool kingSide = kfrom < rfrom; - int cr = (kingSide ? WHITE_OO : WHITE_OOO) << c; + CastlingSide cs = kfrom < rfrom ? KING_SIDE : QUEEN_SIDE; + CastleRight cr = make_castle_right(c, cs); st->castleRights |= cr; castleRightsMask[kfrom] |= cr; castleRightsMask[rfrom] |= cr; - castleRookSquare[cr] = rfrom; + castleRookSquare[c][cs] = rfrom; - Square kto = relative_square(c, kingSide ? SQ_G1 : SQ_C1); - Square rto = relative_square(c, kingSide ? SQ_F1 : SQ_D1); + Square kto = relative_square(c, cs == KING_SIDE ? SQ_G1 : SQ_C1); + Square rto = relative_square(c, cs == KING_SIDE ? SQ_F1 : SQ_D1); for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); s++) if (s != kfrom && s != rfrom) - castlePath[cr] |= s; + castlePath[c][cs] |= s; for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); s++) if (s != kfrom && s != rfrom) - castlePath[cr] |= s; + castlePath[c][cs] |= s; } @@ -277,7 +270,7 @@ const string Position::to_fen() const { { sq = make_square(file, rank); - if (square_empty(sq)) + if (is_empty(sq)) emptyCnt++; else { @@ -300,16 +293,16 @@ const string Position::to_fen() const { fen << (sideToMove == WHITE ? " w " : " b "); if (can_castle(WHITE_OO)) - fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OO))))) : 'K'); + fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, KING_SIDE))))) : 'K'); if (can_castle(WHITE_OOO)) - fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OOO))))) : 'Q'); + fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE, QUEEN_SIDE))))) : 'Q'); if (can_castle(BLACK_OO)) - fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OO))) : 'k'); + fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, KING_SIDE))) : 'k'); if (can_castle(BLACK_OOO)) - fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OOO))) : 'q'); + fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK, QUEEN_SIDE))) : 'q'); if (st->castleRights == CASTLES_NONE) fen << '-'; @@ -326,7 +319,11 @@ const string Position::to_fen() const { void Position::print(Move move) const { - const char* dottedLine = "\n+---+---+---+---+---+---+---+---+\n"; + const string dottedLine = "\n+---+---+---+---+---+---+---+---+"; + const string twoRows = dottedLine + "\n| | . | | . | | . | | . |" + + dottedLine + "\n| . | | . | | . | | . | |"; + + string brd = twoRows + twoRows + twoRows + twoRows + dottedLine; if (move) { @@ -334,22 +331,11 @@ void Position::print(Move move) const { cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move); } - for (Rank rank = RANK_8; rank >= RANK_1; rank--) - { - cout << dottedLine << '|'; - for (File file = FILE_A; file <= FILE_H; file++) - { - Square sq = make_square(file, rank); - Piece piece = piece_on(sq); - char c = (color_of(piece) == BLACK ? '=' : ' '); - - if (piece == NO_PIECE && !opposite_colors(sq, SQ_A1)) - piece++; // Index the dot + for (Square sq = SQ_A1; sq <= SQ_H8; sq++) + if (piece_on(sq) != NO_PIECE) + brd[513 - 68*rank_of(sq) + 4*file_of(sq)] = PieceToChar[piece_on(sq)]; - cout << c << PieceToChar[piece] << c << '|'; - } - } - cout << dottedLine << "Fen is: " << to_fen() << "\nKey is: " << st->key << endl; + cout << brd << "\nFen is: " << to_fen() << "\nKey is: " << st->key << endl; } @@ -371,9 +357,9 @@ Bitboard Position::hidden_checkers() const { while (pinners) { - b = squares_between(ksq, pop_1st_bit(&pinners)) & pieces(); + b = between_bb(ksq, pop_1st_bit(&pinners)) & pieces(); - if (b && single_bit(b) && (b & pieces(sideToMove))) + if (b && !more_than_one(b) && (b & pieces(sideToMove))) result |= b; } return result; @@ -389,8 +375,8 @@ template Bitboard Position::hidden_checkers() const; Bitboard Position::attackers_to(Square s, Bitboard occ) const { - return (attacks_from(s, BLACK) & pieces(PAWN, WHITE)) - | (attacks_from(s, WHITE) & pieces(PAWN, BLACK)) + return (attacks_from(s, BLACK) & pieces(WHITE, PAWN)) + | (attacks_from(s, WHITE) & pieces(BLACK, PAWN)) | (attacks_from(s) & pieces(KNIGHT)) | (attacks_bb(s, occ) & pieces(ROOK, QUEEN)) | (attacks_bb(s, occ) & pieces(BISHOP, QUEEN)) @@ -428,7 +414,7 @@ bool Position::move_attacks_square(Move m, Square s) const { Square to = to_sq(m); Piece piece = piece_moved(m); - assert(!square_empty(from)); + assert(!is_empty(from)); // Update occupancy as if the piece is moving occ = pieces() ^ from ^ to; @@ -438,8 +424,8 @@ bool Position::move_attacks_square(Move m, Square s) const { return true; // Scan for possible X-ray attackers behind the moved piece - xray = (attacks_bb(s, occ) & pieces(ROOK, QUEEN, color_of(piece))) - |(attacks_bb(s, occ) & pieces(BISHOP, QUEEN, color_of(piece))); + xray = (attacks_bb< ROOK>(s, occ) & pieces(color_of(piece), QUEEN, ROOK)) + | (attacks_bb(s, occ) & pieces(color_of(piece), QUEEN, BISHOP)); // Verify attackers are triggered by our move and not already existing return xray && (xray ^ (xray & attacks_from(s))); @@ -475,8 +461,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { assert(piece_on(capsq) == make_piece(them, PAWN)); assert(piece_on(to) == NO_PIECE); - return !(attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them)) - && !(attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them)); + return !(attacks_bb< ROOK>(ksq, b) & pieces(them, QUEEN, ROOK)) + && !(attacks_bb(ksq, b) & pieces(them, QUEEN, BISHOP)); } // If the moving piece is a king, check whether the destination @@ -570,7 +556,7 @@ bool Position::is_pseudo_legal(const Move m) const { case DELTA_N: case DELTA_S: // Pawn push. The destination square must be empty. - if (!square_empty(to)) + if (!is_empty(to)) return false; break; @@ -578,9 +564,9 @@ bool Position::is_pseudo_legal(const Move m) const { // Double white pawn push. The destination square must be on the fourth // rank, and both the destination square and the square between the // source and destination squares must be empty. - if ( rank_of(to) != RANK_4 - || !square_empty(to) - || !square_empty(from + DELTA_N)) + if ( rank_of(to) != RANK_4 + || !is_empty(to) + || !is_empty(from + DELTA_N)) return false; break; @@ -588,9 +574,9 @@ bool Position::is_pseudo_legal(const Move m) const { // Double black pawn push. The destination square must be on the fifth // rank, and both the destination square and the square between the // source and destination squares must be empty. - if ( rank_of(to) != RANK_5 - || !square_empty(to) - || !square_empty(from + DELTA_S)) + if ( rank_of(to) != RANK_5 + || !is_empty(to) + || !is_empty(from + DELTA_S)) return false; break; @@ -615,7 +601,7 @@ bool Position::is_pseudo_legal(const Move m) const { return false; // Our move must be a blocking evasion or a capture of the checking piece - if (!((squares_between(checksq, king_square(us)) | checkers()) & to)) + if (!((between_bb(checksq, king_square(us)) | checkers()) & to)) return false; } // In case of king moves under check we have to remove king so to catch @@ -648,7 +634,7 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { if (ci.dcCandidates && (ci.dcCandidates & from)) { // For pawn and king moves we need to verify also direction - if ( (pt != PAWN && pt != KING) + if ( (pt != PAWN && pt != KING) || !squares_aligned(from, to, king_square(~sideToMove))) return true; } @@ -673,8 +659,8 @@ bool Position::move_gives_check(Move m, const CheckInfo& ci) const { Square capsq = make_square(file_of(to), rank_of(from)); Bitboard b = (pieces() ^ from ^ capsq) | to; - return (attacks_bb< ROOK>(ksq, b) & pieces( ROOK, QUEEN, us)) - | (attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us)); + return (attacks_bb< ROOK>(ksq, b) & pieces(us, QUEEN, ROOK)) + | (attacks_bb(ksq, b) & pieces(us, QUEEN, BISHOP)); } // Castling with check ? @@ -714,14 +700,6 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI // Copy some fields of old state to our new StateInfo object except the ones // which are recalculated from scratch anyway, then switch our state pointer // to point to the new, ready to be updated, state. - struct ReducedStateInfo { - Key pawnKey, materialKey; - Value npMaterial[2]; - int castleRights, rule50, pliesFromNull; - Score psq_score; - Square epSquare; - }; - memcpy(&newSt, st, sizeof(ReducedStateInfo)); newSt.previous = st; @@ -830,7 +808,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI prefetch((char*)TT.first_entry(k)); // Move the piece - Bitboard from_to_bb = SquareBB[from] | SquareBB[to]; + Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to]; byTypeBB[ALL_PIECES] ^= from_to_bb; byTypeBB[pt] ^= from_to_bb; byColorBB[us] ^= from_to_bb; @@ -848,7 +826,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI { // Set en-passant square, only if moved pawn can be captured if ( (int(to) ^ int(from)) == 16 - && (attacks_from(from + pawn_push(us), us) & pieces(PAWN, them))) + && (attacks_from(from + pawn_push(us), us) & pieces(them, PAWN))) { st->epSquare = Square((from + to) / 2); k ^= zobEp[file_of(st->epSquare)]; @@ -926,17 +904,15 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI if (ci.dcCandidates && (ci.dcCandidates & from)) { if (pt != ROOK) - st->checkersBB |= attacks_from(king_square(them)) & pieces(ROOK, QUEEN, us); + st->checkersBB |= attacks_from(king_square(them)) & pieces(us, QUEEN, ROOK); if (pt != BISHOP) - st->checkersBB |= attacks_from(king_square(them)) & pieces(BISHOP, QUEEN, us); + st->checkersBB |= attacks_from(king_square(them)) & pieces(us, QUEEN, BISHOP); } } } - // Finish sideToMove = ~sideToMove; - st->psqScore += (sideToMove == WHITE ? Tempo : -Tempo); assert(pos_is_ok()); } @@ -965,7 +941,7 @@ void Position::undo_move(Move m) { PieceType pt = type_of(piece); PieceType capture = st->capturedType; - assert(square_empty(from)); + assert(is_empty(from)); assert(color_of(piece) == us); assert(capture != KING); @@ -995,7 +971,7 @@ void Position::undo_move(Move m) { } // Put the piece back at the source square - Bitboard from_to_bb = SquareBB[from] | SquareBB[to]; + Bitboard from_to_bb = SquareBB[from] ^ SquareBB[to]; byTypeBB[ALL_PIECES] ^= from_to_bb; byTypeBB[pt] ^= from_to_bb; byColorBB[us] ^= from_to_bb; @@ -1078,21 +1054,13 @@ void Position::do_castle_move(Move m) { assert(piece_on(kfrom) == make_piece(us, KING)); assert(piece_on(rfrom) == make_piece(us, ROOK)); - // Remove pieces from source squares - byTypeBB[ALL_PIECES] ^= kfrom; - byTypeBB[KING] ^= kfrom; - byColorBB[us] ^= kfrom; - byTypeBB[ALL_PIECES] ^= rfrom; - byTypeBB[ROOK] ^= rfrom; - byColorBB[us] ^= rfrom; - - // Put pieces on destination squares - byTypeBB[ALL_PIECES] |= kto; - byTypeBB[KING] |= kto; - byColorBB[us] |= kto; - byTypeBB[ALL_PIECES] |= rto; - byTypeBB[ROOK] |= rto; - byColorBB[us] |= rto; + // Move the pieces, with some care; in chess960 could be kto == rfrom + Bitboard k_from_to_bb = SquareBB[kfrom] ^ SquareBB[kto]; + Bitboard r_from_to_bb = SquareBB[rfrom] ^ SquareBB[rto]; + byTypeBB[KING] ^= k_from_to_bb; + byTypeBB[ROOK] ^= r_from_to_bb; + byTypeBB[ALL_PIECES] ^= k_from_to_bb ^ r_from_to_bb; + byColorBB[us] ^= k_from_to_bb ^ r_from_to_bb; // Update board Piece king = make_piece(us, KING); @@ -1135,9 +1103,7 @@ void Position::do_castle_move(Move m) { // Update checkers BB st->checkersBB = attackers_to(king_square(~us)) & pieces(us); - // Finish sideToMove = ~sideToMove; - st->psqScore += (sideToMove == WHITE ? Tempo : -Tempo); } else // Undo: point our state pointer back to the previous state @@ -1180,7 +1146,6 @@ void Position::do_null_move(StateInfo& backupSt) { st->epSquare = SQ_NONE; st->rule50++; st->pliesFromNull = 0; - st->psqScore += (sideToMove == WHITE ? Tempo : -Tempo); } assert(pos_is_ok()); @@ -1352,19 +1317,21 @@ void Position::put_piece(Piece p, Square s) { Key Position::compute_key() const { - Key result = zobCastle[st->castleRights]; + Key k = zobCastle[st->castleRights]; - for (Square s = SQ_A1; s <= SQ_H8; s++) - if (!square_empty(s)) - result ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s]; + for (Bitboard b = pieces(); b; ) + { + Square s = pop_1st_bit(&b); + k ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s]; + } if (ep_square() != SQ_NONE) - result ^= zobEp[file_of(ep_square())]; + k ^= zobEp[file_of(ep_square())]; if (sideToMove == BLACK) - result ^= zobSideToMove; + k ^= zobSideToMove; - return result; + return k; } @@ -1376,16 +1343,15 @@ Key Position::compute_key() const { Key Position::compute_pawn_key() const { - Bitboard b; - Key result = 0; + Key k = 0; - for (Color c = WHITE; c <= BLACK; c++) + for (Bitboard b = pieces(PAWN); b; ) { - b = pieces(PAWN, c); - while (b) - result ^= zobrist[c][PAWN][pop_1st_bit(&b)]; + Square s = pop_1st_bit(&b); + k ^= zobrist[color_of(piece_on(s))][PAWN][s]; } - return result; + + return k; } @@ -1397,14 +1363,14 @@ Key Position::compute_pawn_key() const { Key Position::compute_material_key() const { - Key result = 0; + Key k = 0; for (Color c = WHITE; c <= BLACK; c++) for (PieceType pt = PAWN; pt <= QUEEN; pt++) - for (int i = 0; i < piece_count(c, pt); i++) - result ^= zobrist[c][pt][i]; + for (int cnt = 0; cnt < piece_count(c, pt); cnt++) + k ^= zobrist[c][pt][cnt]; - return result; + return k; } @@ -1414,19 +1380,15 @@ Key Position::compute_material_key() const { /// updated by do_move and undo_move when the program is running in debug mode. Score Position::compute_psq_score() const { - Bitboard b; - Score result = SCORE_ZERO; + Score score = SCORE_ZERO; - for (Color c = WHITE; c <= BLACK; c++) - for (PieceType pt = PAWN; pt <= KING; pt++) - { - b = pieces(pt, c); - while (b) - result += pieceSquareTable[make_piece(c, pt)][pop_1st_bit(&b)]; - } + for (Bitboard b = pieces(); b; ) + { + Square s = pop_1st_bit(&b); + score += pieceSquareTable[piece_on(s)][s]; + } - result += (sideToMove == WHITE ? Tempo / 2 : -Tempo / 2); - return result; + return score; } @@ -1437,12 +1399,12 @@ Score Position::compute_psq_score() const { Value Position::compute_non_pawn_material(Color c) const { - Value result = VALUE_ZERO; + Value value = VALUE_ZERO; for (PieceType pt = KNIGHT; pt <= QUEEN; pt++) - result += piece_count(c, pt) * PieceValueMidgame[pt]; + value += piece_count(c, pt) * PieceValueMidgame[pt]; - return result; + return value; } @@ -1521,14 +1483,14 @@ void Position::init() { zobSideToMove = rk.rand(); zobExclusion = rk.rand(); - for (Piece p = W_PAWN; p <= W_KING; p++) + for (PieceType pt = PAWN; pt <= KING; pt++) { - Score ps = make_score(PieceValueMidgame[p], PieceValueEndgame[p]); + Score v = make_score(PieceValueMidgame[pt], PieceValueEndgame[pt]); for (Square s = SQ_A1; s <= SQ_H8; s++) { - pieceSquareTable[p][s] = ps + PSQT[p][s]; - pieceSquareTable[p+8][~s] = -pieceSquareTable[p][s]; + pieceSquareTable[make_piece(WHITE, pt)][ s] = (v + PSQT[pt][s]); + pieceSquareTable[make_piece(BLACK, pt)][~s] = -(v + PSQT[pt][s]); } } } @@ -1550,26 +1512,27 @@ void Position::flip() { startPosPly = pos.startpos_ply_counter(); for (Square s = SQ_A1; s <= SQ_H8; s++) - if (!pos.square_empty(s)) + if (!pos.is_empty(s)) put_piece(Piece(pos.piece_on(s) ^ 8), ~s); if (pos.can_castle(WHITE_OO)) - set_castle_right(BLACK, ~pos.castle_rook_square(WHITE_OO)); + set_castle_right(BLACK, ~pos.castle_rook_square(WHITE, KING_SIDE)); if (pos.can_castle(WHITE_OOO)) - set_castle_right(BLACK, ~pos.castle_rook_square(WHITE_OOO)); + set_castle_right(BLACK, ~pos.castle_rook_square(WHITE, QUEEN_SIDE)); if (pos.can_castle(BLACK_OO)) - set_castle_right(WHITE, ~pos.castle_rook_square(BLACK_OO)); + set_castle_right(WHITE, ~pos.castle_rook_square(BLACK, KING_SIDE)); if (pos.can_castle(BLACK_OOO)) - set_castle_right(WHITE, ~pos.castle_rook_square(BLACK_OOO)); + set_castle_right(WHITE, ~pos.castle_rook_square(BLACK, QUEEN_SIDE)); if (pos.st->epSquare != SQ_NONE) st->epSquare = ~pos.st->epSquare; + st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); + st->key = compute_key(); st->pawnKey = compute_pawn_key(); st->materialKey = compute_material_key(); st->psqScore = compute_psq_score(); - st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); @@ -1582,42 +1545,39 @@ void Position::flip() { bool Position::pos_is_ok(int* failedStep) const { + int dummy, *step = failedStep ? failedStep : &dummy; + // What features of the position should be verified? - const bool debugAll = false; - - const bool debugBitboards = debugAll || false; - const bool debugKingCount = debugAll || false; - const bool debugKingCapture = debugAll || false; - const bool debugCheckerCount = debugAll || false; - const bool debugKey = debugAll || false; - const bool debugMaterialKey = debugAll || false; - const bool debugPawnKey = debugAll || false; - const bool debugIncrementalEval = debugAll || false; - const bool debugNonPawnMaterial = debugAll || false; - const bool debugPieceCounts = debugAll || false; - const bool debugPieceList = debugAll || false; - const bool debugCastleSquares = debugAll || false; - - if (failedStep) *failedStep = 1; - - // Side to move OK? + const bool all = false; + + const bool debugBitboards = all || false; + const bool debugKingCount = all || false; + const bool debugKingCapture = all || false; + const bool debugCheckerCount = all || false; + const bool debugKey = all || false; + const bool debugMaterialKey = all || false; + const bool debugPawnKey = all || false; + const bool debugIncrementalEval = all || false; + const bool debugNonPawnMaterial = all || false; + const bool debugPieceCounts = all || false; + const bool debugPieceList = all || false; + const bool debugCastleSquares = all || false; + + *step = 1; + if (sideToMove != WHITE && sideToMove != BLACK) return false; - // Are the king squares in the position correct? - if (failedStep) (*failedStep)++; - if (piece_on(king_square(WHITE)) != W_KING) + if ((*step)++, piece_on(king_square(WHITE)) != W_KING) return false; - if (failedStep) (*failedStep)++; - if (piece_on(king_square(BLACK)) != B_KING) + if ((*step)++, piece_on(king_square(BLACK)) != B_KING) return false; - // Do both sides have exactly one king? - if (failedStep) (*failedStep)++; - if (debugKingCount) + if ((*step)++, debugKingCount) { - int kingCount[2] = {0, 0}; + int kingCount[2] = {}; + for (Square s = SQ_A1; s <= SQ_H8; s++) if (type_of(piece_on(s)) == KING) kingCount[color_of(piece_on(s))]++; @@ -1626,25 +1586,14 @@ bool Position::pos_is_ok(int* failedStep) const { return false; } - // Can the side to move capture the opponent's king? - if (failedStep) (*failedStep)++; - if (debugKingCapture) - { - Color us = sideToMove; - Color them = ~us; - Square ksq = king_square(them); - if (attackers_to(ksq) & pieces(us)) + if ((*step)++, debugKingCapture) + if (attackers_to(king_square(~sideToMove)) & pieces(sideToMove)) return false; - } - // Is there more than 2 checkers? - if (failedStep) (*failedStep)++; - if (debugCheckerCount && popcount(st->checkersBB) > 2) + if ((*step)++, debugCheckerCount && popcount(st->checkersBB) > 2) return false; - // Bitboards OK? - if (failedStep) (*failedStep)++; - if (debugBitboards) + if ((*step)++, debugBitboards) { // The intersection of the white and black pieces must be empty if (pieces(WHITE) & pieces(BLACK)) @@ -1662,57 +1611,35 @@ bool Position::pos_is_ok(int* failedStep) const { return false; } - // En passant square OK? - if (failedStep) (*failedStep)++; - if (ep_square() != SQ_NONE) - { - // The en passant square must be on rank 6, from the point of view of the - // side to move. - if (relative_rank(sideToMove, ep_square()) != RANK_6) - return false; - } + if ((*step)++, ep_square() != SQ_NONE && relative_rank(sideToMove, ep_square()) != RANK_6) + return false; - // Hash key OK? - if (failedStep) (*failedStep)++; - if (debugKey && st->key != compute_key()) + if ((*step)++, debugKey && st->key != compute_key()) return false; - // Pawn hash key OK? - if (failedStep) (*failedStep)++; - if (debugPawnKey && st->pawnKey != compute_pawn_key()) + if ((*step)++, debugPawnKey && st->pawnKey != compute_pawn_key()) return false; - // Material hash key OK? - if (failedStep) (*failedStep)++; - if (debugMaterialKey && st->materialKey != compute_material_key()) + if ((*step)++, debugMaterialKey && st->materialKey != compute_material_key()) return false; - // Incremental eval OK? - if (failedStep) (*failedStep)++; - if (debugIncrementalEval && st->psqScore != compute_psq_score()) + if ((*step)++, debugIncrementalEval && st->psqScore != compute_psq_score()) return false; - // Non-pawn material OK? - if (failedStep) (*failedStep)++; - if (debugNonPawnMaterial) + if ((*step)++, debugNonPawnMaterial) { - if (st->npMaterial[WHITE] != compute_non_pawn_material(WHITE)) - return false; - - if (st->npMaterial[BLACK] != compute_non_pawn_material(BLACK)) + if ( st->npMaterial[WHITE] != compute_non_pawn_material(WHITE) + || st->npMaterial[BLACK] != compute_non_pawn_material(BLACK)) return false; } - // Piece counts OK? - if (failedStep) (*failedStep)++; - if (debugPieceCounts) + if ((*step)++, debugPieceCounts) for (Color c = WHITE; c <= BLACK; c++) for (PieceType pt = PAWN; pt <= KING; pt++) - if (pieceCount[c][pt] != popcount(pieces(pt, c))) + if (pieceCount[c][pt] != popcount(pieces(c, pt))) return false; - if (failedStep) (*failedStep)++; - if (debugPieceList) + if ((*step)++, debugPieceList) for (Color c = WHITE; c <= BLACK; c++) for (PieceType pt = PAWN; pt <= KING; pt++) for (int i = 0; i < pieceCount[c][pt]; i++) @@ -1724,20 +1651,23 @@ bool Position::pos_is_ok(int* failedStep) const { return false; } - if (failedStep) (*failedStep)++; - if (debugCastleSquares) - for (CastleRight f = WHITE_OO; f <= BLACK_OOO; f = CastleRight(f << 1)) - { - if (!can_castle(f)) - continue; + if ((*step)++, debugCastleSquares) + for (Color c = WHITE; c <= BLACK; c++) + for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) + { + CastleRight cr = make_castle_right(c, s); - Piece rook = (f & (WHITE_OO | WHITE_OOO) ? W_ROOK : B_ROOK); + if (!can_castle(cr)) + continue; - if ( piece_on(castleRookSquare[f]) != rook - || castleRightsMask[castleRookSquare[f]] != f) - return false; - } + if ((castleRightsMask[king_square(c)] & cr) != cr) + return false; + + if ( piece_on(castleRookSquare[c][s]) != make_piece(c, ROOK) + || castleRightsMask[castleRookSquare[c][s]] != cr) + return false; + } - if (failedStep) *failedStep = 0; + *step = 0; return true; }