diff --git a/src/benchmark.cpp b/src/benchmark.cpp index 6d69541f..2978f346 100644 --- a/src/benchmark.cpp +++ b/src/benchmark.cpp @@ -144,10 +144,12 @@ void benchmark(const Position& current, istream& is) { uint64_t nodes = 0; TimePoint elapsed = now(); + Position pos; for (size_t i = 0; i < fens.size(); ++i) { - Position pos(fens[i], Options["UCI_Chess960"], Threads.main()); + StateListPtr states(new std::vector(1)); + pos.set(fens[i], Options["UCI_Chess960"], &states->back(), Threads.main()); cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl; @@ -156,9 +158,8 @@ void benchmark(const Position& current, istream& is) { else { - Search::StateStackPtr st; limits.startTime = now(); - Threads.start_thinking(pos, limits, st); + Threads.start_thinking(pos, states, limits); Threads.main()->wait_for_search_finished(); nodes += Threads.nodes_searched(); } diff --git a/src/endgame.cpp b/src/endgame.cpp index cc663043..04469e87 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -99,7 +99,8 @@ namespace { string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/" + sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10"; - return Position(fen, false, nullptr).material_key(); + StateInfo st; + return Position().set(fen, false, &st, nullptr).material_key(); } } // namespace diff --git a/src/position.cpp b/src/position.cpp index f42377de..6e8b03d1 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -155,42 +155,11 @@ void Position::init() { } -/// Position::operator=() creates a copy of 'pos' but detaching the state pointer -/// from the source to be self-consistent and not depending on any external data. - -Position& Position::operator=(const Position& pos) { - - std::memcpy(this, &pos, sizeof(Position)); - std::memcpy(&startState, st, sizeof(StateInfo)); - st = &startState; - nodes = 0; - - assert(pos_is_ok()); - - return *this; -} - - -/// Position::clear() erases the position object to a pristine state, with an -/// empty board, white to move, and no castling rights. - -void Position::clear() { - - std::memset(this, 0, sizeof(Position)); - startState.epSquare = SQ_NONE; - st = &startState; - - for (int i = 0; i < PIECE_TYPE_NB; ++i) - for (int j = 0; j < 16; ++j) - pieceList[WHITE][i][j] = pieceList[BLACK][i][j] = SQ_NONE; -} - - /// Position::set() initializes the position object with the given FEN string. /// This function is not very robust - make sure that input FENs are correct, /// this is assumed to be the responsibility of the GUI. -void Position::set(const string& fenStr, bool isChess960, Thread* th) { +Position& Position::set(const string& fenStr, bool isChess960, StateInfo* si, Thread* th) { /* A FEN string defines a particular position using only the ASCII character set. @@ -230,7 +199,11 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { Square sq = SQ_A8; std::istringstream ss(fenStr); - clear(); + std::memset(this, 0, sizeof(Position)); + std::memset(si, 0, sizeof(StateInfo)); + std::fill_n(&pieceList[0][0][0], sizeof(pieceList) / sizeof(Square), SQ_NONE); + st = si; + ss >> std::noskipws; // 1. Piece placement @@ -291,6 +264,8 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { if (!(attackers_to(st->epSquare) & pieces(sideToMove, PAWN))) st->epSquare = SQ_NONE; } + else + st->epSquare = SQ_NONE; // 5-6. Halfmove clock and fullmove number ss >> std::skipws >> st->rule50 >> gamePly; @@ -304,6 +279,8 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) { set_state(st); assert(pos_is_ok()); + + return *this; } @@ -1108,7 +1085,7 @@ void Position::flip() { std::getline(ss, token); // Half and full moves f += token; - set(f, is_chess960(), this_thread()); + set(f, is_chess960(), st, this_thread()); assert(pos_is_ok()); } diff --git a/src/position.h b/src/position.h index 1070236b..d44ed009 100644 --- a/src/position.h +++ b/src/position.h @@ -23,7 +23,9 @@ #include #include // For offsetof() +#include // For std::unique_ptr #include +#include #include "bitboard.h" #include "types.h" @@ -75,6 +77,8 @@ struct StateInfo { StateInfo* previous; }; +typedef std::unique_ptr> StateListPtr; + /// Position class stores information regarding the board representation as /// pieces, side to move, hash keys, castling info, etc. Important methods are @@ -86,14 +90,12 @@ class Position { public: static void init(); - Position() = default; // To define the global object RootPos + Position() = default; Position(const Position&) = delete; - Position(const Position& pos, Thread* th) { *this = pos; thisThread = th; } - Position(const std::string& f, bool c960, Thread* th) { set(f, c960, th); } - Position& operator=(const Position&); // To assign RootPos from UCI + Position& operator=(const Position&) = delete; // FEN string input/output - void set(const std::string& fenStr, bool isChess960, Thread* th); + Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th); const std::string fen() const; // Position representation @@ -178,7 +180,6 @@ public: private: // Initialization helpers (used while setting up a position) - void clear(); void set_castling_right(Color c, Square rfrom); void set_state(StateInfo* si) const; @@ -200,7 +201,6 @@ private: int castlingRightsMask[SQUARE_NB]; Square castlingRookSquare[CASTLING_RIGHT_NB]; Bitboard castlingPath[CASTLING_RIGHT_NB]; - StateInfo startState; uint64_t nodes; int gamePly; Color sideToMove; diff --git a/src/search.cpp b/src/search.cpp index 10d491c0..31764533 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -40,7 +40,6 @@ namespace Search { SignalsType Signals; LimitsType Limits; - StateStackPtr SetupStates; } namespace Tablebases { @@ -317,16 +316,8 @@ void MainThread::search() { } for (Thread* th : Threads) - { - th->maxPly = 0; - th->rootDepth = DEPTH_ZERO; if (th != this) - { - th->rootPos = Position(rootPos, th); - th->rootMoves = rootMoves; th->start_searching(); - } - } Thread::search(); // Let's start searching! } @@ -1488,7 +1479,7 @@ moves_loop: // When in check search starts from here Move Skill::pick_best(size_t multiPV) { - const Search::RootMoveVector& rootMoves = Threads.main()->rootMoves; + 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 @@ -1553,7 +1544,7 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { std::stringstream ss; int elapsed = Time.elapsed() + 1; - const Search::RootMoveVector& rootMoves = pos.this_thread()->rootMoves; + 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 nodes_searched = Threads.nodes_searched(); diff --git a/src/search.h b/src/search.h index 84420373..d722af1e 100644 --- a/src/search.h +++ b/src/search.h @@ -22,8 +22,6 @@ #define SEARCH_H_INCLUDED #include -#include // For std::unique_ptr -#include #include #include "misc.h" @@ -65,7 +63,7 @@ struct RootMove { std::vector pv; }; -typedef std::vector RootMoveVector; +typedef std::vector RootMoves; /// LimitsType struct stores information sent by GUI about available time to /// search the current move, maximum depth/time, if we are in analysis mode or @@ -74,8 +72,8 @@ typedef std::vector RootMoveVector; struct LimitsType { LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC - nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movestogo = - depth = movetime = mate = infinite = ponder = 0; + nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = + npmsec = movestogo = depth = movetime = mate = infinite = ponder = 0; } bool use_time_management() const { @@ -95,11 +93,8 @@ struct SignalsType { std::atomic_bool stop, stopOnPonderhit; }; -typedef std::unique_ptr> StateStackPtr; - extern SignalsType Signals; extern LimitsType Limits; -extern StateStackPtr SetupStates; void init(); void clear(); diff --git a/src/syzygy/tbcore.cpp b/src/syzygy/tbcore.cpp index 99057d40..d025682a 100644 --- a/src/syzygy/tbcore.cpp +++ b/src/syzygy/tbcore.cpp @@ -95,8 +95,7 @@ static char *map_file(const std::string& name, const std::string& suffix, uint64 #else DWORD size_low, size_high; size_low = GetFileSize(fd, &size_high); - HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low, - NULL); + HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low, NULL); if (map == NULL) { std::cerr << "CreateFileMapping() failed\n"; @@ -481,8 +480,7 @@ void free_wdl_entry(TBEntry_pawn* entry) { unmap_file(entry->data, entry->mapping); - for (int f = 0; f < 4; f++) - { + for (int f = 0; f < 4; f++) { free(entry->file[f].precomp[0]); free(entry->file[f].precomp[1]); } @@ -510,8 +508,7 @@ void Tablebases::init(const std::string& path) free_wdl_entry(&TB_pawn[i]); for (int i = 0; i < DTZ_ENTRIES; i++) - if (DTZ_table[i].entry) - { + if (DTZ_table[i].entry) { free_dtz_entry(DTZ_table[i].entry); DTZ_table[i].entry = nullptr; } @@ -526,8 +523,7 @@ void Tablebases::init(const std::string& path) // Fill binomial[] with the Binomial Coefficents using pascal triangle // so that binomial[k-1][n] = Binomial(n, k). - for (int k = 0; k < 5; k++) - { + for (int k = 0; k < 5; k++) { binomial[k][0] = 0; for (int n = 1; n < 64; n++) @@ -565,20 +561,17 @@ void Tablebases::init(const std::string& path) const std::string K("K"); - for (PieceType p1 = PAWN; p1 < KING; ++p1) - { + for (PieceType p1 = PAWN; p1 < KING; ++p1) { init_tb(K + pchr[p1] + "vK"); - for (PieceType p2 = PAWN; p2 <= p1; ++p2) - { + for (PieceType p2 = PAWN; p2 <= p1; ++p2) { init_tb(K + pchr[p1] + pchr[p2] + "vK"); init_tb(K + pchr[p1] + "vK" + pchr[p2]); for (PieceType p3 = PAWN; p3 < KING; ++p3) init_tb(K + pchr[p1] + pchr[p2] + "vK" + pchr[p3]); - for (PieceType p3 = PAWN; p3 <= p2; ++p3) - { + for (PieceType p3 = PAWN; p3 <= p2; ++p3) { init_tb(K + pchr[p1] + pchr[p2] + pchr[p3] + "vK"); for (PieceType p4 = PAWN; p4 <= p3; ++p4) @@ -603,9 +596,9 @@ static uint64_t encode_piece(TBEntry_piece *ptr, uint8_t *norm, int *pos, int *f int i, j, k, m, l, p; int n = ptr->num; - if (pos[0] & 0x04) { + if (pos[0] & 4) { for (i = 0; i < n; i++) - pos[i] ^= 0x07; + pos[i] ^= 7; } if (pos[0] & 0x20) { @@ -682,7 +675,7 @@ static uint64_t encode_piece(TBEntry_piece *ptr, uint8_t *norm, int *pos, int *f s += binomial[m - i][p - j]; } - idx += ((uint64_t)s) * ((uint64_t)factor[i]); + idx += (uint64_t)s * ((uint64_t)factor[i]); i += t; } @@ -698,7 +691,7 @@ static int pawn_file(TBEntry_pawn *ptr, int *pos) if (flap[pos[0]] > flap[pos[i]]) std::swap(pos[0], pos[i]); - return file_to_file[pos[0] & 0x07]; + return file_to_file[pos[0] & 7]; } static uint64_t encode_pawn(TBEntry_pawn *ptr, uint8_t *norm, int *pos, int *factor) @@ -707,9 +700,9 @@ static uint64_t encode_pawn(TBEntry_pawn *ptr, uint8_t *norm, int *pos, int *fac int i, j, k, m, s, t; int n = ptr->num; - if (pos[0] & 0x04) + if (pos[0] & 4) for (i = 0; i < n; i++) - pos[i] ^= 0x07; + pos[i] ^= 7; for (i = 1; i < ptr->pawns[0]; i++) for (j = i + 1; j < ptr->pawns[0]; j++) @@ -744,7 +737,7 @@ static uint64_t encode_pawn(TBEntry_pawn *ptr, uint8_t *norm, int *pos, int *fac s += binomial[m - i][p - j - 8]; } - idx += ((uint64_t)s) * ((uint64_t)factor[i]); + idx += (uint64_t)s * ((uint64_t)factor[i]); i = t; } @@ -766,7 +759,7 @@ static uint64_t encode_pawn(TBEntry_pawn *ptr, uint8_t *norm, int *pos, int *fac s += binomial[m - i][p - j]; } - idx += ((uint64_t)s) * ((uint64_t)factor[i]); + idx += (uint64_t)s * ((uint64_t)factor[i]); i += t; } @@ -1088,8 +1081,8 @@ static int init_table_wdl(TBEntry *entry, const std::string& str) return 0; } - int split = data[4] & 0x01; - int files = data[4] & 0x02 ? 4 : 1; + int split = data[4] & 1; + int files = data[4] & 2 ? 4 : 1; data += 5; @@ -1097,7 +1090,7 @@ static int init_table_wdl(TBEntry *entry, const std::string& str) TBEntry_piece *ptr = (TBEntry_piece *)entry; setup_pieces_piece(ptr, data, &tb_size[0]); data += ptr->num + 1; - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; ptr->precomp[0] = setup_pairs(data, tb_size[0], &size[0], &next, &flags, 1); data = next; @@ -1124,12 +1117,12 @@ static int init_table_wdl(TBEntry *entry, const std::string& str) data += size[4]; } - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->precomp[0]->data = data; data += size[2]; if (split) { - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->precomp[1]->data = data; } } else { @@ -1141,7 +1134,7 @@ static int init_table_wdl(TBEntry *entry, const std::string& str) data += ptr->num + s; } - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; for (f = 0; f < files; f++) { ptr->file[f].precomp[0] = setup_pairs(data, tb_size[2 * f], &size[6 * f], &next, &flags, 1); @@ -1175,12 +1168,12 @@ static int init_table_wdl(TBEntry *entry, const std::string& str) } for (f = 0; f < files; f++) { - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->file[f].precomp[0]->data = data; data += size[6 * f + 2]; if (split) { - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->file[f].precomp[1]->data = data; data += size[6 * f + 5]; } @@ -1209,7 +1202,7 @@ static int init_table_dtz(TBEntry *entry) return 0; } - int files = data[4] & 0x02 ? 4 : 1; + int files = data[4] & 2 ? 4 : 1; data += 5; @@ -1217,7 +1210,7 @@ static int init_table_dtz(TBEntry *entry) DTZEntry_piece *ptr = (DTZEntry_piece *)entry; setup_pieces_piece_dtz(ptr, data, &tb_size[0]); data += ptr->num + 1; - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; ptr->precomp = setup_pairs(data, tb_size[0], &size[0], &next, &(ptr->flags), 0); data = next; @@ -1232,7 +1225,7 @@ static int init_table_dtz(TBEntry *entry) data += 1 + data[0]; } - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; } ptr->precomp->indextable = (char *)data; @@ -1241,7 +1234,7 @@ static int init_table_dtz(TBEntry *entry) ptr->precomp->sizetable = (uint16_t *)data; data += size[1]; - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->precomp->data = data; data += size[2]; } else { @@ -1253,7 +1246,7 @@ static int init_table_dtz(TBEntry *entry) data += ptr->num + s; } - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; for (f = 0; f < files; f++) { ptr->file[f].precomp = setup_pairs(data, tb_size[f], &size[3 * f], &next, &(ptr->flags[f]), 0); @@ -1273,7 +1266,7 @@ static int init_table_dtz(TBEntry *entry) } } - data += ((uintptr_t)data) & 0x01; + data += (uintptr_t)data & 1; for (f = 0; f < files; f++) { ptr->file[f].precomp->indextable = (char *)data; @@ -1286,7 +1279,7 @@ static int init_table_dtz(TBEntry *entry) } for (f = 0; f < files; f++) { - data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); + data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f); ptr->file[f].precomp->data = data; data += size[3 * f + 2]; } @@ -1366,7 +1359,7 @@ static uint8_t decompress_pairs(PairsData *d, uint64_t idx) if (LittleEndian) tmp = BSWAP32(tmp); - code |= ((uint64_t)tmp) << bitcnt; + code |= (uint64_t)tmp << bitcnt; } } diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 4d169eb8..b410f452 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -52,17 +52,11 @@ static uint64_t calc_key(Position& pos, bool mirror) { uint64_t key = 0; - Color color = mirror ? BLACK: WHITE; - - for (PieceType pt = PAWN; pt <= KING; ++pt) - for (int i = popcount(pos.pieces(color, pt)); i > 0; i--) - key ^= Zobrist::psq[WHITE][pt][i - 1]; - - color = ~color; - - for (PieceType pt = PAWN; pt <= KING; ++pt) - for (int i = popcount(pos.pieces(color, pt)); i > 0; i--) - key ^= Zobrist::psq[BLACK][pt][i - 1]; + for (int i = 0; i < 2; i++) { + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (int j = popcount(pos.pieces(Color(i ^ mirror), pt)); j > 0; j--) + key ^= Zobrist::psq[i][pt][j - 1]; + } return key; } @@ -75,17 +69,11 @@ static uint64_t calc_key_from_pcs(int *pcs, bool mirror) { uint64_t key = 0; - Color color = mirror ? BLACK : WHITE; - - for (PieceType pt = PAWN; pt <= KING; ++pt) - for (int i = 0; i < pcs[8 * color + pt]; i++) - key ^= Zobrist::psq[WHITE][pt][i]; - - color = ~color; - - for (PieceType pt = PAWN; pt <= KING; ++pt) - for (int i = 0; i < pcs[8 * color + pt]; i++) - key ^= Zobrist::psq[BLACK][pt][i]; + for (int i = 0; i < 2; i++) { + for (PieceType pt = PAWN; pt <= KING; ++pt) + for (int j = 0; j < pcs[8 * (i ^ mirror) + pt]; j++) + key ^= Zobrist::psq[i][pt][j]; + } return key; } @@ -189,7 +177,7 @@ static int probe_wdl_table(Position& pos, int *success) for (i = 0; i < entry->num;) { Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), - (PieceType)(pc[i] & 0x07)); + (PieceType)(pc[i] & 7)); do { p[i++] = pop_lsb(&bb); @@ -201,7 +189,7 @@ static int probe_wdl_table(Position& pos, int *success) } else { TBEntry_pawn *entry = (TBEntry_pawn *)ptr; int k = entry->file[0].pieces[0][0] ^ cmirror; - Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07)); + Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 7)); i = 0; do { @@ -213,7 +201,7 @@ static int probe_wdl_table(Position& pos, int *success) for (; i < entry->num;) { bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), - (PieceType)(pc[i] & 0x07)); + (PieceType)(pc[i] & 7)); do { p[i++] = pop_lsb(&bb) ^ mirror; @@ -224,7 +212,7 @@ static int probe_wdl_table(Position& pos, int *success) res = decompress_pairs(entry->file[f].precomp[bside], idx); } - return ((int)res) - 2; + return (int)res - 2; } static int probe_dtz_table(Position& pos, int wdl, int *success) @@ -311,7 +299,7 @@ static int probe_dtz_table(Position& pos, int wdl, int *success) for (i = 0; i < entry->num;) { Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), - (PieceType)(pc[i] & 0x07)); + (PieceType)(pc[i] & 7)); do { p[i++] = pop_lsb(&bb); @@ -329,7 +317,7 @@ static int probe_dtz_table(Position& pos, int wdl, int *success) } else { DTZEntry_pawn *entry = (DTZEntry_pawn *)ptr; int k = entry->file[0].pieces[0] ^ cmirror; - Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 0x07)); + Bitboard bb = pos.pieces((Color)(k >> 3), (PieceType)(k & 7)); i = 0; do { @@ -347,7 +335,7 @@ static int probe_dtz_table(Position& pos, int wdl, int *success) for (; i < entry->num;) { bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), - (PieceType)(pc[i] & 0x07)); + (PieceType)(pc[i] & 7)); do { p[i++] = pop_lsb(&bb) ^ mirror; @@ -799,7 +787,7 @@ static Value wdl_to_Value[5] = { // // A return value false indicates that not all probes were successful and that // no moves were filtered out. -bool Tablebases::root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score) +bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score) { int success; @@ -930,7 +918,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoveVector& rootMoves, Va // // A return value false indicates that not all probes were successful and that // no moves were filtered out. -bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score) +bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score) { int success; diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index 4233e1aa..2bcc0834 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -10,8 +10,8 @@ extern int MaxCardinality; void init(const std::string& path); int probe_wdl(Position& pos, int *success); int probe_dtz(Position& pos, int *success); -bool root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score); -bool root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score); +bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score); +bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score); } diff --git a/src/thread.cpp b/src/thread.cpp index 440b8bf0..dc4ec05e 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -26,8 +26,6 @@ #include "thread.h" #include "uci.h" -using namespace Search; - ThreadPool Threads; // Global object /// Thread constructor launches the thread and then waits until it goes to sleep @@ -171,26 +169,34 @@ int64_t ThreadPool::nodes_searched() { /// ThreadPool::start_thinking() wakes up the main thread sleeping in idle_loop() /// and starts a new search, then returns immediately. -void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, - StateStackPtr& states) { +void ThreadPool::start_thinking(const Position& pos, StateListPtr& states, + const Search::LimitsType& limits) { main()->wait_for_search_finished(); - Signals.stopOnPonderhit = Signals.stop = false; - - main()->rootMoves.clear(); - main()->rootPos = pos; - Limits = limits; - if (states.get()) // If we don't set a new position, preserve current state - { - SetupStates = std::move(states); // Ownership transfer here - assert(!states.get()); - } + Search::Signals.stopOnPonderhit = Search::Signals.stop = false; + Search::Limits = limits; + Search::RootMoves rootMoves; for (const auto& m : MoveList(pos)) if ( limits.searchmoves.empty() || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) - main()->rootMoves.push_back(RootMove(m)); + rootMoves.push_back(Search::RootMove(m)); + + // 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 + + for (Thread* th : Threads) + { + th->maxPly = 0; + th->rootDepth = DEPTH_ZERO; + th->rootMoves = rootMoves; + th->rootPos.set(pos.fen(), pos.is_chess960(), &setupStates->back(), th); + } main()->start_searching(); } diff --git a/src/thread.h b/src/thread.h index 43ddfbb7..0b112de9 100644 --- a/src/thread.h +++ b/src/thread.h @@ -64,7 +64,7 @@ public: int maxPly, callsCnt; Position rootPos; - Search::RootMoveVector rootMoves; + Search::RootMoves rootMoves; Depth rootDepth; HistoryStats history; MoveStats counterMoves; @@ -94,9 +94,12 @@ struct ThreadPool : public std::vector { void exit(); // be initialized and valid during the whole thread lifetime. MainThread* main() { return static_cast(at(0)); } - void start_thinking(const Position&, const Search::LimitsType&, Search::StateStackPtr&); + void start_thinking(const Position&, StateListPtr&, const Search::LimitsType&); void read_uci_options(); int64_t nodes_searched(); + +private: + StateListPtr setupStates; }; extern ThreadPool Threads; diff --git a/src/timeman.cpp b/src/timeman.cpp index bc9c2e5b..c7c19f47 100644 --- a/src/timeman.cpp +++ b/src/timeman.cpp @@ -33,7 +33,7 @@ namespace { enum TimeType { OptimumTime, MaxTime }; const int MoveHorizon = 50; // Plan time management at most this many moves ahead - const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio + const double MaxRatio = 7.09; // When in trouble, we can step over reserved time with this ratio const double StealRatio = 0.35; // However we must not steal time from remaining moves over this ratio diff --git a/src/uci.cpp b/src/uci.cpp index 4d12ca40..cfd253b1 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -39,10 +39,10 @@ namespace { // FEN string of the initial position, normal chess const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; - // Stack to keep track of the position states along the setup moves (from the + // 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. - Search::StateStackPtr SetupStates; + StateListPtr States(new std::vector(1)); // position() is called when engine receives the "position" UCI command. @@ -68,14 +68,14 @@ namespace { else return; - pos.set(fen, Options["UCI_Chess960"], Threads.main()); - SetupStates = Search::StateStackPtr(new std::stack); + States = StateListPtr(new std::vector(1)); + pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main()); // Parse move list (if any) while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) { - SetupStates->push(StateInfo()); - pos.do_move(m, SetupStates->top(), pos.gives_check(m, CheckInfo(pos))); + States->push_back(StateInfo()); + pos.do_move(m, States->back(), pos.gives_check(m, CheckInfo(pos))); } } @@ -132,7 +132,7 @@ namespace { else if (token == "infinite") limits.infinite = 1; else if (token == "ponder") limits.ponder = 1; - Threads.start_thinking(pos, limits, SetupStates); + Threads.start_thinking(pos, States, limits); } } // namespace @@ -146,9 +146,11 @@ namespace { void UCI::loop(int argc, char* argv[]) { - Position pos(StartFEN, false, Threads.main()); // The root position + Position pos; string token, cmd; + pos.set(StartFEN, false, &States->back(), Threads.main()); + for (int i = 1; i < argc; ++i) cmd += std::string(argv[i]) + " ";