From: Stéphane Nicolet Date: Sun, 3 Jul 2016 08:35:44 +0000 (+0200) Subject: Move CheckInfo under StateInfo X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=805afcbf3d5db39c85b759232cfb99ab0a250311 Move CheckInfo under StateInfo This greately simplifies usage because hides to the search the implementation specific CheckInfo. This is based on the work done by Marco in pull request #716, implementing on top of it the ideas in the discussion: caching the calls to slider_blockers() in the CheckInfo structure, and simplifying the slider_blockers() function by removing its first parameter. Compared to master, bench is identical but the number of calls to slider_blockers() during bench goes down from 22461515 to 18853422, hopefully being a little bit faster overall. archlinux, gcc-6 make profile-build ARCH=x86-64-bmi2 50 runs each bench: base = 2356320 +/- 981 test = 2403811 +/- 981 diff = 47490 +/- 1828 speedup = 0.0202 P(speedup > 0) = 1.0000 perft 6: base = 175498484 +/- 429925 test = 183997959 +/- 429925 diff = 8499474 +/- 469401 speedup = 0.0484 P(speedup > 0) = 1.0000 perft 7 (but only 10 runs): base = 185403228 +/- 468705 test = 188777591 +/- 468705 diff = 3374363 +/- 476687 speedup = 0.0182 P(speedup > 0) = 1.0000 $ ./pyshbench ../Stockfish/master ../Stockfish/test 20 run base test diff ... base = 2501728 +/- 182034 test = 2532997 +/- 182034 diff = 31268 +/- 5116 speedup = 0.0125 P(speedup > 0) = 1.0000 No functional change. --- diff --git a/src/evaluate.cpp b/src/evaluate.cpp index 1f5e906d..8651ab27 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -359,7 +359,7 @@ namespace { if (Pt == QUEEN) { // Penalty if any relative pin or discovered attack against the queen - if (pos.slider_blockers(pos.pieces(), pos.pieces(Them, ROOK, BISHOP), s)) + if (pos.slider_blockers(pos.pieces(Them, ROOK, BISHOP), s)) score -= WeakQueen; } } diff --git a/src/movegen.cpp b/src/movegen.cpp index 3622f18e..3a69f8ab 100644 --- a/src/movegen.cpp +++ b/src/movegen.cpp @@ -26,7 +26,7 @@ namespace { template - ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us, const CheckInfo* ci) { + ExtMove* generate_castling(const Position& pos, ExtMove* moveList, Color us) { static const bool KingSide = (Cr == WHITE_OO || Cr == BLACK_OO); @@ -57,10 +57,8 @@ namespace { Move m = make(kfrom, rfrom); - if (Checks && !pos.gives_check(m, *ci)) + if (Checks && !pos.gives_check(m)) return moveList; - else - (void)ci; // Silence a warning under MSVC *moveList++ = m; return moveList; @@ -68,7 +66,7 @@ namespace { template - ExtMove* make_promotions(ExtMove* moveList, Square to, const CheckInfo* ci) { + ExtMove* make_promotions(ExtMove* moveList, Square to, Square ksq) { if (Type == CAPTURES || Type == EVASIONS || Type == NON_EVASIONS) *moveList++ = make(to - Delta, to, QUEEN); @@ -82,18 +80,15 @@ namespace { // Knight promotion is the only promotion that can give a direct check // that's not already included in the queen promotion. - if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ci->ksq)) + if (Type == QUIET_CHECKS && (StepAttacksBB[W_KNIGHT][to] & ksq)) *moveList++ = make(to - Delta, to, KNIGHT); - else - (void)ci; // Silence a warning under MSVC return moveList; } template - ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, - Bitboard target, const CheckInfo* ci) { + ExtMove* generate_pawn_moves(const Position& pos, ExtMove* moveList, Bitboard target) { // Compute our parametrized parameters at compile time, named according to // the point of view of white side. @@ -129,16 +124,19 @@ namespace { if (Type == QUIET_CHECKS) { - b1 &= pos.attacks_from(ci->ksq, Them); - b2 &= pos.attacks_from(ci->ksq, Them); + Square ksq = pos.square(Them); + + b1 &= pos.attacks_from(ksq, Them); + b2 &= pos.attacks_from(ksq, Them); // Add pawn pushes which give discovered check. This is possible only // if the pawn is not on the same file as the enemy king, because we // don't generate captures. Note that a possible discovery check // promotion has been already generated amongst the captures. - if (pawnsNotOn7 & ci->dcCandidates) + Bitboard dcCandidates = pos.discovered_check_candidates(); + if (pawnsNotOn7 & dcCandidates) { - Bitboard dc1 = shift_bb(pawnsNotOn7 & ci->dcCandidates) & emptySquares & ~file_bb(ci->ksq); + Bitboard dc1 = shift_bb(pawnsNotOn7 & dcCandidates) & emptySquares & ~file_bb(ksq); Bitboard dc2 = shift_bb(dc1 & TRank3BB) & emptySquares; b1 |= dc1; @@ -172,14 +170,16 @@ namespace { Bitboard b2 = shift_bb(pawnsOn7) & enemies; Bitboard b3 = shift_bb(pawnsOn7) & emptySquares; + Square ksq = pos.square(Them); + while (b1) - moveList = make_promotions(moveList, pop_lsb(&b1), ci); + moveList = make_promotions(moveList, pop_lsb(&b1), ksq); while (b2) - moveList = make_promotions(moveList, pop_lsb(&b2), ci); + moveList = make_promotions(moveList, pop_lsb(&b2), ksq); while (b3) - moveList = make_promotions(moveList, pop_lsb(&b3), ci); + moveList = make_promotions(moveList, pop_lsb(&b3), ksq); } // Standard and en-passant captures @@ -225,7 +225,7 @@ namespace { template ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us, - Bitboard target, const CheckInfo* ci) { + Bitboard target) { assert(Pt != KING && Pt != PAWN); @@ -236,17 +236,17 @@ namespace { if (Checks) { if ( (Pt == BISHOP || Pt == ROOK || Pt == QUEEN) - && !(PseudoAttacks[Pt][from] & target & ci->checkSquares[Pt])) + && !(PseudoAttacks[Pt][from] & target & pos.check_info().checkSquares[Pt])) continue; - if (ci->dcCandidates & from) + if (pos.discovered_check_candidates() & from) continue; } Bitboard b = pos.attacks_from(from) & target; if (Checks) - b &= ci->checkSquares[Pt]; + b &= pos.check_info().checkSquares[Pt]; while (b) *moveList++ = make_move(from, pop_lsb(&b)); @@ -257,16 +257,15 @@ namespace { template - ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target, - const CheckInfo* ci = nullptr) { + ExtMove* generate_all(const Position& pos, ExtMove* moveList, Bitboard target) { const bool Checks = Type == QUIET_CHECKS; - moveList = generate_pawn_moves(pos, moveList, target, ci); - moveList = generate_moves(pos, moveList, Us, target, ci); - moveList = generate_moves(pos, moveList, Us, target, ci); - moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target, ci); - moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target, ci); + moveList = generate_pawn_moves(pos, moveList, target); + moveList = generate_moves(pos, moveList, Us, target); + moveList = generate_moves(pos, moveList, Us, target); + moveList = generate_moves< ROOK, Checks>(pos, moveList, Us, target); + moveList = generate_moves< QUEEN, Checks>(pos, moveList, Us, target); if (Type != QUIET_CHECKS && Type != EVASIONS) { @@ -280,13 +279,13 @@ namespace { { if (pos.is_chess960()) { - moveList = generate_castling::right, Checks, true>(pos, moveList, Us, ci); - moveList = generate_castling::right, Checks, true>(pos, moveList, Us, ci); + moveList = generate_castling::right, Checks, true>(pos, moveList, Us); + moveList = generate_castling::right, Checks, true>(pos, moveList, Us); } else { - moveList = generate_castling::right, Checks, false>(pos, moveList, Us, ci); - moveList = generate_castling::right, Checks, false>(pos, moveList, Us, ci); + moveList = generate_castling::right, Checks, false>(pos, moveList, Us); + moveList = generate_castling::right, Checks, false>(pos, moveList, Us); } } @@ -335,8 +334,7 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { assert(!pos.checkers()); Color us = pos.side_to_move(); - CheckInfo ci(pos); - Bitboard dc = ci.dcCandidates; + Bitboard dc = pos.discovered_check_candidates(); while (dc) { @@ -349,14 +347,14 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { Bitboard b = pos.attacks_from(Piece(pt), from) & ~pos.pieces(); if (pt == KING) - b &= ~PseudoAttacks[QUEEN][ci.ksq]; + b &= ~PseudoAttacks[QUEEN][pos.square(~us)]; while (b) *moveList++ = make_move(from, pop_lsb(&b)); } - return us == WHITE ? generate_all(pos, moveList, ~pos.pieces(), &ci) - : generate_all(pos, moveList, ~pos.pieces(), &ci); + return us == WHITE ? generate_all(pos, moveList, ~pos.pieces()) + : generate_all(pos, moveList, ~pos.pieces()); } @@ -411,7 +409,7 @@ ExtMove* generate(const Position& pos, ExtMove* moveList) { : generate(pos, moveList); while (cur != moveList) if ( (pinned || from_sq(*cur) == ksq || type_of(*cur) == ENPASSANT) - && !pos.legal(*cur, pinned)) + && !pos.legal(*cur)) *cur = (--moveList)->move; else ++cur; diff --git a/src/position.cpp b/src/position.cpp index 6022518e..5b2efabe 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -81,25 +81,6 @@ PieceType min_attacker(const Bitboard*, Square, Bitboard, Bitboard&, Bitbo } // namespace -/// CheckInfo constructor - -CheckInfo::CheckInfo(const Position& pos) { - - Color them = ~pos.side_to_move(); - ksq = pos.square(them); - - pinned = pos.pinned_pieces(pos.side_to_move()); - dcCandidates = pos.discovered_check_candidates(); - - checkSquares[PAWN] = pos.attacks_from(ksq, them); - checkSquares[KNIGHT] = pos.attacks_from(ksq); - checkSquares[BISHOP] = pos.attacks_from(ksq); - checkSquares[ROOK] = pos.attacks_from(ksq); - checkSquares[QUEEN] = checkSquares[BISHOP] | checkSquares[ROOK]; - checkSquares[KING] = 0; -} - - /// operator<<(Position) returns an ASCII representation of the position std::ostream& operator<<(std::ostream& os, const Position& pos) { @@ -311,6 +292,24 @@ void Position::set_castling_right(Color c, Square rfrom) { } +/// Position::set_check_info() sets king attacks to detect if a move gives check + +void Position::set_check_info(CheckInfo* ci) const { + + ci->blockersForKing[WHITE] = slider_blockers(pieces(BLACK), square(WHITE)); + ci->blockersForKing[BLACK] = slider_blockers(pieces(WHITE), square(BLACK)); + + Square ksq = ci->ksq = square(~sideToMove); + + ci->checkSquares[PAWN] = attacks_from(ksq, ~sideToMove); + ci->checkSquares[KNIGHT] = attacks_from(ksq); + ci->checkSquares[BISHOP] = attacks_from(ksq); + ci->checkSquares[ROOK] = attacks_from(ksq); + ci->checkSquares[QUEEN] = ci->checkSquares[BISHOP] | ci->checkSquares[ROOK]; + ci->checkSquares[KING] = 0; +} + + /// Position::set_state() computes the hash keys of the position, and other /// data that once computed is updated incrementally as moves are made. /// The function is only used when a new position is set up, and to verify @@ -321,9 +320,10 @@ void Position::set_state(StateInfo* si) const { si->key = si->pawnKey = si->materialKey = 0; si->nonPawnMaterial[WHITE] = si->nonPawnMaterial[BLACK] = VALUE_ZERO; si->psq = SCORE_ZERO; - si->checkersBB = attackers_to(square(sideToMove)) & pieces(~sideToMove); + set_check_info(&si->ci); + for (Bitboard b = pieces(); b; ) { Square s = pop_lsb(&b); @@ -420,14 +420,14 @@ Phase Position::game_phase() const { } -/// Position::slider_blockers() returns a bitboard of all the pieces in 'target' that +/// Position::slider_blockers() returns a bitboard of all the pieces (both colors) that /// are blocking attacks on the square 's' from 'sliders'. A piece blocks a slider /// if removing that piece from the board would result in a position where square 's' /// is attacked. For example, a king-attack blocking piece can be either a pinned or /// a discovered check piece, according if its color is the opposite or the same of /// the color of the slider. -Bitboard Position::slider_blockers(Bitboard target, Bitboard sliders, Square s) const { +Bitboard Position::slider_blockers(Bitboard sliders, Square s) const { Bitboard b, pinners, result = 0; @@ -440,7 +440,7 @@ Bitboard Position::slider_blockers(Bitboard target, Bitboard sliders, Square s) b = between_bb(s, pop_lsb(&pinners)) & pieces(); if (!more_than_one(b)) - result |= b & target; + result |= b; } return result; } @@ -462,10 +462,9 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied) const { /// Position::legal() tests whether a pseudo-legal move is legal -bool Position::legal(Move m, Bitboard pinned) const { +bool Position::legal(Move m) const { assert(is_ok(m)); - assert(pinned == pinned_pieces(sideToMove)); Color us = sideToMove; Square from = from_sq(m); @@ -500,7 +499,7 @@ bool Position::legal(Move m, Bitboard pinned) 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 !(pinned & from) + return !(pinned_pieces(us) & from) || aligned(from, to_sq(m), square(us)); } @@ -579,22 +578,21 @@ bool Position::pseudo_legal(const Move m) const { /// Position::gives_check() tests whether a pseudo-legal move gives a check -bool Position::gives_check(Move m, const CheckInfo& ci) const { +bool Position::gives_check(Move m) const { assert(is_ok(m)); - assert(ci.dcCandidates == discovered_check_candidates()); assert(color_of(moved_piece(m)) == sideToMove); Square from = from_sq(m); Square to = to_sq(m); // Is there a direct check? - if (ci.checkSquares[type_of(piece_on(from))] & to) + if (st->ci.checkSquares[type_of(piece_on(from))] & to) return true; // Is there a discovered check? - if ( (ci.dcCandidates & from) - && !aligned(from, to, ci.ksq)) + if ( (discovered_check_candidates() & from) + && !aligned(from, to, st->ci.ksq)) return true; switch (type_of(m)) @@ -603,7 +601,7 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const { return false; case PROMOTION: - return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & ci.ksq; + return attacks_bb(Piece(promotion_type(m)), to, pieces() ^ from) & st->ci.ksq; // En passant capture with check? We have already handled the case // of direct checks and ordinary discovered check, so the only case we @@ -614,8 +612,8 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const { Square capsq = make_square(file_of(to), rank_of(from)); Bitboard b = (pieces() ^ from ^ capsq) | to; - return (attacks_bb< ROOK>(ci.ksq, b) & pieces(sideToMove, QUEEN, ROOK)) - | (attacks_bb(ci.ksq, b) & pieces(sideToMove, QUEEN, BISHOP)); + return (attacks_bb< ROOK>(st->ci.ksq, b) & pieces(sideToMove, QUEEN, ROOK)) + | (attacks_bb(st->ci.ksq, b) & pieces(sideToMove, QUEEN, BISHOP)); } case CASTLING: { @@ -624,8 +622,8 @@ bool Position::gives_check(Move m, const CheckInfo& ci) const { Square kto = relative_square(sideToMove, rfrom > kfrom ? SQ_G1 : SQ_C1); Square rto = relative_square(sideToMove, rfrom > kfrom ? SQ_F1 : SQ_D1); - return (PseudoAttacks[ROOK][rto] & ci.ksq) - && (attacks_bb(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & ci.ksq); + return (PseudoAttacks[ROOK][rto] & st->ci.ksq) + && (attacks_bb(rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & st->ci.ksq); } default: assert(false); @@ -801,6 +799,9 @@ void Position::do_move(Move m, StateInfo& newSt, bool givesCheck) { sideToMove = ~sideToMove; + // Update CheckInfo + set_check_info(&st->ci); + assert(pos_is_ok()); } @@ -914,6 +915,8 @@ void Position::do_null_move(StateInfo& newSt) { sideToMove = ~sideToMove; + set_check_info(&st->ci); + assert(pos_is_ok()); } diff --git a/src/position.h b/src/position.h index b2538e96..d6efe711 100644 --- a/src/position.h +++ b/src/position.h @@ -41,15 +41,12 @@ namespace PSQT { void init(); } -/// CheckInfo struct is initialized at constructor time and keeps info used to -/// detect if a move gives check. -struct CheckInfo { +/// CheckInfo struct keeps info used to detect if a move gives check - explicit CheckInfo(const Position&); +struct CheckInfo { - Bitboard dcCandidates; - Bitboard pinned; + Bitboard blockersForKing[COLOR_NB]; Bitboard checkSquares[PIECE_TYPE_NB]; Square ksq; }; @@ -76,6 +73,7 @@ struct StateInfo { Bitboard checkersBB; PieceType capturedType; StateInfo* previous; + CheckInfo ci; }; // In a std::deque references to elements are unaffected upon resizing @@ -124,6 +122,7 @@ public: Bitboard checkers() const; Bitboard discovered_check_candidates() const; Bitboard pinned_pieces(Color c) const; + const CheckInfo& check_info() const; // Attacks to/from a given square Bitboard attackers_to(Square s) const; @@ -131,14 +130,14 @@ public: Bitboard attacks_from(Piece pc, Square s) const; template Bitboard attacks_from(Square s) const; template Bitboard attacks_from(Square s, Color c) const; - Bitboard slider_blockers(Bitboard target, Bitboard sliders, Square s) const; + Bitboard slider_blockers(Bitboard sliders, Square s) const; // Properties of moves - bool legal(Move m, Bitboard pinned) const; + bool legal(Move m) const; bool pseudo_legal(const Move m) const; bool capture(Move m) const; bool capture_or_promotion(Move m) const; - bool gives_check(Move m, const CheckInfo& ci) const; + bool gives_check(Move m) const; bool advanced_pawn_push(Move m) const; Piece moved_piece(Move m) const; PieceType captured_piece_type() const; @@ -185,6 +184,7 @@ private: // Initialization helpers (used while setting up a position) void set_castling_right(Color c, Square rfrom); void set_state(StateInfo* si) const; + void set_check_info(CheckInfo* ci) const; // Other helpers void put_piece(Color c, PieceType pt, Square s); @@ -311,11 +311,15 @@ inline Bitboard Position::checkers() const { } inline Bitboard Position::discovered_check_candidates() const { - return slider_blockers(pieces(sideToMove), pieces(sideToMove), square(~sideToMove)); + return st->ci.blockersForKing[~sideToMove] & pieces(sideToMove); } inline Bitboard Position::pinned_pieces(Color c) const { - return slider_blockers(pieces(c), pieces(~c), square(c)); + return st->ci.blockersForKing[c] & pieces(c); +} + +inline const CheckInfo& Position::check_info() const { + return st->ci; } inline bool Position::pawn_passed(Color c, Square s) const { diff --git a/src/search.cpp b/src/search.cpp index 789a4a2f..ce8c4b7a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -113,8 +113,8 @@ namespace { std::copy(newPv.begin(), newPv.begin() + 3, pv); StateInfo st[2]; - pos.do_move(newPv[0], st[0], pos.gives_check(newPv[0], CheckInfo(pos))); - pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1], CheckInfo(pos))); + pos.do_move(newPv[0], st[0], pos.gives_check(newPv[0])); + pos.do_move(newPv[1], st[1], pos.gives_check(newPv[1])); expectedPosKey = pos.key(); pos.undo_move(newPv[1]); pos.undo_move(newPv[0]); @@ -228,7 +228,6 @@ uint64_t Search::perft(Position& pos, Depth depth) { StateInfo st; uint64_t cnt, nodes = 0; - CheckInfo ci(pos); const bool leaf = (depth == 2 * ONE_PLY); for (const auto& m : MoveList(pos)) @@ -237,7 +236,7 @@ uint64_t Search::perft(Position& pos, Depth depth) { cnt = 1, nodes++; else { - pos.do_move(m, st, pos.gives_check(m, ci)); + pos.do_move(m, st, pos.gives_check(m)); cnt = leaf ? MoveList(pos).size() : perft(pos, depth - ONE_PLY); nodes += cnt; pos.undo_move(m); @@ -804,14 +803,13 @@ namespace { assert((ss-1)->currentMove != MOVE_NULL); MovePicker mp(pos, ttMove, PieceValue[MG][pos.captured_piece_type()]); - CheckInfo ci(pos); while ((move = mp.next_move()) != MOVE_NONE) - if (pos.legal(move, ci.pinned)) + if (pos.legal(move)) { ss->currentMove = move; ss->counterMoves = &CounterMoveHistory[pos.moved_piece(move)][to_sq(move)]; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); value = -search(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode); pos.undo_move(move); if (value >= rbeta) @@ -840,7 +838,6 @@ moves_loop: // When in check search starts from here const CounterMoveStats* fmh2 = (ss-4)->counterMoves; MovePicker mp(pos, ttMove, depth, ss); - CheckInfo ci(pos); value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc improving = ss->staticEval >= (ss-2)->staticEval /* || ss->staticEval == VALUE_NONE Already implicit in the previous condition */ @@ -885,9 +882,9 @@ moves_loop: // When in check search starts from here captureOrPromotion = pos.capture_or_promotion(move); moved_piece = pos.moved_piece(move); - givesCheck = type_of(move) == NORMAL && !ci.dcCandidates - ? ci.checkSquares[type_of(pos.piece_on(from_sq(move)))] & to_sq(move) - : pos.gives_check(move, ci); + givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() + ? pos.check_info().checkSquares[type_of(pos.piece_on(from_sq(move)))] & to_sq(move) + : pos.gives_check(move); moveCountPruning = depth < 16 * ONE_PLY && moveCount >= FutilityMoveCounts[improving][depth / ONE_PLY]; @@ -906,7 +903,7 @@ moves_loop: // When in check search starts from here if ( singularExtensionNode && move == ttMove && !extension - && pos.legal(move, ci.pinned)) + && pos.legal(move)) { Value rBeta = ttValue - 2 * depth / ONE_PLY; Depth d = (depth / (2 * ONE_PLY)) * ONE_PLY; @@ -966,7 +963,7 @@ moves_loop: // When in check search starts from here prefetch(TT.first_entry(pos.key_after(move))); // Check for legality just before making the move - if (!rootNode && !pos.legal(move, ci.pinned)) + if (!rootNode && !pos.legal(move)) { ss->moveCount = --moveCount; continue; @@ -1281,16 +1278,15 @@ moves_loop: // When in check search starts from here // queen promotions and checks (only if depth >= DEPTH_QS_CHECKS) will // be generated. MovePicker mp(pos, ttMove, depth, to_sq((ss-1)->currentMove)); - CheckInfo ci(pos); // Loop through the moves until no moves remain or a beta cutoff occurs while ((move = mp.next_move()) != MOVE_NONE) { assert(is_ok(move)); - givesCheck = type_of(move) == NORMAL && !ci.dcCandidates - ? ci.checkSquares[type_of(pos.piece_on(from_sq(move)))] & to_sq(move) - : pos.gives_check(move, ci); + givesCheck = type_of(move) == NORMAL && !pos.discovered_check_candidates() + ? pos.check_info().checkSquares[type_of(pos.piece_on(from_sq(move)))] & to_sq(move) + : pos.gives_check(move); // Futility pruning if ( !InCheck @@ -1330,7 +1326,7 @@ moves_loop: // When in check search starts from here prefetch(TT.first_entry(pos.key_after(move))); // Check for legality just before making the move - if (!pos.legal(move, ci.pinned)) + if (!pos.legal(move)) continue; ss->currentMove = move; @@ -1602,7 +1598,7 @@ bool RootMove::extract_ponder_from_tt(Position& pos) assert(pv.size() == 1); - pos.do_move(pv[0], st, pos.gives_check(pv[0], CheckInfo(pos))); + pos.do_move(pv[0], st, pos.gives_check(pv[0])); TTEntry* tte = TT.probe(pos.key(), ttHit); if (ttHit) diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 1b05db9e..6f6627ab 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -361,14 +361,12 @@ static int probe_ab(Position& pos, int alpha, int beta, int *success) } else end = generate(pos, stack); - CheckInfo ci(pos); - for (moves = stack; moves < end; moves++) { Move capture = moves->move; if (!pos.capture(capture) || type_of(capture) == ENPASSANT - || !pos.legal(capture, ci.pinned)) + || !pos.legal(capture)) continue; - pos.do_move(capture, st, pos.gives_check(capture, ci)); + pos.do_move(capture, st, pos.gives_check(capture)); v = -probe_ab(pos, -beta, -alpha, success); pos.undo_move(capture); if (*success == 0) return 0; @@ -424,14 +422,12 @@ int Tablebases::probe_wdl(Position& pos, int *success) else end = generate(pos, stack); - CheckInfo ci(pos); - for (moves = stack; moves < end; moves++) { Move capture = moves->move; if (type_of(capture) != ENPASSANT - || !pos.legal(capture, ci.pinned)) + || !pos.legal(capture)) continue; - pos.do_move(capture, st, pos.gives_check(capture, ci)); + pos.do_move(capture, st, pos.gives_check(capture)); int v0 = -probe_ab(pos, -2, 2, success); pos.undo_move(capture); if (*success == 0) return 0; @@ -444,13 +440,13 @@ int Tablebases::probe_wdl(Position& pos, int *success) for (moves = stack; moves < end; moves++) { Move capture = moves->move; if (type_of(capture) == ENPASSANT) continue; - if (pos.legal(capture, ci.pinned)) break; + if (pos.legal(capture)) break; } if (moves == end && !pos.checkers()) { end = generate(pos, end); for (; moves < end; moves++) { Move move = moves->move; - if (pos.legal(move, ci.pinned)) + if (pos.legal(move)) break; } } @@ -479,7 +475,6 @@ static int probe_dtz_no_ep(Position& pos, int *success) ExtMove stack[192]; ExtMove *moves, *end = NULL; StateInfo st; - CheckInfo ci(pos); if (wdl > 0) { // Generate at least all legal non-capturing pawn moves @@ -492,9 +487,9 @@ static int probe_dtz_no_ep(Position& pos, int *success) for (moves = stack; moves < end; moves++) { Move move = moves->move; if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move) - || !pos.legal(move, ci.pinned)) + || !pos.legal(move)) continue; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); int v = -Tablebases::probe_wdl(pos, success); pos.undo_move(move); if (*success == 0) return 0; @@ -514,9 +509,9 @@ static int probe_dtz_no_ep(Position& pos, int *success) for (moves = stack; moves < end; moves++) { Move move = moves->move; if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN - || !pos.legal(move, ci.pinned)) + || !pos.legal(move)) continue; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); int v = -Tablebases::probe_dtz(pos, success); pos.undo_move(move); if (*success == 0) return 0; @@ -533,9 +528,9 @@ static int probe_dtz_no_ep(Position& pos, int *success) for (moves = stack; moves < end; moves++) { int v; Move move = moves->move; - if (!pos.legal(move, ci.pinned)) + if (!pos.legal(move)) continue; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); if (st.rule50 == 0) { if (wdl == -2) v = -1; else { @@ -604,14 +599,13 @@ int Tablebases::probe_dtz(Position& pos, int *success) end = generate(pos, stack); else end = generate(pos, stack); - CheckInfo ci(pos); for (moves = stack; moves < end; moves++) { Move capture = moves->move; if (type_of(capture) != ENPASSANT - || !pos.legal(capture, ci.pinned)) + || !pos.legal(capture)) continue; - pos.do_move(capture, st, pos.gives_check(capture, ci)); + pos.do_move(capture, st, pos.gives_check(capture)); int v0 = -probe_ab(pos, -2, 2, success); pos.undo_move(capture); if (*success == 0) return 0; @@ -637,13 +631,13 @@ int Tablebases::probe_dtz(Position& pos, int *success) for (moves = stack; moves < end; moves++) { Move move = moves->move; if (type_of(move) == ENPASSANT) continue; - if (pos.legal(move, ci.pinned)) break; + if (pos.legal(move)) break; } if (moves == end && !pos.checkers()) { end = generate(pos, end); for (; moves < end; moves++) { Move move = moves->move; - if (pos.legal(move, ci.pinned)) + if (pos.legal(move)) break; } } @@ -696,12 +690,11 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& if (!success) return false; StateInfo st; - CheckInfo ci(pos); // Probe each move. for (size_t i = 0; i < rootMoves.size(); i++) { Move move = rootMoves[i].pv[0]; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); int v = 0; if (pos.checkers() && dtz > 0) { ExtMove s[192]; @@ -804,14 +797,13 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val score = wdl_to_Value[wdl + 2]; StateInfo st; - CheckInfo ci(pos); int best = -2; // Probe each move. for (size_t i = 0; i < rootMoves.size(); i++) { Move move = rootMoves[i].pv[0]; - pos.do_move(move, st, pos.gives_check(move, ci)); + pos.do_move(move, st, pos.gives_check(move)); int v = -Tablebases::probe_wdl(pos, &success); pos.undo_move(move); if (!success) return false; diff --git a/src/uci.cpp b/src/uci.cpp index 4ae66620..b195b871 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -75,7 +75,7 @@ namespace { while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) { States->push_back(StateInfo()); - pos.do_move(m, States->back(), pos.gives_check(m, CheckInfo(pos))); + pos.do_move(m, States->back(), pos.gives_check(m)); } }