X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=12485fbb780fb64026e359bc97cdd271ea9c2599;hp=13cf59944a961c75f3b30afc2e7fd7c95eb4dbf2;hb=c6f497f09de59ce4889c2045e0e4b6efb3082899;hpb=81801d395f83ff757558f640bc5d5ce44031d2b5 diff --git a/src/position.cpp b/src/position.cpp index 13cf5994..12485fbb 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -120,29 +120,35 @@ void Position::from_fen(const string& fenStr, bool isChess960) { /* A FEN string defines a particular position using only the ASCII character set. - A FEN string contains six fields. The separator between fields is a space. The fields are: + A FEN string contains six fields separated by a space. The fields are: - 1) Piece placement (from white's perspective). Each rank is described, starting with rank 8 and ending - with rank 1; within each rank, the contents of each square are described from file A through file H. - Following the Standard Algebraic Notation (SAN), each piece is identified by a single letter taken - from the standard English names. White pieces are designated using upper-case letters ("PNBRQK") - while Black take lowercase ("pnbrqk"). Blank squares are noted using digits 1 through 8 (the number - of blank squares), and "/" separate ranks. + 1) Piece placement (from white's perspective). Each rank is described, starting + with rank 8 and ending with rank 1; within each rank, the contents of each + square are described from file A through file H. Following the Standard + Algebraic Notation (SAN), each piece is identified by a single letter taken + from the standard English names. White pieces are designated using upper-case + letters ("PNBRQK") while Black take lowercase ("pnbrqk"). Blank squares are + noted using digits 1 through 8 (the number of blank squares), and "/" + separates ranks. 2) Active color. "w" means white moves next, "b" means black. - 3) Castling availability. If neither side can castle, this is "-". Otherwise, this has one or more - letters: "K" (White can castle kingside), "Q" (White can castle queenside), "k" (Black can castle - kingside), and/or "q" (Black can castle queenside). + 3) Castling availability. If neither side can castle, this is "-". Otherwise, + this has one or more letters: "K" (White can castle kingside), "Q" (White + can castle queenside), "k" (Black can castle kingside), and/or "q" (Black + can castle queenside). - 4) En passant target square in algebraic notation. If there's no en passant target square, this is "-". - If a pawn has just made a 2-square move, this is the position "behind" the pawn. This is recorded - regardless of whether there is a pawn in position to make an en passant capture. + 4) En passant target square (in algebraic notation). If there's no en passant + target square, this is "-". If a pawn has just made a 2-square move, this + is the position "behind" the pawn. This is recorded regardless of whether + there is a pawn in position to make an en passant capture. - 5) Halfmove clock: This is the number of halfmoves since the last pawn advance or capture. This is used - to determine if a draw can be claimed under the fifty-move rule. + 5) Halfmove clock. This is the number of halfmoves since the last pawn advance + or capture. This is used to determine if a draw can be claimed under the + fifty-move rule. - 6) Fullmove number: The number of the full move. It starts at 1, and is incremented after Black's move. + 6) Fullmove number. The number of the full move. It starts at 1, and is + incremented after Black's move. */ char col, row, token; @@ -263,20 +269,20 @@ const string Position::to_fen() const { { sq = make_square(file, rank); - if (!square_is_empty(sq)) + if (square_is_empty(sq)) + emptyCnt++; + else { - if (emptyCnt) + if (emptyCnt > 0) { fen << emptyCnt; emptyCnt = 0; } fen << PieceToChar[piece_on(sq)]; } - else - emptyCnt++; } - if (emptyCnt) + if (emptyCnt > 0) fen << emptyCnt; if (rank > RANK_1) @@ -285,24 +291,23 @@ const string Position::to_fen() const { fen << (sideToMove == WHITE ? " w " : " b "); - if (st->castleRights != CASTLES_NONE) - { - if (can_castle(WHITE_OO)) - fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OO))))) : 'K'); + if (can_castle(WHITE_OO)) + fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OO))))) : 'K'); + + if (can_castle(WHITE_OOO)) + fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OOO))))) : 'Q'); - if (can_castle(WHITE_OOO)) - fen << (chess960 ? char(toupper(file_to_char(file_of(castle_rook_square(WHITE_OOO))))) : 'Q'); + if (can_castle(BLACK_OO)) + fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OO))) : 'k'); - if (can_castle(BLACK_OO)) - fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OO))) : 'k'); + if (can_castle(BLACK_OOO)) + fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OOO))) : 'q'); - if (can_castle(BLACK_OOO)) - fen << (chess960 ? file_to_char(file_of(castle_rook_square(BLACK_OOO))) : 'q'); - } else + if (st->castleRights == CASTLES_NONE) fen << '-'; - fen << (ep_square() == SQ_NONE ? " -" : " " + square_to_string(ep_square())) - << " " << st->rule50 << " " << 1 + (startPosPly - int(sideToMove == BLACK)) / 2; + fen << (ep_square() == SQ_NONE ? " - " : " " + square_to_string(ep_square()) + " ") + << st->rule50 << " " << 1 + (startPosPly - int(sideToMove == BLACK)) / 2; return fen.str(); } @@ -318,8 +323,7 @@ void Position::print(Move move) const { if (move) { Position p(*this, thread()); - string dd = (sideToMove == BLACK ? ".." : ""); - cout << "\nMove is: " << dd << move_to_san(p, move); + cout << "\nMove is: " << (sideToMove == BLACK ? ".." : "") << move_to_san(p, move); } for (Rank rank = RANK_8; rank >= RANK_1; rank--) @@ -329,11 +333,11 @@ void Position::print(Move move) const { { Square sq = make_square(file, rank); Piece piece = piece_on(sq); + char c = (color_of(piece) == BLACK ? '=' : ' '); if (piece == PIECE_NONE && color_of(sq) == DARK) piece = PIECE_NONE_DARK_SQ; - char c = (color_of(piece_on(sq)) == BLACK ? '=' : ' '); cout << c << PieceToChar[piece] << c << '|'; } } @@ -345,12 +349,11 @@ void Position::print(Move move) const { /// king) pieces for the given color. Or, when template parameter FindPinned is /// false, the function return the pieces of the given color candidate for a /// discovery check against the enemy king. - template Bitboard Position::hidden_checkers() const { // Pinned pieces protect our king, dicovery checks attack the enemy king - Bitboard b, result = EmptyBoardBB; + Bitboard b, result = 0; Bitboard pinners = pieces(FindPinned ? flip(sideToMove) : sideToMove); Square ksq = king_square(FindPinned ? sideToMove : flip(sideToMove)); @@ -369,26 +372,12 @@ Bitboard Position::hidden_checkers() const { return result; } +// Explicit template instantiations +template Bitboard Position::hidden_checkers() const; +template Bitboard Position::hidden_checkers() const; -/// Position:pinned_pieces() returns a bitboard of all pinned (against the -/// king) pieces for the side to move. - -Bitboard Position::pinned_pieces() const { - - return hidden_checkers(); -} - - -/// Position:discovered_check_candidates() returns a bitboard containing all -/// pieces for the side to move which are candidates for giving a discovered -/// check. - -Bitboard Position::discovered_check_candidates() const { - - return hidden_checkers(); -} -/// Position::attackers_to() computes a bitboard of all pieces which attacks a +/// Position::attackers_to() computes a bitboard of all pieces which attack a /// given square. Slider attacks use occ bitboard as occupancy. Bitboard Position::attackers_to(Square s, Bitboard occ) const { @@ -401,6 +390,7 @@ Bitboard Position::attackers_to(Square s, Bitboard occ) const { | (attacks_from(s) & pieces(KING)); } + /// Position::attacks_from() computes a bitboard of all attacks of a given piece /// put in a given square. Slider attacks use occ bitboard as occupancy. @@ -427,22 +417,25 @@ bool Position::move_attacks_square(Move m, Square s) const { assert(square_is_ok(s)); Bitboard occ, xray; - Square f = move_from(m), t = move_to(m); + Square from = move_from(m); + Square to = move_to(m); + Piece piece = piece_on(from); - assert(!square_is_empty(f)); + assert(!square_is_empty(from)); - if (bit_is_set(attacks_from(piece_on(f), t), s)) + // Update occupancy as if the piece is moving + occ = occupied_squares(); + do_move_bb(&occ, make_move_bb(from, to)); + + // The piece moved in 'to' attacks the square 's' ? + if (bit_is_set(attacks_from(piece, to, occ), s)) return true; - // Move the piece and scan for X-ray attacks behind it - occ = occupied_squares(); - do_move_bb(&occ, make_move_bb(f, t)); - xray = ( (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN)) - |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))) - & pieces(color_of(piece_on(f))); + // Scan for possible X-ray attackers behind the moved piece + xray = (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN, color_of(piece))) + |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN, color_of(piece))); - // If we have attacks we need to verify that are caused by our move - // and are not already existent ones. + // Verify attackers are triggered by our move and not already existing return xray && (xray ^ (xray & attacks_from(s))); } @@ -499,8 +492,8 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const { /// Position::move_is_legal() takes a random move and tests whether the move -/// is legal. This version is not very fast and should be used only -/// in non time-critical paths. +/// is legal. This version is not very fast and should be used only in non +/// time-critical paths. bool Position::move_is_legal(const Move m) const {