mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 09:13:08 +00:00
Assorted tweaks from DON
Mainly renames and some little code style improvment, inspired by looking at DON sources: https://github.com/erashid/DON No functional change.
This commit is contained in:
parent
2f5aaf7de6
commit
41641e3b1e
16 changed files with 87 additions and 88 deletions
|
@ -126,7 +126,7 @@ void benchmark(const Position& current, istream& is) {
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t nodes = 0;
|
uint64_t nodes = 0;
|
||||||
Search::StateStackPtr st;
|
Search::StateStackPtr st;
|
||||||
Time::point elapsed = Time::now();
|
Time::point elapsed = Time::now();
|
||||||
|
|
||||||
|
@ -138,13 +138,13 @@ void benchmark(const Position& current, istream& is) {
|
||||||
|
|
||||||
if (limitType == "perft")
|
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;
|
cerr << "\nPerft " << limits.depth << " leaf nodes: " << cnt << endl;
|
||||||
nodes += cnt;
|
nodes += cnt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Threads.start_thinking(pos, limits, vector<Move>(), st);
|
Threads.start_thinking(pos, limits, st);
|
||||||
Threads.wait_for_think_finished();
|
Threads.wait_for_think_finished();
|
||||||
nodes += Search::RootPos.nodes_searched();
|
nodes += Search::RootPos.nodes_searched();
|
||||||
}
|
}
|
||||||
|
|
|
@ -325,11 +325,11 @@ namespace {
|
||||||
if (attack && attack != reference[i])
|
if (attack && attack != reference[i])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
assert(reference[i] != 0);
|
assert(reference[i]);
|
||||||
|
|
||||||
attack = reference[i];
|
attack = reference[i];
|
||||||
}
|
}
|
||||||
} while (i != size);
|
} while (i < size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ int main(int argc, char* argv[]) {
|
||||||
Pawns::init();
|
Pawns::init();
|
||||||
Eval::init();
|
Eval::init();
|
||||||
Threads.init();
|
Threads.init();
|
||||||
TT.set_size(Options["Hash"]);
|
TT.resize(Options["Hash"]);
|
||||||
|
|
||||||
std::string args;
|
std::string args;
|
||||||
|
|
||||||
|
|
|
@ -144,10 +144,10 @@ std::ostream& operator<<(std::ostream& os, SyncCout sc) {
|
||||||
|
|
||||||
static Mutex m;
|
static Mutex m;
|
||||||
|
|
||||||
if (sc == io_lock)
|
if (sc == IO_LOCK)
|
||||||
m.lock();
|
m.lock();
|
||||||
|
|
||||||
if (sc == io_unlock)
|
if (sc == IO_UNLOCK)
|
||||||
m.unlock();
|
m.unlock();
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
|
|
|
@ -59,10 +59,10 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum SyncCout { io_lock, io_unlock };
|
enum SyncCout { IO_LOCK, IO_UNLOCK };
|
||||||
std::ostream& operator<<(std::ostream&, SyncCout);
|
std::ostream& operator<<(std::ostream&, SyncCout);
|
||||||
|
|
||||||
#define sync_cout std::cout << io_lock
|
#define sync_cout std::cout << IO_LOCK
|
||||||
#define sync_endl std::endl << io_unlock
|
#define sync_endl std::endl << IO_UNLOCK
|
||||||
|
|
||||||
#endif // #ifndef MISC_H_INCLUDED
|
#endif // #ifndef MISC_H_INCLUDED
|
||||||
|
|
|
@ -159,8 +159,8 @@ public:
|
||||||
int game_ply() const;
|
int game_ply() const;
|
||||||
bool is_chess960() const;
|
bool is_chess960() const;
|
||||||
Thread* this_thread() const;
|
Thread* this_thread() const;
|
||||||
int64_t nodes_searched() const;
|
uint64_t nodes_searched() const;
|
||||||
void set_nodes_searched(int64_t n);
|
void set_nodes_searched(uint64_t n);
|
||||||
bool is_draw() const;
|
bool is_draw() const;
|
||||||
|
|
||||||
// Position consistency check, for debugging
|
// Position consistency check, for debugging
|
||||||
|
@ -201,7 +201,7 @@ private:
|
||||||
Square castlingRookSquare[COLOR_NB][CASTLING_SIDE_NB];
|
Square castlingRookSquare[COLOR_NB][CASTLING_SIDE_NB];
|
||||||
Bitboard castlingPath[COLOR_NB][CASTLING_SIDE_NB];
|
Bitboard castlingPath[COLOR_NB][CASTLING_SIDE_NB];
|
||||||
StateInfo startState;
|
StateInfo startState;
|
||||||
int64_t nodes;
|
uint64_t nodes;
|
||||||
int gamePly;
|
int gamePly;
|
||||||
Color sideToMove;
|
Color sideToMove;
|
||||||
Thread* thisThread;
|
Thread* thisThread;
|
||||||
|
@ -209,11 +209,11 @@ private:
|
||||||
int chess960;
|
int chess960;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int64_t Position::nodes_searched() const {
|
inline uint64_t Position::nodes_searched() const {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Position::set_nodes_searched(int64_t n) {
|
inline void Position::set_nodes_searched(uint64_t n) {
|
||||||
nodes = n;
|
nodes = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,15 +45,15 @@ class RKISS {
|
||||||
|
|
||||||
uint64_t a, b, c, d;
|
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));
|
return (x << k) | (x >> (64 - k));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t rand64() {
|
uint64_t rand64() {
|
||||||
|
|
||||||
const uint64_t e = a - rotate(b, 7);
|
const uint64_t e = a - rotate_L(b, 7);
|
||||||
a = b ^ rotate(c, 13);
|
a = b ^ rotate_L(c, 13);
|
||||||
b = c + rotate(d, 37);
|
b = c + rotate_L(d, 37);
|
||||||
c = d + e;
|
c = d + e;
|
||||||
return d = e + a;
|
return d = e + a;
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,10 +154,10 @@ void Search::init() {
|
||||||
/// Search::perft() is our utility to verify move generation. All the leaf nodes
|
/// 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.
|
/// 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;
|
StateInfo st;
|
||||||
size_t cnt = 0;
|
uint64_t cnt = 0;
|
||||||
CheckInfo ci(pos);
|
CheckInfo ci(pos);
|
||||||
const bool leaf = depth == 2 * ONE_PLY;
|
const bool leaf = depth == 2 * ONE_PLY;
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ static size_t perft(Position& pos, Depth depth) {
|
||||||
return cnt;
|
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();
|
return depth > ONE_PLY ? ::perft(pos, depth) : MoveList<LEGAL>(pos).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ struct LimitsType {
|
||||||
LimitsType() { std::memset(this, 0, sizeof(LimitsType)); }
|
LimitsType() { std::memset(this, 0, sizeof(LimitsType)); }
|
||||||
bool use_time_management() const { return !(mate | movetime | depth | nodes | infinite); }
|
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;
|
int time[COLOR_NB], inc[COLOR_NB], movestogo, depth, nodes, movetime, mate, infinite, ponder;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ struct LimitsType {
|
||||||
/// typically in an async fashion e.g. to stop the search by the GUI.
|
/// typically in an async fashion e.g. to stop the search by the GUI.
|
||||||
|
|
||||||
struct SignalsType {
|
struct SignalsType {
|
||||||
bool stopOnPonderhit, firstRootMove, stop, failedLowAtRoot;
|
bool stop, stopOnPonderhit, firstRootMove, failedLowAtRoot;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;
|
typedef std::auto_ptr<std::stack<StateInfo> > StateStackPtr;
|
||||||
|
@ -103,7 +104,7 @@ extern Time::point SearchTime, IterationTime;
|
||||||
extern StateStackPtr SetupStates;
|
extern StateStackPtr SetupStates;
|
||||||
|
|
||||||
extern void init();
|
extern void init();
|
||||||
extern size_t perft(Position& pos, Depth depth);
|
extern uint64_t perft(Position& pos, Depth depth);
|
||||||
extern void think();
|
extern void think();
|
||||||
|
|
||||||
} // namespace Search
|
} // namespace Search
|
||||||
|
|
|
@ -29,6 +29,8 @@ using namespace Search;
|
||||||
|
|
||||||
ThreadPool Threads; // Global object
|
ThreadPool Threads; // Global object
|
||||||
|
|
||||||
|
extern void check_time();
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// start_routine() is the C function which is called when a new thread
|
// start_routine() is the C function which is called when a new thread
|
||||||
|
@ -90,9 +92,43 @@ Thread::Thread() /* : splitPoints() */ { // Value-initialization bug in MSVC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
// 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.
|
// and then calls check_time(). If msec is 0 thread sleeps until it's woken up.
|
||||||
extern void check_time();
|
|
||||||
|
|
||||||
void TimerThread::idle_loop() {
|
void TimerThread::idle_loop() {
|
||||||
|
|
||||||
|
@ -144,41 +180,6 @@ void MainThread::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
|
// 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
|
// 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
|
// a c'tor because Threads is a static object and we need a fully initialized
|
||||||
|
@ -264,8 +265,7 @@ void Thread::split(Position& pos, const Stack* ss, Value alpha, Value beta, Valu
|
||||||
MovePicker* movePicker, int nodeType, bool cutNode) {
|
MovePicker* movePicker, int nodeType, bool cutNode) {
|
||||||
|
|
||||||
assert(pos.pos_is_ok());
|
assert(pos.pos_is_ok());
|
||||||
assert(*bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE);
|
assert(-VALUE_INFINITE < *bestValue && *bestValue <= alpha && alpha < beta && beta <= VALUE_INFINITE);
|
||||||
assert(*bestValue > -VALUE_INFINITE);
|
|
||||||
assert(depth >= Threads.minimumSplitDepth);
|
assert(depth >= Threads.minimumSplitDepth);
|
||||||
assert(searching);
|
assert(searching);
|
||||||
assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD);
|
assert(splitPointsSize < MAX_SPLITPOINTS_PER_THREAD);
|
||||||
|
@ -367,8 +367,8 @@ void ThreadPool::wait_for_think_finished() {
|
||||||
// start_thinking() wakes up the main thread sleeping in MainThread::idle_loop()
|
// start_thinking() wakes up the main thread sleeping in MainThread::idle_loop()
|
||||||
// so to start a new search, then returns immediately.
|
// so to start a new search, then returns immediately.
|
||||||
|
|
||||||
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
|
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, StateStackPtr& states) {
|
||||||
const std::vector<Move>& searchMoves, StateStackPtr& states) {
|
|
||||||
wait_for_think_finished();
|
wait_for_think_finished();
|
||||||
|
|
||||||
SearchTime = Time::now(); // As early as possible
|
SearchTime = Time::now(); // As early as possible
|
||||||
|
@ -386,8 +386,8 @@ void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MoveList<LEGAL> it(pos); *it; ++it)
|
for (MoveList<LEGAL> it(pos); *it; ++it)
|
||||||
if ( searchMoves.empty()
|
if ( limits.searchmoves.empty()
|
||||||
|| std::count(searchMoves.begin(), searchMoves.end(), *it))
|
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), *it))
|
||||||
RootMoves.push_back(RootMove(*it));
|
RootMoves.push_back(RootMove(*it));
|
||||||
|
|
||||||
main()->thinking = true;
|
main()->thinking = true;
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct SplitPoint {
|
||||||
// Shared data
|
// Shared data
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
volatile uint64_t slavesMask;
|
volatile uint64_t slavesMask;
|
||||||
volatile int64_t nodes;
|
volatile uint64_t nodes;
|
||||||
volatile Value alpha;
|
volatile Value alpha;
|
||||||
volatile Value bestValue;
|
volatile Value bestValue;
|
||||||
volatile Move bestMove;
|
volatile Move bestMove;
|
||||||
|
@ -162,8 +162,7 @@ struct ThreadPool : public std::vector<Thread*> {
|
||||||
void read_uci_options();
|
void read_uci_options();
|
||||||
Thread* available_slave(const Thread* master) const;
|
Thread* available_slave(const Thread* master) const;
|
||||||
void wait_for_think_finished();
|
void wait_for_think_finished();
|
||||||
void start_thinking(const Position&, const Search::LimitsType&,
|
void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&);
|
||||||
const std::vector<Move>&, Search::StateStackPtr&);
|
|
||||||
|
|
||||||
bool sleepWhileIdle;
|
bool sleepWhileIdle;
|
||||||
Depth minimumSplitDepth;
|
Depth minimumSplitDepth;
|
||||||
|
|
|
@ -26,11 +26,11 @@
|
||||||
TranspositionTable TT; // Our global transposition table
|
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
|
/// measured in megabytes. Transposition table consists of a power of 2 number
|
||||||
/// of clusters and each cluster consists of ClusterSize number of TTEntry.
|
/// 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);
|
assert(msb((mbSize << 20) / sizeof(TTEntry)) < 32);
|
||||||
|
|
||||||
|
|
2
src/tt.h
2
src/tt.h
|
@ -81,7 +81,7 @@ public:
|
||||||
const TTEntry* probe(const Key key) const;
|
const TTEntry* probe(const Key key) const;
|
||||||
TTEntry* first_entry(const Key key) const;
|
TTEntry* first_entry(const Key key) const;
|
||||||
void refresh(const TTEntry* tte) const;
|
void refresh(const TTEntry* tte) const;
|
||||||
void set_size(uint64_t mbSize);
|
void resize(uint64_t mbSize);
|
||||||
void clear();
|
void clear();
|
||||||
void store(const Key key, Value v, Bound type, Depth d, Move m, Value statV);
|
void store(const Key key, Value v, Bound type, Depth d, Move m, Value statV);
|
||||||
|
|
||||||
|
|
|
@ -194,14 +194,13 @@ namespace {
|
||||||
void go(const Position& pos, istringstream& is) {
|
void go(const Position& pos, istringstream& is) {
|
||||||
|
|
||||||
Search::LimitsType limits;
|
Search::LimitsType limits;
|
||||||
vector<Move> searchMoves;
|
|
||||||
string token;
|
string token;
|
||||||
|
|
||||||
while (is >> token)
|
while (is >> token)
|
||||||
{
|
{
|
||||||
if (token == "searchmoves")
|
if (token == "searchmoves")
|
||||||
while (is >> token)
|
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 == "wtime") is >> limits.time[WHITE];
|
||||||
else if (token == "btime") is >> limits.time[BLACK];
|
else if (token == "btime") is >> limits.time[BLACK];
|
||||||
|
@ -216,6 +215,6 @@ namespace {
|
||||||
else if (token == "ponder") limits.ponder = true;
|
else if (token == "ponder") limits.ponder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Threads.start_thinking(pos, limits, searchMoves, SetupStates);
|
Threads.start_thinking(pos, limits, SetupStates);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace UCI {
|
||||||
void on_logger(const Option& o) { start_logger(o); }
|
void on_logger(const Option& o) { start_logger(o); }
|
||||||
void on_eval(const Option&) { Eval::init(); }
|
void on_eval(const Option&) { Eval::init(); }
|
||||||
void on_threads(const Option&) { Threads.read_uci_options(); }
|
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(); }
|
void on_clear_hash(const Option&) { TT.clear(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,16 +115,16 @@ std::ostream& operator<<(std::ostream& os, const OptionsMap& om) {
|
||||||
|
|
||||||
/// Option class constructors and conversion operators
|
/// 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; }
|
{ 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"); }
|
{ 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(); }
|
{ std::ostringstream ss; ss << v; defaultValue = currentValue = ss.str(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ Option& Option::operator=(const string& v) {
|
||||||
currentValue = v;
|
currentValue = v;
|
||||||
|
|
||||||
if (on_change)
|
if (on_change)
|
||||||
(*on_change)(*this);
|
on_change(*this);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,13 +38,13 @@ typedef std::map<std::string, Option, CaseInsensitiveLess> OptionsMap;
|
||||||
/// Option class implements an option as defined by UCI protocol
|
/// Option class implements an option as defined by UCI protocol
|
||||||
class Option {
|
class Option {
|
||||||
|
|
||||||
typedef void (Fn)(const Option&);
|
typedef void (*OnChange)(const Option&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Option(Fn* = NULL);
|
Option(OnChange = NULL);
|
||||||
Option(bool v, Fn* = NULL);
|
Option(bool v, OnChange = NULL);
|
||||||
Option(const char* v, Fn* = NULL);
|
Option(const char* v, OnChange = NULL);
|
||||||
Option(int v, int min, int max, Fn* = NULL);
|
Option(int v, int min, int max, OnChange = NULL);
|
||||||
|
|
||||||
Option& operator=(const std::string& v);
|
Option& operator=(const std::string& v);
|
||||||
operator int() const;
|
operator int() const;
|
||||||
|
@ -56,7 +56,7 @@ private:
|
||||||
std::string defaultValue, currentValue, type;
|
std::string defaultValue, currentValue, type;
|
||||||
int min, max;
|
int min, max;
|
||||||
size_t idx;
|
size_t idx;
|
||||||
Fn* on_change;
|
OnChange on_change;
|
||||||
};
|
};
|
||||||
|
|
||||||
void init(OptionsMap&);
|
void init(OptionsMap&);
|
||||||
|
|
Loading…
Add table
Reference in a new issue