mirror of
https://github.com/opelly27/Stockfish.git
synced 2026-05-20 13:17:44 +00:00
Merge branch 'master' into trainer
This commit is contained in:
@@ -36,10 +36,11 @@ Bryan Cross (crossbr)
|
||||
candirufish
|
||||
Chess13234
|
||||
Chris Cain (ceebo)
|
||||
Dale Weiler (graphitemaster)
|
||||
Dan Schmidt (dfannius)
|
||||
Daniel Axtens (daxtens)
|
||||
Daniel Dugovic (ddugovic)
|
||||
Dariusz Orzechowski
|
||||
Dariusz Orzechowski (dorzechowski)
|
||||
David Zar
|
||||
Daylen Yang (daylen)
|
||||
DiscanX
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ build_script:
|
||||
- cmake --build . --config %CONFIGURATION% -- /verbosity:minimal
|
||||
- ps: |
|
||||
# Download default NNUE net from fishtest
|
||||
$nnuenet = Get-Content -Path src\ucioption.cpp | Select-String -CaseSensitive -Pattern "Option" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
|
||||
$nnuenet = Get-Content -Path src\evaluate.h | Select-String -CaseSensitive -Pattern "EvalFileDefaultName" | Select-String -CaseSensitive -Pattern "nn-[a-z0-9]{12}.nnue"
|
||||
$dummy = $nnuenet -match "(?<nnuenet>nn-[a-z0-9]{12}.nnue)"
|
||||
$nnuenet = $Matches.nnuenet
|
||||
Write-Host "Default net:" $nnuenet
|
||||
|
||||
+22
-10
@@ -100,12 +100,17 @@ VPATH = syzygy:nnue:nnue/features:eval:extra:learn
|
||||
|
||||
### 2.1. General and architecture defaults
|
||||
|
||||
ifeq ($(ARCH),)
|
||||
ARCH = x86-64-modern
|
||||
help_skip_sanity = yes
|
||||
endif
|
||||
# explicitly check for the list of supported architectures (as listed with make help),
|
||||
# the user can override with `make ARCH=x86-32-vnni256 SUPPORTED_ARCH=true`
|
||||
ifeq ($(ARCH),$(filter $(ARCH),x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
|
||||
x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
|
||||
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 \
|
||||
armv7 armv7-neon armv8 apple-silicon general-64 general-32))
|
||||
ifeq ($(ARCH), $(filter $(ARCH), \
|
||||
x86-64-vnni512 x86-64-vnni256 x86-64-avx512 x86-64-bmi2 x86-64-avx2 \
|
||||
x86-64-sse41-popcnt x86-64-modern x86-64-ssse3 x86-64-sse3-popcnt \
|
||||
x86-64 x86-32-sse41-popcnt x86-32-sse2 x86-32 ppc-64 ppc-32 \
|
||||
armv7 armv7-neon armv8 apple-silicon general-64 general-32))
|
||||
SUPPORTED_ARCH=true
|
||||
else
|
||||
SUPPORTED_ARCH=false
|
||||
@@ -128,7 +133,6 @@ avx512 = no
|
||||
vnni256 = no
|
||||
vnni512 = no
|
||||
neon = no
|
||||
ARCH = x86-64-modern
|
||||
STRIP = strip
|
||||
|
||||
### BLAS libraries
|
||||
@@ -620,6 +624,11 @@ ifeq ($(debug), no)
|
||||
LDFLAGS += $(CXXFLAGS)
|
||||
else ifeq ($(comp),clang)
|
||||
CXXFLAGS += -flto=thin
|
||||
ifneq ($(findstring MINGW,$(KERNEL)),)
|
||||
CXXFLAGS += -fuse-ld=lld
|
||||
else ifneq ($(findstring MSYS,$(KERNEL)),)
|
||||
CXXFLAGS += -fuse-ld=lld
|
||||
endif
|
||||
LDFLAGS += $(CXXFLAGS)
|
||||
|
||||
# GCC and CLANG use different methods for parallelizing LTO and CLANG pretends to be
|
||||
@@ -643,10 +652,12 @@ ifeq ($(debug), no)
|
||||
# So, only enable it for a cross from Linux by default.
|
||||
else ifeq ($(comp),mingw)
|
||||
ifeq ($(KERNEL),Linux)
|
||||
ifneq ($(arch),i386)
|
||||
CXXFLAGS += -flto
|
||||
LDFLAGS += $(CXXFLAGS) -flto=jobserver
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -722,11 +733,12 @@ help:
|
||||
@echo "make -j build ARCH=x86-64-ssse3 COMP=clang"
|
||||
@echo ""
|
||||
@echo "-------------------------------"
|
||||
ifeq ($(SUPPORTED_ARCH), true)
|
||||
ifeq ($(SUPPORTED_ARCH)$(help_skip_sanity), true)
|
||||
@echo "The selected architecture $(ARCH) will enable the following configuration: "
|
||||
@$(MAKE) ARCH=$(ARCH) COMP=$(COMP) config-sanity
|
||||
else
|
||||
@echo "Specify a supported architecture with the ARCH option for more details"
|
||||
@echo ""
|
||||
endif
|
||||
|
||||
|
||||
@@ -734,7 +746,7 @@ endif
|
||||
config-sanity icc-profile-use icc-profile-make gcc-profile-use gcc-profile-make \
|
||||
clang-profile-use clang-profile-make
|
||||
|
||||
build: config-sanity
|
||||
build: config-sanity net
|
||||
$(MAKE) ARCH=$(ARCH) COMP=$(COMP) all
|
||||
|
||||
profile-build: net config-sanity objclean profileclean
|
||||
@@ -760,12 +772,13 @@ install:
|
||||
-cp $(EXE) $(BINDIR)
|
||||
-strip $(BINDIR)/$(EXE)
|
||||
|
||||
#clean all
|
||||
# clean all
|
||||
clean: objclean profileclean
|
||||
@rm -f .depend *~ core
|
||||
|
||||
# evaluation network (nnue)
|
||||
net:
|
||||
$(eval nnuenet := $(shell grep EvalFile ucioption.cpp | grep Option | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
|
||||
$(eval nnuenet := $(shell grep EvalFileDefaultName evaluate.h | grep define | sed 's/.*\(nn-[a-z0-9]\{12\}.nnue\).*/\1/'))
|
||||
@echo "Default net: $(nnuenet)"
|
||||
$(eval nnuedownloadurl := https://tests.stockfishchess.org/api/nn/$(nnuenet))
|
||||
$(eval curl_or_wget := $(shell if hash curl 2>/dev/null; then echo "curl -skL"; elif hash wget 2>/dev/null; then echo "wget -qO-"; fi))
|
||||
@@ -787,7 +800,6 @@ net:
|
||||
echo "shasum / sha256sum not found, skipping net validation"; \
|
||||
fi
|
||||
|
||||
|
||||
# clean binaries and objects
|
||||
objclean:
|
||||
@rm -f $(EXE) *.o ./syzygy/*.o ./nnue/*.o ./nnue/features/*.o ./learn/*.o ./extra/*.o ./eval/*.o
|
||||
|
||||
+94
-20
@@ -20,52 +20,126 @@
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstring> // For std::memset
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <streambuf>
|
||||
#include <vector>
|
||||
|
||||
#include "bitboard.h"
|
||||
#include "evaluate.h"
|
||||
#include "material.h"
|
||||
#include "misc.h"
|
||||
#include "pawns.h"
|
||||
#include "thread.h"
|
||||
#include "uci.h"
|
||||
#include "incbin/incbin.h"
|
||||
|
||||
|
||||
// Macro to embed the default NNUE file data in the engine binary (using incbin.h, by Dale Weiler).
|
||||
// This macro invocation will declare the following three variables
|
||||
// const unsigned char gEmbeddedNNUEData[]; // a pointer to the embedded data
|
||||
// const unsigned char *const gEmbeddedNNUEEnd; // a marker to the end
|
||||
// const unsigned int gEmbeddedNNUESize; // the size of the embedded file
|
||||
// Note that this does not work in Microsof Visual Studio.
|
||||
#if !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
|
||||
INCBIN(EmbeddedNNUE, EvalFileDefaultName);
|
||||
#else
|
||||
const unsigned char gEmbeddedNNUEData[1] = {0x0};
|
||||
const unsigned char *const gEmbeddedNNUEEnd = &gEmbeddedNNUEData[1];
|
||||
const unsigned int gEmbeddedNNUESize = 1;
|
||||
#endif
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace Eval::NNUE;
|
||||
|
||||
namespace Eval {
|
||||
|
||||
bool useNNUE;
|
||||
std::string eval_file_loaded="None";
|
||||
string eval_file_loaded = "None";
|
||||
|
||||
/// init_NNUE() tries to load a nnue network at startup time, or when the engine
|
||||
/// receives a UCI command "setoption name EvalFile value nn-[a-z0-9]{12}.nnue"
|
||||
/// The name of the nnue network is always retrieved from the EvalFile option.
|
||||
/// We search the given network in three locations: internally (the default
|
||||
/// network may be embedded in the binary), in the active working directory and
|
||||
/// in the engine directory. Distro packagers may define the DEFAULT_NNUE_DIRECTORY
|
||||
/// variable to have the engine search in a special directory in their distro.
|
||||
|
||||
void init_NNUE() {
|
||||
|
||||
useNNUE = Options["Use NNUE"];
|
||||
std::string eval_file = std::string(Options["EvalFile"]);
|
||||
if (useNNUE && eval_file_loaded != eval_file)
|
||||
if (Eval::NNUE::load_eval_file(eval_file))
|
||||
eval_file_loaded = eval_file;
|
||||
if (!useNNUE)
|
||||
return;
|
||||
|
||||
string eval_file = string(Options["EvalFile"]);
|
||||
|
||||
#if defined(DEFAULT_NNUE_DIRECTORY)
|
||||
#define stringify2(x) #x
|
||||
#define stringify(x) stringify2(x)
|
||||
vector<string> dirs = { "<internal>" , "" , CommandLine::binaryDirectory , stringify(DEFAULT_NNUE_DIRECTORY) };
|
||||
#else
|
||||
vector<string> dirs = { "<internal>" , "" , CommandLine::binaryDirectory };
|
||||
#endif
|
||||
|
||||
for (string directory : dirs)
|
||||
if (eval_file_loaded != eval_file)
|
||||
{
|
||||
if (directory != "<internal>")
|
||||
{
|
||||
ifstream stream(directory + eval_file, ios::binary);
|
||||
if (load_eval(eval_file, stream))
|
||||
eval_file_loaded = eval_file;
|
||||
}
|
||||
|
||||
if (directory == "<internal>" && eval_file == EvalFileDefaultName)
|
||||
{
|
||||
// C++ way to prepare a buffer for a memory stream
|
||||
class MemoryBuffer : public basic_streambuf<char> {
|
||||
public: MemoryBuffer(char* p, size_t n) { setg(p, p, p + n); setp(p, p + n); }
|
||||
};
|
||||
|
||||
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
|
||||
size_t(gEmbeddedNNUESize));
|
||||
|
||||
istream stream(&buffer);
|
||||
if (load_eval(eval_file, stream))
|
||||
eval_file_loaded = eval_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// verify_NNUE() verifies that the last net used was loaded successfully
|
||||
void verify_NNUE() {
|
||||
|
||||
std::string eval_file = std::string(Options["EvalFile"]);
|
||||
string eval_file = string(Options["EvalFile"]);
|
||||
|
||||
if (useNNUE && eval_file_loaded != eval_file)
|
||||
{
|
||||
UCI::OptionsMap defaults;
|
||||
UCI::init(defaults);
|
||||
|
||||
sync_cout << "info string ERROR: NNUE evaluation used, but the network file " << eval_file << " was not loaded successfully." << sync_endl;
|
||||
sync_cout << "info string ERROR: The UCI option EvalFile might need to specify the full path, including the directory/folder name, to the file." << sync_endl;
|
||||
sync_cout << "info string ERROR: The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/"+std::string(defaults["EvalFile"]) << sync_endl;
|
||||
sync_cout << "info string ERROR: If the UCI option Use NNUE is set to true, network evaluation parameters compatible with the program must be available." << sync_endl;
|
||||
sync_cout << "info string ERROR: The engine will be terminated now." << sync_endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
string msg1 = "If the UCI option \"Use NNUE\" is set to true, network evaluation parameters compatible with the engine must be available.";
|
||||
string msg2 = "The option is set to true, but the network file " + eval_file + " was not loaded successfully.";
|
||||
string msg3 = "The UCI option EvalFile might need to specify the full path, including the directory name, to the network file.";
|
||||
string msg4 = "The default net can be downloaded from: https://tests.stockfishchess.org/api/nn/" + string(defaults["EvalFile"]);
|
||||
string msg5 = "The engine will be terminated now.";
|
||||
|
||||
sync_cout << "info string ERROR: " << msg1 << sync_endl;
|
||||
sync_cout << "info string ERROR: " << msg2 << sync_endl;
|
||||
sync_cout << "info string ERROR: " << msg3 << sync_endl;
|
||||
sync_cout << "info string ERROR: " << msg4 << sync_endl;
|
||||
sync_cout << "info string ERROR: " << msg5 << sync_endl;
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (useNNUE)
|
||||
sync_cout << "info string NNUE evaluation using " << eval_file << " enabled." << sync_endl;
|
||||
sync_cout << "info string NNUE evaluation using " << eval_file << " enabled" << sync_endl;
|
||||
else
|
||||
sync_cout << "info string classical evaluation enabled." << sync_endl;
|
||||
sync_cout << "info string classical evaluation enabled" << sync_endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,26 +227,26 @@ namespace {
|
||||
|
||||
// Outpost[knight/bishop] contains bonuses for each knight or bishop occupying a
|
||||
// pawn protected square on rank 4 to 6 which is also safe from a pawn attack.
|
||||
constexpr Score Outpost[] = { S(56, 36), S(30, 23) };
|
||||
constexpr Score Outpost[] = { S(56, 34), S(31, 23) };
|
||||
|
||||
// PassedRank[Rank] contains a bonus according to the rank of a passed pawn
|
||||
constexpr Score PassedRank[RANK_NB] = {
|
||||
S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260)
|
||||
S(0, 0), S(9, 28), S(15, 31), S(17, 39), S(64, 70), S(171, 177), S(277, 260)
|
||||
};
|
||||
|
||||
// RookOnFile[semiopen/open] contains bonuses for each rook when there is
|
||||
// no (friendly) pawn on the rook file.
|
||||
constexpr Score RookOnFile[] = { S(19, 7), S(48, 29) };
|
||||
constexpr Score RookOnFile[] = { S(19, 7), S(48, 27) };
|
||||
|
||||
// ThreatByMinor/ByRook[attacked PieceType] contains bonuses according to
|
||||
// which piece type attacks which one. Attacks on lesser pieces which are
|
||||
// pawn-defended are not considered.
|
||||
constexpr Score ThreatByMinor[PIECE_TYPE_NB] = {
|
||||
S(0, 0), S(5, 32), S(57, 41), S(77, 56), S(88, 119), S(79, 161)
|
||||
S(0, 0), S(5, 32), S(55, 41), S(77, 56), S(89, 119), S(79, 162)
|
||||
};
|
||||
|
||||
constexpr Score ThreatByRook[PIECE_TYPE_NB] = {
|
||||
S(0, 0), S(3, 46), S(37, 68), S(42, 60), S(0, 38), S(58, 41)
|
||||
S(0, 0), S(3, 44), S(37, 68), S(42, 60), S(0, 39), S(58, 43)
|
||||
};
|
||||
|
||||
// Assorted bonuses and penalties
|
||||
|
||||
+6
-1
@@ -35,12 +35,17 @@ namespace Eval {
|
||||
void init_NNUE();
|
||||
void verify_NNUE();
|
||||
|
||||
// The default net name MUST follow the format nn-[SHA256 first 12 digits].nnue
|
||||
// for the build process (profile-build and fishtest) to work. Do not change the
|
||||
// name of the macro, as it is used in the Makefile.
|
||||
#define EvalFileDefaultName "nn-82215d0fd0df.nnue"
|
||||
|
||||
namespace NNUE {
|
||||
|
||||
Value evaluate(const Position& pos);
|
||||
Value compute_eval(const Position& pos);
|
||||
void update_eval(const Position& pos);
|
||||
bool load_eval_file(const std::string& evalFile);
|
||||
bool load_eval(std::string streamName, std::istream& stream);
|
||||
|
||||
} // namespace NNUE
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
The file "incbin.h" is free and unencumbered software released into
|
||||
the public domain by Dale Weiler, see:
|
||||
<https://github.com/graphitemaster/incbin>
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
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 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.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
Executable
+368
@@ -0,0 +1,368 @@
|
||||
/**
|
||||
* @file incbin.h
|
||||
* @author Dale Weiler
|
||||
* @brief Utility for including binary files
|
||||
*
|
||||
* Facilities for including binary files into the current translation unit and
|
||||
* making use from them externally in other translation units.
|
||||
*/
|
||||
#ifndef INCBIN_HDR
|
||||
#define INCBIN_HDR
|
||||
#include <limits.h>
|
||||
#if defined(__AVX512BW__) || \
|
||||
defined(__AVX512CD__) || \
|
||||
defined(__AVX512DQ__) || \
|
||||
defined(__AVX512ER__) || \
|
||||
defined(__AVX512PF__) || \
|
||||
defined(__AVX512VL__) || \
|
||||
defined(__AVX512F__)
|
||||
# define INCBIN_ALIGNMENT_INDEX 6
|
||||
#elif defined(__AVX__) || \
|
||||
defined(__AVX2__)
|
||||
# define INCBIN_ALIGNMENT_INDEX 5
|
||||
#elif defined(__SSE__) || \
|
||||
defined(__SSE2__) || \
|
||||
defined(__SSE3__) || \
|
||||
defined(__SSSE3__) || \
|
||||
defined(__SSE4_1__) || \
|
||||
defined(__SSE4_2__) || \
|
||||
defined(__neon__)
|
||||
# define INCBIN_ALIGNMENT_INDEX 4
|
||||
#elif ULONG_MAX != 0xffffffffu
|
||||
# define INCBIN_ALIGNMENT_INDEX 3
|
||||
# else
|
||||
# define INCBIN_ALIGNMENT_INDEX 2
|
||||
#endif
|
||||
|
||||
/* Lookup table of (1 << n) where `n' is `INCBIN_ALIGNMENT_INDEX' */
|
||||
#define INCBIN_ALIGN_SHIFT_0 1
|
||||
#define INCBIN_ALIGN_SHIFT_1 2
|
||||
#define INCBIN_ALIGN_SHIFT_2 4
|
||||
#define INCBIN_ALIGN_SHIFT_3 8
|
||||
#define INCBIN_ALIGN_SHIFT_4 16
|
||||
#define INCBIN_ALIGN_SHIFT_5 32
|
||||
#define INCBIN_ALIGN_SHIFT_6 64
|
||||
|
||||
/* Actual alignment value */
|
||||
#define INCBIN_ALIGNMENT \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_CONCATENATE(INCBIN_ALIGN_SHIFT, _), \
|
||||
INCBIN_ALIGNMENT_INDEX)
|
||||
|
||||
/* Stringize */
|
||||
#define INCBIN_STR(X) \
|
||||
#X
|
||||
#define INCBIN_STRINGIZE(X) \
|
||||
INCBIN_STR(X)
|
||||
/* Concatenate */
|
||||
#define INCBIN_CAT(X, Y) \
|
||||
X ## Y
|
||||
#define INCBIN_CONCATENATE(X, Y) \
|
||||
INCBIN_CAT(X, Y)
|
||||
/* Deferred macro expansion */
|
||||
#define INCBIN_EVAL(X) \
|
||||
X
|
||||
#define INCBIN_INVOKE(N, ...) \
|
||||
INCBIN_EVAL(N(__VA_ARGS__))
|
||||
|
||||
/* Green Hills uses a different directive for including binary data */
|
||||
#if defined(__ghs__)
|
||||
# if (__ghs_asm == 2)
|
||||
# define INCBIN_MACRO ".file"
|
||||
/* Or consider the ".myrawdata" entry in the ld file */
|
||||
# else
|
||||
# define INCBIN_MACRO "\tINCBIN"
|
||||
# endif
|
||||
#else
|
||||
# define INCBIN_MACRO ".incbin"
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
# define INCBIN_ALIGN \
|
||||
__attribute__((aligned(INCBIN_ALIGNMENT)))
|
||||
#else
|
||||
# define INCBIN_ALIGN __declspec(align(INCBIN_ALIGNMENT))
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || /* GNU C and RealView */ \
|
||||
defined(__arm) || /* Diab */ \
|
||||
defined(_ARM) /* ImageCraft */
|
||||
# define INCBIN_ARM
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
/* Utilize .balign where supported */
|
||||
# define INCBIN_ALIGN_HOST ".balign " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
|
||||
# define INCBIN_ALIGN_BYTE ".balign 1\n"
|
||||
#elif defined(INCBIN_ARM)
|
||||
/*
|
||||
* On arm assemblers, the alignment value is calculated as (1 << n) where `n' is
|
||||
* the shift count. This is the value passed to `.align'
|
||||
*/
|
||||
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT_INDEX) "\n"
|
||||
# define INCBIN_ALIGN_BYTE ".align 0\n"
|
||||
#else
|
||||
/* We assume other inline assembler's treat `.align' as `.balign' */
|
||||
# define INCBIN_ALIGN_HOST ".align " INCBIN_STRINGIZE(INCBIN_ALIGNMENT) "\n"
|
||||
# define INCBIN_ALIGN_BYTE ".align 1\n"
|
||||
#endif
|
||||
|
||||
/* INCBIN_CONST is used by incbin.c generated files */
|
||||
#if defined(__cplusplus)
|
||||
# define INCBIN_EXTERNAL extern "C"
|
||||
# define INCBIN_CONST extern const
|
||||
#else
|
||||
# define INCBIN_EXTERNAL extern
|
||||
# define INCBIN_CONST const
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Optionally override the linker section into which data is emitted.
|
||||
*
|
||||
* @warning If you use this facility, you'll have to deal with platform-specific linker output
|
||||
* section naming on your own
|
||||
*
|
||||
* Overriding the default linker output section, e.g for esp8266/Arduino:
|
||||
* @code
|
||||
* #define INCBIN_OUTPUT_SECTION ".irom.text"
|
||||
* #include "incbin.h"
|
||||
* INCBIN(Foo, "foo.txt");
|
||||
* // Data is emitted into program memory that never gets copied to RAM
|
||||
* @endcode
|
||||
*/
|
||||
#if !defined(INCBIN_OUTPUT_SECTION)
|
||||
# if defined(__APPLE__)
|
||||
# define INCBIN_OUTPUT_SECTION ".const_data"
|
||||
# else
|
||||
# define INCBIN_OUTPUT_SECTION ".rodata"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
/* The directives are different for Apple branded compilers */
|
||||
# define INCBIN_SECTION INCBIN_OUTPUT_SECTION "\n"
|
||||
# define INCBIN_GLOBAL(NAME) ".globl " INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
|
||||
# define INCBIN_INT ".long "
|
||||
# define INCBIN_MANGLE "_"
|
||||
# define INCBIN_BYTE ".byte "
|
||||
# define INCBIN_TYPE(...)
|
||||
#else
|
||||
# define INCBIN_SECTION ".section " INCBIN_OUTPUT_SECTION "\n"
|
||||
# define INCBIN_GLOBAL(NAME) ".global " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME "\n"
|
||||
# if defined(__ghs__)
|
||||
# define INCBIN_INT ".word "
|
||||
# else
|
||||
# define INCBIN_INT ".int "
|
||||
# endif
|
||||
# if defined(__USER_LABEL_PREFIX__)
|
||||
# define INCBIN_MANGLE INCBIN_STRINGIZE(__USER_LABEL_PREFIX__)
|
||||
# else
|
||||
# define INCBIN_MANGLE ""
|
||||
# endif
|
||||
# if defined(INCBIN_ARM)
|
||||
/* On arm assemblers, `@' is used as a line comment token */
|
||||
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", %object\n"
|
||||
# elif defined(__MINGW32__) || defined(__MINGW64__)
|
||||
/* Mingw doesn't support this directive either */
|
||||
# define INCBIN_TYPE(NAME)
|
||||
# else
|
||||
/* It's safe to use `@' on other architectures */
|
||||
# define INCBIN_TYPE(NAME) ".type " INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME ", @object\n"
|
||||
# endif
|
||||
# define INCBIN_BYTE ".byte "
|
||||
#endif
|
||||
|
||||
/* List of style types used for symbol names */
|
||||
#define INCBIN_STYLE_CAMEL 0
|
||||
#define INCBIN_STYLE_SNAKE 1
|
||||
|
||||
/**
|
||||
* @brief Specify the prefix to use for symbol names.
|
||||
*
|
||||
* By default this is `g', producing symbols of the form:
|
||||
* @code
|
||||
* #include "incbin.h"
|
||||
* INCBIN(Foo, "foo.txt");
|
||||
*
|
||||
* // Now you have the following symbols:
|
||||
* // const unsigned char gFooData[];
|
||||
* // const unsigned char *const gFooEnd;
|
||||
* // const unsigned int gFooSize;
|
||||
* @endcode
|
||||
*
|
||||
* If however you specify a prefix before including: e.g:
|
||||
* @code
|
||||
* #define INCBIN_PREFIX incbin
|
||||
* #include "incbin.h"
|
||||
* INCBIN(Foo, "foo.txt");
|
||||
*
|
||||
* // Now you have the following symbols instead:
|
||||
* // const unsigned char incbinFooData[];
|
||||
* // const unsigned char *const incbinFooEnd;
|
||||
* // const unsigned int incbinFooSize;
|
||||
* @endcode
|
||||
*/
|
||||
#if !defined(INCBIN_PREFIX)
|
||||
# define INCBIN_PREFIX g
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Specify the style used for symbol names.
|
||||
*
|
||||
* Possible options are
|
||||
* - INCBIN_STYLE_CAMEL "CamelCase"
|
||||
* - INCBIN_STYLE_SNAKE "snake_case"
|
||||
*
|
||||
* Default option is *INCBIN_STYLE_CAMEL* producing symbols of the form:
|
||||
* @code
|
||||
* #include "incbin.h"
|
||||
* INCBIN(Foo, "foo.txt");
|
||||
*
|
||||
* // Now you have the following symbols:
|
||||
* // const unsigned char <prefix>FooData[];
|
||||
* // const unsigned char *const <prefix>FooEnd;
|
||||
* // const unsigned int <prefix>FooSize;
|
||||
* @endcode
|
||||
*
|
||||
* If however you specify a style before including: e.g:
|
||||
* @code
|
||||
* #define INCBIN_STYLE INCBIN_STYLE_SNAKE
|
||||
* #include "incbin.h"
|
||||
* INCBIN(foo, "foo.txt");
|
||||
*
|
||||
* // Now you have the following symbols:
|
||||
* // const unsigned char <prefix>foo_data[];
|
||||
* // const unsigned char *const <prefix>foo_end;
|
||||
* // const unsigned int <prefix>foo_size;
|
||||
* @endcode
|
||||
*/
|
||||
#if !defined(INCBIN_STYLE)
|
||||
# define INCBIN_STYLE INCBIN_STYLE_CAMEL
|
||||
#endif
|
||||
|
||||
/* Style lookup tables */
|
||||
#define INCBIN_STYLE_0_DATA Data
|
||||
#define INCBIN_STYLE_0_END End
|
||||
#define INCBIN_STYLE_0_SIZE Size
|
||||
#define INCBIN_STYLE_1_DATA _data
|
||||
#define INCBIN_STYLE_1_END _end
|
||||
#define INCBIN_STYLE_1_SIZE _size
|
||||
|
||||
/* Style lookup: returning identifier */
|
||||
#define INCBIN_STYLE_IDENT(TYPE) \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_STYLE_, \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_EVAL(INCBIN_STYLE), \
|
||||
INCBIN_CONCATENATE(_, TYPE)))
|
||||
|
||||
/* Style lookup: returning string literal */
|
||||
#define INCBIN_STYLE_STRING(TYPE) \
|
||||
INCBIN_STRINGIZE( \
|
||||
INCBIN_STYLE_IDENT(TYPE)) \
|
||||
|
||||
/* Generate the global labels by indirectly invoking the macro with our style
|
||||
* type and concatenating the name against them. */
|
||||
#define INCBIN_GLOBAL_LABELS(NAME, TYPE) \
|
||||
INCBIN_INVOKE( \
|
||||
INCBIN_GLOBAL, \
|
||||
INCBIN_CONCATENATE( \
|
||||
NAME, \
|
||||
INCBIN_INVOKE( \
|
||||
INCBIN_STYLE_IDENT, \
|
||||
TYPE))) \
|
||||
INCBIN_INVOKE( \
|
||||
INCBIN_TYPE, \
|
||||
INCBIN_CONCATENATE( \
|
||||
NAME, \
|
||||
INCBIN_INVOKE( \
|
||||
INCBIN_STYLE_IDENT, \
|
||||
TYPE)))
|
||||
|
||||
/**
|
||||
* @brief Externally reference binary data included in another translation unit.
|
||||
*
|
||||
* Produces three external symbols that reference the binary data included in
|
||||
* another translation unit.
|
||||
*
|
||||
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
|
||||
* "Data", as well as "End" and "Size" after. An example is provided below.
|
||||
*
|
||||
* @param NAME The name given for the binary data
|
||||
*
|
||||
* @code
|
||||
* INCBIN_EXTERN(Foo);
|
||||
*
|
||||
* // Now you have the following symbols:
|
||||
* // extern const unsigned char <prefix>FooData[];
|
||||
* // extern const unsigned char *const <prefix>FooEnd;
|
||||
* // extern const unsigned int <prefix>FooSize;
|
||||
* @endcode
|
||||
*/
|
||||
#define INCBIN_EXTERN(NAME) \
|
||||
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
||||
INCBIN_STYLE_IDENT(DATA))[]; \
|
||||
INCBIN_EXTERNAL const INCBIN_ALIGN unsigned char *const \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
||||
INCBIN_STYLE_IDENT(END)); \
|
||||
INCBIN_EXTERNAL const unsigned int \
|
||||
INCBIN_CONCATENATE( \
|
||||
INCBIN_CONCATENATE(INCBIN_PREFIX, NAME), \
|
||||
INCBIN_STYLE_IDENT(SIZE))
|
||||
|
||||
/**
|
||||
* @brief Include a binary file into the current translation unit.
|
||||
*
|
||||
* Includes a binary file into the current translation unit, producing three symbols
|
||||
* for objects that encode the data and size respectively.
|
||||
*
|
||||
* The symbol names are a concatenation of `INCBIN_PREFIX' before *NAME*; with
|
||||
* "Data", as well as "End" and "Size" after. An example is provided below.
|
||||
*
|
||||
* @param NAME The name to associate with this binary data (as an identifier.)
|
||||
* @param FILENAME The file to include (as a string literal.)
|
||||
*
|
||||
* @code
|
||||
* INCBIN(Icon, "icon.png");
|
||||
*
|
||||
* // Now you have the following symbols:
|
||||
* // const unsigned char <prefix>IconData[];
|
||||
* // const unsigned char *const <prefix>IconEnd;
|
||||
* // const unsigned int <prefix>IconSize;
|
||||
* @endcode
|
||||
*
|
||||
* @warning This must be used in global scope
|
||||
* @warning The identifiers may be different if INCBIN_STYLE is not default
|
||||
*
|
||||
* To externally reference the data included by this in another translation unit
|
||||
* please @see INCBIN_EXTERN.
|
||||
*/
|
||||
#ifdef _MSC_VER
|
||||
#define INCBIN(NAME, FILENAME) \
|
||||
INCBIN_EXTERN(NAME)
|
||||
#else
|
||||
#define INCBIN(NAME, FILENAME) \
|
||||
__asm__(INCBIN_SECTION \
|
||||
INCBIN_GLOBAL_LABELS(NAME, DATA) \
|
||||
INCBIN_ALIGN_HOST \
|
||||
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) ":\n" \
|
||||
INCBIN_MACRO " \"" FILENAME "\"\n" \
|
||||
INCBIN_GLOBAL_LABELS(NAME, END) \
|
||||
INCBIN_ALIGN_BYTE \
|
||||
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) ":\n" \
|
||||
INCBIN_BYTE "1\n" \
|
||||
INCBIN_GLOBAL_LABELS(NAME, SIZE) \
|
||||
INCBIN_ALIGN_HOST \
|
||||
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(SIZE) ":\n" \
|
||||
INCBIN_INT INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(END) " - " \
|
||||
INCBIN_MANGLE INCBIN_STRINGIZE(INCBIN_PREFIX) #NAME INCBIN_STYLE_STRING(DATA) "\n" \
|
||||
INCBIN_ALIGN_HOST \
|
||||
".text\n" \
|
||||
); \
|
||||
INCBIN_EXTERN(NAME)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -35,6 +35,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
std::cout << engine_info() << std::endl;
|
||||
|
||||
CommandLine::init(argc, argv);
|
||||
UCI::init(Options);
|
||||
Tune::init();
|
||||
PSQT::init();
|
||||
|
||||
@@ -132,6 +132,7 @@ public:
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
/// engine_info() returns the full name of the current Stockfish version. This
|
||||
/// will be either "Stockfish <Tag> DD-MM-YY" (where DD-MM-YY is the date when
|
||||
/// the program was compiled) or "Stockfish <Version>", depending on whether
|
||||
@@ -590,6 +591,63 @@ void bindThisThread(size_t idx) {
|
||||
|
||||
} // namespace WinProcGroup
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#define GETCWD _getcwd
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define GETCWD getcwd
|
||||
#endif
|
||||
|
||||
namespace CommandLine {
|
||||
|
||||
string argv0; // path+name of the executable binary, as given by argv[0]
|
||||
string binaryDirectory; // path of the executable directory
|
||||
string workingDirectory; // path of the working directory
|
||||
string pathSeparator; // Separator for our current OS
|
||||
|
||||
void init(int argc, char* argv[]) {
|
||||
(void)argc;
|
||||
string separator;
|
||||
|
||||
// extract the path+name of the executable binary
|
||||
argv0 = argv[0];
|
||||
|
||||
#ifdef _WIN32
|
||||
pathSeparator = "\\";
|
||||
#ifdef _MSC_VER
|
||||
// Under windows argv[0] may not have the extension. Also _get_pgmptr() had
|
||||
// issues in some windows 10 versions, so check returned values carefully.
|
||||
char* pgmptr = nullptr;
|
||||
if (!_get_pgmptr(&pgmptr) && pgmptr != nullptr && *pgmptr)
|
||||
argv0 = pgmptr;
|
||||
#endif
|
||||
#else
|
||||
pathSeparator = "/";
|
||||
#endif
|
||||
|
||||
// extract the working directory
|
||||
workingDirectory = "";
|
||||
char buff[40000];
|
||||
char* cwd = GETCWD(buff, 40000);
|
||||
if (cwd)
|
||||
workingDirectory = cwd;
|
||||
|
||||
// extract the binary directory path from argv0
|
||||
binaryDirectory = argv0;
|
||||
size_t pos = binaryDirectory.find_last_of("\\/");
|
||||
if (pos == std::string::npos)
|
||||
binaryDirectory = "." + pathSeparator;
|
||||
else
|
||||
binaryDirectory.resize(pos + 1);
|
||||
|
||||
// pattern replacement: "./" at the start of path is replaced by the working directory
|
||||
if (binaryDirectory.find("." + pathSeparator) == 0)
|
||||
binaryDirectory.replace(0, 1, workingDirectory);
|
||||
}
|
||||
|
||||
|
||||
} // namespace CommandLine
|
||||
// Returns a string that represents the current time. (Used when learning evaluation functions)
|
||||
std::string now_string()
|
||||
{
|
||||
|
||||
+7
-2
@@ -44,9 +44,7 @@ void dbg_mean_of(int v);
|
||||
void dbg_print();
|
||||
|
||||
typedef std::chrono::milliseconds::rep TimePoint; // A value in milliseconds
|
||||
|
||||
static_assert(sizeof(TimePoint) == sizeof(int64_t), "TimePoint should be 64 bits");
|
||||
|
||||
inline TimePoint now() {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>
|
||||
(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
@@ -275,4 +273,11 @@ namespace Dependency
|
||||
extern bool getline(std::ifstream& fs, std::string& s);
|
||||
}
|
||||
|
||||
namespace CommandLine {
|
||||
void init(int argc, char* argv[]);
|
||||
|
||||
extern std::string binaryDirectory; // path of the executable directory
|
||||
extern std::string workingDirectory; // path of the working directory
|
||||
}
|
||||
|
||||
#endif // #ifndef MISC_H_INCLUDED
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
// Code for calculating NNUE evaluation function
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
@@ -179,26 +178,17 @@ namespace Eval::NNUE {
|
||||
return accumulator.score;
|
||||
}
|
||||
|
||||
// Load the evaluation function file
|
||||
bool load_eval_file(const std::string& evalFile) {
|
||||
// Load eval, from a file stream or a memory stream
|
||||
bool load_eval(std::string streamName, std::istream& stream) {
|
||||
|
||||
Initialize();
|
||||
|
||||
#if defined(EVAL_NNUE)
|
||||
if (Options["SkipLoadingEval"])
|
||||
{
|
||||
std::cout << "info string SkipLoadingEval set to true, Net not loaded!" << std::endl;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
fileName = evalFile;
|
||||
|
||||
std::ifstream stream(evalFile, std::ios::binary);
|
||||
|
||||
const bool result = ReadParameters(stream);
|
||||
|
||||
return result;
|
||||
fileName = streamName;
|
||||
return ReadParameters(stream);
|
||||
}
|
||||
|
||||
// Evaluation function. Perform differential calculation.
|
||||
|
||||
+46
-24
@@ -597,7 +597,7 @@ namespace {
|
||||
Move ttMove, move, excludedMove, bestMove;
|
||||
Depth extension, newDepth;
|
||||
Value bestValue, value, ttValue, eval, maxValue, probCutBeta;
|
||||
bool ttHit, ttPv, formerPv, givesCheck, improving, didLMR, priorCapture;
|
||||
bool ttHit, formerPv, givesCheck, improving, didLMR, priorCapture;
|
||||
bool captureOrPromotion, doFullDepthSearch, moveCountPruning,
|
||||
ttCapture, singularQuietLMR;
|
||||
Piece movedPiece;
|
||||
@@ -644,6 +644,7 @@ namespace {
|
||||
assert(0 <= ss->ply && ss->ply < MAX_PLY);
|
||||
|
||||
(ss+1)->ply = ss->ply + 1;
|
||||
(ss+1)->ttPv = false;
|
||||
(ss+1)->excludedMove = bestMove = MOVE_NONE;
|
||||
(ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE;
|
||||
Square prevSq = to_sq((ss-1)->currentMove);
|
||||
@@ -667,10 +668,11 @@ namespace {
|
||||
ttValue = ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
|
||||
ttMove = rootNode ? thisThread->rootMoves[thisThread->pvIdx].pv[0]
|
||||
: ttHit ? tte->move() : MOVE_NONE;
|
||||
ttPv = PvNode || (ttHit && tte->is_pv());
|
||||
formerPv = ttPv && !PvNode;
|
||||
if (!excludedMove)
|
||||
ss->ttPv = PvNode || (ttHit && tte->is_pv());
|
||||
formerPv = ss->ttPv && !PvNode;
|
||||
|
||||
if ( ttPv
|
||||
if ( ss->ttPv
|
||||
&& depth > 12
|
||||
&& ss->ply - 1 < MAX_LPH
|
||||
&& !priorCapture
|
||||
@@ -748,7 +750,7 @@ namespace {
|
||||
if ( b == BOUND_EXACT
|
||||
|| (b == BOUND_LOWER ? value >= beta : value <= alpha))
|
||||
{
|
||||
tte->save(posKey, value_to_tt(value, ss->ply), ttPv, b,
|
||||
tte->save(posKey, value_to_tt(value, ss->ply), ss->ttPv, b,
|
||||
std::min(MAX_PLY - 1, depth + 6),
|
||||
MOVE_NONE, VALUE_NONE);
|
||||
|
||||
@@ -798,7 +800,7 @@ namespace {
|
||||
else
|
||||
ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
|
||||
|
||||
tte->save(posKey, VALUE_NONE, ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
|
||||
tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
|
||||
}
|
||||
|
||||
// Step 7. Razoring (~1 Elo)
|
||||
@@ -824,7 +826,7 @@ namespace {
|
||||
&& (ss-1)->statScore < 22977
|
||||
&& eval >= beta
|
||||
&& eval >= ss->staticEval
|
||||
&& ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ttPv + 182
|
||||
&& ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 182
|
||||
&& !excludedMove
|
||||
&& pos.non_pawn_material(us)
|
||||
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
|
||||
@@ -898,6 +900,8 @@ namespace {
|
||||
assert(probCutBeta < VALUE_INFINITE);
|
||||
MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory);
|
||||
int probCutCount = 0;
|
||||
bool ttPv = ss->ttPv;
|
||||
ss->ttPv = false;
|
||||
|
||||
while ( (move = mp.next_move()) != MOVE_NONE
|
||||
&& probCutCount < 2 + 2 * cutNode)
|
||||
@@ -938,8 +942,15 @@ namespace {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
ss->ttPv = ttPv;
|
||||
}
|
||||
|
||||
// Step 11. If the position is not in TT, decrease depth by 2
|
||||
if ( PvNode
|
||||
&& depth >= 6
|
||||
&& !ttMove)
|
||||
depth -= 2;
|
||||
|
||||
moves_loop: // When in check, search starts from here
|
||||
|
||||
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
|
||||
@@ -963,7 +974,7 @@ moves_loop: // When in check, search starts from here
|
||||
// Mark this node as being searched
|
||||
ThreadHolding th(thisThread, posKey, ss->ply);
|
||||
|
||||
// Step 11. Loop through all pseudo-legal moves until no moves remain
|
||||
// Step 12. Loop through all pseudo-legal moves until no moves remain
|
||||
// or a beta cutoff occurs.
|
||||
while ((move = mp.next_move(moveCountPruning)) != MOVE_NONE)
|
||||
{
|
||||
@@ -1005,7 +1016,7 @@ moves_loop: // When in check, search starts from here
|
||||
// Calculate new depth for this move
|
||||
newDepth = depth - 1;
|
||||
|
||||
// Step 12. Pruning at shallow depth (~200 Elo)
|
||||
// Step 13. Pruning at shallow depth (~200 Elo)
|
||||
if ( !rootNode
|
||||
&& !(Options["Training"] && PvNode)
|
||||
&& pos.non_pawn_material(us)
|
||||
@@ -1064,7 +1075,7 @@ moves_loop: // When in check, search starts from here
|
||||
}
|
||||
}
|
||||
|
||||
// Step 13. Extensions (~75 Elo)
|
||||
// Step 14. Extensions (~75 Elo)
|
||||
|
||||
// Singular extension search (~70 Elo). If all moves but one fail low on a
|
||||
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
|
||||
@@ -1147,14 +1158,13 @@ moves_loop: // When in check, search starts from here
|
||||
[movedPiece]
|
||||
[to_sq(move)];
|
||||
|
||||
// Step 14. Make the move
|
||||
// Step 15. Make the move
|
||||
pos.do_move(move, st, givesCheck);
|
||||
|
||||
// Step 15. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
|
||||
// Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
|
||||
// re-searched at full depth.
|
||||
if ( depth >= 3
|
||||
&& moveCount > 1 + 2 * rootNode + 2 * (PvNode && abs(bestValue) < 2)
|
||||
&& (!rootNode || thisThread->best_move_count(move) == 0)
|
||||
&& ( !captureOrPromotion
|
||||
|| moveCountPruning
|
||||
|| ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha
|
||||
@@ -1179,7 +1189,7 @@ moves_loop: // When in check, search starts from here
|
||||
r++;
|
||||
|
||||
// Decrease reduction if position is or has been on the PV (~10 Elo)
|
||||
if (ttPv)
|
||||
if (ss->ttPv)
|
||||
r -= 2;
|
||||
|
||||
if (moveCountPruning && !formerPv)
|
||||
@@ -1208,7 +1218,7 @@ moves_loop: // When in check, search starts from here
|
||||
// hence break make_move(). (~2 Elo)
|
||||
else if ( type_of(move) == NORMAL
|
||||
&& !pos.see_ge(reverse_move(move)))
|
||||
r -= 2 + ttPv - (type_of(movedPiece) == PAWN);
|
||||
r -= 2 + ss->ttPv - (type_of(movedPiece) == PAWN);
|
||||
|
||||
ss->statScore = thisThread->mainHistory[us][from_to(move)]
|
||||
+ (*contHist[0])[movedPiece][to_sq(move)]
|
||||
@@ -1253,7 +1263,7 @@ moves_loop: // When in check, search starts from here
|
||||
didLMR = false;
|
||||
}
|
||||
|
||||
// Step 16. Full depth search when LMR is skipped or fails high
|
||||
// Step 17. Full depth search when LMR is skipped or fails high
|
||||
if (doFullDepthSearch)
|
||||
{
|
||||
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
|
||||
@@ -1281,12 +1291,12 @@ moves_loop: // When in check, search starts from here
|
||||
value = -search<PV>(pos, ss+1, -beta, -alpha, newDepth, false);
|
||||
}
|
||||
|
||||
// Step 17. Undo move
|
||||
// Step 18. Undo move
|
||||
pos.undo_move(move);
|
||||
|
||||
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
||||
|
||||
// Step 18. Check for a new best move
|
||||
// Step 19. Check for a new best move
|
||||
// Finished searching the move. If a stop occurred, the return value of
|
||||
// the search cannot be trusted, and we return immediately without
|
||||
// updating best move, PV and TT.
|
||||
@@ -1363,7 +1373,7 @@ moves_loop: // When in check, search starts from here
|
||||
return VALUE_DRAW;
|
||||
*/
|
||||
|
||||
// Step 19. Check for mate and stalemate
|
||||
// Step 20. Check for mate and stalemate
|
||||
// All legal moves have been searched and if there are no legal moves, it
|
||||
// must be a mate or a stalemate. If we are in a singular extension search then
|
||||
// return a fail low score.
|
||||
@@ -1386,8 +1396,17 @@ moves_loop: // When in check, search starts from here
|
||||
if (PvNode)
|
||||
bestValue = std::min(bestValue, maxValue);
|
||||
|
||||
// If no good move is found and the previous position was ttPv, then the previous
|
||||
// opponent move is probably good and the new position is added to the search tree.
|
||||
if (bestValue <= alpha)
|
||||
ss->ttPv = ss->ttPv || ((ss-1)->ttPv && depth > 3);
|
||||
// Otherwise, a counter move has been found and if the position is the last leaf
|
||||
// in the search tree, remove the position from the search tree.
|
||||
else if (depth > 3)
|
||||
ss->ttPv = ss->ttPv && (ss+1)->ttPv;
|
||||
|
||||
if (!excludedMove && !(rootNode && thisThread->pvIdx))
|
||||
tte->save(posKey, value_to_tt(bestValue, ss->ply), ttPv,
|
||||
tte->save(posKey, value_to_tt(bestValue, ss->ply), ss->ttPv,
|
||||
bestValue >= beta ? BOUND_LOWER :
|
||||
PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER,
|
||||
depth, bestMove, ss->staticEval);
|
||||
@@ -1576,7 +1595,7 @@ moves_loop: // When in check, search starts from here
|
||||
[to_sq(move)];
|
||||
|
||||
if ( !captureOrPromotion
|
||||
&& moveCount >= abs(depth) + 1
|
||||
&& moveCount
|
||||
&& (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold
|
||||
&& (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < CounterMovePruneThreshold)
|
||||
continue;
|
||||
@@ -1852,12 +1871,15 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) {
|
||||
{
|
||||
bool updated = rootMoves[i].score != -VALUE_INFINITE;
|
||||
|
||||
if (depth == 1 && !updated)
|
||||
if (depth == 1 && !updated && i > 0)
|
||||
continue;
|
||||
|
||||
Depth d = updated ? depth : depth - 1;
|
||||
Depth d = updated ? depth : std::max(1, depth - 1);
|
||||
Value v = updated ? rootMoves[i].score : rootMoves[i].previousScore;
|
||||
|
||||
if (v == -VALUE_INFINITE)
|
||||
v = VALUE_ZERO;
|
||||
|
||||
bool tb = TB::RootInTB && abs(v) < VALUE_MATE_IN_MAX_PLY;
|
||||
v = tb ? rootMoves[i].tbScore : v;
|
||||
|
||||
@@ -1955,7 +1977,7 @@ void Tablebases::rank_root_moves(Position& pos, Search::RootMoves& rootMoves) {
|
||||
if (RootInTB)
|
||||
{
|
||||
// Sort moves according to TB rank
|
||||
std::sort(rootMoves.begin(), rootMoves.end(),
|
||||
std::stable_sort(rootMoves.begin(), rootMoves.end(),
|
||||
[](const RootMove &a, const RootMove &b) { return a.tbRank > b.tbRank; } );
|
||||
|
||||
// Probe during search only if DTZ is not available and we are winning
|
||||
|
||||
@@ -48,6 +48,7 @@ struct Stack {
|
||||
int statScore;
|
||||
int moveCount;
|
||||
bool inCheck;
|
||||
bool ttPv;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -758,7 +758,7 @@ Ret do_probe_table(const Position& pos, T* entry, WDLScore wdl, ProbeState* resu
|
||||
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]]];
|
||||
@@ -859,7 +859,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
|
||||
|
||||
@@ -51,17 +51,6 @@ Thread::~Thread() {
|
||||
}
|
||||
|
||||
|
||||
/// Thread::bestMoveCount(Move move) return best move counter for the given root move
|
||||
|
||||
int Thread::best_move_count(Move move) const {
|
||||
|
||||
auto rm = std::find(rootMoves.begin() + pvIdx,
|
||||
rootMoves.begin() + pvLast, move);
|
||||
|
||||
return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0;
|
||||
}
|
||||
|
||||
|
||||
/// Thread::clear() reset histories, usually before a new game
|
||||
|
||||
void Thread::clear() {
|
||||
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
void idle_loop();
|
||||
void start_searching();
|
||||
void wait_for_search_finished();
|
||||
int best_move_count(Move move) const;
|
||||
|
||||
Pawns::Table pawnsTable;
|
||||
Material::Table materialTable;
|
||||
|
||||
+2
-7
@@ -21,6 +21,7 @@
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "evaluate.h"
|
||||
#include "misc.h"
|
||||
#include "search.h"
|
||||
#include "thread.h"
|
||||
@@ -80,19 +81,13 @@ void init(OptionsMap& o) {
|
||||
o["Syzygy50MoveRule"] << Option(true);
|
||||
o["SyzygyProbeLimit"] << Option(7, 0, 7);
|
||||
o["Use NNUE"] << Option(true, on_use_NNUE);
|
||||
// The default must follow the format nn-[SHA256 first 12 digits].nnue
|
||||
// for the build process (profile-build and fishtest) to work.
|
||||
o["EvalFile"] << Option("nn.bin", on_eval_file);
|
||||
#ifdef EVAL_NNUE
|
||||
o["EvalFile"] << Option(EvalFileDefaultName, on_eval_file);
|
||||
// When the evaluation function is loaded at the ucinewgame timing, it is necessary to convert the new evaluation function.
|
||||
// I want to hit the test eval convert command, but there is no new evaluation function
|
||||
// It ends abnormally before executing this command.
|
||||
// Therefore, with this hidden option, you can suppress the loading of the evaluation function when ucinewgame,
|
||||
// Hit the test eval convert command.
|
||||
o["SkipLoadingEval"] << Option(false);
|
||||
// how many moves to use a fixed move
|
||||
// o["BookMoves"] << Option(16, 0, 10000);
|
||||
#endif
|
||||
#if defined(EVAL_LEARN)
|
||||
// When learning the evaluation function, you can change the folder to save the evaluation function.
|
||||
// Evalsave by default. This folder shall be prepared in advance.
|
||||
|
||||
Reference in New Issue
Block a user