1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-13 12:39:16 +00:00

Syzygy pull (#639)

* factorize repetitive code in calc_key() and calc_key_from_pcs()

and do some cleanup while at it.

* sync with master

No functional change.
This commit is contained in:
lucasart 2016-04-18 20:08:23 +08:00 committed by Marco Costalba
parent e8610fbe7c
commit a037e20f28
13 changed files with 118 additions and 161 deletions

View file

@ -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<StateInfo>(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();
}

View file

@ -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

View file

@ -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());
}

View file

@ -23,7 +23,9 @@
#include <cassert>
#include <cstddef> // For offsetof()
#include <memory> // For std::unique_ptr
#include <string>
#include <vector>
#include "bitboard.h"
#include "types.h"
@ -75,6 +77,8 @@ struct StateInfo {
StateInfo* previous;
};
typedef std::unique_ptr<std::vector<StateInfo>> 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;

View file

@ -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();

View file

@ -22,8 +22,6 @@
#define SEARCH_H_INCLUDED
#include <atomic>
#include <memory> // For std::unique_ptr
#include <stack>
#include <vector>
#include "misc.h"
@ -65,7 +63,7 @@ struct RootMove {
std::vector<Move> pv;
};
typedef std::vector<RootMove> RootMoveVector;
typedef std::vector<RootMove> 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<RootMove> 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<std::stack<StateInfo>> StateStackPtr;
extern SignalsType Signals;
extern LimitsType Limits;
extern StateStackPtr SetupStates;
void init();
void clear();

View file

@ -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;
}
}

View file

@ -52,17 +52,11 @@ static uint64_t calc_key(Position& pos, bool mirror)
{
uint64_t key = 0;
Color color = mirror ? BLACK: WHITE;
for (int i = 0; i < 2; i++) {
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 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 (int i = 0; i < 2; i++) {
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 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;

View file

@ -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);
}

View file

@ -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<LEGAL>(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();
}

View file

@ -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<Thread*> {
void exit(); // be initialized and valid during the whole thread lifetime.
MainThread* main() { return static_cast<MainThread*>(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;

View file

@ -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<StateInfo>(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<StateInfo>);
States = StateListPtr(new std::vector<StateInfo>(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]) + " ";