From fa1e3427bdf7f6347326015a381014564e8fb337 Mon Sep 17 00:00:00 2001 From: Marco Costalba Date: Sat, 24 Jun 2017 12:36:07 +0200 Subject: [PATCH] Simplify pos_is_ok() Now we don't need anymore the tricky pointer to show the failed test. Added some few tests too. Also small rename in see_ge() while there. No functional change Closes #1151 --- src/position.cpp | 129 ++++++++++++++++++++++------------------------- src/position.h | 4 +- 2 files changed, 63 insertions(+), 70 deletions(-) diff --git a/src/position.cpp b/src/position.cpp index 01f51ed0..67cf2a02 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -381,8 +381,7 @@ void Position::set_state(StateInfo* si) const { /// Position::set() is an overload to initialize the position object with /// the given endgame code string like "KBPKN". It is mainly a helper to -/// get the material key out of an endgame code. Position is not playable, -/// indeed is even not guaranteed to be legal. +/// get the material key out of an endgame code. Position& Position::set(const string& code, Color c, StateInfo* si) { @@ -394,8 +393,8 @@ Position& Position::set(const string& code, Color c, StateInfo* si) { std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower); - string fenStr = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/" - + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10"; + string fenStr = "8/" + sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/" + + sides[1] + char(8 - sides[1].length() + '0') + "/8 w - - 0 10"; return set(fenStr, false, si, nullptr); } @@ -1000,10 +999,10 @@ Key Position::key_after(Move m) const { /// Position::see_ge (Static Exchange Evaluation Greater or Equal) tests if the -/// SEE value of move is greater or equal to the given value. We'll use an +/// SEE value of move is greater or equal to the given threshold. We'll use an /// algorithm similar to alpha-beta pruning with a null window. -bool Position::see_ge(Move m, Value v) const { +bool Position::see_ge(Move m, Value threshold) const { assert(is_ok(m)); @@ -1011,7 +1010,7 @@ bool Position::see_ge(Move m, Value v) const { // handled correctly. Simply assume the SEE value is VALUE_ZERO that is always // correct unless in the rare case the rook ends up under attack. if (type_of(m) == CASTLING) - return VALUE_ZERO >= v; + return VALUE_ZERO >= threshold; Square from = from_sq(m), to = to_sq(m); PieceType nextVictim = type_of(piece_on(from)); @@ -1030,7 +1029,7 @@ bool Position::see_ge(Move m, Value v) const { occupied = 0; } - if (balance < v) + if (balance < threshold) return false; if (nextVictim == KING) @@ -1038,7 +1037,7 @@ bool Position::see_ge(Move m, Value v) const { balance -= PieceValue[MG][nextVictim]; - if (balance >= v) + if (balance >= threshold) return true; bool relativeStm = true; // True if the opponent is to move @@ -1071,7 +1070,7 @@ bool Position::see_ge(Move m, Value v) const { relativeStm = !relativeStm; - if (relativeStm == (balance >= v)) + if (relativeStm == (balance >= threshold)) return relativeStm; stm = ~stm; @@ -1146,78 +1145,72 @@ void Position::flip() { } -/// Position::pos_is_ok() performs some consistency checks for the position object. +/// Position::pos_is_ok() performs some consistency checks for the +/// position object and raises an asserts if something wrong is detected. /// This is meant to be helpful when debugging. -bool Position::pos_is_ok(int* failedStep) const { +bool Position::pos_is_ok() const { const bool Fast = true; // Quick (default) or full check? - enum { Default, King, Bitboards, State, Lists, Castling }; + if ( (sideToMove != WHITE && sideToMove != BLACK) + || piece_on(square(WHITE)) != W_KING + || piece_on(square(BLACK)) != B_KING + || ( ep_square() != SQ_NONE + && relative_rank(sideToMove, ep_square()) != RANK_6)) + assert(0 && "pos_is_ok: Default"); - for (int step = Default; step <= (Fast ? Default : Castling); step++) - { - if (failedStep) - *failedStep = step; - - if (step == Default) - if ( (sideToMove != WHITE && sideToMove != BLACK) - || piece_on(square(WHITE)) != W_KING - || piece_on(square(BLACK)) != B_KING - || ( ep_square() != SQ_NONE - && relative_rank(sideToMove, ep_square()) != RANK_6)) - return false; + if (Fast) + return true; - if (step == King) - if ( std::count(board, board + SQUARE_NB, W_KING) != 1 - || std::count(board, board + SQUARE_NB, B_KING) != 1 - || attackers_to(square(~sideToMove)) & pieces(sideToMove)) - return false; + if ( pieceCount[W_KING] != 1 + || pieceCount[B_KING] != 1 + || attackers_to(square(~sideToMove)) & pieces(sideToMove)) + assert(0 && "pos_is_ok: Kings"); - if (step == Bitboards) - { - if ( (pieces(WHITE) & pieces(BLACK)) - ||(pieces(WHITE) | pieces(BLACK)) != pieces()) - return false; + if ( (pieces(PAWN) & (Rank1BB | Rank8BB)) + || pieceCount[W_PAWN] > 8 + || pieceCount[B_PAWN] > 8) + assert(0 && "pos_is_ok: Pawns"); - for (PieceType p1 = PAWN; p1 <= KING; ++p1) - for (PieceType p2 = PAWN; p2 <= KING; ++p2) - if (p1 != p2 && (pieces(p1) & pieces(p2))) - return false; - } + if ( (pieces(WHITE) & pieces(BLACK)) + || (pieces(WHITE) | pieces(BLACK)) != pieces() + || popcount(pieces(WHITE)) > 16 + || popcount(pieces(BLACK)) > 16) + assert(0 && "pos_is_ok: Bitboards"); - if (step == State) - { - StateInfo si = *st; - set_state(&si); - if (std::memcmp(&si, st, sizeof(StateInfo))) - return false; - } + for (PieceType p1 = PAWN; p1 <= KING; ++p1) + for (PieceType p2 = PAWN; p2 <= KING; ++p2) + if (p1 != p2 && (pieces(p1) & pieces(p2))) + assert(0 && "pos_is_ok: Bitboards"); - if (step == Lists) - for (Piece pc : Pieces) - { - if (pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc)))) - return false; + StateInfo si = *st; + set_state(&si); + if (std::memcmp(&si, st, sizeof(StateInfo))) + assert(0 && "pos_is_ok: State"); - for (int i = 0; i < pieceCount[pc]; ++i) - if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i) - return false; - } + for (Piece pc : Pieces) + { + if ( pieceCount[pc] != popcount(pieces(color_of(pc), type_of(pc))) + || pieceCount[pc] != std::count(board, board + SQUARE_NB, pc)) + assert(0 && "pos_is_ok: Pieces"); - if (step == Castling) - for (Color c = WHITE; c <= BLACK; ++c) - for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) - { - if (!can_castle(c | s)) - continue; - - if ( piece_on(castlingRookSquare[c | s]) != make_piece(c, ROOK) - || castlingRightsMask[castlingRookSquare[c | s]] != (c | s) - ||(castlingRightsMask[square(c)] & (c | s)) != (c | s)) - return false; - } + for (int i = 0; i < pieceCount[pc]; ++i) + if (board[pieceList[pc][i]] != pc || index[pieceList[pc][i]] != i) + assert(0 && "pos_is_ok: Index"); } + for (Color c = WHITE; c <= BLACK; ++c) + for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1)) + { + if (!can_castle(c | s)) + continue; + + if ( piece_on(castlingRookSquare[c | s]) != make_piece(c, ROOK) + || castlingRightsMask[castlingRookSquare[c | s]] != (c | s) + || (castlingRightsMask[square(c)] & (c | s)) != (c | s)) + assert(0 && "pos_is_ok: Castling"); + } + return true; } diff --git a/src/position.h b/src/position.h index 25e57512..8342df3c 100644 --- a/src/position.h +++ b/src/position.h @@ -138,7 +138,7 @@ public: void increment_tbHits(); // Static Exchange Evaluation - bool see_ge(Move m, Value value = VALUE_ZERO) const; + bool see_ge(Move m, Value threshold = VALUE_ZERO) const; // Accessing hash keys Key key() const; @@ -161,7 +161,7 @@ public: Value non_pawn_material() const; // Position consistency check, for debugging - bool pos_is_ok(int* failedStep = nullptr) const; + bool pos_is_ok() const; void flip(); private: -- 2.39.2