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:
parent
e8610fbe7c
commit
a037e20f28
13 changed files with 118 additions and 161 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
11
src/search.h
11
src/search.h
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
18
src/uci.cpp
18
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<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]) + " ";
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue