From: Marco Costalba Date: Wed, 28 Mar 2012 05:40:17 +0000 (-0700) Subject: Merge pull request #11 from glinscott/squash X-Git-Url: https://git.sesse.net/?p=stockfish;a=commitdiff_plain;h=cc2b3ece5c5d8d1183f8526fbb0ee4e1ea7a69fe;hp=374c9e6b63d0e233371ae38cc054d885f2117884 Merge pull request #11 from glinscott/squash Add more detailed pawn shelter/storm evaluation After 10670 games at 10"+0.05 Mod vs Orig 2277 - 1941 - 6452 ELO +11 !!! The first real increase since 2.2.2, congratulations Gary !!! Signed-off-by: Marco Costalba --- diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 4124899b..136c6e80 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -74,13 +74,13 @@ void benchmark(int argc, char* argv[]) { Options["Threads"] = threads; if (valType == "time") - limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms + limits.movetime = 1000 * atoi(valStr.c_str()); // movetime is in ms else if (valType == "nodes") - limits.maxNodes = atoi(valStr.c_str()); + limits.nodes = atoi(valStr.c_str()); else - limits.maxDepth = atoi(valStr.c_str()); + limits.depth = atoi(valStr.c_str()); if (fenFile != "default") { @@ -112,13 +112,14 @@ void benchmark(int argc, char* argv[]) { if (valType == "perft") { - int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY); - cerr << "\nPerft " << limits.maxDepth << " leaf nodes: " << cnt << endl; + int64_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); + Threads.start_searching(pos, limits); + Threads.wait_for_search_finished(); nodes += Search::RootPosition.nodes_searched(); } } diff --git a/src/evaluate.cpp b/src/evaluate.cpp index b2cae94c..6e515d88 100644 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@ -167,8 +167,8 @@ namespace { // happen in Chess960 games. const Score TrappedBishopA1H1Penalty = make_score(100, 100); - // Penalty for a minor piece that is not defended by anything - const Score UndefendedMinorPenalty = make_score(25, 10); + // Penalty for BNR that is not defended by anything + const Score UndefendedPiecePenalty = make_score(25, 10); // The SpaceMask[Color] contains the area of the board which is considered // by the space evaluation. In the middle game, each side is given a bonus @@ -678,21 +678,24 @@ Value do_evaluate(const Position& pos, Value& margin) { const Color Them = (Us == WHITE ? BLACK : WHITE); - Bitboard b; + Bitboard b, undefended, undefendedMinors, weakEnemies; Score score = SCORE_ZERO; - // Undefended minors get penalized even if not under attack - Bitboard undefended = pos.pieces(Them) - & (pos.pieces(BISHOP) | pos.pieces(KNIGHT)) - & ~ei.attackedBy[Them][0]; - if (undefended) - score += single_bit(undefended) ? UndefendedMinorPenalty - : UndefendedMinorPenalty * 2; + // Undefended pieces get penalized even if not under attack + undefended = pos.pieces(Them) & ~ei.attackedBy[Them][0]; + undefendedMinors = undefended & (pos.pieces(BISHOP) | pos.pieces(KNIGHT)); + + if (undefendedMinors) + score += single_bit(undefendedMinors) ? UndefendedPiecePenalty + : UndefendedPiecePenalty * 2; + if (undefended & pos.pieces(ROOK)) + score += UndefendedPiecePenalty; // Enemy pieces not defended by a pawn and under our attack - Bitboard weakEnemies = pos.pieces(Them) - & ~ei.attackedBy[Them][PAWN] - & ei.attackedBy[Us][0]; + weakEnemies = pos.pieces(Them) + & ~ei.attackedBy[Them][PAWN] + & ei.attackedBy[Us][0]; + if (!weakEnemies) return score; diff --git a/src/search.cpp b/src/search.cpp index a76a9521..8d0c0c6b 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -254,7 +254,7 @@ void Search::think() { Chess960 = pos.is_chess960(); Eval::RootColor = pos.side_to_move(); SearchTime.restart(); - TimeMgr.init(Limits, pos.startpos_ply_counter()); + TimeMgr.init(Limits, pos.startpos_ply_counter(), pos.side_to_move()); TT.new_search(); H.clear(); @@ -292,9 +292,9 @@ void Search::think() { log << "\nSearching: " << pos.to_fen() << "\ninfinite: " << Limits.infinite << " ponder: " << Limits.ponder - << " time: " << Limits.time - << " increment: " << Limits.increment - << " moves to go: " << Limits.movesToGo + << " time: " << Limits.times[pos.side_to_move()] + << " increment: " << Limits.incs[pos.side_to_move()] + << " moves to go: " << Limits.movestogo << endl; } @@ -362,7 +362,7 @@ namespace { ss->currentMove = MOVE_NULL; // Hack to skip update gains // Iterative deepening loop until requested to stop or target depth reached - while (!Signals.stop && ++depth <= MAX_PLY && (!Limits.maxDepth || depth <= Limits.maxDepth)) + while (!Signals.stop && ++depth <= MAX_PLY && (!Limits.depth || depth <= Limits.depth)) { // Save last iteration's scores before first PV line is searched and all // the move scores but the (new) PV are set to -VALUE_INFINITE. @@ -584,7 +584,7 @@ namespace { // Step 2. Check for aborted search and immediate draw // Enforce node limit here. FIXME: This only works with 1 search thread. - if (Limits.maxNodes && pos.nodes_searched() >= Limits.maxNodes) + if (Limits.nodes && pos.nodes_searched() >= Limits.nodes) Signals.stop = true; if (( Signals.stop @@ -1894,6 +1894,6 @@ void check_time() { || stillAtFirstMove; if ( (Limits.use_time_management() && noMoreTime) - || (Limits.maxTime && e >= Limits.maxTime)) + || (Limits.movetime && e >= Limits.movetime)) Signals.stop = true; } diff --git a/src/search.h b/src/search.h index bd371a4a..c957c34b 100644 --- a/src/search.h +++ b/src/search.h @@ -77,9 +77,9 @@ struct RootMove { struct LimitsType { LimitsType() { memset(this, 0, sizeof(LimitsType)); } - bool use_time_management() const { return !(maxTime | maxDepth | maxNodes | infinite); } + bool use_time_management() const { return !(movetime | depth | nodes | infinite); } - int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder; + int times[2], incs[2], movestogo, depth, nodes, movetime, infinite, ponder; }; diff --git a/src/thread.cpp b/src/thread.cpp index f2a2c821..6a5454fa 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -50,7 +50,7 @@ Thread::Thread(Fn fn) { start_fn = fn; threadID = Threads.size(); - do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_thinking() + do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_searching() lock_init(sleepLock); cond_init(sleepCond); @@ -154,10 +154,7 @@ void Thread::wait_for_stop_or_ponderhit() { Signals.stopOnPonderhit = true; lock_grab(sleepLock); - - while (!Signals.stop) - cond_wait(sleepCond, sleepLock); - + while (!Signals.stop) cond_wait(sleepCond, sleepLock); lock_release(sleepLock); } @@ -258,8 +255,8 @@ void ThreadsManager::wake_up() const { for (int i = 0; i < size(); i++) { - threads[i]->do_sleep = false; threads[i]->maxPly = 0; + threads[i]->do_sleep = false; if (!useSleepingThreads) threads[i]->wake_up(); @@ -273,7 +270,7 @@ void ThreadsManager::wake_up() const { void ThreadsManager::sleep() const { for (int i = 1; i < size(); i++) // Main thread will go to sleep by itself - threads[i]->do_sleep = true; // to avoid a race with start_thinking() + threads[i]->do_sleep = true; // to avoid a race with start_searching() } @@ -415,19 +412,24 @@ void ThreadsManager::set_timer(int msec) { } -// ThreadsManager::start_thinking() is used by UI thread to wake up the main -// thread parked in main_loop() and starting a new search. If async is true -// then function returns immediately, otherwise caller is blocked waiting for -// the search to finish. +// ThreadsManager::wait_for_search_finished() waits for main thread to go to +// sleep, this means search is finished. Then returns. + +void ThreadsManager::wait_for_search_finished() { + + Thread* main = threads[0]; + lock_grab(main->sleepLock); + while (!main->do_sleep) cond_wait(sleepCond, main->sleepLock); + lock_release(main->sleepLock); +} -void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limits, - const std::set& searchMoves, bool async) { - Thread& main = *threads.front(); - lock_grab(main.sleepLock); +// ThreadsManager::start_searching() wakes up the main thread sleeping in +// main_loop() so to start a new search, then returns immediately. - while (!main.do_sleep) - cond_wait(sleepCond, main.sleepLock); // Wait main thread has finished +void ThreadsManager::start_searching(const Position& pos, const LimitsType& limits, + const std::set& searchMoves) { + wait_for_search_finished(); Signals.stopOnPonderhit = Signals.firstRootMove = false; Signals.stop = Signals.failedLowAtRoot = false; @@ -440,33 +442,6 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit if (searchMoves.empty() || searchMoves.count(ml.move())) RootMoves.push_back(RootMove(ml.move())); - main.do_sleep = false; - cond_signal(main.sleepCond); // Wake up main thread and start searching - - if (!async) - while (!main.do_sleep) - cond_wait(sleepCond, main.sleepLock); - - lock_release(main.sleepLock); -} - - -// ThreadsManager::stop_thinking() is used by UI thread to raise a stop request -// and to wait for the main thread finishing the search. We cannot return before -// main has finished to avoid a crash in case of a 'quit' command. - -void ThreadsManager::stop_thinking() { - - Thread& main = *threads.front(); - - Search::Signals.stop = true; - - lock_grab(main.sleepLock); - - cond_signal(main.sleepCond); // In case is waiting for stop or ponderhit - - while (!main.do_sleep) - cond_wait(sleepCond, main.sleepLock); - - lock_release(main.sleepLock); + threads[0]->do_sleep = false; + threads[0]->wake_up(); } diff --git a/src/thread.h b/src/thread.h index 04e02306..9b0a8bcf 100644 --- a/src/thread.h +++ b/src/thread.h @@ -47,7 +47,6 @@ struct SplitPoint { MovePicker* mp; SplitPoint* parent; - // Shared data Lock lock; volatile uint64_t slavesMask; @@ -125,9 +124,9 @@ public: void read_uci_options(); bool available_slave_exists(int master) const; void set_timer(int msec); - void stop_thinking(); - void start_thinking(const Position& pos, const Search::LimitsType& limits, - const std::set& = std::set(), bool async = false); + void wait_for_search_finished(); + void start_searching(const Position& pos, const Search::LimitsType& limits, + const std::set& = std::set()); template Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove, diff --git a/src/timeman.cpp b/src/timeman.cpp index 9ca46c93..d545269c 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -83,7 +83,7 @@ void TimeManager::pv_instability(int curChanges, int prevChanges) { } -void TimeManager::init(const Search::LimitsType& limits, int currentPly) +void TimeManager::init(const Search::LimitsType& limits, int currentPly, Color us) { /* We support four different kind of time controls: @@ -111,15 +111,15 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly) // Initialize to maximum values but unstablePVExtraTime that is reset unstablePVExtraTime = 0; - optimumSearchTime = maximumSearchTime = limits.time; + optimumSearchTime = maximumSearchTime = limits.times[us]; // We calculate optimum time usage for different hypothetic "moves to go"-values and choose the // minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values. - for (hypMTG = 1; hypMTG <= (limits.movesToGo ? std::min(limits.movesToGo, MoveHorizon) : MoveHorizon); hypMTG++) + for (hypMTG = 1; hypMTG <= (limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon); hypMTG++) { // Calculate thinking time for hypothetic "moves to go"-value - hypMyTime = limits.time - + limits.increment * (hypMTG - 1) + hypMyTime = limits.times[us] + + limits.incs[us] * (hypMTG - 1) - emergencyBaseTime - emergencyMoveTime * std::min(hypMTG, emergencyMoveHorizon); diff --git a/src/timeman.h b/src/timeman.h index 2030cc20..ddf96c67 100644 --- a/src/timeman.h +++ b/src/timeman.h @@ -25,7 +25,7 @@ class TimeManager { public: - void init(const Search::LimitsType& limits, int currentPly); + void init(const Search::LimitsType& limits, int currentPly, Color us); void pv_instability(int curChanges, int prevChanges); int available_time() const { return optimumSearchTime + unstablePVExtraTime; } int maximum_time() const { return maximumSearchTime; } diff --git a/src/uci.cpp b/src/uci.cpp index 718c7875..1b770506 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -67,7 +67,12 @@ void uci_loop() { is >> skipws >> token; if (token == "quit" || token == "stop") - Threads.stop_thinking(); + { + Search::Signals.stop = true; + + if (token == "quit") // Cannot quit while threads are still running + Threads.wait_for_search_finished(); + } else if (token == "ponderhit") { @@ -77,7 +82,7 @@ void uci_loop() { Search::Limits.ponder = false; if (Search::Signals.stopOnPonderhit) - Threads.stop_thinking(); + Search::Signals.stop = true; } else if (token == "go") @@ -184,46 +189,42 @@ namespace { // go() is called when engine receives the "go" UCI command. The function sets // the thinking time and other parameters from the input string, and then starts - // the main searching thread. + // the search. void go(Position& pos, istringstream& is) { - string token; Search::LimitsType limits; std::set searchMoves; - int time[] = { 0, 0 }, inc[] = { 0, 0 }; + string token; while (is >> token) { - if (token == "infinite") - limits.infinite = true; - else if (token == "ponder") - limits.ponder = true; - else if (token == "wtime") - is >> time[WHITE]; + if (token == "wtime") + is >> limits.times[WHITE]; else if (token == "btime") - is >> time[BLACK]; + is >> limits.times[BLACK]; else if (token == "winc") - is >> inc[WHITE]; + is >> limits.incs[WHITE]; else if (token == "binc") - is >> inc[BLACK]; + is >> limits.incs[BLACK]; else if (token == "movestogo") - is >> limits.movesToGo; + is >> limits.movestogo; else if (token == "depth") - is >> limits.maxDepth; + is >> limits.depth; else if (token == "nodes") - is >> limits.maxNodes; + is >> limits.nodes; else if (token == "movetime") - is >> limits.maxTime; + is >> limits.movetime; + else if (token == "infinite") + limits.infinite = true; + else if (token == "ponder") + limits.ponder = true; else if (token == "searchmoves") while (is >> token) searchMoves.insert(move_from_uci(pos, token)); } - limits.time = time[pos.side_to_move()]; - limits.increment = inc[pos.side_to_move()]; - - Threads.start_thinking(pos, limits, searchMoves, true); + Threads.start_searching(pos, limits, searchMoves); }