// Pinners are sliders, not checkers, that give check when
// candidate pinned is removed.
- pinners = (rooks_and_queens(FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
- | (bishops_and_queens(FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
+ pinners = (pieces(ROOK, QUEEN, FindPinned ? opposite_color(c) : c) & RookPseudoAttacks[ksq])
+ | (pieces(BISHOP, QUEEN, FindPinned ? opposite_color(c) : c) & BishopPseudoAttacks[ksq]);
if (FindPinned && pinners)
pinners &= ~st->checkersBB;
return hidden_checkers<false>(c);
}
-/// Position::attacks_to() computes a bitboard containing all pieces which
+/// Position::attackers_to() computes a bitboard containing all pieces which
/// attacks a given square.
-Bitboard Position::attacks_to(Square s) const {
+Bitboard Position::attackers_to(Square s) const {
- return (pawn_attacks(BLACK, s) & pawns(WHITE))
- | (pawn_attacks(WHITE, s) & pawns(BLACK))
- | (piece_attacks<KNIGHT>(s) & pieces_of_type(KNIGHT))
- | (piece_attacks<ROOK>(s) & rooks_and_queens())
- | (piece_attacks<BISHOP>(s) & bishops_and_queens())
- | (piece_attacks<KING>(s) & pieces_of_type(KING));
+ return (pawn_attacks_from(s, BLACK) & pieces(PAWN, WHITE))
+ | (pawn_attacks_from(s, WHITE) & pieces(PAWN, BLACK))
+ | (piece_attacks_from<KNIGHT>(s) & pieces(KNIGHT))
+ | (piece_attacks_from<ROOK>(s) & pieces(ROOK, QUEEN))
+ | (piece_attacks_from<BISHOP>(s) & pieces(BISHOP, QUEEN))
+ | (piece_attacks_from<KING>(s) & pieces(KING));
}
-/// Position::piece_attacks_square() tests whether the piece on square f
-/// attacks square t.
+/// Position::piece_attacks_from() computes a bitboard of all attacks
+/// of a given piece put in a given square.
-bool Position::piece_attacks_square(Piece p, Square f, Square t) const {
+Bitboard Position::piece_attacks_from(Piece p, Square s) const {
- assert(square_is_ok(f));
- assert(square_is_ok(t));
+ assert(square_is_ok(s));
switch (p)
{
- case WP: return pawn_attacks_square(WHITE, f, t);
- case BP: return pawn_attacks_square(BLACK, f, t);
- case WN: case BN: return piece_attacks_square<KNIGHT>(f, t);
- case WB: case BB: return piece_attacks_square<BISHOP>(f, t);
- case WR: case BR: return piece_attacks_square<ROOK>(f, t);
- case WQ: case BQ: return piece_attacks_square<QUEEN>(f, t);
- case WK: case BK: return piece_attacks_square<KING>(f, t);
+ case WP: return pawn_attacks_from(s, WHITE);
+ case BP: return pawn_attacks_from(s, BLACK);
+ case WN: case BN: return piece_attacks_from<KNIGHT>(s);
+ case WB: case BB: return piece_attacks_from<BISHOP>(s);
+ case WR: case BR: return piece_attacks_from<ROOK>(s);
+ case WQ: case BQ: return piece_attacks_from<QUEEN>(s);
+ case WK: case BK: return piece_attacks_from<KING>(s);
default: break;
}
return false;
assert(square_is_occupied(f));
- if (piece_attacks_square(piece_on(f), t, s))
+ if (bit_is_set(piece_attacks_from(piece_on(f), t), s))
return true;
// Move the piece and scan for X-ray attacks behind it
Color us = color_of_piece_on(f);
clear_bit(&occ, f);
set_bit(&occ, t);
- Bitboard xray = ( (rook_attacks_bb(s, occ) & rooks_and_queens())
- |(bishop_attacks_bb(s, occ) & bishops_and_queens())) & pieces_of_color(us);
+ Bitboard xray = ( (rook_attacks_bb(s, occ) & pieces(ROOK, QUEEN))
+ |(bishop_attacks_bb(s, occ) & pieces(BISHOP, QUEEN))) & pieces_of_color(us);
// If we have attacks we need to verify that are caused by our move
// and are not already existent ones.
- return xray && (xray ^ (xray & piece_attacks<QUEEN>(s)));
+ return xray && (xray ^ (xray & piece_attacks_from<QUEEN>(s)));
}
/// Position::find_checkers() computes the checkersBB bitboard, which
/// contains a nonzero bit for each checking piece (0, 1 or 2). It
-/// currently works by calling Position::attacks_to, which is probably
+/// currently works by calling Position::attackers_to, which is probably
/// inefficient. Consider rewriting this function to use the last move
/// played, like in non-bitboard versions of Glaurung.
void Position::find_checkers() {
Color us = side_to_move();
- st->checkersBB = attacks_to(king_square(us), opposite_color(us));
+ st->checkersBB = attackers_to(king_square(us)) & pieces_of_color(opposite_color(us));
}
Color us = side_to_move();
Square from = move_from(m);
- Square ksq = king_square(us);
assert(color_of_piece_on(from) == us);
- assert(piece_on(ksq) == piece_of_color_and_type(us, KING));
+ assert(piece_on(king_square(us)) == piece_of_color_and_type(us, KING));
// En passant captures are a tricky special case. Because they are
// rather uncommon, we do it simply by testing whether the king is attacked
Square to = move_to(m);
Square capsq = make_square(square_file(to), square_rank(from));
Bitboard b = occupied_squares();
+ Square ksq = king_square(us);
assert(to == ep_square());
assert(piece_on(from) == piece_of_color_and_type(us, PAWN));
clear_bit(&b, capsq);
set_bit(&b, to);
- return !(rook_attacks_bb(ksq, b) & rooks_and_queens(them))
- && !(bishop_attacks_bb(ksq, b) & bishops_and_queens(them));
+ return !(rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, them))
+ && !(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, them));
}
// If the moving piece is a king, check whether the destination
// square is attacked by the opponent.
- if (from == ksq)
- return !(square_is_attacked(move_to(m), opposite_color(us)));
+ if (type_of_piece_on(from) == KING)
+ return !(attackers_to(move_to(m)) & pieces_of_color(opposite_color(us)));
// A non-king move is legal if and only if it is not pinned or it
// is moving along the ray towards or away from the king.
return ( !pinned
|| !bit_is_set(pinned, from)
- || (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq)));
+ || (direction_between_squares(from, king_square(us)) == direction_between_squares(move_to(m), king_square(us))));
}
{
case PAWN:
- if (bit_is_set(pawn_attacks(them, ksq), to)) // Normal check?
+ if (bit_is_set(pawn_attacks_from(ksq, them), to)) // Normal check?
return true;
if ( dcCandidates // Discovered check?
switch (move_promotion_piece(m))
{
case KNIGHT:
- return bit_is_set(piece_attacks<KNIGHT>(to), ksq);
+ return bit_is_set(piece_attacks_from<KNIGHT>(to), ksq);
case BISHOP:
return bit_is_set(bishop_attacks_bb(to, b), ksq);
case ROOK:
clear_bit(&b, from);
clear_bit(&b, capsq);
set_bit(&b, to);
- return (rook_attacks_bb(ksq, b) & rooks_and_queens(us))
- ||(bishop_attacks_bb(ksq, b) & bishops_and_queens(us));
+ return (rook_attacks_bb(ksq, b) & pieces(ROOK, QUEEN, us))
+ ||(bishop_attacks_bb(ksq, b) & pieces(BISHOP, QUEEN, us));
}
return false;
// Test discovered check and normal check according to piece type
case KNIGHT:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || bit_is_set(piece_attacks<KNIGHT>(ksq), to);
+ || bit_is_set(piece_attacks_from<KNIGHT>(ksq), to);
case BISHOP:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks<BISHOP>(ksq), to));
+ || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks_from<BISHOP>(ksq), to));
case ROOK:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || (direction_is_straight(ksq, to) && bit_is_set(piece_attacks<ROOK>(ksq), to));
+ || (direction_is_straight(ksq, to) && bit_is_set(piece_attacks_from<ROOK>(ksq), to));
case QUEEN:
// Discovered checks are impossible!
assert(!bit_is_set(dcCandidates, from));
- return ( (direction_is_straight(ksq, to) && bit_is_set(piece_attacks<ROOK>(ksq), to))
- || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks<BISHOP>(ksq), to)));
+ return ( (direction_is_straight(ksq, to) && bit_is_set(piece_attacks_from<ROOK>(ksq), to))
+ || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks_from<BISHOP>(ksq), to)));
case KING:
// Discovered check?
// Direct checks
if ( ( (Bishop && bit_is_set(BishopPseudoAttacks[ksq], to))
|| (Rook && bit_is_set(RookPseudoAttacks[ksq], to)))
- && bit_is_set(piece_attacks<Piece>(ksq), to)) // slow, try to early skip
+ && bit_is_set(piece_attacks_from<Piece>(ksq), to)) // slow, try to early skip
set_bit(pCheckersBB, to);
else if ( Piece != KING
&& !Slider
- && bit_is_set(piece_attacks<Piece>(ksq), to))
+ && bit_is_set(Piece == PAWN ? pawn_attacks_from(ksq, opposite_color(sideToMove))
+ : piece_attacks_from<Piece>(ksq), to))
set_bit(pCheckersBB, to);
// Discovery checks
if (Piece != QUEEN && bit_is_set(dcCandidates, from))
{
if (Piece != ROOK)
- (*pCheckersBB) |= (piece_attacks<ROOK>(ksq) & rooks_and_queens(side_to_move()));
+ (*pCheckersBB) |= (piece_attacks_from<ROOK>(ksq) & pieces(ROOK, QUEEN, side_to_move()));
if (Piece != BISHOP)
- (*pCheckersBB) |= (piece_attacks<BISHOP>(ksq) & bishops_and_queens(side_to_move()));
+ (*pCheckersBB) |= (piece_attacks_from<BISHOP>(ksq) & pieces(BISHOP, QUEEN, side_to_move()));
}
}
struct ReducedStateInfo {
Key key, pawnKey, materialKey;
int castleRights, rule50;
- Square epSquare;
+ Square kingSquare[2], epSquare;
Value mgValue, egValue;
Value npMaterial[2];
};
}
// Update castle rights, try to shortcut a common case
- if ((castleRightsMask[from] & castleRightsMask[to]) != ALL_CASTLES)
+ int cm = castleRightsMask[from] & castleRightsMask[to];
+ if (cm != ALL_CASTLES && ((cm & st->castleRights) != st->castleRights))
{
key ^= zobCastle[st->castleRights];
st->castleRights &= castleRightsMask[from];
// If the moving piece was a king, update the king square
if (pt == KING)
- kingSquare[us] = to;
+ st->kingSquare[us] = to;
// Update piece lists, note that index[from] is not updated and
// becomes stale. This works as long as index[] is accessed just
// Set en passant square, only if moved pawn can be captured
if (abs(int(to) - int(from)) == 16)
{
- if ( (us == WHITE && (pawn_attacks(WHITE, from + DELTA_N) & pawns(BLACK)))
- || (us == BLACK && (pawn_attacks(BLACK, from + DELTA_S) & pawns(WHITE))))
- {
+ if (pawn_attacks_from(from + (us == WHITE ? DELTA_N : DELTA_S), us) & pieces(PAWN, them))
+ {
st->epSquare = Square((int(from) + int(to)) / 2);
key ^= zobEp[st->epSquare];
}
st->mgValue += pst_delta<MidGame>(piece, from, to);
st->egValue += pst_delta<EndGame>(piece, from, to);
- if (pm)
+ if (pm) // promotion ?
{
PieceType promotion = move_promotion_piece(m);
set_bit(&(byTypeBB[promotion]), to);
board[to] = piece_of_color_and_type(us, promotion);
+ // Update material key
+ st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]];
+ st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1];
+
// Update piece counts
pieceCount[us][PAWN]--;
pieceCount[us][promotion]++;
key ^= zobrist[us][PAWN][to] ^ zobrist[us][promotion][to];
st->pawnKey ^= zobrist[us][PAWN][to];
- // Update material key
- st->materialKey ^= zobMaterial[us][PAWN][pieceCount[us][PAWN]];
- st->materialKey ^= zobMaterial[us][promotion][pieceCount[us][promotion]+1];
-
// Partially revert and update incremental scores
st->mgValue -= pst<MidGame>(us, PAWN, to);
st->mgValue += pst<MidGame>(us, promotion, to);
// Update checkers bitboard, piece must be already moved
if (ep | pm)
- st->checkersBB = attacks_to(king_square(them), us);
+ st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
else
{
st->checkersBB = EmptyBoardBB;
st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
+
+ assert(is_ok());
}
Square capsq = to;
- if (ep)
+ if (ep) // en passant ?
{
capsq = (them == BLACK)? (to - DELTA_N) : (to - DELTA_S);
// Update hash key
key ^= zobrist[them][capture][capsq];
- // If the captured piece was a pawn, update pawn hash key
- if (capture == PAWN)
- st->pawnKey ^= zobrist[them][PAWN][capsq];
-
// Update incremental scores
st->mgValue -= pst<MidGame>(them, capture, capsq);
st->egValue -= pst<EndGame>(them, capture, capsq);
- // Update material
- if (capture != PAWN)
+ // If the captured piece was a pawn, update pawn hash key,
+ // otherwise update non-pawn material.
+ if (capture == PAWN)
+ st->pawnKey ^= zobrist[them][PAWN][capsq];
+ else
st->npMaterial[them] -= piece_value_midgame(capture);
// Update material hash key
pieceCount[them][capture]--;
// Update piece list, move the last piece at index[capsq] position
+ //
+ // WARNING: This is a not perfectly revresible operation. When we
+ // will reinsert the captured piece in undo_move() we will put it
+ // at the end of the list and not in its original place, it means
+ // index[] and pieceList[] are not guaranteed to be invariant to a
+ // do_move() + undo_move() sequence.
Square lastPieceSquare = pieceList[them][capture][pieceCount[them][capture]];
index[lastPieceSquare] = index[capsq];
pieceList[them][capture][index[lastPieceSquare]] = lastPieceSquare;
void Position::do_castle_move(Move m) {
- assert(is_ok());
assert(move_is_ok(m));
assert(move_is_castle(m));
board[rto] = rook;
// Update king square
- kingSquare[us] = kto;
+ st->kingSquare[us] = kto;
// Update piece lists
pieceList[us][KING][index[kfrom]] = kto;
pieceList[us][ROOK][index[rfrom]] = rto;
- int tmp = index[rfrom];
+ int tmp = index[rfrom]; // In Chess960 could be rto == kfrom
index[kto] = index[kfrom];
index[rto] = tmp;
st->rule50 = 0;
// Update checkers BB
- st->checkersBB = attacks_to(king_square(them), us);
+ st->checkersBB = attackers_to(king_square(them)) & pieces_of_color(us);
// Finish
sideToMove = opposite_color(sideToMove);
st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
+
+ assert(is_ok());
}
assert(!ep || relative_rank(us, to) == RANK_6);
assert(!ep || piece_on(to) == piece_of_color_and_type(us, PAWN));
- if (pm)
+ if (pm) // promotion ?
{
PieceType promotion = move_promotion_piece(m);
pt = PAWN;
pieceCount[us][PAWN]++;
// Update piece list replacing promotion piece with a pawn
- pieceList[us][promotion][index[to]] = pieceList[us][promotion][pieceCount[us][promotion]];
- index[pieceList[us][promotion][index[to]]] = index[to];
- pieceList[us][PAWN][pieceCount[us][PAWN] - 1] = to;
+ Square lastPromotionSquare = pieceList[us][promotion][pieceCount[us][promotion]];
+ index[lastPromotionSquare] = index[to];
+ pieceList[us][promotion][index[lastPromotionSquare]] = lastPromotionSquare;
index[to] = pieceCount[us][PAWN] - 1;
+ pieceList[us][PAWN][index[to]] = to;
}
// Put the piece back at the source square
board[from] = piece_of_color_and_type(us, pt);
board[to] = EMPTY;
- // If the moving piece was a king, update the king square
- if (pt == KING)
- kingSquare[us] = from;
-
// Update piece list
- pieceList[us][pt][index[to]] = from;
index[from] = index[to];
+ pieceList[us][pt][index[from]] = from;
if (st->capture)
{
board[capsq] = piece_of_color_and_type(them, st->capture);
- // Update piece list
- pieceList[them][st->capture][pieceCount[them][st->capture]] = capsq;
- index[capsq] = pieceCount[them][st->capture];
-
// Update piece count
pieceCount[them][st->capture]++;
+
+ // Update piece list, add a new captured piece in capsq square
+ index[capsq] = pieceCount[them][st->capture] - 1;
+ pieceList[them][st->capture][index[capsq]] = capsq;
}
// Finally point our state pointer back to the previous state
st = st->previous;
+
+ assert(is_ok());
}
board[rfrom] = piece_of_color_and_type(us, ROOK);
board[kfrom] = piece_of_color_and_type(us, KING);
- // Update king square
- kingSquare[us] = kfrom;
-
// Update piece lists
pieceList[us][KING][index[kto]] = kfrom;
pieceList[us][ROOK][index[rto]] = rfrom;
- int tmp = index[rto]; // Necessary because we may have rto == kfrom in FRC.
+ int tmp = index[rto]; // In Chess960 could be rto == kfrom
index[kfrom] = index[kto];
index[rfrom] = tmp;
// Finally point our state pointer back to the previous state
st = st->previous;
+
+ assert(is_ok());
}
// StateInfo object.
// Note that differently from normal case here backupSt is actually used as
// a backup storage not as a new state to be used.
+ backupSt.key = st->key;
backupSt.epSquare = st->epSquare;
- backupSt.key = st->key;
- backupSt.mgValue = st->mgValue;
- backupSt.egValue = st->egValue;
+ backupSt.mgValue = st->mgValue;
+ backupSt.egValue = st->egValue;
backupSt.previous = st->previous;
st->previous = &backupSt;
st->key ^= zobSideToMove;
TT.prefetch(st->key);
+
sideToMove = opposite_color(sideToMove);
st->epSquare = SQ_NONE;
st->rule50++;
st->mgValue += (sideToMove == WHITE)? TempoValueMidgame : -TempoValueMidgame;
st->egValue += (sideToMove == WHITE)? TempoValueEndgame : -TempoValueEndgame;
-
- assert(is_ok());
}
assert(!is_check());
// Restore information from the our backup StateInfo object
- st->epSquare = st->previous->epSquare;
- st->key = st->previous->key;
- st->mgValue = st->previous->mgValue;
- st->egValue = st->previous->egValue;
- st->previous = st->previous->previous;
+ StateInfo* backupSt = st->previous;
+ st->key = backupSt->key;
+ st->epSquare = backupSt->epSquare;
+ st->mgValue = backupSt->mgValue;
+ st->egValue = backupSt->egValue;
+ st->previous = backupSt->previous;
// Update the necessary information
sideToMove = opposite_color(sideToMove);
st->rule50--;
gamePly--;
-
- assert(is_ok());
}
while (true)
{
clear_bit(&occ, from);
- attackers = (rook_attacks_bb(to, occ) & rooks_and_queens())
- | (bishop_attacks_bb(to, occ) & bishops_and_queens())
- | (piece_attacks<KNIGHT>(to) & knights())
- | (piece_attacks<KING>(to) & kings())
- | (pawn_attacks(WHITE, to) & pawns(BLACK))
- | (pawn_attacks(BLACK, to) & pawns(WHITE));
+ attackers = (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
+ | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN))
+ | (piece_attacks_from<KNIGHT>(to) & pieces(KNIGHT))
+ | (piece_attacks_from<KING>(to) & pieces(KING))
+ | (pawn_attacks_from(to, WHITE) & pieces(PAWN, BLACK))
+ | (pawn_attacks_from(to, BLACK) & pieces(PAWN, WHITE));
if (from != SQ_NONE)
break;
// Locate the least valuable attacker to the destination square
// and use it to initialize from square.
+ stmAttackers = attackers & pieces_of_color(us);
PieceType pt;
- for (pt = PAWN; !(attackers & pieces_of_color_and_type(us, pt)); pt++)
+ for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
assert(pt < KING);
- from = first_1(attackers & pieces_of_color_and_type(us, pt));
+ from = first_1(stmAttackers & pieces(pt));
piece = piece_on(from);
}
// Locate the least valuable attacker for the side to move. The loop
// below looks like it is potentially infinite, but it isn't. We know
// that the side to move still has at least one attacker left.
- for (pt = PAWN; !(stmAttackers & pieces_of_type(pt)); pt++)
+ for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
assert(pt < KING);
// Remove the attacker we just found from the 'attackers' bitboard,
// and scan for new X-ray attacks behind the attacker.
- b = stmAttackers & pieces_of_type(pt);
+ b = stmAttackers & pieces(pt);
occ ^= (b & (~b + 1));
- attackers |= (rook_attacks_bb(to, occ) & rooks_and_queens())
- | (bishop_attacks_bb(to, occ) & bishops_and_queens());
+ attackers |= (rook_attacks_bb(to, occ) & pieces(ROOK, QUEEN))
+ | (bishop_attacks_bb(to, occ) & pieces(BISHOP, QUEEN));
attackers &= occ;
memset(st, 0, sizeof(StateInfo));
st->epSquare = SQ_NONE;
- memset(index, 0, sizeof(int) * 64);
- memset(byColorBB, 0, sizeof(Bitboard) * 2);
+ memset(byColorBB, 0, sizeof(Bitboard) * 2);
+ memset(byTypeBB, 0, sizeof(Bitboard) * 8);
+ memset(pieceCount, 0, sizeof(int) * 2 * 8);
+ memset(index, 0, sizeof(int) * 64);
for (int i = 0; i < 64; i++)
board[i] = EMPTY;
for (int i = 0; i < 7; i++)
- {
- byTypeBB[i] = EmptyBoardBB;
- pieceCount[0][i] = pieceCount[1][i] = 0;
for (int j = 0; j < 8; j++)
pieceList[0][i][j] = pieceList[1][i][j] = SQ_NONE;
- }
sideToMove = WHITE;
gamePly = 0;
pieceCount[c][pt]++;
if (pt == KING)
- kingSquare[c] = s;
+ st->kingSquare[c] = s;
}
for (Color c = WHITE; c <= BLACK; c++)
{
- b = pawns(c);
+ b = pieces(PAWN, c);
while(b)
{
s = pop_1st_bit(&b);
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++)
{
- b = pieces_of_color_and_type(c, pt);
+ b = pieces(pt, c);
while(b)
{
s = pop_1st_bit(&b);
for (PieceType pt = KNIGHT; pt <= QUEEN; pt++)
{
- Bitboard b = pieces_of_color_and_type(c, pt);
+ Bitboard b = pieces(pt, c);
while (b)
{
assert(piece_on(first_1(b)) == piece_of_color_and_type(c, pt));
bool Position::is_draw() const {
// Draw by material?
- if ( !pawns()
+ if ( !pieces(PAWN)
&& (non_pawn_material(WHITE) + non_pawn_material(BLACK) <= BishopValueMidgame))
return true;
MoveStack moves[256];
- return is_check() && !generate_evasions(*this, moves, pinned_pieces(sideToMove));
+ return is_check() && (generate_evasions(*this, moves, pinned_pieces(sideToMove)) == moves);
}
do_null_move(st1);
MoveStack mlist[120];
- int count;
bool result = false;
Bitboard dc = discovered_check_candidates(sideToMove);
Bitboard pinned = pinned_pieces(sideToMove);
// Generate pseudo-legal non-capture and capture check moves
- count = generate_non_capture_checks(*this, mlist, dc);
- count += generate_captures(*this, mlist + count);
+ MoveStack* last = generate_non_capture_checks(*this, mlist, dc);
+ last = generate_captures(*this, last);
// Loop through the moves, and see if one of them is mate
- for (int i = 0; i < count; i++)
+ for (MoveStack* cur = mlist; cur != last; cur++)
{
- Move move = mlist[i].move;
-
+ Move move = cur->move;
if (!pl_move_is_legal(move, pinned))
continue;
Color us = side_to_move();
Color them = opposite_color(us);
Square ksq = king_square(them);
- if (square_is_attacked(ksq, us))
+ if (attackers_to(ksq) & pieces_of_color(us))
return false;
}
// Separate piece type bitboards must have empty intersections
for (PieceType p1 = PAWN; p1 <= KING; p1++)
for (PieceType p2 = PAWN; p2 <= KING; p2++)
- if (p1 != p2 && (pieces_of_type(p1) & pieces_of_type(p2)))
+ if (p1 != p2 && (pieces(p1) & pieces(p2)))
return false;
}
if (debugPieceCounts)
for (Color c = WHITE; c <= BLACK; c++)
for (PieceType pt = PAWN; pt <= KING; pt++)
- if (pieceCount[c][pt] != count_1s(pieces_of_color_and_type(c, pt)))
+ if (pieceCount[c][pt] != count_1s(pieces(pt, c)))
return false;
if (failedStep) (*failedStep)++;
for(PieceType pt = PAWN; pt <= KING; pt++)
for(int i = 0; i < pieceCount[c][pt]; i++)
{
- if (piece_on(piece_list(c, pt, i)) != piece_of_color_and_type(c, pt))
+ if (piece_on(piece_list(c, pt, i)) != (pieces(pt, c)))
return false;
if (index[piece_list(c, pt, i)] != i)