if (limitType == "time")
secsPerPos = val * 1000;
- else if (limitType == "depth")
+ else if (limitType == "depth" || limitType == "perft")
maxDepth = val;
else
maxNodes = val;
int dummy[2] = {0, 0};
Position pos(*it);
cerr << "\nBench position: " << cnt << '/' << positions.size() << endl << endl;
- if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
+ if (limitType == "perft")
+ totalNodes += perft(pos, maxDepth * OnePly);
+ else if (!think(pos, true, false, 0, dummy, dummy, 0, maxDepth, maxNodes, secsPerPos, moves))
break;
totalNodes += nodes_searched();
}
if (string(argv[1]) != "bench" || argc < 4 || argc > 8)
cout << "Usage: stockfish bench <hash size> <threads> "
<< "[time = 60s] [fen positions file = default] "
- << "[time, depth or node limited = time] "
+ << "[time, depth, perft or node limited = time] "
<< "[timing file name = none]" << endl;
else
{
//// Functions
////
+
+/// perft() is our utility to verify move generation is bug free. All the
+/// legal moves up to given depth are generated and counted and the sum returned.
+
+int perft(Position& pos, Depth depth)
+{
+ if (depth <= Depth(0)) // Replace with '<' to test also qsearch
+ return 1;
+
+ Move move;
+ MovePicker mp = MovePicker(pos, MOVE_NONE, depth, H);
+ Bitboard dcCandidates = mp.discovered_check_candidates();
+ int sum = 0;
+
+ // Loop through all legal moves
+ while ((move = mp.get_next_move()) != MOVE_NONE)
+ {
+ StateInfo st;
+ pos.do_move(move, st, dcCandidates);
+ sum += perft(pos, depth - OnePly);
+ pos.undo_move(move);
+ }
+ return sum;
+}
+
+
/// think() is the external interface to Stockfish's search, and is called when
/// the program receives the UCI 'go' command. It initializes various
/// search-related global variables, and calls root_search(). It returns false
if (movesToGo == 1)
{
MaxSearchTime = myTime / 2;
- AbsoluteMaxSearchTime =
+ AbsoluteMaxSearchTime =
(myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
} else {
MaxSearchTime = myTime / Min(movesToGo, 20);
std::cout << std::endl;
if (UseLogFile)
- LogFile << pretty_pv(pos, current_search_time(), Iteration, nodes_searched(), value,
+ LogFile << pretty_pv(pos, current_search_time(), Iteration, nodes_searched(), value,
((value >= beta)? VALUE_TYPE_LOWER
: ((value <= alpha)? VALUE_TYPE_UPPER : VALUE_TYPE_EXACT)),
ss[0].pv)
extern bool think(const Position &pos, bool infinite, bool ponder, int side_to_move,
int time[], int increment[], int movesToGo, int maxDepth,
int maxNodes, int maxTime, Move searchMoves[]);
+extern int perft(Position &pos, Depth depth);
extern int64_t nodes_searched();
void set_option(UCIInputParser& uip);
void set_position(UCIInputParser& uip);
bool go(UCIInputParser& uip);
+ void perft(UCIInputParser& uip);
}
cout << "key: " << hex << RootPosition.get_key()
<< "\nmaterial key: " << RootPosition.get_material_key()
<< "\npawn key: " << RootPosition.get_pawn_key() << endl;
+ else if (token == "perft")
+ perft(uip);
else
{
cout << "Unknown command: " << command << endl;
time, inc, movesToGo, depth, nodes, moveTime, searchMoves);
}
+ void perft(UCIInputParser& uip) {
+
+ string token;
+ int depth = 0;
+
+ while (!uip.eof())
+ {
+ uip >> token;
+
+ if (token == "depth")
+ uip >> depth;
+ }
+ Position pos = RootPosition;
+ int tm = get_system_time();
+ int n = perft(pos, depth * OnePly);
+ tm = get_system_time() - tm;
+ std::cout << "\nNodes " << n
+ << "\nTime (ms) " << tm
+ << "\nNodes/second " << (int)(n/(tm/1000.0)) << std::endl;
+ }
}