X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=0be309ee60cac3d0ea78bcec0ad6c38237e7768b;hp=fdae0ae0bf211999f9c2ee69472c4f151af0f8a0;hb=108f0da4d7f993732aa2e854b8f3fa8ca6d3b46c;hpb=a09eee579810fe446e34d0004e5716191310f4e4 diff --git a/src/position.cpp b/src/position.cpp index fdae0ae0..0be309ee 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -52,8 +52,8 @@ namespace { const string PieceToChar(" PNBRQK pnbrqk"); -const Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, - B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; +constexpr Piece Pieces[] = { W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING, + B_PAWN, B_KNIGHT, B_BISHOP, B_ROOK, B_QUEEN, B_KING }; // min_attacker() is a helper function used by see_ge() to locate the least // valuable attacker for the side to move, remove the attacker we just found @@ -322,8 +322,8 @@ void Position::set_castling_right(Color c, Square rfrom) { void Position::set_check_info(StateInfo* si) const { - si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE), si->pinnersForKing[WHITE]); - si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK), si->pinnersForKing[BLACK]); + si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE), si->pinners[BLACK]); + si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK), si->pinners[WHITE]); Square ksq = square(~sideToMove); @@ -464,7 +464,7 @@ const string Position::fen() const { Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners) const { - Bitboard result = 0; + Bitboard blockers = 0; pinners = 0; // Snipers are sliders that attack 's' when a piece is removed @@ -476,14 +476,14 @@ Bitboard Position::slider_blockers(Bitboard sliders, Square s, Bitboard& pinners Square sniperSq = pop_lsb(&snipers); Bitboard b = between_bb(s, sniperSq) & pieces(); - if (!more_than_one(b)) + if (b && !more_than_one(b)) { - result |= b; + blockers |= b; if (b & pieces(color_of(piece_on(s)))) pinners |= sniperSq; } } - return result; + return blockers; } @@ -540,7 +540,7 @@ bool Position::legal(Move m) const { // A non-king move is legal if and only if it is not pinned or it // is moving along the ray towards or away from the king. - return !(pinned_pieces(us) & from) + return !(blockers_for_king(us) & from) || aligned(from, to_sq(m), square(us)); } @@ -632,7 +632,7 @@ bool Position::gives_check(Move m) const { return true; // Is there a discovered check? - if ( (discovered_check_candidates() & from) + if ( (st->blockersForKing[~sideToMove] & from) && !aligned(from, to, square(~sideToMove))) return true; @@ -1037,7 +1037,7 @@ bool Position::see_ge(Move m, Value threshold) const { // Don't allow pinned pieces to attack (except the king) as long as // all pinners are on their original square. - if (!(st->pinnersForKing[stm] & ~occupied)) + if (!(st->pinners[~stm] & ~occupied)) stmAttackers &= ~st->blockersForKing[stm]; // If stm has no more attackers then give up: stm loses @@ -1105,6 +1105,35 @@ bool Position::is_draw(int ply) const { } +// Position::has_repeated() tests whether there has been at least one repetition +// of positions since the last capture or pawn move. + +bool Position::has_repeated() const { + + StateInfo* stc = st; + while (true) + { + int i = 4, e = std::min(stc->rule50, stc->pliesFromNull); + + if (e < i) + return false; + + StateInfo* stp = st->previous->previous; + + do { + stp = stp->previous->previous; + + if (stp->key == stc->key) + return true; + + i += 2; + } while (i <= e); + + stc = stc->previous; + } +} + + /// Position::flip() flips position with the white and black sides reversed. This /// is only useful for debugging e.g. for finding evaluation symmetry bugs. @@ -1146,7 +1175,7 @@ void Position::flip() { bool Position::pos_is_ok() const { - const bool Fast = true; // Quick (default) or full check? + constexpr bool Fast = true; // Quick (default) or full check? if ( (sideToMove != WHITE && sideToMove != BLACK) || piece_on(square(WHITE)) != W_KING