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
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.
Bitboard b = stmAttackers & bb[Pt];
if (!b)
- return min_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
+ return min_attacker<Pt + 1>(bb, to, stmAttackers, occupied, attackers);
occupied ^= b & ~(b - 1);
/// 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";
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 << ")";
}
/// 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.
&& 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
return false;
case PROMOTION:
- return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & square<KING>(~sideToMove);
+ return attacks_bb(promotion_type(m), to, pieces() ^ from) & square<KING>(~sideToMove);
// En passant capture with check? We have already handled the case
// of direct checks and ordinary discovered check, so the only case we
// 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;
/// 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<LEGAL>(*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;
}