commit 664eeb29d4722c4663863878105d1561ce7d9bb4
parent 75e27270d7d82dceb3274989abbe149546584541
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Mon, 11 Mar 2024 18:55:44 +0100
Merge pull request #2 from DimitrijeDobrota/1-windows-exe
Solved: 1 windows exe
Diffstat:
27 files changed, 295 insertions(+), 337 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
- VERSION 1.2.0
+ VERSION 1.2.6
DESCRIPTION "Chess engine written in C++"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES CXX
@@ -25,39 +25,14 @@ set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
FORCE
)
+add_subdirectory(src)
-include(CheckCXXCompilerFlag)
-
-option(STELLAR_ENABLE_PCH "Build using pre-compiled headers" ON)
-function(stellar_target_precompile_headers)
- if(STELLAR_ENABLE_PCH)
- target_precompile_headers(${ARGV})
- endif()
-endfunction()
-
-CHECK_CXX_COMPILER_FLAG("-flto" COMPILER_SUPPORTS_LTO)
-if(COMPILER_SUPPORTS_LTO)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
-endif()
-
-CHECK_CXX_COMPILER_FLAG("-fno-fat-lto-objects" COMPILER_SUPPORTS_LTO_NOFAT)
-if(COMPILER_SUPPORTS_LTO_NOFAT)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-fat-lto-objects")
-endif()
-
-CHECK_CXX_COMPILER_FLAG("-fconstexpr-ops-limit=10000000000" COMPILER_SUPPORTS_CONSTEXPR_OPS_LIMIT)
-if(COMPILER_SUPPORTS_CONSTEXPR_OPS_LIMIT)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fconstexpr-ops-limit=1000000000")
-endif()
-
-CHECK_CXX_COMPILER_FLAG("-fconstexpr-steps=1000000000" COMPILER_SUPPORTS_CONSTEXPR_STEPS)
-if(COMPILER_SUPPORTS_CONSTEXPR_STEPS)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fconstexpr-steps=1000000000")
-endif()
+include(CheckIPOSupported)
+check_ipo_supported(RESULT lto_supported OUTPUT lto_error)
-CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCH_NATIVE)
-if(COMPILER_SUPPORTS_MARCH_NATIVE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+if( lto_supported )
+ message(STATUS "IPO / LTO enabled")
+ set_property(TARGET engine PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+else()
+ message(STATUS "IPO / LTO not supported: <${error}>")
endif()
-
-add_subdirectory(src)
diff --git a/src/arena/arena.cpp b/src/arena/arena.cpp
@@ -7,6 +7,7 @@
#include <bits/getopt_core.h>
#include <stdexcept>
+#include "attack.hpp"
#include "logger.hpp"
#include "match.hpp"
@@ -95,6 +96,8 @@ int main(int argc, char *argv[]) {
for (int i = optind; i < argc; i++)
positions.emplace_back(!strcmp(argv[i], "-") ? start_position : argv[i]);
+ attack::init();
+ zobrist::init();
Arena arena(engine1, engine2);
arena(positions, settings1, settings2);
diff --git a/src/arena/engine.hpp b/src/arena/engine.hpp
@@ -1,7 +1,9 @@
#ifndef STELLAR_ARENA_ENGINE_H
#define STELLAR_ARENA_ENGINE_H
+#include <cstdint>
#include <queue>
+#include <string>
class Engine {
public:
diff --git a/src/arena/logger.hpp b/src/arena/logger.hpp
@@ -5,6 +5,7 @@
#include <cerrno>
#include <cstring>
#include <format>
+#include <iostream>
namespace logger {
diff --git a/src/attack/CMakeLists.txt b/src/attack/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_library(attack attack.cpp)
+add_library(attack attack.cpp bishop.cpp rook.cpp)
target_link_libraries(attack
PRIVATE bit
@@ -9,14 +9,3 @@ target_link_libraries(attack
)
target_include_directories(attack INTERFACE .)
-
-stellar_target_precompile_headers(attack
- PRIVATE "bishop.hpp"
- PRIVATE "king.hpp"
- PRIVATE "knight.hpp"
- PRIVATE "pawnb.hpp"
- PRIVATE "pawnw.hpp"
- PRIVATE "queen.hpp"
- PRIVATE "rook.hpp"
- PRIVATE "slider.hpp"
-)
diff --git a/src/attack/attack.cpp b/src/attack/attack.cpp
@@ -1 +1,10 @@
#include "attack.hpp"
+
+namespace attack {
+
+void init(void) {
+ bishop::init();
+ rook::init();
+}
+
+} // namespace attack
diff --git a/src/attack/attack.hpp b/src/attack/attack.hpp
@@ -11,12 +11,12 @@
#include "pawnw.hpp"
#include "queen.hpp"
#include "rook.hpp"
-#include "slider.hpp"
namespace attack {
+void init(void);
using attack_f = U64 (*)(const square::Square, U64);
-}
+} // namespace attack
#endif
diff --git a/src/attack/bishop.cpp b/src/attack/bishop.cpp
@@ -0,0 +1,94 @@
+#include "bishop.hpp"
+#include "bit.hpp"
+#include "bitboard.hpp"
+#include "slider.hpp"
+
+#include <array>
+#include <iostream>
+
+namespace attack {
+namespace bishop {
+
+inline constexpr const U64 bishop_magic_numbers[64] = {
+ C64(0x40040844404084), C64(0x2004208a004208), C64(0x10190041080202), C64(0x108060845042010),
+ C64(0x581104180800210), C64(0x2112080446200010), C64(0x1080820820060210), C64(0x3c0808410220200),
+ C64(0x4050404440404), C64(0x21001420088), C64(0x24d0080801082102), C64(0x1020a0a020400),
+ C64(0x40308200402), C64(0x4011002100800), C64(0x401484104104005), C64(0x801010402020200),
+ C64(0x400210c3880100), C64(0x404022024108200), C64(0x810018200204102), C64(0x4002801a02003),
+ C64(0x85040820080400), C64(0x810102c808880400), C64(0xe900410884800), C64(0x8002020480840102),
+ C64(0x220200865090201), C64(0x2010100a02021202), C64(0x152048408022401), C64(0x20080002081110),
+ C64(0x4001001021004000), C64(0x800040400a011002), C64(0xe4004081011002), C64(0x1c004001012080),
+ C64(0x8004200962a00220), C64(0x8422100208500202), C64(0x2000402200300c08), C64(0x8646020080080080),
+ C64(0x80020a0200100808), C64(0x2010004880111000), C64(0x623000a080011400), C64(0x42008c0340209202),
+ C64(0x209188240001000), C64(0x400408a884001800), C64(0x110400a6080400), C64(0x1840060a44020800),
+ C64(0x90080104000041), C64(0x201011000808101), C64(0x1a2208080504f080), C64(0x8012020600211212),
+ C64(0x500861011240000), C64(0x180806108200800), C64(0x4000020e01040044), C64(0x300000261044000a),
+ C64(0x802241102020002), C64(0x20906061210001), C64(0x5a84841004010310), C64(0x4010801011c04),
+ C64(0xa010109502200), C64(0x4a02012000), C64(0x500201010098b028), C64(0x8040002811040900),
+ C64(0x28000010020204), C64(0x6000020202d0240), C64(0x8918844842082200), C64(0x4010011029020020),
+};
+
+static inline constexpr const int relevant_bits[64] = {
+ // clang-format off
+ 6, 5, 5, 5, 5, 5, 5, 6,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 7, 7, 7, 7, 5, 5,
+ 5, 5, 7, 9, 9, 7, 5, 5,
+ 5, 5, 7, 9, 9, 7, 5, 5,
+ 5, 5, 7, 7, 7, 7, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 5, 5, 5, 5, 5, 5, 6,
+ // clang-format on
+};
+
+inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboard::noWeOne,
+ bitboard::soEaOne, bitboard::soWeOne};
+
+inline constexpr U32 hash(const U64 key, const square::Square square) {
+ uint8_t square_i = to_underlying(square);
+ return (key * bishop_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
+}
+
+inline constexpr U64 mask_fly(const square::Square square, U64 block) {
+ uint8_t square_i = to_underlying(square);
+ int tr = square_i / 8, tf = square_i % 8;
+ int len[4] = {std::min(7 - tf, 7 - tr), std::min(tf, 7 - tr), std::min(7 - tf, tr), std::min(tf, tr)};
+
+ return attack::slider::mask(square, block, dir, len);
+}
+
+std::array<U64, 64> masks = {{0}};
+inline U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
+
+std::array<std::array<U64, 4098>, 64> attacks = {{{0}}};
+
+void init(void) {
+ for (uint8_t square = 0; square < 64; square++) {
+ int tr = square / 8, tf = square % 8;
+ int len[4] = {std::min(7 - tf, 7 - tr) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1,
+ std::min(tf, tr) - 1};
+ masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
+ }
+
+ for (uint8_t square = 0; square < 64; square++) {
+ square::Square Square = static_cast<square::Square>(square);
+ U64 attack_mask = mask(Square);
+ uint8_t relevant_bits = bit::count(attack_mask);
+ U64 occupancy_indices = C64(1) << relevant_bits;
+
+ for (U64 idx = 0; idx < occupancy_indices; idx++) {
+ U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask);
+ U32 magic_index = hash(occupancy, Square);
+ attacks[square][magic_index] = mask_fly(Square, occupancy);
+ }
+ }
+}
+
+U64 attack(const square::Square square, U64 occupancy) {
+ occupancy &= mask(square);
+ occupancy = hash(occupancy, square);
+ return attacks[to_underlying(square)][occupancy];
+}
+
+} // namespace bishop
+} // namespace attack
diff --git a/src/attack/bishop.hpp b/src/attack/bishop.hpp
@@ -1,103 +1,16 @@
-#ifndef STELLAR_ATTACK_BISHOP_H
-#define STELLAR_ATTACK_BISHOP_H
+#ifndef STELLAR_BISHOP_H
+#define STELLAR_BISHOP_H
-#include "bit.hpp"
-#include "bitboard.hpp"
-#include "slider.hpp"
#include "square.hpp"
#include "utils.hpp"
-#include <array>
-
namespace attack {
namespace bishop {
-inline constexpr const U64 bishop_magic_numbers[64] = {
- C64(0x40040844404084), C64(0x2004208a004208), C64(0x10190041080202), C64(0x108060845042010),
- C64(0x581104180800210), C64(0x2112080446200010), C64(0x1080820820060210), C64(0x3c0808410220200),
- C64(0x4050404440404), C64(0x21001420088), C64(0x24d0080801082102), C64(0x1020a0a020400),
- C64(0x40308200402), C64(0x4011002100800), C64(0x401484104104005), C64(0x801010402020200),
- C64(0x400210c3880100), C64(0x404022024108200), C64(0x810018200204102), C64(0x4002801a02003),
- C64(0x85040820080400), C64(0x810102c808880400), C64(0xe900410884800), C64(0x8002020480840102),
- C64(0x220200865090201), C64(0x2010100a02021202), C64(0x152048408022401), C64(0x20080002081110),
- C64(0x4001001021004000), C64(0x800040400a011002), C64(0xe4004081011002), C64(0x1c004001012080),
- C64(0x8004200962a00220), C64(0x8422100208500202), C64(0x2000402200300c08), C64(0x8646020080080080),
- C64(0x80020a0200100808), C64(0x2010004880111000), C64(0x623000a080011400), C64(0x42008c0340209202),
- C64(0x209188240001000), C64(0x400408a884001800), C64(0x110400a6080400), C64(0x1840060a44020800),
- C64(0x90080104000041), C64(0x201011000808101), C64(0x1a2208080504f080), C64(0x8012020600211212),
- C64(0x500861011240000), C64(0x180806108200800), C64(0x4000020e01040044), C64(0x300000261044000a),
- C64(0x802241102020002), C64(0x20906061210001), C64(0x5a84841004010310), C64(0x4010801011c04),
- C64(0xa010109502200), C64(0x4a02012000), C64(0x500201010098b028), C64(0x8040002811040900),
- C64(0x28000010020204), C64(0x6000020202d0240), C64(0x8918844842082200), C64(0x4010011029020020),
-};
-
-static inline constexpr const int relevant_bits[64] = {
- // clang-format off
- 6, 5, 5, 5, 5, 5, 5, 6,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 7, 7, 7, 7, 5, 5,
- 5, 5, 7, 9, 9, 7, 5, 5,
- 5, 5, 7, 9, 9, 7, 5, 5,
- 5, 5, 7, 7, 7, 7, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, 5,
- 6, 5, 5, 5, 5, 5, 5, 6,
- // clang-format on
-};
+void init(void);
+U64 attack(const square::Square square, U64 occupancy);
-inline constexpr const bitboard::direction_f dir[4] = {bitboard::noEaOne, bitboard::noWeOne,
- bitboard::soEaOne, bitboard::soWeOne};
-
-inline constexpr U32 hash(const U64 key, const square::Square square) {
- uint8_t square_i = to_underlying(square);
- return (key * bishop_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
}
-
-inline constexpr U64 mask_fly(const square::Square square, U64 block) {
- uint8_t square_i = to_underlying(square);
- int tr = square_i / 8, tf = square_i % 8;
- int len[4] = {std::min(7 - tf, 7 - tr), std::min(tf, 7 - tr), std::min(7 - tf, tr), std::min(tf, tr)};
-
- return slider::mask(square, block, dir, len);
-}
-
-inline constexpr const std::array<U64, 64> masks = []() constexpr -> std::array<U64, 64> {
- std::array<U64, 64> masks;
- for (uint8_t square = 0; square < 64; square++) {
- int tr = square / 8, tf = square % 8;
- int len[4] = {std::min(7 - tf, 7 - tr) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1,
- std::min(tf, tr) - 1};
- masks[square] = slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
- }
- return masks;
-}();
-
-inline constexpr U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
-
-using attack_array = std::array<std::array<U64, 4096>, 64>;
-inline constexpr const attack_array attacks = []() constexpr -> attack_array {
- attack_array attacks = {{{0}}};
- for (uint8_t square = 0; square < 64; square++) {
- square::Square Square = static_cast<square::Square>(square);
- U64 attack_mask = mask(Square);
- uint8_t relevant_bits = bit::count(attack_mask);
- U64 occupancy_indices = C64(1) << relevant_bits;
-
- for (U64 idx = 0; idx < occupancy_indices; idx++) {
- U64 occupancy = slider::occupancy(idx, relevant_bits, attack_mask);
- U32 magic_index = hash(occupancy, Square);
- attacks[square][magic_index] = mask_fly(Square, occupancy);
- }
- }
- return attacks;
-}();
-
-inline constexpr U64 attack(const square::Square square, U64 occupancy) {
- occupancy &= mask(square);
- occupancy = hash(occupancy, square);
- return attacks[to_underlying(square)][occupancy];
-}
-
-} // namespace bishop
} // namespace attack
#endif
diff --git a/src/attack/queen.hpp b/src/attack/queen.hpp
@@ -7,7 +7,7 @@
namespace attack {
namespace queen {
-inline constexpr U64 attack(const square::Square square, U64 occupancy) {
+inline U64 attack(const square::Square square, U64 occupancy) {
return rook::attack(square, occupancy) | bishop::attack(square, occupancy);
}
diff --git a/src/attack/rook.cpp b/src/attack/rook.cpp
@@ -0,0 +1,93 @@
+#include "rook.hpp"
+#include "bit.hpp"
+#include "bitboard.hpp"
+#include "slider.hpp"
+
+#include <array>
+
+namespace attack {
+namespace rook {
+
+inline constexpr const int relevant_bits[64] = {
+ // clang-format off
+ 12, 11, 11, 11, 11, 11, 11, 12,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 11, 10, 10, 10, 10, 10, 10, 11,
+ 12, 11, 11, 11, 11, 11, 11, 12,
+ // clang-format on
+};
+
+inline constexpr const U64 rook_magic_numbers[64] = {
+ C64(0x8a80104000800020), C64(0x140002000100040), C64(0x2801880a0017001), C64(0x100081001000420),
+ C64(0x200020010080420), C64(0x3001c0002010008), C64(0x8480008002000100), C64(0x2080088004402900),
+ C64(0x800098204000), C64(0x2024401000200040), C64(0x100802000801000), C64(0x120800800801000),
+ C64(0x208808088000400), C64(0x2802200800400), C64(0x2200800100020080), C64(0x801000060821100),
+ C64(0x80044006422000), C64(0x100808020004000), C64(0x12108a0010204200), C64(0x140848010000802),
+ C64(0x481828014002800), C64(0x8094004002004100), C64(0x4010040010010802), C64(0x20008806104),
+ C64(0x100400080208000), C64(0x2040002120081000), C64(0x21200680100081), C64(0x20100080080080),
+ C64(0x2000a00200410), C64(0x20080800400), C64(0x80088400100102), C64(0x80004600042881),
+ C64(0x4040008040800020), C64(0x440003000200801), C64(0x4200011004500), C64(0x188020010100100),
+ C64(0x14800401802800), C64(0x2080040080800200), C64(0x124080204001001), C64(0x200046502000484),
+ C64(0x480400080088020), C64(0x1000422010034000), C64(0x30200100110040), C64(0x100021010009),
+ C64(0x2002080100110004), C64(0x202008004008002), C64(0x20020004010100), C64(0x2048440040820001),
+ C64(0x101002200408200), C64(0x40802000401080), C64(0x4008142004410100), C64(0x2060820c0120200),
+ C64(0x1001004080100), C64(0x20c020080040080), C64(0x2935610830022400), C64(0x44440041009200),
+ C64(0x280001040802101), C64(0x2100190040002085), C64(0x80c0084100102001), C64(0x4024081001000421),
+ C64(0x20030a0244872), C64(0x12001008414402), C64(0x2006104900a0804), C64(0x1004081002402),
+};
+
+inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboard::soutOne,
+ bitboard::eastOne, bitboard::nortOne};
+
+inline constexpr U32 hash(const U64 key, const square::Square square) {
+ uint8_t square_i = to_underlying(square);
+ return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
+}
+
+inline constexpr U64 mask_fly(const square::Square square, U64 block) {
+ uint8_t square_i = to_underlying(square);
+ int tr = square_i / 8, tf = square_i % 8;
+ int len[4] = {tf, tr, 7 - tf, 7 - tr};
+
+ return attack::slider::mask(square, block, dir, len);
+}
+
+std::array<U64, 64> masks = {{0}};
+U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
+
+std::array<std::array<U64, 4096>, 64> attacks = {{{0}}};
+
+void init(void) {
+ for (uint8_t square = 0; square < 64; square++) {
+ const int tr = square / 8, tf = square % 8;
+ const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr};
+
+ masks[square] = attack::slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
+ }
+
+ for (uint8_t square = 0; square < 64; square++) {
+ square::Square Square = static_cast<square::Square>(square);
+ U64 attack_mask = mask(Square);
+ uint8_t relevant_bits = bit::count(attack_mask);
+ U64 occupancy_indices = C64(1) << relevant_bits;
+
+ for (U64 idx = 0; idx < occupancy_indices; idx++) {
+ U64 occupancy = attack::slider::occupancy(idx, relevant_bits, attack_mask);
+ U32 magic_index = hash(occupancy, Square);
+ attacks[square][magic_index] = mask_fly(Square, occupancy);
+ }
+ }
+}
+
+U64 attack(const square::Square square, U64 occupancy) {
+ occupancy &= mask(square);
+ occupancy = hash(occupancy, square);
+ return attacks[to_underlying(square)][occupancy];
+}
+
+} // namespace rook
+} // namespace attack
diff --git a/src/attack/rook.hpp b/src/attack/rook.hpp
@@ -1,101 +1,14 @@
#ifndef STELLAR_ATTACK_ROOK_H
#define STELLAR_ATTACK_ROOK_H
-#include "bit.hpp"
-#include "bitboard.hpp"
-#include "slider.hpp"
#include "square.hpp"
#include "utils.hpp"
-#include <array>
-
namespace attack {
namespace rook {
-inline constexpr const int relevant_bits[64] = {
- // clang-format off
- 12, 11, 11, 11, 11, 11, 11, 12,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 11, 10, 10, 10, 10, 10, 10, 11,
- 12, 11, 11, 11, 11, 11, 11, 12,
- // clang-format on
-};
-
-inline constexpr const U64 rook_magic_numbers[64] = {
- C64(0x8a80104000800020), C64(0x140002000100040), C64(0x2801880a0017001), C64(0x100081001000420),
- C64(0x200020010080420), C64(0x3001c0002010008), C64(0x8480008002000100), C64(0x2080088004402900),
- C64(0x800098204000), C64(0x2024401000200040), C64(0x100802000801000), C64(0x120800800801000),
- C64(0x208808088000400), C64(0x2802200800400), C64(0x2200800100020080), C64(0x801000060821100),
- C64(0x80044006422000), C64(0x100808020004000), C64(0x12108a0010204200), C64(0x140848010000802),
- C64(0x481828014002800), C64(0x8094004002004100), C64(0x4010040010010802), C64(0x20008806104),
- C64(0x100400080208000), C64(0x2040002120081000), C64(0x21200680100081), C64(0x20100080080080),
- C64(0x2000a00200410), C64(0x20080800400), C64(0x80088400100102), C64(0x80004600042881),
- C64(0x4040008040800020), C64(0x440003000200801), C64(0x4200011004500), C64(0x188020010100100),
- C64(0x14800401802800), C64(0x2080040080800200), C64(0x124080204001001), C64(0x200046502000484),
- C64(0x480400080088020), C64(0x1000422010034000), C64(0x30200100110040), C64(0x100021010009),
- C64(0x2002080100110004), C64(0x202008004008002), C64(0x20020004010100), C64(0x2048440040820001),
- C64(0x101002200408200), C64(0x40802000401080), C64(0x4008142004410100), C64(0x2060820c0120200),
- C64(0x1001004080100), C64(0x20c020080040080), C64(0x2935610830022400), C64(0x44440041009200),
- C64(0x280001040802101), C64(0x2100190040002085), C64(0x80c0084100102001), C64(0x4024081001000421),
- C64(0x20030a0244872), C64(0x12001008414402), C64(0x2006104900a0804), C64(0x1004081002402),
-};
-
-inline constexpr const bitboard::direction_f dir[4] = {bitboard::westOne, bitboard::soutOne,
- bitboard::eastOne, bitboard::nortOne};
-
-inline constexpr U32 hash(const U64 key, const square::Square square) {
- uint8_t square_i = to_underlying(square);
- return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
-}
-
-inline constexpr U64 mask_fly(const square::Square square, U64 block) {
- uint8_t square_i = to_underlying(square);
- int tr = square_i / 8, tf = square_i % 8;
- int len[4] = {tf, tr, 7 - tf, 7 - tr};
-
- return slider::mask(square, block, dir, len);
-}
-
-inline constexpr const std::array<U64, 64> masks = []() constexpr -> std::array<U64, 64> {
- std::array<U64, 64> masks;
- for (uint8_t square = 0; square < 64; square++) {
- const int tr = square / 8, tf = square % 8;
- const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr};
-
- masks[square] = slider::mask(static_cast<square::Square>(square), C64(0), dir, len);
- }
- return masks;
-}();
-
-inline constexpr U64 mask(const square::Square square) { return masks[to_underlying(square)]; }
-
-using attack_array = std::array<std::array<U64, 4096>, 64>;
-inline constexpr const attack_array attacks = []() constexpr -> attack_array {
- attack_array attacks = {{{0}}};
- for (uint8_t square = 0; square < 64; square++) {
- square::Square Square = static_cast<square::Square>(square);
- U64 attack_mask = mask(Square);
- uint8_t relevant_bits = bit::count(attack_mask);
- U64 occupancy_indices = C64(1) << relevant_bits;
-
- for (U64 idx = 0; idx < occupancy_indices; idx++) {
- U64 occupancy = slider::occupancy(idx, relevant_bits, attack_mask);
- U32 magic_index = hash(occupancy, Square);
- attacks[square][magic_index] = mask_fly(Square, occupancy);
- }
- }
- return attacks;
-}();
-
-inline constexpr U64 attack(const square::Square square, U64 occupancy) {
- occupancy &= mask(square);
- occupancy = hash(occupancy, square);
- return attacks[to_underlying(square)][occupancy];
-}
+void init(void);
+U64 attack(const square::Square square, U64 occupancy);
} // namespace rook
} // namespace attack
diff --git a/src/attack/slider.hpp b/src/attack/slider.hpp
@@ -1,6 +1,8 @@
#ifndef STELLAR_ATTAKC_SLIDER_H
#define STELLAR_ATTAKC_SLIDER_H
+#include "bit.hpp"
+#include "bitboard.hpp"
#include "square.hpp"
#include "utils.hpp"
diff --git a/src/board/CMakeLists.txt b/src/board/CMakeLists.txt
@@ -9,6 +9,3 @@ target_link_libraries(board
)
target_include_directories(board INTERFACE .)
-stellar_target_precompile_headers(board INTERFACE "board.hpp")
-
-
diff --git a/src/board/board.cpp b/src/board/board.cpp
@@ -1,7 +1,7 @@
#include <cctype>
-#include <exception>
#include <cstdio>
#include <cstring>
+#include <exception>
#include "board.hpp"
#include "piece.hpp"
@@ -9,6 +9,11 @@
#include "utils.hpp"
#include "zobrist.hpp"
+/* Init arrays for Zobris hashing */
+std::array<std::array<U64, 64>, 12> zobrist::keys_piece = {{{0}}};
+std::array<U64, 64> zobrist::keys_enpassant = {{0}};
+std::array<U64, 16> zobrist::keys_castle = {{0}};
+
/* Getters */
Board::Board(const std::string &fen) {
@@ -34,8 +39,7 @@ Board::Board(const std::string &fen) {
: throw std::runtime_error("Invalid player char");
for (i += 2; fen[i] != ' '; i++) {
- if (fen[i] == 'K')
- castle |= to_underlying(Castle::WK);
+ if (fen[i] == 'K') castle |= to_underlying(Castle::WK);
else if (fen[i] == 'Q')
castle |= to_underlying(Castle::WQ);
else if (fen[i] == 'k')
@@ -51,7 +55,7 @@ Board::Board(const std::string &fen) {
enpassant = fen[++i] != '-' ? square::from_coordinates(fen.substr(i, 2)) : square::no_sq;
- hash = Zobrist::hash(*this);
+ hash = zobrist::hash(*this);
}
std::ostream &operator<<(std::ostream &os, const Board &board) {
diff --git a/src/board/board.hpp b/src/board/board.hpp
@@ -41,11 +41,11 @@ class Board {
[[nodiscard]] inline constexpr U64 get_bitboard_piece(piece::Type piece, color::Color color) const;
[[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(piece::Type piece, color::Color color,
- square::Square from) const;
+ square::Square from) const;
[[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(piece::Type piece, color::Color color,
- square::Square from) const;
+ square::Square from) const;
[[nodiscard]] inline constexpr U64 get_bitboard_square_land(square::Square land, piece::Type piece,
- color::Color side) const;
+ color::Color side) const;
[[nodiscard]] inline constexpr color::Color get_square_piece_color(square::Square square) const;
[[nodiscard]] inline constexpr piece::Type get_square_piece_type(square::Square square) const;
@@ -71,8 +71,9 @@ class Board {
[[nodiscard]] inline constexpr bool is_square_attacked(square::Square square, color::Color side) const;
[[nodiscard]] inline constexpr bool is_square_occupied(square::Square square) const;
- [[nodiscard]] inline constexpr bool is_piece_attack_square(piece::Type type, color::Color color, square::Square source,
- square::Square target) const;
+ [[nodiscard]] inline constexpr bool is_piece_attack_square(piece::Type type, color::Color color,
+ square::Square source,
+ square::Square target) const;
[[nodiscard]] inline constexpr bool is_check() const;
private:
@@ -142,19 +143,19 @@ constexpr const piece::Piece *Board::get_square_piece(square::Square square) con
constexpr void Board::xor_hash(U64 op) { hash ^= op; }
constexpr void Board::and_castle(uint8_t right) {
- hash ^= Zobrist::key_castle(castle);
+ hash ^= zobrist::key_castle(castle);
castle &= right;
- hash ^= Zobrist::key_castle(castle);
+ hash ^= zobrist::key_castle(castle);
}
constexpr void Board::switch_side() {
side = color::other(side);
- hash ^= Zobrist::key_side();
+ hash ^= zobrist::key_side();
}
constexpr void Board::set_enpassant(square::Square target) {
- if (enpassant != square::Square::no_sq) hash ^= Zobrist::key_enpassant(enpassant);
- if (target != square::Square::no_sq) hash ^= Zobrist::key_enpassant(target);
+ if (enpassant != square::Square::no_sq) hash ^= zobrist::key_enpassant(enpassant);
+ if (target != square::Square::no_sq) hash ^= zobrist::key_enpassant(target);
enpassant = target;
}
@@ -214,7 +215,7 @@ constexpr bool Board::is_check() const {
return is_square_attacked(square, side_other);
}
-U64 Zobrist::hash(const Board &board) {
+U64 zobrist::hash(const Board &board) {
U64 key_final = C64(0);
uint8_t square = 0;
diff --git a/src/board/zobrist.hpp b/src/board/zobrist.hpp
@@ -9,57 +9,44 @@
#include <random>
class Board;
-class Zobrist {
- public:
- Zobrist() = delete;
-
- static inline U64 hash(const Board &board);
- static inline constexpr U64 key_side() { return keys_side; }
- static inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; }
- static inline constexpr U64 key_enpassant(square::Square square) {
- return keys_enpassant[to_underlying(square)];
- }
- static inline constexpr U64 key_piece(piece::Type type, color::Color color, square::Square square) {
- return keys_piece[piece::get_index(type, color)][to_underlying(square)];
+namespace zobrist {
+
+extern std::array<std::array<U64, 64>, 12> keys_piece;
+extern std::array<U64, 64> keys_enpassant;
+extern std::array<U64, 16> keys_castle;
+
+const U64 keys_side = Random(C32(1699391443))();
+
+inline void init() {
+ Random gen1(C64(1804289383));
+ for (piece::Type type : piece::TypeIter()) {
+ int piece_index_white = piece::get(type, color::Color::WHITE).index;
+ int piece_index_black = piece::get(type, color::Color::BLACK).index;
+ for (int square = 0; square < 64; square++) {
+ keys_piece[piece_index_white][square] = gen1();
+ keys_piece[piece_index_black][square] = gen1();
+ }
}
- private:
- using key_piece_array = std::array<std::array<U64, 64>, 12>;
- static inline constexpr const key_piece_array keys_piece = []() constexpr -> key_piece_array {
- key_piece_array key_piece;
- Random gen(C64(1804289383));
- for (piece::Type type : piece::TypeIter()) {
- int piece_index_white = piece::get(type, color::Color::WHITE).index;
- int piece_index_black = piece::get(type, color::Color::BLACK).index;
- for (int square = 0; square < 64; square++) {
- key_piece[piece_index_white][square] = gen();
- key_piece[piece_index_black][square] = gen();
- }
- }
- return key_piece;
- }();
+ Random gen2(C32(337245213));
+ for (int castle = 0; castle < 64; castle++) {
+ keys_enpassant[castle] = gen2();
+ }
- using key_enpassant_array = std::array<U64, 64>;
- static inline constexpr const key_enpassant_array keys_enpassant = []() constexpr -> key_enpassant_array {
- key_enpassant_array key_enpassant;
- Random gen(C32(337245213));
- for (int castle = 0; castle < 64; castle++) {
- key_enpassant[castle] = gen();
- }
- return key_enpassant;
- }();
+ Random gen3(C32(3642040919));
+ for (int castle = 0; castle < 16; castle++) {
+ keys_castle[castle] = gen3();
+ }
+};
- using key_castle_array = std::array<U64, 16>;
- static inline constexpr const key_castle_array keys_castle = []() constexpr -> key_castle_array {
- key_castle_array key_castle;
- Random gen(C32(3642040919));
- for (int castle = 0; castle < 16; castle++) {
- key_castle[castle] = gen();
- }
- return key_castle;
- }();
+inline U64 hash(const Board &board);
+inline constexpr U64 key_side() { return keys_side; }
+inline constexpr U64 key_castle(int exp) { return keys_castle[exp]; }
+inline constexpr U64 key_enpassant(square::Square square) { return keys_enpassant[to_underlying(square)]; }
+inline constexpr U64 key_piece(piece::Type type, color::Color color, square::Square square) {
+ return keys_piece[piece::get_index(type, color)][to_underlying(square)];
+}
- static inline constexpr const U64 keys_side = Random(C32(1699391443))();
-};
+}; // namespace zobrist
#endif
diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
@@ -4,6 +4,7 @@ add_executable(engine
engine.cpp
)
+
target_link_libraries(engine
PRIVATE Stellar_version
PRIVATE board
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -17,13 +17,13 @@
#include "utils.hpp"
enum {
-FULL_DEPTH = 4,
-REDUCTION_LIMIT = 3,
-REDUCTION_MOVE = 2
+ FULL_DEPTH = 4,
+ REDUCTION_LIMIT = 3,
+ REDUCTION_MOVE = 2
};
enum {
-WINDOW = 50
+ WINDOW = 50
};
namespace engine {
@@ -473,6 +473,8 @@ Move search_position(const uci::Settings &settingsr) {
} // namespace engine
int main() {
+ attack::init();
+ zobrist::init();
uci::loop();
return 0;
}
diff --git a/src/move/move.cpp b/src/move/move.cpp
@@ -6,12 +6,12 @@
void Move::piece_remove(Board &board, piece::Type type, color::Color color, square::Square square) const {
board.pop_piece(type, color, square);
- board.xor_hash(Zobrist::key_piece(type, color, square));
+ board.xor_hash(zobrist::key_piece(type, color, square));
}
void Move::piece_set(Board &board, piece::Type type, color::Color color, square::Square square) const {
board.set_piece(type, color, square);
- board.xor_hash(Zobrist::key_piece(type, color, square));
+ board.xor_hash(zobrist::key_piece(type, color, square));
}
void Move::piece_move(Board &board, piece::Type type, color::Color color, square::Square source,
diff --git a/src/perft/CMakeLists.txt b/src/perft/CMakeLists.txt
@@ -12,10 +12,6 @@ target_link_libraries(perft
PRIVATE utils
)
-target_precompile_headers(perft
- REUSE_FROM engine
-)
-
set_target_properties(perft PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp
@@ -2,6 +2,7 @@
#include <semaphore>
#include <thread>
+#include "attack.hpp"
#include "board.hpp"
#include "move.hpp"
#include "movelist.hpp"
@@ -151,6 +152,8 @@ int main(int argc, char *argv[]) {
}
}
+ attack::init();
+ zobrist::init();
perft_test(fen, depth, thread_num);
return 0;
}
diff --git a/src/piece/CMakeLists.txt b/src/piece/CMakeLists.txt
@@ -7,5 +7,3 @@ target_link_libraries(piece
)
target_include_directories(piece INTERFACE .)
-stellar_target_precompile_headers(piece INTERFACE "piece.hpp")
-
diff --git a/src/random/CMakeLists.txt b/src/random/CMakeLists.txt
@@ -1,4 +1,3 @@
add_library(random INTERFACE)
target_link_libraries(piece INTERFACE utils)
target_include_directories(random INTERFACE .)
-stellar_target_precompile_headers(random INTERFACE "random.hpp")
diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt
@@ -1,23 +1,17 @@
add_library(bit INTERFACE)
target_include_directories(bit INTERFACE .)
-stellar_target_precompile_headers(bit INTERFACE "bit.hpp")
add_library(bitboard INTERFACE bitboard.cpp)
target_include_directories(bitboard INTERFACE .)
-stellar_target_precompile_headers(bitboard INTERFACE "bitboard.hpp")
add_library(color INTERFACE)
target_include_directories(color INTERFACE .)
-stellar_target_precompile_headers(color INTERFACE "color.hpp")
add_library(square INTERFACE)
target_include_directories(square INTERFACE .)
-stellar_target_precompile_headers(square INTERFACE "square.hpp")
add_library(timer INTERFACE)
target_include_directories(timer INTERFACE .)
-stellar_target_precompile_headers(timer INTERFACE "timer.hpp")
add_library(utils INTERFACE)
target_include_directories(utils INTERFACE .)
-stellar_target_precompile_headers(utils INTERFACE "utils.hpp")
diff --git a/src/utils/bit.hpp b/src/utils/bit.hpp
@@ -2,6 +2,7 @@
#define STELLAR_BIT_H
#include "utils.hpp"
+#include <bit>
namespace bit {
@@ -9,26 +10,8 @@ inline constexpr bool get(const U64 &bitboard, uint8_t square) { return (bitboar
inline constexpr void set(U64 &bitboard, uint8_t square) { bitboard |= (C64(1) << square); }
inline constexpr void pop(U64 &bitboard, uint8_t square) { bitboard &= ~(C64(1) << (square)); }
-inline constexpr uint8_t count(U64 bitboard) {
-#if __has_builtin(__builtin_popcountll)
- return __builtin_popcountll(bitboard);
-#else
- int count = 0;
- for (; bitboard > 0; bitboard &= bitboard - 1)
- count++;
- return count;
-#endif
-}
-
-inline constexpr uint8_t lsb_index(U64 bitboard) {
-#if __has_builtin(__builtin_ffsll)
- return __builtin_ffsll(bitboard) - 1;
-#else
- if (!bitboard) return -1;
- return bit_count((bitboard & -bitboard) - 1);
-#endif
-}
-
+inline constexpr uint8_t count(U64 bitboard) { return std::popcount(bitboard); }
+inline constexpr uint8_t lsb_index(U64 bitboard) { return std::countr_zero(bitboard); }
inline constexpr U64 &lsb_pop(U64 &bitboard) { return bitboard &= bitboard & (bitboard - 1); }
#define bitboard_for_each_bit(var, bb) \
diff --git a/src/utils/timer.hpp b/src/utils/timer.hpp
@@ -1,14 +1,13 @@
#ifndef STELLAR_TIME_H
#define STELLAR_TIME_H
-#include <sys/time.h>
+#include <chrono>
namespace timer {
inline uint32_t get_ms() {
- struct timeval time{};
- gettimeofday(&time, nullptr);
- return time.tv_sec * 1000 + time.tv_usec / 1000;
+ const auto duration = std::chrono::system_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
}
} // namespace timer