along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstring> // For std::memset
return d > 17 ? 0 : 29 * d * d + 138 * d - 134;
}
- // Add a small random component to draw evaluations to keep search dynamic
- // and to avoid 3fold-blindness.
+ // Add a small random component to draw evaluations to avoid 3fold-blindness
Value value_draw(Depth depth, Thread* thisThread) {
return depth < 4 ? VALUE_DRAW
- : VALUE_DRAW + Value(2 * (thisThread->nodes.load(std::memory_order_relaxed) % 2) - 1);
+ : VALUE_DRAW + Value(2 * (thisThread->nodes & 1) - 1);
}
// Skill structure is used to implement strength limit
void update_quiet_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietCount, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCount, int bonus);
- inline bool gives_check(const Position& pos, Move move) {
- Color us = pos.side_to_move();
- return type_of(move) == NORMAL && !(pos.blockers_for_king(~us) & pos.pieces(us))
- ? pos.check_squares(type_of(pos.moved_piece(move))) & to_sq(move)
- : pos.gives_check(move);
- }
-
// perft() is our utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
template<bool Root>
Time.availableNodes = 0;
TT.clear();
Threads.clear();
- Tablebases::init(Options["SyzygyPath"]); // Free up mapped files
+ Tablebases::init(Options["SyzygyPath"]); // Free mapped files
}
-/// MainThread::search() is called by the main thread when the program receives
-/// the UCI 'go' command. It searches from the root position and outputs the "bestmove".
+/// MainThread::search() is started when the program receives the UCI 'go'
+/// command. It searches from the root position and outputs the "bestmove".
void MainThread::search() {
if (Limits.npmsec)
Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
- // Check if there are threads with a better score than main thread
Thread* bestThread = this;
+
+ // Check if there are threads with a better score than main thread
if ( Options["MultiPV"] == 1
&& !Limits.depth
&& !Skill(Options["Skill Level"]).enabled()
void Thread::search() {
- // To allow access to (ss-5) up to (ss+2), the stack must be oversized.
+ // To allow access to (ss-7) up to (ss+2), the stack must be oversized.
// The former is needed to allow update_continuation_histories(ss-1, ...),
- // which accesses its argument at ss-4, also near the root.
+ // which accesses its argument at ss-6, also near the root.
// The latter is needed for statScores and killer initialization.
Stack stack[MAX_PLY+10], *ss = stack+7;
Move pv[MAX_PLY+1];
: Options["Analysis Contempt"] == "Black" && us == WHITE ? -ct
: ct;
- // In evaluate.cpp the evaluation is from the white point of view
+ // Evaluation score is from the white point of view
contempt = (us == WHITE ? make_score(ct, ct / 2)
: -make_score(ct, ct / 2));
&& !mainThread->stopOnPonderhit)
{
double fallingEval = (306 + 9 * (mainThread->previousScore - bestValue)) / 581.0;
- fallingEval = std::max(0.5, std::min(1.5, fallingEval));
+ fallingEval = clamp(fallingEval, 0.5, 1.5);
// If the bestMove is stable over several iterations, reduce time accordingly
timeReduction = lastBestMoveDepth + 10 * ONE_PLY < completedDepth ? 1.95 : 1.0;
: ttHit ? tte->move() : MOVE_NONE;
ttPv = (ttHit && tte->is_pv()) || (PvNode && depth > 4 * ONE_PLY);
+ // if position has been searched at higher depths and we are shuffling, return value_draw
+ if (pos.rule50_count() > 36
+ && ss->ply > 36
+ && depth < 3 * ONE_PLY
+ && ttHit
+ && tte->depth() > depth
+ && pos.count<PAWN>() > 0)
+ return VALUE_DRAW;
+
// At non-PV nodes we check for an early TT cutoff
if ( !PvNode
&& ttHit
}
// Step 11. Internal iterative deepening (~2 Elo)
- if ( depth >= 8 * ONE_PLY
- && !ttMove)
+ if (depth >= 8 * ONE_PLY && !ttMove)
{
search<NT>(pos, ss, alpha, beta, depth - 7 * ONE_PLY, cutNode);
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
nullptr, (ss-4)->continuationHistory,
nullptr, (ss-6)->continuationHistory };
+
Move countermove = thisThread->counterMoves[pos.piece_on(prevSq)][prevSq];
MovePicker mp(pos, ttMove, depth, &thisThread->mainHistory,
contHist,
countermove,
ss->killers);
- value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
+ value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc
moveCountPruning = false;
ttCapture = ttMove && pos.capture_or_promotion(ttMove);
extension = DEPTH_ZERO;
captureOrPromotion = pos.capture_or_promotion(move);
movedPiece = pos.moved_piece(move);
- givesCheck = gives_check(pos, move);
+ givesCheck = pos.gives_check(move);
// Step 13. Extensions (~70 Elo)
&& (pos.blockers_for_king(~us) & from_sq(move) || pos.see_ge(move)))
extension = ONE_PLY;
+ // Shuffle extension
+ else if(pos.rule50_count() > 14 && ss->ply > 14 && depth < 3 * ONE_PLY && PvNode)
+ extension = ONE_PLY;
+
// Castling extension
else if (type_of(move) == CASTLING)
extension = ONE_PLY;
&& bestValue > VALUE_MATED_IN_MAX_PLY)
{
// Skip quiet moves if movecount exceeds our FutilityMoveCount threshold
- moveCountPruning = moveCount >= futility_move_count(improving,depth / ONE_PLY);
+ moveCountPruning = moveCount >= futility_move_count(improving, depth / ONE_PLY);
if ( !captureOrPromotion
&& !givesCheck
{
assert(is_ok(move));
- givesCheck = gives_check(pos, move);
+ givesCheck = pos.gives_check(move);
moveCount++;