X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsyzygy%2Ftbprobe.cpp;h=c0cd04c1d4d8bd8f30607b616ae02363cb84da69;hp=2b7f4497246e90a7105ebd202cfe0246191402a3;hb=699bae632f283746a3eee15c0950fcdbca8a355e;hpb=e8005ebe569c102bca627b24c1dcf1b8a2d900c8 diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index 2b7f4497..c0cd04c1 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -1,7 +1,6 @@ /* Stockfish, a UCI chess playing engine derived from Glaurung 2.1 - Copyright (c) 2013 Ronald de Man - Copyright (C) 2016-2018 Marco Costalba, Lucas Braesch + Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file) Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,12 +26,12 @@ #include #include #include +#include #include "../bitboard.h" #include "../movegen.h" #include "../position.h" #include "../search.h" -#include "../thread_win32.h" #include "../types.h" #include "../uci.h" @@ -45,26 +44,29 @@ #include #else #define WIN32_LEAN_AND_MEAN -#define NOMINMAX +#ifndef NOMINMAX +# define NOMINMAX // Disable macros min() and max() +#endif #include #endif -using namespace Tablebases; +using namespace Stockfish::Tablebases; + +int Stockfish::Tablebases::MaxCardinality; -int Tablebases::MaxCardinality; +namespace Stockfish { namespace { -constexpr int TBPIECES = 6; // Max number of supported pieces +constexpr int TBPIECES = 7; // Max number of supported pieces enum { BigEndian, LittleEndian }; -enum TBType { KEY, WDL, DTZ }; // Used as template parameter +enum TBType { WDL, DTZ }; // Used as template parameter // Each table has a set of flags: all of them refer to DTZ tables, the last one to WDL tables -enum TBFlag { STM = 1, Mapped = 2, WinPlies = 4, LossPlies = 8, SingleValue = 128 }; +enum TBFlag { STM = 1, Mapped = 2, WinPlies = 4, LossPlies = 8, Wide = 16, SingleValue = 128 }; inline WDLScore operator-(WDLScore d) { return WDLScore(-int(d)); } -inline Square operator^=(Square& s, int i) { return s = Square(int(s) ^ i); } inline Square operator^(Square s, int i) { return Square(int(s) ^ i); } const std::string PieceToChar = " PNBRQK pnbrqk"; @@ -74,9 +76,9 @@ int MapB1H1H7[SQUARE_NB]; int MapA1D1D4[SQUARE_NB]; int MapKK[10][SQUARE_NB]; // [MapA1D1D4][SQUARE_NB] -int Binomial[6][SQUARE_NB]; // [k][n] k elements from a set of n elements -int LeadPawnIdx[5][SQUARE_NB]; // [leadPawnsCnt][SQUARE_NB] -int LeadPawnsSize[5][4]; // [leadPawnsCnt][FILE_A..FILE_D] +int Binomial[7][SQUARE_NB]; // [k][n] k elements from a set of n elements +int LeadPawnIdx[6][SQUARE_NB]; // [leadPawnsCnt][SQUARE_NB] +int LeadPawnsSize[6][4]; // [leadPawnsCnt][FILE_A..FILE_D] // Comparison function to sort leading pawns in ascending MapPawns[] order bool pawns_comp(Square i, Square j) { return MapPawns[i] < MapPawns[j]; } @@ -144,16 +146,15 @@ static_assert(sizeof(SparseEntry) == 6, "SparseEntry must be 6 bytes"); typedef uint16_t Sym; // Huffman symbol struct LR { - enum Side { Left, Right, Value }; + enum Side { Left, Right }; uint8_t lr[3]; // The first 12 bits is the left-hand symbol, the second 12 // bits is the right-hand symbol. If symbol has length 1, - // then the first byte is the stored value. + // then the left-hand symbol is the stored value. template Sym get() { return S == Left ? ((lr[1] & 0xF) << 8) | lr[0] : - S == Right ? (lr[2] << 4) | (lr[1] >> 4) : - S == Value ? lr[0] : (assert(false), Sym(-1)); + S == Right ? (lr[2] << 4) | (lr[1] >> 4) : (assert(false), Sym(-1)); } }; @@ -215,38 +216,59 @@ public: return *baseAddress = nullptr, nullptr; fstat(fd, &statbuf); + + if (statbuf.st_size % 64 != 16) + { + std::cerr << "Corrupt tablebase file " << fname << std::endl; + exit(EXIT_FAILURE); + } + *mapping = statbuf.st_size; *baseAddress = mmap(nullptr, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); +#if defined(MADV_RANDOM) + madvise(*baseAddress, statbuf.st_size, MADV_RANDOM); +#endif ::close(fd); - if (*baseAddress == MAP_FAILED) { + if (*baseAddress == MAP_FAILED) + { std::cerr << "Could not mmap() " << fname << std::endl; - exit(1); + exit(EXIT_FAILURE); } #else + // Note FILE_FLAG_RANDOM_ACCESS is only a hint to Windows and as such may get ignored. HANDLE fd = CreateFile(fname.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, nullptr); if (fd == INVALID_HANDLE_VALUE) return *baseAddress = nullptr, nullptr; DWORD size_high; DWORD size_low = GetFileSize(fd, &size_high); + + if (size_low % 64 != 16) + { + std::cerr << "Corrupt tablebase file " << fname << std::endl; + exit(EXIT_FAILURE); + } + HANDLE mmap = CreateFileMapping(fd, nullptr, PAGE_READONLY, size_high, size_low, nullptr); CloseHandle(fd); - if (!mmap) { + if (!mmap) + { std::cerr << "CreateFileMapping() failed" << std::endl; - exit(1); + exit(EXIT_FAILURE); } *mapping = (uint64_t)mmap; *baseAddress = MapViewOfFile(mmap, FILE_MAP_READ, 0, 0, 0); - if (!*baseAddress) { + if (!*baseAddress) + { std::cerr << "MapViewOfFile() failed, name = " << fname << ", error = " << GetLastError() << std::endl; - exit(1); + exit(EXIT_FAILURE); } #endif uint8_t* data = (uint8_t*)*baseAddress; @@ -254,7 +276,8 @@ public: constexpr uint8_t Magics[][4] = { { 0xD7, 0x66, 0x0C, 0xA5 }, { 0x71, 0xE8, 0x23, 0x5D } }; - if (memcmp(data, Magics[type == WDL], 4)) { + if (memcmp(data, Magics[type == WDL], 4)) + { std::cerr << "Corrupted table in file " << fname << std::endl; unmap(*baseAddress, *mapping); return *baseAddress = nullptr, nullptr; @@ -348,7 +371,7 @@ TBTable::TBTable(const std::string& code) : TBTable() { hasPawns = pos.pieces(PAWN); hasUniquePieces = false; - for (Color c = WHITE; c <= BLACK; ++c) + for (Color c : { WHITE, BLACK }) for (PieceType pt = PAWN; pt < KING; ++pt) if (popcount(pos.pieces(c, pt)) == 1) hasUniquePieces = true; @@ -383,34 +406,57 @@ TBTable::TBTable(const TBTable& wdl) : TBTable() { // at init time, accessed at probe time. class TBTables { - typedef std::tuple*, TBTable*> Entry; + struct Entry + { + Key key; + TBTable* wdl; + TBTable* dtz; - static const int Size = 1 << 12; // 4K table, indexed by key's 12 lsb + template + TBTable* get() const { + return (TBTable*)(Type == WDL ? (void*)wdl : (void*)dtz); + } + }; - Entry hashTable[Size]; + static constexpr int Size = 1 << 12; // 4K table, indexed by key's 12 lsb + static constexpr int Overflow = 1; // Number of elements allowed to map to the last bucket + + Entry hashTable[Size + Overflow]; std::deque> wdlTable; std::deque> dtzTable; void insert(Key key, TBTable* wdl, TBTable* dtz) { - Entry* entry = &hashTable[(uint32_t)key & (Size - 1)]; + uint32_t homeBucket = (uint32_t)key & (Size - 1); + Entry entry{ key, wdl, dtz }; // Ensure last element is empty to avoid overflow when looking up - for ( ; entry - hashTable < Size - 1; ++entry) - if (std::get(*entry) == key || !std::get(*entry)) { - *entry = std::make_tuple(key, wdl, dtz); + for (uint32_t bucket = homeBucket; bucket < Size + Overflow - 1; ++bucket) { + Key otherKey = hashTable[bucket].key; + if (otherKey == key || !hashTable[bucket].get()) { + hashTable[bucket] = entry; return; } + + // Robin Hood hashing: If we've probed for longer than this element, + // insert here and search for a new spot for the other element instead. + uint32_t otherHomeBucket = (uint32_t)otherKey & (Size - 1); + if (otherHomeBucket > homeBucket) { + std::swap(entry, hashTable[bucket]); + key = otherKey; + homeBucket = otherHomeBucket; + } + } std::cerr << "TB hash table size too low!" << std::endl; - exit(1); + exit(EXIT_FAILURE); } public: template TBTable* get(Key key) { for (const Entry* entry = &hashTable[(uint32_t)key & (Size - 1)]; ; ++entry) { - if (std::get(*entry) == key || !std::get(*entry)) - return std::get(*entry); + if (entry->key == key || !entry->get()) + return entry->get(); } } @@ -487,7 +533,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) { // 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 definition (1) - uint32_t k = idx / d->span; + uint32_t k = uint32_t(idx / d->span); // Then we read the corresponding SparseIndex[] entry uint32_t block = number(&d->sparseIndex[k].block); @@ -512,7 +558,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) { offset -= d->blockLength[block++] + 1; // Finally, we find the start address of our block of canonical Huffman symbols - uint32_t* ptr = (uint32_t*)(d->data + block * d->sizeofBlock); + uint32_t* ptr = (uint32_t*)(d->data + ((uint64_t)block * d->sizeofBlock)); // Read the first 64 bits in our block, this is a (truncated) sequence of // unknown number of symbols of unknown length but we know the first one @@ -533,7 +579,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) { // All the symbols of a given length are consecutive integers (numerical // sequence property), so we can compute the offset of our symbol of // length len, stored at the beginning of buf64. - sym = (buf64 - d->base64[len]) >> (64 - len - d->minSymLen); + sym = Sym((buf64 - d->base64[len]) >> (64 - len - d->minSymLen)); // Now add the value of the lowest symbol of length len to get our symbol sym += number(&d->lowestSym[len]); @@ -575,7 +621,7 @@ int decompress_pairs(PairsData* d, uint64_t idx) { } } - return d->btree[sym].get(); + return d->btree[sym].get(); } bool check_dtz_stm(TBTable*, int, File) { return true; } @@ -601,8 +647,12 @@ int map_score(TBTable* entry, File f, int value, WDLScore wdl) { uint8_t* map = entry->map; uint16_t* idx = entry->get(0, f)->map_idx; - if (flags & TBFlag::Mapped) - value = map[idx[WDLMap[wdl + 2]] + value]; + if (flags & TBFlag::Mapped) { + if (flags & TBFlag::Wide) + value = ((uint16_t *)map)[idx[WDLMap[wdl + 2]] + value]; + else + value = map[idx[WDLMap[wdl + 2]] + value]; + } // DTZ tables store distance to zero in number of moves or plies. We // want to return plies, so we have convert to plies when needed. @@ -645,7 +695,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu bool blackStronger = (pos.material_key() != entry->key); int flipColor = (symmetricBlackToMove || blackStronger) * 8; - int flipSquares = (symmetricBlackToMove || blackStronger) * 070; + int flipSquares = (symmetricBlackToMove || blackStronger) * 56; int stm = (symmetricBlackToMove || blackStronger) ^ pos.side_to_move(); // For pawns, TB files store 4 separate tables according if leading pawn is on @@ -668,9 +718,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu std::swap(squares[0], *std::max_element(squares, squares + leadPawnsCnt, pawns_comp)); - tbFile = file_of(squares[0]); - if (tbFile > FILE_D) - tbFile = file_of(squares[0] ^ 7); // Horizontal flip: SQ_H1 -> SQ_A1 + tbFile = File(edge_distance(file_of(squares[0]))); } // DTZ tables are one-sided, i.e. they store positions only for white to @@ -694,8 +742,8 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu // Then we reorder the pieces to have the same sequence as the one stored // in pieces[i]: the sequence that ensures the best compression. - for (int i = leadPawnsCnt; i < size; ++i) - for (int j = i; j < size; ++j) + for (int i = leadPawnsCnt; i < size - 1; ++i) + for (int j = i + 1; j < size; ++j) if (d->pieces[i] == pieces[j]) { std::swap(pieces[i], pieces[j]); @@ -707,14 +755,14 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu // the triangle A1-D1-D4. if (file_of(squares[0]) > FILE_D) for (int i = 0; i < size; ++i) - squares[i] ^= 7; // Horizontal flip: SQ_H1 -> SQ_A1 + squares[i] = flip_file(squares[i]); // Encode leading pawns starting with the one with minimum MapPawns[] and // proceeding in ascending order. if (entry->hasPawns) { idx = LeadPawnIdx[leadPawnsCnt][squares[0]]; - std::sort(squares + 1, squares + leadPawnsCnt, pawns_comp); + std::stable_sort(squares + 1, squares + leadPawnsCnt, pawns_comp); for (int i = 1; i < leadPawnsCnt; ++i) idx += Binomial[i][MapPawns[squares[i]]]; @@ -726,7 +774,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu // piece is below RANK_5. if (rank_of(squares[0]) > RANK_4) for (int i = 0; i < size; ++i) - squares[i] ^= 070; // Vertical flip: SQ_A8 -> SQ_A1 + squares[i] = flip_rank(squares[i]); // Look for the first piece of the leading group not on the A1-D4 diagonal // and ensure it is mapped below the diagonal. @@ -734,7 +782,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu if (!off_A1H8(squares[i])) continue; - if (off_A1H8(squares[i]) > 0) // A1-H8 diagonal flip: SQ_A3 -> SQ_C3 + if (off_A1H8(squares[i]) > 0) // A1-H8 diagonal flip: SQ_A3 -> SQ_C1 for (int j = i; j < size; ++j) squares[j] = Square(((squares[j] >> 3) | (squares[j] << 3)) & 63); break; @@ -815,7 +863,7 @@ encode_remaining: while (d->groupLen[++next]) { - std::sort(groupSq, groupSq + d->groupLen[next]); + std::stable_sort(groupSq, groupSq + d->groupLen[next]); uint64_t n = 0; // Map down a square if "comes later" than a square in the previous @@ -939,7 +987,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) { d->sizeofBlock = 1ULL << *data++; d->span = 1ULL << *data++; - d->sparseIndexSize = (tbSize + d->span - 1) / d->span; // Round up + d->sparseIndexSize = size_t((tbSize + d->span - 1) / d->span); // Round up auto padding = number(data++); d->blocksNum = number(data); data += sizeof(uint32_t); d->blockLengthSize = d->blocksNum + padding; // Padded to ensure SparseIndex[] @@ -954,7 +1002,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) { // so that d->lowestSym[i] >= d->lowestSym[i+1] (when read as LittleEndian). // Starting from this we compute a base64[] table indexed by symbol length // and containing 64 bit values so that d->base64[i] >= d->base64[i+1]. - // See http://www.eecs.harvard.edu/~michaelm/E210/huffman.pdf + // See https://en.wikipedia.org/wiki/Huffman_coding for (int i = d->base64.size() - 2; i >= 0; --i) { d->base64[i] = (d->base64[i + 1] + number(&d->lowestSym[i]) - number(&d->lowestSym[i + 1])) / 2; @@ -973,7 +1021,7 @@ uint8_t* set_sizes(PairsData* d, uint8_t* data) { d->symlen.resize(number(data)); data += sizeof(uint16_t); d->btree = (LR*)data; - // The comrpession scheme used is "Recursive Pairing", that replaces the most + // The compression scheme used is "Recursive Pairing", that replaces the most // frequent adjacent pair of symbols in the source message by a new symbol, // reevaluating the frequencies of all of the symbol pairs with respect to // the extended alphabet, and then repeating the process. @@ -994,11 +1042,22 @@ uint8_t* set_dtz_map(TBTable& e, uint8_t* data, File maxFile) { e.map = data; for (File f = FILE_A; f <= maxFile; ++f) { - if (e.get(0, f)->flags & TBFlag::Mapped) - for (int i = 0; i < 4; ++i) { // Sequence like 3,x,x,x,1,x,0,2,x,x - e.get(0, f)->map_idx[i] = (uint16_t)(data - e.map + 1); - data += *data + 1; + auto flags = e.get(0, f)->flags; + if (flags & TBFlag::Mapped) { + if (flags & TBFlag::Wide) { + data += (uintptr_t)data & 1; // Word alignment, we may have a mixed table + for (int i = 0; i < 4; ++i) { // Sequence like 3,x,x,x,1,x,0,2,x,x + e.get(0, f)->map_idx[i] = (uint16_t)((uint16_t *)data - (uint16_t *)e.map + 1); + data += 2 * number(data) + 2; + } + } + else { + for (int i = 0; i < 4; ++i) { + e.get(0, f)->map_idx[i] = (uint16_t)(data - e.map + 1); + data += *data + 1; + } } + } } return data += (uintptr_t)data & 1; // Word alignment @@ -1013,8 +1072,8 @@ void set(T& e, uint8_t* data) { enum { Split = 1, HasPawns = 2 }; - assert(e.hasPawns == !!(*data & HasPawns)); - assert((e.key != e.key2) == !!(*data & Split)); + assert(e.hasPawns == bool(*data & HasPawns)); + assert((e.key != e.key2) == bool(*data & Split)); data++; // First byte stores flags @@ -1077,14 +1136,14 @@ void set(T& e, uint8_t* data) { template void* mapped(TBTable& e, const Position& pos) { - static Mutex mutex; + static std::mutex mutex; - // Use 'aquire' to avoid a thread reads 'ready' == true while another is - // still working, this could happen due to compiler reordering. + // Use 'acquire' to avoid a thread reading 'ready' == true while + // another is still working. (compiler reordering may cause this). if (e.ready.load(std::memory_order_acquire)) - return e.baseAddress; // Could be nullptr if file does not exsist + return e.baseAddress; // Could be nullptr if file does not exist - std::unique_lock lk(mutex); + std::scoped_lock lk(mutex); if (e.ready.load(std::memory_order_relaxed)) // Recheck under lock return e.baseAddress; @@ -1144,7 +1203,7 @@ WDLScore search(Position& pos, ProbeState* result) { auto moveList = MoveList(pos); size_t totalCount = moveList.size(), moveCount = 0; - for (const Move& move : moveList) + for (const Move move : moveList) { if ( !pos.capture(move) && (!CheckZeroingMoves || type_of(pos.moved_piece(move)) != PAWN)) @@ -1249,7 +1308,7 @@ void Tablebases::init(const std::string& paths) { continue; // First on diagonal, second above else if (!off_A1H8(s1) && !off_A1H8(s2)) - bothOnDiagonal.push_back(std::make_pair(idx, s2)); + bothOnDiagonal.emplace_back(idx, s2); else MapKK[idx][s2] = code++; @@ -1264,7 +1323,7 @@ void Tablebases::init(const std::string& paths) { Binomial[0][0] = 1; for (int n = 1; n < 64; n++) // Squares - for (int k = 0; k < 6 && k <= n; ++k) // Pieces + for (int k = 0; k < 7 && k <= n; ++k) // Pieces Binomial[k][n] = (k > 0 ? Binomial[k - 1][n - 1] : 0) + (k < n ? Binomial[k ][n - 1] : 0); @@ -1274,9 +1333,9 @@ void Tablebases::init(const std::string& paths) { // among pawns with same file, the one with lowest rank. int availableSquares = 47; // Available squares when lead pawn is in a2 - // Init the tables for the encoding of leading pawns group: with 6-men TB we - // can have up to 4 leading pawns (KPPPPK). - for (int leadPawnsCnt = 1; leadPawnsCnt <= 4; ++leadPawnsCnt) + // Init the tables for the encoding of leading pawns group: with 7-men TB we + // can have up to 5 leading pawns (KPPPPPK). + for (int leadPawnsCnt = 1; leadPawnsCnt <= 5; ++leadPawnsCnt) for (File f = FILE_A; f <= FILE_D; ++f) { // Restart the index at every file because TB table is splitted @@ -1297,7 +1356,7 @@ void Tablebases::init(const std::string& paths) { if (leadPawnsCnt == 1) { MapPawns[sq] = availableSquares--; - MapPawns[sq ^ 7] = availableSquares--; // Horizontal flip + MapPawns[flip_file(sq)] = availableSquares--; } LeadPawnIdx[leadPawnsCnt][sq] = idx; idx += Binomial[leadPawnsCnt - 1][MapPawns[sq]]; @@ -1306,7 +1365,7 @@ void Tablebases::init(const std::string& paths) { LeadPawnsSize[leadPawnsCnt][f] = idx; } - // Add entries in TB tables if the corresponding ".rtbw" file exsists + // Add entries in TB tables if the corresponding ".rtbw" file exists for (PieceType p1 = PAWN; p1 < KING; ++p1) { TBTables.add({KING, p1, KING}); @@ -1320,11 +1379,22 @@ void Tablebases::init(const std::string& paths) { for (PieceType p3 = PAWN; p3 <= p2; ++p3) { TBTables.add({KING, p1, p2, p3, KING}); - for (PieceType p4 = PAWN; p4 <= p3; ++p4) + for (PieceType p4 = PAWN; p4 <= p3; ++p4) { TBTables.add({KING, p1, p2, p3, p4, KING}); - for (PieceType p4 = PAWN; p4 < KING; ++p4) + for (PieceType p5 = PAWN; p5 <= p4; ++p5) + TBTables.add({KING, p1, p2, p3, p4, p5, KING}); + + for (PieceType p5 = PAWN; p5 < KING; ++p5) + TBTables.add({KING, p1, p2, p3, p4, KING, p5}); + } + + for (PieceType p4 = PAWN; p4 < KING; ++p4) { TBTables.add({KING, p1, p2, p3, KING, p4}); + + for (PieceType p5 = PAWN; p5 <= p4; ++p5) + TBTables.add({KING, p1, p2, p3, KING, p4, p5}); + } } for (PieceType p3 = PAWN; p3 <= p1; ++p3) @@ -1372,7 +1442,7 @@ WDLScore Tablebases::probe_wdl(Position& pos, ProbeState* result) { // If n = 100 immediately after a capture or pawn move, then the position // is also certainly a win, and during the whole phase until the next // capture or pawn move, the inequality to be preserved is -// dtz + 50-movecounter <= 100. +// dtz + 50-move-counter <= 100. // // In short, if a move is available resulting in dtz + 50-move-counter <= 99, // then do not accept moves leading to dtz + 50-move-counter == 100. @@ -1402,7 +1472,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) { StateInfo st; int minDTZ = 0xFFFF; - for (const Move& move : MoveList(pos)) + for (const Move move : MoveList(pos)) { bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN; @@ -1491,12 +1561,12 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves) { int r = dtz > 0 ? (dtz + cnt50 <= 99 && !rep ? 1000 : 1000 - (dtz + cnt50)) : dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -1000 : -1000 + (-dtz + cnt50)) : 0; - m.TBRank = r; + m.tbRank = r; // Determine the score to be displayed for this move. Assign at least // 1 cp to cursed wins and let it grow to 49 cp as the positions gets // closer to a real win. - m.TBScore = r >= bound ? VALUE_MATE - MAX_PLY - 1 + m.tbScore = r >= bound ? VALUE_MATE - MAX_PLY - 1 : r > 0 ? Value((std::max( 3, r - 800) * int(PawnValueEg)) / 200) : r == 0 ? VALUE_DRAW : r > -bound ? Value((std::min(-3, r + 800) * int(PawnValueEg)) / 200) @@ -1532,13 +1602,15 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves) { if (result == FAIL) return false; - m.TBRank = WDL_to_rank[wdl + 2]; + m.tbRank = WDL_to_rank[wdl + 2]; if (!rule50) wdl = wdl > WDLDraw ? WDLWin : wdl < WDLDraw ? WDLLoss : WDLDraw; - m.TBScore = WDL_to_value[wdl + 2]; + m.tbScore = WDL_to_value[wdl + 2]; } return true; } + +} // namespace Stockfish