X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=7f997bb776376874a36c882c206c8a57b4ce1147;hp=8b043af83b4a0826c0d0fe52000bce970cce9c79;hb=96f4ab48d8b2e3129a2d028f7739f12db2200667;hpb=d549497144ee2a704057e005d2bbe1fbc666ca7e diff --git a/src/position.cpp b/src/position.cpp index 8b043af8..7f997bb7 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 @@ -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 { @@ -371,9 +364,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; @@ -428,7 +421,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; @@ -570,7 +563,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 +571,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 +581,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 +608,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 +641,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; } @@ -830,7 +823,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; @@ -934,9 +927,7 @@ void Position::do_move(Move m, StateInfo& newSt, const CheckInfo& ci, bool moveI } } - // Finish sideToMove = ~sideToMove; - st->psqScore += (sideToMove == WHITE ? Tempo : -Tempo); assert(pos_is_ok()); } @@ -965,7 +956,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 +986,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 +1069,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 +1118,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 +1161,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 +1332,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 +1358,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 +1378,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 +1395,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 +1414,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 +1498,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,7 +1527,7 @@ 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)) @@ -1565,11 +1542,12 @@ void Position::flip() { 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 +1560,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 +1601,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 +1626,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))) 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,19 +1666,23 @@ bool Position::pos_is_ok(int* failedStep) const { return false; } - if (failedStep) (*failedStep)++; - if (debugCastleSquares) + if ((*step)++, debugCastleSquares) for (Color c = WHITE; c <= BLACK; c++) for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) { - if (!can_castle(make_castle_right(c, s))) + CastleRight cr = make_castle_right(c, s); + + if (!can_castle(cr)) continue; + if ((castleRightsMask[king_square(c)] & cr) != cr) + return false; + if ( piece_on(castleRookSquare[c][s]) != make_piece(c, ROOK) - || castleRightsMask[castleRookSquare[c][s]] != make_castle_right(c, s)) + || castleRightsMask[castleRookSquare[c][s]] != cr) return false; } - if (failedStep) *failedStep = 0; + *step = 0; return true; }