Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
void update_stats(const Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt);
Value value_from_tt(Value v, int ply);
void update_pv(Move* pv, Move move, Move* childPv);
void update_stats(const Position& pos, Stack* ss, Move move, Depth depth, Move* quiets, int quietsCnt);
- pos.do_move(ms.move, st, ci, pos.gives_check(ms.move, ci));
+ pos.do_move(m, st, pos.gives_check(m, ci));
- sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
+ sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
// In case of failing low/high increase aspiration window and
// re-search, otherwise exit the loop.
// In case of failing low/high increase aspiration window and
// re-search, otherwise exit the loop.
<< " time " << Time::now() - SearchTime << sync_endl;
else if (PVIdx + 1 == multiPV || Time::now() - SearchTime > 3000)
<< " time " << Time::now() - SearchTime << sync_endl;
else if (PVIdx + 1 == multiPV || Time::now() - SearchTime > 3000)
- sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
+ sync_cout << UCI::pv(pos, depth, alpha, beta) << sync_endl;
- pos.do_move(move, st, ci, pos.gives_check(move, ci));
+ pos.do_move(move, st, pos.gives_check(move, ci));
value = -search<NonPV, false>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
pos.undo_move(move);
if (value >= rbeta)
value = -search<NonPV, false>(pos, ss+1, -rbeta, -rbeta+1, rdepth, !cutNode);
pos.undo_move(move);
if (value >= rbeta)
// Check for legality just before making the move
if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
// Check for legality just before making the move
if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
// Step 15. Reduced depth search (LMR). If the move fails high it will be
// re-searched at full depth.
// Step 15. Reduced depth search (LMR). If the move fails high it will be
// re-searched at full depth.
// Check for legality just before making the move
if (!pos.legal(move, ci.pinned))
// Check for legality just before making the move
if (!pos.legal(move, ci.pinned))
value = givesCheck ? -qsearch<NT, true>(pos, ss+1, -beta, -alpha, depth - ONE_PLY)
: -qsearch<NT, false>(pos, ss+1, -beta, -alpha, depth - ONE_PLY);
pos.undo_move(move);
value = givesCheck ? -qsearch<NT, true>(pos, ss+1, -beta, -alpha, depth - ONE_PLY)
: -qsearch<NT, false>(pos, ss+1, -beta, -alpha, depth - ONE_PLY);
pos.undo_move(move);
- score += ( weakness * int(RootMoves[0].score - score)
- + variance * (rng.rand<unsigned>() % weakness)) / 128;
+ int push = ( weakness * int(RootMoves[0].score - RootMoves[i].score)
+ + variance * (rng.rand<unsigned>() % weakness)) / 128;
- string uci_pv(const Position& pos, Depth depth, Value alpha, Value beta) {
+/// UCI::pv() formats PV information according to the UCI protocol. UCI requires
+/// that all (if any) unsearched PV lines are sent using a previous search score.
- std::stringstream ss;
- Time::point elapsed = Time::now() - SearchTime + 1;
- size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size());
- int selDepth = 0;
+string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
- for (Thread* th : Threads)
- if (th->maxPly > selDepth)
- selDepth = th->maxPly;
+ std::stringstream ss;
+ Time::point elapsed = Time::now() - SearchTime + 1;
+ size_t multiPV = std::min((size_t)Options["MultiPV"], RootMoves.size());
+ int selDepth = 0;
- ss << "info depth " << d / ONE_PLY
- << " seldepth " << selDepth
- << " multipv " << i + 1
- << " score " << UCI::value(v);
+ if (ss.rdbuf()->in_avail()) // Not at first line
+ ss << "\n";
- if (!tb && i == PVIdx)
- ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
+ ss << "info"
+ << " depth " << d / ONE_PLY
+ << " seldepth " << selDepth
+ << " multipv " << i + 1
+ << " score " << UCI::value(v);
- for (size_t j = 0; j < RootMoves[i].pv.size(); ++j)
- ss << " " << UCI::move(RootMoves[i].pv[j], pos.is_chess960());
- }
+ ss << " nodes " << pos.nodes_searched()
+ << " nps " << pos.nodes_searched() * 1000 / elapsed;
+
+ if (elapsed > 1000) // Earlier makes little sense
+ ss << " hashfull " << TT.hashfull();
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY], *st = state;
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY], *st = state;
- if (!ttHit || tte->move() != pv[idx]) // Don't overwrite correct entries
- tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[idx], VALUE_NONE, TT.generation());
+ TTEntry* tte = TT.probe(pos.key(), ttHit);
- assert(MoveList<LEGAL>(pos).contains(pv[idx]));
+ if (!ttHit || tte->move() != m) // Don't overwrite correct entries
+ tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, m, VALUE_NONE, TT.generation());
/// root. We try hard to have a ponder move to return to the GUI, otherwise in case of
/// 'ponder on' we have nothing to think on.
/// root. We try hard to have a ponder move to return to the GUI, otherwise in case of
/// 'ponder on' we have nothing to think on.
- TTEntry* tte = TT.probe(pos.key(), found);
- Move m = found ? tte->move() : MOVE_NONE;
- if (!MoveList<LEGAL>(pos).contains(m))
- m = MOVE_NONE;
-
+ TTEntry* tte = TT.probe(pos.key(), ttHit);