X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fposition.cpp;h=4c8145c490f508d68375298a0180243bd1646bd1;hp=7c5ffdc5f6adcc905a2a98adb2e5b5cd60e1e4bc;hb=6d89d0b64a99003576d3e0ed616b43333c9eca01;hpb=9eccba776198c210563666787a9b5fe44b386fdc diff --git a/src/position.cpp b/src/position.cpp index 7c5ffdc5..4c8145c4 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -2,7 +2,7 @@ Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad - Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad + Copyright (C) 2015-2017 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,6 +52,9 @@ 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 }; + // 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 // from the bitboards and scan for new X-ray attacks behind it. @@ -62,7 +65,7 @@ PieceType min_attacker(const Bitboard* bb, Square to, Bitboard stmAttackers, Bitboard b = stmAttackers & bb[Pt]; if (!b) - return min_attacker(bb, to, stmAttackers, occupied, attackers); + return min_attacker(bb, to, stmAttackers, occupied, attackers); occupied ^= b & ~(b - 1); @@ -86,7 +89,7 @@ PieceType min_attacker(const Bitboard*, Square, Bitboard, Bitboard&, Bitbo /// operator<<(Position) returns an ASCII representation of the position -std::ostream& operator<<(std::ostream& os, Position& pos) { +std::ostream& operator<<(std::ostream& os, const Position& pos) { os << "\n +---+---+---+---+---+---+---+---+\n"; @@ -108,9 +111,12 @@ std::ostream& operator<<(std::ostream& os, Position& pos) { if ( int(Tablebases::MaxCardinality) >= popcount(pos.pieces()) && !pos.can_castle(ANY_CASTLING)) { + StateInfo st; + Position p; + p.set(pos.fen(), pos.is_chess960(), &st, pos.this_thread()); Tablebases::ProbeState s1, s2; - Tablebases::WDLScore wdl = Tablebases::probe_wdl(pos, &s1); - int dtz = Tablebases::probe_dtz(pos, &s2); + Tablebases::WDLScore wdl = Tablebases::probe_wdl(p, &s1); + int dtz = Tablebases::probe_dtz(p, &s2); os << "\nTablebases WDL: " << std::setw(4) << wdl << " (" << s1 << ")" << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")"; } @@ -374,7 +380,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 manily an helper to +/// 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. @@ -592,7 +598,7 @@ bool Position::pseudo_legal(const Move m) const { && empty(to - pawn_push(us)))) return false; } - else if (!(attacks_from(pc, from) & to)) + else if (!(attacks_from(type_of(pc), from) & to)) return false; // Evasions generator already takes care to avoid some kind of illegal moves @@ -645,7 +651,7 @@ bool Position::gives_check(Move m) const { return false; case PROMOTION: - return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & square(~sideToMove); + return attacks_bb(promotion_type(m), to, pieces() ^ from) & square(~sideToMove); // En passant capture with check? We have already handled the case // of direct checks and ordinary discovered check, so the only case we @@ -824,7 +830,7 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { // Update pawn hash key and prefetch access to pawnsTable st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to]; - prefetch(thisThread->pawnsTable[st->pawnKey]); + prefetch2(thisThread->pawnsTable[st->pawnKey]); // Reset rule 50 draw counter st->rule50 = 0; @@ -1076,25 +1082,30 @@ bool Position::see_ge(Move m, Value v) const { /// Position::is_draw() tests whether the position is drawn by 50-move rule /// or by repetition. It does not detect stalemates. -bool Position::is_draw() const { +bool Position::is_draw(int ply) const { if (st->rule50 > 99 && (!checkers() || MoveList(*this).size())) return true; - int e = std::min(st->rule50, st->pliesFromNull); + int end = std::min(st->rule50, st->pliesFromNull); - if (e < 4) + if (end < 4) return false; StateInfo* stp = st->previous->previous; + int cnt = 0; - do { + for (int i = 4; i <= end; i += 2) + { stp = stp->previous->previous; - if (stp->key == st->key) - return true; // Draw at first repetition - - } while ((e -= 2) >= 4); + // At root position ply is 1, so return a draw score if a position + // repeats once earlier but strictly after the root, or repeats twice + // before or at the root. + if ( stp->key == st->key + && ++cnt + (ply - 1 > i) == 2) + return true; + } return false; }