+template<int Pt>
+PieceType min_attacker(const Bitboard* byTypeBB, Square to, Bitboard stmAttackers,
+ Bitboard& occupied, Bitboard& attackers) {
+
+ Bitboard b = stmAttackers & byTypeBB[Pt];
+ if (!b)
+ return min_attacker<Pt + 1>(byTypeBB, to, stmAttackers, occupied, attackers);
+
+ occupied ^= lsb(b); // Remove the attacker from occupied
+
+ // Add any X-ray attack behind the just removed piece. For instance with
+ // rooks in a8 and a7 attacking a1, after removing a7 we add rook in a8.
+ // Note that new added attackers can be of any color.
+ if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
+ attackers |= attacks_bb<BISHOP>(to, occupied) & (byTypeBB[BISHOP] | byTypeBB[QUEEN]);
+
+ if (Pt == ROOK || Pt == QUEEN)
+ attackers |= attacks_bb<ROOK>(to, occupied) & (byTypeBB[ROOK] | byTypeBB[QUEEN]);
+
+ // X-ray may add already processed pieces because byTypeBB[] is constant: in
+ // the rook example, now attackers contains _again_ rook in a7, so remove it.
+ attackers &= occupied;
+ return (PieceType)Pt;
+}
+
+template<>
+PieceType min_attacker<KING>(const Bitboard*, Square, Bitboard, Bitboard&, Bitboard&) {
+ return KING; // No need to update bitboards: it is the last cycle
+}
+
+} // namespace
+
+
+/// operator<<(Position) returns an ASCII representation of the position
+
+std::ostream& operator<<(std::ostream& os, const Position& pos) {
+
+ os << "\n +---+---+---+---+---+---+---+---+\n";
+
+ for (Rank r = RANK_8; r >= RANK_1; --r)
+ {
+ for (File f = FILE_A; f <= FILE_H; ++f)
+ os << " | " << PieceToChar[pos.piece_on(make_square(f, r))];
+
+ os << " |\n +---+---+---+---+---+---+---+---+\n";
+ }
+
+ os << "\nFen: " << pos.fen() << "\nKey: " << std::hex << std::uppercase
+ << std::setfill('0') << std::setw(16) << pos.key()
+ << std::setfill(' ') << std::dec << "\nCheckers: ";
+
+ for (Bitboard b = pos.checkers(); b; )
+ os << UCI::square(pop_lsb(&b)) << " ";
+
+ 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(p, &s1);
+ int dtz = Tablebases::probe_dtz(p, &s2);
+ os << "\nTablebases WDL: " << std::setw(4) << wdl << " (" << s1 << ")"
+ << "\nTablebases DTZ: " << std::setw(4) << dtz << " (" << s2 << ")";
+ }
+
+ return os;