Skip to content

Commit 3dec2ad

Browse files
Jlisowskyykryczkal
andauthored
See implementation (#64)
* Prepared simple test for agin and half moves * Moved repetition map to the board * Fixed default board in engine class * Added board creation * Working GetDefault call * fixed repetitions init * Created test file * Added 50 moves tests * Added next draw tests * Fixed 3fold * Reworked search thread mechanics * Fixed Thread Manager destruction * Enforced depth limit on search * Added SEE tests * Added delta-prunning with SEE * Improved delta prunning. TODO: fix bugs with ZHasher * Added zhasher test sketch * Added zhasher test * Removed positional evaluation from draw meterial constelations * Added test breaking ZHasher * gitignore fix * Fixed hasher bugh * Applied clang format * Fixed include * Update SearchTests.cc * Update GameTimeManager.cpp --------- Co-authored-by: Łukasz Kryczka <60490378+kryczkal@users.noreply.github.com>
1 parent 1ab98d9 commit 3dec2ad

33 files changed

+657
-257
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,4 @@ lib/
2929
c-chess*
3030

3131
uci*
32+
.vs/

CMakeLists.txt

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ set(CMAKE_CXX_STANDARD 20)
99
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1010
# We C++ 20 is required by the main exec
1111

12+
################################################################################
13+
# Tunable parameters #
14+
################################################################################
15+
16+
# Uncomment to stop enforcing inline on INLINE macro
17+
#add_compile_definitions(PREVENT_FORCE_INLINE=1)
18+
19+
# Uncomment to add gathering TT statistics
20+
add_compile_definitions(TEST_TT=1)
21+
22+
# Uncomment to add displaying debug info about aspiration window
23+
add_compile_definitions(TEST_ASP_WIN=1)
24+
25+
# Uncomment to allow usage of aspiration windows inside the search
26+
#add_compile_definitions(USE_ASP_WIN=1)
27+
1228
################################################################################
1329
# Inspecting platform capabilities #
1430
################################################################################
@@ -122,6 +138,7 @@ set(CHECKMATE_CHARIOT_SOURCES
122138
include/TestsAndDebugging/TestSetup.h
123139
include/TestsAndDebugging/StateReconstructor.h
124140
include/TestsAndDebugging/DebugTools.h
141+
src/DebugTools.cpp
125142
)
126143

127144
# Create a library with the core functionality
@@ -142,6 +159,8 @@ add_executable(Checkmate-Chariot-Tests
142159
tests/Logger.cc
143160
tests/UCITranslator.cc
144161
tests/BoardEvaluator.cc
162+
tests/ChessMechanics.cc
163+
tests/SearchTests.cc
145164
)
146165
target_link_libraries(
147166
Checkmate-Chariot-Tests PRIVATE Checkmate-Core GTest::gtest_main)
@@ -174,9 +193,9 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
174193
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
175194

176195
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
177-
target_compile_options(Checkmate-Core PUBLIC -fconstexpr-ops-limit=133554432;-g;-fopenmp)
196+
target_compile_options(Checkmate-Core PUBLIC -fconstexpr-ops-limit=133554432;-g;-fopenmp;-O0)
178197
elseif (CMAKE_BUILD_TYPE STREQUAL "Release")
179-
target_compile_options(Checkmate-Core PUBLIC -O3;-march=native;-fopenmp;-fconstexpr-ops-limit=1335544322 ;-funroll-loops;-fno-peel-loops;-fno-tracer)
198+
target_compile_options(Checkmate-Core PUBLIC -O3;-march=native;-fopenmp;-fconstexpr-ops-limit=1335544322 ;-funroll-loops;-fno-peel-loops;-fno-tracer;)
180199
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
181200
target_compile_options(Checkmate-Core PUBLIC -g;-fconstexpr-ops-limit=133554432;-fopenmp;-O2;-march=native;-fopenmp)
182201
else()
@@ -201,15 +220,6 @@ else()
201220
message(FATAL_ERROR "Unknown compiler")
202221
endif()
203222

204-
# Uncomment to add gathering TT statistics
205-
add_compile_definitions(TEST_TT=1)
206-
207-
# Uncomment to add displaying debug info about aspiration window
208-
add_compile_definitions(TEST_ASP_WIN=1)
209-
210-
# Uncomment to allow usage of aspiration windows inside the search
211-
#add_compile_definitions(USE_ASP_WIN=1)
212-
213223
################################################################################
214224
# Post build #
215225
################################################################################

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Clone the repository to the desired directory:
3030

3131
Use a command below to build the project:
3232
```shell
33-
cmake CMakeLists.txt -DCMAKE_BUILD_TYPE=RELEASE
33+
cmake CMakeLists.txt -DCMAKE_BUILD_TYPE=Release ; make -j {Number of cores on your platform}
3434
```
3535
## Features
3636

Tests/searchTests.csv

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
3r2k1/B7/4q3/1R4P1/1P3r2/8/2P2P1p/R4K2 w - - 0 49, 10
2-
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1, 10
3-
r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1, 10
4-
8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1, 10
5-
r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1, 10
6-
r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1, 10
7-
rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8, 10
8-
r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10, 10
9-
3rr1k1/1pq2pp1/p2nb2p/2pp4/6PR/2PBPN2/PPQ2PP1/K2R4 b - - 0 20, 10
10-
7k/r2q1ppp/1p1p4/p1bPrPPb/P1PNPR1P/1PQ5/2B5/R5K1 w - - 23 16, 10
1+
3r2k1/B7/4q3/1R4P1/1P3r2/8/2P2P1p/R4K2 w - - 0 49, 9
2+
rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1, 9
3+
r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1, 9
4+
8/2p5/3p4/KP5r/1R3p1k/8/4P1P1/8 w - - 0 1, 9
5+
r3k2r/Pppp1ppp/1b3nbN/nP6/BBP1P3/q4N2/Pp1P2PP/R2Q1RK1 w kq - 0 1, 9
6+
r2q1rk1/pP1p2pp/Q4n2/bbp1p3/Np6/1B3NBn/pPPP1PPP/R3K2R b KQ - 0 1, 9
7+
rnbq1k1r/pp1Pbppp/2p5/8/2B5/8/PPP1NnPP/RNBQK2R w KQ - 1 8, 9
8+
r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10, 9
9+
3rr1k1/1pq2pp1/p2nb2p/2pp4/6PR/2PBPN2/PPQ2PP1/K2R4 b - - 0 20, 9
10+
7k/r2q1ppp/1p1p4/p1bPrPPb/P1PNPR1P/1PQ5/2B5/R5K1 w - - 23 16, 9

include/Board.h

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
#include <array>
99
#include <bitset>
1010
#include <cinttypes>
11+
#include <unordered_map>
1112

1213
#include "BitOperations.h"
14+
#include "CompilationConstants.h"
1315

1416
/*
1517
* Given enum defines values and order of both colors. All indexing schemes used across the projects follows given
@@ -100,6 +102,16 @@ enum CastlingPossibilities : size_t
100102

101103
struct Board
102104
{
105+
// ------------------------------
106+
// Class creation
107+
// ------------------------------
108+
109+
Board() = default;
110+
~Board() = default;
111+
112+
Board(const Board &) = default;
113+
Board &operator=(const Board &) = default;
114+
103115
// ------------------------------
104116
// class interaction
105117
// ------------------------------
@@ -115,6 +127,8 @@ struct Board
115127

116128
constexpr uint64_t GetFigBoard(int col, size_t figDesc) const { return BitBoards[col * BitBoardsPerCol + figDesc]; }
117129

130+
[[nodiscard]] bool IsEndGame() const { return LastPhase < END_GAME_PHASE; }
131+
118132
// ------------------------------
119133
// Class fields
120134
// ------------------------------
@@ -155,12 +169,28 @@ struct Board
155169
MinMsbPossible << 61 | MinMsbPossible << 62, MinMsbPossible << 58 | MinMsbPossible << 59 | MinMsbPossible << 57
156170
};
157171

158-
std::bitset<CastlingCount + 1> Castlings{0}; // additional sentinel field
159-
uint64_t ElPassantField = MaxMsbPossible >> InvalidElPassantField;
160-
int MovingColor = WHITE;
161-
int HalfMoves = {};
162-
uint64_t BitBoards[BitBoardsCount + 1] = {}; // additional sentinel board
163-
uint16_t Age{}; // stores total half moves since the beginning of the game
172+
// --------------------------------
173+
// Main processing components
174+
// --------------------------------
175+
176+
std::bitset<CastlingCount + 1> Castlings = {0}; // additional sentinel field
177+
uint64_t ElPassantField = MaxMsbPossible >> InvalidElPassantField;
178+
int MovingColor = WHITE;
179+
std::array<uint64_t, BitBoardsCount + 1> BitBoards = {}; // additional sentinel board
180+
181+
// --------------------------------------
182+
// Draw and state monitoring fields
183+
// --------------------------------------
184+
185+
int HalfMoves = {};
186+
uint16_t Age = {}; // stores total half moves since the beginning of the game
187+
std::unordered_map<uint64_t, int> Repetitions = {}; // Stores hashes of previous encountered positions
188+
189+
// ------------------------------
190+
// Optimisation components
191+
// ------------------------------
192+
193+
int LastPhase = {}; // Field used to save previously calculated phase during evaluation
164194
};
165195

166196
#endif // BOARD_H

include/CompilationConstants.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,26 @@ static constexpr int16_t SPECIAL_DRAW_SCORE = 0;
2424

2525
static constexpr int RESERVED_SCORE_VALUES = 64;
2626
static constexpr int TIME_STOP_RESERVED_VALUE = std::numeric_limits<int16_t>::max() - 1;
27-
static constexpr int NO_EVAL = std::numeric_limits<int16_t>::max() - 2;
27+
static constexpr int NO_EVAL_RESERVED_VALUE = std::numeric_limits<int16_t>::max() - 2;
28+
static constexpr int EVAL_DRAW_RESERVED_VALUE = std::numeric_limits<int16_t>::max() - 3;
2829
static constexpr int NEGATIVE_INFINITY = std::numeric_limits<int16_t>::min() + RESERVED_SCORE_VALUES + 1;
2930
static constexpr int POSITIVE_INFINITY = std::numeric_limits<int16_t>::max() - RESERVED_SCORE_VALUES;
3031
static constexpr int BEST_MATE_VALUE = NEGATIVE_INFINITY + MAX_SEARCH_DEPTH;
3132
static constexpr int BEST_MATE_VALUE_ABS = -(BEST_MATE_VALUE);
3233
static constexpr uint16_t QUIESENCE_AGE_DIFF_REPLACE = 16;
3334
static constexpr uint16_t DEFAULT_AGE_DIFF_REPLACE = 10;
3435

36+
// average pawn value + some part of average pawn
37+
static constexpr int DELTA_PRUNNING_SAFETY_MARGIN = 115 + 115 / 6;
38+
// average queen value - average pawn value
39+
static constexpr int DELTA_PRUNNING_PROMO = 1000 - 115;
40+
41+
// value below which SEE capture is considered bad
42+
static constexpr int SEE_GOOD_MOVE_BOUNDARY = 115 / 2;
43+
44+
// value of phase below game is considering to be an end-game
45+
static constexpr int END_GAME_PHASE = 64;
46+
3547
/* Depth from which Internal Iterative Deepening (IID) is used */
3648
static constexpr int IID_MIN_DEPTH = 6;
3749

@@ -63,6 +75,11 @@ static constexpr int MAX_ASP_WINDOW_RETRIES = 4;
6375

6476
#endif
6577

78+
#else
79+
80+
// No forced inline allowed
81+
#define INLINE
82+
6683
#endif // PREVENT_FORCE_INLINE
6784

6885
// ------------------------------

include/Engine.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Engine
2828
// --------------------------------------
2929

3030
public:
31-
Engine() = default;
31+
Engine();
3232

3333
/* Load with initial state */
3434
Engine(const Board &bd) : _board(bd), _startingBoard(bd) {}
@@ -72,7 +72,11 @@ class Engine
7272
/* Simply returns the moving color */
7373
[[nodiscard]] int GetMovingColor() const { return _board.MovingColor; }
7474

75-
[[nodiscard]] uint16_t GetAge() const { return _board.Age; }
75+
[[nodiscard]] uint16_t GetAge() const
76+
{
77+
TraceIfFalse(_board.Age >= 1, "Board contains age smaller than 1!");
78+
return _board.Age;
79+
}
7680

7781
/* Returns FEN encoded actual board state */
7882
[[nodiscard]] std::string GetFenTranslation() const;
@@ -128,10 +132,10 @@ class Engine
128132
// private fields
129133
// ------------------------------
130134

131-
Board _board = FenTranslator::GetDefault();
132-
Board _startingBoard = FenTranslator::GetDefault();
135+
const Board _defaultBoard;
136+
Board _board;
137+
Board _startingBoard;
133138
OpeningBook _book{};
134-
std::unordered_map<uint64_t, int> _repetitionMap{};
135139
std::string _bookPath = _defaultBookPath;
136140

137141
bool _isStartPosPlayed = true;

include/EngineUtils.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,22 @@ std::string ConvertToStrPos(uint64_t boardMap);
7474
extern const char IndexToFigCharMap[Board::BitBoardsCount];
7575

7676
/* Does the same thing as above but in reverse */
77-
extern const std::unordered_map<char, size_t> FigCharToIndexMap;
77+
/* This object must be inline due to problem with extern initialisation on startup */
78+
/* When FenTranslator referred empty not initialised map on its static field init */
79+
inline static const std::unordered_map<char, size_t> FigCharToIndexMap{
80+
{'P', wPawnsIndex},
81+
{'N', wKnightsIndex},
82+
{'B', wBishopsIndex},
83+
{'R', wRooksIndex},
84+
{'Q', wQueensIndex},
85+
{'K', wKingIndex},
86+
{'p', bPawnsIndex},
87+
{'n', bKnightsIndex},
88+
{'b', bBishopsIndex},
89+
{'r', bRooksIndex},
90+
{'q', bQueensIndex},
91+
{'k', bKingIndex}
92+
};
7893

7994
/*
8095
* Function checks whether given score is a mate,

include/Evaluation/BoardEvaluator.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,19 @@ class BoardEvaluator
122122
const auto [isSuccess, counts] = _countFigures(bd);
123123
const int32_t phase = _calcPhase(counts);
124124

125+
// save phase for later usage
126+
bd.LastPhase = phase;
127+
125128
if constexpr (mode == EvalMode::PrintMode)
126129
BoardEvaluatorPrinter::setPhase<mode>(phase);
127130

128131
const int32_t materialEval =
129132
isSuccess ? _materialTable[_getMaterialBoardIndex(counts)] : _slowMaterialCalculation<mode>(counts, phase);
133+
134+
// Avoid positional evaluation on material constellations that are enforced draws
135+
if (materialEval == EVAL_DRAW_RESERVED_VALUE)
136+
return DRAW_SCORE;
137+
130138
const int32_t positionEval = _evaluateFields<mode>(bd, phase);
131139

132140
// only to print bonuses
@@ -165,6 +173,16 @@ class BoardEvaluator
165173
return {whiteMaterial, blackMaterial};
166174
}
167175

176+
/* Function calculates phase of the given board and saves the results inside LastPhase field */
177+
static void PopulateLastPhase(Board &bd)
178+
{
179+
const auto [isSuccess, counts] = _countFigures(bd);
180+
const int32_t phase = _calcPhase(counts);
181+
182+
// save phase for later usage
183+
bd.LastPhase = phase;
184+
}
185+
168186
// ------------------------------
169187
// Private class methods
170188
// ------------------------------
@@ -436,6 +454,21 @@ class BoardEvaluator
436454
-10000 // king
437455
};
438456

457+
static constexpr int16_t ColorlessBasicFigureValues[]{
458+
100, // Pawn
459+
325, // Knight
460+
325, // Bishop
461+
500, // RookS
462+
975, // Queen
463+
10000, // king
464+
100, // Pawn
465+
325, // Knight
466+
325, // Bishop
467+
500, // Rook
468+
975, // Queen
469+
10000 // king
470+
};
471+
439472
// values that are used to calculate material value of given board at the end-game stage
440473
static constexpr int16_t EndGameFigureValues[]{
441474
130, // Pawn
@@ -564,6 +597,8 @@ class BoardEvaluator
564597

565598
static constexpr size_t BlackFigStartIndex = 5;
566599

600+
// Table stores hashed material values for material constellations limited by hash function mentioned above
601+
// In case of draw material stored value is equal to EVAL_DRAW_RESERVED_VALUE
567602
static MaterialArrayT _materialTable;
568603
};
569604

include/Interface/FenTranslator.h

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@ struct FenTranslator
1717
// Class interaction
1818
// ------------------------------
1919

20-
static const Board &GetDefault();
20+
static INLINE Board GetDefault()
21+
{
22+
Board rv;
23+
Translate(StartingPosition, rv);
24+
return rv;
25+
}
2126

2227
static bool Translate(const std::string &fenPos, Board &bd)
2328
// Function simply translates position from FEN notation into inner representation.
2429
;
2530

31+
static Board GetTranslated(const std::string &fenPos);
32+
2633
static std::string Translate(const Board &board);
2734

2835
// ------------------------------
@@ -97,21 +104,6 @@ struct FenTranslator
97104

98105
public:
99106
static constexpr auto StartingPosition = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
100-
101-
static constexpr Board StartBoard = {
102-
.Castlings = {0b11111},
103-
.ElPassantField = Board::InvalidElPassantBitBoard,
104-
.MovingColor = WHITE,
105-
.BitBoards =
106-
{
107-
65280LLU, 66LLU,
108-
36LLU, 129LLU,
109-
8LLU, 16LLU,
110-
71776119061217280LLU, 4755801206503243776LLU,
111-
2594073385365405696LLU, 9295429630892703744LLU,
112-
576460752303423488LLU, 1152921504606846976LLU,
113-
}
114-
};
115107
};
116108

117109
#endif // FENTRANSLATOR_H

0 commit comments

Comments
 (0)