mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Revert hidden checkers rework
It is slower the previous uglier but faster code. So completely restore old one for now :-( Just leave in the rework of status backup/restore in do_move(). We will cherry pick bits of previous work once we are sure we have fixed the performance regression. Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
parent
9b6b9e67fe
commit
c02613860a
7 changed files with 111 additions and 201 deletions
|
@ -166,14 +166,13 @@ int generate_noncaptures(const Position& pos, MoveStack* mlist) {
|
|||
/// generate_checks() generates all pseudo-legal non-capturing, non-promoting
|
||||
/// checks. It returns the number of generated moves.
|
||||
|
||||
int generate_checks(const Position& pos, MoveStack* mlist) {
|
||||
int generate_checks(const Position& pos, MoveStack* mlist, Bitboard dc) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
assert(!pos.is_check());
|
||||
|
||||
Color us = pos.side_to_move();
|
||||
Square ksq = pos.king_square(opposite_color(us));
|
||||
Bitboard dc = pos.discovered_check_candidates(us);
|
||||
MoveStack* mlist_start = mlist;
|
||||
|
||||
assert(pos.piece_on(ksq) == piece_of_color_and_type(opposite_color(us), KING));
|
||||
|
@ -205,7 +204,7 @@ int generate_checks(const Position& pos, MoveStack* mlist) {
|
|||
/// in check. Unlike the other move generation functions, this one generates
|
||||
/// only legal moves. It returns the number of generated moves.
|
||||
|
||||
int generate_evasions(const Position& pos, MoveStack* mlist) {
|
||||
int generate_evasions(const Position& pos, MoveStack* mlist, Bitboard pinned) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
assert(pos.is_check());
|
||||
|
@ -259,7 +258,6 @@ int generate_evasions(const Position& pos, MoveStack* mlist) {
|
|||
if (!(checkers & (checkers - 1))) // Only one bit set?
|
||||
{
|
||||
Square checksq = first_1(checkers);
|
||||
Bitboard pinned = pos.pinned_pieces(us);
|
||||
|
||||
assert(pos.color_of_piece_on(checksq) == them);
|
||||
|
||||
|
@ -349,8 +347,10 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
|
|||
|
||||
assert(pos.is_ok());
|
||||
|
||||
Bitboard pinned = pos.pinned_pieces(pos.side_to_move());
|
||||
|
||||
if (pos.is_check())
|
||||
return generate_evasions(pos, mlist);
|
||||
return generate_evasions(pos, mlist, pinned);
|
||||
|
||||
// Generate pseudo-legal moves
|
||||
int n = generate_captures(pos, mlist);
|
||||
|
@ -358,7 +358,7 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
|
|||
|
||||
// Remove illegal moves from the list
|
||||
for (int i = 0; i < n; i++)
|
||||
if (!pos.pl_move_is_legal(mlist[i].move))
|
||||
if (!pos.pl_move_is_legal(mlist[i].move, pinned))
|
||||
mlist[i--].move = mlist[--n].move;
|
||||
|
||||
return n;
|
||||
|
@ -371,11 +371,12 @@ int generate_legal_moves(const Position& pos, MoveStack* mlist) {
|
|||
/// returned. If not, the function returns false. This function must
|
||||
/// only be used when the side to move is not in check.
|
||||
|
||||
bool move_is_legal(const Position& pos, const Move m) {
|
||||
bool move_is_legal(const Position& pos, const Move m, Bitboard pinned) {
|
||||
|
||||
assert(pos.is_ok());
|
||||
assert(!pos.is_check());
|
||||
assert(move_is_ok(m));
|
||||
assert(pinned == pos.pinned_pieces(pos.side_to_move()));
|
||||
|
||||
Color us = pos.side_to_move();
|
||||
Color them = opposite_color(us);
|
||||
|
@ -402,7 +403,7 @@ bool move_is_legal(const Position& pos, const Move m) {
|
|||
assert(pos.piece_on(to - pawn_push(us)) == piece_of_color_and_type(them, PAWN));
|
||||
|
||||
// The move is pseudo-legal, check if it is also legal
|
||||
return pos.pl_move_is_legal(m);
|
||||
return pos.pl_move_is_legal(m, pinned);
|
||||
}
|
||||
|
||||
// Castling moves
|
||||
|
@ -534,12 +535,12 @@ bool move_is_legal(const Position& pos, const Move m) {
|
|||
return false;
|
||||
}
|
||||
// The move is pseudo-legal, check if it is also legal
|
||||
return pos.pl_move_is_legal(m);
|
||||
return pos.pl_move_is_legal(m, pinned);
|
||||
}
|
||||
|
||||
// Luckly we can handle all the other pieces in one go
|
||||
return ( pos.piece_attacks_square(pos.piece_on(from), from, to)
|
||||
&& pos.pl_move_is_legal(m)
|
||||
&& pos.pl_move_is_legal(m, pinned)
|
||||
&& !move_promotion(m));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@
|
|||
|
||||
extern int generate_captures(const Position &pos, MoveStack *mlist);
|
||||
extern int generate_noncaptures(const Position &pos, MoveStack *mlist);
|
||||
extern int generate_checks(const Position &pos, MoveStack *mlist);
|
||||
extern int generate_evasions(const Position &pos, MoveStack *mlist);
|
||||
extern int generate_checks(const Position &pos, MoveStack *mlist, Bitboard dc);
|
||||
extern int generate_evasions(const Position &pos, MoveStack *mlist, Bitboard pinned);
|
||||
extern int generate_legal_moves(const Position &pos, MoveStack *mlist);
|
||||
extern bool move_is_legal(const Position &pos, const Move m);
|
||||
extern bool move_is_legal(const Position &pos, const Move m, Bitboard pinned);
|
||||
|
||||
|
||||
#endif // !defined(MOVEGEN_H_INCLUDED)
|
||||
|
|
|
@ -96,6 +96,9 @@ MovePicker::MovePicker(const Position& p, bool pv, Move ttm,
|
|||
else
|
||||
phaseIndex = (noCaptures ? NoMovesPhaseIndex : QsearchWithoutChecksPhaseIndex);
|
||||
|
||||
dc = p.discovered_check_candidates(us);
|
||||
pinned = p.pinned_pieces(us);
|
||||
|
||||
finished = false;
|
||||
}
|
||||
|
||||
|
@ -127,7 +130,7 @@ Move MovePicker::get_next_move() {
|
|||
if (ttMove != MOVE_NONE)
|
||||
{
|
||||
assert(move_is_ok(ttMove));
|
||||
if (move_is_legal(pos, ttMove))
|
||||
if (move_is_legal(pos, ttMove, pinned))
|
||||
return ttMove;
|
||||
}
|
||||
break;
|
||||
|
@ -136,7 +139,7 @@ Move MovePicker::get_next_move() {
|
|||
if (mateKiller != MOVE_NONE)
|
||||
{
|
||||
assert(move_is_ok(mateKiller));
|
||||
if (move_is_legal(pos, mateKiller))
|
||||
if (move_is_legal(pos, mateKiller, pinned))
|
||||
return mateKiller;
|
||||
}
|
||||
break;
|
||||
|
@ -159,7 +162,7 @@ Move MovePicker::get_next_move() {
|
|||
|
||||
case PH_EVASIONS:
|
||||
assert(pos.is_check());
|
||||
numOfMoves = generate_evasions(pos, moves);
|
||||
numOfMoves = generate_evasions(pos, moves, pinned);
|
||||
score_evasions();
|
||||
movesPicked = 0;
|
||||
break;
|
||||
|
@ -171,7 +174,7 @@ Move MovePicker::get_next_move() {
|
|||
break;
|
||||
|
||||
case PH_QCHECKS:
|
||||
numOfMoves = generate_checks(pos, moves);
|
||||
numOfMoves = generate_checks(pos, moves, dc);
|
||||
movesPicked = 0;
|
||||
break;
|
||||
|
||||
|
@ -391,7 +394,7 @@ Move MovePicker::pick_move_from_list() {
|
|||
moves[bestIndex] = moves[movesPicked++];
|
||||
if ( move != ttMove
|
||||
&& move != mateKiller
|
||||
&& pos.pl_move_is_legal(move))
|
||||
&& pos.pl_move_is_legal(move, pinned))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
|
@ -411,7 +414,7 @@ Move MovePicker::pick_move_from_list() {
|
|||
moves[bestIndex] = moves[movesPicked++];
|
||||
if ( move != ttMove
|
||||
&& move != mateKiller
|
||||
&& pos.pl_move_is_legal(move))
|
||||
&& pos.pl_move_is_legal(move, pinned))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
|
@ -439,7 +442,7 @@ Move MovePicker::pick_move_from_list() {
|
|||
move = badCaptures[movesPicked++].move;
|
||||
if ( move != ttMove
|
||||
&& move != mateKiller
|
||||
&& pos.pl_move_is_legal(move))
|
||||
&& pos.pl_move_is_legal(move, pinned))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
|
@ -454,7 +457,7 @@ Move MovePicker::pick_move_from_list() {
|
|||
moves[bestIndex] = moves[movesPicked++];
|
||||
// Remember to change the line below if we decide to hash the qsearch!
|
||||
// Maybe also postpone the legality check until after futility pruning?
|
||||
if (/* move != ttMove && */ pos.pl_move_is_legal(move))
|
||||
if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
|
@ -468,7 +471,7 @@ Move MovePicker::pick_move_from_list() {
|
|||
{
|
||||
move = moves[movesPicked++].move;
|
||||
// Remember to change the line below if we decide to hash the qsearch!
|
||||
if (/* move != ttMove && */ pos.pl_move_is_legal(move))
|
||||
if (/* move != ttMove && */ pos.pl_move_is_legal(move, pinned))
|
||||
return move;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
int number_of_moves() const;
|
||||
int current_move_score() const;
|
||||
MovegenPhase current_move_type() const;
|
||||
Bitboard discovered_check_candidates() const;
|
||||
|
||||
static void init_phase_table();
|
||||
|
||||
|
@ -83,6 +84,7 @@ private:
|
|||
|
||||
const Position& pos;
|
||||
Move ttMove, mateKiller, killer1, killer2;
|
||||
Bitboard pinned, dc;
|
||||
MoveStack moves[256], badCaptures[64];
|
||||
bool pvNode;
|
||||
Depth depth;
|
||||
|
@ -107,4 +109,12 @@ inline int MovePicker::number_of_moves() const {
|
|||
return numOfMoves;
|
||||
}
|
||||
|
||||
/// MovePicker::discovered_check_candidates() returns a bitboard containing
|
||||
/// all pieces which can possibly give discovered check. This bitboard is
|
||||
/// computed by the constructor function.
|
||||
|
||||
inline Bitboard MovePicker::discovered_check_candidates() const {
|
||||
return dc;
|
||||
}
|
||||
|
||||
#endif // !defined(MOVEPICK_H_INCLUDED)
|
||||
|
|
188
src/position.cpp
188
src/position.cpp
|
@ -207,7 +207,6 @@ void Position::from_fen(const std::string& fen) {
|
|||
castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO;
|
||||
|
||||
find_checkers();
|
||||
find_hidden_checks();
|
||||
|
||||
st->key = compute_key();
|
||||
st->pawnKey = compute_pawn_key();
|
||||
|
@ -321,6 +320,29 @@ void Position::copy(const Position &pos) {
|
|||
}
|
||||
|
||||
|
||||
/// Position:pinned_pieces() returns a bitboard of all pinned (against the
|
||||
/// king) pieces for the given color.
|
||||
Bitboard Position::pinned_pieces(Color c) const {
|
||||
|
||||
Bitboard p;
|
||||
Square ksq = king_square(c);
|
||||
return hidden_checks<ROOK, true>(c, ksq, p) | hidden_checks<BISHOP, true>(c, ksq, p);
|
||||
}
|
||||
|
||||
|
||||
/// Position:discovered_check_candidates() returns a bitboard containing all
|
||||
/// pieces for the given side which are candidates for giving a discovered
|
||||
/// check. The code is almost the same as the function for finding pinned
|
||||
/// pieces.
|
||||
|
||||
Bitboard Position::discovered_check_candidates(Color c) const {
|
||||
|
||||
Bitboard p;
|
||||
Square ksq = king_square(opposite_color(c));
|
||||
return hidden_checks<ROOK, false>(c, ksq, p) | hidden_checks<BISHOP, false>(c, ksq, p);
|
||||
}
|
||||
|
||||
|
||||
/// Position:hidden_checks<>() returns a bitboard of all pinned (against the
|
||||
/// king) pieces for the given color and for the given pinner type. Or, when
|
||||
/// template parameter FindPinned is false, the pinned pieces of opposite color
|
||||
|
@ -446,38 +468,19 @@ void Position::find_checkers() {
|
|||
st->checkersBB = attacks_to(king_square(us), opposite_color(us));
|
||||
}
|
||||
|
||||
/// Position:find_hidden_checks() computes the pinned, pinners and dcCandidates
|
||||
/// bitboards. There are two versions of this function. One takes a color and
|
||||
/// computes bitboards relative to that color only, the other computes both
|
||||
/// colors. Bitboard checkersBB must be already updated.
|
||||
|
||||
void Position::find_hidden_checks(Color us, unsigned int types) {
|
||||
|
||||
Bitboard p1, p2;
|
||||
Color them = opposite_color(us);
|
||||
Square ksq = king_square(them);
|
||||
if (types & Pinned)
|
||||
{
|
||||
st->pinned[them] = hidden_checks<ROOK, true>(them, ksq, p1) | hidden_checks<BISHOP, true>(them, ksq, p2);
|
||||
st->pinners[them] = p1 | p2;
|
||||
}
|
||||
if (types & DcCandidates)
|
||||
st->dcCandidates[us] = hidden_checks<ROOK, false>(us, ksq, p1) | hidden_checks<BISHOP, false>(us, ksq, p2);
|
||||
}
|
||||
|
||||
void Position::find_hidden_checks() {
|
||||
|
||||
for (Color c = WHITE; c <= BLACK; c++)
|
||||
find_hidden_checks(c, Pinned | DcCandidates);
|
||||
}
|
||||
|
||||
|
||||
/// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
|
||||
|
||||
bool Position::pl_move_is_legal(Move m) const {
|
||||
|
||||
return 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.
|
||||
|
@ -525,7 +528,7 @@ bool Position::pl_move_is_legal(Move m) const {
|
|||
|
||||
// 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 ( !bit_is_set(pinned_pieces(us), from)
|
||||
return ( !bit_is_set(pinned, from)
|
||||
|| (direction_between_squares(from, ksq) == direction_between_squares(move_to(m), ksq)));
|
||||
}
|
||||
|
||||
|
@ -534,15 +537,21 @@ bool Position::pl_move_is_legal(Move m) const {
|
|||
|
||||
bool Position::move_is_check(Move m) const {
|
||||
|
||||
Bitboard dc = discovered_check_candidates(side_to_move());
|
||||
return move_is_check(m, dc);
|
||||
}
|
||||
|
||||
bool Position::move_is_check(Move m, Bitboard dcCandidates) const {
|
||||
|
||||
assert(is_ok());
|
||||
assert(move_is_ok(m));
|
||||
assert(dcCandidates == discovered_check_candidates(side_to_move()));
|
||||
|
||||
Color us = side_to_move();
|
||||
Color them = opposite_color(us);
|
||||
Square from = move_from(m);
|
||||
Square to = move_to(m);
|
||||
Square ksq = king_square(them);
|
||||
Bitboard dcCandidates = discovered_check_candidates(us);
|
||||
|
||||
assert(color_of_piece_on(from) == us);
|
||||
assert(piece_on(ksq) == piece_of_color_and_type(them, KING));
|
||||
|
@ -684,88 +693,20 @@ inline void Position::update_checkers(Bitboard* pCheckersBB, Square ksq, Square
|
|||
}
|
||||
|
||||
|
||||
/// Position::update_hidden_checks() udpates pinned, pinners and dcCandidates
|
||||
/// bitboards incrementally, given the move. It is called in do_move and is
|
||||
/// faster then find_hidden_checks().
|
||||
|
||||
void Position::update_hidden_checks(Square from, Square to) {
|
||||
|
||||
Color us = sideToMove;
|
||||
Color them = opposite_color(us);
|
||||
Square ksq = king_square(opposite_color(us));
|
||||
|
||||
Bitboard moveSquares = EmptyBoardBB;
|
||||
set_bit(&moveSquares, from);
|
||||
set_bit(&moveSquares, to);
|
||||
|
||||
// Our moving piece could have been a possible pinner or hidden checker behind a dcCandidates?
|
||||
bool checkerMoved = (st->dcCandidates[us] || bit_is_set(st->pinners[them], from)) && (moveSquares & sliders());
|
||||
|
||||
// If we are moving from/to an opponent king attack direction and we was a possible hidden checker
|
||||
// or there exsist some possible hidden checker on that line then recalculate the position
|
||||
// otherwise skip because our dcCandidates and opponent pinned pieces are not changed.
|
||||
if ( (moveSquares & RookPseudoAttacks[ksq]) && (checkerMoved || (rooks_and_queens(us) & RookPseudoAttacks[ksq]))
|
||||
|| (moveSquares & BishopPseudoAttacks[ksq]) && (checkerMoved || (bishops_and_queens(us) & BishopPseudoAttacks[ksq])))
|
||||
{
|
||||
// If the move gives direct check and we don't have pinners/dc cadidates
|
||||
// then we can be sure that we won't have them also after the move if
|
||||
// we are not moving from a possible king attack direction.
|
||||
bool outsideChecker = false;
|
||||
|
||||
if ( bit_is_set(st->checkersBB, to)
|
||||
&& !(bit_is_set(RookPseudoAttacks[ksq], from) && (checkerMoved || (rooks_and_queens(us) & RookPseudoAttacks[ksq])))
|
||||
&& !(bit_is_set(BishopPseudoAttacks[ksq], from) && (checkerMoved || (bishops_and_queens(us) & BishopPseudoAttacks[ksq]))))
|
||||
outsideChecker = true;
|
||||
|
||||
if (!outsideChecker || st->pinned[them])
|
||||
find_hidden_checks(us, Pinned);
|
||||
|
||||
if (!outsideChecker || st->dcCandidates[us] || bit_is_set(st->pinned[them], to))
|
||||
find_hidden_checks(us, DcCandidates);
|
||||
}
|
||||
|
||||
ksq = king_square(us);
|
||||
|
||||
if (ksq == to)
|
||||
{
|
||||
find_hidden_checks(them, Pinned | DcCandidates);
|
||||
return;
|
||||
}
|
||||
|
||||
// It is possible that we have captured an opponent hidden checker?
|
||||
Bitboard checkerCaptured = st->capture && (st->dcCandidates[them] || bit_is_set(st->pinners[us], to));
|
||||
|
||||
// If we are moving from/to an our king attack direction and there was/is some possible
|
||||
// opponent hidden checker then calculate the position otherwise skip because opponent
|
||||
// dcCandidates and our pinned pieces are not changed.
|
||||
if ( (moveSquares & RookPseudoAttacks[ksq]) && (checkerCaptured || (rooks_and_queens(them) & RookPseudoAttacks[ksq]))
|
||||
|| (moveSquares & BishopPseudoAttacks[ksq]) && (checkerCaptured || (bishops_and_queens(them) & BishopPseudoAttacks[ksq])))
|
||||
{
|
||||
find_hidden_checks(them, Pinned);
|
||||
|
||||
// If we don't have opponent dc candidates and we are moving in the
|
||||
// attack line then won't be any dc candidates also after the move.
|
||||
if ( st->dcCandidates[them]
|
||||
|| (bit_is_set(RookPseudoAttacks[ksq], from) && (rooks_and_queens(them) & RookPseudoAttacks[ksq]))
|
||||
|| (bit_is_set(BishopPseudoAttacks[ksq], from) && (bishops_and_queens(them) & BishopPseudoAttacks[ksq])))
|
||||
find_hidden_checks(them, DcCandidates);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Position::do_move() makes a move, and saves all information necessary
|
||||
/// to a StateInfo object. The move is assumed to be legal.
|
||||
/// Pseudo-legal moves should be filtered out before this function is called.
|
||||
|
||||
void Position::do_move(Move m, StateInfo& newSt) {
|
||||
|
||||
do_move(m, newSt, discovered_check_candidates(side_to_move()));
|
||||
}
|
||||
|
||||
void Position::do_move(Move m, StateInfo& newSt, Bitboard dcCandidates) {
|
||||
|
||||
assert(is_ok());
|
||||
assert(move_is_ok(m));
|
||||
|
||||
// Get now the current (before to move) dc candidates that we will use
|
||||
// in update_checkers().
|
||||
Bitboard oldDcCandidates = discovered_check_candidates(side_to_move());
|
||||
|
||||
// Copy some fields of old state to our new StateInfo object (except the
|
||||
// captured piece, which is taken care of later) and switch state pointer
|
||||
// to point to the new, ready to be updated, state.
|
||||
|
@ -871,16 +812,14 @@ void Position::do_move(Move m, StateInfo& newSt) {
|
|||
Square ksq = king_square(them);
|
||||
switch (piece)
|
||||
{
|
||||
case PAWN: update_checkers<PAWN>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case KNIGHT: update_checkers<KNIGHT>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case BISHOP: update_checkers<BISHOP>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case ROOK: update_checkers<ROOK>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case QUEEN: update_checkers<QUEEN>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case KING: update_checkers<KING>(&st->checkersBB, ksq, from, to, oldDcCandidates); break;
|
||||
case PAWN: update_checkers<PAWN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case KNIGHT: update_checkers<KNIGHT>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case BISHOP: update_checkers<BISHOP>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case ROOK: update_checkers<ROOK>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case QUEEN: update_checkers<QUEEN>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
case KING: update_checkers<KING>(&(st->checkersBB), ksq, from, to, dcCandidates); break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
|
||||
update_hidden_checks(from, to);
|
||||
}
|
||||
|
||||
// Finish
|
||||
|
@ -1032,9 +971,6 @@ void Position::do_castle_move(Move m) {
|
|||
|
||||
// Update checkers BB
|
||||
st->checkersBB = attacks_to(king_square(them), us);
|
||||
|
||||
// Update hidden checks
|
||||
find_hidden_checks();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1125,9 +1061,6 @@ void Position::do_promotion_move(Move m) {
|
|||
|
||||
// Update checkers BB
|
||||
st->checkersBB = attacks_to(king_square(them), us);
|
||||
|
||||
// Update hidden checks
|
||||
find_hidden_checks();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1210,9 +1143,6 @@ void Position::do_ep_move(Move m) {
|
|||
|
||||
// Update checkers BB
|
||||
st->checkersBB = attacks_to(king_square(them), us);
|
||||
|
||||
// Update hidden checks
|
||||
find_hidden_checks();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1597,11 +1527,6 @@ int Position::see(Square from, Square to) const {
|
|||
Color us = (from != SQ_NONE ? color_of_piece_on(from) : opposite_color(color_of_piece_on(to)));
|
||||
Color them = opposite_color(us);
|
||||
|
||||
// Initialize pinned and pinners bitboards
|
||||
Bitboard pinned[2], pinners[2];
|
||||
pinned[us] = pinned_pieces(us, pinners[us]);
|
||||
pinned[them] = pinned_pieces(them, pinners[them]);
|
||||
|
||||
// Initialize pieces
|
||||
Piece piece = piece_on(from);
|
||||
Piece capture = piece_on(to);
|
||||
|
@ -1634,17 +1559,6 @@ int Position::see(Square from, Square to) const {
|
|||
| (pawn_attacks(WHITE, to) & pawns(BLACK))
|
||||
| (pawn_attacks(BLACK, to) & pawns(WHITE));
|
||||
|
||||
// Remove our pinned pieces from attacks if the captured piece is not
|
||||
// a pinner, otherwise we could remove a valid "capture the pinner" attack.
|
||||
if (pinned[us] != EmptyBoardBB && !bit_is_set(pinners[us], to))
|
||||
attackers &= ~pinned[us];
|
||||
|
||||
// Remove opponent pinned pieces from attacks if the moving piece is not
|
||||
// a pinner, otherwise we could remove a piece that is no more pinned
|
||||
// due to our pinner piece is moving away.
|
||||
if (pinned[them] != EmptyBoardBB && !bit_is_set(pinners[them], from))
|
||||
attackers &= ~pinned[them];
|
||||
|
||||
if (from != SQ_NONE)
|
||||
break;
|
||||
|
||||
|
@ -1707,12 +1621,6 @@ int Position::see(Square from, Square to) const {
|
|||
lastCapturingPieceValue = seeValues[pt];
|
||||
c = opposite_color(c);
|
||||
|
||||
// Remove pinned pieces from attackers
|
||||
if ( pinned[c] != EmptyBoardBB
|
||||
&& !bit_is_set(pinners[c], to)
|
||||
&& !(pinners[c] & attackers))
|
||||
attackers &= ~pinned[c];
|
||||
|
||||
// Stop after a king capture
|
||||
if (pt == KING && (attackers & pieces_of_color(c)))
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ enum CastleRights {
|
|||
/// must be passed as a parameter.
|
||||
|
||||
struct StateInfo {
|
||||
Bitboard pinners[2], pinned[2], dcCandidates[2], checkersBB;
|
||||
Bitboard checkersBB;
|
||||
Key key, pawnKey, materialKey;
|
||||
int castleRights, rule50;
|
||||
Square epSquare;
|
||||
|
@ -219,7 +219,9 @@ public:
|
|||
|
||||
// Properties of moves
|
||||
bool pl_move_is_legal(Move m) const;
|
||||
bool pl_move_is_legal(Move m, Bitboard pinned) const;
|
||||
bool move_is_check(Move m) const;
|
||||
bool move_is_check(Move m, Bitboard dcCandidates) const;
|
||||
bool move_is_capture(Move m) const;
|
||||
bool move_is_deep_pawn_push(Move m) const;
|
||||
bool move_is_pawn_push_to_7th(Move m) const;
|
||||
|
@ -242,6 +244,7 @@ public:
|
|||
// Doing and undoing moves
|
||||
void setStartState(const StateInfo& st);
|
||||
void do_move(Move m, StateInfo& st);
|
||||
void do_move(Move m, StateInfo& st, Bitboard dcCandidates);
|
||||
void undo_move(Move m);
|
||||
void do_null_move(StateInfo& st);
|
||||
void undo_null_move();
|
||||
|
@ -289,11 +292,6 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
enum {
|
||||
Pinned = 1,
|
||||
DcCandidates = 2
|
||||
};
|
||||
|
||||
// Initialization helper functions (used while setting up a position)
|
||||
void clear();
|
||||
void put_piece(Piece p, Square s);
|
||||
|
@ -309,9 +307,6 @@ private:
|
|||
void undo_promotion_move(Move m);
|
||||
void undo_ep_move(Move m);
|
||||
void find_checkers();
|
||||
void find_hidden_checks(Color us, unsigned int types);
|
||||
void find_hidden_checks();
|
||||
void update_hidden_checks(Square from, Square to);
|
||||
|
||||
template<PieceType Piece>
|
||||
void update_checkers(Bitboard* pCheckersBB, Square ksq, Square from, Square to, Bitboard dcCandidates);
|
||||
|
@ -566,19 +561,6 @@ inline Bitboard Position::piece_attacks<KING>(Square s) const {
|
|||
return StepAttackBB[KING][s];
|
||||
}
|
||||
|
||||
inline Bitboard Position::pinned_pieces(Color c) const {
|
||||
return st->pinned[c];
|
||||
}
|
||||
|
||||
inline Bitboard Position::pinned_pieces(Color c, Bitboard& p) const {
|
||||
p = st->pinners[c];
|
||||
return st->pinned[c];
|
||||
}
|
||||
|
||||
inline Bitboard Position::discovered_check_candidates(Color c) const {
|
||||
return st->dcCandidates[c];
|
||||
}
|
||||
|
||||
inline Bitboard Position::checkers() const {
|
||||
return st->checkersBB;
|
||||
}
|
||||
|
|
|
@ -290,8 +290,8 @@ namespace {
|
|||
bool thread_is_available(int slave, int master);
|
||||
bool idle_thread_exists(int master);
|
||||
bool split(const Position &pos, SearchStack *ss, int ply,
|
||||
Value *alpha, Value *beta, Value *bestValue, Depth depth,
|
||||
int *moves, MovePicker *mp, int master, bool pvNode);
|
||||
Value *alpha, Value *beta, Value *bestValue, Depth depth, int *moves,
|
||||
MovePicker *mp, Bitboard dcCandidates, int master, bool pvNode);
|
||||
void wake_sleeping_threads();
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
|
@ -775,6 +775,7 @@ namespace {
|
|||
|
||||
Value alpha = -VALUE_INFINITE;
|
||||
Value beta = VALUE_INFINITE, value;
|
||||
Bitboard dcCandidates = pos.discovered_check_candidates(pos.side_to_move());
|
||||
|
||||
// Loop through all the moves in the root move list
|
||||
for (int i = 0; i < rml.move_count() && !AbortSearch; i++)
|
||||
|
@ -807,7 +808,7 @@ namespace {
|
|||
newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
|
||||
|
||||
// Make the move, and search it
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, dcCandidates);
|
||||
|
||||
if (i < MultiPV)
|
||||
{
|
||||
|
@ -981,6 +982,7 @@ namespace {
|
|||
Move move, movesSearched[256];
|
||||
int moveCount = 0;
|
||||
Value value, bestValue = -VALUE_INFINITE;
|
||||
Bitboard dcCandidates = mp.discovered_check_candidates();
|
||||
Color us = pos.side_to_move();
|
||||
bool isCheck = pos.is_check();
|
||||
bool mateThreat = pos.has_mate_threat(opposite_color(us));
|
||||
|
@ -994,7 +996,7 @@ namespace {
|
|||
assert(move_is_ok(move));
|
||||
|
||||
bool singleReply = (isCheck && mp.number_of_moves() == 1);
|
||||
bool moveIsCheck = pos.move_is_check(move);
|
||||
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
|
||||
bool moveIsCapture = pos.move_is_capture(move);
|
||||
|
||||
movesSearched[moveCount++] = ss[ply].currentMove = move;
|
||||
|
@ -1012,7 +1014,7 @@ namespace {
|
|||
|
||||
// Make and search the move
|
||||
StateInfo st;
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, dcCandidates);
|
||||
|
||||
if (moveCount == 1) // The first move in list is the PV
|
||||
value = -search_pv(pos, ss, -beta, -alpha, newDepth, ply+1, threadID);
|
||||
|
@ -1087,7 +1089,7 @@ namespace {
|
|||
&& !AbortSearch
|
||||
&& !thread_should_stop(threadID)
|
||||
&& split(pos, ss, ply, &alpha, &beta, &bestValue, depth,
|
||||
&moveCount, &mp, threadID, true))
|
||||
&moveCount, &mp, dcCandidates, threadID, true))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1281,6 +1283,7 @@ namespace {
|
|||
Move move, movesSearched[256];
|
||||
int moveCount = 0;
|
||||
Value value, bestValue = -VALUE_INFINITE;
|
||||
Bitboard dcCandidates = mp.discovered_check_candidates();
|
||||
Value futilityValue = VALUE_NONE;
|
||||
bool useFutilityPruning = UseFutilityPruning
|
||||
&& depth < SelectiveDepth
|
||||
|
@ -1295,7 +1298,7 @@ namespace {
|
|||
assert(move_is_ok(move));
|
||||
|
||||
bool singleReply = (isCheck && mp.number_of_moves() == 1);
|
||||
bool moveIsCheck = pos.move_is_check(move);
|
||||
bool moveIsCheck = pos.move_is_check(move, dcCandidates);
|
||||
bool moveIsCapture = pos.move_is_capture(move);
|
||||
|
||||
movesSearched[moveCount++] = ss[ply].currentMove = move;
|
||||
|
@ -1335,7 +1338,7 @@ namespace {
|
|||
|
||||
// Make and search the move
|
||||
StateInfo st;
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, dcCandidates);
|
||||
|
||||
// Try to reduce non-pv search depth by one ply if move seems not problematic,
|
||||
// if the move fails high will be re-searched at full depth.
|
||||
|
@ -1382,7 +1385,7 @@ namespace {
|
|||
&& !AbortSearch
|
||||
&& !thread_should_stop(threadID)
|
||||
&& split(pos, ss, ply, &beta, &beta, &bestValue, depth, &moveCount,
|
||||
&mp, threadID, false))
|
||||
&mp, dcCandidates, threadID, false))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1467,6 +1470,7 @@ namespace {
|
|||
MovePicker mp = MovePicker(pos, pvNode, MOVE_NONE, EmptySearchStack, depth, isCheck ? NULL : &ei);
|
||||
Move move;
|
||||
int moveCount = 0;
|
||||
Bitboard dcCandidates = mp.discovered_check_candidates();
|
||||
Color us = pos.side_to_move();
|
||||
bool enoughMaterial = pos.non_pawn_material(us) > RookValueMidgame;
|
||||
|
||||
|
@ -1486,7 +1490,7 @@ namespace {
|
|||
&& !isCheck
|
||||
&& !pvNode
|
||||
&& !move_promotion(move)
|
||||
&& !pos.move_is_check(move)
|
||||
&& !pos.move_is_check(move, dcCandidates)
|
||||
&& !pos.move_is_passed_pawn_push(move))
|
||||
{
|
||||
Value futilityValue = staticValue
|
||||
|
@ -1514,7 +1518,7 @@ namespace {
|
|||
|
||||
// Make and search the move.
|
||||
StateInfo st;
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, dcCandidates);
|
||||
Value value = -qsearch(pos, ss, -beta, -alpha, depth-OnePly, ply+1, threadID);
|
||||
pos.undo_move(move);
|
||||
|
||||
|
@ -1581,7 +1585,7 @@ namespace {
|
|||
{
|
||||
assert(move_is_ok(move));
|
||||
|
||||
bool moveIsCheck = pos.move_is_check(move);
|
||||
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
|
||||
bool moveIsCapture = pos.move_is_capture(move);
|
||||
|
||||
lock_grab(&(sp->lock));
|
||||
|
@ -1606,7 +1610,7 @@ namespace {
|
|||
|
||||
// Make and search the move.
|
||||
StateInfo st;
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, sp->dcCandidates);
|
||||
|
||||
// Try to reduce non-pv search depth by one ply if move seems not problematic,
|
||||
// if the move fails high will be re-searched at full depth.
|
||||
|
@ -1691,7 +1695,7 @@ namespace {
|
|||
&& !thread_should_stop(threadID)
|
||||
&& (move = sp->mp->get_next_move(sp->lock)) != MOVE_NONE)
|
||||
{
|
||||
bool moveIsCheck = pos.move_is_check(move);
|
||||
bool moveIsCheck = pos.move_is_check(move, sp->dcCandidates);
|
||||
bool moveIsCapture = pos.move_is_capture(move);
|
||||
|
||||
assert(move_is_ok(move));
|
||||
|
@ -1715,7 +1719,7 @@ namespace {
|
|||
|
||||
// Make and search the move.
|
||||
StateInfo st;
|
||||
pos.do_move(move, st);
|
||||
pos.do_move(move, st, sp->dcCandidates);
|
||||
|
||||
// Try to reduce non-pv search depth by one ply if move seems not problematic,
|
||||
// if the move fails high will be re-searched at full depth.
|
||||
|
@ -2671,8 +2675,9 @@ namespace {
|
|||
// splitPoint->cpus becomes 0), split() returns true.
|
||||
|
||||
bool split(const Position &p, SearchStack *sstck, int ply,
|
||||
Value *alpha, Value *beta, Value *bestValue,
|
||||
Depth depth, int *moves, MovePicker *mp, int master, bool pvNode) {
|
||||
Value *alpha, Value *beta, Value *bestValue, Depth depth, int *moves,
|
||||
MovePicker *mp, Bitboard dcCandidates, int master, bool pvNode) {
|
||||
|
||||
assert(p.is_ok());
|
||||
assert(sstck != NULL);
|
||||
assert(ply >= 0 && ply < PLY_MAX);
|
||||
|
@ -2708,6 +2713,7 @@ namespace {
|
|||
splitPoint->alpha = pvNode? *alpha : (*beta - 1);
|
||||
splitPoint->beta = *beta;
|
||||
splitPoint->pvNode = pvNode;
|
||||
splitPoint->dcCandidates = dcCandidates;
|
||||
splitPoint->bestValue = *bestValue;
|
||||
splitPoint->master = master;
|
||||
splitPoint->mp = mp;
|
||||
|
|
Loading…
Add table
Reference in a new issue