using std::endl;
Key Position::zobrist[2][8][64];
-Key Position::zobEp[64];
+Key Position::zobEp[8];
Key Position::zobCastle[16];
Key Position::zobSideToMove;
Key Position::zobExclusion;
return (attacks_from<PAWN>(s, BLACK) & pieces(PAWN, WHITE))
| (attacks_from<PAWN>(s, WHITE) & pieces(PAWN, BLACK))
| (attacks_from<KNIGHT>(s) & pieces(KNIGHT))
- | (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))
+ | (attacks_bb<ROOK>(s, occ) & pieces(ROOK, QUEEN))
+ | (attacks_bb<BISHOP>(s, occ) & pieces(BISHOP, QUEEN))
| (attacks_from<KING>(s) & pieces(KING));
}
switch (type_of(p))
{
- case BISHOP: return bishop_attacks_bb(s, occ);
- case ROOK : return rook_attacks_bb(s, occ);
- case QUEEN : return bishop_attacks_bb(s, occ) | rook_attacks_bb(s, occ);
+ case BISHOP: return attacks_bb<BISHOP>(s, occ);
+ case ROOK : return attacks_bb<ROOK>(s, occ);
+ case QUEEN : return attacks_bb<BISHOP>(s, occ) | attacks_bb<ROOK>(s, occ);
default : return StepAttacksBB[p][s];
}
}
return true;
// Scan for possible X-ray attackers behind the moved piece
- xray = (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN, color_of(piece)))
- |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN, color_of(piece)));
+ xray = (attacks_bb<ROOK>(s, occ) & pieces(ROOK, QUEEN, color_of(piece)))
+ |(attacks_bb<BISHOP>(s, occ) & pieces(BISHOP, QUEEN, color_of(piece)));
// Verify attackers are triggered by our move and not already existing
return xray && (xray ^ (xray & attacks_from<QUEEN>(s)));
b ^= capsq;
b |= to;
- return !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
- && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
+ return !(attacks_bb<ROOK>(ksq, b) & pieces(ROOK, QUEEN, them))
+ && !(attacks_bb<BISHOP>(ksq, b) & pieces(BISHOP, QUEEN, them));
}
// If the moving piece is a king, check whether the destination
b ^= from;
b ^= capsq;
b |= to;
- return (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
- ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
+ return (attacks_bb<ROOK>(ksq, b) & pieces(ROOK, QUEEN, us))
+ ||(attacks_bb<BISHOP>(ksq, b) & pieces(BISHOP, QUEEN, us));
}
// Castling with check ?
b ^= rfrom;
b |= rto;
b |= kto;
- return rook_attacks_bb(rto, b) & ksq;
+ return attacks_bb<ROOK>(rto, b) & ksq;
}
return false;
k ^= zobSideToMove;
// Increment the 50 moves rule draw counter. Resetting it to zero in the
- // case of non-reversible moves is taken care of later.
+ // case of a capture or a pawn move is taken care of later.
st->rule50++;
st->pliesFromNull++;
// Reset en passant square
if (st->epSquare != SQ_NONE)
{
- k ^= zobEp[st->epSquare];
+ k ^= zobEp[file_of(st->epSquare)];
st->epSquare = SQ_NONE;
}
if ( st->castleRights != CASTLES_NONE
&& (castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
{
- k ^= zobCastle[st->castleRights];
- st->castleRights &= castleRightsMask[from] & castleRightsMask[to];
- k ^= zobCastle[st->castleRights];
+ int cr = castleRightsMask[from] & castleRightsMask[to];
+ k ^= zobCastle[st->castleRights & (cr ^ ALL_CASTLES)];
+ st->castleRights &= cr;
}
// Prefetch TT access as soon as we know key is updated
&& (attacks_from<PAWN>(from + pawn_push(us), us) & pieces(PAWN, them)))
{
st->epSquare = Square((from + to) / 2);
- k ^= zobEp[st->epSquare];
+ k ^= zobEp[file_of(st->epSquare)];
}
if (is_promotion(m))
// Clear en passant square
if (st->epSquare != SQ_NONE)
{
- st->key ^= zobEp[st->epSquare];
+ st->key ^= zobEp[file_of(st->epSquare)];
st->epSquare = SQ_NONE;
}
// Update castling rights
- st->key ^= zobCastle[st->castleRights];
- st->castleRights &= castleRightsMask[kfrom];
- st->key ^= zobCastle[st->castleRights];
-
- // Reset rule 50 counter
- st->rule50 = 0;
+ int cr = castleRightsMask[kfrom];
+ st->key ^= zobCastle[st->castleRights & (cr ^ ALL_CASTLES)];
+ st->castleRights &= cr;
// Update checkers BB
st->checkersBB = attackers_to(king_square(~us)) & pieces(us);
if (Do)
{
if (st->epSquare != SQ_NONE)
- st->key ^= zobEp[st->epSquare];
+ st->key ^= zobEp[file_of(st->epSquare)];
st->key ^= zobSideToMove;
prefetch((char*)TT.first_entry(st->key));
// and scan for new X-ray attacks behind the attacker.
b = stmAttackers & pieces(pt);
occ ^= (b & (~b + 1));
- attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
- | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
+ attackers |= (attacks_bb<ROOK>(to, occ) & pieces(ROOK, QUEEN))
+ | (attacks_bb<BISHOP>(to, occ) & pieces(BISHOP, QUEEN));
attackers &= occ; // Cut out pieces we've already done
result ^= zobrist[color_of(piece_on(s))][type_of(piece_on(s))][s];
if (ep_square() != SQ_NONE)
- result ^= zobEp[ep_square()];
+ result ^= zobEp[file_of(ep_square())];
if (sideToMove == BLACK)
result ^= zobSideToMove;
for (Square s = SQ_A1; s <= SQ_H8; s++)
zobrist[c][pt][s] = rk.rand<Key>();
- for (Square s = SQ_A1; s <= SQ_H8; s++)
- zobEp[s] = rk.rand<Key>();
+ for (File f = FILE_A; f <= FILE_H; f++)
+ zobEp[f] = rk.rand<Key>();
- for (int i = 0; i < 16; i++)
- zobCastle[i] = rk.rand<Key>();
+ for (int cr = CASTLES_NONE; cr <= ALL_CASTLES; cr++)
+ {
+ Bitboard b = cr;
+ while (b)
+ {
+ Key k = zobCastle[1 << pop_1st_bit(&b)];
+ zobCastle[cr] ^= k ? k : rk.rand<Key>();
+ }
+ }
zobSideToMove = rk.rand<Key>();
zobExclusion = rk.rand<Key>();