X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=2266f2a573dfa05e313b0913d903578d1e4ebb2d;hp=1e0f46b7dc1786d2c5982d9aa5182f778fdd5947;hb=7a1ff6d8ff39bb9e6844d24467899d47e942486f;hpb=408e6ee9b646ed8ce230c75a3cc021a5a4979c72 diff --git a/src/position.cpp b/src/position.cpp index 1e0f46b7..2266f2a5 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -17,12 +17,12 @@ along with this program. If not, see . */ +#include #include #include #include #include #include -#include #include "bitcount.h" #include "movegen.h" @@ -120,12 +120,12 @@ void Position::init() { RKISS rk; - for (Color c = WHITE; c <= BLACK; c++) - for (PieceType pt = PAWN; pt <= KING; pt++) - for (Square s = SQ_A1; s <= SQ_H8; s++) + for (Color c = WHITE; c <= BLACK; ++c) + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (Square s = SQ_A1; s <= SQ_H8; ++s) Zobrist::psq[c][pt][s] = rk.rand(); - for (File f = FILE_A; f <= FILE_H; f++) + for (File f = FILE_A; f <= FILE_H; ++f) Zobrist::enpassant[f] = rk.rand(); for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++) @@ -141,14 +141,14 @@ void Position::init() { Zobrist::side = rk.rand(); Zobrist::exclusion = rk.rand(); - for (PieceType pt = PAWN; pt <= KING; pt++) + for (PieceType pt = PAWN; pt <= KING; ++pt) { PieceValue[MG][make_piece(BLACK, pt)] = PieceValue[MG][pt]; PieceValue[EG][make_piece(BLACK, pt)] = PieceValue[EG][pt]; Score v = make_score(PieceValue[MG][pt], PieceValue[EG][pt]); - for (Square s = SQ_A1; s <= SQ_H8; s++) + for (Square s = SQ_A1; s <= SQ_H8; ++s) { psq[WHITE][pt][ s] = (v + PSQT[pt][s]); psq[BLACK][pt][~s] = -(v + PSQT[pt][s]); @@ -233,7 +233,7 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { else if ((p = PieceToChar.find(token)) != string::npos) { put_piece(sq, color_of(Piece(p)), type_of(Piece(p))); - sq++; + ++sq; } } @@ -255,10 +255,10 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { token = char(toupper(token)); if (token == 'K') - for (rsq = relative_square(c, SQ_H1); type_of(piece_on(rsq)) != ROOK; rsq--) {} + for (rsq = relative_square(c, SQ_H1); type_of(piece_on(rsq)) != ROOK; --rsq) {} else if (token == 'Q') - for (rsq = relative_square(c, SQ_A1); type_of(piece_on(rsq)) != ROOK; rsq++) {} + for (rsq = relative_square(c, SQ_A1); type_of(piece_on(rsq)) != ROOK; ++rsq) {} else if (token >= 'A' && token <= 'H') rsq = File(token - 'A') | relative_rank(c, RANK_1); @@ -317,11 +317,11 @@ void Position::set_castle_right(Color c, Square rfrom) { 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++) + for (Square s = std::min(rfrom, rto); s <= std::max(rfrom, rto); ++s) if (s != kfrom && s != rfrom) castlePath[c][cs] |= s; - for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); s++) + for (Square s = std::min(kfrom, kto); s <= std::max(kfrom, kto); ++s) if (s != kfrom && s != rfrom) castlePath[c][cs] |= s; } @@ -334,9 +334,9 @@ const string Position::fen() const { std::ostringstream ss; - for (Rank rank = RANK_8; rank >= RANK_1; rank--) + for (Rank rank = RANK_8; rank >= RANK_1; --rank) { - for (File file = FILE_A; file <= FILE_H; file++) + for (File file = FILE_A; file <= FILE_H; ++file) { Square sq = file | rank; @@ -344,7 +344,7 @@ const string Position::fen() const { { int emptyCnt = 1; - for ( ; file < FILE_H && is_empty(sq++); file++) + for ( ; file < FILE_H && is_empty(++sq); ++file) emptyCnt++; ss << emptyCnt; @@ -989,25 +989,12 @@ void Position::undo_move(Move m) { void Position::do_castle(Square kfrom, Square kto, Square rfrom, Square rto) { - Color us = sideToMove; - 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; - - // Could be from == to, so first set NO_PIECE then KING and ROOK - board[kfrom] = board[rfrom] = NO_PIECE; - board[kto] = make_piece(us, KING); - board[rto] = make_piece(us, ROOK); - - // Could be kfrom == rto, so use a 'tmp' variable - int tmp = index[kfrom]; - index[rto] = index[rfrom]; - index[kto] = tmp; - pieceList[us][KING][index[kto]] = kto; - pieceList[us][ROOK][index[rto]] = rto; + // Remove both pieces first since squares could overlap in Chess960 + remove_piece(kfrom, sideToMove, KING); + remove_piece(rfrom, sideToMove, ROOK); + board[kfrom] = board[rfrom] = NO_PIECE; // Since remove_piece doesn't do it for us + put_piece(kto, sideToMove, KING); + put_piece(rto, sideToMove, ROOK); } @@ -1162,9 +1149,9 @@ void Position::clear() { startState.epSquare = SQ_NONE; st = &startState; - for (int i = 0; i < 8; i++) + for (int i = 0; i < PIECE_TYPE_NB; i++) for (int j = 0; j < 16; j++) - pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE; + pieceList[WHITE][i][j] = pieceList[BLACK][i][j] = SQ_NONE; } @@ -1223,9 +1210,9 @@ Key Position::compute_material_key() const { Key k = 0; - for (Color c = WHITE; c <= BLACK; c++) - for (PieceType pt = PAWN; pt <= QUEEN; pt++) - for (int cnt = 0; cnt < pieceCount[c][pt]; cnt++) + for (Color c = WHITE; c <= BLACK; ++c) + for (PieceType pt = PAWN; pt <= QUEEN; ++pt) + for (int cnt = 0; cnt < pieceCount[c][pt]; ++cnt) k ^= Zobrist::psq[c][pt][cnt]; return k; @@ -1236,6 +1223,7 @@ Key Position::compute_material_key() const { /// game and the endgame. These functions are used to initialize the incremental /// scores when a new position is set up, and to verify that the scores are correctly /// updated by do_move and undo_move when the program is running in debug mode. + Score Position::compute_psq_score() const { Score score = SCORE_ZERO; @@ -1260,7 +1248,7 @@ Value Position::compute_non_pawn_material(Color c) const { Value value = VALUE_ZERO; - for (PieceType pt = KNIGHT; pt <= QUEEN; pt++) + for (PieceType pt = KNIGHT; pt <= QUEEN; ++pt) value += pieceCount[c][pt] * PieceValue[MG][pt]; return value; @@ -1281,7 +1269,6 @@ bool Position::is_draw() const { if (st->rule50 > 99 && (!checkers() || MoveList(*this).size())) return true; - // Draw by repetition? int i = 4, e = std::min(st->rule50, st->pliesFromNull); if (i <= e) @@ -1292,7 +1279,7 @@ bool Position::is_draw() const { stp = stp->previous->previous; if (stp->key == st->key) - return true; + return true; // Draw after first repetition i += 2; @@ -1306,45 +1293,36 @@ bool Position::is_draw() const { /// Position::flip() flips position with the white and black sides reversed. This /// is only useful for debugging especially for finding evaluation symmetry bugs. +static char toggle_case(char c) { + return char(islower(c) ? toupper(c) : tolower(c)); +} + void Position::flip() { - const Position pos(*this); + string f, token; + std::stringstream ss(fen()); - clear(); + for (Rank rank = RANK_8; rank >= RANK_1; --rank) // Piece placement + { + std::getline(ss, token, rank > RANK_1 ? '/' : ' '); + f.insert(0, token + (f.empty() ? " " : "/")); + } - sideToMove = ~pos.side_to_move(); - thisThread = pos.this_thread(); - nodes = pos.nodes_searched(); - chess960 = pos.is_chess960(); - gamePly = pos.game_ply(); + ss >> token; // Active color + f += (token == "w" ? "B " : "W "); // Will be lowercased later - for (Square s = SQ_A1; s <= SQ_H8; s++) - if (!pos.is_empty(s)) - { - Piece p = Piece(pos.piece_on(s) ^ 8); - put_piece(~s, color_of(p), type_of(p)); - } + ss >> token; // Castling availability + f += token + " "; - if (pos.can_castle(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, QUEEN_SIDE)); - if (pos.can_castle(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, QUEEN_SIDE)); + std::transform(f.begin(), f.end(), f.begin(), toggle_case); - if (pos.st->epSquare != SQ_NONE) - st->epSquare = ~pos.st->epSquare; + ss >> token; // En passant square + f += (token == "-" ? token : token.replace(1, 1, token[1] == '3' ? "6" : "3")); - st->checkersBB = attackers_to(king_square(sideToMove)) & pieces(~sideToMove); + std::getline(ss, token); // Half and full moves + f += token; - st->key = compute_key(); - st->pawnKey = compute_pawn_key(); - st->materialKey = compute_material_key(); - st->psq = compute_psq_score(); - st->npMaterial[WHITE] = compute_non_pawn_material(WHITE); - st->npMaterial[BLACK] = compute_non_pawn_material(BLACK); + set(f, is_chess960(), this_thread()); assert(pos_is_ok()); } @@ -1388,7 +1366,7 @@ bool Position::pos_is_ok(int* failedStep) const { { int kingCount[COLOR_NB] = {}; - for (Square s = SQ_A1; s <= SQ_H8; s++) + for (Square s = SQ_A1; s <= SQ_H8; ++s) if (type_of(piece_on(s)) == KING) kingCount[color_of(piece_on(s))]++; @@ -1415,8 +1393,8 @@ bool Position::pos_is_ok(int* failedStep) const { return false; // Separate piece type bitboards must have empty intersections - for (PieceType p1 = PAWN; p1 <= KING; p1++) - for (PieceType p2 = PAWN; p2 <= KING; p2++) + for (PieceType p1 = PAWN; p1 <= KING; ++p1) + for (PieceType p2 = PAWN; p2 <= KING; ++p2) if (p1 != p2 && (pieces(p1) & pieces(p2))) return false; } @@ -1442,21 +1420,21 @@ bool Position::pos_is_ok(int* failedStep) const { return false; if ((*step)++, debugPieceCounts) - for (Color c = WHITE; c <= BLACK; c++) - for (PieceType pt = PAWN; pt <= KING; pt++) + for (Color c = WHITE; c <= BLACK; ++c) + for (PieceType pt = PAWN; pt <= KING; ++pt) if (pieceCount[c][pt] != popcount(pieces(c, pt))) return false; if ((*step)++, debugPieceList) - for (Color c = WHITE; c <= BLACK; c++) - for (PieceType pt = PAWN; pt <= KING; pt++) + for (Color c = WHITE; c <= BLACK; ++c) + for (PieceType pt = PAWN; pt <= KING; ++pt) for (int i = 0; i < pieceCount[c][pt]; i++) if ( board[pieceList[c][pt][i]] != make_piece(c, pt) || index[pieceList[c][pt][i]] != i) return false; if ((*step)++, debugCastleSquares) - for (Color c = WHITE; c <= BLACK; c++) + 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);