Bitboard& occupied, Bitboard& attackers) {
Bitboard b = stmAttackers & bb[Pt];
+ if (!b)
+ return min_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
- if (b)
- {
- occupied ^= b & ~(b - 1);
-
- if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
- attackers |= attacks_bb<BISHOP>(to, occupied) & (bb[BISHOP] | bb[QUEEN]);
+ occupied ^= b & ~(b - 1);
- if (Pt == ROOK || Pt == QUEEN)
- attackers |= attacks_bb<ROOK>(to, occupied) & (bb[ROOK] | bb[QUEEN]);
+ if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
+ attackers |= attacks_bb<BISHOP>(to, occupied) & (bb[BISHOP] | bb[QUEEN]);
- attackers &= occupied; // Remove the just found attacker
+ if (Pt == ROOK || Pt == QUEEN)
+ attackers |= attacks_bb<ROOK>(to, occupied) & (bb[ROOK] | bb[QUEEN]);
- return (PieceType)Pt;
- }
- return min_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
+ attackers &= occupied; // After X-ray that may add already processed pieces
+ return (PieceType)Pt;
}
template<> FORCE_INLINE
string brd = twoRows + twoRows + twoRows + twoRows + dottedLine;
+ for (Bitboard b = pieces(); b; )
+ {
+ Square s = pop_lsb(&b);
+ brd[513 - 68 * rank_of(s) + 4 * file_of(s)] = PieceToChar[piece_on(s)];
+ }
+
std::ostringstream ss;
if (move)
ss << "\nMove: " << (sideToMove == BLACK ? ".." : "")
<< move_to_san(*const_cast<Position*>(this), move);
- for (Square sq = SQ_A1; sq <= SQ_H8; sq++)
- if (piece_on(sq) != NO_PIECE)
- brd[513 - 68*rank_of(sq) + 4*file_of(sq)] = PieceToChar[piece_on(sq)];
-
ss << brd << "\nFen: " << fen() << "\nKey: " << std::hex << std::uppercase
<< std::setfill('0') << std::setw(16) << st->key << "\nCheckers: ";
return false;
// The destination square cannot be occupied by a friendly piece
- if (piece_on(to) != NO_PIECE && color_of(piece_on(to)) == us)
+ if (pieces(us) & to)
return false;
// Handle the special case of a pawn move
return true;
// Discovery check ?
- if (ci.dcCandidates && (ci.dcCandidates & from))
+ if (unlikely(ci.dcCandidates) && (ci.dcCandidates & from))
{
// For pawn and king moves we need to verify also direction
if ( (pt != PAWN && pt != KING)
from = from_sq(m);
to = to_sq(m);
- captured = type_of(piece_on(to));
+ swapList[0] = PieceValue[MG][type_of(piece_on(to))];
+ stm = color_of(piece_on(from));
occupied = pieces() ^ from;
- // Handle en passant moves
+ // Castle moves are implemented as king capturing the rook so cannot be
+ // handled correctly. Simply return 0 that is always the correct value
+ // unless in the rare case the rook ends up under attack.
+ if (type_of(m) == CASTLE)
+ return 0;
+
if (type_of(m) == ENPASSANT)
{
- Square capQq = to - pawn_push(sideToMove);
-
- assert(!captured);
- assert(type_of(piece_on(capQq)) == PAWN);
-
- // Remove the captured pawn
- occupied ^= capQq;
- captured = PAWN;
+ occupied ^= to - pawn_push(stm); // Remove the captured pawn
+ swapList[0] = PieceValue[MG][PAWN];
}
- else if (type_of(m) == CASTLE)
- // Castle moves are implemented as king capturing the rook so cannot be
- // handled correctly. Simply return 0 that is always the correct value
- // unless the rook is ends up under attack.
- return 0;
// Find all attackers to the destination square, with the moving piece
// removed, but possibly an X-ray attacker added behind it.
- attackers = attackers_to(to, occupied);
+ attackers = attackers_to(to, occupied) & occupied;
// If the opponent has no attackers we are finished
- stm = ~color_of(piece_on(from));
+ stm = ~stm;
stmAttackers = attackers & pieces(stm);
if (!stmAttackers)
- return PieceValue[MG][captured];
+ return swapList[0];
// The destination square is defended, which makes things rather more
// difficult to compute. We proceed by building up a "swap list" containing
// destination square, where the sides alternately capture, and always
// capture with the least valuable piece. After each capture, we look for
// new X-ray attacks from behind the capturing piece.
- swapList[0] = PieceValue[MG][captured];
captured = type_of(piece_on(from));
do {
assert(slIndex < 32);
- if (captured == KING) // Stop before processing a king capture
- {
- swapList[slIndex++] = QueenValueMg * 16;
- break;
- }
-
// Add the new entry to the swap list
swapList[slIndex] = -swapList[slIndex - 1] + PieceValue[MG][captured];
slIndex++;
stm = ~stm;
stmAttackers = attackers & pieces(stm);
+ // Stop before processing a king capture
+ if (captured == KING && stmAttackers)
+ {
+ swapList[slIndex++] = QueenValueMg * 16;
+ break;
+ }
+
} while (stmAttackers);
// If we are doing asymmetric SEE evaluation and the same side does the first