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
void Position::set_check_info(StateInfo* si) const {
- si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinnersForKing[WHITE]);
- si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinnersForKing[BLACK]);
+ si->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square<KING>(WHITE), si->pinners[BLACK]);
+ si->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square<KING>(BLACK), si->pinners[WHITE]);
Square ksq = square<KING>(~sideToMove);
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
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;
}
// 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<KING>(us));
}
return true;
// Is there a discovered check?
- if ( (discovered_check_candidates() & from)
+ if ( (st->blockersForKing[~sideToMove] & from)
&& !aligned(from, to, square<KING>(~sideToMove)))
return true;
// 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
}
+// 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.
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<KING>(WHITE)) != W_KING