namespace {
-// next_attacker() is an helper function used by see() to locate the least
+// min_attacker() is an helper function used by see() to locate the least
// valuable attacker for the side to move, remove the attacker we just found
-// from the 'occupied' bitboard and scan for new X-ray attacks behind it.
+// from the bitboards and scan for new X-ray attacks behind it.
template<int Pt> FORCE_INLINE
-PieceType next_attacker(const Bitboard* bb, const Square& to, const Bitboard& stmAttackers,
- Bitboard& occupied, Bitboard& attackers) {
+PieceType min_attacker(const Bitboard* bb, const Square& to, const Bitboard& stmAttackers,
+ Bitboard& occupied, Bitboard& attackers) {
- if (stmAttackers & bb[Pt])
+ Bitboard b = stmAttackers & bb[Pt];
+
+ if (b)
{
- Bitboard b = stmAttackers & bb[Pt];
occupied ^= b & ~(b - 1);
if (Pt == PAWN || Pt == BISHOP || Pt == QUEEN)
return (PieceType)Pt;
}
- return next_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
+ return min_attacker<Pt+1>(bb, to, stmAttackers, occupied, attackers);
}
template<> FORCE_INLINE
-PieceType next_attacker<KING>(const Bitboard*, const Square&, const Bitboard&, Bitboard&, Bitboard&) {
+PieceType min_attacker<KING>(const Bitboard*, const Square&, const Bitboard&, Bitboard&, Bitboard&) {
return KING; // No need to update bitboards, it is the last cycle
}
Position& Position::operator=(const Position& pos) {
- memcpy(this, &pos, sizeof(Position));
+ std::memcpy(this, &pos, sizeof(Position));
startState = *st;
st = &startState;
nodes = 0;
}
-/// Position:hidden_checkers<>() returns a bitboard of all pinned (against the
-/// king) pieces for the given color. Or, when template parameter FindPinned is
-/// false, the function return the pieces of the given color candidate for a
-/// discovery check against the enemy king.
-template<bool FindPinned>
-Bitboard Position::hidden_checkers() const {
+/// Position:hidden_checkers() returns a bitboard of all pinned / discovery check
+/// pieces, according to the call parameters. Pinned pieces protect our king,
+/// discovery check pieces attack the enemy king.
+
+Bitboard Position::hidden_checkers(Square ksq, Color c) const {
- // Pinned pieces protect our king, dicovery checks attack the enemy king
- Bitboard b, result = 0;
- Bitboard pinners = pieces(FindPinned ? ~sideToMove : sideToMove);
- Square ksq = king_square(FindPinned ? sideToMove : ~sideToMove);
+ Bitboard b, pinners, result = 0;
- // Pinners are sliders, that give check when candidate pinned is removed
- pinners &= (pieces(ROOK, QUEEN) & PseudoAttacks[ROOK][ksq])
- | (pieces(BISHOP, QUEEN) & PseudoAttacks[BISHOP][ksq]);
+ // Pinners are sliders that give check when pinned piece is removed
+ pinners = ( (pieces( ROOK, QUEEN) & PseudoAttacks[ROOK ][ksq])
+ | (pieces(BISHOP, QUEEN) & PseudoAttacks[BISHOP][ksq])) & pieces(c);
while (pinners)
{
b = between_bb(ksq, pop_lsb(&pinners)) & pieces();
- if (b && !more_than_one(b) && (b & pieces(sideToMove)))
- result |= b;
+ if (!more_than_one(b))
+ result |= b & pieces(sideToMove);
}
return result;
}
-// Explicit template instantiations
-template Bitboard Position::hidden_checkers<true>() const;
-template Bitboard Position::hidden_checkers<false>() const;
-
/// Position::attackers_to() computes a bitboard of all pieces which attack a
/// given square. Slider attacks use occ bitboard as occupancy.
Square rfrom = to; // 'King captures the rook' notation
Square kto = relative_square(us, rfrom > kfrom ? SQ_G1 : SQ_C1);
Square rto = relative_square(us, rfrom > kfrom ? SQ_F1 : SQ_D1);
- Bitboard b = (pieces() ^ kfrom ^ rfrom) | rto | kto;
- return attacks_bb<ROOK>(rto, b) & ksq;
+ return (PseudoAttacks[ROOK][rto] & ksq)
+ && (attacks_bb<ROOK>(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & ksq);
}
default:
assert(false);
// Copy some fields of old state to our new StateInfo object except the ones
// which are going to be recalculated from scratch anyway, then switch our state
// pointer to point to the new, ready to be updated, state.
- memcpy(&newSt, st, StateCopySize64 * sizeof(uint64_t));
+ std::memcpy(&newSt, st, StateCopySize64 * sizeof(uint64_t));
newSt.previous = st;
st = &newSt;
assert(!checkers());
- memcpy(&newSt, st, sizeof(StateInfo)); // Fully copy here
+ std::memcpy(&newSt, st, sizeof(StateInfo)); // Fully copy here
newSt.previous = st;
st = &newSt;
// Early return if SEE cannot be negative because captured piece value
// is not less then capturing one. Note that king moves always return
// here because king midgame value is set to 0.
- if (PieceValue[MG][piece_on(to_sq(m))] >= PieceValue[MG][piece_moved(m)])
+ if (PieceValue[MG][piece_moved(m)] <= PieceValue[MG][piece_on(to_sq(m))])
return 1;
return see(m);
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++;
- // Locate and remove from 'occupied' the next least valuable attacker
- captured = next_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
-
+ // Locate and remove the next least valuable attacker
+ captured = min_attacker<PAWN>(byTypeBB, to, stmAttackers, occupied, attackers);
attackers &= occupied; // Remove the just found attacker
stm = ~stm;
stmAttackers = attackers & pieces(stm);
- if (captured == KING)
- {
- // Stop before processing a king capture
- if (stmAttackers)
- swapList[slIndex++] = QueenValueMg * 16;
-
- break;
- }
-
} while (stmAttackers);
// If we are doing asymmetric SEE evaluation and the same side does the first
void Position::clear() {
- memset(this, 0, sizeof(Position));
+ std::memset(this, 0, sizeof(Position));
startState.epSquare = SQ_NONE;
st = &startState;
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= QUEEN; pt++)
- for (int cnt = 0; cnt < piece_count(c, pt); cnt++)
+ for (int cnt = 0; cnt < pieceCount[c][pt]; cnt++)
k ^= Zobrist::psq[c][pt][cnt];
return k;
Value value = VALUE_ZERO;
for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
- value += piece_count(c, pt) * PieceValue[MG][pt];
+ value += pieceCount[c][pt] * PieceValue[MG][pt];
return value;
}
return false;
if ((*step)++, debugNonPawnMaterial)
- {
if ( st->npMaterial[WHITE] != compute_non_pawn_material(WHITE)
|| st->npMaterial[BLACK] != compute_non_pawn_material(BLACK))
return false;
- }
if ((*step)++, debugPieceCounts)
for (Color c = WHITE; c <= BLACK; c++)
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++)
for (int i = 0; i < pieceCount[c][pt]; i++)
- {
- if (piece_on(piece_list(c, pt)[i]) != make_piece(c, pt))
+ if ( board[pieceList[c][pt][i]] != make_piece(c, pt)
+ || index[pieceList[c][pt][i]] != i)
return false;
- if (index[piece_list(c, pt)[i]] != i)
- return false;
- }
-
if ((*step)++, debugCastleSquares)
for (Color c = WHITE; c <= BLACK; c++)
for (CastlingSide s = KING_SIDE; s <= QUEEN_SIDE; s = CastlingSide(s + 1))
if (!can_castle(cr))
continue;
- if ((castleRightsMask[king_square(c)] & cr) != cr)
- return false;
-
- if ( piece_on(castleRookSquare[c][s]) != make_piece(c, ROOK)
+ if ( (castleRightsMask[king_square(c)] & cr) != cr
+ || piece_on(castleRookSquare[c][s]) != make_piece(c, ROOK)
|| castleRightsMask[castleRookSquare[c][s]] != cr)
return false;
}