Key psq[PIECE_NB][SQUARE_NB];
Key enpassant[FILE_NB];
Key castling[CASTLING_RIGHT_NB];
-Key side;
+Key side, noPawns;
}
namespace {
for (int cr = NO_CASTLING; cr <= ANY_CASTLING; ++cr)
Zobrist::castling[cr] = rng.rand<Key>();
- Zobrist::side = rng.rand<Key>();
+ Zobrist::side = rng.rand<Key>();
+ Zobrist::noPawns = rng.rand<Key>();
// Prepare the cuckoo tables
std::memset(cuckoo, 0, sizeof(cuckoo));
void Position::set_state() const {
st->key = st->materialKey = 0;
+ st->pawnKey = Zobrist::noPawns;
st->nonPawnMaterial[WHITE] = st->nonPawnMaterial[BLACK] = VALUE_ZERO;
st->checkersBB = attackers_to(square<KING>(sideToMove)) & pieces(~sideToMove);
Piece pc = piece_on(s);
st->key ^= Zobrist::psq[pc][s];
- if (type_of(pc) != KING && type_of(pc) != PAWN)
+ if (type_of(pc) == PAWN)
+ st->pawnKey ^= Zobrist::psq[pc][s];
+
+ else if (type_of(pc) != KING)
st->nonPawnMaterial[color_of(pc)] += PieceValue[pc];
}
}
-// Overload to initialize the position object with
-// the given endgame code string like "KBPKN". It is mainly a helper to
-// get the material key out of an endgame code.
+// Overload to initialize the position object with the given endgame code string
+// like "KBPKN". It's mainly a helper to get the material key out of an endgame code.
Position& Position::set(const string& code, Color c, StateInfo* si) {
assert(code[0] == 'K');
}
-// Computes a bitboard of all pieces which attack a
-// given square. Slider attacks use the occupied bitboard to indicate occupancy.
+// Computes a bitboard of all pieces which attack a given square.
+// Slider attacks use the occupied bitboard to indicate occupancy.
Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
return (pawn_attacks_bb(BLACK, s) & pieces(WHITE, PAWN))
// Handle the special case of a pawn move
if (type_of(pc) == PAWN)
{
- // We have already handled promotion moves, so destination
- // cannot be on the 8th/1st rank.
+ // We have already handled promotion moves, so destination cannot be on the 8th/1st rank
if ((Rank8BB | Rank1BB) & to)
return false;
case PROMOTION :
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
- // need to handle is the unusual case of a discovered check through
- // the captured pawn.
+ // En passant capture with check? We have already handled the case of direct
+ // checks and ordinary discovered check, so the only case we need to handle
+ // is the unusual case of a discovered check through the captured pawn.
case EN_PASSANT : {
Square capsq = make_square(file_of(to), rank_of(from));
Bitboard b = (pieces() ^ from ^ capsq) | to;
assert(piece_on(to) == NO_PIECE);
assert(piece_on(capsq) == make_piece(them, PAWN));
}
+
+ st->pawnKey ^= Zobrist::psq[captured][capsq];
}
else
st->nonPawnMaterial[them] -= PieceValue[captured];
// Update hash keys
k ^= Zobrist::psq[pc][to] ^ Zobrist::psq[promotion][to];
+ st->pawnKey ^= Zobrist::psq[pc][to];
st->materialKey ^=
Zobrist::psq[promotion][pieceCount[promotion] - 1] ^ Zobrist::psq[pc][pieceCount[pc]];
st->nonPawnMaterial[us] += PieceValue[promotion];
}
+ // Update pawn hash key
+ st->pawnKey ^= Zobrist::psq[pc][from] ^ Zobrist::psq[pc][to];
+
// Reset rule 50 draw counter
st->rule50 = 0;
}
}
-// Helper used to do/undo a castling move. This
-// is a bit tricky in Chess960 where from/to squares can overlap.
+// Helper used to do/undo a castling move. This is a bit
+// tricky in Chess960 where from/to squares can overlap.
template<bool Do>
void Position::do_castling(Color us, Square from, Square& to, Square& rfrom, Square& rto) {
}
-// Performs some consistency checks for the
-// position object and raise an assert if something wrong is detected.
+// Performs some consistency checks for the position object
+// and raise an assert if something wrong is detected.
// This is meant to be helpful when debugging.
bool Position::pos_is_ok() const {