file.close();
}
- int64_t nodes = 0;
+ uint64_t nodes = 0;
Search::StateStackPtr st;
Time::point elapsed = Time::now();
if (limitType == "perft")
{
- size_t cnt = Search::perft(pos, limits.depth * ONE_PLY);
+ uint64_t cnt = Search::perft(pos, limits.depth * ONE_PLY);
cerr << "\nPerft " << limits.depth << " leaf nodes: " << cnt << endl;
nodes += cnt;
}
else
{
- Threads.start_thinking(pos, limits, vector<Move>(), st);
+ Threads.start_thinking(pos, limits, st);
Threads.wait_for_think_finished();
nodes += Search::RootPos.nodes_searched();
}
if (attack && attack != reference[i])
break;
- assert(reference[i] != 0);
+ assert(reference[i]);
attack = reference[i];
}
- } while (i != size);
+ } while (i < size);
}
}
}
Pawns::init();
Eval::init();
Threads.init();
- TT.set_size(Options["Hash"]);
+ TT.resize(Options["Hash"]);
std::string args;
static Mutex m;
- if (sc == io_lock)
+ if (sc == IO_LOCK)
m.lock();
- if (sc == io_unlock)
+ if (sc == IO_UNLOCK)
m.unlock();
return os;
};
-enum SyncCout { io_lock, io_unlock };
+enum SyncCout { IO_LOCK, IO_UNLOCK };
std::ostream& operator<<(std::ostream&, SyncCout);
-#define sync_cout std::cout << io_lock
-#define sync_endl std::endl << io_unlock
+#define sync_cout std::cout << IO_LOCK
+#define sync_endl std::endl << IO_UNLOCK
#endif // #ifndef MISC_H_INCLUDED
int game_ply() const;
bool is_chess960() const;
Thread* this_thread() const;
- int64_t nodes_searched() const;
- void set_nodes_searched(int64_t n);
+ uint64_t nodes_searched() const;
+ void set_nodes_searched(uint64_t n);
bool is_draw() const;
// Position consistency check, for debugging
Square castlingRookSquare[COLOR_NB][CASTLING_SIDE_NB];
Bitboard castlingPath[COLOR_NB][CASTLING_SIDE_NB];
StateInfo startState;
- int64_t nodes;
+ uint64_t nodes;
int gamePly;
Color sideToMove;
Thread* thisThread;
int chess960;
};
-inline int64_t Position::nodes_searched() const {
+inline uint64_t Position::nodes_searched() const {
return nodes;
}
-inline void Position::set_nodes_searched(int64_t n) {
+inline void Position::set_nodes_searched(uint64_t n) {
nodes = n;
}
uint64_t a, b, c, d;
- uint64_t rotate(uint64_t x, uint64_t k) const {
+ uint64_t rotate_L(uint64_t x, unsigned k) const {
return (x << k) | (x >> (64 - k));
}
uint64_t rand64() {
- const uint64_t e = a - rotate(b, 7);
- a = b ^ rotate(c, 13);
- b = c + rotate(d, 37);
+ const uint64_t e = a - rotate_L(b, 7);
+ a = b ^ rotate_L(c, 13);
+ b = c + rotate_L(d, 37);
c = d + e;
return d = e + a;
}
/// 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 size_t perft(Position& pos, Depth depth) {
+static uint64_t perft(Position& pos, Depth depth) {
StateInfo st;
- size_t cnt = 0;
+ uint64_t cnt = 0;
CheckInfo ci(pos);
const bool leaf = depth == 2 * ONE_PLY;
return cnt;
}
-size_t Search::perft(Position& pos, Depth depth) {
+uint64_t Search::perft(Position& pos, Depth depth) {
return depth > ONE_PLY ? ::perft(pos, depth) : MoveList<LEGAL>(pos).size();
}
LimitsType() { std::memset(this, 0, sizeof(LimitsType)); }
bool use_time_management() const { return !(mate | movetime | depth | nodes | infinite); }
+ std::vector<Move> searchmoves;
int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, nodes, movetime, mate, infinite, ponder;
};
/// typically in an async fashion e.g. to stop the search by the GUI.
struct SignalsType {
- bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;
+ bool stop, stopOnPonderhit, firstRootMove, failedLowAtRoot;
};
typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;
extern StateStackPtr SetupStates;
extern void init();
-extern size_t perft(Position& pos, Depth depth);
+extern uint64_t perft(Position& pos, Depth depth);
extern void think();
} // namespace Search
ThreadPool Threads; // Global object
+extern void check_time();
+
namespace {
// start_routine() is the C function which is called when a new thread
}
+// Thread::cutoff_occurred() checks whether a beta cutoff has occurred in the
+// current active split point, or in some ancestor of the split point.
+
+bool Thread::cutoff_occurred() const {
+
+ for (SplitPoint* sp = activeSplitPoint; sp; sp = sp->parentSplitPoint)
+ if (sp->cutoff)
+ return true;
+
+ return false;
+}
+
+
+// Thread::available_to() checks whether the thread is available to help the
+// thread 'master' at a split point. An obvious requirement is that thread must
+// be idle. With more than two threads, this is not sufficient: If the thread is
+// the master of some split point, it is only available as a slave to the slaves
+// which are busy searching the split point at the top of slave's split point
+// stack (the "helpful master concept" in YBWC terminology).
+
+bool Thread::available_to(const Thread* master) const {
+
+ if (searching)
+ return false;
+
+ // Make a local copy to be sure it doesn't become zero under our feet while
+ // testing next condition and so leading to an out of bounds access.
+ int size = splitPointsSize;
+
+ // No split points means that the thread is available as a slave for any
+ // other thread otherwise apply the "helpful master" concept if possible.
+ return !size || (splitPoints[size - 1].slavesMask & (1ULL << master->idx));
+}
+
+
// TimerThread::idle_loop() is where the timer thread waits msec milliseconds
// and then calls check_time(). If msec is 0 thread sleeps until it's woken up.
-extern void check_time();
void TimerThread::idle_loop() {
}
-// Thread::cutoff_occurred() checks whether a beta cutoff has occurred in the
-// current active split point, or in some ancestor of the split point.
-
-bool Thread::cutoff_occurred() const {
-
- for (SplitPoint* sp = activeSplitPoint; sp; sp = sp->parentSplitPoint)
- if (sp->cutoff)
- return true;
-
- return false;
-}
-
-
-// Thread::available_to() checks whether the thread is available to help the
-// thread 'master' at a split point. An obvious requirement is that thread must
-// be idle. With more than two threads, this is not sufficient: If the thread is
-// the master of some split point, it is only available as a slave to the slaves
-// which are busy searching the split point at the top of slave's split point
-// stack (the "helpful master concept" in YBWC terminology).
-
-bool Thread::available_to(const Thread* master) const {
-
- if (searching)
- return false;
-
- // Make a local copy to be sure it doesn't become zero under our feet while
- // testing next condition and so leading to an out of bounds access.
- int size = splitPointsSize;
-
- // No split points means that the thread is available as a slave for any
- // other thread otherwise apply the "helpful master" concept if possible.
- return !size || (splitPoints[size - 1].slavesMask & (1ULL << master->idx));
-}
-
-
// init() is called at startup to create and launch requested threads, that will
// go immediately to sleep due to 'sleepWhileIdle' set to true. We cannot use
// a c'tor because Threads is a static object and we need a fully initialized
MovePicker* movePicker, int nodeType, bool cutNode) {
assert(pos.pos_is_ok());
- assert(*bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE);
- assert(*bestValue > -VALUE_INFINITE);
+ assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE);
assert(depth >= Threads.minimumSplitDepth);
assert(searching);
assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD);
// start_thinking() wakes up the main thread sleeping in MainThread::idle_loop()
// so to start a new search, then returns immediately.
-void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
- const std::vector<Move>& searchMoves, StateStackPtr& states) {
+void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, StateStackPtr& states) {
+
wait_for_think_finished();
SearchTime = Time::now(); // As early as possible
}
for (MoveList<LEGAL> it(pos); *it; ++it)
- if ( searchMoves.empty()
- || std::count(searchMoves.begin(), searchMoves.end(), *it))
+ if ( limits.searchmoves.empty()
+ || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), *it))
RootMoves.push_back(RootMove(*it));
main()->thinking = true;
// Shared data
Mutex mutex;
volatile uint64_t slavesMask;
- volatile int64_t nodes;
+ volatile uint64_t nodes;
volatile Value alpha;
volatile Value bestValue;
volatile Move bestMove;
void read_uci_options();
Thread* available_slave(const Thread* master) const;
void wait_for_think_finished();
- void start_thinking(const Position&, const Search::LimitsType&,
- const std::vector<Move>&, Search::StateStackPtr&);
+ void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
bool sleepWhileIdle;
Depth minimumSplitDepth;
TranspositionTable TT; // Our global transposition table
-/// TranspositionTable::set_size() sets the size of the transposition table,
+/// TranspositionTable::resize() sets the size of the transposition table,
/// measured in megabytes. Transposition table consists of a power of 2 number
/// of clusters and each cluster consists of ClusterSize number of TTEntry.
-void TranspositionTable::set_size(uint64_t mbSize) {
+void TranspositionTable::resize(uint64_t mbSize) {
assert(msb((mbSize << 20) / sizeof(TTEntry)) < 32);
const TTEntry* probe(const Key key) const;
TTEntry* first_entry(const Key key) const;
void refresh(const TTEntry* tte) const;
- void set_size(uint64_t mbSize);
+ void resize(uint64_t mbSize);
void clear();
void store(const Key key, Value v, Bound type, Depth d, Move m, Value statV);
void go(const Position& pos, istringstream& is) {
Search::LimitsType limits;
- vector<Move> searchMoves;
string token;
while (is >> token)
{
if (token == "searchmoves")
while (is >> token)
- searchMoves.push_back(move_from_uci(pos, token));
+ limits.searchmoves.push_back(move_from_uci(pos, token));
else if (token == "wtime") is >> limits.time[WHITE];
else if (token == "btime") is >> limits.time[BLACK];
else if (token == "ponder") limits.ponder = true;
}
- Threads.start_thinking(pos, limits, searchMoves, SetupStates);
+ Threads.start_thinking(pos, limits, SetupStates);
}
}
void on_logger(const Option& o) { start_logger(o); }
void on_eval(const Option&) { Eval::init(); }
void on_threads(const Option&) { Threads.read_uci_options(); }
-void on_hash_size(const Option& o) { TT.set_size(o); }
+void on_hash_size(const Option& o) { TT.resize(o); }
void on_clear_hash(const Option&) { TT.clear(); }
/// Option class constructors and conversion operators
-Option::Option(const char* v, Fn* f) : type("string"), min(0), max(0), idx(Options.size()), on_change(f)
+Option::Option(const char* v, OnChange f) : type("string"), min(0), max(0), idx(Options.size()), on_change(f)
{ defaultValue = currentValue = v; }
-Option::Option(bool v, Fn* f) : type("check"), min(0), max(0), idx(Options.size()), on_change(f)
+Option::Option(bool v, OnChange f) : type("check"), min(0), max(0), idx(Options.size()), on_change(f)
{ defaultValue = currentValue = (v ? "true" : "false"); }
-Option::Option(Fn* f) : type("button"), min(0), max(0), idx(Options.size()), on_change(f)
+Option::Option(OnChange f) : type("button"), min(0), max(0), idx(Options.size()), on_change(f)
{}
-Option::Option(int v, int minv, int maxv, Fn* f) : type("spin"), min(minv), max(maxv), idx(Options.size()), on_change(f)
+Option::Option(int v, int minv, int maxv, OnChange f) : type("spin"), min(minv), max(maxv), idx(Options.size()), on_change(f)
{ std::ostringstream ss; ss << v; defaultValue = currentValue = ss.str(); }
currentValue = v;
if (on_change)
- (*on_change)(*this);
+ on_change(*this);
return *this;
}
/// Option class implements an option as defined by UCI protocol
class Option {
- typedef void (Fn)(const Option&);
+ typedef void (*OnChange)(const Option&);
public:
- Option(Fn* = NULL);
- Option(bool v, Fn* = NULL);
- Option(const char* v, Fn* = NULL);
- Option(int v, int min, int max, Fn* = NULL);
+ Option(OnChange = NULL);
+ Option(bool v, OnChange = NULL);
+ Option(const char* v, OnChange = NULL);
+ Option(int v, int min, int max, OnChange = NULL);
Option& operator=(const std::string& v);
operator int() const;
std::string defaultValue, currentValue, type;
int min, max;
size_t idx;
- Fn* on_change;
+ OnChange on_change;
};
void init(OptionsMap&);