From: Marco Costalba Date: Sat, 14 Jan 2012 12:49:25 +0000 (+0100) Subject: Move struct RootMove to Search namespace X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=103b368ab7f5fd696e0c6925917344d15a3c2d9c;hp=a29dd88f7563c5af871d9adc137218c39586b09c Move struct RootMove to Search namespace And directly pass RootMoves instead of SearchMoves to main thread. A class declaration is better suited in a header and slims a bit the fatty search.cpp No functional change. Signed-off-by: Marco Costalba --- diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 1491e222..ba05ac7f 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -19,7 +19,6 @@ #include #include -#include #include #include "misc.h" @@ -29,7 +28,6 @@ #include "ucioption.h" using namespace std; -using namespace Search; static const char* Defaults[] = { "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", @@ -62,7 +60,7 @@ static const char* Defaults[] = { void benchmark(int argc, char* argv[]) { vector fens; - LimitsType limits; + Search::LimitsType limits; int time; int64_t nodes = 0; @@ -116,14 +114,14 @@ void benchmark(int argc, char* argv[]) { if (valType == "perft") { - int64_t cnt = perft(pos, limits.maxDepth * ONE_PLY); + int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY); cerr << "\nPerft " << limits.maxDepth << " leaf nodes: " << cnt << endl; nodes += cnt; } else { - Threads.start_thinking(pos, limits, set(), false); - nodes += RootPosition.nodes_searched(); + Threads.start_thinking(pos, limits); + nodes += Search::RootPosition.nodes_searched(); } } diff --git a/src/search.cpp b/src/search.cpp index 0839bd0f..48cb4d6b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include "book.h" #include "evaluate.h" @@ -42,7 +41,7 @@ namespace Search { volatile SignalsType Signals; LimitsType Limits; - std::set SearchMoves; + std::vector RootMoves; Position RootPosition; } @@ -59,33 +58,6 @@ namespace { // Different node types, used as template parameter enum NodeType { Root, PV, NonPV, SplitPointRoot, SplitPointPV, SplitPointNonPV }; - // RootMove struct is used for moves at the root of the tree. For each root - // move we store a score, a node count, and a PV (really a refutation in the - // case of moves which fail low). Score is normally set at -VALUE_INFINITE for - // all non-pv moves. - struct RootMove { - - RootMove(){} - RootMove(Move m) { - score = prevScore = -VALUE_INFINITE; - pv.push_back(m); - pv.push_back(MOVE_NONE); - } - - bool operator<(const RootMove& m) const { return score < m.score; } - bool operator==(const Move& m) const { return pv[0] == m; } - - void extract_pv_from_tt(Position& pos); - void insert_pv_in_tt(Position& pos); - - Value score; - Value prevScore; - std::vector pv; - }; - - - /// Constants - // Lookup table to check if a Piece is a slider and its access function const bool Slidings[18] = { 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1 }; inline bool piece_is_slider(Piece p) { return Slidings[p]; } @@ -135,17 +107,14 @@ namespace { return (Depth) Reductions[PvNode][std::min(int(d) / ONE_PLY, 63)][std::min(mn, 63)]; } - // Easy move margin. An easy move candidate must be at least this much - // better than the second best move. + // Easy move margin. An easy move candidate must be at least this much better + // than the second best move. const Value EasyMoveMargin = Value(0x150); // This is the minimum interval in msec between two check_time() calls const int TimerResolution = 5; - /// Namespace variables - - std::vector RootMoves; size_t MultiPV, UCIMultiPV, PVIdx; TimeManager TimeMgr; int BestMoveChanges; @@ -154,8 +123,6 @@ namespace { History H; - /// Local functions - template Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth); @@ -289,13 +256,6 @@ void Search::think() { TimeMgr.init(Limits, pos.startpos_ply_counter()); TT.new_search(); H.clear(); - RootMoves.clear(); - - // Populate RootMoves with all the legal moves (default) or, if a SearchMoves - // is given, with the subset of legal moves to search. - for (MoveList ml(pos); !ml.end(); ++ml) - if (SearchMoves.empty() || SearchMoves.count(ml.move())) - RootMoves.push_back(RootMove(ml.move())); if (RootMoves.empty()) { @@ -1798,74 +1758,74 @@ split_point_start: // At split points actual search starts from here return best; } +} // namespace - // extract_pv_from_tt() builds a PV by adding moves from the transposition table. - // We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes. This - // allow to always have a ponder move even when we fail high at root and also a - // long PV to print that is important for position analysis. - void RootMove::extract_pv_from_tt(Position& pos) { +/// RootMove::extract_pv_from_tt() builds a PV by adding moves from the TT table. +/// We consider also failing high nodes and not only VALUE_TYPE_EXACT nodes so +/// to allow to always have a ponder move even when we fail high at root, and +/// a long PV to print that is important for position analysis. - StateInfo state[MAX_PLY_PLUS_2], *st = state; - TTEntry* tte; - int ply = 1; - Move m = pv[0]; - - assert(m != MOVE_NONE && pos.is_pseudo_legal(m)); - - pv.clear(); - pv.push_back(m); - pos.do_move(m, *st++); - - while ( (tte = TT.probe(pos.key())) != NULL - && tte->move() != MOVE_NONE - && pos.is_pseudo_legal(tte->move()) - && pos.pl_move_is_legal(tte->move(), pos.pinned_pieces()) - && ply < MAX_PLY - && (!pos.is_draw() || ply < 2)) - { - pv.push_back(tte->move()); - pos.do_move(tte->move(), *st++); - ply++; - } - pv.push_back(MOVE_NONE); +void RootMove::extract_pv_from_tt(Position& pos) { + + StateInfo state[MAX_PLY_PLUS_2], *st = state; + TTEntry* tte; + int ply = 1; + Move m = pv[0]; + + assert(m != MOVE_NONE && pos.is_pseudo_legal(m)); - do pos.undo_move(pv[--ply]); while (ply); + pv.clear(); + pv.push_back(m); + pos.do_move(m, *st++); + + while ( (tte = TT.probe(pos.key())) != NULL + && tte->move() != MOVE_NONE + && pos.is_pseudo_legal(tte->move()) + && pos.pl_move_is_legal(tte->move(), pos.pinned_pieces()) + && ply < MAX_PLY + && (!pos.is_draw() || ply < 2)) + { + pv.push_back(tte->move()); + pos.do_move(tte->move(), *st++); + ply++; } + pv.push_back(MOVE_NONE); + do pos.undo_move(pv[--ply]); while (ply); +} - // insert_pv_in_tt() is called at the end of a search iteration, and inserts - // the PV back into the TT. This makes sure the old PV moves are searched - // first, even if the old TT entries have been overwritten. - void RootMove::insert_pv_in_tt(Position& pos) { +/// RootMove::insert_pv_in_tt() is called at the end of a search iteration, and +/// inserts the PV back into the TT. This makes sure the old PV moves are searched +/// first, even if the old TT entries have been overwritten. - StateInfo state[MAX_PLY_PLUS_2], *st = state; - TTEntry* tte; - Key k; - Value v, m = VALUE_NONE; - int ply = 0; +void RootMove::insert_pv_in_tt(Position& pos) { - assert(pv[ply] != MOVE_NONE && pos.is_pseudo_legal(pv[ply])); + StateInfo state[MAX_PLY_PLUS_2], *st = state; + TTEntry* tte; + Key k; + Value v, m = VALUE_NONE; + int ply = 0; - do { - k = pos.key(); - tte = TT.probe(k); + assert(pv[ply] != MOVE_NONE && pos.is_pseudo_legal(pv[ply])); - // Don't overwrite existing correct entries - if (!tte || tte->move() != pv[ply]) - { - v = (pos.in_check() ? VALUE_NONE : evaluate(pos, m)); - TT.store(k, VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[ply], v, m); - } - pos.do_move(pv[ply], *st++); + do { + k = pos.key(); + tte = TT.probe(k); - } while (pv[++ply] != MOVE_NONE); + // Don't overwrite existing correct entries + if (!tte || tte->move() != pv[ply]) + { + v = (pos.in_check() ? VALUE_NONE : evaluate(pos, m)); + TT.store(k, VALUE_NONE, VALUE_TYPE_NONE, DEPTH_NONE, pv[ply], v, m); + } + pos.do_move(pv[ply], *st++); - do pos.undo_move(pv[--ply]); while (ply); - } + } while (pv[++ply] != MOVE_NONE); -} // namespace + do pos.undo_move(pv[--ply]); while (ply); +} /// Thread::idle_loop() is where the thread is parked when it has no work to do. diff --git a/src/search.h b/src/search.h index d805d462..a4cba6bf 100644 --- a/src/search.h +++ b/src/search.h @@ -21,7 +21,7 @@ #define SEARCH_H_INCLUDED #include -#include +#include #include "types.h" @@ -48,13 +48,36 @@ struct Stack { }; +/// RootMove struct is used for moves at the root of the tree. For each root +/// move we store a score, a node count, and a PV (really a refutation in the +/// case of moves which fail low). Score is normally set at -VALUE_INFINITE for +/// all non-pv moves. +struct RootMove { + + RootMove(){} // Needed by sort() + RootMove(Move m) : score(-VALUE_INFINITE), prevScore(-VALUE_INFINITE) { + pv.push_back(m); pv.push_back(MOVE_NONE); + } + + bool operator<(const RootMove& m) const { return score < m.score; } + bool operator==(const Move& m) const { return pv[0] == m; } + + void extract_pv_from_tt(Position& pos); + void insert_pv_in_tt(Position& pos); + + Value score; + Value prevScore; + std::vector pv; +}; + + /// The LimitsType struct stores information sent by GUI about available time /// to search the current move, maximum depth/time, if we are in analysis mode /// or if we have to ponder while is our opponent's side to move. struct LimitsType { - LimitsType() { memset(this, 0, sizeof(LimitsType)); } + LimitsType() { memset(this, 0, sizeof(LimitsType)); } bool use_time_management() const { return !(maxTime | maxDepth | maxNodes | infinite); } int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder; @@ -70,13 +93,13 @@ struct SignalsType { extern volatile SignalsType Signals; extern LimitsType Limits; -extern std::set SearchMoves; +extern std::vector RootMoves; extern Position RootPosition; extern void init(); extern int64_t perft(Position& pos, Depth depth); extern void think(); -} // namespace +} // namespace Search #endif // !defined(SEARCH_H_INCLUDED) diff --git a/src/thread.cpp b/src/thread.cpp index 74ca48cc..1db61a20 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -19,6 +19,7 @@ #include +#include "movegen.h" #include "search.h" #include "thread.h" #include "ucioption.h" @@ -420,7 +421,7 @@ void Thread::main_loop() { if (do_terminate) return; - think(); // This is the search entry point + Search::think(); } } @@ -431,7 +432,7 @@ void Thread::main_loop() { // the search to finish. void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limits, - const std::set& searchMoves, bool asyncMode) { + const std::set& searchMoves, bool async) { Thread& main = threads[0]; lock_grab(&main.sleepLock); @@ -443,7 +444,13 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit // Copy input arguments to initialize the search RootPosition.copy(pos, 0); Limits = limits; - SearchMoves = searchMoves; + RootMoves.clear(); + + // Populate RootMoves with all the legal moves (default) or, if a searchMoves + // set is given, with the subset of legal moves to search. + for (MoveList ml(pos); !ml.end(); ++ml) + if (searchMoves.empty() || searchMoves.count(ml.move())) + RootMoves.push_back(RootMove(ml.move())); // Reset signals before to start the new search Signals.stopOnPonderhit = Signals.firstRootMove = false; @@ -452,7 +459,7 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit main.do_sleep = false; cond_signal(&main.sleepCond); // Wake up main thread and start searching - if (!asyncMode) + if (!async) while (!main.do_sleep) cond_wait(&sleepCond, &main.sleepLock); diff --git a/src/thread.h b/src/thread.h index 6bccde4c..cc490639 100644 --- a/src/thread.h +++ b/src/thread.h @@ -121,7 +121,7 @@ public: void wait_for_stop_or_ponderhit(); void stop_thinking(); void start_thinking(const Position& pos, const Search::LimitsType& limits, - const std::set& searchMoves, bool asyncMode); + const std::set& = std::set(), bool async = false); template Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue,