diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..a431afa
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,65 @@
+BasedOnStyle: LLVM
+AccessModifierOffset: -4
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: None
+AlignOperands: Align
+AllowAllArgumentsOnNextLine: false
+AllowAllConstructorInitializersOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: Always
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: All
+AllowShortIfStatementsOnASingleLine: Always
+AllowShortLambdasOnASingleLine: All
+AllowShortLoopsOnASingleLine: true
+AlwaysBreakAfterReturnType: None
+AlwaysBreakTemplateDeclarations: Yes
+BreakBeforeBraces: Custom
+BraceWrapping:
+ AfterCaseLabel: false
+ AfterClass: false
+ AfterControlStatement: Never
+ AfterEnum: false
+ AfterFunction: false
+ AfterNamespace: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: false
+ SplitEmptyRecord: true
+BreakBeforeBinaryOperators: None
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializers: BeforeColon
+BreakInheritanceList: BeforeColon
+ColumnLimit: 0
+CompactNamespaces: false
+ContinuationIndentWidth: 8
+IndentCaseLabels: true
+IndentPPDirectives: None
+IndentWidth: 4
+KeepEmptyLinesAtTheStartOfBlocks: true
+MaxEmptyLinesToKeep: 2
+NamespaceIndentation: All
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: true
+PointerAlignment: Right
+ReflowComments: false
+SpaceAfterCStyleCast: true
+SpaceAfterLogicalNot: false
+SpaceAfterTemplateKeyword: false
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeCpp11BracedList: false
+SpaceBeforeCtorInitializerColon: true
+SpaceBeforeInheritanceColon: true
+SpaceBeforeParens: ControlStatements
+SpaceBeforeRangeBasedForLoopColon: true
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 0
+SpacesInAngles: Never
+SpacesInCStyleCastParentheses: false
+SpacesInContainerLiterals: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+TabWidth: 4
+UseTab: Never
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3f40bfc..e9914b5 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,34 +13,34 @@ jobs:
strategy:
matrix:
config:
- - {
- name: "Ubuntu g++ popcnt",
- os: ubuntu-latest,
- compiler: g++-11,
- arch: popcnt,
- target: BlackCore-popcnt-linux,
- }
- - {
- name: "Ubuntu g++ modern",
- os: ubuntu-latest,
- compiler: g++-11,
- arch: modern,
- target: BlackCore-modern-linux,
- }
- - {
- name: "Ubuntu g++ avx2",
- os: ubuntu-latest,
- compiler: g++-11,
- arch: avx2,
- target: BlackCore-avx2-linux,
- }
- - {
- name: "Ubuntu g++ bmi2",
- os: ubuntu-latest,
- compiler: g++-11,
- arch: bmi2,
- target: BlackCore-bmi2-linux,
- }
+ #- {
+ # name: "Ubuntu g++ popcnt",
+ # os: ubuntu-latest,
+ # compiler: g++-11,
+ # arch: popcnt,
+ # target: BlackCore-popcnt-linux,
+ #}
+ #- {
+ # name: "Ubuntu g++ modern",
+ # os: ubuntu-latest,
+ # compiler: g++-11,
+ # arch: modern,
+ # target: BlackCore-modern-linux,
+ #}
+ #- {
+ # name: "Ubuntu g++ avx2",
+ # os: ubuntu-latest,
+ # compiler: g++-11,
+ # arch: avx2,
+ # target: BlackCore-avx2-linux,
+ #}
+ #- {
+ # name: "Ubuntu g++ bmi2",
+ # os: ubuntu-latest,
+ # compiler: g++-11,
+ # arch: bmi2,
+ # target: BlackCore-bmi2-linux,
+ #}
- {
name: "Windows g++ popcnt",
os: windows-latest,
diff --git a/src/Makefile b/src/Makefile
index 522569f..3303477 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -2,7 +2,7 @@ CXX = g++
TARGET_FLAGS = -static -static-libgcc -static-libstdc++
ARCH=native
NAME = BlackCore
-VERSION_MAJOR = 2
+VERSION_MAJOR = 3
VERSION_MINOR = 0
OBJECT_DIR = objects
SOURCES := $(wildcard *.cpp)
@@ -14,7 +14,6 @@ else
uname_S := $(shell uname -s)
endif
-
ifeq ($(uname_S), Windows)
SUFFIX = .exe
else
@@ -44,8 +43,8 @@ ifeq ($(ARCH), popcnt)
ARCH_FLAGS = -march=x86-64 -mpopcnt
endif
-CXXFLAGS = -std=c++20 -O3 -flto -pthread -Wall -Wno-class-memaccess $(DEFINE_FLAGS) $(ARCH_FLAGS)
-EXE = $(NAME)_v$(VERSION_MAJOR)-$(VERSION_MINOR)$(SUFFIX)
+CXXFLAGS = -std=c++20 -O3 -flto -pthread -Wall -Wno-class-memaccess -DVERSION=\"v$(VERSION_MAJOR).$(VERSION_MINOR)\" $(DEFINE_FLAGS) $(ARCH_FLAGS)
+EXE = $(NAME)-v$(VERSION_MAJOR)-$(VERSION_MINOR)$(SUFFIX)
default: $(EXE)
diff --git a/src/bench.cpp b/src/bench.cpp
index eb956cc..08d05d9 100644
--- a/src/bench.cpp
+++ b/src/bench.cpp
@@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
-#include
-#include
-#include
#include "bench.h"
-#include "tt.h"
#include "search.h"
#include "timeman.h"
+#include "tt.h"
+#include
+#include
+#include
+#include
struct TestPosition {
std::string fen;
@@ -31,25 +31,24 @@ struct TestPosition {
const unsigned int posCount = 10;
-const unsigned int searchTestHashSize = 16;
+const unsigned int searchTestHashSize = 32;
-const Depth SEARCH_DEPTH = 13;
+const Depth SEARCH_DEPTH = 15;
const TestPosition testPositions[posCount] = {
// Positions from CPW
- {"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 ", 6, 119060324},
- {"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - ", 5, 193690690},
- {"8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -", 7, 178633661},
- {"r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1", 5, 15833292},
- {"r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1 ", 5, 15833292},
- {"rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8 ", 5, 89941194},
+ {"rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 ", 6, 119060324},
+ {"r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - ", 5, 193690690},
+ {"8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - -", 7, 178633661},
+ {"r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1", 5, 15833292},
+ {"r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1 ", 5, 15833292},
+ {"rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8 ", 5, 89941194},
{"r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10 ", 5, 164075551},
// Own positions
- {"r3kb1r/1p3ppp/pqn1pn2/1Bpp1b2/3P1B2/1QP1PN2/PP1N1PPP/R3K2R w KQkq - 0 9", 5, 140824446},
- {"rnb1k2r/pppp1ppp/5q2/2b5/2BNP3/2N5/PPP2KPP/R1BQ3R w kq - 1 8", 5, 19782759},
- {"8/pp5p/8/2p2kp1/2Pp4/3P1KPP/PP6/8 w - - 0 32", 7, 13312960}
-};
+ {"r3kb1r/1p3ppp/pqn1pn2/1Bpp1b2/3P1B2/1QP1PN2/PP1N1PPP/R3K2R w KQkq - 0 9", 5, 140824446},
+ {"rnb1k2r/pppp1ppp/5q2/2b5/2BNP3/2N5/PPP2KPP/R1BQ3R w kq - 1 8", 5, 19782759},
+ {"8/pp5p/8/2p2kp1/2Pp4/3P1KPP/PP6/8 w - - 0 32", 7, 13312960}};
void testPerft() {
initSearch();
@@ -71,7 +70,8 @@ void testPerft() {
U64 nps = totalNodes * 1000 / elapsedTime;
if (ok) {
- std::cout << "PERFT OK\n" << totalNodes << " nodes " << nps << " nps" << std::endl;
+ std::cout << "PERFT OK\n"
+ << totalNodes << " nodes " << nps << " nps" << std::endl;
} else {
std::cout << "PERFT FAILED" << std::endl;
exit(1);
@@ -82,13 +82,20 @@ void testSearch() {
initSearch();
ttResize(searchTestHashSize);
- startSearch(0, 0, 0, 0);
+ U64 totalNodes = 0;
+ U64 nps;
+
for (const TestPosition &tPos : testPositions) {
ttClear();
Position pos = {tPos.fen};
- std::atomic a;
- iterativeDeepening(pos, SEARCH_DEPTH, false, std::ref(a));
+ SearchInfo info;
+ info.maxDepth = SEARCH_DEPTH;
+ info.uciMode = false;
+ startSearch(info, pos, 1);
+ joinThread(true);
+ totalNodes += nodeCount;
+ nps += getNps();
}
- std::cout << nodeCount << " nodes " << getNps() << " nps" << std::endl;
+ std::cout << totalNodes << " nodes " << nps / posCount << " nps" << std::endl;
}
diff --git a/src/bench.h b/src/bench.h
index 3c5e280..a2be07b 100644
--- a/src/bench.h
+++ b/src/bench.h
@@ -20,11 +20,14 @@
#include "movegen.h"
+#include
+
template
U64 perft(Position &position, Depth depth) {
Move moves[200];
Move *movesEnd = generateMoves(position, moves, false);
- if (depth == 1) return movesEnd - moves;
+ if (depth == 1)
+ return movesEnd - moves;
U64 nodes = 0;
for (Move *it = moves; it != movesEnd; it++) {
position.makeMove(*it);
@@ -42,4 +45,4 @@ void testPerft();
void testSearch();
-#endif //BLACKCORE_BENCH_H
+#endif//BLACKCORE_BENCH_H
diff --git a/src/bitboard.cpp b/src/bitboard.cpp
index ef3d805..fb5605a 100644
--- a/src/bitboard.cpp
+++ b/src/bitboard.cpp
@@ -14,13 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
-#include
#include "bitboard.h"
#include "utils.h"
+#include
+#include
-Bitboard bitMasks[64], pawnMasks[64][2], knightMasks[64], kingMasks[64], fileMasks[64], rankMasks[64], rookMasks[64], diagonalMasks[64], antiDiagonalMasks[64], bishopMasks[64],
- rookAttackTable[102400], bishopAttackTable[5248], commonRay[64][64], adjacentFileMasks[64], adjacentNorthMasks[64], adjacentSouthMasks[64];
+Bitboard bitMasks[64], pawnMasks[64][2], knightMasks[64], kingMasks[64], fileMasks[64], rankMasks[64], rookMasks[64],
+ diagonalMasks[64], antiDiagonalMasks[64], bishopMasks[64],
+ rookAttackTable[102400], bishopAttackTable[5248], commonRay[64][64], adjacentFileMasks[64], adjacentNorthMasks[64],
+ adjacentSouthMasks[64];
LineType lineType[64][64];
void initBitboard() {
@@ -67,7 +69,8 @@ void initBitboard() {
~fileMask(sq) & (adjacentNorthMasks[sq] | adjacentSouthMasks[sq] | step(sq) | step(sq));
for (Square sq2 = A1; sq2 < 64; sq2 += 1) {
- if (sq == sq2) continue;
+ if (sq == sq2)
+ continue;
for (Direction dir : DIRECTIONS) {
Bitboard value = slide(dir, sq) & slide(-dir, sq2);
@@ -101,7 +104,6 @@ void initBitboard() {
initMagic(rookMagics, ROOK);
initMagic(bishopMagics, BISHOP);
-
}
Bitboard slidingAttacks(Square square, Bitboard occupied, PieceType type) {
@@ -160,8 +162,10 @@ void findMagics(Bitboard *attackTable, Magic *magics, PieceType type) {
magic.mask = slidingAttacks(square, 0, type) & ~edge;
magic.shift = magic.mask.popCount();
- if (square == A1) magic.ptr = attackTable;
- else magic.ptr = magics[square - 1].ptr + length;
+ if (square == A1)
+ magic.ptr = attackTable;
+ else
+ magic.ptr = magics[square - 1].ptr + length;
// Carry-Ripler trick for reference check out: https://www.chessprogramming.org/Traversing_Subsets_of_a_Set
length = 0;
@@ -178,7 +182,8 @@ void findMagics(Bitboard *attackTable, Magic *magics, PieceType type) {
while (true) {
magic.magic = randBB() & randBB() & randBB();
- if (((magic.magic * magic.mask) >> 56).popCount() < 6) continue;
+ if (((magic.magic * magic.mask) >> 56).popCount() < 6)
+ continue;
std::memset(used, 0, sizeof(used));
@@ -204,7 +209,6 @@ void findMagics(Bitboard *attackTable, Magic *magics, PieceType type) {
std::cout << " {bishopAttackTable + " << magic.ptr - bishopAttackTable << ", " << BBToHex(magic.mask)
<< ", "
<< BBToHex(magic.magic) << ", " << magic.shift << "},\n";
-
}
std::cout << "};\n";
diff --git a/src/bitboard.h b/src/bitboard.h
index 7f963c9..31f7cc1 100644
--- a/src/bitboard.h
+++ b/src/bitboard.h
@@ -17,9 +17,9 @@
#ifndef BLACKCORE_BITBOARD_H
#define BLACKCORE_BITBOARD_H
+#include "constants.h"
#include
#include
-#include "constants.h"
#ifdef _MSC_VER
#include
@@ -30,26 +30,33 @@ struct Bitboard {
U64 bb = 0;
- constexpr Bitboard(U64 value) { bb = value; }
+ constexpr Bitboard(U64 value) {
+ bb = value;
+ }
inline Bitboard(Square square);
constexpr Bitboard() = default;
- constexpr bool get(Square square) const { return (bb >> square) & 1; }
+ constexpr bool get(Square square) const {
+ return (bb >> square) & 1;
+ }
- constexpr void set(Square square) { bb |= 1ULL << square; }
+ constexpr void set(Square square) {
+ bb |= 1ULL << square;
+ }
- constexpr void clear(Square square) { bb &= ~(1ULL << square); }
+ constexpr void clear(Square square) {
+ bb &= ~(1ULL << square);
+ }
constexpr int popCount() const {
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
- return (int)_mm_popcnt_u64(bb);
+ return (int) _mm_popcnt_u64(bb);
#else
return __builtin_popcountll(bb);
#endif
-
}
constexpr Square lsb() const {
@@ -63,7 +70,6 @@ struct Bitboard {
#else
#error "Unsupported compiler!"
#endif
-
}
constexpr Square popLsb() {
@@ -72,41 +78,77 @@ struct Bitboard {
return square;
}
- constexpr Bitboard operator*(Bitboard a) const { return bb * a.bb; }
+ constexpr Bitboard operator*(Bitboard a) const {
+ return bb * a.bb;
+ }
- constexpr bool operator==(Bitboard a) const { return bb == a.bb; }
+ constexpr bool operator==(Bitboard a) const {
+ return bb == a.bb;
+ }
- constexpr bool operator!=(Bitboard a) const { return bb != a.bb; }
+ constexpr bool operator!=(Bitboard a) const {
+ return bb != a.bb;
+ }
- constexpr Bitboard operator+(Bitboard a) const { return bb + a.bb; }
+ constexpr Bitboard operator+(Bitboard a) const {
+ return bb + a.bb;
+ }
- constexpr Bitboard operator-(Bitboard a) const { return bb - a.bb; }
+ constexpr Bitboard operator-(Bitboard a) const {
+ return bb - a.bb;
+ }
- constexpr Bitboard operator&(Bitboard a) const { return bb & a.bb; }
+ constexpr Bitboard operator&(Bitboard a) const {
+ return bb & a.bb;
+ }
- constexpr Bitboard operator|(Bitboard a) const { return bb | a.bb; }
+ constexpr Bitboard operator|(Bitboard a) const {
+ return bb | a.bb;
+ }
- constexpr Bitboard operator^(Bitboard a) const { return bb ^ a.bb; }
+ constexpr Bitboard operator^(Bitboard a) const {
+ return bb ^ a.bb;
+ }
- constexpr Bitboard operator~() const { return ~bb; }
+ constexpr Bitboard operator~() const {
+ return ~bb;
+ }
- constexpr Bitboard operator<<(const unsigned int a) const { return bb << a; }
+ constexpr Bitboard operator<<(const unsigned int a) const {
+ return bb << a;
+ }
- constexpr Bitboard operator>>(const unsigned int a) const { return bb >> a; }
+ constexpr Bitboard operator>>(const unsigned int a) const {
+ return bb >> a;
+ }
- constexpr void operator&=(Bitboard a) { bb &= a.bb; }
+ constexpr void operator&=(Bitboard a) {
+ bb &= a.bb;
+ }
- constexpr void operator|=(Bitboard a) { bb |= a.bb; }
+ constexpr void operator|=(Bitboard a) {
+ bb |= a.bb;
+ }
- constexpr void operator^=(Bitboard a) { bb ^= a.bb; }
+ constexpr void operator^=(Bitboard a) {
+ bb ^= a.bb;
+ }
- constexpr void operator<<=(const unsigned int a) { bb <<= a; }
+ constexpr void operator<<=(const unsigned int a) {
+ bb <<= a;
+ }
- constexpr void operator>>=(const unsigned int a) { bb >>= a; }
+ constexpr void operator>>=(const unsigned int a) {
+ bb >>= a;
+ }
- constexpr explicit operator bool() const { return bb; }
+ constexpr explicit operator bool() const {
+ return bb;
+ }
- constexpr explicit operator U64() const { return bb; }
+ constexpr explicit operator U64() const {
+ return bb;
+ }
};
struct Magic {
@@ -123,137 +165,137 @@ extern Bitboard bishopAttackTable[5248];
// To generate the attackTables from them use initMagic
// To generate new magic numbers use findMagics
constexpr Magic rookMagics[64] = {
- {rookAttackTable + 0, 0x101010101017eULL, 0x200102084420100ULL, 12},
- {rookAttackTable + 4096, 0x202020202027cULL, 0x40200040001000ULL, 11},
- {rookAttackTable + 6144, 0x404040404047aULL, 0x4100082000104300ULL, 11},
- {rookAttackTable + 8192, 0x8080808080876ULL, 0x480049000080080ULL, 11},
- {rookAttackTable + 10240, 0x1010101010106eULL, 0x100040211000800ULL, 11},
- {rookAttackTable + 12288, 0x2020202020205eULL, 0x2500240002080100ULL, 11},
- {rookAttackTable + 14336, 0x4040404040403eULL, 0x280120001000080ULL, 11},
- {rookAttackTable + 16384, 0x8080808080807eULL, 0x200004086002b04ULL, 12},
- {rookAttackTable + 20480, 0x1010101017e00ULL, 0x401800280400020ULL, 11},
- {rookAttackTable + 22528, 0x2020202027c00ULL, 0x8601400050002000ULL, 10},
- {rookAttackTable + 23552, 0x4040404047a00ULL, 0x802801000200280ULL, 10},
- {rookAttackTable + 24576, 0x8080808087600ULL, 0x411001001002008ULL, 10},
- {rookAttackTable + 25600, 0x10101010106e00ULL, 0x11000410080300ULL, 10},
- {rookAttackTable + 26624, 0x20202020205e00ULL, 0x20a000804108200ULL, 10},
- {rookAttackTable + 27648, 0x40404040403e00ULL, 0x84006850240102ULL, 10},
- {rookAttackTable + 28672, 0x80808080807e00ULL, 0x24800049000080ULL, 11},
- {rookAttackTable + 30720, 0x10101017e0100ULL, 0x208000400080ULL, 11},
- {rookAttackTable + 32768, 0x20202027c0200ULL, 0x101020020804202ULL, 10},
- {rookAttackTable + 33792, 0x40404047a0400ULL, 0x20828010022000ULL, 10},
- {rookAttackTable + 34816, 0x8080808760800ULL, 0x801230009001000ULL, 10},
- {rookAttackTable + 35840, 0x101010106e1000ULL, 0x5608808004020801ULL, 10},
- {rookAttackTable + 36864, 0x202020205e2000ULL, 0x3086008080040002ULL, 10},
- {rookAttackTable + 37888, 0x404040403e4000ULL, 0x40041221008ULL, 10},
- {rookAttackTable + 38912, 0x808080807e8000ULL, 0x8000020000811044ULL, 11},
- {rookAttackTable + 40960, 0x101017e010100ULL, 0x21c00180002081ULL, 11},
- {rookAttackTable + 43008, 0x202027c020200ULL, 0xa010024140002000ULL, 10},
- {rookAttackTable + 44032, 0x404047a040400ULL, 0x1040200280100080ULL, 10},
- {rookAttackTable + 45056, 0x8080876080800ULL, 0x2100100200b00ULL, 10},
- {rookAttackTable + 46080, 0x1010106e101000ULL, 0x8014008080040800ULL, 10},
- {rookAttackTable + 47104, 0x2020205e202000ULL, 0x840200120008904cULL, 10},
- {rookAttackTable + 48128, 0x4040403e404000ULL, 0x10020400811058ULL, 10},
- {rookAttackTable + 49152, 0x8080807e808000ULL, 0x8280040200004081ULL, 11},
- {rookAttackTable + 51200, 0x1017e01010100ULL, 0xa000408001002100ULL, 11},
- {rookAttackTable + 53248, 0x2027c02020200ULL, 0x210904000802000ULL, 10},
- {rookAttackTable + 54272, 0x4047a04040400ULL, 0x200204082001200ULL, 10},
- {rookAttackTable + 55296, 0x8087608080800ULL, 0x2204201042000a00ULL, 10},
- {rookAttackTable + 56320, 0x10106e10101000ULL, 0x6c80040801001100ULL, 10},
- {rookAttackTable + 57344, 0x20205e20202000ULL, 0x8040080800200ULL, 10},
- {rookAttackTable + 58368, 0x40403e40404000ULL, 0x2b0900804001663ULL, 10},
- {rookAttackTable + 59392, 0x80807e80808000ULL, 0x4074800040800100ULL, 11},
- {rookAttackTable + 61440, 0x17e0101010100ULL, 0x4000400080208000ULL, 11},
- {rookAttackTable + 63488, 0x27c0202020200ULL, 0x1a40500020004001ULL, 10},
- {rookAttackTable + 64512, 0x47a0404040400ULL, 0x1004020010018ULL, 10},
- {rookAttackTable + 65536, 0x8760808080800ULL, 0x20201200420008ULL, 10},
- {rookAttackTable + 66560, 0x106e1010101000ULL, 0xc24008008008005ULL, 10},
- {rookAttackTable + 67584, 0x205e2020202000ULL, 0x4002010804020010ULL, 10},
- {rookAttackTable + 68608, 0x403e4040404000ULL, 0xb015081002040001ULL, 10},
- {rookAttackTable + 69632, 0x807e8080808000ULL, 0x4000408c020029ULL, 11},
- {rookAttackTable + 71680, 0x7e010101010100ULL, 0xb840004020800080ULL, 11},
- {rookAttackTable + 73728, 0x7c020202020200ULL, 0x60804001002100ULL, 10},
- {rookAttackTable + 74752, 0x7a040404040400ULL, 0x210810a285420200ULL, 10},
- {rookAttackTable + 75776, 0x76080808080800ULL, 0xa000080010008080ULL, 10},
- {rookAttackTable + 76800, 0x6e101010101000ULL, 0x800050010080100ULL, 10},
- {rookAttackTable + 77824, 0x5e202020202000ULL, 0x4040002008080ULL, 10},
- {rookAttackTable + 78848, 0x3e404040404000ULL, 0x80b4011042080400ULL, 10},
- {rookAttackTable + 79872, 0x7e808080808000ULL, 0x6014004114008200ULL, 11},
+ {rookAttackTable + 0, 0x101010101017eULL, 0x200102084420100ULL, 12},
+ {rookAttackTable + 4096, 0x202020202027cULL, 0x40200040001000ULL, 11},
+ {rookAttackTable + 6144, 0x404040404047aULL, 0x4100082000104300ULL, 11},
+ {rookAttackTable + 8192, 0x8080808080876ULL, 0x480049000080080ULL, 11},
+ {rookAttackTable + 10240, 0x1010101010106eULL, 0x100040211000800ULL, 11},
+ {rookAttackTable + 12288, 0x2020202020205eULL, 0x2500240002080100ULL, 11},
+ {rookAttackTable + 14336, 0x4040404040403eULL, 0x280120001000080ULL, 11},
+ {rookAttackTable + 16384, 0x8080808080807eULL, 0x200004086002b04ULL, 12},
+ {rookAttackTable + 20480, 0x1010101017e00ULL, 0x401800280400020ULL, 11},
+ {rookAttackTable + 22528, 0x2020202027c00ULL, 0x8601400050002000ULL, 10},
+ {rookAttackTable + 23552, 0x4040404047a00ULL, 0x802801000200280ULL, 10},
+ {rookAttackTable + 24576, 0x8080808087600ULL, 0x411001001002008ULL, 10},
+ {rookAttackTable + 25600, 0x10101010106e00ULL, 0x11000410080300ULL, 10},
+ {rookAttackTable + 26624, 0x20202020205e00ULL, 0x20a000804108200ULL, 10},
+ {rookAttackTable + 27648, 0x40404040403e00ULL, 0x84006850240102ULL, 10},
+ {rookAttackTable + 28672, 0x80808080807e00ULL, 0x24800049000080ULL, 11},
+ {rookAttackTable + 30720, 0x10101017e0100ULL, 0x208000400080ULL, 11},
+ {rookAttackTable + 32768, 0x20202027c0200ULL, 0x101020020804202ULL, 10},
+ {rookAttackTable + 33792, 0x40404047a0400ULL, 0x20828010022000ULL, 10},
+ {rookAttackTable + 34816, 0x8080808760800ULL, 0x801230009001000ULL, 10},
+ {rookAttackTable + 35840, 0x101010106e1000ULL, 0x5608808004020801ULL, 10},
+ {rookAttackTable + 36864, 0x202020205e2000ULL, 0x3086008080040002ULL, 10},
+ {rookAttackTable + 37888, 0x404040403e4000ULL, 0x40041221008ULL, 10},
+ {rookAttackTable + 38912, 0x808080807e8000ULL, 0x8000020000811044ULL, 11},
+ {rookAttackTable + 40960, 0x101017e010100ULL, 0x21c00180002081ULL, 11},
+ {rookAttackTable + 43008, 0x202027c020200ULL, 0xa010024140002000ULL, 10},
+ {rookAttackTable + 44032, 0x404047a040400ULL, 0x1040200280100080ULL, 10},
+ {rookAttackTable + 45056, 0x8080876080800ULL, 0x2100100200b00ULL, 10},
+ {rookAttackTable + 46080, 0x1010106e101000ULL, 0x8014008080040800ULL, 10},
+ {rookAttackTable + 47104, 0x2020205e202000ULL, 0x840200120008904cULL, 10},
+ {rookAttackTable + 48128, 0x4040403e404000ULL, 0x10020400811058ULL, 10},
+ {rookAttackTable + 49152, 0x8080807e808000ULL, 0x8280040200004081ULL, 11},
+ {rookAttackTable + 51200, 0x1017e01010100ULL, 0xa000408001002100ULL, 11},
+ {rookAttackTable + 53248, 0x2027c02020200ULL, 0x210904000802000ULL, 10},
+ {rookAttackTable + 54272, 0x4047a04040400ULL, 0x200204082001200ULL, 10},
+ {rookAttackTable + 55296, 0x8087608080800ULL, 0x2204201042000a00ULL, 10},
+ {rookAttackTable + 56320, 0x10106e10101000ULL, 0x6c80040801001100ULL, 10},
+ {rookAttackTable + 57344, 0x20205e20202000ULL, 0x8040080800200ULL, 10},
+ {rookAttackTable + 58368, 0x40403e40404000ULL, 0x2b0900804001663ULL, 10},
+ {rookAttackTable + 59392, 0x80807e80808000ULL, 0x4074800040800100ULL, 11},
+ {rookAttackTable + 61440, 0x17e0101010100ULL, 0x4000400080208000ULL, 11},
+ {rookAttackTable + 63488, 0x27c0202020200ULL, 0x1a40500020004001ULL, 10},
+ {rookAttackTable + 64512, 0x47a0404040400ULL, 0x1004020010018ULL, 10},
+ {rookAttackTable + 65536, 0x8760808080800ULL, 0x20201200420008ULL, 10},
+ {rookAttackTable + 66560, 0x106e1010101000ULL, 0xc24008008008005ULL, 10},
+ {rookAttackTable + 67584, 0x205e2020202000ULL, 0x4002010804020010ULL, 10},
+ {rookAttackTable + 68608, 0x403e4040404000ULL, 0xb015081002040001ULL, 10},
+ {rookAttackTable + 69632, 0x807e8080808000ULL, 0x4000408c020029ULL, 11},
+ {rookAttackTable + 71680, 0x7e010101010100ULL, 0xb840004020800080ULL, 11},
+ {rookAttackTable + 73728, 0x7c020202020200ULL, 0x60804001002100ULL, 10},
+ {rookAttackTable + 74752, 0x7a040404040400ULL, 0x210810a285420200ULL, 10},
+ {rookAttackTable + 75776, 0x76080808080800ULL, 0xa000080010008080ULL, 10},
+ {rookAttackTable + 76800, 0x6e101010101000ULL, 0x800050010080100ULL, 10},
+ {rookAttackTable + 77824, 0x5e202020202000ULL, 0x4040002008080ULL, 10},
+ {rookAttackTable + 78848, 0x3e404040404000ULL, 0x80b4011042080400ULL, 10},
+ {rookAttackTable + 79872, 0x7e808080808000ULL, 0x6014004114008200ULL, 11},
{rookAttackTable + 81920, 0x7e01010101010100ULL, 0x1001002018408202ULL, 12},
- {rookAttackTable + 86016, 0x7c02020202020200ULL, 0x2400104128421ULL, 11},
- {rookAttackTable + 88064, 0x7a04040404040400ULL, 0x407600010408901ULL, 11},
+ {rookAttackTable + 86016, 0x7c02020202020200ULL, 0x2400104128421ULL, 11},
+ {rookAttackTable + 88064, 0x7a04040404040400ULL, 0x407600010408901ULL, 11},
{rookAttackTable + 90112, 0x7608080808080800ULL, 0x108448a01001000dULL, 11},
{rookAttackTable + 92160, 0x6e10101010101000ULL, 0x8402011008842002ULL, 11},
- {rookAttackTable + 94208, 0x5e20202020202000ULL, 0x11000204000801ULL, 11},
+ {rookAttackTable + 94208, 0x5e20202020202000ULL, 0x11000204000801ULL, 11},
{rookAttackTable + 96256, 0x3e40404040404000ULL, 0x4026000108208452ULL, 11},
- {rookAttackTable + 98304, 0x7e80808080808000ULL, 0x800081004c2c06ULL, 12},
+ {rookAttackTable + 98304, 0x7e80808080808000ULL, 0x800081004c2c06ULL, 12},
};
constexpr Magic bishopMagics[64] = {
- {bishopAttackTable + 0, 0x40201008040200ULL, 0x4100216240212ULL, 6},
- {bishopAttackTable + 64, 0x402010080400ULL, 0x8080110420002ULL, 5},
- {bishopAttackTable + 96, 0x4020100a00ULL, 0x4280091000005ULL, 5},
- {bishopAttackTable + 128, 0x40221400ULL, 0x24410020801400ULL, 5},
- {bishopAttackTable + 160, 0x2442800ULL, 0x4242000000311ULL, 5},
- {bishopAttackTable + 192, 0x204085000ULL, 0x882021006148000ULL, 5},
- {bishopAttackTable + 224, 0x20408102000ULL, 0xb440a0210260800ULL, 5},
- {bishopAttackTable + 256, 0x2040810204000ULL, 0x80840c0a011c00ULL, 6},
- {bishopAttackTable + 320, 0x20100804020000ULL, 0x1000040488080100ULL, 5},
- {bishopAttackTable + 352, 0x40201008040000ULL, 0x800a200202284112ULL, 5},
- {bishopAttackTable + 384, 0x4020100a0000ULL, 0xcc00098401020000ULL, 5},
- {bishopAttackTable + 416, 0x4022140000ULL, 0x8000080a00202000ULL, 5},
- {bishopAttackTable + 448, 0x244280000ULL, 0x8821210000824ULL, 5},
- {bishopAttackTable + 480, 0x20408500000ULL, 0xc000088230400020ULL, 5},
- {bishopAttackTable + 512, 0x2040810200000ULL, 0x2904494808a41024ULL, 5},
- {bishopAttackTable + 544, 0x4081020400000ULL, 0x2302882301004ULL, 5},
- {bishopAttackTable + 576, 0x10080402000200ULL, 0x910200610100104ULL, 5},
- {bishopAttackTable + 608, 0x20100804000400ULL, 0x910800850008080ULL, 5},
- {bishopAttackTable + 640, 0x4020100a000a00ULL, 0x30080010004d4009ULL, 7},
- {bishopAttackTable + 768, 0x402214001400ULL, 0x4108000c20222001ULL, 7},
- {bishopAttackTable + 896, 0x24428002800ULL, 0x22000400942005ULL, 7},
- {bishopAttackTable + 1024, 0x2040850005000ULL, 0xa021100512400ULL, 7},
- {bishopAttackTable + 1152, 0x4081020002000ULL, 0xa001000041301024ULL, 5},
- {bishopAttackTable + 1184, 0x8102040004000ULL, 0x8000420206021981ULL, 5},
- {bishopAttackTable + 1216, 0x8040200020400ULL, 0x1008480004606800ULL, 5},
- {bishopAttackTable + 1248, 0x10080400040800ULL, 0x4a8280003100100ULL, 5},
- {bishopAttackTable + 1280, 0x20100a000a1000ULL, 0x3480010182240ULL, 7},
+ {bishopAttackTable + 0, 0x40201008040200ULL, 0x4100216240212ULL, 6},
+ {bishopAttackTable + 64, 0x402010080400ULL, 0x8080110420002ULL, 5},
+ {bishopAttackTable + 96, 0x4020100a00ULL, 0x4280091000005ULL, 5},
+ {bishopAttackTable + 128, 0x40221400ULL, 0x24410020801400ULL, 5},
+ {bishopAttackTable + 160, 0x2442800ULL, 0x4242000000311ULL, 5},
+ {bishopAttackTable + 192, 0x204085000ULL, 0x882021006148000ULL, 5},
+ {bishopAttackTable + 224, 0x20408102000ULL, 0xb440a0210260800ULL, 5},
+ {bishopAttackTable + 256, 0x2040810204000ULL, 0x80840c0a011c00ULL, 6},
+ {bishopAttackTable + 320, 0x20100804020000ULL, 0x1000040488080100ULL, 5},
+ {bishopAttackTable + 352, 0x40201008040000ULL, 0x800a200202284112ULL, 5},
+ {bishopAttackTable + 384, 0x4020100a0000ULL, 0xcc00098401020000ULL, 5},
+ {bishopAttackTable + 416, 0x4022140000ULL, 0x8000080a00202000ULL, 5},
+ {bishopAttackTable + 448, 0x244280000ULL, 0x8821210000824ULL, 5},
+ {bishopAttackTable + 480, 0x20408500000ULL, 0xc000088230400020ULL, 5},
+ {bishopAttackTable + 512, 0x2040810200000ULL, 0x2904494808a41024ULL, 5},
+ {bishopAttackTable + 544, 0x4081020400000ULL, 0x2302882301004ULL, 5},
+ {bishopAttackTable + 576, 0x10080402000200ULL, 0x910200610100104ULL, 5},
+ {bishopAttackTable + 608, 0x20100804000400ULL, 0x910800850008080ULL, 5},
+ {bishopAttackTable + 640, 0x4020100a000a00ULL, 0x30080010004d4009ULL, 7},
+ {bishopAttackTable + 768, 0x402214001400ULL, 0x4108000c20222001ULL, 7},
+ {bishopAttackTable + 896, 0x24428002800ULL, 0x22000400942005ULL, 7},
+ {bishopAttackTable + 1024, 0x2040850005000ULL, 0xa021100512400ULL, 7},
+ {bishopAttackTable + 1152, 0x4081020002000ULL, 0xa001000041301024ULL, 5},
+ {bishopAttackTable + 1184, 0x8102040004000ULL, 0x8000420206021981ULL, 5},
+ {bishopAttackTable + 1216, 0x8040200020400ULL, 0x1008480004606800ULL, 5},
+ {bishopAttackTable + 1248, 0x10080400040800ULL, 0x4a8280003100100ULL, 5},
+ {bishopAttackTable + 1280, 0x20100a000a1000ULL, 0x3480010182240ULL, 7},
{bishopAttackTable + 1408, 0x40221400142200ULL, 0x2048080102820042ULL, 9},
- {bishopAttackTable + 1920, 0x2442800284400ULL, 0x4001020004008400ULL, 9},
- {bishopAttackTable + 2432, 0x4085000500800ULL, 0x204004048080200ULL, 7},
- {bishopAttackTable + 2560, 0x8102000201000ULL, 0x2008200040212a0ULL, 5},
- {bishopAttackTable + 2592, 0x10204000402000ULL, 0x10c013002430400ULL, 5},
- {bishopAttackTable + 2624, 0x4020002040800ULL, 0x4300a5082214480ULL, 5},
- {bishopAttackTable + 2656, 0x8040004081000ULL, 0x401041000215900ULL, 5},
- {bishopAttackTable + 2688, 0x100a000a102000ULL, 0x104804048040408ULL, 7},
- {bishopAttackTable + 2816, 0x22140014224000ULL, 0x800400808208200ULL, 9},
- {bishopAttackTable + 3328, 0x44280028440200ULL, 0x8002400054101ULL, 9},
- {bishopAttackTable + 3840, 0x8500050080400ULL, 0x2001004502020102ULL, 7},
+ {bishopAttackTable + 1920, 0x2442800284400ULL, 0x4001020004008400ULL, 9},
+ {bishopAttackTable + 2432, 0x4085000500800ULL, 0x204004048080200ULL, 7},
+ {bishopAttackTable + 2560, 0x8102000201000ULL, 0x2008200040212a0ULL, 5},
+ {bishopAttackTable + 2592, 0x10204000402000ULL, 0x10c013002430400ULL, 5},
+ {bishopAttackTable + 2624, 0x4020002040800ULL, 0x4300a5082214480ULL, 5},
+ {bishopAttackTable + 2656, 0x8040004081000ULL, 0x401041000215900ULL, 5},
+ {bishopAttackTable + 2688, 0x100a000a102000ULL, 0x104804048040408ULL, 7},
+ {bishopAttackTable + 2816, 0x22140014224000ULL, 0x800400808208200ULL, 9},
+ {bishopAttackTable + 3328, 0x44280028440200ULL, 0x8002400054101ULL, 9},
+ {bishopAttackTable + 3840, 0x8500050080400ULL, 0x2001004502020102ULL, 7},
{bishopAttackTable + 3968, 0x10200020100800ULL, 0x1988080110006100ULL, 5},
{bishopAttackTable + 4000, 0x20400040201000ULL, 0x1282009200102201ULL, 5},
- {bishopAttackTable + 4032, 0x2000204081000ULL, 0xa208010420001280ULL, 5},
- {bishopAttackTable + 4064, 0x4000408102000ULL, 0x4004010809000200ULL, 5},
- {bishopAttackTable + 4096, 0xa000a10204000ULL, 0x43008150006100ULL, 7},
- {bishopAttackTable + 4224, 0x14001422400000ULL, 0x2410145000801ULL, 7},
- {bishopAttackTable + 4352, 0x28002844020000ULL, 0x280104006040ULL, 7},
- {bishopAttackTable + 4480, 0x50005008040200ULL, 0x4012042000902ULL, 7},
- {bishopAttackTable + 4608, 0x20002010080400ULL, 0x28100482080a82ULL, 5},
+ {bishopAttackTable + 4032, 0x2000204081000ULL, 0xa208010420001280ULL, 5},
+ {bishopAttackTable + 4064, 0x4000408102000ULL, 0x4004010809000200ULL, 5},
+ {bishopAttackTable + 4096, 0xa000a10204000ULL, 0x43008150006100ULL, 7},
+ {bishopAttackTable + 4224, 0x14001422400000ULL, 0x2410145000801ULL, 7},
+ {bishopAttackTable + 4352, 0x28002844020000ULL, 0x280104006040ULL, 7},
+ {bishopAttackTable + 4480, 0x50005008040200ULL, 0x4012042000902ULL, 7},
+ {bishopAttackTable + 4608, 0x20002010080400ULL, 0x28100482080a82ULL, 5},
{bishopAttackTable + 4640, 0x40004020100800ULL, 0x80040c2400240240ULL, 5},
- {bishopAttackTable + 4672, 0x20408102000ULL, 0x80c1101101044a0ULL, 5},
- {bishopAttackTable + 4704, 0x40810204000ULL, 0x180804802310808ULL, 5},
- {bishopAttackTable + 4736, 0xa1020400000ULL, 0x8048080064ULL, 5},
- {bishopAttackTable + 4768, 0x142240000000ULL, 0x8c8400020880000ULL, 5},
- {bishopAttackTable + 4800, 0x284402000000ULL, 0x30001010020a2000ULL, 5},
- {bishopAttackTable + 4832, 0x500804020000ULL, 0x80600282220010ULL, 5},
- {bishopAttackTable + 4864, 0x201008040200ULL, 0x120228228010000ULL, 5},
- {bishopAttackTable + 4896, 0x402010080400ULL, 0xc08020802042300ULL, 5},
- {bishopAttackTable + 4928, 0x2040810204000ULL, 0x2a008048221000ULL, 6},
- {bishopAttackTable + 4992, 0x4081020400000ULL, 0x4601204100901002ULL, 5},
- {bishopAttackTable + 5024, 0xa102040000000ULL, 0x821200104052400ULL, 5},
- {bishopAttackTable + 5056, 0x14224000000000ULL, 0x8200084208810ULL, 5},
+ {bishopAttackTable + 4672, 0x20408102000ULL, 0x80c1101101044a0ULL, 5},
+ {bishopAttackTable + 4704, 0x40810204000ULL, 0x180804802310808ULL, 5},
+ {bishopAttackTable + 4736, 0xa1020400000ULL, 0x8048080064ULL, 5},
+ {bishopAttackTable + 4768, 0x142240000000ULL, 0x8c8400020880000ULL, 5},
+ {bishopAttackTable + 4800, 0x284402000000ULL, 0x30001010020a2000ULL, 5},
+ {bishopAttackTable + 4832, 0x500804020000ULL, 0x80600282220010ULL, 5},
+ {bishopAttackTable + 4864, 0x201008040200ULL, 0x120228228010000ULL, 5},
+ {bishopAttackTable + 4896, 0x402010080400ULL, 0xc08020802042300ULL, 5},
+ {bishopAttackTable + 4928, 0x2040810204000ULL, 0x2a008048221000ULL, 6},
+ {bishopAttackTable + 4992, 0x4081020400000ULL, 0x4601204100901002ULL, 5},
+ {bishopAttackTable + 5024, 0xa102040000000ULL, 0x821200104052400ULL, 5},
+ {bishopAttackTable + 5056, 0x14224000000000ULL, 0x8200084208810ULL, 5},
{bishopAttackTable + 5088, 0x28440200000000ULL, 0x8c022040a80b0408ULL, 5},
{bishopAttackTable + 5120, 0x50080402000000ULL, 0x2140201012100512ULL, 5},
- {bishopAttackTable + 5152, 0x20100804020000ULL, 0x10210240128120aULL, 5},
- {bishopAttackTable + 5184, 0x40201008040200ULL, 0x208600082060020ULL, 6},
+ {bishopAttackTable + 5152, 0x20100804020000ULL, 0x10210240128120aULL, 5},
+ {bishopAttackTable + 5184, 0x40201008040200ULL, 0x208600082060020ULL, 6},
};
constexpr Bitboard fileA = 0x101010101010101ULL;
@@ -307,31 +349,57 @@ extern LineType lineType[64][64];
void initBitboard();
-inline Bitboard::Bitboard(Square square) { bb = bitMasks[square].bb; }
+inline Bitboard::Bitboard(Square square) {
+ bb = bitMasks[square].bb;
+}
-inline Bitboard adjacentFileMask(Square square) { return adjacentFileMasks[square]; }
+inline Bitboard adjacentFileMask(Square square) {
+ return adjacentFileMasks[square];
+}
-inline Bitboard adjacentNorthMask(Square square) { return adjacentNorthMasks[square]; }
+inline Bitboard adjacentNorthMask(Square square) {
+ return adjacentNorthMasks[square];
+}
-inline Bitboard adjacentSouthMask(Square square) { return adjacentSouthMasks[square]; }
+inline Bitboard adjacentSouthMask(Square square) {
+ return adjacentSouthMasks[square];
+}
-inline Bitboard pawnMask(Square square, Color color) { return pawnMasks[square][color]; }
+inline Bitboard pawnMask(Square square, Color color) {
+ return pawnMasks[square][color];
+}
-inline Bitboard knightMask(Square square) { return knightMasks[square]; }
+inline Bitboard knightMask(Square square) {
+ return knightMasks[square];
+}
-inline Bitboard kingMask(Square square) { return kingMasks[square]; }
+inline Bitboard kingMask(Square square) {
+ return kingMasks[square];
+}
-inline Bitboard fileMask(Square square) { return fileMasks[square]; }
+inline Bitboard fileMask(Square square) {
+ return fileMasks[square];
+}
-inline Bitboard rankMask(Square square) { return rankMasks[square]; }
+inline Bitboard rankMask(Square square) {
+ return rankMasks[square];
+}
-inline Bitboard rookMask(Square square) { return rookMasks[square]; }
+inline Bitboard rookMask(Square square) {
+ return rookMasks[square];
+}
-inline Bitboard diagonalMask(Square square) { return diagonalMasks[square]; }
+inline Bitboard diagonalMask(Square square) {
+ return diagonalMasks[square];
+}
-inline Bitboard antiDiagonalMask(Square square) { return antiDiagonalMasks[square]; }
+inline Bitboard antiDiagonalMask(Square square) {
+ return antiDiagonalMasks[square];
+}
-inline Bitboard bishopMask(Square square) { return bishopMasks[square]; }
+inline Bitboard bishopMask(Square square) {
+ return bishopMasks[square];
+}
inline unsigned int getMagicIndex(const Magic &m, Bitboard occ) {
#ifdef BMI2
@@ -494,4 +562,4 @@ void initMagic(const Magic *magics, PieceType type);
void findMagics(Bitboard *attackTable, Magic *magics, PieceType type);
-#endif //BLACKCORE_BITBOARD_H
+#endif//BLACKCORE_BITBOARD_H
diff --git a/src/constants.h b/src/constants.h
index 11f6488..397647a 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -29,7 +29,6 @@
#define AVX2
#endif
-
typedef uint64_t U64;
typedef int32_t Score;
typedef int32_t Depth;
@@ -41,19 +40,77 @@ constexpr Score MATE_VALUE = 100000;
constexpr Score WORST_MATE = MATE_VALUE - 100;
constexpr Score DRAW_VALUE = 0;
+const Ply MAX_PLY = 100;
+
const std::string STARTING_FEN = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
constexpr unsigned int RANDOM_SEED = 1254383;
enum Square : int {
- A1 = 0, B1 = 1, C1 = 2, D1 = 3, E1 = 4, F1 = 5, G1 = 6, H1 = 7,
- A2 = 8, B2 = 9, C2 = 10, D2 = 11, E2 = 12, F2 = 13, G2 = 14, H2 = 15,
- A3 = 16, B3 = 17, C3 = 18, D3 = 19, E3 = 20, F3 = 21, G3 = 22, H3 = 23,
- A4 = 24, B4 = 25, C4 = 26, D4 = 27, E4 = 28, F4 = 29, G4 = 30, H4 = 31,
- A5 = 32, B5 = 33, C5 = 34, D5 = 35, E5 = 36, F5 = 37, G5 = 38, H5 = 39,
- A6 = 40, B6 = 41, C6 = 42, D6 = 43, E6 = 44, F6 = 45, G6 = 46, H6 = 47,
- A7 = 48, B7 = 49, C7 = 50, D7 = 51, E7 = 52, F7 = 53, G7 = 54, H7 = 55,
- A8 = 56, B8 = 57, C8 = 58, D8 = 59, E8 = 60, F8 = 61, G8 = 62, H8 = 63,
+ A1 = 0,
+ B1 = 1,
+ C1 = 2,
+ D1 = 3,
+ E1 = 4,
+ F1 = 5,
+ G1 = 6,
+ H1 = 7,
+ A2 = 8,
+ B2 = 9,
+ C2 = 10,
+ D2 = 11,
+ E2 = 12,
+ F2 = 13,
+ G2 = 14,
+ H2 = 15,
+ A3 = 16,
+ B3 = 17,
+ C3 = 18,
+ D3 = 19,
+ E3 = 20,
+ F3 = 21,
+ G3 = 22,
+ H3 = 23,
+ A4 = 24,
+ B4 = 25,
+ C4 = 26,
+ D4 = 27,
+ E4 = 28,
+ F4 = 29,
+ G4 = 30,
+ H4 = 31,
+ A5 = 32,
+ B5 = 33,
+ C5 = 34,
+ D5 = 35,
+ E5 = 36,
+ F5 = 37,
+ G5 = 38,
+ H5 = 39,
+ A6 = 40,
+ B6 = 41,
+ C6 = 42,
+ D6 = 43,
+ E6 = 44,
+ F6 = 45,
+ G6 = 46,
+ H6 = 47,
+ A7 = 48,
+ B7 = 49,
+ C7 = 50,
+ D7 = 51,
+ E7 = 52,
+ F7 = 53,
+ G7 = 54,
+ H7 = 55,
+ A8 = 56,
+ B8 = 57,
+ C8 = 58,
+ D8 = 59,
+ E8 = 60,
+ F8 = 61,
+ G8 = 62,
+ H8 = 63,
NULL_SQUARE = 64
};
@@ -62,13 +119,21 @@ constexpr unsigned char WQ_MASK = 2;
constexpr unsigned char BK_MASK = 4;
constexpr unsigned char BQ_MASK = 8;
-inline Square operator+(Square &a, int b) { return Square(int(a) + b); }
+inline Square operator+(Square &a, int b) {
+ return Square(int(a) + b);
+}
-inline Square operator-(Square &a, int b) { return Square(int(a) - b); }
+inline Square operator-(Square &a, int b) {
+ return Square(int(a) - b);
+}
-inline Square operator+=(Square &a, int b) { return a = a + b; }
+inline Square operator+=(Square &a, int b) {
+ return a = a + b;
+}
-inline Square operator-=(Square &a, int b) { return a = a - b; }
+inline Square operator-=(Square &a, int b) {
+ return a = a - b;
+}
inline Square stringToSquare(std::string s) {
if (s[0] == '-') {
@@ -92,25 +157,53 @@ inline std::istream &operator>>(std::istream &is, Square &square) {
}
enum LineType : int {
- HORIZONTAL = 0, VERTICAL = 1, DIAGONAL = 2, ANTI_DIAGONAL = 3
+ HORIZONTAL = 0,
+ VERTICAL = 1,
+ DIAGONAL = 2,
+ ANTI_DIAGONAL = 3
};
enum Direction : int {
- NORTH = 8, WEST = -1, SOUTH = -8, EAST = 1, NORTH_EAST = 9, NORTH_WEST = 7, SOUTH_WEST = -9, SOUTH_EAST = -7
+ NORTH = 8,
+ WEST = -1,
+ SOUTH = -8,
+ EAST = 1,
+ NORTH_EAST = 9,
+ NORTH_WEST = 7,
+ SOUTH_WEST = -9,
+ SOUTH_EAST = -7
};
constexpr Direction DIRECTIONS[8] = {NORTH, WEST, NORTH_EAST, NORTH_WEST, SOUTH, EAST, SOUTH_WEST, SOUTH_EAST};
-constexpr Direction opposite(Direction direction) { return Direction(-direction); }
+constexpr Direction opposite(Direction direction) {
+ return Direction(-direction);
+}
-constexpr Direction operator-(Direction direction) { return opposite(direction); }
+constexpr Direction operator-(Direction direction) {
+ return opposite(direction);
+}
enum PieceType {
- PIECE_EMPTY = 6, KING = 0, PAWN = 1, KNIGHT = 2, BISHOP = 3, ROOK = 4, QUEEN = 5
+ PIECE_EMPTY = 6,
+ KING = 0,
+ PAWN = 1,
+ KNIGHT = 2,
+ BISHOP = 3,
+ ROOK = 4,
+ QUEEN = 5
};
enum Color {
- COLOR_EMPTY = 2, WHITE = 0, BLACK = 1
+ COLOR_EMPTY = 2,
+ WHITE = 0,
+ BLACK = 1
+};
+
+enum NodeType {
+ ROOT_NODE,
+ PV_NODE,
+ NON_PV_NODE
};
constexpr PieceType PIECE_TYPES_BY_VALUE[6] = {PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING};
@@ -126,7 +219,9 @@ struct Piece {
color = c;
}
- constexpr bool isNull() const { return type == PIECE_EMPTY || color == COLOR_EMPTY; }
+ constexpr bool isNull() const {
+ return type == PIECE_EMPTY || color == COLOR_EMPTY;
+ }
};
// 2 colors * 6 types * 64 square = 768
@@ -532,4 +627,4 @@ constexpr U64 const *castlingRandTable = randTable + 768;
constexpr U64 const *epRandTable = randTable + 772;
constexpr U64 const *blackRand = randTable + 780;
-#endif //BLACKCORE_CONSTANTS_H
+#endif//BLACKCORE_CONSTANTS_H
diff --git a/src/corenet.bin b/src/corenet.bin
index 64126dc..2df2179 100644
Binary files a/src/corenet.bin and b/src/corenet.bin differ
diff --git a/src/eval.cpp b/src/eval.cpp
index 3812435..6ed3ed8 100644
--- a/src/eval.cpp
+++ b/src/eval.cpp
@@ -19,13 +19,6 @@
#ifdef TUNE
Score PIECE_VALUES[6] = {
- 0, 150, 762, 892, 1254, 1651
-};
+ 0, 170, 610, 660, 780, 1200};
#endif
-
-Score eval(const Position &pos) {
-
- Score score = pos.getState()->accumulator.forward();
- return (pos.getSideToMove() == WHITE ? score : -score) + TEMPO_SCORE;
-}
\ No newline at end of file
diff --git a/src/eval.h b/src/eval.h
index 4a1a2c6..eb81004 100644
--- a/src/eval.h
+++ b/src/eval.h
@@ -27,13 +27,12 @@ extern Score PIECE_VALUES[6];
#else
constexpr Score PIECE_VALUES[6] = {
- 0, 150, 762, 892, 1254, 1651
-};
+ 0, 156, 561, 608, 736, 1022};
#endif
-constexpr Score TEMPO_SCORE = 10;
+inline Score eval(const Position &pos) {
+ return pos.getState()->accumulator.forward(pos.getSideToMove());
+}
-Score eval(const Position &pos);
-
-#endif //BLACKCORE_EVAL_H
+#endif//BLACKCORE_EVAL_H
diff --git a/src/main.cpp b/src/main.cpp
index 5c6d43f..d225164 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
-#include "bitboard.h"
#include "bench.h"
-#include "uci.h"
-#include "search.h"
+#include "bitboard.h"
#include "eval.h"
-#include "tuner.h"
#include "nnue.h"
+#include "search.h"
+#include "tuner.h"
+#include "uci.h"
+#include
int main(int argc, char **argv) {
diff --git a/src/move.cpp b/src/move.cpp
index c39748d..05f2ffe 100644
--- a/src/move.cpp
+++ b/src/move.cpp
@@ -20,10 +20,14 @@
std::string Move::str() const {
std::string token;
if (isPromo()) {
- if (!isSpecial1() && !isSpecial2()) token += "n";
- else if (!isSpecial1() && isSpecial2()) token += "b";
- else if (isSpecial1() && !isSpecial2()) token += "r";
- else token += "q";
+ if (!isSpecial1() && !isSpecial2())
+ token += "n";
+ else if (!isSpecial1() && isSpecial2())
+ token += "b";
+ else if (isSpecial1() && !isSpecial2())
+ token += "r";
+ else
+ token += "q";
}
return formatSquare(getFrom()) + formatSquare(getTo()) + token;
}
@@ -32,4 +36,3 @@ std::ostream &operator<<(std::ostream &os, const Move &move) {
os << move.str();
return os;
}
-
diff --git a/src/move.h b/src/move.h
index 0ed6ed4..d191ee3 100644
--- a/src/move.h
+++ b/src/move.h
@@ -18,13 +18,13 @@
#ifndef CHESS_MOVE_H
#define CHESS_MOVE_H
-#include "utils.h"
#include "constants.h"
+#include "utils.h"
-constexpr unsigned int PROMO_FLAG = 0x8; // 0b1000
-constexpr unsigned int CAPTURE_FLAG = 0x4; // 0b0100
-constexpr unsigned int SPECIAL1_FLAG = 0x2; // 0b0010
-constexpr unsigned int SPECIAL2_FLAG = 0x1; // 0b0001
+constexpr unsigned int PROMO_FLAG = 0x8; // 0b1000
+constexpr unsigned int CAPTURE_FLAG = 0x4; // 0b0100
+constexpr unsigned int SPECIAL1_FLAG = 0x2;// 0b0010
+constexpr unsigned int SPECIAL2_FLAG = 0x1;// 0b0001
constexpr unsigned int QUIET_MOVE = 0;
constexpr unsigned int CAPTURE = CAPTURE_FLAG;
@@ -45,7 +45,6 @@ constexpr unsigned int PROMO_CAPTURE_QUEEN = CAPTURE_FLAG | PROMO_FLAG | SPECIAL
constexpr unsigned int KING_CASTLE = SPECIAL1_FLAG;
constexpr unsigned int QUEEN_CASTLE = SPECIAL1_FLAG | SPECIAL2_FLAG;
-
class Move {
public:
constexpr Move(Square from, Square to, unsigned int flags) {
@@ -58,31 +57,57 @@ class Move {
constexpr Move() = default;
- constexpr Square getTo() const { return Square(data & 0x3f); }
+ constexpr Square getTo() const {
+ return Square(data & 0x3f);
+ }
- constexpr Square getFrom() const { return Square((data >> 6) & 0x3f); }
+ constexpr Square getFrom() const {
+ return Square((data >> 6) & 0x3f);
+ }
- constexpr bool isFlag(unsigned int flag) const { return (data >> 12) & flag; }
+ constexpr bool isFlag(unsigned int flag) const {
+ return (data >> 12) & flag;
+ }
- constexpr bool equalFlag(unsigned int flag) const { return (data >> 12) == flag; }
+ constexpr bool equalFlag(unsigned int flag) const {
+ return (data >> 12) == flag;
+ }
- constexpr bool isNull() const { return data == 0; }
+ constexpr bool isNull() const {
+ return data == 0;
+ }
- constexpr bool isCapture() const { return isFlag(CAPTURE_FLAG); }
+ constexpr bool isCapture() const {
+ return isFlag(CAPTURE_FLAG);
+ }
- constexpr bool isPromo() const { return isFlag(PROMO_FLAG); }
+ constexpr bool isPromo() const {
+ return isFlag(PROMO_FLAG);
+ }
- constexpr bool isSpecial1() const { return isFlag(SPECIAL1_FLAG); }
+ constexpr bool isSpecial1() const {
+ return isFlag(SPECIAL1_FLAG);
+ }
- constexpr bool isSpecial2() const { return isFlag(SPECIAL2_FLAG); }
+ constexpr bool isSpecial2() const {
+ return isFlag(SPECIAL2_FLAG);
+ }
- constexpr bool isQuiet() const { return !isCapture(); }
+ constexpr bool isQuiet() const {
+ return !isCapture();
+ }
- constexpr explicit operator bool() const { return !isNull(); }
+ constexpr explicit operator bool() const {
+ return !isNull();
+ }
- constexpr bool operator==(Move a) const { return (data & 0xFFFF) == (a.data & 0xFFFF); }
+ constexpr bool operator==(Move a) const {
+ return (data & 0xFFFF) == (a.data & 0xFFFF);
+ }
- constexpr bool operator!=(Move a) const { return (data & 0xFFFF) != (a.data & 0xFFFF); }
+ constexpr bool operator!=(Move a) const {
+ return (data & 0xFFFF) != (a.data & 0xFFFF);
+ }
std::string str() const;
@@ -92,4 +117,4 @@ class Move {
std::ostream &operator<<(std::ostream &os, const Move &move);
-#endif //CHESS_MOVE_H
+#endif//CHESS_MOVE_H
diff --git a/src/move_ordering.cpp b/src/move_ordering.cpp
index 6ec7c30..dbdbdec 100644
--- a/src/move_ordering.cpp
+++ b/src/move_ordering.cpp
@@ -15,32 +15,25 @@
// along with this program. If not, see .
#include "move_ordering.h"
-#include "tt.h"
#include "search.h"
+#include "tt.h"
#include
-constexpr Score winningCapture[6][6] = {
-// KING PAWN KNIGHT BISHOP ROOK QUEEN
- {0, 0, 0, 0, 0, 0}, // KING
- {0, 800004, 800104, 800204, 800304, 800404}, // PAWN
- {0, 800003, 800103, 800203, 800303, 800403}, // KNIGHT
- {0, 800002, 800102, 800202, 800302, 800402}, // BISHOP
- {0, 800001, 800101, 800201, 800301, 800401}, // ROOK
- {0, 800000, 800100, 800200, 800300, 800400}, // QUEEN
+constexpr Score MVV_LVA[6][6] = {
+ // KING PAWN KNIGHT BISHOP ROOK QUEEN
+ {0, 0, 0, 0, 0, 0}, // KING
+ {0, 800004, 800104, 800204, 800304, 800404},// PAWN
+ {0, 800003, 800103, 800203, 800303, 800403},// KNIGHT
+ {0, 800002, 800102, 800202, 800302, 800402},// BISHOP
+ {0, 800001, 800101, 800201, 800301, 800401},// ROOK
+ {0, 800000, 800100, 800200, 800300, 800400},// QUEEN
};
-constexpr Score losingCapture[6][6] = {
-// KING PAWN KNIGHT BISHOP ROOK QUEEN
- {0, 0, 0, 0, 0, 0}, // KING
- {0, 200004, 200104, 200204, 200304, 200404}, // PAWN
- {0, 200003, 200103, 200203, 200303, 200403}, // KNIGHT
- {0, 200002, 200102, 200202, 200302, 200402}, // BISHOP
- {0, 200001, 200101, 200201, 200301, 200401}, // ROOK
- {0, 200000, 200100, 200200, 200300, 200400}, // QUEEN
-};
+constexpr Score winningCapture = 800000;
+constexpr Score losingCapture = 200000;
-Move killerMoves[101][2];
+Move killerMoves[MAX_PLY + 1][2];
// TODO Counter move history
Score historyTable[2][64][64];
@@ -63,17 +56,18 @@ Score scoreQMove(const Position &pos, Move m) {
if (m == getHashMove(pos.getHash())) {
return 1000000;
} else if (m.isPromo()) {
- if (m.isSpecial1() && m.isSpecial2()) { // Queen promo
+ if (m.isSpecial1() && m.isSpecial2()) {// Queen promo
return 900000;
- } else { // Anything else, under promotions should only be played in really few cases
+ } else {// Anything else, under promotions should only be played in really few cases
return -100000;
}
} else {
Score seeScore = see(pos, m);
+
if (seeScore >= 0)
- return 800000 + seeScore;
+ return winningCapture + seeScore;
else
- return seeScore;
+ return losingCapture + seeScore;
}
}
@@ -81,19 +75,18 @@ Score scoreMove(const Position &pos, Move m, Ply ply) {
if (m == getHashMove(pos.getHash())) {
return 1000000;
} else if (m.isPromo()) {
- if (m.isSpecial1() && m.isSpecial2()) { // Queen promo
+ if (m.isSpecial1() && m.isSpecial2()) {// Queen promo
return 900000;
- } else { // Anything else, under promotions should only be played in really few cases
+ } else {// Anything else, under promotions should only be played in really few cases
return -100000;
}
} else if (m.isCapture()) {
- Square from = m.getFrom();
- Square to = m.getTo();
+ Score seeScore = see(pos, m);
if (see(pos, m) >= 0)
- return winningCapture[pos.pieceAt(from).type][pos.pieceAt(to).type];
+ return winningCapture + seeScore;
else
- return losingCapture[pos.pieceAt(from).type][pos.pieceAt(to).type];
+ return losingCapture + seeScore;
} else if (killerMoves[ply][0] == m) {
return 750000;
} else if (killerMoves[ply][1] == m) {
diff --git a/src/move_ordering.h b/src/move_ordering.h
index d736f1c..6c218ef 100644
--- a/src/move_ordering.h
+++ b/src/move_ordering.h
@@ -20,7 +20,7 @@
#include "move.h"
#include "position.h"
-extern Move killerMoves[101][2];
+extern Move killerMoves[MAX_PLY + 1][2];
Score scoreMove(const Position &pos, Move m, Ply ply);
@@ -32,4 +32,4 @@ void recordKillerMove(Move m, Ply ply);
void recordHHMove(Move move, Color color, Depth depth);
-#endif //BLACKCORE_MOVE_ORDERING_H
+#endif//BLACKCORE_MOVE_ORDERING_H
diff --git a/src/movegen.cpp b/src/movegen.cpp
index d66550e..e072ed2 100644
--- a/src/movegen.cpp
+++ b/src/movegen.cpp
@@ -78,7 +78,6 @@ inline Move *generateMovesFromPieces(const Position &pos, Move *moves, Bitboard
}
return moves;
-
}
template
@@ -287,7 +286,6 @@ inline Move *generateSliderAndJumpMoves(const Position &pos, Move *moves, Bitboa
moves = generateMovesFromPieces(pos, moves, pinnedDA, checkMask & pinDA, occupied, empty,
enemy);
-
return moves;
}
@@ -327,7 +325,8 @@ Move *generateMoves(const Position &pos, Move *moves) {
Bitboard possiblePinners = (pieceAttacks(king, occupied) ^ seenSquares) & enemy;
Bitboard pinners = ((pieceAttacks(king, occupied) & pos.pieces()) |
(pieceAttacks(king, occupied) & pos.pieces()) |
- (pieceAttacks(king, occupied) & pos.pieces())) & possiblePinners;
+ (pieceAttacks(king, occupied) & pos.pieces())) &
+ possiblePinners;
Bitboard pinH, pinV, pinD, pinA, pinHV, pinDA, moveH, moveV, moveD, moveA;
diff --git a/src/movegen.h b/src/movegen.h
index 4c8f462..e77a87c 100644
--- a/src/movegen.h
+++ b/src/movegen.h
@@ -17,9 +17,9 @@
#ifndef BLACKCORE_MOVEGEN_H
#define BLACKCORE_MOVEGEN_H
-#include "position.h"
#include "move.h"
#include "move_ordering.h"
+#include "position.h"
template
inline Bitboard getAttackers(const Position &pos, Square square) {
@@ -29,7 +29,8 @@ inline Bitboard getAttackers(const Position &pos, Square square) {
(pieceAttacks(square, occupied) & pos.pieces()) |
(pieceAttacks(square, occupied) & pos.pieces()) |
(pieceAttacks(square, occupied) & pos.pieces()) |
- (pieceAttacks(square, occupied) & pos.pieces())) & enemy;
+ (pieceAttacks(square, occupied) & pos.pieces())) &
+ enemy;
}
inline Bitboard getAttackers(const Position &pos, Square square) {
@@ -85,5 +86,4 @@ struct MoveList {
}
};
-
-#endif //BLACKCORE_MOVEGEN_H
+#endif//BLACKCORE_MOVEGEN_H
diff --git a/src/nnue.cpp b/src/nnue.cpp
index 995520a..c5d6549 100644
--- a/src/nnue.cpp
+++ b/src/nnue.cpp
@@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#include "nnue.h"
+#include "position.h"
#include
#include
#include
-#include "nnue.h"
-#include "position.h"
#include "incbin/incbin.h"
@@ -29,120 +29,144 @@ namespace NNUE {
alignas(64) int16_t L_0_WEIGHTS[L_0_SIZE * L_1_SIZE];
alignas(64) int16_t L_0_BIASES[L_1_SIZE];
- alignas(64) int16_t L_1_WEIGHTS[L_1_SIZE * 1];
+ alignas(64) int16_t L_1_WEIGHTS[L_1_SIZE * 2];
alignas(64) int16_t L_1_BIASES[1];
void Accumulator::loadAccumulator(NNUE::Accumulator &accumulator) {
+ for (Color perspective : {WHITE, BLACK}) {
#ifdef AVX2
- for (int i = 0; i < chunkNum; i += 4) {
- const int offset1 = (i + 0) * regWidth;
- const int offset2 = (i + 1) * regWidth;
- const int offset3 = (i + 2) * regWidth;
- const int offset4 = (i + 3) * regWidth;
-
- __m256i ac1 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[offset1]);
- __m256i ac2 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[offset2]);
- __m256i ac3 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[offset3]);
- __m256i ac4 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[offset4]);
-
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset1], ac1);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset2], ac2);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset3], ac3);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset4], ac4);
- }
+ for (int i = 0; i < chunkNum; i += 4) {
+ const int offset1 = (i + 0) * regWidth;
+ const int offset2 = (i + 1) * regWidth;
+ const int offset3 = (i + 2) * regWidth;
+ const int offset4 = (i + 3) * regWidth;
+
+ __m256i ac1 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[perspective][offset1]);
+ __m256i ac2 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[perspective][offset2]);
+ __m256i ac3 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[perspective][offset3]);
+ __m256i ac4 = _mm256_loadu_si256((__m256i *) &accumulator.hiddenLayer[perspective][offset4]);
+
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset1], ac1);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset2], ac2);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset3], ac3);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset4], ac4);
+ }
#else
- std::memcpy(hiddenLayer, accumulator.hiddenLayer, sizeof(int16_t) * L_1_SIZE);
+ std::memcpy(hiddenLayer[perspective], accumulator.hiddenLayer[perspective], sizeof(int16_t) * L_1_SIZE * 1);
#endif
+ }
}
void Accumulator::refresh(const Position &pos) {
- std::memcpy(hiddenLayer, L_0_BIASES, sizeof(int16_t) * L_1_SIZE);
+ for (Color perspective : {WHITE, BLACK}) {
+ std::memcpy(hiddenLayer[perspective], L_0_BIASES, sizeof(int16_t) * L_1_SIZE);
+ }
for (Square sq = A1; sq < 64; sq += 1) {
Piece p = pos.pieceAt(sq);
if (!p.isNull()) {
- addFeature(getAccumulatorIndex(p.color, p.type, sq));
+ addFeature(p.color, p.type, sq);
}
}
}
- void Accumulator::addFeature(int index) {
+ void Accumulator::addFeature(Color pieceColor, PieceType pieceType, Square sq) {
+ for (Color perspective : {WHITE, BLACK}) {
+ unsigned int index = getAccumulatorIndex(perspective, pieceColor, pieceType, sq);
#ifdef AVX2
- for (int i = 0; i < chunkNum; i += 4) {
- const int offset1 = (i + 0) * regWidth;
- const int offset2 = (i + 1) * regWidth;
- const int offset3 = (i + 2) * regWidth;
- const int offset4 = (i + 3) * regWidth;
-
- __m256i ac1 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset1]);
- __m256i ac2 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset2]);
- __m256i ac3 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset3]);
- __m256i ac4 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset4]);
-
- __m256i we1 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset1]);
- __m256i we2 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset2]);
- __m256i we3 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset3]);
- __m256i we4 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset4]);
-
- __m256i sum1 = _mm256_add_epi16(ac1, we1);
- __m256i sum2 = _mm256_add_epi16(ac2, we2);
- __m256i sum3 = _mm256_add_epi16(ac3, we3);
- __m256i sum4 = _mm256_add_epi16(ac4, we4);
-
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset1], sum1);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset2], sum2);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset3], sum3);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset4], sum4);
- }
+ for (int i = 0; i < chunkNum; i += 4) {
+ const int offset1 = (i + 0) * regWidth;
+ const int offset2 = (i + 1) * regWidth;
+ const int offset3 = (i + 2) * regWidth;
+ const int offset4 = (i + 3) * regWidth;
+
+ __m256i ac1 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset1]);
+ __m256i ac2 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset2]);
+ __m256i ac3 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset3]);
+ __m256i ac4 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset4]);
+
+ __m256i we1 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset1]);
+ __m256i we2 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset2]);
+ __m256i we3 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset3]);
+ __m256i we4 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset4]);
+
+ __m256i sum1 = _mm256_add_epi16(ac1, we1);
+ __m256i sum2 = _mm256_add_epi16(ac2, we2);
+ __m256i sum3 = _mm256_add_epi16(ac3, we3);
+ __m256i sum4 = _mm256_add_epi16(ac4, we4);
+
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset1], sum1);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset2], sum2);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset3], sum3);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset4], sum4);
+ }
#else
- for (int i = 0; i < L_1_SIZE; i++) {
- hiddenLayer[i] += L_0_WEIGHTS[index * L_1_SIZE + i];
- }
+ for (int i = 0; i < L_1_SIZE; i++) {
+ hiddenLayer[perspective][i] += L_0_WEIGHTS[index * L_1_SIZE + i];
+ }
#endif
+ }
}
- void Accumulator::removeFeature(int index) {
+ void Accumulator::removeFeature(Color pieceColor, PieceType pieceType, Square sq) {
+ for (Color perspective : {WHITE, BLACK}) {
+ unsigned int index = getAccumulatorIndex(perspective, pieceColor, pieceType, sq);
#ifdef AVX2
- for (int i = 0; i < chunkNum; i += 4) {
-
- const int offset1 = (i + 0) * regWidth;
- const int offset2 = (i + 1) * regWidth;
- const int offset3 = (i + 2) * regWidth;
- const int offset4 = (i + 3) * regWidth;
-
- __m256i ac1 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset1]);
- __m256i ac2 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset2]);
- __m256i ac3 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset3]);
- __m256i ac4 = _mm256_loadu_si256((__m256i *) &hiddenLayer[offset4]);
-
- __m256i we1 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset1]);
- __m256i we2 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset2]);
- __m256i we3 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset3]);
- __m256i we4 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset4]);
-
- __m256i sum1 = _mm256_sub_epi16(ac1, we1);
- __m256i sum2 = _mm256_sub_epi16(ac2, we2);
- __m256i sum3 = _mm256_sub_epi16(ac3, we3);
- __m256i sum4 = _mm256_sub_epi16(ac4, we4);
-
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset1], sum1);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset2], sum2);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset3], sum3);
- _mm256_storeu_si256((__m256i *) &hiddenLayer[offset4], sum4);
- }
+ for (int i = 0; i < chunkNum; i += 4) {
+
+ const int offset1 = (i + 0) * regWidth;
+ const int offset2 = (i + 1) * regWidth;
+ const int offset3 = (i + 2) * regWidth;
+ const int offset4 = (i + 3) * regWidth;
+
+ __m256i ac1 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset1]);
+ __m256i ac2 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset2]);
+ __m256i ac3 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset3]);
+ __m256i ac4 = _mm256_loadu_si256((__m256i *) &hiddenLayer[perspective][offset4]);
+
+ __m256i we1 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset1]);
+ __m256i we2 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset2]);
+ __m256i we3 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset3]);
+ __m256i we4 = _mm256_loadu_si256((__m256i *) &L_0_WEIGHTS[index * L_1_SIZE + offset4]);
+
+ __m256i sum1 = _mm256_sub_epi16(ac1, we1);
+ __m256i sum2 = _mm256_sub_epi16(ac2, we2);
+ __m256i sum3 = _mm256_sub_epi16(ac3, we3);
+ __m256i sum4 = _mm256_sub_epi16(ac4, we4);
+
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset1], sum1);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset2], sum2);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset3], sum3);
+ _mm256_storeu_si256((__m256i *) &hiddenLayer[perspective][offset4], sum4);
+ }
#else
- for (int i = 0; i < L_1_SIZE; i++) {
- hiddenLayer[i] -= L_0_WEIGHTS[index * L_1_SIZE + i];
- }
+ for (int i = 0; i < L_1_SIZE; i++) {
+ hiddenLayer[perspective][i] -= L_0_WEIGHTS[index * L_1_SIZE + i];
+ }
#endif
+ }
}
- Score Accumulator::forward() {
+ Score Accumulator::forward(Color stm) {
int32_t output = L_1_BIASES[0];
- for (int i = 0; i < L_1_SIZE; i++) {
- output += ReLU(hiddenLayer[i]) * L_1_WEIGHTS[i];
+ if (stm == WHITE) {
+ for (int i = 0; i < L_1_SIZE; i++) {
+ output += ReLU(hiddenLayer[WHITE][i]) * L_1_WEIGHTS[i];
+ }
+
+ for (int i = 0; i < L_1_SIZE; i++) {
+ output += ReLU(hiddenLayer[BLACK][i]) * L_1_WEIGHTS[L_1_SIZE + i];
+ }
+ } else {
+ for (int i = 0; i < L_1_SIZE; i++) {
+ output += ReLU(hiddenLayer[BLACK][i]) * L_1_WEIGHTS[i];
+ }
+
+ for (int i = 0; i < L_1_SIZE; i++) {
+ output += ReLU(hiddenLayer[WHITE][i]) * L_1_WEIGHTS[L_1_SIZE + i];
+ }
}
return output * 400 / (255 * 255);
@@ -155,8 +179,8 @@ namespace NNUE {
ptr += sizeof(int16_t) * L_0_SIZE * L_1_SIZE;
std::memcpy(L_0_BIASES, gNetData + ptr, sizeof(int16_t) * L_1_SIZE);
ptr += sizeof(int16_t) * L_1_SIZE;
- std::memcpy(L_1_WEIGHTS, gNetData + ptr, sizeof(int16_t) * L_1_SIZE * 1);
- ptr += sizeof(int16_t) * L_1_SIZE * 1;
+ std::memcpy(L_1_WEIGHTS, gNetData + ptr, sizeof(int16_t) * L_1_SIZE * 2);
+ ptr += sizeof(int16_t) * L_1_SIZE * 2;
std::memcpy(L_1_BIASES, gNetData + ptr, sizeof(int16_t) * 1);
// Currently loading net from a file is not supported
@@ -168,9 +192,9 @@ namespace NNUE {
fread(L_0_WEIGHTS, sizeof(int16_t), L_0_SIZE * L_1_SIZE, file);
fread(L_0_BIASES, sizeof(int16_t), L_1_SIZE, file);
- fread(L_1_WEIGHTS, sizeof(int16_t), L_1_SIZE * 1, file);
+ fread(L_1_WEIGHTS, sizeof(int16_t), L_1_SIZE * 2, file);
fread(L_1_BIASES, sizeof(int16_t), 1, file);
}*/
}
-}
\ No newline at end of file
+}// namespace NNUE
diff --git a/src/nnue.h b/src/nnue.h
index 6391a30..0032624 100644
--- a/src/nnue.h
+++ b/src/nnue.h
@@ -23,21 +23,22 @@ class Position;
namespace NNUE {
- /* +-----------------------+
- * | NNUE Architecture |
- * | 768->256->1 |
- * | Activation: ReLU |
- * +-----------------------+
- *
- * L_0_IN = features count
- *
- * L_1_WEIGHTS = in features -> L_1 (768 -> 32)
- * L_1_BIASES = L_1 biases
- *
- * L_2_WEIGHTS = L_1 -> L_2 (32 -> 32)
- * L_2_BIASES = L_2 biases
- *
- */
+ /*
+ * +-----------------------+
+ * | NNUE Architecture |
+ * | 2x(768->256)->1 |
+ * | Activation: ReLU |
+ * +-----------------------+
+ *
+ * L_0_SIZE = features count
+ *
+ * L_0_WEIGHTS = in features -> L_1 (768 -> 256)
+ * L_0_BIASES = L_1 biases
+ *
+ * L_1_WEIGHTS = 2xL_1 -> L_2 (2x256 -> 1)
+ * L_1_BIASES = L_2 biases
+ *
+ */
constexpr int L_0_SIZE = 768;
@@ -47,23 +48,25 @@ namespace NNUE {
constexpr int chunkNum = 256 / regWidth;
struct Accumulator {
- alignas(32) int16_t hiddenLayer[L_1_SIZE];
+ alignas(32) int16_t hiddenLayer[2][L_1_SIZE];
- constexpr Accumulator() {}
+ constexpr Accumulator() {
+ }
void loadAccumulator(Accumulator &accumulator);
void refresh(const Position &pos);
- void addFeature(int index);
+ void addFeature(Color pieceColor, PieceType pieceType, Square sq);
- void removeFeature(int index);
+ void removeFeature(Color pieceColor, PieceType pieceType, Square sq);
- Score forward();
+ Score forward(Color stm);
};
- constexpr int getAccumulatorIndex(Color color, PieceType type, Square square) {
- return color * 384 + type * 64 + square;
+ constexpr int getAccumulatorIndex(Color perspective, Color pieceColor, PieceType pieceType, Square square) {
+ return (perspective == WHITE ? pieceColor : 1 - pieceColor) * 384 + pieceType * 64 +
+ (perspective == WHITE ? square : square ^ 56);
}
constexpr int16_t ReLU(int16_t in) {
@@ -71,6 +74,6 @@ namespace NNUE {
}
void init();
-}
+}// namespace NNUE
-#endif //BLACKCORE_NNUE_H
+#endif//BLACKCORE_NNUE_H
diff --git a/src/position.cpp b/src/position.cpp
index 9034eed..e131c51 100644
--- a/src/position.cpp
+++ b/src/position.cpp
@@ -17,9 +17,9 @@
#include "position.h"
#include "eval.h"
+#include
#include
#include
-#include
#define state states.top()
@@ -73,17 +73,22 @@ bool Position::isRepetition() {
}
void Position::display() const {
- state->accumulator.forward();
+
std::vector text;
text.emplace_back(string("Hash: ") + std::to_string(state->hash));
if (getEpSquare() != NULL_SQUARE)
text.emplace_back(string("En passant square: ") + formatSquare(getEpSquare()));
string cr;
- if (getCastleRight(WK_MASK)) cr += 'K';
- if (getCastleRight(WQ_MASK)) cr += 'Q';
- if (getCastleRight(BK_MASK)) cr += 'k';
- if (getCastleRight(BQ_MASK)) cr += 'q';
- if (cr.empty()) cr = "None";
+ if (getCastleRight(WK_MASK))
+ cr += 'K';
+ if (getCastleRight(WQ_MASK))
+ cr += 'Q';
+ if (getCastleRight(BK_MASK))
+ cr += 'k';
+ if (getCastleRight(BQ_MASK))
+ cr += 'q';
+ if (cr.empty())
+ cr = "None";
text.emplace_back(string("Castling rights: ") + cr);
text.emplace_back(string("Side to move: ") + string(getSideToMove() == WHITE ? "White" : "Black"));
// TODO FEN, full-half move counter
@@ -105,7 +110,8 @@ void Position::display() const {
}
cout << "\n";
}
- cout << " +---+---+---+---+---+---+---+---+\n\n" << std::endl;
+ cout << " +---+---+---+---+---+---+---+---+\n\n"
+ << std::endl;
}
void Position::displayEval() {
@@ -134,7 +140,8 @@ void Position::displayEval() {
}
cout << "\n";
}
- cout << " +-----+-----+-----+-----+-----+-----+-----+-----+\n" << std::endl;
+ cout << " +-----+-----+-----+-----+-----+-----+-----+-----+\n"
+ << std::endl;
cout << "Eval: " << score << std::endl;
}
diff --git a/src/position.h b/src/position.h
index 6079f5b..0750833 100644
--- a/src/position.h
+++ b/src/position.h
@@ -17,11 +17,11 @@
#ifndef BLACKCORE_POSITION_H
#define BLACKCORE_POSITION_H
-#include
#include "bitboard.h"
-#include "utils.h"
#include "move.h"
#include "nnue.h"
+#include "utils.h"
+#include
extern U64 nodeCount;
@@ -69,72 +69,116 @@ struct StateStack {
currState--;
}
- inline BoardState *top() const { return currState; }
+ inline BoardState *top() const {
+ return currState;
+ }
inline void clear() {
currState = stateStart;
*currState = {};
}
- inline Ply getMove50() const { return currState - currState->lastIrreversibleMove; }
-
+ inline Ply getMove50() const {
+ return currState - currState->lastIrreversibleMove;
+ }
};
#define state states.top()
class Position {
public:
-
- constexpr Piece pieceAt(Square square) const { return board[square]; }
+ constexpr Piece pieceAt(Square square) const {
+ return board[square];
+ }
// This will be mostly used with constant color and type so this will result a nicer code
// pieces<{ROOK, WHITE}>() --> pieces()
template
- constexpr Bitboard pieces() const { return pieceBB[type] & allPieceBB[color]; }
+ constexpr Bitboard pieces() const {
+ return pieceBB[type] & allPieceBB[color];
+ }
template
- constexpr Bitboard pieces(PieceType type) const { return pieceBB[type] & allPieceBB[color]; }
+ constexpr Bitboard pieces(PieceType type) const {
+ return pieceBB[type] & allPieceBB[color];
+ }
template
- constexpr Bitboard pieces(Color color) const { return pieceBB[type] & allPieceBB[color]; }
+ constexpr Bitboard pieces(Color color) const {
+ return pieceBB[type] & allPieceBB[color];
+ }
- constexpr Bitboard pieces(Color color, PieceType type) const { return pieceBB[type] & allPieceBB[color]; }
+ constexpr Bitboard pieces(Color color, PieceType type) const {
+ return pieceBB[type] & allPieceBB[color];
+ }
template
- constexpr Bitboard pieces() const { return pieceBB[type]; }
+ constexpr Bitboard pieces() const {
+ return pieceBB[type];
+ }
- constexpr Bitboard pieces(PieceType type) const { return pieceBB[type]; }
+ constexpr Bitboard pieces(PieceType type) const {
+ return pieceBB[type];
+ }
template
- constexpr Bitboard friendly() const { return allPieceBB[color]; }
+ constexpr Bitboard friendly() const {
+ return allPieceBB[color];
+ }
- constexpr Bitboard friendly(Color color) const { return allPieceBB[color]; }
+ constexpr Bitboard friendly(Color color) const {
+ return allPieceBB[color];
+ }
template
- constexpr Bitboard enemy() const { return allPieceBB[EnemyColor()]; }
+ constexpr Bitboard enemy() const {
+ return allPieceBB[EnemyColor()];
+ }
template
- constexpr Bitboard enemyOrEmpty() const { return ~friendly(); }
+ constexpr Bitboard enemyOrEmpty() const {
+ return ~friendly();
+ }
- inline Bitboard occupied() const { return allPieceBB[WHITE] | allPieceBB[BLACK]; }
+ inline Bitboard occupied() const {
+ return allPieceBB[WHITE] | allPieceBB[BLACK];
+ }
- inline Bitboard empty() const { return ~occupied(); }
+ inline Bitboard empty() const {
+ return ~occupied();
+ }
- inline Color getSideToMove() const { return state->stm; }
+ inline Color getSideToMove() const {
+ return state->stm;
+ }
- inline Square getEpSquare() const { return state->epSquare; }
+ inline Square getEpSquare() const {
+ return state->epSquare;
+ }
- inline bool getCastleRight(unsigned char castleRight) const { return castleRight & state->castlingRights; }
+ inline bool getCastleRight(unsigned char castleRight) const {
+ return castleRight & state->castlingRights;
+ }
- inline unsigned char getCastlingRights() const { return state->castlingRights; }
+ inline unsigned char getCastlingRights() const {
+ return state->castlingRights;
+ }
- inline BoardState *getState() { return state; }
+ inline BoardState *getState() {
+ return state;
+ }
- inline BoardState *getState() const { return state; }
+ inline BoardState *getState() const {
+ return state;
+ }
- inline U64 getHash() const { return state->hash; }
+ inline U64 getHash() const {
+ return state->hash;
+ }
- inline Ply getMove50() const { return states.getMove50(); }
+ inline Ply getMove50() const {
+ return states.getMove50();
+ }
inline void makeMove(Move move);
@@ -161,7 +205,6 @@ class Position {
Position(const std::string &fen);
private:
-
template
void clearSquare(Square square);
@@ -171,9 +214,13 @@ class Position {
template
void movePiece(Square from, Square to);
- inline void setCastleRight(unsigned char castleRight) { state->castlingRights |= castleRight; }
+ inline void setCastleRight(unsigned char castleRight) {
+ state->castlingRights |= castleRight;
+ }
- inline void removeCastleRight(unsigned char castleRight) { state->castlingRights &= ~castleRight; }
+ inline void removeCastleRight(unsigned char castleRight) {
+ state->castlingRights &= ~castleRight;
+ }
void clearPosition();
@@ -205,7 +252,7 @@ void Position::clearSquare(Square square) {
state->hash ^= pieceRandTable[12 * square + 6 * piece.color + piece.type];
if constexpr (updateAccumulator) {
- state->accumulator.removeFeature(NNUE::getAccumulatorIndex(piece.color, piece.type, square));
+ state->accumulator.removeFeature(piece.color, piece.type, square);
}
}
@@ -220,7 +267,7 @@ void Position::setSquare(Square square, Piece piece) {
state->hash ^= pieceRandTable[12 * square + 6 * p.color + p.type];
if constexpr (updateAccumulator) {
- state->accumulator.removeFeature(NNUE::getAccumulatorIndex(p.color, p.type, square));
+ state->accumulator.removeFeature(p.color, p.type, square);
}
}
@@ -231,7 +278,7 @@ void Position::setSquare(Square square, Piece piece) {
state->hash ^= pieceRandTable[12 * square + 6 * piece.color + piece.type];
if constexpr (updateAccumulator) {
- state->accumulator.addFeature(NNUE::getAccumulatorIndex(piece.color, piece.type, square));
+ state->accumulator.addFeature(piece.color, piece.type, square);
}
}
@@ -345,7 +392,6 @@ void Position::undoMove(Move move) {
movePiece(to, from);
-
if (move.equalFlag(KING_CASTLE)) {
if constexpr (enemyColor == WHITE) {
movePiece(F1, H1);
@@ -372,15 +418,19 @@ void Position::undoMove(Move move) {
}
inline void Position::makeMove(Move move) {
- if (getSideToMove() == WHITE) makeMove(move);
- else makeMove(move);
+ if (getSideToMove() == WHITE)
+ makeMove(move);
+ else
+ makeMove(move);
}
inline void Position::undoMove(Move move) {
- if (getSideToMove() == WHITE) undoMove(move);
- else undoMove(move);
+ if (getSideToMove() == WHITE)
+ undoMove(move);
+ else
+ undoMove(move);
}
#undef state
-#endif //BLACKCORE_POSITION_H
+#endif//BLACKCORE_POSITION_H
diff --git a/src/search.cpp b/src/search.cpp
index c73f775..b0c0bb4 100644
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -15,22 +15,23 @@
// along with this program. If not, see .
#include "search.h"
+#include "eval.h"
#include "timeman.h"
#include "tt.h"
-#include "eval.h"
#include "uci.h"
+#include
#include
#ifdef TUNE
-Score DELTA_MARGIN = 307;
+Score DELTA_MARGIN = 252;
-Score RAZOR_MARGIN = 146;
+Score RAZOR_MARGIN = 155;
Depth RFP_DEPTH = 8;
-Score RFP_DEPTH_MULTIPLIER = 60;
-Score RFP_IMPROVING_MULTIPLIER = 56;
+Score RFP_DEPTH_MULTIPLIER = 56;
+Score RFP_IMPROVING_MULTIPLIER = 46;
Depth NULL_MOVE_DEPTH = 2;
Depth NULL_MOVE_BASE_R = 3;
@@ -38,9 +39,8 @@ Depth NULL_MOVE_R_SCALE = 3;
Depth LMR_DEPTH = 3;
double LMR_BASE = 1;
-double LMR_SCALE = 1.75;
-int LMR_MIN_I = 2;
-int LMR_PVNODE_I = 1;
+double LMR_SCALE = 1.65;
+int LMR_INDEX = 2;
Depth LMP_DEPTH = 4;
int LMP_MOVES = 5;
@@ -50,7 +50,6 @@ Score ASPIRATION_DELTA = 28;
Score ASPIRATION_BOUND = 3000;
Score SEE_MARGIN = 2;
-Depth SEE_DEPTH = 4;
#endif
@@ -58,15 +57,13 @@ Ply selectiveDepth = 0;
Move bestPV;
// Move index -> depth
-Depth reductions[200][64];
+Depth reductions[200][MAX_PLY + 1];
void initLmr() {
for (int moveIndex = 0; moveIndex < 200; moveIndex++) {
- for (Depth depth = 0; depth < 64; depth++) {
-
- reductions[moveIndex][depth] = std::max(2, Depth(
- LMR_BASE + (log((double) moveIndex) * log((double) depth) / LMR_SCALE)));
+ for (Depth depth = 0; depth < MAX_PLY; depth++) {
+ reductions[moveIndex][depth] = std::max(2, Depth(LMR_BASE + (log((double) moveIndex) * log((double) depth) / LMR_SCALE)));
}
}
}
@@ -87,7 +84,8 @@ Bitboard getAllAttackers(const Position &pos, Square square, Bitboard occ) {
(pieceAttacks(square, occ) & pos.pieces()) |
(pieceAttacks(square, occ) & pos.pieces()) |
(pieceAttacks(square, occ) & pos.pieces()) |
- (pieceAttacks(square, occ) & pos.pieces())) & occ;
+ (pieceAttacks(square, occ) & pos.pieces())) &
+ occ;
}
Score see(const Position &pos, Move move) {
@@ -96,7 +94,7 @@ Score see(const Position &pos, Move move) {
Square from = move.getFrom();
Square to = move.getTo();
- e[0] = PIECE_VALUES[pos.pieceAt(to).type];
+ e[0] = move.equalFlag(EP_CAPTURE) ? PIECE_VALUES[PAWN] : PIECE_VALUES[pos.pieceAt(to).type];
Bitboard rooks = pos.pieces() | pos.pieces();
Bitboard bishops = pos.pieces() | pos.pieces();
@@ -111,7 +109,8 @@ Score see(const Position &pos, Move move) {
d++;
e[d] = PIECE_VALUES[type] - e[d - 1];
- if (std::max(-e[d - 1], e[d]) < 0) break;
+ if (std::max(-e[d - 1], e[d]) < 0)
+ break;
occ ^= attacker;
attackers ^= attacker;
@@ -131,21 +130,31 @@ Score see(const Position &pos, Move move) {
return e[0];
}
-
+template
Score quiescence(Position &pos, Score alpha, Score beta, Ply ply) {
- if (shouldEnd()) return UNKNOWN_SCORE;
+ constexpr bool pvNode = type != NON_PV_NODE;
+ constexpr bool nonPvNode = !pvNode;
+
+ if (shouldEnd())
+ return UNKNOWN_SCORE;
if (ply > selectiveDepth) {
selectiveDepth = ply;
}
- bool ttHit;
- Score ttScore = ttProbe(pos.getHash(), ttHit, 0, alpha, beta);
- if (ttScore != UNKNOWN_SCORE) return ttScore;
+ bool ttHit = false;
+ TTEntry *ttEntry = ttProbe(pos.getHash(), ttHit, 0, alpha, beta);
+ if (ttHit && nonPvNode && (ttEntry->flag == EXACT || (ttEntry->flag == ALPHA && ttEntry->eval <= alpha) || (ttEntry->flag == BETA && ttEntry->eval >= beta))) {
+ return ttEntry->eval;
+ }
Score staticEval = eval(pos);
+ if (ply >= MAX_PLY) {
+ return staticEval;
+ }
+
if (staticEval >= beta) {
return beta;
}
@@ -164,7 +173,8 @@ Score quiescence(Position &pos, Score alpha, Score beta, Ply ply) {
// Delta pruning
if (m.isPromo() * PIECE_VALUES[QUEEN] + PIECE_VALUES[pos.pieceAt(m.getTo()).type] +
- staticEval + DELTA_MARGIN < alpha)
+ staticEval + DELTA_MARGIN <
+ alpha)
continue;
// SEE pruning
@@ -173,11 +183,12 @@ Score quiescence(Position &pos, Score alpha, Score beta, Ply ply) {
pos.makeMove(m);
- Score score = -quiescence(pos, -beta, -alpha, ply + 1);
+ Score score = -quiescence(pos, -beta, -alpha, ply + 1);
pos.undoMove(m);
- if (shouldEnd()) return UNKNOWN_SCORE;
+ if (shouldEnd())
+ return UNKNOWN_SCORE;
if (score >= beta) {
ttSave(pos.getHash(), 0, score, BETA, m);
@@ -189,95 +200,120 @@ Score quiescence(Position &pos, Score alpha, Score beta, Ply ply) {
ttFlag = EXACT;
bestMove = m;
}
-
}
- // TODO elo test storing null move instead of bestMove
ttSave(pos.getHash(), 0, alpha, ttFlag, bestMove);
return alpha;
}
-Score search(Position &pos, SearchState *state, Depth depth, Score alpha, Score beta, Ply ply) {
+template
+Score search(Position &pos, SearchStack *stack, Depth depth, Score alpha, Score beta, Ply ply) {
- if (shouldEnd()) return UNKNOWN_SCORE;
+ constexpr bool rootNode = type == ROOT_NODE;
+ constexpr bool pvNode = type != NON_PV_NODE;
+ constexpr bool notRootNode = !rootNode;
+ constexpr bool nonPvNode = !pvNode;
+ constexpr NodeType nextPv = rootNode ? PV_NODE : type;
- if (pos.getMove50() >= 4 && ply > 0 && pos.isRepetition()) return DRAW_VALUE;
+ if (shouldEnd())
+ return UNKNOWN_SCORE;
+
+ if (notRootNode && pos.getMove50() >= 3 && pos.isRepetition()) {
+ alpha = DRAW_VALUE;
+ if (alpha >= beta)
+ return alpha;
+ }
bool ttHit = false;
- bool pvNode = beta - alpha > 1;
Score matePly = MATE_VALUE - ply;
- Score ttScore = ttProbe(pos.getHash(), ttHit, depth, alpha, beta);
- if (!pvNode && ttScore != UNKNOWN_SCORE) return ttScore;
+ TTEntry *ttEntry = ttProbe(pos.getHash(), ttHit, depth, alpha, beta);
+
+ if (ttHit && nonPvNode &&
+ ttEntry->depth >= depth && (ttEntry->flag == EXACT || (ttEntry->flag == ALPHA && ttEntry->eval <= alpha) || (ttEntry->flag == BETA && ttEntry->eval >= beta))) {
+ return ttEntry->eval;
+ }
// Mate distance pruning
- if (ply > 0) {
- if (alpha < -matePly) alpha = -matePly;
- if (beta > matePly - 1) beta = matePly - 1;
- if (alpha >= beta) return alpha;
+ if (notRootNode) {
+ if (alpha < -matePly)
+ alpha = -matePly;
+ if (beta > matePly - 1)
+ beta = matePly - 1;
+ if (alpha >= beta)
+ return alpha;
}
- if (depth <= 0) return quiescence(pos, alpha, beta, ply);
+ if (ply >= MAX_PLY) {
+ return eval(pos);
+ }
- MoveList moves = {pos, ply, false};
+ if (depth <= 0)
+ return quiescence(pos, alpha, beta, ply);
Color color = pos.getSideToMove();
bool inCheck = bool(getAttackers(pos, pos.pieces(color).lsb()));
- if (moves.count == 0) {
- if (inCheck) {
- return -matePly;
- } else {
- return DRAW_VALUE;
- }
- }
+ Score staticEval = stack->eval = eval(pos);
- Score staticEval = state->eval = eval(pos);
+ bool improving = ply >= 2 && staticEval >= (stack - 2)->eval;
- if (ply > 0 && !inCheck) {
-
- bool improving = ply >= 2 && staticEval >= (state - 2)->eval;
+ if (notRootNode && !inCheck) {
// Razoring
- if (depth == 1 && !pvNode && staticEval + RAZOR_MARGIN < alpha) {
- return quiescence(pos, alpha, beta, ply);
+ if (depth == 1 && nonPvNode && staticEval + RAZOR_MARGIN < alpha) {
+ return quiescence(pos, alpha, beta, ply);
}
// Reverse futility pruning
if (depth <= RFP_DEPTH &&
- staticEval - RFP_DEPTH_MULTIPLIER * (int) depth + RFP_IMPROVING_MULTIPLIER * improving >= beta &&
+ staticEval - RFP_DEPTH_MULTIPLIER * depth + RFP_IMPROVING_MULTIPLIER * improving >= beta &&
std::abs(beta) < WORST_MATE)
return beta;
// Null move pruning
- if (!pvNode && !(state - 1)->move.isNull() && depth >= NULL_MOVE_DEPTH && staticEval >= beta) {
+ if (nonPvNode && !(stack - 1)->move.isNull() && depth >= NULL_MOVE_DEPTH && staticEval >= beta) {
// We don't want to make a null move in a Zugzwang position
if (pos.pieces(color) | pos.pieces(color) | pos.pieces(color) |
pos.pieces(color)) {
Depth R = NULL_MOVE_BASE_R + depth / NULL_MOVE_R_SCALE;
- state->move = Move();
+ stack->move = Move();
pos.makeNullMove();
- Score score = -search(pos, state + 1, depth - R, -beta, -beta + 1, ply + 1);
+ Score score = -search(pos, stack + 1, depth - R, -beta, -beta + 1, ply + 1);
pos.undoNullMove();
if (score >= beta) {
- if (std::abs(score) > WORST_MATE) return beta;
+ if (std::abs(score) > WORST_MATE)
+ return beta;
return score;
}
}
}
// Internal iterative deepening
- if (!ttHit && !pvNode) depth--;
+ if (!ttHit && pvNode)
+ depth--;
+ if (!ttHit && depth >= 5)
+ depth--;
- if (depth <= 0) return quiescence(pos, alpha, beta, ply);
+ if (depth <= 0)
+ return quiescence(pos, alpha, beta, ply);
}
// Check extension
if (inCheck)
depth++;
+ MoveList moves = {pos, ply, false};
+ if (moves.count == 0) {
+ if (inCheck) {
+ return -matePly;
+ } else {
+ return DRAW_VALUE;
+ }
+ }
+
Move bestMove;
EntryFlag ttFlag = ALPHA;
int index = 0;
@@ -285,14 +321,20 @@ Score search(Position &pos, SearchState *state, Depth depth, Score alpha, Score
while (!moves.empty()) {
Move m = moves.nextMove();
- state->move = m;
+ stack->move = m;
Score score;
// We can prune the move in some cases
- if (ply > 0 && !pvNode && !inCheck && alpha > -WORST_MATE) {
+ if (notRootNode && nonPvNode && !inCheck && alpha > -WORST_MATE) {
+
+ if (depth <= FUTILITY_DEPTH && m.isQuiet() &&
+ staticEval + FUTILITY_MARGIN + FUTILITY_MARGIN_DEPTH * depth + FUTILITY_MARGIN_IMPROVING * improving <
+ alpha)
+ continue;
// Late move/movecount pruning
+ // This will also prune losing captures
if (depth <= LMP_DEPTH && index >= LMP_MOVES + depth * depth && m.isQuiet())
break;
}
@@ -301,32 +343,36 @@ Score search(Position &pos, SearchState *state, Depth depth, Score alpha, Score
ttPrefetch(pos.getHash());
- if (index == 0) {
- score = -search(pos, state + 1, depth - 1, -beta, -alpha, ply + 1);
- } else {
- // Late move reduction
- if (!inCheck && depth >= LMR_DEPTH && index >= LMR_MIN_I + pvNode * LMR_PVNODE_I && !m.isPromo() &&
- m.isQuiet() && m != killerMoves[ply][0] && m != killerMoves[ply][1]) {
+ // Late move reduction
+ if (!inCheck && depth >= LMR_DEPTH && index >= LMR_INDEX && !m.isPromo() &&
+ m.isQuiet()) {
- score = -search(pos, state + 1, depth - reductions[index][depth], -alpha - 1, -alpha,
- ply + 1);
- } else score = alpha + 1;
+ Depth R = reductions[index][depth];
+ R += improving;
+ R -= pvNode;
- // Principal variation search
- if (score > alpha) {
- score = -search(pos, state + 1, depth - 1, -alpha - 1, -alpha, ply + 1);
+ Depth newDepth = std::clamp(depth - R, 1, depth - 1);
- if (score > alpha) {
- score = -search(pos, state + 1, depth - 1, -beta, -alpha, ply + 1);
- }
+ score = -search(pos, stack + 1, newDepth,
+ -alpha - 1, -alpha, ply + 1);
+
+ if (score > alpha && R > 1) {
+ score = -search(pos, stack + 1, depth - 1, -alpha - 1, -alpha, ply + 1);
}
+ } else if (nonPvNode || index != 0) {
+ score = -search(pos, stack + 1, depth - 1, -alpha - 1, -alpha, ply + 1);
+ }
+
+ if (pvNode && (index == 0 || (score > alpha && score < beta))) {
+ score = -search(pos, stack + 1, depth - 1, -beta, -alpha, ply + 1);
}
pos.undoMove(m);
- if (shouldEnd()) return UNKNOWN_SCORE;
+ if (shouldEnd())
+ return UNKNOWN_SCORE;
if (score >= beta) {
@@ -370,7 +416,7 @@ Score searchRoot(Position &pos, Score prevScore, Depth depth, bool uci) {
globalAge++;
clearTables();
selectiveDepth = 0;
- SearchState stateStack[100];
+ SearchStack stateStack[MAX_PLY + 1];
Score alpha = -INF_SCORE;
Score beta = INF_SCORE;
@@ -381,14 +427,18 @@ Score searchRoot(Position &pos, Score prevScore, Depth depth, bool uci) {
int iter = 1;
while (true) {
- if (shouldEnd()) return UNKNOWN_SCORE;
+ if (shouldEnd())
+ return UNKNOWN_SCORE;
- if (alpha < -ASPIRATION_BOUND) alpha = -INF_SCORE;
- if (beta > ASPIRATION_BOUND) beta = INF_SCORE;
+ if (alpha < -ASPIRATION_BOUND)
+ alpha = -INF_SCORE;
+ if (beta > ASPIRATION_BOUND)
+ beta = INF_SCORE;
- Score score = search(pos, stateStack + 1, depth, alpha, beta, 0);
+ Score score = search(pos, stateStack + 1, depth, alpha, beta, 0);
- if (score == UNKNOWN_SCORE) return UNKNOWN_SCORE;
+ if (score == UNKNOWN_SCORE)
+ return UNKNOWN_SCORE;
if (score <= alpha) {
alpha = std::max(alpha - iter * iter * ASPIRATION_DELTA, -INF_SCORE);
@@ -426,12 +476,10 @@ Score searchRoot(Position &pos, Score prevScore, Depth depth, bool uci) {
}
}
-void iterativeDeepening(Position pos, Depth depth, bool uci, std::atomic &searchRunning) {
+void iterativeDeepening(Position pos, Depth depth, bool uci) {
pos.getState()->accumulator.refresh(pos);
- searchRunning = true;
-
Score prevScore;
Move bestMove;
@@ -439,12 +487,13 @@ void iterativeDeepening(Position pos, Depth depth, bool uci, std::atomic &
for (Depth currDepth = 1; currDepth <= depth; currDepth++) {
Score score = searchRoot(pos, prevScore, currDepth, uci);
- if (score == UNKNOWN_SCORE) break;
+ if (score == UNKNOWN_SCORE)
+ break;
// We only care about stability if we searched enough depth
- if (currDepth >= 12) {
+ if (currDepth >= 16) {
if (bestMove != bestPV) {
- stability -= 6;
+ stability -= 10;
} else {
if (std::abs(prevScore - score) >= std::max(prevScore / 10, 50)) {
stability -= 4;
@@ -464,5 +513,31 @@ void iterativeDeepening(Position pos, Depth depth, bool uci, std::atomic &
out("bestmove", bestMove);
}
- searchRunning = false;
+ searchStopped() = true;
+}
+
+#include
+
+std::thread th;
+
+void joinThread(bool waitToFinish) {
+ if (!waitToFinish)
+ stopSearch();
+
+ if (th.joinable())
+ th.join();
+}
+
+void startSearch(SearchInfo &searchInfo, Position &pos, int threadCount) {
+
+ joinThread(false);
+
+ Color stm = pos.getSideToMove();
+ if (stm == WHITE) {
+ initTimeMan(searchInfo.wtime, searchInfo.winc, searchInfo.movestogo, searchInfo.movetime, searchInfo.maxNodes);
+ } else {
+ initTimeMan(searchInfo.btime, searchInfo.binc, searchInfo.movestogo, searchInfo.movetime, searchInfo.maxNodes);
+ }
+
+ th = std::thread(iterativeDeepening, pos, searchInfo.maxDepth, searchInfo.uciMode);
}
\ No newline at end of file
diff --git a/src/search.h b/src/search.h
index 1fbc19d..61459dc 100644
--- a/src/search.h
+++ b/src/search.h
@@ -17,8 +17,9 @@
#ifndef BLACKCORE_SEARCH_H
#define BLACKCORE_SEARCH_H
-#include
#include "movegen.h"
+#include "uci.h"
+#include
#ifdef TUNE
@@ -37,8 +38,7 @@ extern Depth NULL_MOVE_R_SCALE;
extern Depth LMR_DEPTH;
extern double LMR_BASE;
extern double LMR_SCALE;
-extern int LMR_MIN_I;
-extern int LMR_PVNODE_I;
+extern int LMR_INDEX;
extern Depth LMP_DEPTH;
extern int LMP_MOVES;
@@ -51,27 +51,31 @@ extern Score SEE_MARGIN;
#else
-constexpr Score DELTA_MARGIN = 307;
+constexpr Score DELTA_MARGIN = 252;
-constexpr Score RAZOR_MARGIN = 146;
+constexpr Score RAZOR_MARGIN = 155;
constexpr Depth RFP_DEPTH = 8;
-constexpr Score RFP_DEPTH_MULTIPLIER = 60;
-constexpr Score RFP_IMPROVING_MULTIPLIER = 56;
+constexpr Score RFP_DEPTH_MULTIPLIER = 42;
+constexpr Score RFP_IMPROVING_MULTIPLIER = 66;
constexpr Depth NULL_MOVE_DEPTH = 2;
-constexpr Depth NULL_MOVE_BASE_R = 3;
-constexpr Depth NULL_MOVE_R_SCALE = 3;
+constexpr Depth NULL_MOVE_BASE_R = 4;
+constexpr Depth NULL_MOVE_R_SCALE = 2;
constexpr Depth LMR_DEPTH = 3;
constexpr double LMR_BASE = 1;
-constexpr double LMR_SCALE = 1.75;
-constexpr int LMR_MIN_I = 2;
-constexpr int LMR_PVNODE_I = 1;
+constexpr double LMR_SCALE = 1.65;
+constexpr int LMR_INDEX = 2;
constexpr Depth LMP_DEPTH = 4;
constexpr int LMP_MOVES = 5;
+constexpr Depth FUTILITY_DEPTH = 3;
+constexpr Score FUTILITY_MARGIN = 30;
+constexpr Score FUTILITY_MARGIN_DEPTH = 60;
+constexpr Score FUTILITY_MARGIN_IMPROVING = 80;
+
constexpr Depth ASPIRATION_DEPTH = 9;
constexpr Score ASPIRATION_DELTA = 28;
constexpr Score ASPIRATION_BOUND = 3000;
@@ -80,7 +84,7 @@ constexpr Score SEE_MARGIN = 2;
#endif
-struct SearchState {
+struct SearchStack {
Move move;
Score eval = 0;
};
@@ -95,6 +99,8 @@ inline void initSearch() {
Score see(const Position &pos, Move move);
-void iterativeDeepening(Position pos, Depth depth, bool uci, std::atomic &searchRunning);
+void joinThread(bool waitToFinish);
+
+void startSearch(SearchInfo &searchInfo, Position &pos, int threadCount);
-#endif //BLACKCORE_SEARCH_H
+#endif//BLACKCORE_SEARCH_H
diff --git a/src/timeman.cpp b/src/timeman.cpp
index 0dccf57..1e0a515 100644
--- a/src/timeman.cpp
+++ b/src/timeman.cpp
@@ -16,50 +16,49 @@
#include "timeman.h"
#include "position.h"
-
#include
unsigned int MOVE_OVERHEAD = 10;
-constexpr U64 mask = (1ULL << 15) - 1;
-
-U64 startedSearch;
-U64 shouldSearch;
-U64 searchTime;
-U64 maxSearch;
-U64 stabilityTime;
+constexpr U64 mask = 1023;
+U64 startedSearch, shouldSearch, searchTime, maxSearch, stabilityTime, maxNodes;
-bool stop = false;
+bool stopping = true;
+bool stopped = true;
U64 getTime() {
return std::chrono::duration_cast(
- std::chrono::system_clock::now().time_since_epoch()).count();
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
}
-void startSearch(U64 time, U64 inc, U64 movesToGo, U64 moveTime) {
+void initTimeMan(U64 time, U64 inc, U64 movesToGo, U64 moveTime, U64 nodes) {
nodeCount = 0;
- movesToGo = movesToGo == 0 ? 15 : movesToGo;
+ movesToGo = movesToGo == 0 ? 20 : movesToGo + 1;
startedSearch = getTime();
stabilityTime = 0;
- stop = false;
+ stopping = false;
+ stopped = false;
- if (time == 0) {
- // We have infinite time
- shouldSearch = 0;
- maxSearch = 0;
- } else if (moveTime != 0) {
+ maxNodes = nodes;
+
+ if (moveTime != 0) {
// We are limited how much can we search
shouldSearch = moveTime - MOVE_OVERHEAD;
maxSearch = moveTime - MOVE_OVERHEAD;
+ } else if (time == 0) {
+ // We have infinite time
+ shouldSearch = 0;
+ maxSearch = 0;
} else {
U64 panicTime = time / (movesToGo + 10) + 2 * inc;
- stabilityTime = time / 400;
+ stabilityTime = time / 500;
- shouldSearch = std::min(time - MOVE_OVERHEAD, time / (movesToGo + 5) + inc * 3 / 4 - MOVE_OVERHEAD);
+ shouldSearch = std::min(time - MOVE_OVERHEAD, time / movesToGo + inc * 3 / 4 - MOVE_OVERHEAD);
maxSearch = std::min(time - MOVE_OVERHEAD, shouldSearch + panicTime);
}
@@ -67,7 +66,11 @@ void startSearch(U64 time, U64 inc, U64 movesToGo, U64 moveTime) {
}
void stopSearch() {
- stop = true;
+ stopping = true;
+}
+
+bool &searchStopped() {
+ return stopped;
}
void allocateTime(int stability) {
@@ -76,10 +79,10 @@ void allocateTime(int stability) {
}
bool shouldEnd() {
- if ((nodeCount & mask) == 0 && maxSearch != 0 && !stop) {
- stop = getSearchTime() >= searchTime;
+ if ((nodeCount & mask) == 0 && !stopping) {
+ stopping = (maxSearch != 0 && getSearchTime() >= searchTime) || (maxNodes != 0 && nodeCount > maxNodes);
}
- return stop;
+ return stopping;
}
U64 getSearchTime() {
diff --git a/src/timeman.h b/src/timeman.h
index 8dbb40f..ef6d339 100644
--- a/src/timeman.h
+++ b/src/timeman.h
@@ -21,16 +21,18 @@
extern unsigned int MOVE_OVERHEAD;
-void startSearch(U64 time, U64 inc, U64 movesToGo, U64 moveTime);
+void initTimeMan(U64 time, U64 inc, U64 movesToGo, U64 moveTime, U64 nodes);
bool shouldEnd();
void stopSearch();
+bool &searchStopped();
+
void allocateTime(int stability);
U64 getSearchTime();
U64 getNps();
-#endif //BLACKCORE_TIMEMAN_H
+#endif//BLACKCORE_TIMEMAN_H
diff --git a/src/tt.cpp b/src/tt.cpp
index 5ff7476..3e8273e 100644
--- a/src/tt.cpp
+++ b/src/tt.cpp
@@ -14,8 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
#include "tt.h"
+#include
#ifdef __linux__
@@ -45,12 +45,12 @@ void ttResize(unsigned int MBSize) {
ttFree();
unsigned int i = 10;
- while ((1ULL << i) <= MBSize * 1024 * 1024 / sizeof(TTBucket)) i++;
+ while ((1ULL << i) <= MBSize * 1024 * 1024 / sizeof(TTBucket))
+ i++;
tt.bucketCount = (1ULL << (i - 1));
tt.mask = tt.bucketCount - 1ULL;
-
#ifdef __linux__
// Allocate memory with 1MB alignment
tt.table = static_cast(aligned_alloc((1ULL << 20), tt.bucketCount * sizeof(TTBucket)));
@@ -58,14 +58,13 @@ void ttResize(unsigned int MBSize) {
// For reference see https://man7.org/linux/man-pages/man2/madvise.2.html on MADV HUGEPAGE
madvise(tt.table, tt.bucketCount * sizeof(TTBucket), MADV_HUGEPAGE);
#else
- tt.table = (TTBucket*)malloc(tt.bucketCount * sizeof(TTBucket));
+ tt.table = (TTBucket *) malloc(tt.bucketCount * sizeof(TTBucket));
#endif
ttClear();
-
}
-Score ttProbe(U64 hash, bool &ttHit, Depth depth, Score alpha, Score beta) {
+TTEntry *ttProbe(U64 hash, bool &ttHit, Depth depth, Score alpha, Score beta) {
TTBucket *bucket = getBucket(hash);
TTEntry *entry;
if (bucket->entryA.hash == hash) {
@@ -74,25 +73,14 @@ Score ttProbe(U64 hash, bool &ttHit, Depth depth, Score alpha, Score beta) {
} else if (bucket->entryB.hash == hash) {
entry = &bucket->entryB;
} else {
- return UNKNOWN_SCORE;
+ return nullptr;
}
- ttHit = true;
- if (std::abs(entry->eval) > MATE_VALUE - 100) return UNKNOWN_SCORE;
-
- if (entry->depth >= depth) {
- if (entry->flag == EXACT) {
- return entry->eval;
- }
- if (entry->flag == ALPHA && entry->eval <= alpha) {
- return alpha;
- }
- if (entry->flag == BETA && entry->eval >= beta) {
- return beta;
- }
- }
+ if (std::abs(entry->eval) > MATE_VALUE - 100)
+ return nullptr;
- return UNKNOWN_SCORE;
+ ttHit = true;
+ return entry;
}
void ttSave(U64 hash, Depth depth, Score eval, EntryFlag flag, Move bestMove) {
@@ -114,13 +102,14 @@ void ttSave(U64 hash, Depth depth, Score eval, EntryFlag flag, Move bestMove) {
entry->hashMove = bestMove;
entry->age = globalAge;
}
-
}
Move getHashMove(U64 hash) {
TTBucket *bucket = getBucket(hash);
- if (bucket->entryA.hash == hash) return bucket->entryA.hashMove;
- else if (bucket->entryB.hash == hash) return bucket->entryB.hashMove;
+ if (bucket->entryA.hash == hash)
+ return bucket->entryA.hashMove;
+ else if (bucket->entryB.hash == hash)
+ return bucket->entryB.hashMove;
return {};
}
diff --git a/src/tt.h b/src/tt.h
index d7d9434..0c4582f 100644
--- a/src/tt.h
+++ b/src/tt.h
@@ -23,22 +23,25 @@
extern uint16_t globalAge;
enum EntryFlag : uint16_t {
- NONE = 0, EXACT = 1, ALPHA = 2, BETA = 3
+ NONE = 0,
+ EXACT = 1,
+ ALPHA = 2,
+ BETA = 3
};
-struct TTEntry { // Total: 21 bytes -> compiler makes it 24
- U64 hash; // 8 bytes
- Depth depth; // 4 bytes
- Score eval; // 4 bytes
- Move hashMove; // 2 bytes
- EntryFlag flag; // 1 bytes
- uint16_t age; // 2 bytes
+struct TTEntry { // Total: 21 bytes -> compiler makes it 24
+ U64 hash; // 8 bytes
+ Depth depth; // 4 bytes
+ Score eval; // 4 bytes
+ Move hashMove; // 2 bytes
+ EntryFlag flag;// 1 bytes
+ uint16_t age; // 2 bytes
};
-struct TTBucket { // 64 bytes
- TTEntry entryA; // 24 bytes
- TTEntry entryB; // 24 bytes
- U64 _padding1, _padding2; // 16 bytes
+struct TTBucket { // 64 bytes
+ TTEntry entryA; // 24 bytes
+ TTEntry entryB; // 24 bytes
+ U64 _padding1, _padding2;// 16 bytes
};
struct TTable {
@@ -53,7 +56,7 @@ void ttClear();
void ttFree();
-Score ttProbe(U64 hash, bool &ttHit, Depth depth, Score alpha, Score beta);
+TTEntry *ttProbe(U64 hash, bool &ttHit, Depth depth, Score alpha, Score beta);
void ttSave(U64 hash, Depth depth, Score eval, EntryFlag flag, Move bestMove);
@@ -61,4 +64,4 @@ Move getHashMove(U64 hash);
void ttPrefetch(U64 hash);
-#endif //BLACKCORE_TT_H
+#endif//BLACKCORE_TT_H
diff --git a/src/tuner.cpp b/src/tuner.cpp
index 79f4e4c..f41a5f9 100644
--- a/src/tuner.cpp
+++ b/src/tuner.cpp
@@ -14,11 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
-#include
-#include
#include "tuner.h"
#include "eval.h"
+#include
+#include
+#include
double K = 0.2;
@@ -37,13 +37,11 @@ double E(const std::vector &data) {
double predicted = 1 / double(1 + pow(10, -K * score / 400));
error += (entry.result - predicted) * (entry.result - predicted);
-
}
error /= double(data.size());
return error;
-
}
void saveResults(const unsigned int paramCnt, EvalParameter *evalParameters) {
@@ -83,7 +81,6 @@ void saveResults(const unsigned int paramCnt, EvalParameter *evalParameters) {
params << "\t";
}
}
-
}
params << "};\n";
}
@@ -135,8 +132,7 @@ void tune(const std::string &inputFile) {
const unsigned int PSQTparamCnt = 768;
const unsigned int paramCnt = 0;
- EvalParameter params[paramCnt] = {
- };
+ EvalParameter params[paramCnt] = {};
while (improved) {
diff --git a/src/tuner.h b/src/tuner.h
index ec118c4..6a48381 100644
--- a/src/tuner.h
+++ b/src/tuner.h
@@ -17,11 +17,11 @@
#ifndef BLACKCORE_TUNER_H
#define BLACKCORE_TUNER_H
-#include
-#include
+#include "position.h"
#include
#include
-#include "position.h"
+#include
+#include
struct DataEntry {
RawState pos;
@@ -36,4 +36,4 @@ struct EvalParameter {
void tune(const std::string &inputFile);
-#endif //BLACKCORE_TUNER_H
+#endif//BLACKCORE_TUNER_H
diff --git a/src/uci.cpp b/src/uci.cpp
index 01ca1a2..9927bce 100644
--- a/src/uci.cpp
+++ b/src/uci.cpp
@@ -14,15 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#include
-#include
-#include
#include "uci.h"
-#include "tt.h"
+#include "bench.h"
+#include "eval.h"
+#include "position.h"
#include "search.h"
#include "timeman.h"
-#include "position.h"
-#include "bench.h"
+#include "tt.h"
+#include
+#include
Move stringToMove(const Position &pos, const std::string &s) {
Square from = stringToSquare(s.substr(0, 2));
@@ -67,12 +67,16 @@ Move stringToMove(const Position &pos, const std::string &s) {
void uciLoop() {
// Identifying ourselves
- out("id", "name", "BlackCore_v2-0-H1");
+#ifdef VERSION
+ out("id", "name", "BlackCore", VERSION);
+#else
+ out("id", "name", "BlackCore");
+#endif
out("id", "author", "SzilBalazs");
// We tell the GUI what options we have
- out("option", "name", "Hash", "type", "spin", "default", 16, "min", 1, "max", 1024);
+ out("option", "name", "Hash", "type", "spin", "default", 32, "min", 1, "max", 4096);
out("option", "name", "Threads", "type", "spin", "default", 1, "min", 1, "max", 1);
out("option", "name", "Ponder", "type", "check", "default", "false");
out("option", "name", "Move Overhead", "type", "spin", "default", 10, "min", 0, "max", 10000);
@@ -80,28 +84,29 @@ void uciLoop() {
#ifdef TUNE
tuneOut("DELTA_MARGIN", 400, 200, 500);
tuneOut("RAZOR_MARGIN", 130, 50, 200);
- tuneOut("RFP_DEPTH", 5, 3, 8);
+ tuneOut("RFP_DEPTH", 5, 3, 10);
tuneOut("RFP_DEPTH_MULTIPLIER", 70, 30, 200);
tuneOut("RFP_IMPROVING_MULTIPLIER", 80, 30, 200);
tuneOut("NULL_MOVE_DEPTH", 3, 1, 6);
tuneOut("NULL_MOVE_BASE_R", 4, 2, 6);
tuneOut("NULL_MOVE_R_SCALE", 5, 2, 10);
tuneOut("LMR_DEPTH", 4, 2, 10);
- tuneOut("LMR_MIN_I", 3, 1, 10);
- tuneOut("LMR_PVNODE_I", 2, 1, 10);
+ tuneOut("LMR_INDEX", 3, 1, 10);
tuneOut("LMP_DEPTH", 4, 1, 10);
tuneOut("LMP_MOVES", 5, 1, 10);
tuneOut("ASPIRATION_DEPTH", 9, 5, 20);
tuneOut("ASPIRATION_DELTA", 30, 10, 100);
tuneOut("SEE_MARGIN", 0, 0, 200);
tuneOut("PAWN_VALUE", 150, 100, 200);
- tuneOut("KNIGHT_VALUE", 750, 500, 1000);
- tuneOut("BISHOP_VALUE", 850, 500, 1000);
- tuneOut("ROOK_VALUE", 1250, 1000, 1500);
- tuneOut("QUEEN_VALUE", 1600, 1200, 2000);
+ tuneOut("KNIGHT_VALUE", 750, 300, 1000);
+ tuneOut("BISHOP_VALUE", 850, 300, 1000);
+ tuneOut("ROOK_VALUE", 800, 300, 1000);
+ tuneOut("QUEEN_VALUE", 1000, 500, 1500);
+ tuneOut("LMR_BASE", 10, 1, 30);
+ tuneOut("LMR_SCALE", 17, 10, 40);
#endif
- ttResize(16);
+ ttResize(32);
// We have sent all the parameters
out("uciok");
@@ -110,9 +115,7 @@ void uciLoop() {
initSearch();
Position pos = {STARTING_FEN};
- std::thread searchThread;
-
- std::atomic searchRunning(false);
+ int threadCount = 1;
while (true) {
std::string line, command, token;
@@ -130,10 +133,10 @@ void uciLoop() {
if (command == "isready") {
out("readyok");
} else if (command == "quit") {
- stopSearch();
+ joinThread(false);
break;
} else if (command == "stop") {
- stopSearch();
+ joinThread(false);
} else if (command == "ucinewgame") {
ttClear();
} else if (command == "setoption") {
@@ -164,10 +167,8 @@ void uciLoop() {
NULL_MOVE_R_SCALE = std::stoi(tokens[3]);
} else if (tokens[1] == "LMR_DEPTH") {
LMR_DEPTH = std::stoi(tokens[3]);
- } else if (tokens[1] == "LMR_MIN_I") {
- LMR_MIN_I = std::stoi(tokens[3]);
- } else if (tokens[1] == "LMR_PVNODE_I") {
- LMR_PVNODE_I = std::stoi(tokens[3]);
+ } else if (tokens[1] == "LMR_INDEX") {
+ LMR_INDEX = std::stoi(tokens[3]);
} else if (tokens[1] == "LMP_DEPTH") {
LMP_DEPTH = std::stoi(tokens[3]);
} else if (tokens[1] == "LMP_MOVES") {
@@ -188,6 +189,10 @@ void uciLoop() {
PIECE_VALUES[ROOK] = std::stoi(tokens[3]);
} else if (tokens[1] == "QUEEN_VALUE") {
PIECE_VALUES[QUEEN] = std::stoi(tokens[3]);
+ } else if (tokens[1] == "LMR_BASE") {
+ LMR_BASE = double(std::stoi(tokens[3])) / 10;
+ } else if (tokens[1] == "LMR_SCALE") {
+ LMR_SCALE = double(std::stoi(tokens[3])) / 10;
}
#endif
}
@@ -208,7 +213,8 @@ void uciLoop() {
unsigned int i = 0;
bool move = false;
while (i < tokens.size()) {
- if (tokens[i] == "moves") move = true;
+ if (tokens[i] == "moves")
+ move = true;
else if (move) {
pos.makeMove(stringToMove(pos, tokens[i]));
}
@@ -220,41 +226,30 @@ void uciLoop() {
} else if (command == "go") {
- if (searchRunning) {
- out("Search is already running!", "To stop it use the \"stop\" command.");
- continue;
- }
-
- U64 wtime = 0, btime = 0, winc = 0, binc = 0, movestogo = 0, movetime = 0;
- Depth depth = 64;
+ SearchInfo searchInfo;
for (unsigned int i = 0; i < tokens.size(); i += 2) {
if (tokens[i] == "wtime") {
- wtime = std::stoi(tokens[i + 1]);
+ searchInfo.wtime = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "btime") {
- btime = std::stoi(tokens[i + 1]);
+ searchInfo.btime = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "winc") {
- winc = std::stoi(tokens[i + 1]);
+ searchInfo.winc = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "binc") {
- binc = std::stoi(tokens[i + 1]);
+ searchInfo.binc = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "movestogo") {
- movestogo = std::stoi(tokens[i + 1]);
+ searchInfo.movestogo = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "depth") {
- depth = std::stoi(tokens[i + 1]);
+ searchInfo.maxDepth = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "movetime") {
- movetime = std::stoi(tokens[i + 1]);
+ searchInfo.movetime = std::stoi(tokens[i + 1]);
+ } else if (tokens[i] == "nodes") {
+ searchInfo.maxNodes = std::stoi(tokens[i + 1]);
} else if (tokens[i] == "infinite") {
- depth = 64;
}
}
- if (pos.getSideToMove() == WHITE)
- startSearch(wtime, winc, movestogo, movetime);
- else
- startSearch(btime, binc, movestogo, movetime);
-
- searchThread = std::thread(iterativeDeepening, pos, depth, true, std::ref(searchRunning));
- searchThread.detach();
+ startSearch(searchInfo, pos, threadCount);
} else if (command == "d" || command == "display") {
pos.display();
diff --git a/src/uci.h b/src/uci.h
index 2479f5e..0a1c15c 100644
--- a/src/uci.h
+++ b/src/uci.h
@@ -17,22 +17,31 @@
#ifndef BLACKCORE_UCI_H
#define BLACKCORE_UCI_H
+#include "constants.h"
#include
-inline void _out() {
- std::cout << std::endl;
-}
+struct SearchInfo {
+ U64 wtime = 0, btime = 0, winc = 0, binc = 0, movestogo = 0, movetime = 0, maxNodes = 0;
+ Depth maxDepth = MAX_PLY;
+ bool uciMode = true;
+};
-template
-inline void _out(T a, Args... args) {
- std::cout << " " << a;
- _out(args...);
-}
+namespace BlackCore {
+ inline void _out() {
+ std::cout << std::endl;
+ }
+
+ template
+ inline void _out(T a, Args... args) {
+ std::cout << " " << a;
+ _out(args...);
+ }
+}// namespace BlackCore
template
inline void out(T a, Args... args) {
std::cout << a;
- _out(args...);
+ BlackCore::_out(args...);
}
inline void tuneOut(const std::string &name, int value, int min, int max) {
@@ -43,4 +52,4 @@ inline void tuneOut(const std::string &name, int value, int min, int max) {
void uciLoop();
-#endif //BLACKCORE_UCI_H
+#endif//BLACKCORE_UCI_H
diff --git a/src/utils.cpp b/src/utils.cpp
index bc5ca08..dc7f64b 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -14,9 +14,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+#include "utils.h"
#include
#include
-#include "utils.h"
std::string formatSquare(Square square) {
return std::string() + (char) ('a' + (char) square % 8) + (char) ('1' + (char) (square / 8));
@@ -46,7 +46,8 @@ char pieceToChar(Piece piece) {
default:
base = ' ';
}
- if (base != ' ' && piece.color == WHITE) base -= 32;
+ if (base != ' ' && piece.color == WHITE)
+ base -= 32;
return base;
}
@@ -112,7 +113,8 @@ void displayBB(Bitboard b) {
}
std::cout << "\n";
}
- std::cout << " +---+---+---+---+---+---+---+---+\n\n" << std::endl;
+ std::cout << " +---+---+---+---+---+---+---+---+\n\n"
+ << std::endl;
}
// source: https://web.archive.org/web/20071031100138/http://www.brucemo.com/compchess/programming/zobrist.htm
diff --git a/src/utils.h b/src/utils.h
index 1850201..9ae61d3 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -17,30 +17,40 @@
#ifndef BLACKCORE_UTILS_H
#define BLACKCORE_UTILS_H
-#include
-#include "constants.h"
#include "bitboard.h"
+#include "constants.h"
+#include
constexpr PieceType indexToType[7] = {KING, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, PIECE_EMPTY};
constexpr Color indexToColor[3] = {WHITE, BLACK, COLOR_EMPTY};
template
constexpr Color EnemyColor() {
- if constexpr (color == WHITE) return BLACK;
- else return WHITE;
+ if constexpr (color == WHITE)
+ return BLACK;
+ else
+ return WHITE;
}
-inline Color EnemyColor(Color color) { return color == WHITE ? BLACK : WHITE; }
+inline Color EnemyColor(Color color) {
+ return color == WHITE ? BLACK : WHITE;
+}
-constexpr unsigned int squareToRank(Square square) { return square >> 3; }
+constexpr unsigned int squareToRank(Square square) {
+ return square >> 3;
+}
-constexpr unsigned int squareToFile(Square square) { return square & 7; }
+constexpr unsigned int squareToFile(Square square) {
+ return square & 7;
+}
constexpr Square mirrorSquare(Square square) {
return Square(56 - square + squareToFile(square));
}
-constexpr unsigned char encodePiece(Piece piece) { return (piece.color << 3) | piece.type; }
+constexpr unsigned char encodePiece(Piece piece) {
+ return (piece.color << 3) | piece.type;
+}
constexpr Piece decodePiece(unsigned char encodedPiece) {
return {indexToType[encodedPiece & 7], indexToColor[encodedPiece >> 3]};
@@ -60,4 +70,4 @@ Bitboard randBB();
std::string BBToHex(Bitboard bb);
-#endif //BLACKCORE_UTILS_H
+#endif//BLACKCORE_UTILS_H