CheckInfo ci(pos);
const bool leaf = (depth == 2 * ONE_PLY);
- for (const ExtMove& ms : MoveList<LEGAL>(pos))
+ for (const auto& m : MoveList<LEGAL>(pos))
{
if (Root && depth <= ONE_PLY)
cnt = 1, nodes++;
else
{
- pos.do_move(ms.move, st, ci, pos.gives_check(ms.move, ci));
+ pos.do_move(m, st, ci, pos.gives_check(m, ci));
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
nodes += cnt;
- pos.undo_move(ms.move);
+ pos.undo_move(m);
}
if (Root)
- sync_cout << UCI::move(ms.move, pos.is_chess960()) << ": " << cnt << sync_endl;
+ sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
if (RootMoves.empty())
{
- RootMoves.push_back(MOVE_NONE);
+ RootMoves.push_back(RootMove(MOVE_NONE));
sync_cout << "info depth 0 score "
<< UCI::value(RootPos.checkers() ? -VALUE_MATE : VALUE_DRAW)
<< sync_endl;
}
// Speculative prefetch as early as possible
- prefetch((char*)TT.first_entry(pos.key_after(move)));
+ prefetch(TT.first_entry(pos.key_after(move)));
// Check for legality just before making the move
if (!RootNode && !SpNode && !pos.legal(move, ci.pinned))
continue;
// Speculative prefetch as early as possible
- prefetch((char*)TT.first_entry(pos.key_after(move)));
+ prefetch(TT.first_entry(pos.key_after(move)));
// Check for legality just before making the move
if (!pos.legal(move, ci.pinned))
// then we choose the move with the resulting highest score.
for (size_t i = 0; i < multiPV; ++i)
{
- int score = RootMoves[i].score;
-
// This is our magic formula
- 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;
- if (score > maxScore)
+ if (RootMoves[i].score + push > maxScore)
{
- maxScore = score;
+ maxScore = RootMoves[i].score + push;
best = RootMoves[i].pv[0];
}
}
ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
ss << " nodes " << pos.nodes_searched()
- << " nps " << pos.nodes_searched() * 1000 / elapsed
- << " tbhits " << TB::Hits
+ << " nps " << pos.nodes_searched() * 1000 / elapsed;
+
+ if (elapsed > 1000) // Earlier makes little sense
+ ss << " hashfull " << TT.hashfull();
+
+ ss << " tbhits " << TB::Hits
<< " time " << elapsed
<< " pv";
void RootMove::insert_pv_in_tt(Position& pos) {
StateInfo state[MAX_PLY], *st = state;
- size_t idx = 0;
+ bool ttHit;
- for ( ; idx < pv.size(); ++idx)
+ for (Move m : pv)
{
- bool ttHit;
- TTEntry* tte = TT.probe(pos.key(), ttHit);
+ assert(MoveList<LEGAL>(pos).contains(m));
- 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());
- pos.do_move(pv[idx], *st++);
+ pos.do_move(m, *st++);
}
- while (idx) pos.undo_move(pv[--idx]);
+ for (size_t i = pv.size(); i > 0; )
+ pos.undo_move(pv[--i]);
}
/// 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.
-Move RootMove::extract_ponder_from_tt(Position& pos)
+bool RootMove::extract_ponder_from_tt(Position& pos)
{
StateInfo st;
- bool found;
+ bool ttHit;
assert(pv.size() == 1);
pos.do_move(pv[0], st);
- 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);
pos.undo_move(pv[0]);
- pv.push_back(m);
- return m;
+
+ if (ttHit)
+ {
+ Move m = tte->move(); // Local copy to be SMP safe
+ if (MoveList<LEGAL>(pos).contains(m))
+ return pv.push_back(m), true;
+ }
+
+ return false;
}