1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-29 16:23:09 +00:00

Restore perft

Rewrite perft to be placed naturally inside new
bench code. In particular we don't have special
custom code to run perft anymore but perft is
just a new parameter of 'go' command.

So user API is now changed, old style command:

$perft 5

becomes

$go perft 4

No functional change.
This commit is contained in:
Marco Costalba 2017-08-15 01:05:22 -07:00
parent 444d99b6d2
commit 45e254a0a0
5 changed files with 52 additions and 53 deletions

View file

@ -86,11 +86,16 @@ const vector<string> Defaults = {
} // namespace
/// setup_bench() builds a list of UCI commands to be run by bench. There
/// are five parameters: TT size, number of search threads that should
/// be used, the limit value spent for each position (optional, default is
/// depth 13), an optional file name where to look for positions in FEN
/// format (defaults are the positions defined above) and the type of the
/// limit value: depth (default), time in millisecs or number of nodes.
/// are five parameters: TT size in MB, number of search threads that
/// should be used, the limit value spent for each position, a file name
/// where to look for positions in FEN format and the type of the limit:
/// depth, perft, nodes and movetime (in millisecs).
///
/// bench -> search default positions up to depth 13
/// bench 64 1 15 -> search default positions up to depth 15 (TT = 64MB)
/// bench 64 4 5000 current movetime -> search current position with 4 threads for 5 sec
/// bench 64 1 100000 default nodes -> search default positions for 100K nodes each
/// bench 16 1 5 default perft -> run a perft 5 on default positions
std::vector<string> setup_bench(const Position& current , istream& is) {

View file

@ -154,6 +154,32 @@ namespace {
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);
// 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>
uint64_t perft(Position& pos, Depth depth) {
StateInfo st;
uint64_t cnt, nodes = 0;
const bool leaf = (depth == 2 * ONE_PLY);
for (const auto& m : MoveList<LEGAL>(pos))
{
if (Root && depth <= ONE_PLY)
cnt = 1, nodes++;
else
{
pos.do_move(m, st);
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
nodes += cnt;
pos.undo_move(m);
}
if (Root)
sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
} // namespace
@ -209,40 +235,18 @@ void Search::clear() {
}
/// 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 is returned.
template<bool Root>
uint64_t Search::perft(Position& pos, Depth depth) {
StateInfo st;
uint64_t cnt, nodes = 0;
const bool leaf = (depth == 2 * ONE_PLY);
for (const auto& m : MoveList<LEGAL>(pos))
{
if (Root && depth <= ONE_PLY)
cnt = 1, nodes++;
else
{
pos.do_move(m, st);
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
nodes += cnt;
pos.undo_move(m);
}
if (Root)
sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl;
}
return nodes;
}
template uint64_t Search::perft<true>(Position&, Depth);
/// 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".
void MainThread::search() {
if (Limits.perft)
{
nodes = perft<true>(rootPos, Limits.perft * ONE_PLY);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
return;
}
Color us = rootPos.side_to_move();
Time.init(Limits, us, rootPos.game_ply());
TT.new_search();

View file

@ -78,15 +78,16 @@ struct LimitsType {
LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] =
npmsec = movestogo = depth = movetime = mate = infinite = 0;
npmsec = movestogo = depth = movetime = mate = perft = infinite = 0;
}
bool use_time_management() const {
return !(mate | movetime | depth | nodes | infinite);
return !(mate | movetime | depth | nodes | perft | infinite);
}
std::vector<Move> searchmoves;
int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth, movetime, mate, infinite;
int time[COLOR_NB], inc[COLOR_NB], npmsec, movestogo, depth,
movetime, mate, perft, infinite;
int64_t nodes;
TimePoint startTime;
};
@ -95,7 +96,6 @@ extern LimitsType Limits;
void init();
void clear();
template<bool Root = true> uint64_t perft(Position& pos, Depth depth);
} // namespace Search

View file

@ -128,6 +128,7 @@ namespace {
else if (token == "nodes") is >> limits.nodes;
else if (token == "movetime") is >> limits.movetime;
else if (token == "mate") is >> limits.mate;
else if (token == "perft") is >> limits.perft;
else if (token == "infinite") limits.infinite = 1;
else if (token == "ponder") ponderMode = true;
@ -137,7 +138,7 @@ namespace {
// bench() is called when engine receives the "bench" command. Firstly
// a list of UCI commands is setup according to bench parameters, then
// it is run one by one printing summaries at the end.
// it is run one by one printing a summary at the end.
void bench(Position& pos, istream& args, StateListPtr& states) {
@ -145,7 +146,7 @@ namespace {
uint64_t num, nodes = 0, cnt = 1;
vector<string> list = setup_bench(pos, args);
num = count_if (list.begin(), list.end(), [](string s) { return s.find("go ") == 0; });
num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0; });
TimePoint elapsed = now();
@ -235,17 +236,6 @@ void UCI::loop(int argc, char* argv[]) {
else if (token == "bench") bench(pos, is, states);
else if (token == "d") sync_cout << pos << sync_endl;
else if (token == "eval") sync_cout << Eval::trace(pos) << sync_endl;
else if (token == "perft")
{
int depth;
stringstream ss;
is >> depth;
ss << Options["Hash"] << " " << Options["Threads"]
<< " " << depth << " current perft";
// TODO benchmark(pos, ss);
}
else
sync_cout << "Unknown command: " << cmd << sync_endl;

View file

@ -14,8 +14,8 @@ cat << EOF > perft.exp
set timeout 10
lassign \$argv pos depth result
spawn ./stockfish
send "position \$pos\\n perft \$depth\\n"
expect "Nodes searched ? \$result" {} timeout {exit 1}
send "position \$pos\\ngo perft \$depth\\n"
expect "Nodes searched? \$result" {} timeout {exit 1}
send "quit\\n"
expect eof
EOF