bool Position::pl_move_is_legal(Move m) const {
- return pl_move_is_legal(m, pinned_pieces(side_to_move()));
+ // If we're in check, all pseudo-legal moves are legal, because our
+ // check evasion generator only generates true legal moves.
+ return is_check() || pl_move_is_legal(m, pinned_pieces(side_to_move()));
}
bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
assert(is_ok());
assert(move_is_ok(m));
assert(pinned == pinned_pieces(side_to_move()));
-
- // If we're in check, all pseudo-legal moves are legal, because our
- // check evasion generator only generates true legal moves.
- if (is_check())
- return true;
+ assert(!is_check());
// Castling moves are checked for legality during move generation.
if (move_is_castle(m))
case BISHOP:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || ( direction_between_squares(ksq, to) != DIR_NONE
- && bit_is_set(piece_attacks<BISHOP>(ksq), to));
+ || (direction_is_diagonal(ksq, to) && bit_is_set(piece_attacks<BISHOP>(ksq), to));
case ROOK:
return (dcCandidates && bit_is_set(dcCandidates, from))
- || ( direction_between_squares(ksq, to) != DIR_NONE
- && bit_is_set(piece_attacks<ROOK>(ksq), to));
+ || (direction_is_straight(ksq, to) && bit_is_set(piece_attacks<ROOK>(ksq), to));
case QUEEN:
// Discovered checks are impossible!
assert(!bit_is_set(dcCandidates, from));
- return ( direction_between_squares(ksq, to) != DIR_NONE
- && bit_is_set(piece_attacks<QUEEN>(ksq), to));
+ 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)));
case KING:
// Discovered check?
}
-/// Position::move_is_capture() tests whether a move from the current
-/// position is a capture. Move must not be MOVE_NONE.
-
-bool Position::move_is_capture(Move m) const {
-
- assert(m != MOVE_NONE);
-
- return ( !square_is_empty(move_to(m))
- && (color_of_piece_on(move_to(m)) != color_of_piece_on(move_from(m)))
- )
- || move_is_ep(m);
-}
-
-
/// Position::update_checkers() udpates chekers info given the move. It is called
/// in do_move() and is faster then find_checkers().
0, 0
};
- Bitboard attackers, occ, b;
+ Bitboard attackers, stmAttackers, occ, b;
assert(square_is_ok(from) || from == SQ_NONE);
assert(square_is_ok(to));
Square capQq = (side_to_move() == WHITE)? (to - DELTA_N) : (to - DELTA_S);
capture = piece_on(capQq);
-
assert(type_of_piece_on(capQq) == PAWN);
// Remove the captured pawn
}
// If the opponent has no attackers we are finished
- if ((attackers & pieces_of_color(them)) == EmptyBoardBB)
+ stmAttackers = attackers & pieces_of_color(them);
+ if (!stmAttackers)
return seeValues[capture];
attackers &= occ; // Remove the moving piece
// 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; !(attackers & pieces_of_color_and_type(c, pt)); pt++)
+ for (pt = PAWN; !(stmAttackers & pieces_of_type(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 = attackers & pieces_of_color_and_type(c, pt);
+ b = stmAttackers & pieces_of_type(pt);
occ ^= (b & (~b + 1));
attackers |= (rook_attacks_bb(to, occ) & rooks_and_queens())
| (bishop_attacks_bb(to, occ) & bishops_and_queens());
// before beginning the next iteration
lastCapturingPieceValue = seeValues[pt];
c = opposite_color(c);
+ stmAttackers = attackers & pieces_of_color(c);
// Stop after a king capture
- if (pt == KING && (attackers & pieces_of_color(c)))
+ if (pt == KING && stmAttackers)
{
assert(n < 32);
swapList[n++] = 100;
break;
}
- } while (attackers & pieces_of_color(c));
+ } while (stmAttackers);
// Having built the swap list, we negamax through it to find the best
// achievable score from the point of view of the side to move
}
-/// Position::is_mate() returns true or false depending on whether the
-/// side to move is checkmated. Note that this function is currently very
-/// slow, and shouldn't be used frequently inside the search.
-
-bool Position::is_mate() const {
-
- if (is_check())
- {
- MovePicker mp = MovePicker(*this, false, MOVE_NONE, EmptySearchStack, Depth(0));
- return mp.get_next_move() == MOVE_NONE;
- }
- return false;
-}
-
-
/// Position::is_draw() tests whether the position is drawn by material,
/// repetition, or the 50 moves rule. It does not detect stalemates, this
/// must be done by the search.
}
+/// Position::is_mate() returns true or false depending on whether the
+/// side to move is checkmated.
+
+bool Position::is_mate() const {
+
+ MoveStack moves[256];
+
+ return is_check() && !generate_evasions(*this, moves, pinned_pieces(sideToMove));
+}
+
+
/// Position::has_mate_threat() tests whether a given color has a mate in one
-/// from the current position. This function is quite slow, but it doesn't
-/// matter, because it is currently only called from PV nodes, which are rare.
+/// from the current position.
bool Position::has_mate_threat(Color c) {
StateInfo st1, st2;
Color stm = side_to_move();
- // The following lines are useless and silly, but prevents gcc from
- // emitting a stupid warning stating that u1.lastMove and u1.epSquare might
- // be used uninitialized.
- st1.lastMove = st->lastMove;
- st1.epSquare = st->epSquare;
-
if (is_check())
return false;
MoveStack mlist[120];
int count;
bool result = false;
+ Bitboard dc = discovered_check_candidates(sideToMove);
+ Bitboard pinned = pinned_pieces(sideToMove);
- // Generate legal moves
- count = generate_legal_moves(*this, mlist);
+ // Generate pseudo-legal non-capture and capture check moves
+ count = generate_non_capture_checks(*this, mlist, dc);
+ count += generate_captures(*this, mlist + count);
// Loop through the moves, and see if one of them is mate
for (int i = 0; i < count; i++)
{
- do_move(mlist[i].move, st2);
+ Move move = mlist[i].move;
+
+ if (!pl_move_is_legal(move, pinned))
+ continue;
+
+ do_move(move, st2);
if (is_mate())
result = true;
- undo_move(mlist[i].move);
+ undo_move(move);
}
// Undo null move, if necessary
void Position::init_zobrist() {
- for(Piece p = WP; p <= BK; p++)
- for(Square s = SQ_A1; s <= SQ_H8; s++)
- zobrist[color_of_piece(p)][type_of_piece(p)][s] = genrand_int64();
+ for (int i = 0; i < 2; i++)
+ for (int j = 0; j < 8; j++)
+ for (int k = 0; k < 64; k++)
+ zobrist[i][j][k] = Key(genrand_int64());
- zobEp[0] = 0ULL;
- for(int i = 1; i < 64; i++)
- zobEp[i] = genrand_int64();
+ for (int i = 0; i < 64; i++)
+ zobEp[i] = Key(genrand_int64());
- for(int i = 15; i >= 0; i--)
- zobCastle[(i&8) | (i&1) | ((i&2) << 1) | ((i&4) >> 1)] = genrand_int64();
+ for (int i = 0; i < 16; i++)
+ zobCastle[i] = genrand_int64();
zobSideToMove = genrand_int64();
for (int i = 0; i < 2; i++)
for (int j = 0; j < 8; j++)
for (int k = 0; k < 16; k++)
- zobMaterial[i][j][k] = (k > 0)? genrand_int64() : 0LL;
+ zobMaterial[i][j][k] = (k > 0)? Key(genrand_int64()) : Key(0LL);
for (int i = 0; i < 16; i++)
- zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = 0ULL;
+ zobMaterial[0][KING][i] = zobMaterial[1][KING][i] = Key(0ULL);
}