void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus);
void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus);
void update_capture_stats(const Position& pos, Move move, Move* captures, int captureCnt, int bonus);
- bool pv_is_draw(Position& pos);
// 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.
Time.init(Limits, us, rootPos.game_ply());
TT.new_search();
- int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
-
- Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2)
- : -make_score(contempt, contempt / 2));
-
if (rootMoves.empty())
{
rootMoves.emplace_back(MOVE_NONE);
Depth lastBestMoveDepth = DEPTH_ZERO;
MainThread* mainThread = (this == Threads.main() ? Threads.main() : nullptr);
double timeReduction = 1.0;
+ Color us = rootPos.side_to_move();
std::memset(ss-4, 0, 7 * sizeof(Stack));
for (int i = 4; i > 0; i--)
mainThread->bestMoveChanges = 0;
}
- multiPV = Options["MultiPV"];
+ size_t multiPV = Options["MultiPV"];
Skill skill(Options["Skill Level"]);
// When playing with strength handicap enable MultiPV search that we will
multiPV = std::min(multiPV, rootMoves.size());
+ int contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
+ Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2)
+ : -make_score(contempt, contempt / 2));
+
// Iterative deepening loop until requested to stop or the target depth is reached
while ( (rootDepth += ONE_PLY) < DEPTH_MAX
&& !Threads.stop
delta = Value(18);
alpha = std::max(rootMoves[PVIdx].previousScore - delta,-VALUE_INFINITE);
beta = std::min(rootMoves[PVIdx].previousScore + delta, VALUE_INFINITE);
+
+ // Adjust contempt based on current situation
+ contempt = Options["Contempt"] * PawnValueEg / 100; // From centipawns
+ contempt += bestValue > 500 ? 50: // Dynamic contempt
+ bestValue < -500 ? -50:
+ bestValue / 10;
+
+ Eval::Contempt = (us == WHITE ? make_score(contempt, contempt / 2)
+ : -make_score(contempt, contempt / 2));
}
// Start with a small aspiration window and, in the case of a fail
bestValue - mainThread->previousScore };
int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1]));
- Color us = rootPos.side_to_move();
- bool thinkHard = bestValue == VALUE_DRAW
- && Limits.time[us] - Time.elapsed() > Limits.time[~us]
- && ::pv_is_draw(rootPos);
-
- double unstablePvFactor = 1 + mainThread->bestMoveChanges + thinkHard;
+ double unstablePvFactor = 1 + mainThread->bestMoveChanges;
// if the bestMove is stable over several iterations, reduce time for this move,
// the longer the move has been stable, the more.
// Use part of the gained time from a previous stable move for the current move.
timeReduction = 1;
for (int i : {3, 4, 5})
- if (lastBestMoveDepth * i < completedDepth && !thinkHard)
+ if (lastBestMoveDepth * i < completedDepth )
timeReduction *= 1.3;
unstablePvFactor *= std::pow(mainThread->previousTimeReduction, 0.51) / timeReduction;
if ( rootMoves.size() == 1
- || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 628)
+ || Time.elapsed() > Time.optimum() * unstablePvFactor * improvingFactor / 605)
{
// If we are allowed to ponder do not stop the search now but
// keep pondering until the GUI sends "ponderhit" or "stop".
if (move == excludedMove)
continue;
- if (rootNode)
- {
- // At root obey the "searchmoves" option and skip moves not listed in Root
- // Move List. As a consequence any illegal move is also skipped.
- if (!std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
- thisThread->rootMoves.end(), move))
- continue;
-
- // In MultiPV mode we not only skip PV moves which have already been searched,
- // but also any other move except we have reached the last PV line.
- if ( thisThread->PVIdx + 1 < thisThread->multiPV
- && move != ttMove)
- continue;
- }
+ // At root obey the "searchmoves" option and skip moves not listed in Root
+ // Move List. As a consequence any illegal move is also skipped. In MultiPV
+ // mode we also skip PV moves which have been already searched.
+ if (rootNode && !std::count(thisThread->rootMoves.begin() + thisThread->PVIdx,
+ thisThread->rootMoves.end(), move))
+ continue;
ss->moveCount = ++moveCount;
}
}
-
- // Is the PV leading to a draw position? Assumes all pv moves are legal
- bool pv_is_draw(Position& pos) {
-
- StateInfo st[MAX_PLY];
- auto& pv = pos.this_thread()->rootMoves[0].pv;
-
- for (size_t i = 0; i < pv.size(); ++i)
- pos.do_move(pv[i], st[i]);
-
- bool isDraw = pos.is_draw(pv.size());
-
- for (size_t i = pv.size(); i > 0; --i)
- pos.undo_move(pv[i-1]);
-
- return isDraw;
- }
-
-
// When playing with strength handicap, choose best move among a set of RootMoves
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
int elapsed = Time.elapsed() + 1;
const RootMoves& rootMoves = pos.this_thread()->rootMoves;
size_t PVIdx = pos.this_thread()->PVIdx;
- size_t multiPV = pos.this_thread()->multiPV;
+ size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
uint64_t nodesSearched = Threads.nodes_searched();
uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);