refactor: 清理无用代码

This commit is contained in:
Calcitem 2020-10-23 02:01:12 +08:00
parent 7594c6e31d
commit 3726ad9635
22 changed files with 48 additions and 1065 deletions

View File

@ -456,7 +456,6 @@
<ClInclude Include="src\movegen.h" />
<ClInclude Include="src\movepick.h" />
<ClInclude Include="src\search.h" />
<ClInclude Include="src\timeman.h" />
<ClInclude Include="src\trainer.h" />
<ClInclude Include="src\tt.h" />
<ClInclude Include="src\debug.h" />
@ -720,7 +719,6 @@
<ClCompile Include="src\movegen.cpp" />
<ClCompile Include="src\movepick.cpp" />
<ClCompile Include="src\search.cpp" />
<ClCompile Include="src\timeman.cpp" />
<ClCompile Include="src\trainer.cpp" />
<ClCompile Include="src\tt.cpp" />
<ClCompile Include="src\misc.cpp" />

View File

@ -120,9 +120,6 @@
<ClInclude Include="src\uci.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\timeman.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\thread_win32_osx.h">
<Filter>Qt Files</Filter>
</ClInclude>
@ -356,9 +353,6 @@
<ClCompile Include="src\ucioption.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\timeman.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\benchmark.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -35,11 +35,6 @@ enum Tracing
NO_TRACE, TRACE
};
double to_cp(Value v)
{
return double(v) / StoneValue;
}
}
using namespace Trace;
@ -176,37 +171,15 @@ Value Eval::evaluate(Position &pos)
/// a string (suitable for outputting to stdout) that contains the detailed
/// descriptions and values of each evaluation term. Useful for debugging.
std::string Eval::trace(const Position &pos)
std::string Eval::trace(Position &pos)
{
#if 0
std::memset(scores, 0, sizeof(scores));
Value v = Evaluation<TRACE>(pos).value();
// TODO
//pos.this_thread()->contempt = 0 // TODO: SCORE_ZERO; // Reset any dynamic contempt
Value v = Evaluation<TRACE>(pos)->value();
v = pos.side_to_move() == WHITE ? v : -v; // Trace scores are from white's point of view
v = pos.side_to_move() == BLACK ? v : -v; // Trace scores are from black's point of view
std::stringstream ss;
ss << std::showpoint << std::noshowpos << std::fixed << std::setprecision(2)
<< " Term | White | Black | Total \n"
<< " | MG EG | MG EG | MG EG \n"
<< " ------------+-------------+-------------+------------\n"
<< " Material | " << Term(MATERIAL)
<< " Imbalance | " << Term(IMBALANCE)
<< " Mobility | " << Term(MOBILITY)
<< " Threats | " << Term(THREAT)
<< " Passed | " << Term(PASSED)
<< " Space | " << Term(SPACE)
<< " Initiative | " << Term(INITIATIVE)
<< " ------------+-------------+-------------+------------\n"
<< " Total | " << Term(TOTAL);
ss << "\nTotal evaluation: " << to_cp(v) << " (white side)\n";
ss << "\nTotal evaluation: " << v << " (black side)\n";
return ss.str();
#endif
//pos = pos;
return "";
}
}

View File

@ -28,7 +28,7 @@ class Position;
namespace Eval {
std::string trace(const Position &pos);
std::string trace(Position &pos);
Value evaluate(Position &pos);
};

View File

@ -133,7 +133,6 @@ template<>
void MoveList<LEGAL>::create()
{
// Note: Not follow order of MoveDirection array
#if 1
const int moveTable_obliqueLine[SQUARE_NB][MD_NB] = {
/* 0 */ {0, 0, 0, 0},
/* 1 */ {0, 0, 0, 0},
@ -227,101 +226,6 @@ void MoveList<LEGAL>::create()
/* 38 */ {0, 0, 0, 0},
/* 39 */ {0, 0, 0, 0},
};
#else
const int moveTable_obliqueLine[Position::N_LOCATIONS][MD_NB] = {
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{9, 15, 0, 16},
{10, 8, 0, 17},
{11, 9, 0, 18},
{12, 10, 0, 19},
{13, 11, 0, 20},
{14, 12, 0, 21},
{15, 13, 0, 22},
{8, 14, 0, 23},
{17, 23, 8, 24},
{18, 16, 9, 25},
{19, 17, 10, 26},
{20, 18, 11, 27},
{21, 19, 12, 28},
{22, 20, 13, 29},
{23, 21, 14, 30},
{16, 22, 15, 31},
{25, 31, 16, 0},
{26, 24, 17, 0},
{27, 25, 18, 0},
{28, 26, 19, 0},
{29, 27, 20, 0},
{30, 28, 21, 0},
{31, 29, 22, 0},
{24, 30, 23, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
};
const int moveTable_noObliqueLine[Position::N_LOCATIONS][MD_NB] = {
/* 0 */ {0, 0, 0, 0},
/* 1 */ {0, 0, 0, 0},
/* 2 */ {0, 0, 0, 0},
/* 3 */ {0, 0, 0, 0},
/* 4 */ {0, 0, 0, 0},
/* 5 */ {0, 0, 0, 0},
/* 6 */ {0, 0, 0, 0},
/* 7 */ {0, 0, 0, 0},
/* 8 */ {9, 15, 0, 16},
/* 9 */ {10, 8, 0, 0},
/* 10 */ {11, 9, 0, 18},
/* 11 */ {12, 10, 0, 0},
/* 12 */ {13, 11, 0, 20},
/* 13 */ {14, 12, 0, 0},
/* 14 */ {15, 13, 0, 22},
/* 15 */ {8, 14, 0, 0},
/* 16 */ {17, 23, 8, 24},
/* 17 */ {18, 16, 0, 0},
/* 18 */ {19, 17, 10, 26},
/* 19 */ {20, 18, 0, 0},
/* 20 */ {21, 19, 12, 28},
/* 21 */ {22, 20, 0, 0},
/* 22 */ {23, 21, 14, 30},
/* 23 */ {16, 22, 0, 0},
/* 24 */ {25, 31, 16, 0},
/* 25 */ {26, 24, 0, 0},
/* 26 */ {27, 25, 18, 0},
/* 27 */ {28, 26, 0, 0},
/* 28 */ {29, 27, 20, 0},
/* 29 */ {30, 28, 0, 0},
/* 30 */ {31, 29, 22, 0},
/* 31 */ {24, 30, 0, 0},
/* 32 */ {0, 0, 0, 0},
/* 33 */ {0, 0, 0, 0},
/* 34 */ {0, 0, 0, 0},
/* 35 */ {0, 0, 0, 0},
/* 36 */ {0, 0, 0, 0},
/* 37 */ {0, 0, 0, 0},
/* 38 */ {0, 0, 0, 0},
/* 39 */ {0, 0, 0, 0},
};
#endif
if (rule->hasObliqueLines) {
memcpy(moveTable, moveTable_obliqueLine, sizeof(moveTable));

View File

@ -21,9 +21,6 @@
#include "movepick.h"
// namespace
// {
// partial_insertion_sort() sorts moves in descending order up to and including
// a given limit. The order of moves smaller than the limit is left unspecified.
void partial_insertion_sort(ExtMove *begin, ExtMove *end, int limit)
@ -38,9 +35,6 @@ void partial_insertion_sort(ExtMove *begin, ExtMove *end, int limit)
}
}
//}
/// Constructors of the MovePicker class. As arguments we pass information
/// to help it to return the (presumably) good moves first, to decide which
/// moves to return (in the quiescence search, for instance, we only want to
@ -180,7 +174,7 @@ Move MovePicker::select(Pred filter)
Move MovePicker::next_move()
{
endMoves = generate<LEGAL>(pos, moves);
moveCount = endMoves - moves;
moveCount = int(endMoves - moves);
score<LEGAL>();
partial_insertion_sort(moves, endMoves, -100); // TODO: limit = -3000 * depth

View File

@ -107,34 +107,6 @@ enum StatsType
NoCaptures, Captures
};
/// ButterflyHistory records how often quiet moves have been successful or
/// unsuccessful during the current search, and is used for reduction and move
/// ordering decisions. It uses 2 tables (one for each color) indexed by
/// the move's from and to squares, see www.chessprogramming.org/Butterfly_Boards
typedef Stats<int16_t, 10692, COLOR_NB, int(SQUARE_NB) *int(SQUARE_NB)> ButterflyHistory;
/// LowPlyHistory at higher depths records successful quiet moves on plies 0 to 3
/// and quiet moves which are/were in the PV (ttPv)
/// It get cleared with each new search and get filled during iterative deepening
constexpr int MAX_LPH = 4;
typedef Stats<int16_t, 10692, MAX_LPH, int(SQUARE_NB) *int(SQUARE_NB)> LowPlyHistory;
/// CounterMoveHistory stores counter moves indexed by [piece][to] of the previous
/// move, see www.chessprogramming.org/Countermove_Heuristic
typedef Stats<Move, NOT_USED, PIECE_NB, SQUARE_NB> CounterMoveHistory;
/// CapturePieceToHistory is addressed by a move's [piece][to][captured piece type]
typedef Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB> CapturePieceToHistory;
/// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
typedef Stats<int16_t, 29952, PIECE_NB, SQUARE_NB> PieceToHistory;
/// ContinuationHistory is the combined history of a given pair of moves, usually
/// the current one given a previous one. The nested history table is based on
/// PieceToHistory instead of ButterflyBoards.
typedef Stats<PieceToHistory, NOT_USED, PIECE_NB, SQUARE_NB> ContinuationHistory;
/// MovePicker class is used to pick one pseudo legal move at a time from the
/// current position. The most important method is next_move(), which returns a
/// new pseudo legal move each time it is called, until there are no moves left,
@ -155,7 +127,6 @@ public:
Move next_move();
//private:
template<PickType T, typename Pred> Move select(Pred);
template<GenType> void score();
ExtMove *begin()

View File

@ -112,4 +112,3 @@ bool GameOptions::getOpeningBook()
{
return openingBook;
}

View File

@ -125,25 +125,6 @@ std::ostream &operator<<(std::ostream &os, const Position &pos)
}
// Marcel van Kervinck's cuckoo algorithm for fast detection of "upcoming repetition"
// situations. Description of the algorithm in the following paper:
// https://marcelk.net/2013-04-06/paper/upcoming-rep-v2.pdf
// First and second hash functions for indexing the cuckoo tables
inline int H1(Key h)
{
return h & 0x1fff;
}
inline int H2(Key h)
{
return (h >> 16) & 0x1fff;
}
// Cuckoo tables with Zobrist hashes of valid reversible moves, and the moves themselves
Key cuckoo[8192];
Move cuckooMove[8192];
/// Position::init() initializes at startup the various arrays used to compute
/// hash keys.
@ -157,18 +138,11 @@ void Position::init()
Zobrist::side = rng.rand<Key>() << Zobrist::KEY_MISC_BIT >> Zobrist::KEY_MISC_BIT;
// Prepare the cuckoo tables
std::memset(cuckoo, 0, sizeof(cuckoo));
std::memset(cuckooMove, 0, sizeof(cuckooMove));
return;
}
Position::Position()
{
// TODO
//st = &tmpSt;
construct_key();
if (rule == nullptr) {
@ -187,7 +161,7 @@ Position::Position()
/// This function is not very robust - make sure that input FENs are correct,
/// this is assumed to be the responsibility of the GUI.
Position &Position::set(const string &fenStr, StateInfo *si, Thread *th)
Position &Position::set(const string &fenStr, Thread *th)
{
/*
A FEN string defines a particular position using only the ASCII character set.
@ -220,7 +194,6 @@ Position &Position::set(const string &fenStr, StateInfo *si, Thread *th)
*/
unsigned char token;
size_t idx;
Square sq = SQ_A1;
std::istringstream ss(fenStr);
@ -229,9 +202,6 @@ Position &Position::set(const string &fenStr, StateInfo *si, Thread *th)
}
std::memset(this, 0, sizeof(Position));
//std::memset(si, 0, sizeof(StateInfo));
//std::fill_n(&pieceList[0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE);
//st = si;
ss >> std::noskipws;
@ -302,7 +272,6 @@ Position &Position::set(const string &fenStr, StateInfo *si, Thread *th)
gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == WHITE);
thisThread = th;
//set_state(st);
assert(pos_is_ok());
out:
@ -310,55 +279,6 @@ out:
}
/// Position::set_state() computes the hash keys of the position, and other
/// data that once computed is updated incrementally as moves are made.
/// The function is only used when a new position is set up, and to verify
/// the correctness of the StateInfo data when running in debug mode.
void Position::set_state(StateInfo *si) const
{
// TODO
#if 0
si->key = 0;
for (Bitboard b = pieces(); b; ) {
Square s = pop_lsb(&b);
Piece pc = piece_on(s);
si->key ^= Zobrist::psq[pc][s];
}
if (sideToMove == BLACK)
si->key ^= Zobrist::side;
#endif
}
// TODO
#if 0
/// Position::set() is an overload to initialize the position object with
/// the given endgame code string like "KBPKN". It is mainly a helper to
/// get the material key out of an endgame code.
Position &Position::set(const string &code, Color c, StateInfo *si)
{
assert(code[0] == 'K');
string sides[] = { code.substr(code.find('K', 1)), // Weak
code.substr(0, std::min(code.find('v'), code.find('K', 1))) }; // Strong
assert(sides[0].length() > 0 && sides[0].length() < 8);
assert(sides[1].length() > 0 && sides[1].length() < 8);
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
string fenStr = "8/" + sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/"
+ sides[1] + char(8 - sides[1].length() + '0') + "/8 w - - 0 10";
return set(fenStr, si, nullptr);
}
#endif
/// Position::fen() returns a FEN representation of the position. In case of
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
@ -477,7 +397,7 @@ bool Position::pseudo_legal(const Move m) const
/// to a StateInfo object. The move is assumed to be legal. Pseudo-legal
/// moves should be filtered out before this function is called.
void Position::do_move(Move m, StateInfo &newSt)
void Position::do_move(Move m)
{
#if 0
assert(is_ok(m));
@ -1204,27 +1124,24 @@ inline void Position::set_gameover(Color w, GameOverReason reason)
winner = w;
}
int Position::update()
void Position::update()
{
int ret = -1;
int timePoint = -1;
time_t *ourSeconds = &elapsedSeconds[sideToMove];
time_t theirSeconds = elapsedSeconds[them];
if (!(phase & PHASE_PLAYING)) {
return -1;
return;
}
currentTime = time(NULL);
if (timePoint >= *ourSeconds) {
*ourSeconds = ret = timePoint;
*ourSeconds = timePoint;
startTime = currentTime - (elapsedSeconds[BLACK] + elapsedSeconds[WHITE]);
} else {
*ourSeconds = ret = currentTime - startTime - theirSeconds;
*ourSeconds = currentTime - startTime - theirSeconds;
}
return ret;
}
void Position::update_score()

View File

@ -42,17 +42,8 @@ struct StateInfo
// Not copied when making a move (will be recomputed anyhow)
Key key;
Piece capturedPiece;
StateInfo *previous;
int repetition;
};
/// A list to keep track of the position states along the setup moves (from the
/// start position to the position just before the search starts). Needed by
/// 'draw by repetition' detection. Use a std::deque because pointers to
/// elements are not invalidated upon list resizing.
typedef std::unique_ptr<std::deque<StateInfo>> StateListPtr;
/// Position class stores information regarding the board representation as
/// pieces, side to move, hash keys, castling info, etc. Important methods are
@ -71,8 +62,7 @@ public:
Position &operator=(const Position &) = delete;
// FEN string input/output
Position &set(const std::string &fenStr, StateInfo *si, Thread *th);
Position &set(const std::string &code, Color c, StateInfo *si);
Position &set(const std::string &fenStr, Thread *th);
const std::string fen() const;
// Position representation
@ -87,7 +77,7 @@ public:
Piece moved_piece(Move m) const;
// Doing and undoing moves
void do_move(Move m, StateInfo &newSt);
void do_move(Move m);
void undo_move(Move m);
void undo_move(Sanmill::Stack<Position> &ss);
void do_null_move();
@ -124,7 +114,6 @@ public:
Piece *get_board() const;
Square current_square() const;
int get_step() const;
enum Phase get_phase() const;
enum Action get_action() const;
const char *cmd_line() const;
@ -135,7 +124,7 @@ public:
bool start();
bool resign(Color loser);
bool command(const char *cmd);
int update();
void update();
void update_score();
bool check_gameover_condition();
void remove_ban_stones();
@ -181,11 +170,9 @@ public:
void put_piece(Piece pc, Square s);
bool put_piece(File file, Rank rank);
bool put_piece(Square s, bool updateCmdlist = false);
bool undo_put_piece(Square s);
bool remove_piece(File file, Rank rank);
bool remove_piece(Square s, bool updateCmdlist = false);
bool undo_remove_piece(Square s);
bool move_piece(File f1, Rank r1, File f2, Rank r2);
bool move_piece(Square from, Square to);
@ -323,10 +310,11 @@ inline bool Position::select_piece(File f, Rank r)
return select_piece(make_square(f, r));
}
#if 0
inline void Position::put_piece(Piece pc, Square s)
{
// TODO: put_piece
#if 0
board[s] = pc;
byTypeBB[ALL_PIECES] |= s;
byTypeBB[type_of(pc)] |= s;
@ -334,8 +322,8 @@ inline void Position::put_piece(Piece pc, Square s)
index[s] = pieceCount[pc]++;
pieceList[pc][index[s]] = s;
pieceCount[make_piece(color_of(pc), ALL_PIECES)]++;
#endif
}
#endif
inline bool Position::put_piece(File f, Rank r)
{

View File

@ -44,4 +44,3 @@ extern const struct Rule RULES[N_RULES];
extern const struct Rule *rule;
#endif /* RULE_H */

View File

@ -31,7 +31,6 @@
#include "position.h"
#include "search.h"
#include "thread.h"
#include "timeman.h"
#include "tt.h"
#include "uci.h"
@ -39,21 +38,6 @@
#include "types.h"
#include "option.h"
namespace Search
{
LimitsType Limits;
}
namespace Tablebases
{
int Cardinality;
bool RootInTB;
bool UseRule50;
Depth ProbeDepth;
}
namespace TB = Tablebases;
using std::string;
using Eval::evaluate;
using namespace Search;
@ -69,100 +53,6 @@ enum NodeType
NonPV, PV
};
// Skill structure is used to implement strength limit
struct Skill
{
explicit Skill(int l) : level(l)
{
}
bool enabled() const
{
return level < 20;
}
bool time_to_pick(Depth depth) const
{
return depth == 1 + level;
}
Move pick_best(size_t multiPV);
int level;
Move best = MOVE_NONE;
};
// Breadcrumbs are used to mark nodes as being searched by a given thread
struct Breadcrumb
{
std::atomic<Thread *> thread;
std::atomic<Key> key;
};
std::array<Breadcrumb, 1024> breadcrumbs;
// ThreadHolding structure keeps track of which thread left breadcrumbs at the given
// node for potential reductions. A free node will be marked upon entering the moves
// loop by the constructor, and unmarked upon leaving that loop by the destructor.
struct ThreadHolding
{
explicit ThreadHolding(Thread *thisThread, Key posKey, int ply)
{
location = ply < 8 ? &breadcrumbs[posKey & (breadcrumbs.size() - 1)] : nullptr;
otherThread = false;
owning = false;
if (location) {
// See if another already marked this location, if not, mark it ourselves
Thread *tmp = (*location).thread.load(std::memory_order_relaxed);
if (tmp == nullptr) {
(*location).thread.store(thisThread, std::memory_order_relaxed);
(*location).key.store(posKey, std::memory_order_relaxed);
owning = true;
} else if (tmp != thisThread
&& (*location).key.load(std::memory_order_relaxed) == posKey)
otherThread = true;
}
}
~ThreadHolding()
{
if (owning) // Free the marked location
(*location).thread.store(nullptr, std::memory_order_relaxed);
}
bool marked()
{
return otherThread;
}
private:
Breadcrumb *location;
bool otherThread, owning;
};
template <NodeType NT>
Value search(Position &pos, Stack *ss, Value alpha, Value beta, Depth depth, bool cutNode);
// perft() is our utility to verify move generation. All the leaf nodes up
// to the given depth are generated and counted, and the sum is returned.
template<bool Root>
uint64_t perft(Position &pos, Depth depth)
{
StateInfo st;
uint64_t cnt, nodes = 0;
const bool leaf = (depth == 2);
for (const auto &m : MoveList<LEGAL>(pos)) {
if (Root && depth <= 1)
cnt = 1, nodes++;
else {
pos.do_move(m, st);
cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - 1);
nodes += cnt;
pos.undo_move(m);
}
if (Root)
sync_cout << UCI::move(m) << ": " << cnt << sync_endl;
}
return nodes;
}
} // namespace
@ -180,7 +70,6 @@ void Search::clear()
{
Threads.main()->wait_for_search_finished();
Time.availableNodes = 0;
#ifdef TRANSPOSITION_TABLE_ENABLE
TT.clear();
#endif
@ -188,106 +77,6 @@ void Search::clear()
}
/// MainThread::search() is started when the program receives the UCI 'go'
/// command. It searches from the root position and outputs the "bestmove".
int MainThread::search()
{
if (Limits.perft) {
nodes = perft<true>(*rootPos, Limits.perft);
sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl;
return 0;
}
Color us = rootPos->side_to_move();
Time.init(Limits, us, rootPos->game_ply());
//TT.new_search();
if (rootMoves.empty()) {
rootMoves.emplace_back(MOVE_NONE);
sync_cout << "info depth 0 score "
<< UCI::value(rootPos->get_phase() == PHASE_GAMEOVER ? -VALUE_MATE : VALUE_DRAW) // TODO
<< sync_endl;
} else {
for (Thread *th : Threads) {
th->bestMoveChanges = 0;
if (th != this)
th->start_searching();
}
Thread::search(); // Let's start searching!
}
// When we reach the maximum depth, we can arrive here without a raise of
// Threads.stop. However, if we are pondering or in an infinite search,
// the UCI protocol states that we shouldn't print the best move before the
// GUI sends a "stop" or "ponderhit" command. We therefore simply wait here
// until the GUI sends one of those commands.
while (!Threads.stop && (ponder || Limits.infinite)) {
} // Busy wait for a stop or a ponder reset
// Stop the threads if not already stopped (also raise the stop if
// "ponderhit" just reset Threads.ponder).
Threads.stop = true;
// Wait until all threads have finished
for (Thread *th : Threads)
if (th != this)
th->wait_for_search_finished();
// When playing in 'nodes as time' mode, subtract the searched nodes from
// the available ones before exiting.
if (Limits.npmsec)
Time.availableNodes += Limits.inc[us] - Threads.nodes_searched();
Thread *bestThread = this;
// Check if there are threads with a better score than main thread
if (Options["MultiPV"] == 1
&& !Limits.depth
&& !(Skill((int)Options["Skill Level"]).enabled() || Options["UCI_LimitStrength"])
&& rootMoves[0].pv[0] != MOVE_NONE) {
std::map<Move, int64_t> votes;
Value minScore = this->rootMoves[0].score;
// Find minimum score
for (Thread *th : Threads)
minScore = std::min(minScore, th->rootMoves[0].score);
// Vote according to score and depth, and select the best thread
for (Thread *th : Threads) {
votes[th->rootMoves[0].pv[0]] +=
(th->rootMoves[0].score - minScore + 14) * int(th->completedDepth);
if (abs(bestThread->rootMoves[0].score) >= VALUE_TB_WIN_IN_MAX_PLY) {
// Make sure we pick the shortest mate / TB conversion or stave off mate the longest
if (th->rootMoves[0].score > bestThread->rootMoves[0].score)
bestThread = th;
} else if (th->rootMoves[0].score >= VALUE_TB_WIN_IN_MAX_PLY
|| (th->rootMoves[0].score > VALUE_TB_LOSS_IN_MAX_PLY
&& votes[th->rootMoves[0].pv[0]] > votes[bestThread->rootMoves[0].pv[0]]))
bestThread = th;
}
}
bestPreviousScore = bestThread->rootMoves[0].score;
// Send again PV info if we have a new best thread
if (bestThread != this)
sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl;
sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0]);
if (bestThread->rootMoves[0].pv.size() > 1 /* || bestThread->rootMoves[0].extract_ponder_from_tt(rootPos) */)
std::cout << " ponder " << UCI::move(bestThread->rootMoves[0].pv[1]);
std::cout << sync_endl;
return 0;
}
/// Thread::search() is the main iterative deepening loop. It calls search()
/// repeatedly with increasing depth until the allocated thinking time has been
/// consumed, the user stops the search, or the maximum search depth is reached.
@ -405,158 +194,17 @@ int Thread::search()
}
namespace
{
// search<>() is the main search function for both PV and non-PV nodes
template <NodeType NT>
Value search(Position &pos, Stack *ss, Value alpha, Value beta, Depth depth, bool cutNode)
{
//return MTDF(rootPos, ss, value, i, adjustedDepth, bestMove); // TODO;
return VALUE_DRAW;
}
// When playing with strength handicap, choose best move among a set of RootMoves
// using a statistical rule dependent on 'level'. Idea by Heinz van Saanen.
Move Skill::pick_best(size_t multiPV)
{
const RootMoves &rootMoves = Threads.main()->rootMoves;
static PRNG rng(now()); // PRNG sequence should be non-deterministic
// RootMoves are already sorted by score in descending order
Value topScore = rootMoves[0].score;
//int delta = std::min(topScore - rootMoves[multiPV - 1].score, PawnValueMg);
int delta = std::min(topScore - rootMoves[multiPV - 1].score, StoneValue);
int weakness = 120 - 2 * level;
int maxScore = -VALUE_INFINITE;
// Choose best move. For each move score we add two terms, both dependent on
// weakness. One is deterministic and bigger for weaker levels, and one is
// 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(topScore - rootMoves[i].score)
+ delta * (rng.rand<unsigned>() % weakness)) / 128;
if (rootMoves[i].score + push >= maxScore) {
maxScore = rootMoves[i].score + push;
best = rootMoves[i].pv[0];
}
}
return best;
}
} // namespace
/// MainThread::check_time() is used to print debug info and, more importantly,
/// to detect when we are out of available time and thus stop the search.
void MainThread::check_time()
{
if (--callsCnt > 0)
return;
// When using nodes, ensure checking rate is not lower than 0.1% of nodes
callsCnt = Limits.nodes ? std::min(1024, int(Limits.nodes / 1024)) : 1024;
static TimePoint lastInfoTime = now();
TimePoint elapsed = Time.elapsed();
TimePoint tick = Limits.startTime + elapsed;
if (tick - lastInfoTime >= 1000) {
lastInfoTime = tick;
dbg_print();
}
// We should not stop pondering until told so by the GUI
if (ponder)
return;
if ((Limits.use_time_management() && (elapsed > Time.maximum() - 10 || stopOnPonderhit))
|| (Limits.movetime && elapsed >= Limits.movetime)
|| (Limits.nodes && Threads.nodes_searched() >= (uint64_t)Limits.nodes))
Threads.stop = true;
}
/// UCI::pv() formats PV information according to the UCI protocol. UCI requires
/// that all (if any) unsearched PV lines are sent using a previous search score.
string UCI::pv(const Position *pos, Depth depth, Value alpha, Value beta)
{
std::stringstream ss;
TimePoint elapsed = Time.elapsed() + 1;
const RootMoves &rootMoves = pos->this_thread()->rootMoves;
size_t pvIdx = pos->this_thread()->pvIdx;
size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
uint64_t nodesSearched = Threads.nodes_searched();
uint64_t tbHits = Threads.tb_hits() + (TB::RootInTB ? rootMoves.size() : 0);
for (size_t i = 0; i < multiPV; ++i) {
bool updated = rootMoves[i].score != -VALUE_INFINITE;
if (depth == 1 && !updated)
continue;
Depth d = updated ? depth : depth - 1;
Value v = updated ? rootMoves[i].score : rootMoves[i].previousScore;
bool tb = TB::RootInTB && abs(v) < VALUE_MATE_IN_MAX_PLY;
v = tb ? rootMoves[i].tbScore : v;
if (ss.rdbuf()->in_avail()) // Not at first line
ss << "\n";
ss << "info"
<< " depth " << d
<< " seldepth " << rootMoves[i].selDepth
<< " multipv " << i + 1
<< " score " << UCI::value(v);
if (!tb && i == pvIdx)
ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : "");
ss << " nodes " << nodesSearched
<< " nps " << nodesSearched * 1000 / elapsed;
#if 0
if (elapsed > 1000) // Earlier makes little sense
ss << " hashfull " << TT.hashfull();
#endif
ss << " tbhits " << tbHits
<< " time " << elapsed
<< " pv";
for (Move m : rootMoves[i].pv)
ss << " " << UCI::move(m);
}
return ss.str();
}
///////////////////////////////////////////////////////////////////////////////
extern ThreadPool Threads;
vector<Key> moveHistory;
Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth originDepth, Value alpha, Value beta, Move &bestMove)
{
Value value;
Value bestValue = -VALUE_INFINITE;
StateInfo st; // TODO
Depth epsilon;
#ifdef TT_MOVE_ENABLE
@ -690,7 +338,7 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
ss.push(*(pos));
Color before = pos->sideToMove;
Move move = mp.moves[i].move;
pos->do_move(move, st);
pos->do_move(move);
Color after = pos->sideToMove;
if (gameOptions.getDepthExtension() == true && moveCount == 1) {

View File

@ -32,94 +32,10 @@
#include "stopwatch.h"
#endif
class AIAlgorithm;
class Node;
class Position;
class MovePicker;
using namespace std;
using namespace CTSL;
namespace Search
{
/// Threshold used for countermoves based pruning
constexpr int CounterMovePruneThreshold = 0;
/// Stack struct keeps track of the information we need to remember from nodes
/// shallower and deeper in the tree during the search. Each search thread has
/// its own array of Stack objects, indexed by the current ply.
struct Stack
{
Move *pv;
PieceToHistory *continuationHistory;
int ply;
Move currentMove;
Move excludedMove;
Move killers[2];
Value staticEval;
int statScore;
int moveCount;
};
/// RootMove struct is used for moves at the root of the tree. For each root move
/// we store a score 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
{
explicit RootMove(Move m) : pv(1, m)
{
}
bool operator==(const Move &m) const
{
return pv[0] == m;
}
bool operator<(const RootMove &m) const
{ // Sort in descending order
return m.score != score ? m.score < score
: m.previousScore < previousScore;
}
Value score = -VALUE_INFINITE;
Value previousScore = -VALUE_INFINITE;
int selDepth = 0;
int tbRank = 0;
int bestMoveCount = 0;
Value tbScore;
std::vector<Move> pv;
};
typedef std::vector<RootMove> RootMoves;
/// LimitsType struct stores information sent by GUI about available time to
/// search the current move, maximum depth/time, or if we are in analysis mode.
struct LimitsType
{
LimitsType()
{
// Init explicitly due to broken value-initialization of non POD in MSVC
time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movetime = TimePoint(0);
movestogo = depth = mate = perft = infinite = 0;
nodes = 0;
}
bool use_time_management() const
{
return !(mate | movetime | depth | nodes | perft | infinite);
}
std::vector<Move> searchmoves;
TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime;
int movestogo, depth, mate, perft, infinite;
int64_t nodes;
};
extern LimitsType Limits;
void init();
void clear();

View File

@ -53,8 +53,6 @@ Thread::Thread(size_t n
#endif
timeLimit(3600)
{
//this->us = color;
wait_for_search_finished();
}
@ -63,27 +61,17 @@ Thread::Thread(size_t n
/// for its termination. Thread should be already waiting.
Thread::~Thread()
{
//delete server;
//delete client
{
assert(!searching);
exit = true;
#ifdef HOSTORY_HEURISTIC
clearHistoryScore();
#endif // HOSTORY_HEURISTIC
start_searching();
stdThread.join();
}
/// Thread::bestMoveCount(Move move) return best move counter for the given root move
int Thread::best_move_count(Move move) const
{
// TODO
return 0;
}
/// Thread::clear() reset histories, usually before a new game
void Thread::clear()
@ -125,24 +113,8 @@ void Thread::wait_for_search_finished()
void Thread::idle_loop()
{
#ifdef DEBUG_MODE
int iTemp = 0;
#endif
loggerDebug("Thread %d start\n", us);
bestvalue = lastvalue = VALUE_ZERO;
#if 0
// If OS already scheduled us on a different group than 0 then don't overwrite
// the choice, eventually we are one of many one-threaded processes running on
// some Windows NUMA hardware, for instance in fishtest. To make it simple,
// just check if running threads are below a threshold, in this case all this
// NUMA machinery is not needed.
if (Options["Threads"] > 8)
WinProcGroup::bindThisThread(idx);
#endif
while (true) {
std::unique_lock<std::mutex> lk(mutex);
searching = false;
@ -183,20 +155,16 @@ void Thread::idle_loop()
strCommand = nextMove();
if (strCommand != "" && strCommand != "error!") {
emitCommand();
} else {
int err = 1;
}
}
#ifdef OPENING_BOOK
}
#endif
}
loggerDebug("Thread %d quit\n", us);
}
///////////////
////////////////////////////////////////////////////////////////////////////
void Thread::setAi(Position *p)
{
@ -517,9 +485,6 @@ void Thread::clearTT()
}
}
string Thread::nextMove()
{
#if 0
@ -676,42 +641,18 @@ void ThreadPool::clear()
{
for (Thread *th : *this)
th->clear();
main()->callsCnt = 0;
main()->bestPreviousScore = VALUE_INFINITE;
main()->previousTimeReduction = 1.0;
}
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search.
void ThreadPool::start_thinking(Position *pos, StateListPtr &states,
const Search::LimitsType &limits, bool ponderMode)
void ThreadPool::start_thinking(Position *pos, bool ponderMode)
{
main()->wait_for_search_finished();
// main()->stopOnPonderhit = stop = false;
// increaseDepth = true;
// main()->ponder = ponderMode;
// Search::Limits = limits;
// Search::RootMoves rootMoves;
// for (const auto &m : MoveList<LEGAL>(*pos))
// if (limits.searchmoves.empty()
// || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m))
// rootMoves.emplace_back(m);
#ifdef TBPROBE
if (!rootMoves.empty())
Tablebases::rank_root_moves(pos, rootMoves);
#endif
// After ownership transfer 'states' becomes empty, so if we stop the search
// and call 'go' again without setting a new position states.get() == NULL.
//assert(states.get() || setupStates.get());
//if (states.get())
// setupStates = std::move(states); // Ownership transfer, states is now empty
main()->stopOnPonderhit = stop = false;
increaseDepth = true;
main()->ponder = ponderMode;
// We use Position::set() to set root position across threads. But there are
// some StateInfo fields (previous, pliesFromNull, capturedPiece) that cannot
@ -721,14 +662,10 @@ void ThreadPool::start_thinking(Position *pos, StateListPtr &states,
//StateInfo tmp = setupStates->back();
for (Thread *th : *this) {
//th->nodes = th->tbHits = th->nmpMinPly = 0;
//th->rootDepth = th->completedDepth = 0;
//th->rootMoves = rootMoves;
// TODO
//th->rootPos->set(pos->fen(), &setupStates->back(), th);
th->rootPos = pos;
}
//setupStates->back() = tmp;
main()->start_searching();
}

View File

@ -64,17 +64,8 @@ public:
void idle_loop();
void start_searching();
void wait_for_search_finished();
int best_move_count(Move move) const;
size_t pvIdx, pvLast;
uint64_t ttHitAverage;
int selDepth, nmpMinPly;
Color nmpColor;
std::atomic<uint64_t> nodes, tbHits, bestMoveChanges;
Position *rootPos { nullptr };
Search::RootMoves rootMoves;
Depth rootDepth, completedDepth;
// Mill Game
@ -167,12 +158,6 @@ struct MainThread : public Thread
{
using Thread::Thread;
int search() /* override */;
void check_time();
double previousTimeReduction;
Value bestPreviousScore;
Value iterValue[4];
int callsCnt;
bool stopOnPonderhit;
std::atomic_bool ponder;
@ -185,7 +170,7 @@ struct MainThread : public Thread
struct ThreadPool : public std::vector<Thread *>
{
void start_thinking(Position *, StateListPtr &, const Search::LimitsType &, bool = false);
void start_thinking(Position *, bool = false);
void clear();
void set(size_t);
@ -193,20 +178,10 @@ struct ThreadPool : public std::vector<Thread *>
{
return static_cast<MainThread *>(front());
}
uint64_t nodes_searched() const
{
return accumulate(&Thread::nodes);
}
uint64_t tb_hits() const
{
return accumulate(&Thread::tbHits);
}
std::atomic_bool stop, increaseDepth;
private:
StateListPtr setupStates;
uint64_t accumulate(std::atomic<uint64_t> Thread:: *member) const
{
uint64_t sum = 0;

View File

@ -1,136 +0,0 @@
/*
Fishmill, a UCI Mill Game playing engine derived from Stockfish
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish author)
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish author)
Copyright (C) 2020 Calcitem <calcitem@outlook.com>
Fishmill is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Fishmill is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <algorithm>
#include <cfloat>
#include <cmath>
#include "search.h"
#include "timeman.h"
#include "uci.h"
TimeManagement Time; // Our global time management object
namespace
{
enum TimeType
{
OptimumTime, MaxTime
};
constexpr int MoveHorizon = 50; // Plan time management at most this many moves ahead
constexpr double MaxRatio = 7.3; // When in trouble, we can step over reserved time with this ratio
constexpr double StealRatio = 0.34; // However we must not steal time from remaining moves over this ratio
// move_importance() is a skew-logistic function based on naive statistical
// analysis of "how many games are still undecided after n half-moves". Game
// is considered "undecided" as long as neither side has >275cp advantage.
// Data was extracted from the CCRL game database with some simple filtering criteria.
double move_importance(int ply)
{
constexpr double XScale = 6.85;
constexpr double XShift = 64.5;
constexpr double Skew = 0.171;
return pow((1 + exp((ply - XShift) / XScale)), -Skew) + DBL_MIN; // Ensure non-zero
}
template<TimeType T>
TimePoint remaining(TimePoint myTime, int movesToGo, int ply, TimePoint slowMover)
{
constexpr double TMaxRatio = (T == OptimumTime ? 1.0 : MaxRatio);
constexpr double TStealRatio = (T == OptimumTime ? 0.0 : StealRatio);
double moveImportance = (move_importance(ply) * slowMover) / 100.0;
double otherMovesImportance = 0.0;
for (int i = 1; i < movesToGo; ++i)
otherMovesImportance += move_importance(ply + 2 * i);
double ratio1 = (TMaxRatio * moveImportance) / (TMaxRatio * moveImportance + otherMovesImportance);
double ratio2 = (moveImportance + TStealRatio * otherMovesImportance) / (moveImportance + otherMovesImportance);
return TimePoint(myTime * std::min(ratio1, ratio2)); // Intel C++ asks for an explicit cast
}
} // namespace
/// init() is called at the beginning of the search and calculates the allowed
/// thinking time out of the time control and current game ply. We support four
/// different kinds of time controls, passed in 'limits':
///
/// inc == 0 && movestogo == 0 means: x basetime [sudden death!]
/// inc == 0 && movestogo != 0 means: x moves in y minutes
/// inc > 0 && movestogo == 0 means: x basetime + z increment
/// inc > 0 && movestogo != 0 means: x moves in y minutes + z increment
void TimeManagement::init(Search::LimitsType &limits, Color us, int ply)
{
TimePoint minThinkingTime = (TimePoint)Options["Minimum Thinking Time"];
TimePoint moveOverhead = (TimePoint)Options["Move Overhead"];
TimePoint slowMover = (TimePoint)Options["Slow Mover"];
TimePoint npmsec = (TimePoint)Options["nodestime"];
TimePoint hypMyTime;
// If we have to play in 'nodes as time' mode, then convert from time
// to nodes, and use resulting values in time management formulas.
// WARNING: to avoid time losses, the given npmsec (nodes per millisecond)
// must be much lower than the real engine speed.
if (npmsec) {
if (!availableNodes) // Only once at game start
availableNodes = npmsec * limits.time[us]; // Time is in msec
// Convert from milliseconds to nodes
limits.time[us] = TimePoint(availableNodes);
limits.inc[us] *= npmsec;
limits.npmsec = npmsec;
}
startTime = limits.startTime;
optimumTime = maximumTime = std::max(limits.time[us], minThinkingTime);
const int maxMTG = limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon;
// We calculate optimum time usage for different hypothetical "moves to go" values
// and choose the minimum of calculated search time values. Usually the greatest
// hypMTG gives the minimum values.
for (int hypMTG = 1; hypMTG <= maxMTG; ++hypMTG) {
// Calculate thinking time for hypothetical "moves to go"-value
hypMyTime = limits.time[us]
+ limits.inc[us] * (hypMTG - 1)
- moveOverhead * (2 + std::min(hypMTG, 40));
hypMyTime = std::max(hypMyTime, TimePoint(0));
TimePoint t1 = minThinkingTime + remaining<OptimumTime>(hypMyTime, hypMTG, ply, slowMover);
TimePoint t2 = minThinkingTime + remaining<MaxTime >(hypMyTime, hypMTG, ply, slowMover);
optimumTime = std::min(t1, optimumTime);
maximumTime = std::min(t2, maximumTime);
}
if (Options["Ponder"])
optimumTime += optimumTime / 4;
}

View File

@ -1,50 +0,0 @@
/*
Fishmill, a UCI Mill Game playing engine derived from Stockfish
Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad (Stockfish author)
Copyright (C) 2015-2020 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad (Stockfish author)
Copyright (C) 2020 Calcitem <calcitem@outlook.com>
Fishmill is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Fishmill is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TIMEMAN_H_INCLUDED
#define TIMEMAN_H_INCLUDED
#include "misc.h"
#include "search.h"
#include "thread.h"
/// The TimeManagement class computes the optimal time to think depending on
/// the maximum available time, the game move number and other parameters.
class TimeManagement {
public:
void init(Search::LimitsType& limits, Color us, int ply);
TimePoint optimum() const { return optimumTime; }
TimePoint maximum() const { return maximumTime; }
TimePoint elapsed() const { return Search::Limits.npmsec ?
TimePoint(Threads.nodes_searched()) : now() - startTime; }
int64_t availableNodes; // When in 'nodes as time' mode
private:
TimePoint startTime;
TimePoint optimumTime;
TimePoint maximumTime;
};
extern TimeManagement Time;
#endif // #ifndef TIMEMAN_H_INCLUDED

View File

@ -67,7 +67,7 @@ Value TranspositionTable::probe(const Key &key,
break;
case BOUND_UPPER:
if (tte.value8 <= alpha) {
return alpha; // TODO: https://github.com/calcitem/NineChess/issues/25
return alpha; // TODO: https://github.com/calcitem/Sanmill/issues/25
}
break;
case BOUND_LOWER:

View File

@ -29,7 +29,6 @@
#include "position.h"
#include "search.h"
#include "thread.h"
#include "timeman.h"
#include "tt.h"
#include "uci.h"
@ -41,7 +40,7 @@ namespace
{
// FEN string of the initial position, normal mill game
const char *StartFEN = "********/********/******** b p p 0 12 0 12 0 0 1"; // Chess: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
const char *StartFEN = "********/********/******** b p p 0 12 0 12 0 0 1";
// position() is called when engine receives the "position" UCI command.
@ -49,7 +48,7 @@ const char *StartFEN = "********/********/******** b p p 0 12 0 12 0 0 1"; // Ch
// or the starting position ("startpos") and then makes the moves given in the
// following move list ("moves").
void position(Position *pos, istringstream &is, StateListPtr &states)
void position(Position *pos, istringstream &is)
{
Move m;
string token, fen;
@ -65,13 +64,11 @@ void position(Position *pos, istringstream &is, StateListPtr &states)
else
return;
states = StateListPtr(new std::deque<StateInfo>(1)); // Drop old and create a new one
pos->set(fen, &states->back(), Threads.main());
pos->set(fen, Threads.main());
// Parse move list (if any)
while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) {
states->emplace_back();
pos->do_move(m, states->back());
pos->do_move(m);
}
}
@ -104,34 +101,10 @@ void setoption(istringstream &is)
// the thinking time and other parameters from the input string, then starts
// the search.
void go(Position *pos, istringstream &is, StateListPtr &states)
void go(Position *pos)
{
begin:
Search::LimitsType limits;
string token;
bool ponderMode = false;
limits.startTime = now(); // As early as possible!
while (is >> token)
if (token == "searchmoves") // Needs to be the last command on the line
while (is >> token)
limits.searchmoves.push_back(UCI::to_move(pos, token));
else if (token == "wtime") is >> limits.time[WHITE];
else if (token == "btime") is >> limits.time[BLACK];
else if (token == "winc") is >> limits.inc[WHITE];
else if (token == "binc") is >> limits.inc[BLACK];
else if (token == "movestogo") is >> limits.movestogo;
else if (token == "depth") is >> limits.depth;
else if (token == "nodes") is >> limits.nodes;
else if (token == "movetime") is >> limits.movetime;
else if (token == "mate") is >> limits.mate;
else if (token == "perft") is >> limits.perft;
else if (token == "infinite") limits.infinite = 1;
else if (token == "ponder") ponderMode = true;
Threads.start_thinking(pos, states, limits, ponderMode);
Threads.start_thinking(pos);
if (pos->get_phase() == PHASE_GAMEOVER)
{
@ -140,7 +113,7 @@ begin:
{
}
pos->set(StartFEN, &states->back(), Threads.main());
pos->set(StartFEN, Threads.main());
}
goto begin;
@ -151,10 +124,10 @@ begin:
// a list of UCI commands is setup according to bench parameters, then
// it is run one by one printing a summary at the end.
void bench(Position *pos, istream &args, StateListPtr &states)
void bench(Position *pos, istream &args)
{
string token;
uint64_t num, nodes = 0, cnt = 1;
uint64_t num, cnt = 1;
vector<string> list = setup_bench(pos, args);
num = count_if(list.begin(), list.end(), [](string s) { return s.find("go ") == 0 || s.find("eval") == 0; });
@ -168,13 +141,12 @@ void bench(Position *pos, istream &args, StateListPtr &states)
if (token == "go" || token == "eval") {
cerr << "\nPosition: " << cnt++ << '/' << num << endl;
if (token == "go") {
go(pos, is, states);
go(pos);
Threads.main()->wait_for_search_finished();
nodes += Threads.nodes_searched();
} else
sync_cout << "\n" << Eval::trace(*pos) << sync_endl;
} else if (token == "setoption") setoption(is);
else if (token == "position") position(pos, is, states);
else if (token == "position") position(pos, is);
else if (token == "ucinewgame") {
Search::clear(); elapsed = now();
} // Search::clear() may take some while
@ -186,8 +158,7 @@ void bench(Position *pos, istream &args, StateListPtr &states)
cerr << "\n==========================="
<< "\nTotal time (ms) : " << elapsed
<< "\nNodes searched : " << nodes
<< "\nNodes/second : " << 1000 * nodes / elapsed << endl;
<< endl;
}
} // namespace
@ -204,9 +175,8 @@ void UCI::loop(int argc, char *argv[])
Position *pos = new Position;
string token, cmd;
StateListPtr states(new std::deque<StateInfo>(1));
pos->set(StartFEN, &states->back(), Threads.main());
pos->set(StartFEN, Threads.main());
for (int i = 1; i < argc; ++i)
cmd += std::string(argv[i]) + " ";
@ -237,15 +207,15 @@ void UCI::loop(int argc, char *argv[])
<< "\nuciok" << sync_endl;
else if (token == "setoption") setoption(is);
else if (token == "go") go(pos, is, states);
else if (token == "position") position(pos, is, states);
else if (token == "go") go(pos);
else if (token == "position") position(pos, is);
else if (token == "ucinewgame") Search::clear();
else if (token == "isready") sync_cout << "readyok" << sync_endl;
// Additional custom non-UCI commands, mainly for debugging.
// Do not use these commands during a search!
else if (token == "flip") pos->flip();
else if (token == "bench") bench(pos, is, states);
else if (token == "bench") bench(pos, is);
else if (token == "d") sync_cout << &pos << sync_endl;
else if (token == "eval") sync_cout << Eval::trace(*pos) << sync_endl;
else if (token == "compiler") sync_cout << compiler_info() << sync_endl;

View File

@ -73,7 +73,6 @@ void loop(int argc, char* argv[]);
std::string value(Value v);
std::string square(Square s);
std::string move(Move m);
std::string pv(const Position* pos, Depth depth, Value alpha, Value beta);
Move to_move(Position* pos, std::string& str);
} // namespace UCI

View File

@ -29,7 +29,6 @@
#include "thread.h"
#include "tt.h"
#include "uci.h"
//#include "syzygy/tbprobe.h"
using std::string;
@ -57,12 +56,6 @@ void on_threads(const Option &o)
{
Threads.set((size_t)o);
}
#ifdef TBPROBE
void on_tb_path(const Option &o)
{
Tablebases::init(o);
}
#endif
/// Our case insensitive less() function as required by UCI protocol
@ -97,12 +90,6 @@ void init(OptionsMap &o)
o["UCI_AnalyseMode"] << Option(false);
o["UCI_LimitStrength"] << Option(false);
o["UCI_Elo"] << Option(1350, 1350, 2850);
#ifdef TBPROBE
o["SyzygyPath"] << Option("<empty>", on_tb_path);
o["SyzygyProbeDepth"] << Option(1, 1, 100);
o["Syzygy50MoveRule"] << Option(true);
o["SyzygyProbeLimit"] << Option(7, 0, 7);
#endif
}

View File

@ -1048,7 +1048,7 @@ bool GameController::command(const string &cmd, bool update /* = true */)
loggerDebug("Game Duration Time: %lldms\n", gameDurationTime);
#ifdef TIME_STAT
loggerDebug("Sort Time: %ld + %ld = %ldms\n",
loggerDebug("Sort Time: %I64d + %I64d = %I64dms\n",
aiThread[BLACK]->sortTime, aiThread[WHITE]->sortTime,
(aiThread[BLACK]->sortTime + aiThread[WHITE]->sortTime));
aiThread[BLACK]->sortTime = aiThread[WHITE]->sortTime = 0;