summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
aa242d2)
The only interesting change is the moving of
stack[MAX_PLY+4] back to its original position
in id_loop (now renamed Thread::search).
No functional change.
void benchmark(const Position& current, istream& is) {
string token;
void benchmark(const Position& current, istream& is) {
string token;
- Search::LimitsType limits;
+ Search::LimitsType limits;
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "16";
// Assign default values to missing arguments
string ttSize = (is >> token) ? token : "16";
Options["Hash"] = ttSize;
Options["Threads"] = threads;
Options["Hash"] = ttSize;
Options["Threads"] = threads;
- limits.movetime = stoi(limit); // movetime is in ms
+ limits.movetime = stoi(limit); // movetime is in millisecs
else if (limitType == "nodes")
limits.nodes = stoi(limit);
else if (limitType == "nodes")
limits.nodes = stoi(limit);
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
if (limitType == "perft")
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
if (limitType == "perft")
- nodes += Search::perft<true>(pos, limits.depth * ONE_PLY);
+ nodes += Search::perft(pos, limits.depth * ONE_PLY);
const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
// Pawn Rank based scaling factors used in KRPPKRP endgame
const int PushAway [8] = { 0, 5, 20, 40, 60, 80, 90, 100 };
// Pawn Rank based scaling factors used in KRPPKRP endgame
- const int KRPPKRPScaleFactors[RANK_NB] = {0, 9, 10, 14, 21, 44, 0, 0};
+ const int KRPPKRPScaleFactors[RANK_NB] = { 0, 9, 10, 14, 21, 44, 0, 0 };
#ifndef NDEBUG
bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
#ifndef NDEBUG
bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
-/// Search::reset() clears all search memory, to obtain reproducible search results
+/// Search::clear() resets to zero search state, to obtain reproducible results
TT.clear();
CounterMovesHistory.clear();
TT.clear();
CounterMovesHistory.clear();
-template uint64_t Search::perft<true>(Position& pos, Depth depth);
+template uint64_t Search::perft<true>(Position&, Depth);
/// MainThread::think() is called by the main thread when the program receives
/// MainThread::think() is called by the main thread when the program receives
void Thread::search(bool isMainThread) {
void Thread::search(bool isMainThread) {
- Stack* ss = stack + 2; // To allow referencing (ss-2) and (ss+2)
+ Stack stack[MAX_PLY+4], *ss = stack+2; // To allow referencing (ss-2) and (ss+2)
Value bestValue, alpha, beta, delta;
Move easyMove = MOVE_NONE;
Value bestValue, alpha, beta, delta;
Move easyMove = MOVE_NONE;
{
// Step 2. Check for aborted search and immediate draw
if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw() || ss->ply >= MAX_PLY)
{
// Step 2. Check for aborted search and immediate draw
if (Signals.stop.load(std::memory_order_relaxed) || pos.is_draw() || ss->ply >= MAX_PLY)
- return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
+ return ss->ply >= MAX_PLY && !inCheck ? evaluate(pos)
: DrawValue[pos.side_to_move()];
// Step 3. Mate distance pruning. Even if we mate at the next move our score
: DrawValue[pos.side_to_move()];
// Step 3. Mate distance pruning. Even if we mate at the next move our score
if (RootNode && thisThread == Threads.main())
{
if (RootNode && thisThread == Threads.main())
{
- Signals.firstRootMove = moveCount == 1;
+ Signals.firstRootMove = (moveCount == 1);
if (Time.elapsed() > 3000)
sync_cout << "info depth " << depth / ONE_PLY
if (Time.elapsed() > 3000)
sync_cout << "info depth " << depth / ONE_PLY
&& is_ok((ss - 1)->currentMove)
&& is_ok((ss - 2)->currentMove))
{
&& is_ok((ss - 1)->currentMove)
&& is_ok((ss - 2)->currentMove))
{
- Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY -1);
+ Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
Square prevPrevSq = to_sq((ss - 2)->currentMove);
CounterMovesStats& prevCmh = CounterMovesHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
prevCmh.update(pos.piece_on(prevSq), prevSq, bonus);
Square prevPrevSq = to_sq((ss - 2)->currentMove);
CounterMovesStats& prevCmh = CounterMovesHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
prevCmh.update(pos.piece_on(prevSq), prevSq, bonus);
- // update_stats() updates killers, history, countermove history and
- // countermoves stats for a quiet best move.
+ // update_stats() updates killers, history, countermove and countermove
+ // history when a new quiet best move is found.
void update_stats(const Position& pos, Stack* ss, Move move,
Depth depth, Move* quiets, int quietsCnt) {
void update_stats(const Position& pos, Stack* ss, Move move,
Depth depth, Move* quiets, int quietsCnt) {
- Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY -1);
+ Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + depth / ONE_PLY - 1);
Square prevSq = to_sq((ss-1)->currentMove);
CounterMovesStats& cmh = CounterMovesHistory[pos.piece_on(prevSq)][prevSq];
Square prevSq = to_sq((ss-1)->currentMove);
CounterMovesStats& cmh = CounterMovesHistory[pos.piece_on(prevSq)][prevSq];
cmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
}
cmh.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
}
- // Extra penalty for TT move in previous ply when it gets refuted
+ // Extra penalty for a quiet TT move in previous ply when it gets refuted
if ( (ss-1)->moveCount == 1
&& !pos.captured_piece_type()
&& is_ok((ss-2)->currentMove))
{
Square prevPrevSq = to_sq((ss-2)->currentMove);
CounterMovesStats& prevCmh = CounterMovesHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
if ( (ss-1)->moveCount == 1
&& !pos.captured_piece_type()
&& is_ok((ss-2)->currentMove))
{
Square prevPrevSq = to_sq((ss-2)->currentMove);
CounterMovesStats& prevCmh = CounterMovesHistory[pos.piece_on(prevPrevSq)][prevPrevSq];
- prevCmh.update(pos.piece_on(prevSq), prevSq, -bonus - 2 * ((depth + 1) / ONE_PLY));
+ prevCmh.update(pos.piece_on(prevSq), prevSq, -bonus - 2 * (depth + 1) / ONE_PLY);
Move Skill::pick_best(size_t multiPV) {
Move Skill::pick_best(size_t multiPV) {
- // PRNG sequence should be non-deterministic, so we seed it with the time at init
const Search::RootMoveVector& rootMoves = Threads.main()->rootMoves;
const Search::RootMoveVector& rootMoves = Threads.main()->rootMoves;
- static PRNG rng(now());
+ static PRNG rng(now()); // PRNG sequence should be non-deterministic
// RootMoves are already sorted by score in descending order
// RootMoves are already sorted by score in descending order
- int variance = std::min(rootMoves[0].score - rootMoves[multiPV - 1].score, PawnValueMg);
+ Value topScore = rootMoves[0].score;
+ int delta = std::min(topScore - rootMoves[multiPV - 1].score, PawnValueMg);
int weakness = 120 - 2 * level;
int maxScore = -VALUE_INFINITE;
int weakness = 120 - 2 * level;
int maxScore = -VALUE_INFINITE;
- // Choose best move. For each move score we add two terms both dependent on
+ // Choose best move. For each move score we add two terms, both dependent on
// weakness. One deterministic and bigger for weaker levels, and one random,
// then we choose the move with the resulting highest score.
for (size_t i = 0; i < multiPV; ++i)
{
// This is our magic formula
// weakness. One deterministic and bigger for weaker levels, and one random,
// then we choose the move with the resulting highest score.
for (size_t i = 0; i < multiPV; ++i)
{
// This is our magic formula
- int push = ( weakness * int(rootMoves[0].score - rootMoves[i].score)
- + variance * (rng.rand<unsigned>() % weakness)) / 128;
+ int push = ( weakness * int(topScore - rootMoves[i].score)
+ + delta * (rng.rand<unsigned>() % weakness)) / 128;
if (rootMoves[i].score + push > maxScore)
{
if (rootMoves[i].score + push > maxScore)
{
best = rootMoves[i].pv[0];
}
}
best = rootMoves[i].pv[0];
}
}
TTEntry* tte = TT.probe(pos.key(), ttHit);
if (!ttHit || tte->move() != m) // Don't overwrite correct entries
TTEntry* tte = TT.probe(pos.key(), ttHit);
if (!ttHit || tte->move() != m) // Don't overwrite correct entries
- tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, m, VALUE_NONE, TT.generation());
+ tte->save(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE,
+ m, VALUE_NONE, TT.generation());
pos.do_move(m, *st++, pos.gives_check(m, CheckInfo(pos)));
}
pos.do_move(m, *st++, pos.gives_check(m, CheckInfo(pos)));
}
-/// RootMove::extract_ponder_from_tt() is called in case we have no ponder move before
-/// exiting the search, for instance in case we stop the search during a fail high at
-/// root. We try hard to have a ponder move to return to the GUI, otherwise in case of
-/// 'ponder on' we have nothing to think on.
+/// RootMove::extract_ponder_from_tt() is called in case we have no ponder move
+/// before exiting the search, for instance in case we stop the search during a
+/// fail high at root. We try hard to have a ponder move to return to the GUI,
+/// otherwise in case of 'ponder on' we have nothing to think on.
bool RootMove::extract_ponder_from_tt(Position& pos)
{
bool RootMove::extract_ponder_from_tt(Position& pos)
{
-/// check_time() is called by the timer thread when the timer triggers. It is
-/// used to print debug info and, more importantly, to detect when we are out of
+/// TimerThread::check_time() is called by when the timer triggers. It is used
+/// to print debug info and, more importantly, to detect when we are out of
/// available time and thus stop the search.
/// available time and thus stop the search.
+void TimerThread::check_time() {
static TimePoint lastInfoTime = now();
int elapsed = Time.elapsed();
static TimePoint lastInfoTime = now();
int elapsed = Time.elapsed();
extern StateStackPtr SetupStates;
void init();
extern StateStackPtr SetupStates;
void init();
-void reset();
-template<bool Root> uint64_t perft(Position& pos, Depth depth);
+void clear();
+template<bool Root = true> uint64_t perft(Position& pos, Depth depth);
ThreadPool Threads; // Global object
ThreadPool Threads; // Global object
-extern void check_time();
-
namespace {
// Helpers to launch a thread after creation and joining before delete. Outside the
namespace {
// Helpers to launch a thread after creation and joining before delete. Outside the
-// Thread constructor makes some init but does not launch any execution thread,
+// Thread constructor makes some init but does not launch any execution thread,
// which will be started only when the constructor returns.
Thread::Thread() {
// which will be started only when the constructor returns.
Thread::Thread() {
// ThreadPool::init() is called at startup to create and launch requested threads,
// ThreadPool::init() is called at startup to create and launch requested threads,
-// that will go immediately to sleep. We cannot use a constructor because Threads
+// that will go immediately to sleep. We cannot use a constructor because Threads
// is a static object and we need a fully initialized engine at this point due to
// allocation of Endgames in the Thread constructor.
// is a static object and we need a fully initialized engine at this point due to
// allocation of Endgames in the Thread constructor.
#include "search.h"
#include "thread_win32.h"
#include "search.h"
#include "thread_win32.h"
-struct Thread;
-
-const size_t MAX_THREADS = 128;
-
/// ThreadBase struct is the base of the hierarchy from where we derive all the
/// specialized thread classes.
/// ThreadBase struct is the base of the hierarchy from where we derive all the
/// specialized thread classes.
Position rootPos;
Search::RootMoveVector rootMoves;
Depth rootDepth;
Position rootPos;
Search::RootMoveVector rootMoves;
Depth rootDepth;
- Search::Stack stack[MAX_PLY+4];
HistoryStats history;
MovesStats counterMoves;
};
HistoryStats history;
MovesStats counterMoves;
};
static const int Resolution = 5; // Millisec between two check_time() calls
virtual void idle_loop();
static const int Resolution = 5; // Millisec between two check_time() calls
virtual void idle_loop();
else if (token == "ucinewgame")
{
else if (token == "ucinewgame")
{
Time.availableNodes = 0;
}
else if (token == "isready") sync_cout << "readyok" << sync_endl;
Time.availableNodes = 0;
}
else if (token == "isready") sync_cout << "readyok" << sync_endl;
namespace UCI {
/// 'On change' actions, triggered by an option's value change
namespace UCI {
/// 'On change' actions, triggered by an option's value change
-void on_clear_hash(const Option&) { Search::reset(); }
+void on_clear_hash(const Option&) { Search::clear(); }
void on_hash_size(const Option& o) { TT.resize(o); }
void on_logger(const Option& o) { start_logger(o); }
void on_threads(const Option&) { Threads.read_uci_options(); }
void on_hash_size(const Option& o) { TT.resize(o); }
void on_logger(const Option& o) { start_logger(o); }
void on_threads(const Option&) { Threads.read_uci_options(); }
o["Write Debug Log"] << Option(false, on_logger);
o["Contempt"] << Option(0, -100, 100);
o["Write Debug Log"] << Option(false, on_logger);
o["Contempt"] << Option(0, -100, 100);
- o["Threads"] << Option(1, 1, MAX_THREADS, on_threads);
+ o["Threads"] << Option(1, 1, 128, on_threads);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Clear Hash"] << Option(on_clear_hash);
o["Ponder"] << Option(true);
o["Hash"] << Option(16, 1, MaxHashMB, on_hash_size);
o["Clear Hash"] << Option(on_clear_hash);
o["Ponder"] << Option(true);