diff --git a/include/search/syzygy.h b/include/search/syzygy.h index 779973c2..7053ecde 100644 --- a/include/search/syzygy.h +++ b/include/search/syzygy.h @@ -17,12 +17,9 @@ #pragma once -extern "C" { -#include -} - #include #include +#include #include diff --git a/syzygy/LICENSE b/syzygy/LICENSE index 8eb910fe..a83f6f0b 100644 --- a/syzygy/LICENSE +++ b/syzygy/LICENSE @@ -1,7 +1,8 @@ The MIT License (MIT) +Copyright (c) 2013-2018 Ronald de Man Copyright (c) 2015 basil00 -Modifications Copyright (c) 2016-2017 by Jon Dart +Copyright (c) 2016-2023 by Jon Dart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/syzygy/README.md b/syzygy/README.md index 5b200151..132f0df5 100644 --- a/syzygy/README.md +++ b/syzygy/README.md @@ -5,9 +5,12 @@ Fathom is a stand-alone Syzygy tablebase probing tool. The aims of Fathom are: * To make it easy to integrate the Syzygy tablebases into existing chess - engines; + engines * To make it easy to create stand-alone applications that use the Syzygy - tablebases; + tablebases + +Fathom is compilable under either C99 or C++ and supports a variety of +platforms, including at least Windows, Linux, and MacOS. Tool ---- @@ -26,79 +29,112 @@ The tool will print out a PGN representation of the probe result, including: * WinningMoves: The list of all winning moves * DrawingMoves: The list of all drawing moves * LosingMoves: The list of all losing moves -* A pseudo "principle variation" of Syzygy vs. Syzygy for the input position. +* A pseudo "principal variation" of Syzygy vs. Syzygy for the input position. For more information, run the following command: fathom --help -Pre-compiled versions of `fathom` (for all platforms) are available from here: - -* https://github.com/basil00/Fathom/releases - Programming API --------------- -Fathom provides a simple API. There are three main function calls: +Fathom provides a simple API. Following are the main function calls: -* `tb_init` initializes the tablebase -* `tb_probe_wdl` probes the Win-Draw-Loss (WDL) table for a given position +* `tb_init` initializes the tablebases. +* `tb_free` releases any resources allocated by Fathom. +* `tb_probe_wdl` probes the Win-Draw-Loss (WDL) table for a given position. * `tb_probe_root` probes the Distance-To-Zero (DTZ) table for the given - position. - -All of the API functions use basic integer types, i.e. there is no need to -create and initialize data-structures. Fathom does not require the callee -to provide any additional functionality (e.g. move generation) unlike the -traditional `tbprobe` code. However, chess engines can opt to replace some -of the functionality of Fathom for better performance (see below). - -Chess Engines + position. It returns a recommended move, and also a list of unsigned + integers, each one encoding a possible move and its DTZ and WDL values. +* `tb_probe_root_dtz` probes the Distance-To-Zero (DTZ) at the root position. + It returns a score and a rank for each possible move. +* `tb_probe_root_wdl` probes the Win-Draw-Loss (WDL) at the root position. + it returns a score and a rank for each possible move. + +Fathom does not require the callee to provide any additional functionality +(e.g. move generation). A simple set of chess-related functions including move +generation is provided in file `tbchess.c`. However, chess engines can opt to +replace some of this functionality for better performance (see below). + +Chess engines ------------- -Chess engines can be `tb_probe_wdl` to get the WDL value during search. The -`tb_probe_root` functional can be used to help pick the best move at the root. -Note that `tb_probe_root` is slower and therefore should only be used at the -root. - -Chess engines can opt for a tighter integration of Fathom by configuring -`tbconfig.h`. Specifically, the chess engines can define `TB_*_ATTACKS` -macros that replace the default definitions with the engine's own definitions, -avoiding duplication of functionality. - -Credits -------- - -The Syzygy tablebases were created by Ronald de Man. Much of the probing code -`tbprobe.c` is a modified version of Ronald's `tbprobe.cpp` for Stockfish (all -Stockfish-specific code has been removed). The `tbcore.c` file is virtually -unchanged from Ronald's original version. +Chess engines can use `tb_probe_wdl` to get the WDL value during +search. This function is thread safe (unless TB_NO_THREADS is +set). The various "probe_root" functions are intended for probing only +at the root node and are not thread-safe. + +Chess engines and other clients can modify some features of Fathom and +override some of its internal functions by configuring +`tbconfig.h`. `tbconfig.h` is included in Fathom's code with angle +brackets. This allows a client of Fathom to override tbconfig.h by +placing its own modified copy in its include path before the Fathom +source directory. + +One option provided by `tbconfig.h` is to define macros that replace +some aspects of Fathom's functionality, such as calculating piece +attacks, avoiding duplication of functionality. If doing this, +however, be careful with including typedefs or defines from your own +code into `tbconfig.h`, since these may clash with internal definitions +used by Fathom. I recommend instead interfacing to external +functions via a small module, with an interface something like this: + +``` +#ifndef _TB_ATTACK_INTERFACE +#define _TB_ATTACK_INTERFACE + +#ifdef __cplusplus +#include +#else +#include +#endif + +extern tb_knight_attacks(unsigned square); +extern tb_king_attacks(unsigned square); +extern tb_root_attacks(unsigned square, uint64_t occ); +extern tb_bishop_attacks(unsigned square, uint64_t occ); +extern tb_queen_attacks(unsigned square, uint64_t occ); +extern tb_pawn_attacks(unsigned square, uint64_t occ); + +#endif +``` + +You can add if wanted other function definitions such as a popcnt +function based on the chess engine's native popcnt support. + +`tbconfig.h` can then reference these functions safety because the +interface depends only on types defined in standard headers. The +implementation, however, can use any types from the chess engine or +other client that are necessary. (A good optimizer with link-time +optimization will inline the implementation code even though it is not +visible in the interface). + +History and Credits +------------------- + +The Syzygy tablebases were created by Ronald de Man. The original version of Fathom +(https://github.com/basil00/Fathom) combined probing code from Ronald de Man, originally written for +Stockfish, with chess-related functions and other support code from Basil Falcinelli. +That codebase is no longer being maintained. This repository was originaly a fork of +that codebase, with additional modifications by Jon Dart. + +However, the current Fathom code in this repository is no longer +derived directly from the probing code written for Stockfish, but +instead derives from tbprobe.c, which is a component of the Cfish +chess engine (https://github.com/syzygy1/Cfish), a Stockfish +derivative. tbprobe.c includes 7-man tablebase support. It was written +by Ronald de Man and released for unrestricted distribution and use. + +This fork of Fathom replaces the Cfish board representation and move +generation code used in tbprobe.c with simpler, MIT-licensed code from the original +Fathom source by Basil. The code has been reorganized so that +`tbchess.c` contains all move generation and most chess-related typedefs +and functions, while `tbprobe.c` contains all the tablebase probing +code. The code replacement and reorganization was done by Jon Dart. License ------- -(C) 2013-2015 Ronald de Man (original code) -(C) 2015 basil (new modifications) - -Ronald de Man's original code can be "redistributed and/or modified without -restrictions". - -The new modifications are released under the permissive MIT License: - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +This version of Fathom is released under the MIT License. See the LICENSE file for +details. diff --git a/syzygy/stdendian.h b/syzygy/stdendian.h index cd0e3177..847db07a 100644 --- a/syzygy/stdendian.h +++ b/syzygy/stdendian.h @@ -113,9 +113,10 @@ #define __ENDIAN_DEFINED 1 #endif /* sun */ -/* Windows */ -#if defined(_WIN32) || defined(_MSC_VER) -/* assumes all Microsoft targets are little endian */ +/* Windows (also Emscripten) */ +#if defined(_WIN32) || defined(_MSC_VER) || defined(__EMSCRIPTEN__) +/* assumes all Microsoft targets are little endian. */ +/* Emscripten (emcc) also currently assumes little endian. */ #define _LITTLE_ENDIAN 1234 #define _BIG_ENDIAN 4321 #define _BYTE_ORDER _LITTLE_ENDIAN diff --git a/syzygy/tbchess.cc b/syzygy/tbchess.cc index 6f16c4f4..7688ec52 100644 --- a/syzygy/tbchess.cc +++ b/syzygy/tbchess.cc @@ -21,10 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include -#include "tbprobe.h" -#include - #define TB_PAWN 1 #define TB_KNIGHT 2 #define TB_BISHOP 3 @@ -566,16 +562,16 @@ static uint64_t calc_key(const Pos *pos, bool mirror) white = black; black = tmp; } - return tb_pop_count(white & pos->queens) * PRIME_WHITE_QUEEN + - tb_pop_count(white & pos->rooks) * PRIME_WHITE_ROOK + - tb_pop_count(white & pos->bishops) * PRIME_WHITE_BISHOP + - tb_pop_count(white & pos->knights) * PRIME_WHITE_KNIGHT + - tb_pop_count(white & pos->pawns) * PRIME_WHITE_PAWN + - tb_pop_count(black & pos->queens) * PRIME_BLACK_QUEEN + - tb_pop_count(black & pos->rooks) * PRIME_BLACK_ROOK + - tb_pop_count(black & pos->bishops) * PRIME_BLACK_BISHOP + - tb_pop_count(black & pos->knights) * PRIME_BLACK_KNIGHT + - tb_pop_count(black & pos->pawns) * PRIME_BLACK_PAWN; + return popcount(white & pos->queens) * PRIME_WHITE_QUEEN + + popcount(white & pos->rooks) * PRIME_WHITE_ROOK + + popcount(white & pos->bishops) * PRIME_WHITE_BISHOP + + popcount(white & pos->knights) * PRIME_WHITE_KNIGHT + + popcount(white & pos->pawns) * PRIME_WHITE_PAWN + + popcount(black & pos->queens) * PRIME_BLACK_QUEEN + + popcount(black & pos->rooks) * PRIME_BLACK_ROOK + + popcount(black & pos->bishops) * PRIME_BLACK_BISHOP + + popcount(black & pos->knights) * PRIME_BLACK_KNIGHT + + popcount(black & pos->pawns) * PRIME_BLACK_PAWN; } // Produce a 64-bit material key corresponding to the material combination @@ -663,62 +659,62 @@ static TbMove *gen_captures(const Pos *pos, TbMove *moves) them = (pos->turn? pos->black: pos->white); uint64_t b, att; { - unsigned from = tb_lsb(pos->kings & us); + unsigned from = lsb(pos->kings & us); assert(from < 64); - for (att = king_attacks(from) & them; att; att = tb_pop_lsb(att)) + for (att = king_attacks(from) & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->queens; b; b = tb_pop_lsb(b)) + for (b = us & pos->queens; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = queen_attacks(from, occ) & them; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = queen_attacks(from, occ) & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->rooks; b; b = tb_pop_lsb(b)) + for (b = us & pos->rooks; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = rook_attacks(from, occ) & them; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = rook_attacks(from, occ) & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->bishops; b; b = tb_pop_lsb(b)) + for (b = us & pos->bishops; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = bishop_attacks(from, occ) & them; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = bishop_attacks(from, occ) & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->knights; b; b = tb_pop_lsb(b)) + for (b = us & pos->knights; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = knight_attacks(from) & them; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = knight_attacks(from) & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->pawns; b; b = tb_pop_lsb(b)) + for (b = us & pos->pawns; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); + unsigned from = lsb(b); att = pawn_attacks(from, pos->turn); if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) { unsigned to = pos->ep; moves = add_move(moves, false, from, to); } - for (att = att & them; att; att = tb_pop_lsb(att)) + for (att = att & them; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to); } @@ -737,52 +733,52 @@ static TbMove *gen_moves(const Pos *pos, TbMove *moves) uint64_t b, att; { - unsigned from = tb_lsb(pos->kings & us); - for (att = king_attacks(from) & ~us; att; att = tb_pop_lsb(att)) + unsigned from = lsb(pos->kings & us); + for (att = king_attacks(from) & ~us; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->queens; b; b = tb_pop_lsb(b)) + for (b = us & pos->queens; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = queen_attacks(from, occ) & ~us; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = queen_attacks(from, occ) & ~us; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->rooks; b; b = tb_pop_lsb(b)) + for (b = us & pos->rooks; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = rook_attacks(from, occ) & ~us; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = rook_attacks(from, occ) & ~us; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->bishops; b; b = tb_pop_lsb(b)) + for (b = us & pos->bishops; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = bishop_attacks(from, occ) & ~us; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = bishop_attacks(from, occ) & ~us; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->knights; b; b = tb_pop_lsb(b)) + for (b = us & pos->knights; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); - for (att = knight_attacks(from) & ~us; att; att = tb_pop_lsb(att)) + unsigned from = lsb(b); + for (att = knight_attacks(from) & ~us; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, false, from, to); } } - for (b = us & pos->pawns; b; b = tb_pop_lsb(b)) + for (b = us & pos->pawns; b; b = poplsb(b)) { - unsigned from = tb_lsb(b); + unsigned from = lsb(b); unsigned next = from + (pos->turn? 8: -8); att = pawn_attacks(from, pos->turn); if (pos->ep != 0 && ((att & board(pos->ep)) != 0)) @@ -799,9 +795,9 @@ static TbMove *gen_moves(const Pos *pos, TbMove *moves) ((board(next2) & occ) == 0)) att |= board(next2); } - for (; att; att = tb_pop_lsb(att)) + for (; att; att = poplsb(att)) { - unsigned to = tb_lsb(att); + unsigned to = lsb(att); moves = add_move(moves, (rank(to) == 7 || rank(to) == 0), from, to); } @@ -850,7 +846,7 @@ static bool is_legal(const Pos *pos) uint64_t king = pos->kings & us; if (!king) return false; - unsigned sq = tb_lsb(king); + unsigned sq = lsb(king); if (king_attacks(sq) & (pos->kings & them)) return false; uint64_t ratt = rook_attacks(sq, occ); @@ -878,7 +874,7 @@ static bool is_check(const Pos *pos) them = (pos->turn? pos->black: pos->white); uint64_t king = pos->kings & us; assert(king != 0); - unsigned sq = tb_lsb(king); + unsigned sq = lsb(king); uint64_t ratt = rook_attacks(sq, occ); uint64_t batt = bishop_attacks(sq, occ); if (ratt & (pos->rooks & them)) @@ -899,11 +895,11 @@ static bool is_check(const Pos *pos) */ static bool is_valid(const Pos *pos) { - if (tb_pop_count(pos->kings) != 2) + if (popcount(pos->kings) != 2) return false; - if (tb_pop_count(pos->kings & pos->white) != 1) + if (popcount(pos->kings & pos->white) != 1) return false; - if (tb_pop_count(pos->kings & pos->black) != 1) + if (popcount(pos->kings & pos->black) != 1) return false; if ((pos->white & pos->black) != 0) return false; diff --git a/syzygy/tbprobe.cc b/syzygy/tbprobe.cc index 0ac125e7..13bca19d 100644 --- a/syzygy/tbprobe.cc +++ b/syzygy/tbprobe.cc @@ -1,6 +1,7 @@ /* +Copyright (c) 2013-2018 Ronald de Man Copyright (c) 2015 basil00 -Modifications Copyright (c) 2016-2019 by Jon Dart +Modifications Copyright (c) 2016-2023 by Jon Dart Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,10 +39,6 @@ SOFTWARE. #endif #include "tbprobe.h" -#ifdef __cplusplus -using namespace std; -#endif - #define TB_PIECES 7 #define TB_HASHBITS (TB_PIECES < 7 ? 11 : 12) #define TB_MAX_PIECE (TB_PIECES < 7 ? 254 : 650) @@ -69,6 +66,13 @@ typedef size_t map_t; typedef HANDLE map_t; #endif +// This must be after the inclusion of Windows headers, because otherwise +// std::byte conflicts with "byte" in rpcndr.h . The error occurs if C++ +// standard is at lest 17, as std::byte was introduced in C++17. +#ifdef __cplusplus +using namespace std; +#endif + #define DECOMP64 // Threading support @@ -120,13 +124,22 @@ typedef HANDLE map_t; #include #define popcount(x) (int)_mm_popcnt_u64((x)) #else +// try to use a builtin +#if defined (__has_builtin) +#if __has_builtin(__builtin_popcountll) +#define popcount(x) __builtin_popcountll((x)) +#else #define TB_SOFTWARE_POP_COUNT #endif +#else +#define TB_SOFTWARE_POP_COUNT +#endif +#endif #ifdef TB_SOFTWARE_POP_COUNT -// Not a recognized compiler/architecture that has popcount: -// fall back to a software popcount. This one is still reasonably -// fast. +// Not a recognized compiler/architecture that has popcount, and +// no builtin available: fall back to a software popcount. This one +// is still reasonably fast. static inline unsigned tb_software_popcount(uint64_t x) { x = x - ((x >> 1) & 0x5555555555555555ull); @@ -134,7 +147,6 @@ static inline unsigned tb_software_popcount(uint64_t x) x = (x + (x >> 4)) & 0x0f0f0f0f0f0f0f0full; return (x * 0x0101010101010101ull) >> 56; } - #define popcount(x) tb_software_popcount(x) #endif @@ -306,11 +318,14 @@ static FD open_tb(const char *str, const char *suffix) wchar_t ucode_name[4096]; size_t len; mbstowcs_s(&len, ucode_name, 4096, file, _TRUNCATE); + /* use FILE_FLAG_RANDOM_ACCESS because we are likely to access this file + randomly, so prefetch is not helpful. See + https://github.com/official-stockfish/Stockfish/pull/1829 */ fd = CreateFile(ucode_name, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); #else fd = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); #endif #endif free(file); @@ -342,15 +357,16 @@ static void *map_file(FD fd, map_t *mapping) *mapping = statbuf.st_size; void *data = mmap(NULL, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0); - - #if defined(MADV_RANDOM) - madvise(data, statbuf.st_size, MADV_RANDOM); - #endif - if (data == MAP_FAILED) { perror("mmap"); return NULL; } +#ifdef POSIX_MADV_RANDOM + /* Advise the kernel that we are likely to access this data + region randomly, so prefetch is not helpful. See + https://github.com/official-stockfish/Stockfish/pull/1829 */ + posix_madvise(data, statbuf.st_size, POSIX_MADV_RANDOM); +#endif #else DWORD size_low, size_high; size_low = GetFileSize(fd, &size_high); @@ -373,8 +389,8 @@ static void *map_file(FD fd, map_t *mapping) static void unmap_file(void *data, map_t size) { if (!data) return; - if (!munmap(data, size)) { - perror("munmap"); + if (munmap(data, size) != 0) { + perror("munmap"); } } #else @@ -836,9 +852,13 @@ bool tb_init(const char *path) numWdl = numDtm = numDtz = 0; } + TB_LARGEST = 0; + // if path is an empty string or equals "", we are done. const char *p = path; - if (strlen(p) == 0 || !strcmp(p, "")) return true; + if (strlen(p) == 0 || !strcmp(p, "")) { + return true; + } pathString = (char*)malloc(strlen(p) + 1); strcpy(pathString, p); @@ -862,7 +882,6 @@ bool tb_init(const char *path) tbNumPiece = tbNumPawn = 0; TB_MaxCardinality = TB_MaxCardinalityDTM = 0; - TB_LARGEST = 0; if (!pieceEntry) { pieceEntry = (struct PieceEntry*)malloc(TB_MAX_PIECE * sizeof(*pieceEntry)); @@ -882,33 +901,33 @@ bool tb_init(const char *path) int i, j, k, l, m; for (i = 0; i < 5; i++) { - sprintf(str, "K%cvK", pchr(i)); + snprintf(str, 16, "K%cvK", pchr(i)); init_tb(str); } for (i = 0; i < 5; i++) for (j = i; j < 5; j++) { - sprintf(str, "K%cvK%c", pchr(i), pchr(j)); + snprintf(str, 16, "K%cvK%c", pchr(i), pchr(j)); init_tb(str); } for (i = 0; i < 5; i++) for (j = i; j < 5; j++) { - sprintf(str, "K%c%cvK", pchr(i), pchr(j)); + snprintf(str, 16, "K%c%cvK", pchr(i), pchr(j)); init_tb(str); } for (i = 0; i < 5; i++) for (j = i; j < 5; j++) for (k = 0; k < 5; k++) { - sprintf(str, "K%c%cvK%c", pchr(i), pchr(j), pchr(k)); + snprintf(str, 16, "K%c%cvK%c", pchr(i), pchr(j), pchr(k)); init_tb(str); } for (i = 0; i < 5; i++) for (j = i; j < 5; j++) for (k = j; k < 5; k++) { - sprintf(str, "K%c%c%cvK", pchr(i), pchr(j), pchr(k)); + snprintf(str, 16, "K%c%c%cvK", pchr(i), pchr(j), pchr(k)); init_tb(str); } @@ -920,7 +939,7 @@ bool tb_init(const char *path) for (j = i; j < 5; j++) for (k = i; k < 5; k++) for (l = (i == k) ? j : k; l < 5; l++) { - sprintf(str, "K%c%cvK%c%c", pchr(i), pchr(j), pchr(k), pchr(l)); + snprintf(str, 16, "K%c%cvK%c%c", pchr(i), pchr(j), pchr(k), pchr(l)); init_tb(str); } @@ -928,7 +947,7 @@ bool tb_init(const char *path) for (j = i; j < 5; j++) for (k = j; k < 5; k++) for (l = 0; l < 5; l++) { - sprintf(str, "K%c%c%cvK%c", pchr(i), pchr(j), pchr(k), pchr(l)); + snprintf(str, 16, "K%c%c%cvK%c", pchr(i), pchr(j), pchr(k), pchr(l)); init_tb(str); } @@ -936,7 +955,7 @@ bool tb_init(const char *path) for (j = i; j < 5; j++) for (k = j; k < 5; k++) for (l = k; l < 5; l++) { - sprintf(str, "K%c%c%c%cvK", pchr(i), pchr(j), pchr(k), pchr(l)); + snprintf(str, 16, "K%c%c%c%cvK", pchr(i), pchr(j), pchr(k), pchr(l)); init_tb(str); } @@ -948,7 +967,7 @@ bool tb_init(const char *path) for (k = j; k < 5; k++) for (l = k; l < 5; l++) for (m = l; m < 5; m++) { - sprintf(str, "K%c%c%c%c%cvK", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); + snprintf(str, 16, "K%c%c%c%c%cvK", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); init_tb(str); } @@ -957,7 +976,7 @@ bool tb_init(const char *path) for (k = j; k < 5; k++) for (l = k; l < 5; l++) for (m = 0; m < 5; m++) { - sprintf(str, "K%c%c%c%cvK%c", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); + snprintf(str, 16, "K%c%c%c%cvK%c", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); init_tb(str); } @@ -966,7 +985,7 @@ bool tb_init(const char *path) for (k = j; k < 5; k++) for (l = 0; l < 5; l++) for (m = l; m < 5; m++) { - sprintf(str, "K%c%c%cvK%c%c", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); + snprintf(str, 16, "K%c%c%cvK%c%c", pchr(i), pchr(j), pchr(k), pchr(l), pchr(m)); init_tb(str); } @@ -1555,7 +1574,7 @@ static bool init_table(struct BaseEntry *be, const char *str, int type) } else { data += (uintptr_t)data & 0x01; for (int i = 0; i < 4; i++) { - mapIdx[t][i] = (uint16_t)(data + 1 - (uint8_t *)map); + mapIdx[t][i] = (uint16_t)((uint16_t*)data + 1 - (uint16_t *)map); data += 2 + 2 * read_le_u16(data); } } @@ -1955,12 +1974,12 @@ int probe_wdl(Pos *pos, int *success) // Now handle the stalemate case. if (bestEp > -3 && v == 0) { TbMove moves[TB_MAX_MOVES]; - TbMove *endMove = gen_moves(pos, moves); + TbMove *end2 = gen_moves(pos, moves); // Check for stalemate in the position with ep captures. - for (m = moves; m < endMove; m++) { + for (m = moves; m < end2; m++) { if (!is_en_passant(pos,*m) && legal_move(pos, *m)) break; } - if (m == endMove && !is_check(pos)) { + if (m == end2 && !is_check(pos)) { // stalemate score from tb (w/o e.p.), but an en-passant capture // is possible. *success = 2; @@ -2078,16 +2097,6 @@ static Value probe_dtm_win(const Pos *pos, int *success) return best; } -//Value TB_probe_dtm(const Pos *pos, int wdl, int *success) -//{ -// assert(wdl != 0); -// -// *success = 1; -// -// return wdl > 0 ? probe_dtm_win(pos, success) -// : probe_dtm_loss(pos, success); -//} - #if 0 // To be called only for non-drawn positions. Value TB_probe_dtm2(const Pos *pos, int wdl, int *success) @@ -2366,98 +2375,7 @@ int root_probe_wdl(const Pos *pos, bool useRule50, struct TbRootMoves *rm) return 1; } -// Use the DTM tables to find mate scores. -// Either DTZ or WDL must have been probed successfully earlier. -// A return value of 0 means that not all probes were successful. -//int root_probe_dtm(const Pos *pos, struct TbRootMoves *rm) -//{ -// int success; -// Value tmpScore[TB_MAX_MOVES]; -// -// // Probe each move. -// for (unsigned i = 0; i < rm->size; i++) { -// Pos pos1; -// struct TbRootMove *m = &rm->moves[i]; -// -// // Use tbScore to find out if the position is won or lost. -// int wdl = m->tbScore > TB_VALUE_PAWN ? 2 -// : m->tbScore < -TB_VALUE_PAWN ? -2 : 0; -// -// if (wdl == 0) -// tmpScore[i] = 0; -// else { -// // Probe and adjust mate score by 1 ply. -// do_move(&pos1, pos, m->pv[0]); -// Value v = -TB_probe_dtm(&pos1, -wdl, &success); -// tmpScore[i] = wdl > 0 ? v - 1 : v + 1; -// if (success == 0) -// return 0; -// } -// } -// -// // All probes were successful. Now adjust TB scores and ranks. -// for (unsigned i = 0; i < rm->size; i++) { -// struct TbRootMove *m = &rm->moves[i]; -// -// m->tbScore = tmpScore[i]; -// -// // Let rank correspond to mate score, except for critical moves -// // ranked 900, which we rank below all other mates for safety. -// // By ranking mates above 1000 or below -1000, we let the search -// // know it need not search those moves. -// m->tbRank = m->tbRank == 900 ? 1001 : m->tbScore; -// } -// -// return 1; -//} - -// Use the DTM tables to complete a PV with mate score. -//void tb_expand_mate(Pos *pos, struct TbRootMove *move, Value moveScore, unsigned cardinalityDTM) -//{ -// int success = 1, chk = 0; -// Value v = moveScore, w = 0; -// int wdl = v > 0 ? 2 : -2; -// -// if (move->pvSize == TB_MAX_PLY) -// return; -// -// Pos root = *pos; -// // First get to the end of the incomplete PV. -// for (unsigned i = 0; i < move->pvSize; i++) { -// v = v > 0 ? -v - 1 : -v + 1; -// wdl = -wdl; -// Pos pos0 = *pos; -// do_move(pos, &pos0, move->pv[i]); -// } -// -// // Now try to expand until the actual mate. -// if ((int)popcount(pos->white | pos->black) <= (int)cardinalityDTM) { -// while (v != -TB_VALUE_MATE && move->pvSize < TB_MAX_PLY) { -// v = v > 0 ? -v - 1 : -v + 1; -// wdl = -wdl; -// TbMove moves[TB_MAX_MOVES]; -// TbMove *end = gen_legal(pos, moves); -// TbMove *m = moves; -// for (; m < end; m++) { -// Pos pos1; -// do_move(&pos1, pos, *m); -// if (wdl < 0) -// chk = probe_wdl(&pos1, &success); // verify that move wins -// w = success && (wdl > 0 || chk < 0) -// ? TB_probe_dtm(&pos1, wdl, &success) -// : 0; -// if (!success || v == w) break; -// } -// if (!success || v != w) -// break; -// move->pv[move->pvSize++] = *m; -// Pos pos0 = *pos; -// do_move(pos, &pos0, *m); -// } -// } -// // Get back to the root position. -// *pos = root; -//} + static const int wdl_to_dtz[] = { diff --git a/syzygy/tbprobe.h b/syzygy/tbprobe.h index 668b54ce..406d566f 100644 --- a/syzygy/tbprobe.h +++ b/syzygy/tbprobe.h @@ -24,7 +24,8 @@ #ifndef TBPROBE_H #define TBPROBE_H -#include "tbconfig.h" +#include + #ifdef __cplusplus extern "C" { @@ -225,9 +226,6 @@ static inline unsigned tb_probe_wdl( _bishops, _knights, _pawns, _ep, _turn); } - - - /* * Probe the Distance-To-Zero (DTZ) table. *