/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
Copyright (c) 2013 Ronald de Man
- Copyright (C) 2016 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
// like captures and pawn moves but we can easily recover the correct dtz of the
// previous move if we know the position's WDL score.
int dtz_before_zeroing(WDLScore wdl) {
- return wdl == WDLWin ? 1 :
- wdl == WDLCursedWin ? 101 :
- wdl == WDLCursedLoss ? -101 :
- wdl == WDLLoss ? -1 : 0;
+ return wdl == WDLWin ? 1 :
+ wdl == WDLCursedWin ? 101 :
+ wdl == WDLBlessedLoss ? -101 :
+ wdl == WDLLoss ? -1 : 0;
}
// Return the sign of a number (-1, 0, 1)
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 {
PairsData* precomp;
- uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLCursedLoss
+ uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLBlessedLoss
uint8_t* map;
};
WDLEntry(const std::string& code);
~WDLEntry();
union {
- WLDEntryPiece pieceTable[2]; // [wtm / btm]
+ WDLEntryPiece pieceTable[2]; // [wtm / btm]
WDLEntryPawn pawnTable;
};
};
#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)
//
if ( (wdl == WDLWin && !(flags & TBFlag::WinPlies))
|| (wdl == WDLLoss && !(flags & TBFlag::LossPlies))
|| wdl == WDLCursedWin
- || wdl == WDLCursedLoss)
+ || wdl == WDLBlessedLoss)
value *= 2;
return value + 1;
// 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;
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.
d->flags = *data++;
if (d->flags & TBFlag::SingleValue) {
- d->blocksNum = d->span =
- d->blockLengthSize = d->sparseIndexSize = 0; // Broken MSVC zero-init
+ d->blocksNum = d->blockLengthSize = 0;
+ d->span = d->sparseIndexSize = 0; // Broken MSVC zero-init
d->minSymLen = *data++; // Here we store the single value
return data;
}
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)
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)
return 0;
if (*result != CHANGE_STM)
- return (dtz + 100 * (wdl == WDLCursedLoss || wdl == WDLCursedWin)) * sign_of(wdl);
+ return (dtz + 100 * (wdl == WDLBlessedLoss || wdl == WDLCursedWin)) * sign_of(wdl);
// DTZ stores results for the other side, so we need to do a 1-ply search and
// find the winning move that minimizes DTZ.
// 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.
- int wdl = 0;
+ WDLScore wdl = WDLDraw;
if (dtz > 0)
- wdl = (dtz + cnt50 <= 100) ? 2 : 1;
+ wdl = (dtz + cnt50 <= 100) ? WDLWin : WDLCursedWin;
else if (dtz < 0)
- wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
+ wdl = (-dtz + cnt50 <= 100) ? WDLLoss : WDLBlessedLoss;
// Determine the score to report to the user.
score = WDL_to_value[wdl + 2];
// If the position is winning or losing, but too few moves left, adjust the
// score to show how close it is to winning or losing.
// NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
- if (wdl == 1 && dtz <= 100)
+ if (wdl == WDLCursedWin && dtz <= 100)
score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
- else if (wdl == -1 && dtz >= -100)
+ else if (wdl == WDLBlessedLoss && dtz >= -100)
score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
// Now be a bit smart about filtering out moves.