1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-07-13 20:49:15 +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; uint64_t nodes = 0;
TimePoint elapsed = now(); TimePoint elapsed = now();
Position pos;
for (size_t i = 0; i < fens.size(); ++i) 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; cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
@ -156,9 +158,8 @@ void benchmark(const Position& current, istream& is) {
else else
{ {
Search::StateStackPtr st;
limits.startTime = now(); limits.startTime = now();
Threads.start_thinking(pos, limits, st); Threads.start_thinking(pos, states, limits);
Threads.main()->wait_for_search_finished(); Threads.main()->wait_for_search_finished();
nodes += Threads.nodes_searched(); 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/" 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"; + 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 } // 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. /// 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 function is not very robust - make sure that input FENs are correct,
/// this is assumed to be the responsibility of the GUI. /// 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. 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; Square sq = SQ_A8;
std::istringstream ss(fenStr); 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; ss >> std::noskipws;
// 1. Piece placement // 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))) if (!(attackers_to(st->epSquare) & pieces(sideToMove, PAWN)))
st->epSquare = SQ_NONE; st->epSquare = SQ_NONE;
} }
else
st->epSquare = SQ_NONE;
// 5-6. Halfmove clock and fullmove number // 5-6. Halfmove clock and fullmove number
ss >> std::skipws >> st->rule50 >> gamePly; ss >> std::skipws >> st->rule50 >> gamePly;
@ -304,6 +279,8 @@ void Position::set(const string& fenStr, bool isChess960, Thread* th) {
set_state(st); set_state(st);
assert(pos_is_ok()); assert(pos_is_ok());
return *this;
} }
@ -1108,7 +1085,7 @@ void Position::flip() {
std::getline(ss, token); // Half and full moves std::getline(ss, token); // Half and full moves
f += token; f += token;
set(f, is_chess960(), this_thread()); set(f, is_chess960(), st, this_thread());
assert(pos_is_ok()); assert(pos_is_ok());
} }

View file

@ -23,7 +23,9 @@
#include <cassert> #include <cassert>
#include <cstddef> // For offsetof() #include <cstddef> // For offsetof()
#include <memory> // For std::unique_ptr
#include <string> #include <string>
#include <vector>
#include "bitboard.h" #include "bitboard.h"
#include "types.h" #include "types.h"
@ -75,6 +77,8 @@ struct StateInfo {
StateInfo* previous; StateInfo* previous;
}; };
typedef std::unique_ptr<std::vector<StateInfo>> StateListPtr;
/// Position class stores information regarding the board representation as /// Position class stores information regarding the board representation as
/// pieces, side to move, hash keys, castling info, etc. Important methods are /// pieces, side to move, hash keys, castling info, etc. Important methods are
@ -86,14 +90,12 @@ class Position {
public: public:
static void init(); static void init();
Position() = default; // To define the global object RootPos Position() = default;
Position(const Position&) = delete; Position(const Position&) = delete;
Position(const Position& pos, Thread* th) { *this = pos; thisThread = th; } Position& operator=(const Position&) = delete;
Position(const std::string& f, bool c960, Thread* th) { set(f, c960, th); }
Position& operator=(const Position&); // To assign RootPos from UCI
// FEN string input/output // 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; const std::string fen() const;
// Position representation // Position representation
@ -178,7 +180,6 @@ public:
private: private:
// Initialization helpers (used while setting up a position) // Initialization helpers (used while setting up a position)
void clear();
void set_castling_right(Color c, Square rfrom); void set_castling_right(Color c, Square rfrom);
void set_state(StateInfo* si) const; void set_state(StateInfo* si) const;
@ -200,7 +201,6 @@ private:
int castlingRightsMask[SQUARE_NB]; int castlingRightsMask[SQUARE_NB];
Square castlingRookSquare[CASTLING_RIGHT_NB]; Square castlingRookSquare[CASTLING_RIGHT_NB];
Bitboard castlingPath[CASTLING_RIGHT_NB]; Bitboard castlingPath[CASTLING_RIGHT_NB];
StateInfo startState;
uint64_t nodes; uint64_t nodes;
int gamePly; int gamePly;
Color sideToMove; Color sideToMove;

View file

@ -40,7 +40,6 @@ namespace Search {
SignalsType Signals; SignalsType Signals;
LimitsType Limits; LimitsType Limits;
StateStackPtr SetupStates;
} }
namespace Tablebases { namespace Tablebases {
@ -317,16 +316,8 @@ void MainThread::search() {
} }
for (Thread* th : Threads) for (Thread* th : Threads)
{
th->maxPly = 0;
th->rootDepth = DEPTH_ZERO;
if (th != this) if (th != this)
{
th->rootPos = Position(rootPos, th);
th->rootMoves = rootMoves;
th->start_searching(); th->start_searching();
}
}
Thread::search(); // Let's 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) { 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 static PRNG rng(now()); // PRNG sequence should be non-deterministic
// RootMoves are already sorted by score in descending order // RootMoves are already sorted by score in descending order
@ -1553,7 +1544,7 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
std::stringstream ss; std::stringstream ss;
int elapsed = Time.elapsed() + 1; 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 PVIdx = pos.this_thread()->PVIdx;
size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size()); size_t multiPV = std::min((size_t)Options["MultiPV"], rootMoves.size());
uint64_t nodes_searched = Threads.nodes_searched(); uint64_t nodes_searched = Threads.nodes_searched();

View file

@ -22,8 +22,6 @@
#define SEARCH_H_INCLUDED #define SEARCH_H_INCLUDED
#include <atomic> #include <atomic>
#include <memory> // For std::unique_ptr
#include <stack>
#include <vector> #include <vector>
#include "misc.h" #include "misc.h"
@ -65,7 +63,7 @@ struct RootMove {
std::vector<Move> pv; 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 /// 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 /// 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 { struct LimitsType {
LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC LimitsType() { // Init explicitly due to broken value-initialization of non POD in MSVC
nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] = npmsec = movestogo = nodes = time[WHITE] = time[BLACK] = inc[WHITE] = inc[BLACK] =
depth = movetime = mate = infinite = ponder = 0; npmsec = movestogo = depth = movetime = mate = infinite = ponder = 0;
} }
bool use_time_management() const { bool use_time_management() const {
@ -95,11 +93,8 @@ struct SignalsType {
std::atomic_bool stop, stopOnPonderhit; std::atomic_bool stop, stopOnPonderhit;
}; };
typedef std::unique_ptr<std::stack<StateInfo>> StateStackPtr;
extern SignalsType Signals; extern SignalsType Signals;
extern LimitsType Limits; extern LimitsType Limits;
extern StateStackPtr SetupStates;
void init(); void init();
void clear(); void clear();

View file

@ -95,8 +95,7 @@ static char *map_file(const std::string& name, const std::string& suffix, uint64
#else #else
DWORD size_low, size_high; DWORD size_low, size_high;
size_low = GetFileSize(fd, &size_high); size_low = GetFileSize(fd, &size_high);
HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low, HANDLE map = CreateFileMapping(fd, NULL, PAGE_READONLY, size_high, size_low, NULL);
NULL);
if (map == NULL) { if (map == NULL) {
std::cerr << "CreateFileMapping() failed\n"; std::cerr << "CreateFileMapping() failed\n";
@ -481,8 +480,7 @@ void free_wdl_entry(TBEntry_pawn* entry)
{ {
unmap_file(entry->data, entry->mapping); 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[0]);
free(entry->file[f].precomp[1]); free(entry->file[f].precomp[1]);
} }
@ -510,8 +508,7 @@ void Tablebases::init(const std::string& path)
free_wdl_entry(&TB_pawn[i]); free_wdl_entry(&TB_pawn[i]);
for (int i = 0; i < DTZ_ENTRIES; 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); free_dtz_entry(DTZ_table[i].entry);
DTZ_table[i].entry = nullptr; 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 // Fill binomial[] with the Binomial Coefficents using pascal triangle
// so that binomial[k-1][n] = Binomial(n, k). // 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; binomial[k][0] = 0;
for (int n = 1; n < 64; n++) for (int n = 1; n < 64; n++)
@ -565,20 +561,17 @@ void Tablebases::init(const std::string& path)
const std::string K("K"); 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"); 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] + pchr[p2] + "vK");
init_tb(K + pchr[p1] + "vK" + pchr[p2]); init_tb(K + pchr[p1] + "vK" + pchr[p2]);
for (PieceType p3 = PAWN; p3 < KING; ++p3) for (PieceType p3 = PAWN; p3 < KING; ++p3)
init_tb(K + pchr[p1] + pchr[p2] + "vK" + pchr[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"); init_tb(K + pchr[p1] + pchr[p2] + pchr[p3] + "vK");
for (PieceType p4 = PAWN; p4 <= p3; ++p4) 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 i, j, k, m, l, p;
int n = ptr->num; int n = ptr->num;
if (pos[0] & 0x04) { if (pos[0] & 4) {
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
pos[i] ^= 0x07; pos[i] ^= 7;
} }
if (pos[0] & 0x20) { 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]; s += binomial[m - i][p - j];
} }
idx += ((uint64_t)s) * ((uint64_t)factor[i]); idx += (uint64_t)s * ((uint64_t)factor[i]);
i += t; i += t;
} }
@ -698,7 +691,7 @@ static int pawn_file(TBEntry_pawn *ptr, int *pos)
if (flap[pos[0]] > flap[pos[i]]) if (flap[pos[0]] > flap[pos[i]])
std::swap(pos[0], 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) 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 i, j, k, m, s, t;
int n = ptr->num; int n = ptr->num;
if (pos[0] & 0x04) if (pos[0] & 4)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
pos[i] ^= 0x07; pos[i] ^= 7;
for (i = 1; i < ptr->pawns[0]; i++) for (i = 1; i < ptr->pawns[0]; i++)
for (j = i + 1; j < ptr->pawns[0]; j++) 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]; 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; 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]; s += binomial[m - i][p - j];
} }
idx += ((uint64_t)s) * ((uint64_t)factor[i]); idx += (uint64_t)s * ((uint64_t)factor[i]);
i += t; i += t;
} }
@ -1088,8 +1081,8 @@ static int init_table_wdl(TBEntry *entry, const std::string& str)
return 0; return 0;
} }
int split = data[4] & 0x01; int split = data[4] & 1;
int files = data[4] & 0x02 ? 4 : 1; int files = data[4] & 2 ? 4 : 1;
data += 5; data += 5;
@ -1097,7 +1090,7 @@ static int init_table_wdl(TBEntry *entry, const std::string& str)
TBEntry_piece *ptr = (TBEntry_piece *)entry; TBEntry_piece *ptr = (TBEntry_piece *)entry;
setup_pieces_piece(ptr, data, &tb_size[0]); setup_pieces_piece(ptr, data, &tb_size[0]);
data += ptr->num + 1; 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); ptr->precomp[0] = setup_pairs(data, tb_size[0], &size[0], &next, &flags, 1);
data = next; data = next;
@ -1124,12 +1117,12 @@ static int init_table_wdl(TBEntry *entry, const std::string& str)
data += size[4]; data += size[4];
} }
data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f);
ptr->precomp[0]->data = data; ptr->precomp[0]->data = data;
data += size[2]; data += size[2];
if (split) { if (split) {
data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f);
ptr->precomp[1]->data = data; ptr->precomp[1]->data = data;
} }
} else { } else {
@ -1141,7 +1134,7 @@ static int init_table_wdl(TBEntry *entry, const std::string& str)
data += ptr->num + s; data += ptr->num + s;
} }
data += ((uintptr_t)data) & 0x01; data += (uintptr_t)data & 1;
for (f = 0; f < files; f++) { for (f = 0; f < files; f++) {
ptr->file[f].precomp[0] = setup_pairs(data, tb_size[2 * f], &size[6 * f], &next, &flags, 1); 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++) { 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; ptr->file[f].precomp[0]->data = data;
data += size[6 * f + 2]; data += size[6 * f + 2];
if (split) { 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; ptr->file[f].precomp[1]->data = data;
data += size[6 * f + 5]; data += size[6 * f + 5];
} }
@ -1209,7 +1202,7 @@ static int init_table_dtz(TBEntry *entry)
return 0; return 0;
} }
int files = data[4] & 0x02 ? 4 : 1; int files = data[4] & 2 ? 4 : 1;
data += 5; data += 5;
@ -1217,7 +1210,7 @@ static int init_table_dtz(TBEntry *entry)
DTZEntry_piece *ptr = (DTZEntry_piece *)entry; DTZEntry_piece *ptr = (DTZEntry_piece *)entry;
setup_pieces_piece_dtz(ptr, data, &tb_size[0]); setup_pieces_piece_dtz(ptr, data, &tb_size[0]);
data += ptr->num + 1; 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); ptr->precomp = setup_pairs(data, tb_size[0], &size[0], &next, &(ptr->flags), 0);
data = next; data = next;
@ -1232,7 +1225,7 @@ static int init_table_dtz(TBEntry *entry)
data += 1 + data[0]; data += 1 + data[0];
} }
data += ((uintptr_t)data) & 0x01; data += (uintptr_t)data & 1;
} }
ptr->precomp->indextable = (char *)data; ptr->precomp->indextable = (char *)data;
@ -1241,7 +1234,7 @@ static int init_table_dtz(TBEntry *entry)
ptr->precomp->sizetable = (uint16_t *)data; ptr->precomp->sizetable = (uint16_t *)data;
data += size[1]; data += size[1];
data = (uint8_t *)((((uintptr_t)data) + 0x3f) & ~0x3f); data = (uint8_t *)(((uintptr_t)data + 0x3f) & ~0x3f);
ptr->precomp->data = data; ptr->precomp->data = data;
data += size[2]; data += size[2];
} else { } else {
@ -1253,7 +1246,7 @@ static int init_table_dtz(TBEntry *entry)
data += ptr->num + s; data += ptr->num + s;
} }
data += ((uintptr_t)data) & 0x01; data += (uintptr_t)data & 1;
for (f = 0; f < files; f++) { for (f = 0; f < files; f++) {
ptr->file[f].precomp = setup_pairs(data, tb_size[f], &size[3 * f], &next, &(ptr->flags[f]), 0); 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++) { for (f = 0; f < files; f++) {
ptr->file[f].precomp->indextable = (char *)data; ptr->file[f].precomp->indextable = (char *)data;
@ -1286,7 +1279,7 @@ static int init_table_dtz(TBEntry *entry)
} }
for (f = 0; f < files; f++) { 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; ptr->file[f].precomp->data = data;
data += size[3 * f + 2]; data += size[3 * f + 2];
} }
@ -1366,7 +1359,7 @@ static uint8_t decompress_pairs(PairsData *d, uint64_t idx)
if (LittleEndian) if (LittleEndian)
tmp = BSWAP32(tmp); 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; uint64_t key = 0;
Color color = mirror ? BLACK: WHITE; for (int i = 0; i < 2; i++) {
for (PieceType pt = PAWN; pt <= KING; ++pt) for (PieceType pt = PAWN; pt <= KING; ++pt)
for (int i = popcount(pos.pieces(color, pt)); i > 0; i--) for (int j = popcount(pos.pieces(Color(i ^ mirror), pt)); j > 0; j--)
key ^= Zobrist::psq[WHITE][pt][i - 1]; key ^= Zobrist::psq[i][pt][j - 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];
return key; return key;
} }
@ -75,17 +69,11 @@ static uint64_t calc_key_from_pcs(int *pcs, bool mirror)
{ {
uint64_t key = 0; uint64_t key = 0;
Color color = mirror ? BLACK : WHITE; for (int i = 0; i < 2; i++) {
for (PieceType pt = PAWN; pt <= KING; ++pt) for (PieceType pt = PAWN; pt <= KING; ++pt)
for (int i = 0; i < pcs[8 * color + pt]; i++) for (int j = 0; j < pcs[8 * (i ^ mirror) + pt]; j++)
key ^= Zobrist::psq[WHITE][pt][i]; key ^= Zobrist::psq[i][pt][j];
}
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];
return key; return key;
} }
@ -189,7 +177,7 @@ static int probe_wdl_table(Position& pos, int *success)
for (i = 0; i < entry->num;) { for (i = 0; i < entry->num;) {
Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
(PieceType)(pc[i] & 0x07)); (PieceType)(pc[i] & 7));
do { do {
p[i++] = pop_lsb(&bb); p[i++] = pop_lsb(&bb);
@ -201,7 +189,7 @@ static int probe_wdl_table(Position& pos, int *success)
} else { } else {
TBEntry_pawn *entry = (TBEntry_pawn *)ptr; TBEntry_pawn *entry = (TBEntry_pawn *)ptr;
int k = entry->file[0].pieces[0][0] ^ cmirror; 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; i = 0;
do { do {
@ -213,7 +201,7 @@ static int probe_wdl_table(Position& pos, int *success)
for (; i < entry->num;) { for (; i < entry->num;) {
bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
(PieceType)(pc[i] & 0x07)); (PieceType)(pc[i] & 7));
do { do {
p[i++] = pop_lsb(&bb) ^ mirror; 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); 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) 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;) { for (i = 0; i < entry->num;) {
Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), Bitboard bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
(PieceType)(pc[i] & 0x07)); (PieceType)(pc[i] & 7));
do { do {
p[i++] = pop_lsb(&bb); p[i++] = pop_lsb(&bb);
@ -329,7 +317,7 @@ static int probe_dtz_table(Position& pos, int wdl, int *success)
} else { } else {
DTZEntry_pawn *entry = (DTZEntry_pawn *)ptr; DTZEntry_pawn *entry = (DTZEntry_pawn *)ptr;
int k = entry->file[0].pieces[0] ^ cmirror; 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; i = 0;
do { do {
@ -347,7 +335,7 @@ static int probe_dtz_table(Position& pos, int wdl, int *success)
for (; i < entry->num;) { for (; i < entry->num;) {
bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3), bb = pos.pieces((Color)((pc[i] ^ cmirror) >> 3),
(PieceType)(pc[i] & 0x07)); (PieceType)(pc[i] & 7));
do { do {
p[i++] = pop_lsb(&bb) ^ mirror; 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 // A return value false indicates that not all probes were successful and that
// no moves were filtered out. // 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; 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 // A return value false indicates that not all probes were successful and that
// no moves were filtered out. // 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; int success;

View file

@ -10,8 +10,8 @@ extern int MaxCardinality;
void init(const std::string& path); void init(const std::string& path);
int probe_wdl(Position& pos, int *success); int probe_wdl(Position& pos, int *success);
int probe_dtz(Position& pos, int *success); int probe_dtz(Position& pos, int *success);
bool root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score); bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score);
bool root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score); bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score);
} }

View file

@ -26,8 +26,6 @@
#include "thread.h" #include "thread.h"
#include "uci.h" #include "uci.h"
using namespace Search;
ThreadPool Threads; // Global object ThreadPool Threads; // Global object
/// Thread constructor launches the thread and then waits until it goes to sleep /// 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() /// ThreadPool::start_thinking() wakes up the main thread sleeping in idle_loop()
/// and starts a new search, then returns immediately. /// and starts a new search, then returns immediately.
void ThreadPool::start_thinking(const Position& pos, const LimitsType& limits, void ThreadPool::start_thinking(const Position& pos, StateListPtr& states,
StateStackPtr& states) { const Search::LimitsType& limits) {
main()->wait_for_search_finished(); main()->wait_for_search_finished();
Signals.stopOnPonderhit = Signals.stop = false; Search::Signals.stopOnPonderhit = Search::Signals.stop = false;
Search::Limits = limits;
main()->rootMoves.clear(); Search::RootMoves rootMoves;
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());
}
for (const auto& m : MoveList<LEGAL>(pos)) for (const auto& m : MoveList<LEGAL>(pos))
if ( limits.searchmoves.empty() if ( limits.searchmoves.empty()
|| std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) || 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(); main()->start_searching();
} }

View file

@ -64,7 +64,7 @@ public:
int maxPly, callsCnt; int maxPly, callsCnt;
Position rootPos; Position rootPos;
Search::RootMoveVector rootMoves; Search::RootMoves rootMoves;
Depth rootDepth; Depth rootDepth;
HistoryStats history; HistoryStats history;
MoveStats counterMoves; MoveStats counterMoves;
@ -94,9 +94,12 @@ struct ThreadPool : public std::vector<Thread*> {
void exit(); // be initialized and valid during the whole thread lifetime. void exit(); // be initialized and valid during the whole thread lifetime.
MainThread* main() { return static_cast<MainThread*>(at(0)); } 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(); void read_uci_options();
int64_t nodes_searched(); int64_t nodes_searched();
private:
StateListPtr setupStates;
}; };
extern ThreadPool Threads; extern ThreadPool Threads;

View file

@ -39,10 +39,10 @@ namespace {
// FEN string of the initial position, normal chess // FEN string of the initial position, normal chess
const char* StartFEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"; 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 // start position to the position just before the search starts). Needed by
// 'draw by repetition' detection. // 'draw by repetition' detection.
Search::StateStackPtr SetupStates; StateListPtr States(new std::vector<StateInfo>(1));
// position() is called when engine receives the "position" UCI command. // position() is called when engine receives the "position" UCI command.
@ -68,14 +68,14 @@ namespace {
else else
return; return;
pos.set(fen, Options["UCI_Chess960"], Threads.main()); States = StateListPtr(new std::vector<StateInfo>(1));
SetupStates = Search::StateStackPtr(new std::stack<StateInfo>); pos.set(fen, Options["UCI_Chess960"], &States->back(), Threads.main());
// Parse move list (if any) // Parse move list (if any)
while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE) while (is >> token && (m = UCI::to_move(pos, token)) != MOVE_NONE)
{ {
SetupStates->push(StateInfo()); States->push_back(StateInfo());
pos.do_move(m, SetupStates->top(), pos.gives_check(m, CheckInfo(pos))); 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 == "infinite") limits.infinite = 1;
else if (token == "ponder") limits.ponder = 1; else if (token == "ponder") limits.ponder = 1;
Threads.start_thinking(pos, limits, SetupStates); Threads.start_thinking(pos, States, limits);
} }
} // namespace } // namespace
@ -146,9 +146,11 @@ namespace {
void UCI::loop(int argc, char* argv[]) { void UCI::loop(int argc, char* argv[]) {
Position pos(StartFEN, false, Threads.main()); // The root position Position pos;
string token, cmd; string token, cmd;
pos.set(StartFEN, false, &States->back(), Threads.main());
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
cmd += std::string(argv[i]) + " "; cmd += std::string(argv[i]) + " ";