void benchmark(int argc, char* argv[]) {
+ std::vector<Move> searchMoves(1, MOVE_NONE);
vector<string> fenList;
+ Search::LimitsType limits;
int64_t totalNodes;
int time;
// Search should be limited by nodes, time or depth ?
if (valType == "nodes")
- Search::Limits.maxNodes = atoi(valStr.c_str());
+ limits.maxNodes = atoi(valStr.c_str());
else if (valType == "time")
- Search::Limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms
+ limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms
else
- Search::Limits.maxDepth = atoi(valStr.c_str());
+ limits.maxDepth = atoi(valStr.c_str());
// Do we need to load positions from a given FEN file?
if (fenFile != "default")
fenList.push_back(Defaults[i]);
// Ok, let's start the benchmark !
- Search::RootMoves.push_back(MOVE_NONE);
totalNodes = 0;
time = get_system_time();
for (size_t i = 0; i < fenList.size(); i++)
{
Position pos(fenList[i], false, 0);
- Search::RootPosition = &pos;
cerr << "\nBench position: " << i + 1 << '/' << fenList.size() << endl;
if (valType == "perft")
{
- int64_t cnt = Search::perft(pos, Search::Limits.maxDepth * ONE_PLY);
+ int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY);
- cerr << "\nPerft " << Search::Limits.maxDepth
+ cerr << "\nPerft " << limits.maxDepth
<< " nodes counted: " << cnt << endl;
totalNodes += cnt;
}
else
{
- Threads.start_thinking(false);
- totalNodes += pos.nodes_searched();
+ Threads.start_thinking(pos, limits, searchMoves, false);
+ totalNodes += Search::RootPosition.nodes_searched();
}
}
/// or the FEN string, we want the new born Position object do not depend
/// on any external data so we detach state pointer from the source one.
-Position::Position(const Position& pos, int th) {
+void Position::copy(const Position& pos, int th) {
memcpy(this, &pos, sizeof(Position));
threadID = th;
class Position {
- // No defaul, copy c'tor or assignment allowed, default c'tor will not be
- // generated anyhow because of user-defined c'tors.
+ // No copy c'tor or assignment operator allowed
Position(const Position&);
Position& operator=(const Position&);
public:
- Position(const Position& pos, int threadID);
- Position(const std::string& fen, bool isChess960, int threadID);
+ Position() {}
+ Position(const Position& pos, int th) { copy(pos, th); }
+ Position(const std::string& fen, bool isChess960, int th);
// Text input/output
+ void copy(const Position& pos, int th);
void from_fen(const std::string& fen, bool isChess960);
const std::string to_fen() const;
void print(Move m = MOVE_NONE) const;
volatile SignalsType Signals;
LimitsType Limits;
std::vector<Move> RootMoves;
- Position* RootPosition;
+ Position RootPosition;
}
namespace {
static Book book; // Defined static to initialize the PRNG only once
- Position& pos = *RootPosition;
+ Position& pos = RootPosition;
// Save "search start" time and reset elapsed time to zero
elapsed_search_time(get_system_time());
struct LimitsType {
+ LimitsType() { memset(this, 0, sizeof(LimitsType)); }
bool useTimeManagement() const { return !(maxTime | maxDepth | maxNodes | infinite); }
int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder;
extern volatile SignalsType Signals;
extern LimitsType Limits;
extern std::vector<Move> RootMoves;
-extern Position* RootPosition;
+extern Position RootPosition;
extern void init();
extern int64_t perft(Position& pos, Depth depth);
}
-// ThreadsManager::wait_end_of_search() blocks UI thread until main thread has
-// returned to sleep in main_loop(). It is needed becuase xboard sends immediately
-// new position to search after a "stop" due to ponder miss.
-
-void ThreadsManager::wait_end_of_search() {
-
- Thread& main = threads[0];
-
- lock_grab(&main.sleepLock);
-
- while (!main.do_sleep)
- cond_wait(&sleepCond, &main.sleepLock);
-
- lock_release(&main.sleepLock);
-}
-
-
// ThreadsManager::start_thinking() is used by UI thread to wake up the main
// thread parked in main_loop() and starting a new search. If asyncMode is true
// then function returns immediately, otherwise caller is blocked waiting for
// the search to finish.
-void ThreadsManager::start_thinking(bool asyncMode) {
-
+void ThreadsManager::start_thinking(const Position& pos, const Search::LimitsType& limits,
+ const std::vector<Move>& searchMoves, bool asyncMode) {
Thread& main = threads[0];
+ lock_grab(&main.sleepLock);
+
// Wait main thread has finished before to launch a new search
- wait_end_of_search();
+ while (!main.do_sleep)
+ cond_wait(&sleepCond, &main.sleepLock);
- lock_grab(&main.sleepLock);
+ // Copy input arguments to Search global variables
+ Search::RootPosition.copy(pos, 0);
+ Search::Limits = limits;
+ Search::RootMoves = searchMoves;
// Reset signals before to start the search
memset((void*)&Search::Signals, 0, sizeof(Search::Signals));
void read_uci_options();
bool available_slave_exists(int master) const;
bool split_point_finished(SplitPoint* sp) const;
-
- void start_thinking(bool asyncMode = true);
void set_timer(int msec);
void wait_for_stop_or_ponderhit();
- void wait_end_of_search();
+ void start_thinking(const Position& pos, const Search::LimitsType& limits,
+ const std::vector<Move>& searchMoves, bool asyncMode);
template <bool Fake>
Value split(Position& pos, SearchStack* ss, Value alpha, Value beta, Value bestValue,
quit = (token == "quit");
Search::Signals.stop = true;
Threads[0].wake_up(); // In case is waiting for stop or ponderhit
- Threads.wait_end_of_search(); // Block here until search finishes
}
else if (cmd == "ponderhit")
void go(Position& pos, istringstream& is) {
string token;
+ Search::LimitsType limits;
+ std::vector<Move> searchMoves;
int time[] = { 0, 0 }, inc[] = { 0, 0 };
- memset(&Search::Limits, 0, sizeof(Search::Limits));
- Search::RootMoves.clear();
- Search::RootPosition = &pos;
-
while (is >> token)
{
if (token == "infinite")
- Search::Limits.infinite = true;
+ limits.infinite = true;
else if (token == "ponder")
- Search::Limits.ponder = true;
+ limits.ponder = true;
else if (token == "wtime")
is >> time[WHITE];
else if (token == "btime")
else if (token == "binc")
is >> inc[BLACK];
else if (token == "movestogo")
- is >> Search::Limits.movesToGo;
+ is >> limits.movesToGo;
else if (token == "depth")
- is >> Search::Limits.maxDepth;
+ is >> limits.maxDepth;
else if (token == "nodes")
- is >> Search::Limits.maxNodes;
+ is >> limits.maxNodes;
else if (token == "movetime")
- is >> Search::Limits.maxTime;
+ is >> limits.maxTime;
else if (token == "searchmoves")
while (is >> token)
- Search::RootMoves.push_back(move_from_uci(pos, token));
+ searchMoves.push_back(move_from_uci(pos, token));
}
+ searchMoves.push_back(MOVE_NONE);
+ limits.time = time[pos.side_to_move()];
+ limits.increment = inc[pos.side_to_move()];
- Search::RootMoves.push_back(MOVE_NONE);
- Search::Limits.time = time[pos.side_to_move()];
- Search::Limits.increment = inc[pos.side_to_move()];
-
- Threads.start_thinking();
+ Threads.start_thinking(pos, limits, searchMoves, true);
}