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>
/// 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));
/// 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());
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);
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);
// 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;
/// 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);
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
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));
}
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)
else
phaseIndex = (noCaptures ? NoMovesPhaseIndex : QsearchWithoutChecksPhaseIndex);
+ dc = p.discovered_check_candidates(us);
+ pinned = p.pinned_pieces(us);
+
finished = false;
}
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;
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;
case PH_EVASIONS:
assert(pos.is_check());
- numOfMoves = generate_evasions(pos, moves);
+ numOfMoves = generate_evasions(pos, moves, pinned);
score_evasions();
movesPicked = 0;
break;
break;
case PH_QCHECKS:
- numOfMoves = generate_checks(pos, moves);
+ numOfMoves = generate_checks(pos, moves, dc);
movesPicked = 0;
break;
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;
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;
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;
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;
{
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;
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();
const Position& pos;
Move ttMove, mateKiller, killer1, killer2;
+ Bitboard pinned, dc;
MoveStack moves[256], badCaptures[64];
bool pvNode;
Depth depth;
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)
castleRightsMask[make_square(initialQRFile, RANK_8)] ^= BLACK_OOO;
find_checkers();
- find_hidden_checks();
st->key = compute_key();
st->pawnKey = compute_pawn_key();
}
+/// 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
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);
-}
+/// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
-void Position::find_hidden_checks() {
+bool Position::pl_move_is_legal(Move m) const {
- for (Color c = WHITE; c <= BLACK; c++)
- find_hidden_checks(c, Pinned | DcCandidates);
+ return pl_move_is_legal(m, pinned_pieces(side_to_move()));
}
-
-/// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
-
-bool Position::pl_move_is_legal(Move m) const {
+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.
// 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)));
}
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));
}
-/// 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.
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
// Update checkers BB
st->checkersBB = attacks_to(king_square(them), us);
-
- // Update hidden checks
- find_hidden_checks();
}
// Update checkers BB
st->checkersBB = attacks_to(king_square(them), us);
-
- // Update hidden checks
- find_hidden_checks();
}
// Update checkers BB
st->checkersBB = attacks_to(king_square(them), us);
-
- // Update hidden checks
- find_hidden_checks();
}
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);
| (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;
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)))
{
/// 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;
// 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;
// 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();
private:
- enum {
- Pinned = 1,
- DcCandidates = 2
- };
-
// Initialization helper functions (used while setting up a position)
void clear();
void put_piece(Piece p, Square s);
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);
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;
}
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)
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++)
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)
{
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));
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;
// 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);
&& !AbortSearch
&& !thread_should_stop(threadID)
&& split(pos, ss, ply, &alpha, &beta, &bestValue, depth,
- &moveCount, &mp, threadID, true))
+ &moveCount, &mp, dcCandidates, threadID, true))
break;
}
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
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;
// 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.
&& !AbortSearch
&& !thread_should_stop(threadID)
&& split(pos, ss, ply, &beta, &beta, &bestValue, depth, &moveCount,
- &mp, threadID, false))
+ &mp, dcCandidates, threadID, false))
break;
}
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;
&& !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
// 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);
{
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));
// 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.
&& !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));
// 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.
// 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);
splitPoint->alpha = pvNode? *alpha : (*beta - 1);
splitPoint->beta = *beta;
splitPoint->pvNode = pvNode;
+ splitPoint->dcCandidates = dcCandidates;
splitPoint->bestValue = *bestValue;
splitPoint->master = master;
splitPoint->mp = mp;