1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 09:13:08 +00:00

Merge branch 'master' into sf-nnue-nodchip

This commit is contained in:
joergoster 2020-06-25 15:10:12 +02:00
commit 151a0dda91
20 changed files with 149 additions and 115 deletions

View file

@ -155,6 +155,7 @@ Tom Vijlbrief (tomtor)
Tomasz Sobczyk (Sopel97) Tomasz Sobczyk (Sopel97)
Torsten Franz (torfranz, tfranzer) Torsten Franz (torfranz, tfranzer)
Tracey Emery (basepr1me) Tracey Emery (basepr1me)
Unai Corzo (unaiic)
Uri Blass (uriblass) Uri Blass (uriblass)
Vince Negri (cuddlestmonkey) Vince Negri (cuddlestmonkey)

View file

@ -92,7 +92,7 @@ endif
optimize = yes optimize = yes
debug = no debug = no
sanitize = no sanitize = no
bits = 32 bits = 64
prefetch = no prefetch = no
popcnt = no popcnt = no
sse = no sse = no
@ -100,36 +100,35 @@ avx2 = no
pext = no pext = no
### 2.2 Architecture specific ### 2.2 Architecture specific
ifeq ($(ARCH),general-32) ifeq ($(ARCH),general-32)
arch = any arch = any
bits = 32
endif endif
ifeq ($(ARCH),x86-32-old) ifeq ($(ARCH),x86-32-old)
arch = i386 arch = i386
bits = 32
endif endif
ifeq ($(ARCH),x86-32) ifeq ($(ARCH),x86-32)
arch = i386 arch = i386
bits = 32
prefetch = yes prefetch = yes
sse = yes sse = yes
endif endif
ifeq ($(ARCH),general-64) ifeq ($(ARCH),general-64)
arch = any arch = any
bits = 64
endif endif
ifeq ($(ARCH),x86-64) ifeq ($(ARCH),x86-64)
arch = x86_64 arch = x86_64
bits = 64
prefetch = yes prefetch = yes
sse = yes sse = yes
endif endif
ifeq ($(ARCH),x86-64-modern) ifeq ($(ARCH),x86-64-modern)
arch = x86_64 arch = x86_64
bits = 64
prefetch = yes prefetch = yes
popcnt = yes popcnt = yes
sse = yes sse = yes
@ -146,7 +145,6 @@ endif
ifeq ($(ARCH),x86-64-bmi2) ifeq ($(ARCH),x86-64-bmi2)
arch = x86_64 arch = x86_64
bits = 64
prefetch = yes prefetch = yes
popcnt = yes popcnt = yes
sse = yes sse = yes
@ -157,26 +155,31 @@ endif
ifeq ($(ARCH),armv7) ifeq ($(ARCH),armv7)
arch = armv7 arch = armv7
prefetch = yes prefetch = yes
bits = 32
endif
ifeq ($(ARCH),armv8)
arch = armv8-a
bits = 64
prefetch = yes
endif endif
ifeq ($(ARCH),ppc-32) ifeq ($(ARCH),ppc-32)
arch = ppc arch = ppc
bits = 32
endif endif
ifeq ($(ARCH),ppc-64) ifeq ($(ARCH),ppc-64)
arch = ppc64 arch = ppc64
bits = 64
popcnt = yes popcnt = yes
prefetch = yes prefetch = yes
endif endif
### ========================================================================== ### ==========================================================================
### Section 3. Low-level configuration ### Section 3. Low-level Configuration
### ========================================================================== ### ==========================================================================
### 3.1 Selecting compiler (default = gcc) ### 3.1 Selecting compiler (default = gcc)
CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS) CXXFLAGS += -Wall -Wcast-qual -fno-exceptions -std=c++17 $(EXTRACXXFLAGS)
DEPENDFLAGS += -std=c++17 DEPENDFLAGS += -std=c++17
LDFLAGS += $(EXTRALDFLAGS) LDFLAGS += $(EXTRALDFLAGS)
@ -190,7 +193,7 @@ ifeq ($(COMP),gcc)
CXX=g++ CXX=g++
CXXFLAGS += -pedantic -Wextra -Wshadow CXXFLAGS += -pedantic -Wextra -Wshadow
ifeq ($(ARCH),armv7) ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
ifeq ($(OS),Android) ifeq ($(OS),Android)
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
@ -247,7 +250,7 @@ ifeq ($(COMP),clang)
endif endif
endif endif
ifeq ($(ARCH),armv7) ifeq ($(ARCH),$(filter $(ARCH),armv7 armv8))
ifeq ($(OS),Android) ifeq ($(OS),Android)
CXXFLAGS += -m$(bits) CXXFLAGS += -m$(bits)
LDFLAGS += -m$(bits) LDFLAGS += -m$(bits)
@ -396,17 +399,10 @@ endif
### needs access to the optimization flags. ### needs access to the optimization flags.
ifeq ($(optimize),yes) ifeq ($(optimize),yes)
ifeq ($(debug), no) ifeq ($(debug), no)
ifeq ($(comp),$(filter $(comp),gcc clang msys2)) ifeq ($(comp),$(filter $(comp),gcc clang mingw))
CXXFLAGS += -flto CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS) LDFLAGS += $(CXXFLAGS)
endif endif
ifeq ($(comp),mingw)
ifeq ($(KERNEL),Linux)
CXXFLAGS += -flto
LDFLAGS += $(CXXFLAGS)
endif
endif
endif endif
endif endif
@ -417,9 +413,8 @@ ifeq ($(OS), Android)
LDFLAGS += -fPIE -pie LDFLAGS += -fPIE -pie
endif endif
### ========================================================================== ### ==========================================================================
### Section 4. Public targets ### Section 4. Public Targets
### ========================================================================== ### ==========================================================================
help: help:
@ -447,6 +442,7 @@ help:
@echo "ppc-64 > PPC 64-bit" @echo "ppc-64 > PPC 64-bit"
@echo "ppc-32 > PPC 32-bit" @echo "ppc-32 > PPC 32-bit"
@echo "armv7 > ARMv7 32-bit" @echo "armv7 > ARMv7 32-bit"
@echo "armv8 > ARMv8 64-bit"
@echo "general-64 > unspecified 64-bit" @echo "general-64 > unspecified 64-bit"
@echo "general-32 > unspecified 32-bit" @echo "general-32 > unspecified 32-bit"
@echo "" @echo ""
@ -518,7 +514,7 @@ default:
help help
### ========================================================================== ### ==========================================================================
### Section 5. Private targets ### Section 5. Private Targets
### ========================================================================== ### ==========================================================================
all: $(EXE) .depend all: $(EXE) .depend
@ -550,7 +546,8 @@ config-sanity:
@test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || test "$(sanitize)" = "address" || test "$(sanitize)" = "no" @test "$(sanitize)" = "undefined" || test "$(sanitize)" = "thread" || test "$(sanitize)" = "address" || test "$(sanitize)" = "no"
@test "$(optimize)" = "yes" || test "$(optimize)" = "no" @test "$(optimize)" = "yes" || test "$(optimize)" = "no"
@test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \ @test "$(arch)" = "any" || test "$(arch)" = "x86_64" || test "$(arch)" = "i386" || \
test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || test "$(arch)" = "armv7" test "$(arch)" = "ppc64" || test "$(arch)" = "ppc" || \
test "$(arch)" = "armv7" || test "$(arch)" = "armv8-a"
@test "$(bits)" = "32" || test "$(bits)" = "64" @test "$(bits)" = "32" || test "$(bits)" = "64"
@test "$(prefetch)" = "yes" || test "$(prefetch)" = "no" @test "$(prefetch)" = "yes" || test "$(prefetch)" = "no"
@test "$(popcnt)" = "yes" || test "$(popcnt)" = "no" @test "$(popcnt)" = "yes" || test "$(popcnt)" = "no"
@ -613,4 +610,3 @@ nnue-learn-use-blas: config-sanity
-@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null -@$(CXX) $(DEPENDFLAGS) -MM $(OBJS:.o=.cpp) > $@ 2> /dev/null
-include .depend -include .depend

View file

@ -110,6 +110,7 @@ inline Bitboard square_bb(Square s) {
return SquareBB[s]; return SquareBB[s];
} }
/// Overloads of bitwise operators between a Bitboard and a Square for testing /// Overloads of bitwise operators between a Bitboard and a Square for testing
/// whether a given bit is set in a bitboard, and for setting and clearing bits. /// whether a given bit is set in a bitboard, and for setting and clearing bits.
@ -200,10 +201,11 @@ inline Bitboard adjacent_files_bb(Square s) {
return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s)); return shift<EAST>(file_bb(s)) | shift<WEST>(file_bb(s));
} }
/// line_bb(Square, Square) returns a Bitboard representing an entire line
/// (from board edge to board edge) that intersects the given squares. /// line_bb(Square, Square) returns a bitboard representing an entire line,
/// If the given squares are not on a same file/rank/diagonal, return 0. /// from board edge to board edge, that intersects the given squares. If the
/// Ex. line_bb(SQ_C4, SQ_F7) returns a bitboard with the A2-G8 diagonal. /// given squares are not on a same file/rank/diagonal, returns 0. For instance,
/// line_bb(SQ_C4, SQ_F7) will return a bitboard with the A2-G8 diagonal.
inline Bitboard line_bb(Square s1, Square s2) { inline Bitboard line_bb(Square s1, Square s2) {
@ -211,10 +213,11 @@ inline Bitboard line_bb(Square s1, Square s2) {
return LineBB[s1][s2]; return LineBB[s1][s2];
} }
/// between_bb() returns a Bitboard representing squares that are linearly
/// between the given squares (excluding the given squares). /// between_bb() returns a bitboard representing squares that are linearly
/// If the given squares are not on a same file/rank/diagonal, return 0. /// between the given squares (excluding the given squares). If the given
/// Ex. between_bb(SQ_C4, SQ_F7) returns a bitboard with squares D5 and E6. /// squares are not on a same file/rank/diagonal, return 0. For instance,
/// between_bb(SQ_C4, SQ_F7) will return a bitboard with squares D5 and E6.
inline Bitboard between_bb(Square s1, Square s2) { inline Bitboard between_bb(Square s1, Square s2) {
Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2)); Bitboard b = line_bb(s1, s2) & ((AllSquares << s1) ^ (AllSquares << s2));
@ -241,8 +244,8 @@ inline Bitboard forward_file_bb(Color c, Square s) {
/// pawn_attack_span() returns a bitboard representing all the squares that can /// pawn_attack_span() returns a bitboard representing all the squares that can
/// be attacked by a pawn of the given color when it moves along its file, /// be attacked by a pawn of the given color when it moves along its file, starting
/// starting from the given square. /// from the given square.
inline Bitboard pawn_attack_span(Color c, Square s) { inline Bitboard pawn_attack_span(Color c, Square s) {
return forward_ranks_bb(c, s) & adjacent_files_bb(s); return forward_ranks_bb(c, s) & adjacent_files_bb(s);
@ -276,7 +279,9 @@ template<> inline int distance<Square>(Square x, Square y) { return SquareDistan
inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); } inline int edge_distance(File f) { return std::min(f, File(FILE_H - f)); }
inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); } inline int edge_distance(Rank r) { return std::min(r, Rank(RANK_8 - r)); }
/// Return the target square bitboard if we do not step off the board, empty otherwise
/// safe_destination() returns the bitboard of target square for the given step
/// from the given square. If the step is off the board, returns empty bitboard.
inline Bitboard safe_destination(Square s, int step) inline Bitboard safe_destination(Square s, int step)
{ {
@ -284,6 +289,7 @@ inline Bitboard safe_destination(Square s, int step)
return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0); return is_ok(to) && distance(s, to) <= 2 ? square_bb(to) : Bitboard(0);
} }
/// attacks_bb(Square) returns the pseudo attacks of the give piece type /// attacks_bb(Square) returns the pseudo attacks of the give piece type
/// assuming an empty board. /// assuming an empty board.
@ -295,6 +301,7 @@ inline Bitboard attacks_bb(Square s) {
return PseudoAttacks[Pt][s]; return PseudoAttacks[Pt][s];
} }
/// attacks_bb(Square, Bitboard) returns the attacks by the given piece /// attacks_bb(Square, Bitboard) returns the attacks by the given piece
/// assuming the board is occupied according to the passed Bitboard. /// assuming the board is occupied according to the passed Bitboard.
/// Sliding piece attacks do not continue passed an occupied square. /// Sliding piece attacks do not continue passed an occupied square.

View file

@ -268,7 +268,7 @@ Value Endgame<KQKP>::operator()(const Position& pos) const {
} }
/// KQ vs KR. This is almost identical to KX vs K: We give the attacking /// KQ vs KR. This is almost identical to KX vs K: we give the attacking
/// king a bonus for having the kings close together, and for forcing the /// king a bonus for having the kings close together, and for forcing the
/// defending king towards the edge. If we also take care to avoid null move for /// defending king towards the edge. If we also take care to avoid null move for
/// the defending side in the search, this is usually sufficient to win KQ vs KR. /// the defending side in the search, this is usually sufficient to win KQ vs KR.
@ -291,7 +291,7 @@ Value Endgame<KQKR>::operator()(const Position& pos) const {
/// KNN vs KP. Very drawish, but there are some mate opportunities if we can /// KNN vs KP. Very drawish, but there are some mate opportunities if we can
// press the weakSide King to a corner before the pawn advances too much. /// press the weakSide King to a corner before the pawn advances too much.
template<> template<>
Value Endgame<KNNKP>::operator()(const Position& pos) const { Value Endgame<KNNKP>::operator()(const Position& pos) const {
@ -352,7 +352,7 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN)); Square weakPawn = frontmost_sq(strongSide, pos.pieces(weakSide, PAWN));
// There's potential for a draw if our pawn is blocked on the 7th rank, // There's potential for a draw if our pawn is blocked on the 7th rank,
// the bishop cannot attack it or they only have one pawn left // the bishop cannot attack it or they only have one pawn left.
if ( relative_rank(strongSide, weakPawn) == RANK_7 if ( relative_rank(strongSide, weakPawn) == RANK_7
&& (strongPawns & (weakPawn + pawn_push(weakSide))) && (strongPawns & (weakPawn + pawn_push(weakSide)))
&& (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns))) && (opposite_colors(strongBishop, weakPawn) || !more_than_one(strongPawns)))
@ -365,7 +365,7 @@ ScaleFactor Endgame<KBPsK>::operator()(const Position& pos) const {
// closer. (I think this rule only fails in practically // closer. (I think this rule only fails in practically
// unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w // unreachable positions such as 5k1K/6p1/6P1/8/8/3B4/8/8 w
// and positions where qsearch will immediately correct the // and positions where qsearch will immediately correct the
// problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w) // problem such as 8/4k1p1/6P1/1K6/3B4/8/8/8 w).
if ( relative_rank(strongSide, weakKing) >= RANK_7 if ( relative_rank(strongSide, weakKing) >= RANK_7
&& weakKingDist <= 2 && weakKingDist <= 2
&& weakKingDist <= strongKingDist) && weakKingDist <= strongKingDist)
@ -576,7 +576,7 @@ ScaleFactor Endgame<KRPPKRP>::operator()(const Position& pos) const {
} }
/// K and two or more pawns vs K. There is just a single rule here: If all pawns /// K and two or more pawns vs K. There is just a single rule here: if all pawns
/// are on the same rook file and are blocked by the defending king, it's a draw. /// are on the same rook file and are blocked by the defending king, it's a draw.
template<> template<>
ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const { ScaleFactor Endgame<KPsK>::operator()(const Position& pos) const {
@ -693,7 +693,7 @@ ScaleFactor Endgame<KBPPKB>::operator()(const Position& pos) const {
} }
/// KBP vs KN. There is a single rule: If the defending king is somewhere along /// KBP vs KN. There is a single rule: if the defending king is somewhere along
/// the path of the pawn, and the square of the king is not of the same color as /// the path of the pawn, and the square of the king is not of the same color as
/// the stronger side's bishop, it's a draw. /// the stronger side's bishop, it's a draw.
template<> template<>
@ -717,7 +717,7 @@ ScaleFactor Endgame<KBPKN>::operator()(const Position& pos) const {
/// KP vs KP. This is done by removing the weakest side's pawn and probing the /// KP vs KP. This is done by removing the weakest side's pawn and probing the
/// KP vs K bitbase: If the weakest side has a draw without the pawn, it probably /// KP vs K bitbase: if the weakest side has a draw without the pawn, it probably
/// has at least a draw with the pawn as well. The exception is when the stronger /// has at least a draw with the pawn as well. The exception is when the stronger
/// side's pawn is far advanced and not on a rook file; in this case it is often /// side's pawn is far advanced and not on a rook file; in this case it is often
/// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1). /// possible to win (e.g. 8/4k3/3p4/3P4/6K1/8/8/8 w - - 0 1).

View file

@ -129,23 +129,23 @@ namespace {
}; };
// Assorted bonuses and penalties // Assorted bonuses and penalties
constexpr Score BishopPawns = S( 3, 7); constexpr Score BishopKingProtector = S( 6, 9);
constexpr Score BishopOnKingRing = S( 24, 0); constexpr Score BishopOnKingRing = S( 24, 0);
constexpr Score BishopOutpost = S( 30, 23);
constexpr Score BishopPawns = S( 3, 7);
constexpr Score BishopXRayPawns = S( 4, 5); constexpr Score BishopXRayPawns = S( 4, 5);
constexpr Score CorneredBishop = S( 50, 50); constexpr Score CorneredBishop = S( 50, 50);
constexpr Score FlankAttacks = S( 8, 0); constexpr Score FlankAttacks = S( 8, 0);
constexpr Score Hanging = S( 69, 36); constexpr Score Hanging = S( 69, 36);
constexpr Score BishopKingProtector = S( 6, 9);
constexpr Score KnightKingProtector = S( 8, 9); constexpr Score KnightKingProtector = S( 8, 9);
constexpr Score KnightOnQueen = S( 16, 11); constexpr Score KnightOnQueen = S( 16, 11);
constexpr Score KnightOutpost = S( 56, 36);
constexpr Score LongDiagonalBishop = S( 45, 0); constexpr Score LongDiagonalBishop = S( 45, 0);
constexpr Score MinorBehindPawn = S( 18, 3); constexpr Score MinorBehindPawn = S( 18, 3);
constexpr Score KnightOutpost = S( 56, 36);
constexpr Score BishopOutpost = S( 30, 23);
constexpr Score ReachableOutpost = S( 31, 22);
constexpr Score PassedFile = S( 11, 8); constexpr Score PassedFile = S( 11, 8);
constexpr Score PawnlessFlank = S( 17, 95); constexpr Score PawnlessFlank = S( 17, 95);
constexpr Score QueenInfiltration = S( -2, 14); constexpr Score QueenInfiltration = S( -2, 14);
constexpr Score ReachableOutpost = S( 31, 22);
constexpr Score RestrictedPiece = S( 7, 7); constexpr Score RestrictedPiece = S( 7, 7);
constexpr Score RookOnKingRing = S( 16, 0); constexpr Score RookOnKingRing = S( 16, 0);
constexpr Score RookOnQueenFile = S( 6, 11); constexpr Score RookOnQueenFile = S( 6, 11);
@ -154,8 +154,9 @@ namespace {
constexpr Score ThreatByPawnPush = S( 48, 39); constexpr Score ThreatByPawnPush = S( 48, 39);
constexpr Score ThreatBySafePawn = S(173, 94); constexpr Score ThreatBySafePawn = S(173, 94);
constexpr Score TrappedRook = S( 55, 13); constexpr Score TrappedRook = S( 55, 13);
constexpr Score WeakQueen = S( 56, 15);
constexpr Score WeakQueenProtection = S( 14, 0); constexpr Score WeakQueenProtection = S( 14, 0);
constexpr Score WeakQueen = S( 56, 15);
#undef S #undef S
@ -218,6 +219,7 @@ namespace {
// Evaluation::initialize() computes king and pawn attacks, and the king ring // Evaluation::initialize() computes king and pawn attacks, and the king ring
// bitboard for a given color. This is done at the beginning of the evaluation. // bitboard for a given color. This is done at the beginning of the evaluation.
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
void Evaluation<T>::initialize() { void Evaluation<T>::initialize() {
@ -257,6 +259,7 @@ namespace {
// Evaluation::pieces() scores pieces of a given color and type // Evaluation::pieces() scores pieces of a given color and type
template<Tracing T> template<Color Us, PieceType Pt> template<Tracing T> template<Color Us, PieceType Pt>
Score Evaluation<T>::pieces() { Score Evaluation<T>::pieces() {
@ -390,6 +393,7 @@ namespace {
// Evaluation::king() assigns bonuses and penalties to a king of a given color // Evaluation::king() assigns bonuses and penalties to a king of a given color
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
Score Evaluation<T>::king() const { Score Evaluation<T>::king() const {
@ -498,6 +502,7 @@ namespace {
// Evaluation::threats() assigns bonuses according to the types of the // Evaluation::threats() assigns bonuses according to the types of the
// attacking and the attacked pieces. // attacking and the attacked pieces.
template<Tracing T> template<Color Us> template<Tracing T> template<Color Us>
Score Evaluation<T>::threats() const { Score Evaluation<T>::threats() const {
@ -723,8 +728,8 @@ namespace {
// Evaluation::winnable() adjusts the mg and eg score components based on the // Evaluation::winnable() adjusts the mg and eg score components based on the
// known attacking/defending status of the players. // known attacking/defending status of the players. A single value is derived
// A single value is derived from the mg and eg values and returned. // by interpolation from the mg and eg values and returned.
template<Tracing T> template<Tracing T>
Value Evaluation<T>::winnable(Score score) const { Value Evaluation<T>::winnable(Score score) const {
@ -830,12 +835,11 @@ namespace {
return pos.side_to_move() == WHITE ? v : -v; return pos.side_to_move() == WHITE ? v : -v;
// Main evaluation begins here // Main evaluation begins here
initialize<WHITE>(); initialize<WHITE>();
initialize<BLACK>(); initialize<BLACK>();
// Pieces evaluated first (also populates attackedBy, attackedBy2). // Pieces evaluated first (also populates attackedBy, attackedBy2).
// Note that the order of evaluation of the terms is left unspecified // Note that the order of evaluation of the terms is left unspecified.
score += pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>() score += pieces<WHITE, KNIGHT>() - pieces<BLACK, KNIGHT>()
+ pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>() + pieces<WHITE, BISHOP>() - pieces<BLACK, BISHOP>()
+ pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >() + pieces<WHITE, ROOK >() - pieces<BLACK, ROOK >()

View file

@ -44,12 +44,12 @@ namespace {
constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = { constexpr int QuadraticTheirs[][PIECE_TYPE_NB] = {
// THEIR PIECES // THEIR PIECES
// pair pawn knight bishop rook queen // pair pawn knight bishop rook queen
{ 0 }, // Bishop pair { }, // Bishop pair
{ 36, 0 }, // Pawn { 36, }, // Pawn
{ 9, 63, 0 }, // Knight OUR PIECES { 9, 63, }, // Knight OUR PIECES
{ 59, 65, 42, 0 }, // Bishop { 59, 65, 42, }, // Bishop
{ 46, 39, 24, -24, 0 }, // Rook { 46, 39, 24, -24, }, // Rook
{ 97, 100, -42, 137, 268, 0 } // Queen { 97, 100, -42, 137, 268, } // Queen
}; };
// Endgame evaluation and scaling functions are accessed directly and not through // Endgame evaluation and scaling functions are accessed directly and not through
@ -79,8 +79,10 @@ namespace {
&& pos.count<PAWN>(~us) >= 1; && pos.count<PAWN>(~us) >= 1;
} }
/// imbalance() calculates the imbalance by comparing the piece count of each /// imbalance() calculates the imbalance by comparing the piece count of each
/// piece type for both colors. /// piece type for both colors.
template<Color Us> template<Color Us>
int imbalance(const int pieceCount[][PIECE_TYPE_NB]) { int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
@ -94,9 +96,9 @@ namespace {
if (!pieceCount[Us][pt1]) if (!pieceCount[Us][pt1])
continue; continue;
int v = 0; int v = QuadraticOurs[pt1][pt1] * pieceCount[Us][pt1];
for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2) for (int pt2 = NO_PIECE_TYPE; pt2 < pt1; ++pt2)
v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2] v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
+ QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2]; + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
@ -110,6 +112,7 @@ namespace {
namespace Material { namespace Material {
/// Material::probe() looks up the current position's material configuration in /// Material::probe() looks up the current position's material configuration in
/// the material hash table. It returns a pointer to the Entry if the position /// the material hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't /// is found. Otherwise a new Entry is computed and stored there, so we don't

View file

@ -44,7 +44,7 @@ struct Entry {
bool specialized_eval_exists() const { return evaluationFunction != nullptr; } bool specialized_eval_exists() const { return evaluationFunction != nullptr; }
Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); } Value evaluate(const Position& pos) const { return (*evaluationFunction)(pos); }
// scale_factor takes a position and a color as input and returns a scale factor // scale_factor() takes a position and a color as input and returns a scale factor
// for the given color. We have to provide the position in addition to the color // for the given color. We have to provide the position in addition to the color
// because the scale factor may also be a function which should be applied to // because the scale factor may also be a function which should be applied to
// the position. For instance, in KBP vs K endgames, the scaling function looks // the position. For instance, in KBP vs K endgames, the scaling function looks

View file

@ -295,9 +295,10 @@ void prefetch(void* addr) {
#endif #endif
/// aligned_ttmem_alloc will return suitably aligned memory, and if possible use large pages. /// aligned_ttmem_alloc() will return suitably aligned memory, and if possible use large pages.
/// The returned pointer is the aligned one, while the mem argument is the one that needs to be passed to free. /// The returned pointer is the aligned one, while the mem argument is the one that needs
/// With c++17 some of this functionality can be simplified. /// to be passed to free. With c++17 some of this functionality could be simplified.
#if defined(__linux__) && !defined(__ANDROID__) #if defined(__linux__) && !defined(__ANDROID__)
void* aligned_ttmem_alloc(size_t allocSize, void*& mem) { void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
@ -337,17 +338,17 @@ static void* aligned_ttmem_alloc_large_pages(size_t allocSize) {
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds, // Try to enable SeLockMemoryPrivilege. Note that even if AdjustTokenPrivileges() succeeds,
// we still need to query GetLastError() to ensure that the privileges were actually obtained... // we still need to query GetLastError() to ensure that the privileges were actually obtained.
if (AdjustTokenPrivileges( if (AdjustTokenPrivileges(
hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) && hProcessToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prevTp, &prevTpLen) &&
GetLastError() == ERROR_SUCCESS) GetLastError() == ERROR_SUCCESS)
{ {
// round up size to full pages and allocate // Round up size to full pages and allocate
allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1); allocSize = (allocSize + largePageSize - 1) & ~size_t(largePageSize - 1);
mem = VirtualAlloc( mem = VirtualAlloc(
NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); NULL, allocSize, MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE);
// privilege no longer needed, restore previous state // Privilege no longer needed, restore previous state
AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL); AdjustTokenPrivileges(hProcessToken, FALSE, &prevTp, 0, NULL, NULL);
} }
} }
@ -361,7 +362,7 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
static bool firstCall = true; static bool firstCall = true;
// try to allocate large pages // Try to allocate large pages
mem = aligned_ttmem_alloc_large_pages(allocSize); mem = aligned_ttmem_alloc_large_pages(allocSize);
// Suppress info strings on the first call. The first call occurs before 'uci' // Suppress info strings on the first call. The first call occurs before 'uci'
@ -375,7 +376,7 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
} }
firstCall = false; firstCall = false;
// fall back to regular, page aligned, allocation if necessary // Fall back to regular, page aligned, allocation if necessary
if (!mem) if (!mem)
mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); mem = VirtualAlloc(NULL, allocSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
@ -395,7 +396,9 @@ void* aligned_ttmem_alloc(size_t allocSize, void*& mem) {
#endif #endif
/// aligned_ttmem_free will free the previously allocated ttmem
/// aligned_ttmem_free() will free the previously allocated ttmem
#if defined(_WIN64) #if defined(_WIN64)
void aligned_ttmem_free(void* mem) { void aligned_ttmem_free(void* mem) {

View file

@ -66,6 +66,12 @@ namespace {
#undef S #undef S
#undef V #undef V
/// evaluate() calculates a score for the static pawn structure of the given position.
/// We cannot use the location of pieces or king in this function, as the evaluation
/// of the pawn structure will be stored in a small cache for speed reasons, and will
/// be re-used even when the pieces have moved.
template<Color Us> template<Color Us>
Score evaluate(const Position& pos, Pawns::Entry* e) { Score evaluate(const Position& pos, Pawns::Entry* e) {
@ -170,6 +176,7 @@ namespace {
namespace Pawns { namespace Pawns {
/// Pawns::probe() looks up the current position's pawns configuration in /// Pawns::probe() looks up the current position's pawns configuration in
/// the pawns hash table. It returns a pointer to the Entry if the position /// the pawns hash table. It returns a pointer to the Entry if the position
/// is found. Otherwise a new Entry is computed and stored there, so we don't /// is found. Otherwise a new Entry is computed and stored there, so we don't

View file

@ -105,8 +105,7 @@ Key cuckoo[8192];
Move cuckooMove[8192]; Move cuckooMove[8192];
/// Position::init() initializes at startup the various arrays used to compute /// Position::init() initializes at startup the various arrays used to compute hash keys
/// hash keys.
void Position::init() { void Position::init() {
@ -1278,6 +1277,7 @@ bool Position::see_ge(Move m, Value threshold) const {
return bool(res); return bool(res);
} }
/// Position::is_draw() tests whether the position is drawn by 50-move rule /// Position::is_draw() tests whether the position is drawn by 50-move rule
/// or by repetition. It does not detect stalemates. /// or by repetition. It does not detect stalemates.

View file

@ -68,6 +68,7 @@ struct StateInfo {
#endif // defined(EVAL_NNUE) #endif // defined(EVAL_NNUE)
}; };
/// A list to keep track of the position states along the setup moves (from the /// A list to keep track of the position states along the setup moves (from the
/// start position to the position just before the search starts). Needed by /// start position to the position just before the search starts). Needed by
/// 'draw by repetition' detection. Use a std::deque because pointers to /// 'draw by repetition' detection. Use a std::deque because pointers to

View file

@ -101,9 +101,10 @@ constexpr Score PBonus[RANK_NB][FILE_NB] =
Score psq[PIECE_NB][SQUARE_NB]; Score psq[PIECE_NB][SQUARE_NB];
// init() initializes piece-square tables: the white halves of the tables are
// copied from Bonus[] adding the piece value, then the black halves of the // PSQT::init() initializes piece-square tables: the white halves of the tables are
// tables are initialized by flipping and changing the sign of the white scores. // copied from Bonus[] and PBonus[], adding the piece value, then the black halves of
// the tables are initialized by flipping and changing the sign of the white scores.
void init() { void init() {
for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING}) for (Piece pc : {W_PAWN, W_KNIGHT, W_BISHOP, W_ROOK, W_QUEEN, W_KING})
@ -113,7 +114,7 @@ void init() {
for (Square s = SQ_A1; s <= SQ_H8; ++s) for (Square s = SQ_A1; s <= SQ_H8; ++s)
{ {
File f = File(edge_distance(file_of(s))); File f = File(edge_distance(file_of(s)));
psq[ pc][ s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)] psq[ pc][s] = score + (type_of(pc) == PAWN ? PBonus[rank_of(s)][file_of(s)]
: Bonus[pc][rank_of(s)][f]); : Bonus[pc][rank_of(s)][f]);
psq[~pc][flip_rank(s)] = -psq[pc][s]; psq[~pc][flip_rank(s)] = -psq[pc][s];
} }

View file

@ -525,7 +525,7 @@ void Thread::search() {
double totalTime = rootMoves.size() == 1 ? 0 : double totalTime = rootMoves.size() == 1 ? 0 :
Time.optimum() * fallingEval * reduction * bestMoveInstability; Time.optimum() * fallingEval * reduction * bestMoveInstability;
// Stop the search if we have exceeded the totalTime, at least 1ms search. // Stop the search if we have exceeded the totalTime, at least 1ms search
if (Time.elapsed() > totalTime) if (Time.elapsed() > totalTime)
{ {
// If we are allowed to ponder do not stop the search now but // If we are allowed to ponder do not stop the search now but
@ -767,9 +767,10 @@ namespace {
// Step 6. Static evaluation of the position // Step 6. Static evaluation of the position
if (ss->inCheck) if (ss->inCheck)
{ {
// Skip early pruning when in check
ss->staticEval = eval = VALUE_NONE; ss->staticEval = eval = VALUE_NONE;
improving = false; improving = false;
goto moves_loop; // Skip early pruning when in check goto moves_loop;
} }
else if (ttHit) else if (ttHit)
{ {
@ -1026,8 +1027,10 @@ moves_loop: // When in check, search starts from here
if ( !givesCheck if ( !givesCheck
&& lmrDepth < 6 && lmrDepth < 6
&& !(PvNode && abs(bestValue) < 2) && !(PvNode && abs(bestValue) < 2)
&& PieceValue[MG][type_of(movedPiece)] >= PieceValue[MG][type_of(pos.piece_on(to_sq(move)))]
&& !ss->inCheck && !ss->inCheck
&& ss->staticEval + 267 + 391 * lmrDepth + PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha) && ss->staticEval + 267 + 391 * lmrDepth
+ PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha)
continue; continue;
// See based pruning // See based pruning
@ -1073,8 +1076,8 @@ moves_loop: // When in check, search starts from here
else if (singularBeta >= beta) else if (singularBeta >= beta)
return singularBeta; return singularBeta;
// If the eval of ttMove is greater than beta we try also if there is an other move that // If the eval of ttMove is greater than beta we try also if there is another
// pushes it over beta, if so also produce a cutoff // move that pushes it over beta, if so also produce a cutoff.
else if (ttValue >= beta) else if (ttValue >= beta)
{ {
ss->excludedMove = move; ss->excludedMove = move;
@ -1152,7 +1155,7 @@ moves_loop: // When in check, search starts from here
if (thisThread->ttHitAverage > 473 * TtHitAverageResolution * TtHitAverageWindow / 1024) if (thisThread->ttHitAverage > 473 * TtHitAverageResolution * TtHitAverageWindow / 1024)
r--; r--;
// Reduction if other threads are searching this position. // Reduction if other threads are searching this position
if (th.marked()) if (th.marked())
r++; r++;
@ -1289,7 +1292,7 @@ moves_loop: // When in check, search starts from here
rm.pv.push_back(*m); rm.pv.push_back(*m);
// We record how often the best move has been changed in each // We record how often the best move has been changed in each
// iteration. This information is used for time management: When // iteration. This information is used for time management: when
// the best move changes frequently, we allocate some more time. // the best move changes frequently, we allocate some more time.
if (moveCount > 1) if (moveCount > 1)
++thisThread->bestMoveChanges; ++thisThread->bestMoveChanges;
@ -1523,7 +1526,7 @@ moves_loop: // When in check, search starts from here
} }
} }
// Don't search moves with negative SEE values // Do not search moves with negative SEE values
if ( !ss->inCheck && !pos.see_ge(move)) if ( !ss->inCheck && !pos.see_ge(move))
continue; continue;
@ -1576,7 +1579,7 @@ moves_loop: // When in check, search starts from here
} }
} }
// All legal moves have been searched. A special case: If we're in check // All legal moves have been searched. A special case: if we're in check
// and no legal moves were found, it is checkmate. // and no legal moves were found, it is checkmate.
if (ss->inCheck && bestValue == -VALUE_INFINITE) if (ss->inCheck && bestValue == -VALUE_INFINITE)
return mated_in(ss->ply); // Plies to mate from the root return mated_in(ss->ply); // Plies to mate from the root
@ -1593,7 +1596,7 @@ moves_loop: // When in check, search starts from here
// value_to_tt() adjusts a mate or TB score from "plies to mate from the root" to // value_to_tt() adjusts a mate or TB score from "plies to mate from the root" to
// "plies to mate from the current position". standard scores are unchanged. // "plies to mate from the current position". Standard scores are unchanged.
// The function is called before storing a value in the transposition table. // The function is called before storing a value in the transposition table.
Value value_to_tt(Value v, int ply) { Value value_to_tt(Value v, int ply) {
@ -1605,11 +1608,11 @@ moves_loop: // When in check, search starts from here
} }
// value_from_tt() is the inverse of value_to_tt(): It adjusts a mate or TB score // value_from_tt() is the inverse of value_to_tt(): it adjusts a mate or TB score
// from the transposition table (which refers to the plies to mate/be mated // from the transposition table (which refers to the plies to mate/be mated from
// from current position) to "plies to mate/be mated (TB win/loss) from the root". // current position) to "plies to mate/be mated (TB win/loss) from the root". However,
// However, for mate scores, to avoid potentially false mate scores related to the 50 moves rule, // for mate scores, to avoid potentially false mate scores related to the 50 moves rule
// and the graph history interaction, return an optimal TB score instead. // and the graph history interaction, we return an optimal TB score instead.
Value value_from_tt(Value v, int ply, int r50c) { Value value_from_tt(Value v, int ply, int r50c) {
@ -1769,6 +1772,7 @@ moves_loop: // When in check, search starts from here
} // namespace } // namespace
/// MainThread::check_time() is used to print debug info and, more importantly, /// MainThread::check_time() is used to print debug info and, more importantly,
/// to detect when we are out of available time and thus stop the search. /// to detect when we are out of available time and thus stop the search.

View file

@ -52,6 +52,7 @@ Thread::~Thread() {
stdThread.join(); stdThread.join();
} }
/// Thread::bestMoveCount(Move move) return best move counter for the given root move /// Thread::bestMoveCount(Move move) return best move counter for the given root move
int Thread::best_move_count(Move move) const { int Thread::best_move_count(Move move) const {
@ -62,6 +63,7 @@ int Thread::best_move_count(Move move) const {
return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0; return rm != rootMoves.begin() + pvLast ? rm->bestMoveCount : 0;
} }
/// Thread::clear() reset histories, usually before a new game /// Thread::clear() reset histories, usually before a new game
void Thread::clear() { void Thread::clear() {
@ -81,6 +83,7 @@ void Thread::clear() {
} }
} }
/// Thread::start_searching() wakes up the thread that will start the search /// Thread::start_searching() wakes up the thread that will start the search
void Thread::start_searching() { void Thread::start_searching() {
@ -158,7 +161,8 @@ void ThreadPool::set(size_t requested) {
} }
} }
/// ThreadPool::clear() sets threadPool data to initial values.
/// ThreadPool::clear() sets threadPool data to initial values
void ThreadPool::clear() { void ThreadPool::clear() {
@ -170,6 +174,7 @@ void ThreadPool::clear() {
main()->previousTimeReduction = 1.0; main()->previousTimeReduction = 1.0;
} }
/// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and /// ThreadPool::start_thinking() wakes up main thread waiting in idle_loop() and
/// returns immediately. Main thread will wake up other threads and start the search. /// returns immediately. Main thread will wake up other threads and start the search.
@ -250,7 +255,8 @@ Thread* ThreadPool::get_best_thread() const {
return bestThread; return bestThread;
} }
/// Start non-main threads.
/// Start non-main threads
void ThreadPool::start_searching() { void ThreadPool::start_searching() {
@ -259,7 +265,8 @@ void ThreadPool::start_searching() {
th->start_searching(); th->start_searching();
} }
/// Wait for non-main threads.
/// Wait for non-main threads
void ThreadPool::wait_for_search_finished() const { void ThreadPool::wait_for_search_finished() const {

View file

@ -28,14 +28,14 @@
TimeManagement Time; // Our global time management object TimeManagement Time; // Our global time management object
/// init() is called at the beginning of the search and calculates the bounds
/// of time allowed for the current game ply. We currently support: /// TimeManagement::init() is called at the beginning of the search and calculates
// 1) x basetime (+z increment) /// the bounds of time allowed for the current game ply. We currently support:
// 2) x moves in y seconds (+z increment) // 1) x basetime (+ z increment)
// 2) x moves in y seconds (+ z increment)
void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) { void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
TimePoint minThinkingTime = TimePoint(Options["Minimum Thinking Time"]);
TimePoint moveOverhead = TimePoint(Options["Move Overhead"]); TimePoint moveOverhead = TimePoint(Options["Move Overhead"]);
TimePoint slowMover = TimePoint(Options["Slow Mover"]); TimePoint slowMover = TimePoint(Options["Slow Mover"]);
TimePoint npmsec = TimePoint(Options["nodestime"]); TimePoint npmsec = TimePoint(Options["nodestime"]);
@ -61,7 +61,7 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
startTime = limits.startTime; startTime = limits.startTime;
//Maximum move horizon of 50 moves // Maximum move horizon of 50 moves
int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50; int mtg = limits.movestogo ? std::min(limits.movestogo, 50) : 50;
// Make sure timeLeft is > 0 since we may use it as a divisor // Make sure timeLeft is > 0 since we may use it as a divisor
@ -91,7 +91,7 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
} }
// Never use more than 80% of the available time for this move // Never use more than 80% of the available time for this move
optimumTime = std::max(minThinkingTime, TimePoint(opt_scale * timeLeft)); optimumTime = TimePoint(opt_scale * timeLeft);
maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, max_scale * optimumTime)); maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, max_scale * optimumTime));
if (Options["Ponder"]) if (Options["Ponder"])

View file

@ -30,7 +30,7 @@
TranspositionTable TT; // Our global transposition table TranspositionTable TT; // Our global transposition table
/// TTEntry::save populates the TTEntry with a new node's data, possibly /// TTEntry::save() populates the TTEntry with a new node's data, possibly
/// overwriting an old position. Update is not atomic and can be racy. /// overwriting an old position. Update is not atomic and can be racy.
void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) { void TTEntry::save(Key k, Value v, bool pv, Bound b, Depth d, Move m, Value ev) {
@ -107,6 +107,7 @@ void TranspositionTable::clear() {
th.join(); th.join();
} }
/// TranspositionTable::probe() looks up the current position in the transposition /// TranspositionTable::probe() looks up the current position in the transposition
/// table. It returns true and a pointer to the TTEntry if the position is found. /// table. It returns true and a pointer to the TTEntry if the position is found.
/// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry /// Otherwise, it returns false and a pointer to an empty or least valuable TTEntry

View file

@ -60,8 +60,8 @@ private:
/// A TranspositionTable is an array of Cluster, of size clusterCount. Each /// A TranspositionTable is an array of Cluster, of size clusterCount. Each
/// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry /// cluster consists of ClusterSize number of TTEntry. Each non-empty TTEntry
/// contains information on exactly one position. The size of a Cluster should /// contains information on exactly one position. The size of a Cluster should
/// divide the size of a cache line for best performance, /// divide the size of a cache line for best performance, as the cacheline is
/// as the cacheline is prefetched when possible. /// prefetched when possible.
class TranspositionTable { class TranspositionTable {

View file

@ -70,7 +70,7 @@ static void make_option(const string& n, int v, const SetRange& r) {
Options[n] << UCI::Option(v, r(v).first, r(v).second, on_tune); Options[n] << UCI::Option(v, r(v).first, r(v).second, on_tune);
LastOption = &Options[n]; LastOption = &Options[n];
// Print formatted parameters, ready to be copy-pasted in fishtest // Print formatted parameters, ready to be copy-pasted in Fishtest
std::cout << n << "," std::cout << n << ","
<< v << "," << v << ","
<< r(v).first << "," << r(v).second << "," << r(v).first << "," << r(v).second << ","

View file

@ -356,16 +356,16 @@ constexpr Color operator~(Color c) {
return Color(c ^ BLACK); // Toggle color return Color(c ^ BLACK); // Toggle color
} }
constexpr Square flip_rank(Square s) { constexpr Square flip_rank(Square s) { // Swap A1 <-> A8
return Square(s ^ SQ_A8); return Square(s ^ SQ_A8);
} }
constexpr Square flip_file(Square s) { constexpr Square flip_file(Square s) { // Swap A1 <-> H1
return Square(s ^ SQ_H1); return Square(s ^ SQ_H1);
} }
constexpr Piece operator~(Piece pc) { constexpr Piece operator~(Piece pc) {
return Piece(pc ^ 8); // Swap color of piece B_KNIGHT -> W_KNIGHT return Piece(pc ^ 8); // Swap color of piece B_KNIGHT <-> W_KNIGHT
} }
constexpr CastlingRights operator&(Color c, CastlingRights cr) { constexpr CastlingRights operator&(Color c, CastlingRights cr) {

View file

@ -53,7 +53,7 @@ bool CaseInsensitiveLess::operator() (const string& s1, const string& s2) const
} }
/// init() initializes the UCI options to their hard-coded default values /// UCI::init() initializes the UCI options to their hard-coded default values
void init(OptionsMap& o) { void init(OptionsMap& o) {
@ -69,7 +69,6 @@ void init(OptionsMap& o) {
o["MultiPV"] << Option(1, 1, 500); o["MultiPV"] << Option(1, 1, 500);
o["Skill Level"] << Option(20, 0, 20); o["Skill Level"] << Option(20, 0, 20);
o["Move Overhead"] << Option(10, 0, 5000); o["Move Overhead"] << Option(10, 0, 5000);
o["Minimum Thinking Time"] << Option( 0, 0, 5000);
o["Slow Mover"] << Option(100, 10, 1000); o["Slow Mover"] << Option(100, 10, 1000);
o["nodestime"] << Option(0, 0, 10000); o["nodestime"] << Option(0, 0, 10000);
o["UCI_Chess960"] << Option(false); o["UCI_Chess960"] << Option(false);