/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016-2017 Marco Costalba, Lucas Braesch
+ Copyright (C) 2016-2018 Marco Costalba, Lucas Braesch
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static_assert(sizeof(LR) == 3, "LR tree entry must be 3 bytes");
-const int TBPIECES = 6;
+constexpr int TBPIECES = 6;
struct PairsData {
int flags;
std::atomic_bool ready;
};
-// We define types for the different parts of the WLDEntry and DTZEntry with
+// We define types for the different parts of the WDLEntry and DTZEntry with
// corresponding specializations for pieces or pawns.
-struct WLDEntryPiece {
+struct WDLEntryPiece {
PairsData* precomp;
};
struct WDLEntryPawn {
uint8_t pawnCount[2]; // [Lead color / other color]
- WLDEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D]
+ WDLEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D]
};
struct DTZEntryPiece {
WDLEntry(const std::string& code);
~WDLEntry();
union {
- WLDEntryPiece pieceTable[2]; // [wtm / btm]
+ WDLEntryPiece pieceTable[2]; // [wtm / btm]
WDLEntryPawn pawnTable;
};
};
bool pawns_comp(Square i, Square j) { return MapPawns[i] < MapPawns[j]; }
int off_A1H8(Square sq) { return int(rank_of(sq)) - file_of(sq); }
-const Value WDL_to_value[] = {
+constexpr Value WDL_to_value[] = {
-VALUE_MATE + MAX_PLY + 1,
VALUE_DRAW - 2,
VALUE_DRAW,
typedef std::pair<WDLEntry*, DTZEntry*> EntryPair;
typedef std::pair<Key, EntryPair> Entry;
- static const int TBHASHBITS = 10;
- static const int HSHMAX = 5;
+ static constexpr int TBHASHBITS = 10;
+ static constexpr int HSHMAX = 5;
Entry hashTable[1 << TBHASHBITS][HSHMAX];
TBFile(const std::string& f) {
#ifndef _WIN32
- const char SepChar = ':';
+ constexpr char SepChar = ':';
#else
- const char SepChar = ';';
+ constexpr char SepChar = ';';
#endif
std::stringstream ss(Paths);
std::string path;
#ifndef _WIN32
struct stat statbuf;
int fd = ::open(fname.c_str(), O_RDONLY);
+
+ if (fd == -1)
+ return *baseAddress = nullptr, nullptr;
+
fstat(fd, &statbuf);
*mapping = statbuf.st_size;
*baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
#else
HANDLE fd = CreateFile(fname.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
+
+ if (fd == INVALID_HANDLE_VALUE)
+ return *baseAddress = nullptr, nullptr;
+
DWORD size_high;
DWORD size_low = GetFileSize(fd, &size_high);
HANDLE mmap = CreateFileMapping(fd, nullptr, PAGE_READONLY, size_high, size_low, nullptr);
|| *data++ != *TB_MAGIC) {
std::cerr << "Corrupted table in file " << fname << std::endl;
unmap(*baseAddress, *mapping);
- *baseAddress = nullptr;
- return nullptr;
+ return *baseAddress = nullptr, nullptr;
}
return data;
TBFile file(code.insert(code.find('K', 1), "v") + ".rtbw"); // KRK -> KRvK
- if (!file.is_open())
+ if (!file.is_open()) // Only WDL file is checked
return;
file.close();
MaxCardinality = std::max((int)pieces.size(), MaxCardinality);
- wdlTable.push_back(WDLEntry(code));
- dtzTable.push_back(DTZEntry(wdlTable.back()));
+ wdlTable.emplace_back(code);
+ dtzTable.emplace_back(wdlTable.back());
insert(wdlTable.back().key , &wdlTable.back(), &dtzTable.back());
insert(wdlTable.back().key2, &wdlTable.back(), &dtzTable.back());
//
// I(k) = k * d->span + d->span / 2 (1)
- // First step is to get the 'k' of the I(k) nearest to our idx, using defintion (1)
+ // First step is to get the 'k' of the I(k) nearest to our idx, using definition (1)
uint32_t k = idx / d->span;
// Then we read the corresponding SparseIndex[] entry
uint32_t block = number<uint32_t, LittleEndian>(&d->sparseIndex[k].block);
int offset = number<uint16_t, LittleEndian>(&d->sparseIndex[k].offset);
- // Now compute the difference idx - I(k). From defintion of k we know that
+ // Now compute the difference idx - I(k). From definition of k we know that
//
// idx = k * d->span + idx % d->span (2)
//
int map_score(DTZEntry* entry, File f, int value, WDLScore wdl) {
- const int WDLMap[] = { 1, 3, 0, 2, 0 };
+ constexpr int WDLMap[] = { 1, 3, 0, 2, 0 };
int flags = entry->hasPawns ? entry->pawnTable.file[f].precomp->flags
: entry->pieceTable.precomp->flags;
// idx = Binomial[1][s1] + Binomial[2][s2] + ... + Binomial[k][sk]
//
template<typename Entry, typename T = typename Ret<Entry>::type>
-T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* result) {
+T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* result) {
- const bool IsWDL = std::is_same<Entry, WDLEntry>::value;
+ constexpr bool IsWDL = std::is_same<Entry, WDLEntry>::value;
Square squares[TBPIECES];
Piece pieces[TBPIECES];
assert(type_of(pc) == PAWN);
leadPawns = b = pos.pieces(color_of(pc), PAWN);
- while (b)
+ do
squares[size++] = pop_lsb(&b) ^ flipSquares;
+ while (b);
leadPawnsCnt = size;
// Now we are ready to get all the position pieces (but the lead pawns) and
// directly map them to the correct color and square.
b = pos.pieces() ^ leadPawns;
- while (b) {
+ do {
Square s = pop_lsb(&b);
squares[size] = s ^ flipSquares;
pieces[size++] = Piece(pos.piece_on(s) ^ flipColor);
- }
+ } while (b);
+
+ assert(size >= 2);
// Then we reorder the pieces to have the same sequence as the one stored
// in precomp->pieces[i]: the sequence that ensures the best compression.
data++; // First byte stores flags
- const int Sides = IsWDL && (e.key != e.key2) ? 2 : 1;
- const File MaxFile = e.hasPawns ? FILE_D : FILE_A;
+ const int sides = IsWDL && (e.key != e.key2) ? 2 : 1;
+ const File maxFile = e.hasPawns ? FILE_D : FILE_A;
bool pp = e.hasPawns && e.pawnTable.pawnCount[1]; // Pawns on both sides
assert(!pp || e.pawnTable.pawnCount[0]);
- for (File f = FILE_A; f <= MaxFile; ++f) {
+ for (File f = FILE_A; f <= maxFile; ++f) {
- for (int i = 0; i < Sides; i++)
+ for (int i = 0; i < sides; i++)
item(p, i, f).precomp = new PairsData();
int order[][2] = { { *data & 0xF, pp ? *(data + 1) & 0xF : 0xF },
data += 1 + pp;
for (int k = 0; k < e.pieceCount; ++k, ++data)
- for (int i = 0; i < Sides; i++)
+ for (int i = 0; i < sides; i++)
item(p, i, f).precomp->pieces[k] = Piece(i ? *data >> 4 : *data & 0xF);
- for (int i = 0; i < Sides; ++i)
+ for (int i = 0; i < sides; ++i)
set_groups(e, item(p, i, f).precomp, order[i], f);
}
data += (uintptr_t)data & 1; // Word alignment
- for (File f = FILE_A; f <= MaxFile; ++f)
- for (int i = 0; i < Sides; i++)
+ for (File f = FILE_A; f <= maxFile; ++f)
+ for (int i = 0; i < sides; i++)
data = set_sizes(item(p, i, f).precomp, data);
if (!IsWDL)
- data = set_dtz_map(e, p, data, MaxFile);
+ data = set_dtz_map(e, p, data, maxFile);
- for (File f = FILE_A; f <= MaxFile; ++f)
- for (int i = 0; i < Sides; i++) {
+ for (File f = FILE_A; f <= maxFile; ++f)
+ for (int i = 0; i < sides; i++) {
(d = item(p, i, f).precomp)->sparseIndex = (SparseEntry*)data;
- data += d->sparseIndexSize * sizeof(SparseEntry) ;
+ data += d->sparseIndexSize * sizeof(SparseEntry);
}
- for (File f = FILE_A; f <= MaxFile; ++f)
- for (int i = 0; i < Sides; i++) {
+ for (File f = FILE_A; f <= maxFile; ++f)
+ for (int i = 0; i < sides; i++) {
(d = item(p, i, f).precomp)->blockLength = (uint16_t*)data;
data += d->blockLengthSize * sizeof(uint16_t);
}
- for (File f = FILE_A; f <= MaxFile; ++f)
- for (int i = 0; i < Sides; i++) {
+ for (File f = FILE_A; f <= maxFile; ++f)
+ for (int i = 0; i < sides; i++) {
data = (uint8_t*)(((uintptr_t)data + 0x3F) & ~0x3F); // 64 byte alignment
(d = item(p, i, f).precomp)->data = data;
data += d->blocksNum * d->sizeofBlock;
template<typename Entry>
void* init(Entry& e, const Position& pos) {
- const bool IsWDL = std::is_same<Entry, WDLEntry>::value;
+ constexpr bool IsWDL = std::is_same<Entry, WDLEntry>::value;
static Mutex mutex;
b += std::string(popcount(pos.pieces(BLACK, pt)), PieceToChar[pt]);
}
- const uint8_t TB_MAGIC[][4] = { { 0xD7, 0x66, 0x0C, 0xA5 },
+ constexpr uint8_t TB_MAGIC[][4] = { { 0xD7, 0x66, 0x0C, 0xA5 },
{ 0x71, 0xE8, 0x23, 0x5D } };
fname = (e.key == pos.material_key() ? w + 'v' + b : b + 'v' + w)
if (MapA1D1D4[s1] == idx && (idx || s1 == SQ_B1)) // SQ_B1 is mapped to 0
{
for (Square s2 = SQ_A1; s2 <= SQ_H8; ++s2)
- if ((StepAttacksBB[KING][s1] | s1) & s2)
+ if ((PseudoAttacks[KING][s1] | s1) & s2)
continue; // Illegal position
else if (!off_A1H8(s1) && off_A1H8(s2) > 0)
// no moves were filtered out.
bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score)
{
+ assert(rootMoves.size());
+
ProbeState result;
int dtz = probe_dtz(pos, &result);
// Obtain 50-move counter for the root position.
// In Stockfish there seems to be no clean way, so we do it like this:
- int cnt50 = st.previous->rule50;
+ int cnt50 = st.previous ? st.previous->rule50 : 0;
// Use 50-move counter to determine whether the root position is
// won, lost or drawn.