#include <algorithm>
#include <cassert>
-#include <cfloat>
#include <cmath>
#include <cstring>
#include <iostream>
string uci_pv(const Position& pos, int depth, Value alpha, Value beta);
struct Skill {
- Skill(int l, int rootSize) : level(l),
- candidates(l < 20 ? std::min(4, rootSize) : 0),
- best(MOVE_NONE) {}
+ Skill(int l, size_t rootSize) : level(l),
+ candidates(l < 20 ? std::min(4, (int)rootSize) : 0),
+ best(MOVE_NONE) {}
~Skill() {
if (candidates) // Swap best PV line with the sub-optimal one
std::swap(RootMoves[0], *std::find(RootMoves.begin(),
/// Search::perft() is our utility to verify move generation. All the leaf nodes
/// up to the given depth are generated and counted and the sum returned.
-
-static uint64_t perft(Position& pos, Depth depth) {
+template<bool Root>
+uint64_t Search::perft(Position& pos, Depth depth) {
StateInfo st;
- uint64_t cnt = 0;
+ uint64_t cnt, nodes = 0;
CheckInfo ci(pos);
const bool leaf = depth == 2 * ONE_PLY;
for (MoveList<LEGAL> it(pos); *it; ++it)
{
- pos.do_move(*it, st, ci, pos.gives_check(*it, ci));
- cnt += leaf ? MoveList<LEGAL>(pos).size() : ::perft(pos, depth - ONE_PLY);
- pos.undo_move(*it);
+ if (Root && depth <= ONE_PLY)
+ cnt = 1, nodes++;
+ else
+ {
+ pos.do_move(*it, st, ci, pos.gives_check(*it, ci));
+ cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
+ nodes += cnt;
+ pos.undo_move(*it);
+ }
+ if (Root)
+ sync_cout << move_to_uci(*it, pos.is_chess960()) << ": " << cnt << sync_endl;
}
- return cnt;
+ return nodes;
}
-uint64_t Search::perft(Position& pos, Depth depth) {
- return depth > ONE_PLY ? ::perft(pos, depth) : MoveList<LEGAL>(pos).size();
-}
+template uint64_t Search::perft<true>(Position& pos, Depth depth);
+
/// Search::think() is the external interface to Stockfish's search, and is
/// called by the main thread when the program receives the UCI 'go' command. It
goto finalize;
}
- if (Options["Write Search Log"])
- {
- Log log(Options["Search Log Filename"]);
- log << "\nSearching: " << RootPos.fen()
- << "\ninfinite: " << Limits.infinite
- << " ponder: " << Limits.ponder
- << " time: " << Limits.time[RootPos.side_to_move()]
- << " increment: " << Limits.inc[RootPos.side_to_move()]
- << " moves to go: " << Limits.movestogo
- << "\n" << std::endl;
- }
-
// Reset the threads, still sleeping: will wake up at split time
for (size_t i = 0; i < Threads.size(); ++i)
Threads[i]->maxPly = 0;
Threads.timer->run = false; // Stop the timer
- if (Options["Write Search Log"])
- {
- Time::point elapsed = Time::now() - SearchTime + 1;
-
- Log log(Options["Search Log Filename"]);
- log << "Nodes: " << RootPos.nodes_searched()
- << "\nNodes/second: " << RootPos.nodes_searched() * 1000 / elapsed
- << "\nBest move: " << move_to_san(RootPos, RootMoves[0].pv[0]);
-
- StateInfo st;
- RootPos.do_move(RootMoves[0].pv[0], st);
- log << "\nPonder move: " << move_to_san(RootPos, RootMoves[0].pv[1]) << std::endl;
- RootPos.undo_move(RootMoves[0].pv[0]);
- }
-
finalize:
// When search is stopped this info is not printed
RootMoves[i].prevScore = RootMoves[i].score;
// MultiPV loop. We perform a full root search for each PV line
- for (PVIdx = 0; PVIdx < multiPV && PVIdx < RootMoves.size() && !Signals.stop; ++PVIdx)
+ for (PVIdx = 0; PVIdx < std::min(multiPV, RootMoves.size()) && !Signals.stop; ++PVIdx)
{
// Reset aspiration window starting size
if (depth >= 5)
else
break;
- delta += delta / 2;
+ delta += 3 * delta / 8;
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
}
// Sort the PV lines searched so far and update the GUI
std::stable_sort(RootMoves.begin(), RootMoves.begin() + PVIdx + 1);
- if (PVIdx + 1 == multiPV || Time::now() - SearchTime > 3000)
+ if (PVIdx + 1 == std::min(multiPV, RootMoves.size()) || Time::now() - SearchTime > 3000)
sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl;
}
if (skill.candidates_size() && skill.time_to_pick(depth))
skill.pick_move();
- if (Options["Write Search Log"])
- {
- RootMove& rm = RootMoves[0];
- if (skill.best != MOVE_NONE)
- rm = *std::find(RootMoves.begin(), RootMoves.end(), skill.best);
-
- Log log(Options["Search Log Filename"]);
- log << pretty_pv(pos, depth, rm.score, Time::now() - SearchTime, &rm.pv[0])
- << std::endl;
- }
-
// Have we found a "mate in x"?
if ( Limits.mate
&& bestValue >= VALUE_MATE_IN_MAX_PLY