Skip to content

Commit b046be7

Browse files
committed
Pooled worker threads and initial code for new tuning method.
1 parent c58e0bd commit b046be7

File tree

24 files changed

+1319
-529
lines changed

24 files changed

+1319
-529
lines changed

CMakeLists.txt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,21 @@ set(TEST_FILES testing/catch.hpp testing/runner.cpp testing/util.h testing/util.
2525
testing/tests/test_perft.cpp
2626
testing/tests/test_see.cpp
2727
testing/tests/test_hash.cpp)
28-
set(TUNE_FILES tuning/tunemain.cpp tuning/tuner.cpp tuning/tuner.h)
28+
set(TOPPLE_TUNE_FILES toppletuning/main.cpp
29+
toppletuning/game.cpp toppletuning/game.h
30+
toppletuning/toppletuner.cpp toppletuning/toppletuner.h
31+
toppletuning/ctpl_stl.h)
32+
set(TEXEL_TUNE_FILES texeltuning/main.cpp
33+
texeltuning/texel.cpp texeltuning/texel.h)
2934

3035
# Add version definitions
3136
add_definitions(-DTOPPLE_VER="${TOPPLE_VERSION}")
3237

3338
add_executable(ToppleTest ${SOURCE_FILES} ${TEST_FILES})
3439
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
3540
add_executable(Topple ${SOURCE_FILES} main.cpp)
36-
add_executable(ToppleTune ${SOURCE_FILES} ${TUNE_FILES})
41+
add_executable(ToppleTune ${SOURCE_FILES} ${TOPPLE_TUNE_FILES})
42+
add_executable(ToppleTexelTune ${SOURCE_FILES} ${TEXEL_TUNE_FILES})
3743

3844
# Link pthreads on linux
3945
set(THREADS_PREFER_PTHREAD_FLAG ON)
@@ -42,15 +48,11 @@ target_link_libraries(Topple Threads::Threads)
4248
target_link_libraries(ToppleTest Threads::Threads)
4349
target_link_libraries(ToppleTune Threads::Threads)
4450

45-
# Need static compile for MinGW on windows, but cannot compile statically on unix.
46-
if (MINGW)
47-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static")
48-
endif ()
49-
5051
# Set -march for the Topple target
5152
target_compile_options(ToppleTest PUBLIC -march=native -O3)
5253
target_compile_options(Topple PUBLIC -march=native -O3 -DNDEBUG) # NDEBUG to disable asserts
5354
target_compile_options(ToppleTune PUBLIC -DTOPPLE_TUNE -O3 -march=native -DNDEBUG)
55+
target_compile_options(ToppleTexelTune PUBLIC -DTEXEL_TUNE -O3 -march=native -DNDEBUG)
5456

5557
# Configure the "Release" target
5658
if (CMAKE_BUILD_TYPE STREQUAL "Release")

board.cpp

Lines changed: 76 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,22 @@
99
#include <cstring>
1010

1111
#include "board.h"
12-
#include "testing/catch.hpp"
1312
#include "move.h"
1413
#include "hash.h"
1514

1615
void board_t::move(move_t move) {
17-
// Copy the record
18-
memcpy(&record[now + 1], &record[now], sizeof(game_record_t));
19-
now += 1;
20-
record[now].prev_move = move;
16+
// Insert a new record
17+
record.push_back(record.back());
18+
record.back().prev_move = move;
2119

2220
// Update side hash
23-
record[now].next_move = (Team) !record[now].next_move;
24-
record[now].hash ^= zobrist::side;
21+
record.back().next_move = (Team) !record.back().next_move;
22+
record.back().hash ^= zobrist::side;
2523

2624
// Update ep hash
27-
if (record[now - 1].ep_square != 0) {
28-
record[now].ep_square = 0;
29-
record[now].hash ^= zobrist::ep[record[now - 1].ep_square];
25+
if (record.crbegin()[1].ep_square != 0) {
26+
record.back().ep_square = 0;
27+
record.back().hash ^= zobrist::ep[record.crbegin()[1].ep_square];
3028
}
3129

3230
if (move != EMPTY_MOVE) {
@@ -35,18 +33,18 @@ void board_t::move(move_t move) {
3533

3634
// Update halfmove clock
3735
if (move.info.piece == PAWN || move.info.is_capture) {
38-
record[now].halfmove_clock = 0;
36+
record.back().halfmove_clock = 0;
3937
} else {
40-
record[now].halfmove_clock++;
38+
record.back().halfmove_clock++;
4139
}
4240

4341
if (move.info.is_capture && move.info.captured_type == ROOK) {
44-
if (move.info.to == (x_team ? H8 : H1) && record[now].castle[x_team][0]) {
45-
record[now].castle[x_team][0] = false;
46-
record[now].hash ^= zobrist::castle[x_team][0];
47-
} else if (move.info.to == (x_team ? A8 : A1) && record[now].castle[x_team][1]) {
48-
record[now].castle[x_team][1] = false;
49-
record[now].hash ^= zobrist::castle[x_team][1];
42+
if (move.info.to == (x_team ? H8 : H1) && record.back().castle[x_team][0]) {
43+
record.back().castle[x_team][0] = false;
44+
record.back().hash ^= zobrist::castle[x_team][0];
45+
} else if (move.info.to == (x_team ? A8 : A1) && record.back().castle[x_team][1]) {
46+
record.back().castle[x_team][1] = false;
47+
record.back().hash ^= zobrist::castle[x_team][1];
5048
}
5149
}
5250

@@ -68,38 +66,38 @@ void board_t::move(move_t move) {
6866

6967
// Update en-passant square
7068
if (team ? move.info.to - move.info.from == -16 : move.info.to - move.info.from == 16) {
71-
record[now].ep_square = team ? move.info.to + uint8_t(8) : move.info.to - uint8_t(8);
72-
record[now].hash ^= zobrist::ep[record[now].ep_square];
69+
record.back().ep_square = team ? move.info.to + uint8_t(8) : move.info.to - uint8_t(8);
70+
record.back().hash ^= zobrist::ep[record.back().ep_square];
7371
}
7472
} else {
7573
// Update castling hashes for moving rook
7674
if (move.info.piece == ROOK) {
7775
if (team) {
78-
if (move.info.from == H8 && record[now].castle[team][0]) {
79-
record[now].hash ^= zobrist::castle[team][0];
80-
record[now].castle[team][0] = false;
81-
} else if (move.info.from == A8 && record[now].castle[team][1]) {
82-
record[now].hash ^= zobrist::castle[team][1];
83-
record[now].castle[team][1] = false;
76+
if (move.info.from == H8 && record.back().castle[team][0]) {
77+
record.back().hash ^= zobrist::castle[team][0];
78+
record.back().castle[team][0] = false;
79+
} else if (move.info.from == A8 && record.back().castle[team][1]) {
80+
record.back().hash ^= zobrist::castle[team][1];
81+
record.back().castle[team][1] = false;
8482
}
8583
} else {
86-
if (move.info.from == H1 && record[now].castle[team][0]) {
87-
record[now].hash ^= zobrist::castle[team][0];
88-
record[now].castle[team][0] = false;
89-
} else if (move.info.from == A1 && record[now].castle[team][1]) {
90-
record[now].hash ^= zobrist::castle[team][1];
91-
record[now].castle[team][1] = false;
84+
if (move.info.from == H1 && record.back().castle[team][0]) {
85+
record.back().hash ^= zobrist::castle[team][0];
86+
record.back().castle[team][0] = false;
87+
} else if (move.info.from == A1 && record.back().castle[team][1]) {
88+
record.back().hash ^= zobrist::castle[team][1];
89+
record.back().castle[team][1] = false;
9290
}
9391
}
9492
} else if (move.info.piece == KING) {
9593
// Update castling hashes
96-
if (record[now].castle[team][0]) {
97-
record[now].hash ^= zobrist::castle[team][0];
98-
record[now].castle[team][0] = false;
94+
if (record.back().castle[team][0]) {
95+
record.back().hash ^= zobrist::castle[team][0];
96+
record.back().castle[team][0] = false;
9997
}
100-
if (record[now].castle[team][1]) {
101-
record[now].hash ^= zobrist::castle[team][1];
102-
record[now].castle[team][1] = false;
98+
if (record.back().castle[team][1]) {
99+
record.back().hash ^= zobrist::castle[team][1];
100+
record.back().castle[team][1] = false;
103101
}
104102

105103
if (move.info.castle) {
@@ -121,8 +119,8 @@ void board_t::move(move_t move) {
121119
}
122120

123121
void board_t::unmove() {
124-
move_t move = record[now].prev_move;
125-
now -= 1;
122+
move_t move = record.back().prev_move;
123+
record.pop_back();
126124

127125
if (move != EMPTY_MOVE) {
128126
if (move.info.piece == PAWN) {
@@ -169,6 +167,8 @@ board_t::board_t(const std::string &fen) {
169167
std::string("FEN: ") + std::to_string(split.size()) + std::string(" components, 4-6 expected"));
170168
}
171169

170+
record.emplace_back();
171+
172172
// Parse board
173173
uint8_t file = 0, rank = 7;
174174
for (char ch : split[0]) {
@@ -348,23 +348,23 @@ move_t board_t::to_move(packed_move_t packed_move) const {
348348
}
349349

350350
// EP
351-
move.info.is_capture |= move.info.is_ep = static_cast<uint16_t>(record[now].ep_square != 0
351+
move.info.is_capture |= move.info.is_ep = static_cast<uint16_t>(record.back().ep_square != 0
352352
&& move.info.piece == PAWN
353-
&& move.info.to == record[now].ep_square);
353+
&& move.info.to == record.back().ep_square);
354354

355355
return move;
356356
}
357357

358358
bool board_t::is_illegal() const {
359-
Team side = record[now].next_move;
359+
Team side = record.back().next_move;
360360
uint8_t king_square = bit_scan(bb_pieces[!side][KING]);
361361

362362
return is_attacked(king_square, side);
363363
}
364364

365365

366366
bool board_t::is_incheck() const {
367-
Team side = record[now].next_move;
367+
Team side = record.back().next_move;
368368
uint8_t king_square = bit_scan(bb_pieces[side][KING]);
369369

370370
return is_attacked(king_square, Team(!side));
@@ -388,10 +388,10 @@ void board_t::switch_piece(Team side, Piece piece, uint8_t sq) {
388388

389389
if (HASH) { // Update hash
390390
U64 square_hash = zobrist::squares[sq][side][piece];
391-
record[now].hash ^= square_hash;
392-
if(piece == PAWN || piece == KING) record[now].kp_hash ^= square_hash;
393-
if(sq_data[sq].occupied) record[now].material.info.inc(side, piece);
394-
else record[now].material.info.dec(side, piece);
391+
record.back().hash ^= square_hash;
392+
if(piece == PAWN || piece == KING) record.back().kp_hash ^= square_hash;
393+
if(sq_data[sq].occupied) record.back().material.info.inc(side, piece);
394+
else record.back().material.info.dec(side, piece);
395395
}
396396
}
397397

@@ -430,10 +430,10 @@ bool board_t::is_pseudo_legal(move_t move) const {
430430
auto team = Team(move.info.team);
431431
auto x_team = Team(!move.info.team);
432432

433-
if (record[now].next_move != team) return false;
433+
if (record.back().next_move != team) return false;
434434

435435
if (move.info.castle) {
436-
if (record[now].castle[move.info.team][move.info.castle_side] == 0) return false;
436+
if (record.back().castle[move.info.team][move.info.castle_side] == 0) return false;
437437
if (move.info.castle_side == 0) {
438438
return (bb_all & bits_between(team ? E8 : E1, team ? H8 : H1)) == 0 &&
439439
!is_attacked(team ? E8 : E1, x_team) &&
@@ -454,7 +454,7 @@ bool board_t::is_pseudo_legal(move_t move) const {
454454
}
455455

456456
if(move.info.is_ep) {
457-
if(record[now].ep_square == 0 || move.info.to != record[now].ep_square) {
457+
if(record.back().ep_square == 0 || move.info.to != record.back().ep_square) {
458458
return false;
459459
}
460460
} else {
@@ -559,10 +559,10 @@ bool board_t::gives_check(move_t move) const {
559559
bool board_t::is_repetition_draw(int search_ply) const {
560560
int rep = 1;
561561

562-
int max = record[now].halfmove_clock;
562+
int max = record.back().halfmove_clock;
563563

564564
for (int i = 2; i <= max; i += 2) {
565-
if (record[now - i].hash == record[now].hash) rep++;
565+
if (record.crbegin()[i].hash == record.back().hash) rep++;
566566
if (rep >= 3) return true;
567567
if (rep >= 2 && i < search_ply) return true;
568568
}
@@ -571,38 +571,38 @@ bool board_t::is_repetition_draw(int search_ply) const {
571571
}
572572

573573
bool board_t::is_material_draw() const {
574-
if(record[now].material.info.w_pawns || record[now].material.info.b_pawns ||
575-
record[now].material.info.w_queens || record[now].material.info.b_queens ||
576-
record[now].material.info.w_rooks || record[now].material.info.b_rooks) {
574+
if(record.back().material.info.w_pawns || record.back().material.info.b_pawns ||
575+
record.back().material.info.w_queens || record.back().material.info.b_queens ||
576+
record.back().material.info.w_rooks || record.back().material.info.b_rooks) {
577577
return false;
578578
} else {
579-
return record[now].material.info.w_bishops + record[now].material.info.b_bishops
580-
+ record[now].material.info.w_knights + record[now].material.info.b_knights <= 1;
579+
return record.back().material.info.w_bishops + record.back().material.info.b_bishops
580+
+ record.back().material.info.w_knights + record.back().material.info.b_knights <= 1;
581581
}
582582
}
583583

584584
void board_t::mirror() {
585585
// Mirror side
586-
record[now].next_move = (Team) !record[now].next_move;
587-
record[now].hash ^= zobrist::side;
586+
record.back().next_move = (Team) !record.back().next_move;
587+
record.back().hash ^= zobrist::side;
588588

589589
// Mirror en-passant
590-
if (record[now].ep_square != 0) {
591-
record[now].hash ^= zobrist::ep[record[now].ep_square];
592-
record[now].ep_square = MIRROR_TABLE[record[now].ep_square];
593-
record[now].hash ^= zobrist::ep[record[now].ep_square];
590+
if (record.back().ep_square != 0) {
591+
record.back().hash ^= zobrist::ep[record.back().ep_square];
592+
record.back().ep_square = MIRROR_TABLE[record.back().ep_square];
593+
record.back().hash ^= zobrist::ep[record.back().ep_square];
594594
}
595595

596596
// Mirror castling rights
597-
if(record[now].castle[0][0] != record[now].castle[1][0]) {
598-
record[now].hash ^= zobrist::castle[0][0];
599-
record[now].hash ^= zobrist::castle[1][0];
600-
std::swap(record[now].castle[0][0], record[now].castle[1][0]);
597+
if(record.back().castle[0][0] != record.back().castle[1][0]) {
598+
record.back().hash ^= zobrist::castle[0][0];
599+
record.back().hash ^= zobrist::castle[1][0];
600+
std::swap(record.back().castle[0][0], record.back().castle[1][0]);
601601
}
602-
if(record[now].castle[0][1] != record[now].castle[1][1]) {
603-
record[now].hash ^= zobrist::castle[0][1];
604-
record[now].hash ^= zobrist::castle[1][1];
605-
std::swap(record[now].castle[0][1], record[now].castle[1][1]);
602+
if(record.back().castle[0][1] != record.back().castle[1][1]) {
603+
record.back().hash ^= zobrist::castle[0][1];
604+
record.back().hash ^= zobrist::castle[1][1];
605+
std::swap(record.back().castle[0][1], record.back().castle[1][1]);
606606
}
607607

608608
// Mirror pieces
@@ -710,3 +710,7 @@ int board_t::see(move_t move) const {
710710
U64 board_t::non_pawn_material(Team side) const {
711711
return (bb_side[side] ^ bb_pieces[side][PAWN] ^ bb_pieces[side][KING]);
712712
}
713+
714+
void board_t::print() {
715+
std::cout << *this;
716+
}

board.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,19 @@ struct alignas(64) board_t {
8282
sq_data_t sq_data[64] = {{}};
8383

8484
/* Game history */
85-
int now = 0; // Index for record array
86-
#ifdef TOPPLE_TUNE
87-
game_record_t record[4] = {{}}; // Shortened record to save memory while tuning
88-
#else
89-
game_record_t record[4096] = {{}}; // Record (supporting games of up to 4096 moves)
90-
#endif
85+
std::vector<game_record_t> record;
9186

9287
/* Internal methods */
9388
template<bool HASH>
9489
void switch_piece(Team side, Piece piece, uint8_t sq);
90+
91+
void print();
9592
};
9693

9794
inline std::ostream &operator<<(std::ostream &stream, const board_t &board) {
9895
stream << std::endl;
9996

100-
for (int i = 1; i <= board.now; i++) {
97+
for (int i = 1; i <= board.record.size(); i++) {
10198
if (i % 2 != 0) {
10299
stream << " " << ((i + 1) / 2) << ". ";
103100
}

0 commit comments

Comments
 (0)