commit f58bf4bfaba4974e1a4af873afc8d74c66bbc285
parent efb266c91585d3dcfe9ade481bc13199b9508418
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Thu, 10 Aug 2023 21:02:31 +0200
Attack generation at compile time with constexpr
Diffstat:
30 files changed, 642 insertions(+), 734 deletions(-)
diff --git a/.clang-format b/.clang-format
@@ -36,7 +36,7 @@ AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
-AllowShortFunctionsOnASingleLine: true
+AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: false
@@ -77,7 +77,7 @@ BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
-ColumnLimit: 80
+ColumnLimit: 110
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Stellar
- VERSION 0.0.18
+ VERSION 0.0.19
DESCRIPTION "Chess engine written in C"
HOMEPAGE_URL https://git.dimitrijedobrota.com/stellar.git
LANGUAGES C CXX
@@ -13,4 +13,10 @@ set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_EXTENSIONS OFF)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fconstexpr-ops-limit=1000000000")
+
add_subdirectory(src)
diff --git a/src/attacks/CMakeLists.txt b/src/attacks/CMakeLists.txt
@@ -1,35 +0,0 @@
-add_library(attacks OBJECT
- attacks.cpp
- internal.cpp
- magic.cpp
-)
-
-target_include_directories(attacks
- PUBLIC "${PROJECT_SOURCE_DIR}/src/include"
- PRIVATE "internal"
-)
-
-
-project(
- MagicGenerator
- VERSION 1.0.0
- DESCRIPTION "Generator of magic numbers for bishup and rook attacks"
- LANGUAGES CXX
-)
-
-
-add_executable(magic
- internal.cpp
- magic.cpp
- magic_generate.cpp
-)
-
-target_link_libraries(magic
- PRIVATE random
-)
-
-set_target_properties(magic PROPERTIES
- VERSION ${PROJECT_VERSION}
- SOVERSION ${PROJECT_VERSION_MAJOR}
- RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
-)
diff --git a/src/attacks/attacks.cpp b/src/attacks/attacks.cpp
@@ -1,99 +0,0 @@
-#include "attacks.hpp"
-#include "internal.hpp"
-#include "magic.hpp"
-#include "utils_cpp.hpp"
-
-#define UNUSED(x) (void)(x)
-
-U64 attacks_wpawn_get(Square square, U64 occupancy) {
- UNUSED(occupancy);
- return pawn_attacks[to_underlying(Color::WHITE)][to_underlying(square)];
-}
-
-U64 attacks_bpawn_get(Square square, U64 occupancy) {
- UNUSED(occupancy);
- return pawn_attacks[to_underlying(Color::BLACK)][to_underlying(square)];
-}
-
-U64 attacks_knight_get(Square square, U64 occupancy) {
- UNUSED(occupancy);
- return knight_attacks[to_underlying(square)];
-}
-
-U64 attacks_king_get(Square square, U64 occupancy) {
- UNUSED(occupancy);
- return king_attacks[to_underlying(square)];
-}
-
-U64 attacks_bishop_get(Square square, U64 occupancy) {
- int square_i = to_underlying(square);
- occupancy &= bishop_masks[square_i];
- occupancy = hash(occupancy, bishop_magic_numbers[square_i],
- bishop_relevant_bits[square_i]);
- return bishop_attacks[square_i][occupancy];
-}
-
-U64 attacks_rook_get(Square square, U64 occupancy) {
- int square_i = to_underlying(square);
- occupancy &= rook_masks[square_i];
- occupancy = hash(occupancy, rook_magic_numbers[square_i],
- rook_relevant_bits[square_i]);
- return rook_attacks[square_i][occupancy];
-}
-
-U64 attacks_queen_get(Square square, U64 occupancy) {
- return (attacks_bishop_get(square, occupancy) |
- attacks_rook_get(square, occupancy));
-}
-
-void attacks_init_leapers(void) {
- for (Square square : SquareIter()) {
- uint8_t square_i = to_underlying(square);
- pawn_attacks[to_underlying(Color::WHITE)][square_i] =
- pawn_mask(Color::WHITE, square);
- pawn_attacks[to_underlying(Color::BLACK)][square_i] =
- pawn_mask(Color::BLACK, square);
- knight_attacks[square_i] = knight_mask(square);
- king_attacks[square_i] = king_mask(square);
- }
-}
-
-void attacks_init_sliders(int bishop) {
- for (Square square : SquareIter()) {
- uint8_t square_i = to_underlying(square);
- U64 attack_mask;
-
- if (bishop) {
- bishop_masks[square_i] = bishop_mask(square);
- attack_mask = bishop_masks[square_i];
- } else {
- rook_masks[square_i] = rook_mask(square);
- attack_mask = rook_masks[square_i];
- }
-
- int relevant_bits = bit_count(attack_mask);
- int occupancy_indicies = 1 << relevant_bits;
-
- for (int index = 0; index < occupancy_indicies; index++) {
- U64 occupancy = set_occupancy(index, relevant_bits, attack_mask);
- if (bishop) {
- int magic_index =
- (occupancy * bishop_magic_numbers[square_i]) >>
- (64 - bishop_relevant_bits[square_i]);
- bishop_attacks[square_i][magic_index] =
- bishop_on_the_fly(square, occupancy);
- } else {
- int magic_index = hash(occupancy, rook_magic_numbers[square_i],
- rook_relevant_bits[square_i]);
- rook_attacks[square_i][magic_index] =
- rook_on_the_fly(square, occupancy);
- }
- }
- }
-}
-
-void attacks_init(void) {
- attacks_init_leapers();
- attacks_init_sliders(0);
- attacks_init_sliders(1);
-}
diff --git a/src/attacks/internal.cpp b/src/attacks/internal.cpp
@@ -1,148 +0,0 @@
-#include "internal.hpp"
-#include "utils_cpp.hpp"
-
-#include <algorithm> // std::min
-
-U64 king_attacks[64];
-U64 knight_attacks[64];
-U64 pawn_attacks[2][64];
-U64 rook_attacks[64][4096]; // 2048K
-U64 bishop_attacks[64][512]; // 256 K
-
-U64 rook_masks[64];
-U64 bishop_masks[64];
-
-// clang-format off
-const int bishop_relevant_bits[64] = {
- 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,
-};
-
-const int rook_relevant_bits[64] = {
- 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
-
-int hash(U64 key, U64 magic, int relevant_bits) {
- return (key * magic) >> (64 - relevant_bits);
-}
-
-U64 set_occupancy(int index, int bits_in_mask, U64 attack_mask) {
- U64 occupancy = C64(0);
-
- for (int count = 0; count < bits_in_mask; count++) {
- uint8_t square = bit_lsb_index(attack_mask);
- bit_pop(attack_mask, square);
-
- if (index & (1 << count)) bit_set(occupancy, square);
- }
-
- return occupancy;
-}
-
-U64 attacks_slide_mask(Square square, U64 block, const direction_f dir[4],
- int len[4]) {
- U64 bitboard = C64(0), attacks = C64(0), tmp;
- int i, j;
-
- bit_set(bitboard, to_underlying(square));
- for (i = 0; i < 4; i++) {
- for (j = 0, tmp = bitboard; j < len[i]; j++) {
- attacks |= tmp = (dir[i])(tmp);
- if (tmp & block) break;
- }
- }
- return attacks;
-}
-
-// Mask Attacks
-
-const direction_f attacks_bishop_direction[4] = {noEaOne, noWeOne, soEaOne,
- soWeOne};
-const direction_f attacks_rook_direction[4] = {westOne, soutOne, eastOne,
- nortOne};
-
-U64 pawn_mask(Color side, Square square) {
- U64 bitboard = C64(0);
-
- bit_set(bitboard, to_underlying(square));
- if (side == Color::WHITE)
- return noWeOne(bitboard) | noEaOne(bitboard);
- else
- return soWeOne(bitboard) | soEaOne(bitboard);
-}
-
-U64 knight_mask(Square square) {
- U64 bitboard = C64(0), attacks = C64(0), tmp;
-
- bit_set(bitboard, to_underlying(square));
- tmp = nortOne(nortOne(bitboard));
- attacks |= westOne(tmp) | eastOne(tmp);
- tmp = soutOne(soutOne(bitboard));
- attacks |= westOne(tmp) | eastOne(tmp);
- tmp = westOne(westOne(bitboard));
- attacks |= soutOne(tmp) | nortOne(tmp);
- tmp = eastOne(eastOne(bitboard));
- attacks |= soutOne(tmp) | nortOne(tmp);
-
- return attacks;
-}
-
-U64 king_mask(Square square) {
- U64 bitboard = C64(0), attacks = C64(0);
-
- bit_set(bitboard, to_underlying(square));
- attacks |= westOne(bitboard) | eastOne(bitboard);
- attacks |= soutOne(bitboard) | nortOne(bitboard);
- attacks |= soutOne(bitboard) | nortOne(bitboard);
- attacks |= soEaOne(bitboard) | noEaOne(bitboard);
- attacks |= soWeOne(bitboard) | noWeOne(bitboard);
-
- return attacks;
-}
-
-U64 bishop_mask(Square square) {
- 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) - 1, std::min(tf, 7 - tr) - 1,
- std::min(7 - tf, tr) - 1, std::min(tf, tr) - 1};
- return attacks_slide_mask(square, C64(0), attacks_bishop_direction, len);
-}
-
-U64 rook_mask(Square square) {
- uint8_t square_i = to_underlying(square);
- int tr = square_i / 8, tf = square_i % 8;
- int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr};
-
- return attacks_slide_mask(square, C64(0), attacks_rook_direction, len);
-}
-
-U64 bishop_on_the_fly(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 attacks_slide_mask(square, block, attacks_bishop_direction, len);
-}
-
-U64 rook_on_the_fly(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 attacks_slide_mask(square, block, attacks_rook_direction, len);
-}
diff --git a/src/attacks/internal.hpp b/src/attacks/internal.hpp
@@ -1,30 +0,0 @@
-#ifndef STELLAR_ATTAKCS_INTERNAL_H
-#define STELLAR_ATTAKCS_INTERNAL_H
-
-#include "utils_cpp.hpp"
-
-extern U64 king_attacks[64]; // king attack table [square]
-extern U64 knight_attacks[64]; // knight attack table [square]
-extern U64 pawn_attacks[2][64]; // pawn attack table [side][square]
-extern U64 rook_attacks[64][4096]; // rook attack table [square][occupancies]
-extern U64 bishop_attacks[64][512]; // bishop attack table [square][occupancies]
-
-extern U64 rook_masks[64]; // rook attack mask
-extern U64 bishop_masks[64]; // bishop attack mask
-
-extern const int rook_relevant_bits[64];
-extern const int bishop_relevant_bits[64];
-
-int hash(U64 key, U64 magic, int relevant_bits);
-
-U64 set_occupancy(int index, int bits_in_mask, U64 attack_mask);
-
-U64 bishop_mask(Square square);
-U64 bishop_on_the_fly(Square square, U64 block);
-U64 king_mask(Square square);
-U64 knight_mask(Square square);
-U64 pawn_mask(Color side, Square square);
-U64 rook_mask(Square square);
-U64 rook_on_the_fly(Square square, U64 block);
-
-#endif
diff --git a/src/attacks/magic.cpp b/src/attacks/magic.cpp
@@ -1,51 +0,0 @@
-#include "magic.hpp"
-
-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),
-};
-
-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),
-};
diff --git a/src/attacks/magic.hpp b/src/attacks/magic.hpp
@@ -1,9 +0,0 @@
-#ifndef STELLAR_ATTACKS_MAGIC_H
-#define STELLAR_ATTACKS_MAGIC_H
-
-#include "utils_cpp.hpp"
-
-extern const U64 bishop_magic_numbers[64];
-extern const U64 rook_magic_numbers[64];
-
-#endif
diff --git a/src/attacks/magic_generate.cpp b/src/attacks/magic_generate.cpp
@@ -1,69 +0,0 @@
-#include "internal.hpp"
-#include "random.hpp"
-#include "utils_cpp.hpp"
-
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-const char *FORMAT = "C64(0x%llx),\n";
-
-U64 generate_magic_number() {
- return random_get_U64() & random_get_U64() & random_get_U64();
-}
-
-U64 find_magic_number(Square square, int relevant_bits, int bishop) {
- U64 occupancies[4096], attacks[4096], used_attacks[4096];
- U64 attack_mask = bishop ? bishop_mask(square) : rook_mask(square);
- int occupancy_indicies = 1 << relevant_bits;
-
- for (int index = 0; index < occupancy_indicies; index++) {
- occupancies[index] = set_occupancy(index, relevant_bits, attack_mask);
- attacks[index] = bishop ? bishop_on_the_fly(square, occupancies[index])
- : rook_on_the_fly(square, occupancies[index]);
- }
-
- for (int random_count = 0; random_count < 100000000; random_count++) {
- U64 magic_number = generate_magic_number();
- if (bit_count((attack_mask * magic_number) & C64(0xFF00000000000000)) <
- 6)
- continue;
-
- memset(used_attacks, C64(0), sizeof(used_attacks));
- int index, fail;
-
- for (index = 0, fail = 0; !fail && index < occupancy_indicies;
- index++) {
- int magic_index =
- hash(occupancies[index], magic_number, relevant_bits);
-
- if (used_attacks[magic_index] == C64(0))
- used_attacks[magic_index] = attacks[index];
- else if (used_attacks[magic_index] != attacks[index])
- fail = 1;
- }
-
- if (!fail) return magic_number;
- }
-
- return C64(0);
-}
-
-int main(void) {
- random_state_reset();
-
- printf("Bishup Magic Numbers:\n");
- for (Square square : SquareIter())
- printf(FORMAT,
- find_magic_number(
- square, bishop_relevant_bits[to_underlying(square)], 1));
-
- printf("Rook Magic Numbers:\n");
- for (Square square : SquareIter())
- printf(FORMAT,
- find_magic_number(square,
- rook_relevant_bits[to_underlying(square)], 0));
- return 0;
-}
diff --git a/src/board/board.cpp b/src/board/board.cpp
@@ -10,18 +10,25 @@
/* Getters */
-Color Board::get_side(void) const { return side; }
-U64 Board::get_hash(void) const { return hash; }
-uint8_t Board::get_castle(void) const { return castle; }
-Square Board::get_enpassant(void) const { return enpassant; }
+Color Board::get_side(void) const {
+ return side;
+}
+U64 Board::get_hash(void) const {
+ return hash;
+}
+uint8_t Board::get_castle(void) const {
+ return castle;
+}
+Square Board::get_enpassant(void) const {
+ return enpassant;
+}
U64 Board::get_bitboard_color(Color side) const {
return colors[to_underlying(side)];
}
U64 Board::get_bitboard_occupancy(void) const {
- return colors[to_underlying(Color::WHITE)] |
- colors[to_underlying(Color::BLACK)];
+ return colors[to_underlying(Color::WHITE)] | colors[to_underlying(Color::BLACK)];
}
U64 Board::get_bitboard_piece(piece::Type piece) const {
@@ -36,45 +43,43 @@ U64 Board::get_bitboard_piece(piece::Type piece, Color color) const {
return pieces[to_underlying(piece)] & colors[to_underlying(color)];
}
-U64 Board::get_bitboard_piece_attacks(piece::Type piece, Color color,
- Square square) const {
+U64 Board::get_bitboard_piece_attacks(piece::Type piece, Color color, Square square) const {
return get_bitboard_piece_attacks(piece::get(piece, color), square);
}
-U64 Board::get_bitboard_piece_attacks(const piece::Piece &piece,
- Square square) const {
- return piece.attacks(square, get_bitboard_occupancy());
+U64 Board::get_bitboard_piece_attacks(const piece::Piece &piece, Square square) const {
+ return piece(square, get_bitboard_occupancy());
}
Color Board::get_square_piece_color(Square square) const {
- if (bit_get(colors[to_underlying(Color::WHITE)], to_underlying(square)))
- return Color::WHITE;
- if (bit_get(colors[to_underlying(Color::BLACK)], to_underlying(square)))
- return Color::BLACK;
+ if (bit_get(colors[to_underlying(Color::WHITE)], to_underlying(square))) return Color::WHITE;
+ if (bit_get(colors[to_underlying(Color::BLACK)], to_underlying(square))) return Color::BLACK;
throw std::exception();
}
piece::Type Board::get_square_piece_type(Square square) const {
for (piece::Type type : piece::TypeIter()) {
- if (bit_get(pieces[to_underlying(type)], to_underlying(square)))
- return type;
+ if (bit_get(pieces[to_underlying(type)], to_underlying(square))) return type;
}
throw std::exception();
}
const piece::Piece *Board::get_square_piece(Square square) const {
try {
- return &piece::get(get_square_piece_type(square),
- get_square_piece_color(square));
- } catch (std::exception e) {
+ return &piece::get(get_square_piece_type(square), get_square_piece_color(square));
+ } catch (std::exception &e) {
return nullptr;
}
}
/* Setters */
-void Board::xor_hash(U64 op) { hash ^= op; }
-void Board::and_castle(uint8_t right) { castle &= right; }
+void Board::xor_hash(U64 op) {
+ hash ^= op;
+}
+void Board::and_castle(uint8_t right) {
+ castle &= right;
+}
void Board::switch_side(void) {
side = (side == Color::BLACK) ? Color::WHITE : Color::BLACK;
@@ -133,8 +138,7 @@ bool Board::is_square_attacked(Square square, Color side) const {
}
bool Board::is_check(void) const {
- U64 king =
- pieces[to_underlying(piece::Type::KING)] & colors[to_underlying(side)];
+ U64 king = pieces[to_underlying(piece::Type::KING)] & colors[to_underlying(side)];
Color side_other = (side == Color::BLACK) ? Color::WHITE : Color::BLACK;
Square square = static_cast<Square>(bit_lsb_index(king));
return is_square_attacked(square, side_other);
@@ -144,8 +148,7 @@ Board::Board(const std::string &fen) {
int file = 0, rank = 7, i;
for (i = 0; fen[i] != ' '; i++) {
if (isalpha(fen[i])) {
- set_piece(piece::get_from_code(fen[i]),
- static_cast<Square>(rank * 8 + file));
+ set_piece(piece::get_from_code(fen[i]), static_cast<Square>(rank * 8 + file));
file++;
} else if (isdigit(fen[i])) {
file += fen[i] - '0';
diff --git a/src/board/zobrist.cpp b/src/board/zobrist.cpp
@@ -8,8 +8,12 @@ U64 enpassant_keys[64];
U64 piece_keys[16][64];
U64 side_key;
-U64 zobrist_key_side(void) { return side_key; }
-U64 zobrist_key_castle(int exp) { return castle_keys[exp]; }
+U64 zobrist_key_side(void) {
+ return side_key;
+}
+U64 zobrist_key_castle(int exp) {
+ return castle_keys[exp];
+}
U64 zobrist_key_enpassant(Square square) {
return enpassant_keys[to_underlying(square)];
}
@@ -40,7 +44,9 @@ void init_hash_keys() {
side_key = random_get_U64();
}
-void zobrist_init(void) { init_hash_keys(); }
+void zobrist_init(void) {
+ init_hash_keys();
+}
U64 zobrist_hash(const Board &board) {
U64 key_final = C64(0);
diff --git a/src/engine/CMakeLists.txt b/src/engine/CMakeLists.txt
@@ -5,10 +5,8 @@ add_executable(engine
)
target_link_libraries(engine
- PRIVATE attacks
PRIVATE board
PRIVATE moves
- PRIVATE piece
PRIVATE random
)
diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp
@@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
-#include "attacks.hpp"
+#include "attack.hpp"
#include "board.hpp"
#include "moves.hpp"
#include "score.hpp"
@@ -65,7 +65,9 @@ int evaluate(const Board &board) {
return score;
}
-int is_repetition() { return 0; }
+int is_repetition() {
+ return 0;
+}
int stats_move_make(Stats &stats, Board ©, Move move, int flag) {
copy = stats.board;
@@ -110,7 +112,7 @@ int quiescence(Stats &stats, int alpha, int beta) {
Board copy;
std::vector<MoveE> list = move_list_generate(stats.board);
Score_move_list(stats, list);
- move_list_sort_pv(list, stats, (Move){0});
+ move_list_sort_pv(list, stats, {0});
move_list_sort(list);
for (const auto [move, _] : list) {
@@ -170,8 +172,7 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
// null move pruning
if (stats.ply && depth > 2 && staticEval >= beta) {
stats_move_make_pruning(stats, copy);
- score = -negamax(stats, -beta, -beta + 1,
- depth - 1 - REDUCTION_MOVE, false);
+ score = -negamax(stats, -beta, -beta + 1, depth - 1 - REDUCTION_MOVE, false);
stats_move_unmake(stats, copy);
if (score >= beta) return beta;
}
@@ -186,16 +187,13 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
score += Score_value(piece::Type::PAWN);
if (score < beta && depth < 4) {
- if (scoreNew < beta)
- return (scoreNew > score) ? scoreNew : score;
+ if (scoreNew < beta) return (scoreNew > score) ? scoreNew : score;
}
}
// futility pruning condition
static const int margin[] = {0, 100, 300, 500};
- if (depth < 4 && abs(alpha) < MATE_SCORE &&
- staticEval + margin[depth] <= alpha)
- futility = 1;
+ if (depth < 4 && abs(alpha) < MATE_SCORE && staticEval + margin[depth] <= alpha) futility = 1;
}
std::vector<MoveE> list = move_list_generate(stats.board);
@@ -210,8 +208,7 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
legal_moves++;
// futility pruning
- if (futility && searched && !move_capture(move) &&
- !move_promote(move) && !stats.board.is_check()) {
+ if (futility && searched && !move_capture(move) && !move_promote(move) && !stats.board.is_check()) {
stats_move_unmake(stats, copy);
continue;
}
@@ -220,15 +217,12 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
score = -negamax(stats, -beta, -alpha, depth - 1, true);
} else {
// Late Move Reduction
- if (!pv_node && searched >= FULL_DEPTH &&
- depth >= REDUCTION_LIMIT && !isCheck && !move_capture(move) &&
- !move_promote(move) &&
+ if (!pv_node && searched >= FULL_DEPTH && depth >= REDUCTION_LIMIT && !isCheck &&
+ !move_capture(move) && !move_promote(move) &&
(move_source(move) != move_source(stats.killer[0][stats.ply]) ||
- move_target(move) !=
- move_target(stats.killer[0][stats.ply])) &&
+ move_target(move) != move_target(stats.killer[0][stats.ply])) &&
(move_source(move) != move_source(stats.killer[1][stats.ply]) ||
- move_target(move) !=
- move_target(stats.killer[1][stats.ply]))) {
+ move_target(move) != move_target(stats.killer[1][stats.ply]))) {
score = -negamax(stats, -alpha - 1, -alpha, depth - 2, true);
} else
score = alpha + 1;
@@ -249,8 +243,7 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
if (score > alpha) {
if (!move_capture(move)) {
- stats.history[move_piece(move).index][move_target(move)] +=
- depth;
+ stats.history[move_piece(move).index][move_target(move)] += depth;
}
alpha = score;
@@ -259,8 +252,7 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
stats_pv_store(stats, move);
if (score >= beta) {
- stats.ttable.write(stats, bestMove, beta, depth,
- HasheFlag::Beta);
+ stats.ttable.write(stats, bestMove, beta, depth, HasheFlag::Beta);
if (!move_capture(move)) {
stats.killer[1][stats.ply] = stats.killer[0][stats.ply];
@@ -284,8 +276,7 @@ int negamax(Stats &stats, int alpha, int beta, int depth, bool null) {
}
void move_print_UCI(Move move) {
- printf("%s%s",
- square_to_coordinates(static_cast<Square>(move_source(move))),
+ printf("%s%s", square_to_coordinates(static_cast<Square>(move_source(move))),
square_to_coordinates(static_cast<Square>(move_target(move))));
if (move_promote(move)) printf("%c", (move_piece_promote(move).code));
}
@@ -309,14 +300,13 @@ void search_position(Board &board, int depth) {
if (stats.pv_length[0]) {
if (score > -MATE_VALUE && score < -MATE_SCORE) {
- printf("info score mate %d depth %d nodes %ld pv ",
- -(score + MATE_VALUE) / 2 - 1, crnt, stats.nodes);
+ printf("info score mate %d depth %d nodes %ld pv ", -(score + MATE_VALUE) / 2 - 1, crnt,
+ stats.nodes);
} else if (score > MATE_SCORE && score < MATE_VALUE) {
- printf("info score mate %d depth %d nodes %ld pv ",
- (MATE_VALUE - score) / 2 + 1, crnt, stats.nodes);
- } else {
- printf("info score cp %d depth %d nodes %ld pv ", score, crnt,
+ printf("info score mate %d depth %d nodes %ld pv ", (MATE_VALUE - score) / 2 + 1, crnt,
stats.nodes);
+ } else {
+ printf("info score cp %d depth %d nodes %ld pv ", score, crnt, stats.nodes);
}
for (int i = 0; i < stats.pv_length[0]; i++) {
@@ -364,7 +354,9 @@ void Instruction_free(Instruction **p) {
delete (*p);
}
-char *Instruction_token(Instruction *self) { return self->token; }
+char *Instruction_token(Instruction *self) {
+ return self->token;
+}
char *Instruction_token_n(Instruction *self, int n) {
while (isspace(*self->crnt) && *self->crnt != '\0')
self->crnt++;
@@ -376,8 +368,7 @@ char *Instruction_token_n(Instruction *self, int n) {
char *p = self->token;
while (n--) {
- while (!isspace(*self->crnt) && *self->crnt != '\0' &&
- *self->crnt != ';')
+ while (!isspace(*self->crnt) && *self->crnt != '\0' && *self->crnt != ';')
*p++ = *self->crnt++;
if (*self->crnt == '\0') {
p++;
@@ -405,8 +396,7 @@ Move parse_move(Board &board, char *move_string) {
for (const auto [move, _] : list) {
if (move_source(move) == source && move_target(move) == target) {
if (move_string[4]) {
- if (tolower(move_piece_promote(move).code) != move_string[4])
- continue;
+ if (tolower(move_piece_promote(move).code) != move_string[4]) continue;
}
result = move;
break;
@@ -444,7 +434,7 @@ Board *Instruction_parse(Instruction *self, Board &board) {
if (strcmp(token, "moves") == 0) {
while ((token = Instruction_token_next(self))) {
Move move = parse_move(board, token);
- if (!move_cmp(move, (Move){0})) {
+ if (!move_cmp(move, {0})) {
move_make(move, board, 0);
} else {
printf("Invalid move %s!\n", token);
@@ -456,8 +446,7 @@ Board *Instruction_parse(Instruction *self, Board &board) {
if (strcmp(token, "go") == 0) {
int depth = 6;
- for (token = Instruction_token_next(self); token;
- token = Instruction_token_next(self)) {
+ for (token = Instruction_token_next(self); token; token = Instruction_token_next(self)) {
if (token && strcmp(token, "depth") == 0) {
token = Instruction_token_next(self);
@@ -509,7 +498,6 @@ void uci_loop(void) {
/* MAIN */
void init(void) {
- attacks_init();
zobrist_init();
}
diff --git a/src/engine/transposition.cpp b/src/engine/transposition.cpp
@@ -2,8 +2,7 @@
#include "board.hpp"
#include "score.hpp"
-int TTable::read(const Stats &stats, Move *best, int alpha, int beta,
- int depth) const {
+int TTable::read(const Stats &stats, Move *best, int alpha, int beta, int depth) const {
U64 hash = stats.board.get_hash();
const Hashe &phashe = table[hash % table.size()];
@@ -15,18 +14,15 @@ int TTable::read(const Stats &stats, Move *best, int alpha, int beta,
if (score > MATE_SCORE) score -= stats.ply;
if (phashe.flag == HasheFlag::Exact) return score;
- if ((phashe.flag == HasheFlag::Alpha) && (score <= alpha))
- return alpha;
- if ((phashe.flag == HasheFlag::Beta) && (score >= beta))
- return beta;
+ if ((phashe.flag == HasheFlag::Alpha) && (score <= alpha)) return alpha;
+ if ((phashe.flag == HasheFlag::Beta) && (score >= beta)) return beta;
}
*best = phashe.best;
}
return TTABLE_UNKNOWN;
}
-void TTable::write(const Stats &stats, Move best, int score, int depth,
- HasheFlag flag) {
+void TTable::write(const Stats &stats, Move best, int score, int depth, HasheFlag flag) {
U64 hash = stats.board.get_hash();
Hashe &phashe = table[hash % table.size()];
diff --git a/src/engine/transposition.hpp b/src/engine/transposition.hpp
@@ -28,13 +28,14 @@ struct Hashe {
class TTable {
public:
- TTable(U64 size) : table(size, {0}) {}
-
- void clear() { table.clear(); };
- void write(const Stats &stats, Move best, int score, int depth,
- HasheFlag flag);
- int read(const Stats &stats, Move *best, int alpha, int beta,
- int depth) const;
+ TTable(U64 size) : table(size, {0}) {
+ }
+
+ void clear() {
+ table.clear();
+ };
+ void write(const Stats &stats, Move best, int score, int depth, HasheFlag flag);
+ int read(const Stats &stats, Move *best, int alpha, int beta, int depth) const;
private:
std::vector<Hashe> table;
diff --git a/src/include/attack.hpp b/src/include/attack.hpp
@@ -0,0 +1,337 @@
+#ifndef STELLAR_ATTAKCS_INTERNAL_H
+#define STELLAR_ATTAKCS_INTERNAL_H
+
+#include "magic.hpp"
+#include "utils_cpp.hpp"
+
+#include <array>
+
+namespace attack {
+
+class Slider {
+ public:
+ virtual constexpr U32 hash(U64 key, Square square) const = 0;
+ virtual constexpr U64 mask(Square square) const = 0;
+ virtual constexpr U64 mask_fly(Square square, U64 block) const = 0;
+
+ static inline constexpr U64 occupancy(U64 index, uint8_t bits_in_mask, U64 attack_mask) {
+ U64 occupancy = C64(0);
+
+ for (uint8_t count = 0; count < bits_in_mask; count++) {
+ uint8_t square = bit_lsb_index(attack_mask);
+ bit_pop(attack_mask, square);
+
+ if (bit_get(index, count)) bit_set(occupancy, square);
+ }
+
+ return occupancy;
+ }
+
+ protected:
+ static inline constexpr U64 mask_slide(Square square, U64 block, const direction_f dir[4],
+ const int len[4]) {
+ U64 bitboard = C64(0), attacks = C64(0);
+ bit_set(bitboard, to_underlying(square));
+ for (int i = 0; i < 4; i++) {
+ U64 tmp = bitboard;
+ for (int j = 0; j < len[i]; j++) {
+ attacks |= tmp = (dir[i])(tmp);
+ if (tmp & block) break;
+ }
+ }
+ return attacks;
+ }
+};
+
+class SliderRook : public Slider {
+ public:
+ virtual constexpr U32 hash(U64 key, Square square) const override {
+ uint8_t square_i = to_underlying(square);
+ return (key * rook_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
+ }
+
+ virtual constexpr U64 mask(Square square) const override {
+ return masks[to_underlying(square)];
+ }
+
+ virtual constexpr U64 mask_fly(Square square, U64 block) const override {
+ 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 mask_slide(square, block, dir, len);
+ }
+
+ private:
+ static inline constexpr const direction_f dir[4] = {westOne, soutOne, eastOne, nortOne};
+
+ // clang-format off
+ static inline constexpr const int relevant_bits[64] = {
+ 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
+
+ static inline constexpr const std::array<U64, 64> masks = []() constexpr -> std::array<U64, 64> {
+ std::array<U64, 64> masks;
+ for (const Square square : SquareIter()) {
+ const uint8_t square_i = to_underlying(square);
+ const int tr = square_i / 8, tf = square_i % 8;
+ const int len[4] = {tf - 1, tr - 1, 6 - tf, 6 - tr};
+
+ masks[square_i] = mask_slide(square, C64(0), dir, len);
+ }
+ return masks;
+ }();
+};
+
+class SliderBishop : public Slider {
+ public:
+ virtual constexpr U32 hash(U64 key, Square square) const override {
+ uint8_t square_i = to_underlying(square);
+ return (key * bishop_magic_numbers[square_i]) >> (64 - relevant_bits[square_i]);
+ }
+
+ virtual constexpr U64 mask(Square square) const override {
+ return masks[to_underlying(square)];
+ }
+
+ virtual constexpr U64 mask_fly(Square square, U64 block) const override {
+ 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 mask_slide(square, block, dir, len);
+ }
+
+ private:
+ static inline constexpr const direction_f dir[4] = {noEaOne, noWeOne, soEaOne, soWeOne};
+
+ // clang-format off
+ static inline constexpr const int relevant_bits[64] = {
+ 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
+
+ static inline constexpr const std::array<U64, 64> masks = []() constexpr -> std::array<U64, 64> {
+ std::array<U64, 64> masks;
+ for (const Square square : SquareIter()) {
+
+ 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) - 1, std::min(tf, 7 - tr) - 1, std::min(7 - tf, tr) - 1,
+ std::min(tf, tr) - 1};
+ masks[square_i] = mask_slide(square, C64(0), dir, len);
+ }
+ return masks;
+ }();
+};
+
+inline constexpr const SliderRook slider_rook;
+inline constexpr const SliderBishop slider_bishop;
+
+class Attack {
+ public:
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const = 0;
+
+ protected:
+ template <std::size_t size> using slider_attack_array = std::array<std::array<U64, size>, 64>;
+
+ static inline constexpr const auto slider_attacks =
+ []<std::size_t size>(const Slider &slider) constexpr -> slider_attack_array<size> {
+ slider_attack_array<size> attacks;
+ for (const Square square : SquareIter()) {
+ uint8_t square_i = to_underlying(square);
+ U64 attack_mask = slider.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 = slider.hash(occupancy, square);
+ attacks[square_i][magic_index] = slider.mask_fly(square, occupancy);
+ }
+ }
+ return attacks;
+ };
+};
+
+class Rook : public Attack {
+ public:
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ occupancy &= slider_rook.mask(square);
+ occupancy = slider_rook.hash(occupancy, square);
+ return attacks[to_underlying(square)][occupancy];
+ }
+
+ private:
+ static inline constexpr const slider_attack_array<4096> attacks =
+ slider_attacks.operator()<4096>(slider_rook);
+};
+
+class Bishop : public Attack {
+ public:
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ occupancy &= slider_bishop.mask(square);
+ occupancy = slider_bishop.hash(occupancy, square);
+ return attacks[to_underlying(square)][occupancy];
+ }
+
+ private:
+ static inline constexpr const slider_attack_array<512> attacks =
+ slider_attacks.operator()<512>(slider_bishop);
+};
+
+class King : public Attack {
+ public:
+ constexpr King() {
+ }
+
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ return attacks[to_underlying(square)];
+ }
+
+ private:
+ static constexpr U64 mask(Square square) {
+ U64 bitboard = C64(0), attacks = C64(0);
+
+ bit_set(bitboard, to_underlying(square));
+ attacks |= westOne(bitboard) | eastOne(bitboard);
+ attacks |= soutOne(bitboard) | nortOne(bitboard);
+ attacks |= soutOne(bitboard) | nortOne(bitboard);
+ attacks |= soEaOne(bitboard) | noEaOne(bitboard);
+ attacks |= soWeOne(bitboard) | noWeOne(bitboard);
+
+ return attacks;
+ }
+
+ typedef std::array<U64, 64> attack_array;
+ const attack_array attacks = []() -> attack_array {
+ std::array<U64, 64> attacks;
+ for (const Square square : SquareIter())
+ attacks[to_underlying(square)] = mask(square);
+ return attacks;
+ }();
+};
+
+class Knight : public Attack {
+ public:
+ constexpr Knight() {
+ }
+
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ return attacks[to_underlying(square)];
+ }
+
+ private:
+ static constexpr U64 mask(Square square) {
+ U64 bitboard = C64(0), attacks = C64(0), tmp;
+
+ bit_set(bitboard, to_underlying(square));
+ tmp = nortOne(nortOne(bitboard));
+ attacks |= westOne(tmp) | eastOne(tmp);
+ tmp = soutOne(soutOne(bitboard));
+ attacks |= westOne(tmp) | eastOne(tmp);
+ tmp = westOne(westOne(bitboard));
+ attacks |= soutOne(tmp) | nortOne(tmp);
+ tmp = eastOne(eastOne(bitboard));
+ attacks |= soutOne(tmp) | nortOne(tmp);
+
+ return attacks;
+ }
+
+ typedef std::array<U64, 64> attack_array;
+ const attack_array attacks = []() -> attack_array {
+ std::array<U64, 64> attacks;
+ for (const Square square : SquareIter())
+ attacks[to_underlying(square)] = mask(square);
+ return attacks;
+ }();
+};
+
+class PawnW : public Attack {
+ public:
+ constexpr PawnW() {
+ }
+
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ return attacks[to_underlying(square)];
+ }
+
+ private:
+ static constexpr U64 mask(Square square) {
+ U64 bitboard = C64(0);
+
+ bit_set(bitboard, to_underlying(square));
+ return noWeOne(bitboard) | noEaOne(bitboard);
+ }
+
+ typedef std::array<U64, 64> attack_array;
+ const attack_array attacks = []() -> attack_array {
+ std::array<U64, 64> attacks;
+ for (const Square square : SquareIter())
+ attacks[to_underlying(square)] = mask(square);
+ return attacks;
+ }();
+};
+
+class PawnB : public Attack {
+ public:
+ constexpr PawnB() {
+ }
+
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ return attacks[to_underlying(square)];
+ }
+
+ private:
+ static constexpr U64 mask(Square square) {
+ U64 bitboard = C64(0);
+
+ bit_set(bitboard, to_underlying(square));
+ return soWeOne(bitboard) | soEaOne(bitboard);
+ }
+
+ typedef std::array<U64, 64> attack_array;
+ const attack_array attacks = []() -> attack_array {
+ std::array<U64, 64> attacks;
+ for (const Square square : SquareIter())
+ attacks[to_underlying(square)] = mask(square);
+ return attacks;
+ }();
+};
+
+inline constexpr const Rook rook;
+inline constexpr const Bishop bishop;
+inline constexpr const King king;
+inline constexpr const Knight knight;
+inline constexpr const PawnW pawnW;
+inline constexpr const PawnB pawnB;
+
+class Queen : public Attack {
+ public:
+ constexpr Queen() {
+ }
+
+ virtual constexpr U64 operator()(Square square, U64 occupancy) const override {
+ return rook(square, occupancy) | bishop(square, occupancy);
+ }
+};
+
+inline constexpr const Queen queen;
+
+} // namespace attack
+#endif
diff --git a/src/include/attacks.hpp b/src/include/attacks.hpp
@@ -1,17 +0,0 @@
-#ifndef STELLAR_ATTACKS_H
-#define STELLAR_ATTACKS_H
-
-#include "utils_cpp.hpp"
-
-void attacks_init(void);
-
-typedef U64 (*attack_get_f)(Square square, U64 occupancy);
-U64 attacks_wpawn_get(Square square, U64 occupancy);
-U64 attacks_bpawn_get(Square square, U64 occupancy);
-U64 attacks_knight_get(Square square, U64 occupancy);
-U64 attacks_king_get(Square square, U64 occupancy);
-U64 attacks_bishop_get(Square square, U64 occupancy);
-U64 attacks_rook_get(Square square, U64 occupancy);
-U64 attacks_queen_get(Square square, U64 occupancy);
-
-#endif
diff --git a/src/include/board.hpp b/src/include/board.hpp
@@ -17,7 +17,8 @@ class Board {
BQ = 8
};
- Board() {}
+ Board() {
+ }
Board(const std::string &fen);
friend std::ostream &operator<<(std::ostream &os, const Board &board);
@@ -36,10 +37,8 @@ class Board {
U64 get_bitboard_piece(piece::Type piece, Color color) const;
U64 get_bitboard_piece(const piece::Piece &piece) const;
- U64 get_bitboard_piece_attacks(piece::Type piece, Color color,
- Square square) const;
- U64 get_bitboard_piece_attacks(const piece::Piece &piece,
- Square square) const;
+ U64 get_bitboard_piece_attacks(piece::Type piece, Color color, Square square) const;
+ U64 get_bitboard_piece_attacks(const piece::Piece &piece, Square square) const;
// exception if not found
Color get_square_piece_color(Square square) const;
@@ -77,7 +76,6 @@ class Board {
uint8_t castle = 0;
};
-const piece::Piece &board_square_piece(const Board *self, Square square,
- Color side);
+const piece::Piece &board_square_piece(const Board *self, Square square, Color side);
#endif
diff --git a/src/include/magic.hpp b/src/include/magic.hpp
@@ -0,0 +1,44 @@
+#ifndef STELLAR_ATTACKS_MAGIC_H
+#define STELLAR_ATTACKS_MAGIC_H
+
+#include "utils_cpp.hpp"
+
+static 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 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),
+};
+
+#endif
diff --git a/src/include/moves.hpp b/src/include/moves.hpp
@@ -24,9 +24,8 @@ struct MoveE {
int score;
};
-Move move_encode(uint8_t src, uint8_t tgt, const piece::Piece *piece,
- const piece::Piece *capture, const piece::Piece *promote,
- bool dbl, bool enpassant, bool castle);
+Move move_encode(uint8_t src, uint8_t tgt, const piece::Piece *piece, const piece::Piece *capture,
+ const piece::Piece *promote, bool dbl, bool enpassant, bool castle);
std::vector<MoveE> move_list_generate(const Board &board);
int move_make(Move move, Board &board, int flag);
void move_list_sort(std::vector<MoveE> &list);
diff --git a/src/include/piece.hpp b/src/include/piece.hpp
@@ -1,7 +1,7 @@
#ifndef STELLAR_PIECE_H
#define STELLAR_PIECE_H
-#include "attacks.hpp"
+#include "attack.hpp"
#include "utils_cpp.hpp"
#include <cctype>
@@ -21,73 +21,84 @@ typedef Iterator<Type, Type::PAWN, Type::KING> TypeIter;
class Piece {
public:
+ constexpr U64 operator()(Square square, U64 occupancy) const {
+ return attack(square, occupancy);
+ }
+
const Type type;
const Color color;
const char code;
const char *symbol;
- const attack_get_f attacks;
const uint8_t index;
protected:
- constexpr Piece(Type type, Color color, char code, const char *symbol,
- attack_get_f attacks)
- : type(type), color(color), code(code), symbol(symbol),
- attacks(attacks), index(index_calc(color, type)) {}
+ constexpr Piece(Type type, Color color, char code, const char *symbol, const attack::Attack &attack)
+ : type(type), color(color), code(code), symbol(symbol), index(index_calc(color, type)),
+ attack(attack) {
+ }
constexpr uint8_t index_calc(Color color, Type type) {
return to_underlying(color) * 6 + to_underlying(type);
}
+
+ private:
+ const attack::Attack &attack;
};
class Pawn : public Piece {
public:
constexpr Pawn(Color color)
- : Piece(Type::PAWN, color, color == Color::WHITE ? 'P' : 'p',
- color == Color::WHITE ? "■ " : "■ ",
- color == Color::WHITE ? attacks_wpawn_get : attacks_bpawn_get) {
+ : Piece(Type::PAWN, color, color == Color::WHITE ? 'P' : 'p', color == Color::WHITE ? "■ " : "■ ",
+ color == Color::WHITE ? *(attack::Attack *)&attack::pawnW
+ : *(attack::Attack *)&attack::pawnB) {
}
};
class Knight : public Piece {
public:
constexpr Knight(Color color)
- : Piece(Type::KNIGHT, color, color == Color::WHITE ? 'N' : 'n',
- color == Color::WHITE ? "■ " : "■ ", attacks_knight_get) {}
+ : Piece(Type::KNIGHT, color, color == Color::WHITE ? 'N' : 'n', color == Color::WHITE ? "■ " : "■ ",
+ attack::knight) {
+ }
};
class Bishop : public Piece {
public:
constexpr Bishop(Color color)
- : Piece(Type::BISHOP, color, color == Color::WHITE ? 'B' : 'b',
- color == Color::WHITE ? "■ " : "■ ", attacks_bishop_get) {}
+ : Piece(Type::BISHOP, color, color == Color::WHITE ? 'B' : 'b', color == Color::WHITE ? "■ " : "■ ",
+ attack::bishop) {
+ }
};
class Rook : public Piece {
public:
constexpr Rook(Color color)
- : Piece(Type::ROOK, color, color == Color::WHITE ? 'R' : 'r',
- color == Color::WHITE ? "■ " : "■ ", attacks_rook_get) {}
+ : Piece(Type::ROOK, color, color == Color::WHITE ? 'R' : 'r', color == Color::WHITE ? "■ " : "■ ",
+ attack::rook) {
+ }
};
class Queen : public Piece {
public:
constexpr Queen(Color color)
- : Piece(Type::QUEEN, color, color == Color::WHITE ? 'Q' : 'q',
- color == Color::WHITE ? "■ " : "■ ", attacks_queen_get) {}
+ : Piece(Type::QUEEN, color, color == Color::WHITE ? 'Q' : 'q', color == Color::WHITE ? "■ " : "■ ",
+ attack::queen) {
+ }
};
class King : public Piece {
public:
constexpr King(Color color)
- : Piece(Type::KING, color, color == Color::WHITE ? 'K' : 'k',
- color == Color::WHITE ? "■ " : "■ ", attacks_king_get) {}
+ : Piece(Type::KING, color, color == Color::WHITE ? 'K' : 'k', color == Color::WHITE ? "■ " : "■ ",
+ attack::king) {
+ }
};
const constexpr Piece table[2][6] = {
- {Pawn(Color::WHITE), Knight(Color::WHITE), Bishop(Color::WHITE),
- Rook(Color::WHITE), Queen(Color::WHITE), King(Color::WHITE)},
- {Pawn(Color::BLACK), Knight(Color::BLACK), Bishop(Color::BLACK),
- Rook(Color::BLACK), Queen(Color::BLACK), King(Color::BLACK)},
+ {Pawn(Color::WHITE), Knight(Color::WHITE), Bishop(Color::WHITE), Rook(Color::WHITE), Queen(Color::WHITE),
+ King(Color::WHITE)},
+ {Pawn(Color::BLACK), Knight(Color::BLACK), Bishop(Color::BLACK), Rook(Color::BLACK), Queen(Color::BLACK),
+ King(Color::BLACK)},
};
constexpr const Piece &get(Type type, Color color) {
diff --git a/src/include/utils_cpp.hpp b/src/include/utils_cpp.hpp
@@ -5,8 +5,7 @@
#include <exception>
#include <type_traits>
-template <typename E>
-constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
+template <typename E> constexpr typename std::underlying_type<E>::type to_underlying(E e) noexcept {
return static_cast<typename std::underlying_type<E>::type>(e);
}
@@ -15,20 +14,28 @@ template <typename C, C beginVal, C endVal> class Iterator {
int val;
public:
- constexpr Iterator(const C &f) : val(static_cast<val_t>(f)) {}
- constexpr Iterator() : val(static_cast<val_t>(beginVal)) {}
+ constexpr Iterator(const C &f) : val(static_cast<val_t>(f)) {
+ }
+ constexpr Iterator() : val(static_cast<val_t>(beginVal)) {
+ }
constexpr Iterator operator++() {
++val;
return *this;
}
- constexpr C operator*() { return static_cast<C>(val); }
- constexpr Iterator begin() { return *this; }
+ constexpr C operator*() {
+ return static_cast<C>(val);
+ }
+ constexpr Iterator begin() {
+ return *this;
+ }
constexpr Iterator end() {
// static const Iterator endIter = ++Iterator(endVal);
// return endIter;
return ++Iterator(endVal);
}
- constexpr bool operator!=(const Iterator &i) { return val != i.val; }
+ constexpr bool operator!=(const Iterator &i) {
+ return val != i.val;
+ }
};
#define C64(constantU64) constantU64##ULL
@@ -77,11 +84,19 @@ inline const char *square_to_coordinates(Square square) {
// clang-format on
// useful bit functions
-#define bit_get(bitboard, square) (((bitboard) >> (square)) & C64(1))
-#define bit_set(bitboard, square) ((bitboard) |= C64(1) << (square))
-#define bit_pop(bitboard, square) ((bitboard) &= ~(C64(1) << (square)))
+constexpr bool bit_get(const U64 &bitboard, uint8_t square) {
+ return (bitboard >> (square)) & C64(1);
+}
+
+constexpr void bit_set(U64 &bitboard, uint8_t square) {
+ bitboard |= (C64(1) << square);
+}
+
+constexpr void bit_pop(U64 &bitboard, uint8_t square) {
+ bitboard &= ~(C64(1) << (square));
+}
-inline uint8_t bit_count(U64 bitboard) {
+constexpr uint8_t bit_count(U64 bitboard) {
#if __has_builtin(__builtin_popcountll)
return __builtin_popcountll(bitboard);
#endif
@@ -92,7 +107,7 @@ inline uint8_t bit_count(U64 bitboard) {
return count;
}
-inline uint8_t bit_lsb_index(U64 bitboard) {
+constexpr uint8_t bit_lsb_index(U64 bitboard) {
#if __has_builtin(__builtin_ffsll)
return __builtin_ffsll(bitboard) - 1;
#endif
@@ -103,25 +118,40 @@ inline uint8_t bit_lsb_index(U64 bitboard) {
#define bit_lsb_pop(bitboard) ((bitboard) &= (bitboard) & ((bitboard)-1))
-#define bitboard_for_each_bit(var, bb) \
+#define bitboard_for_each_bit(var, bb) \
for (var = bit_lsb_index(bb); bb; bit_lsb_pop(bb), var = bit_lsb_index(bb))
// board moving
-const U64 universe = C64(0xffffffffffffffff);
-const U64 notAFile = C64(0xfefefefefefefefe);
-const U64 notHFile = C64(0x7f7f7f7f7f7f7f7f);
+inline constexpr const U64 universe = C64(0xffffffffffffffff);
+inline constexpr const U64 notAFile = C64(0xfefefefefefefefe);
+inline constexpr const U64 notHFile = C64(0x7f7f7f7f7f7f7f7f);
typedef U64 (*direction_f)(U64);
-inline U64 soutOne(U64 b) { return b >> 8; }
-inline U64 nortOne(U64 b) { return b << 8; }
-inline U64 eastOne(U64 b) { return (b & notHFile) << 1; }
-inline U64 westOne(U64 b) { return (b & notAFile) >> 1; }
-inline U64 soEaOne(U64 b) { return (b & notHFile) >> 7; }
-inline U64 soWeOne(U64 b) { return (b & notAFile) >> 9; }
-inline U64 noEaOne(U64 b) { return (b & notHFile) << 9; }
-inline U64 noWeOne(U64 b) { return (b & notAFile) << 7; }
-
-#define start_position \
- "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 "
+inline constexpr U64 soutOne(U64 b) {
+ return b >> 8;
+}
+inline constexpr U64 nortOne(U64 b) {
+ return b << 8;
+}
+inline constexpr U64 eastOne(U64 b) {
+ return (b & notHFile) << 1;
+}
+inline constexpr U64 westOne(U64 b) {
+ return (b & notAFile) >> 1;
+}
+inline constexpr U64 soEaOne(U64 b) {
+ return (b & notHFile) >> 7;
+}
+inline constexpr U64 soWeOne(U64 b) {
+ return (b & notAFile) >> 9;
+}
+inline constexpr U64 noEaOne(U64 b) {
+ return (b & notHFile) << 9;
+}
+inline constexpr U64 noWeOne(U64 b) {
+ return (b & notAFile) << 7;
+}
+
+#define start_position "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 "
#endif
diff --git a/src/moves/moves.cpp b/src/moves/moves.cpp
@@ -4,12 +4,13 @@
#include <algorithm>
#include <cstdio>
-int move_cmp(Move a, Move b) { return *(uint32_t *)&a == *(uint32_t *)&b; }
+int move_cmp(Move a, Move b) {
+ return *(uint32_t *)&a == *(uint32_t *)&b;
+}
-Move move_encode(uint8_t src, uint8_t tgt, const piece::Piece *piece,
- const piece::Piece *capture, const piece::Piece *promote,
- bool dbl, bool enpassant, bool castle) {
- return (Move){
+Move move_encode(uint8_t src, uint8_t tgt, const piece::Piece *piece, const piece::Piece *capture,
+ const piece::Piece *promote, bool dbl, bool enpassant, bool castle) {
+ return {
.source = src,
.target = tgt,
.piece = piece->index,
@@ -26,18 +27,15 @@ Move move_encode(uint8_t src, uint8_t tgt, const piece::Piece *piece,
void move_print(Move move) {
printf("%5s %5s %2c %2c %2c %4d %4d %4d %4d %4d\n",
square_to_coordinates(static_cast<Square>(move_source(move))),
- square_to_coordinates(static_cast<Square>(move_target(move))),
- move_piece(move).code,
+ square_to_coordinates(static_cast<Square>(move_target(move))), move_piece(move).code,
move_capture(move) ? move_piece_capture(move).code : '.',
- move_promote(move) ? move_piece_promote(move).code : '.',
- move_double(move) ? 1 : 0, move_enpassant(move) ? 1 : 0,
- move_castle(move) ? 1 : 0, move_capture(move) ? 1 : 0,
+ move_promote(move) ? move_piece_promote(move).code : '.', move_double(move) ? 1 : 0,
+ move_enpassant(move) ? 1 : 0, move_castle(move) ? 1 : 0, move_capture(move) ? 1 : 0,
move_promote(move) ? 1 : 0);
}
void move_list_sort(std::vector<MoveE> &list) {
- std::sort(list.begin(), list.end(),
- [](const MoveE &a, const MoveE &b) { return a.score < b.score; });
+ std::sort(list.begin(), list.end(), [](const MoveE &a, const MoveE &b) { return a.score < b.score; });
}
void move_list_print(const std::vector<MoveE> &list) {
diff --git a/src/moves/moves_generate.cpp b/src/moves/moves_generate.cpp
@@ -3,36 +3,27 @@
#include "piece.hpp"
#include "utils_cpp.hpp"
-#define pawn_canPromote(color, source) \
- ((color == Color::WHITE && source >= Square::a7 && \
- source <= Square::h7) || \
+#define pawn_canPromote(color, source) \
+ ((color == Color::WHITE && source >= Square::a7 && source <= Square::h7) || \
(color == Color::BLACK && source >= Square::a2 && source <= Square::h2))
-#define pawn_onStart(color, source) \
- ((color == Color::BLACK && source >= Square::a7 && \
- source <= Square::h7) || \
+#define pawn_onStart(color, source) \
+ ((color == Color::BLACK && source >= Square::a7 && source <= Square::h7) || \
(color == Color::WHITE && source >= Square::a2 && source <= Square::h2))
-#define pawn_promote(source, target, piece, capture) \
- res.push_back( \
- {move_encode(source, target, &piece, capture, \
- &piece::get(piece::Type::KNIGHT, color), 0, 0, 0), \
- 0}); \
- res.push_back( \
- {move_encode(source, target, &piece, capture, \
- &piece::get(piece::Type::BISHOP, color), 0, 0, 0), \
- 0}); \
- res.push_back( \
- {move_encode(source, target, &piece, capture, \
- &piece::get(piece::Type::ROOK, color), 0, 0, 0), \
- 0}); \
- res.push_back( \
- {move_encode(source, target, &piece, capture, \
- &piece::get(piece::Type::QUEEN, color), 0, 0, 0), \
- 0});
+#define pawn_promote(source, target, piece, capture) \
+ res.push_back( \
+ {move_encode(source, target, &piece, capture, &piece::get(piece::Type::KNIGHT, color), 0, 0, 0), \
+ 0}); \
+ res.push_back( \
+ {move_encode(source, target, &piece, capture, &piece::get(piece::Type::BISHOP, color), 0, 0, 0), \
+ 0}); \
+ res.push_back( \
+ {move_encode(source, target, &piece, capture, &piece::get(piece::Type::ROOK, color), 0, 0, 0), 0}); \
+ res.push_back( \
+ {move_encode(source, target, &piece, capture, &piece::get(piece::Type::QUEEN, color), 0, 0, 0), 0});
std::vector<MoveE> move_list_generate(const Board &board) {
- Move move;
uint8_t src_i, tgt_i;
Color color = board.get_side();
@@ -54,43 +45,34 @@ std::vector<MoveE> move_list_generate(const Board &board) {
if (pawn_canPromote(color, src)) {
pawn_promote(src_i, tgt_i, piece, nullptr);
} else {
- res.push_back(
- {move_encode(src_i, tgt_i, &piece, 0, 0, 0, 0, 0), 0});
+ res.push_back({move_encode(src_i, tgt_i, &piece, 0, 0, 0, 0, 0), 0});
// two ahead
Square tgt = static_cast<Square>(tgt_i + add);
if (pawn_onStart(color, src) && !board.is_square_occupied(tgt))
- res.push_back(
- {move_encode(src_i, tgt_i + add, &piece, 0, 0, 1, 0, 0),
- 0});
+ res.push_back({move_encode(src_i, tgt_i + add, &piece, 0, 0, 1, 0, 0), 0});
}
}
// capture
- U64 attack = board.get_bitboard_piece_attacks(piece, src) &
- board.get_bitboard_color(colorOther);
+ U64 attack = board.get_bitboard_piece_attacks(piece, src) & board.get_bitboard_color(colorOther);
bitboard_for_each_bit(tgt_i, attack) {
Square tgt = static_cast<Square>(tgt_i);
const piece::Piece *capture = board.get_square_piece(tgt);
if (pawn_canPromote(color, src)) {
pawn_promote(src_i, tgt_i, piece, capture);
} else {
- res.push_back(
- {move_encode(src_i, tgt_i, &piece, capture, 0, 0, 0, 0),
- 0});
+ res.push_back({move_encode(src_i, tgt_i, &piece, capture, 0, 0, 0, 0), 0});
}
}
// en passant
if (board.get_enpassant() != Square::no_sq &&
- board.get_bitboard_piece_attacks(piece,
- static_cast<Square>(src_i)) &
+ board.get_bitboard_piece_attacks(piece, static_cast<Square>(src_i)) &
(C64(1) << to_underlying(board.get_enpassant())))
- res.push_back(
- {move_encode(src_i, to_underlying(board.get_enpassant()),
- &piece, &piece::get(piece::Type::PAWN, colorOther),
- 0, 0, 1, 0),
- 0});
+ res.push_back({move_encode(src_i, to_underlying(board.get_enpassant()), &piece,
+ &piece::get(piece::Type::PAWN, colorOther), 0, 0, 1, 0),
+ 0});
}
// All piece move
@@ -100,66 +82,53 @@ std::vector<MoveE> move_list_generate(const Board &board) {
U64 bitboard = board.get_bitboard_piece(piece);
bitboard_for_each_bit(src_i, bitboard) {
Square src = static_cast<Square>(src_i);
- U64 attack = board.get_bitboard_piece_attacks(piece, src) &
- ~board.get_bitboard_color(color);
+ U64 attack = board.get_bitboard_piece_attacks(piece, src) & ~board.get_bitboard_color(color);
bitboard_for_each_bit(tgt_i, attack) {
Square tgt = static_cast<Square>(tgt_i);
res.push_back(
- {move_encode(src_i, tgt_i, &piece,
- board.get_square_piece(tgt), 0, 0, 0, 0),
- 0});
+ {move_encode(src_i, tgt_i, &piece, board.get_square_piece(tgt), 0, 0, 0, 0), 0});
}
}
}
// Castling
if (color == Color::WHITE) {
- static const piece::Piece &piece =
- piece::get(piece::Type::KING, Color::WHITE);
+ static const piece::Piece &piece = piece::get(piece::Type::KING, Color::WHITE);
if (board.get_castle() & to_underlying(Board::Castle::WK)) {
- if (!board.is_square_occupied(Square::f1) &&
- !board.is_square_occupied(Square::g1) &&
+ if (!board.is_square_occupied(Square::f1) && !board.is_square_occupied(Square::g1) &&
!board.is_square_attacked(Square::e1, Color::BLACK) &&
!board.is_square_attacked(Square::f1, Color::BLACK))
- res.push_back({move_encode(to_underlying(Square::e1),
- to_underlying(Square::g1), &piece, 0,
- 0, 0, 0, 1),
- 0});
+ res.push_back(
+ {move_encode(to_underlying(Square::e1), to_underlying(Square::g1), &piece, 0, 0, 0, 0, 1),
+ 0});
}
if (board.get_castle() & to_underlying(Board::Castle::WQ)) {
- if (!board.is_square_occupied(Square::d1) &&
- !board.is_square_occupied(Square::c1) &&
+ if (!board.is_square_occupied(Square::d1) && !board.is_square_occupied(Square::c1) &&
!board.is_square_occupied(Square::b1) &&
!board.is_square_attacked(Square::e1, Color::BLACK) &&
!board.is_square_attacked(Square::d1, Color::BLACK))
- res.push_back({move_encode(to_underlying(Square::e1),
- to_underlying(Square::c1), &piece, 0,
- 0, 0, 0, 1),
- 0});
+ res.push_back(
+ {move_encode(to_underlying(Square::e1), to_underlying(Square::c1), &piece, 0, 0, 0, 0, 1),
+ 0});
}
} else {
- static const piece::Piece &piece =
- piece::get(piece::Type::KING, Color::BLACK);
+ static const piece::Piece &piece = piece::get(piece::Type::KING, Color::BLACK);
if (board.get_castle() & to_underlying(Board::Castle::BK)) {
- if (!board.is_square_occupied(Square::f8) &&
- !board.is_square_occupied(Square::g8) &&
+ if (!board.is_square_occupied(Square::f8) && !board.is_square_occupied(Square::g8) &&
!board.is_square_attacked(Square::e8, Color::WHITE) &&
!board.is_square_attacked(Square::f8, Color::WHITE))
- res.push_back({move_encode(to_underlying(Square::e8),
- to_underlying(Square::g8), &piece, 0,
- 0, 0, 0, 1),
- 0});
+ res.push_back(
+ {move_encode(to_underlying(Square::e8), to_underlying(Square::g8), &piece, 0, 0, 0, 0, 1),
+ 0});
}
if (board.get_castle() & to_underlying(Board::Castle::BQ)) {
- if (!board.is_square_occupied(Square::d8) &&
- !board.is_square_occupied(Square::c8) &&
+ if (!board.is_square_occupied(Square::d8) && !board.is_square_occupied(Square::c8) &&
!board.is_square_occupied(Square::b8) &&
!board.is_square_attacked(Square::e8, Color::WHITE) &&
!board.is_square_attacked(Square::d8, Color::WHITE))
- res.push_back({move_encode(to_underlying(Square::e8),
- to_underlying(Square::c8), &piece, 0,
- 0, 0, 0, 1),
- 0});
+ res.push_back(
+ {move_encode(to_underlying(Square::e8), to_underlying(Square::c8), &piece, 0, 0, 0, 0, 1),
+ 0});
}
}
diff --git a/src/moves/moves_make.cpp b/src/moves/moves_make.cpp
@@ -25,8 +25,7 @@ void _piece_set(Board &board, const piece::Piece &piece, Square square) {
board.xor_hash(zobrist_key_piece(piece, square));
}
-void _piece_move(Board &board, const piece::Piece &piece, Square source,
- Square target) {
+void _piece_move(Board &board, const piece::Piece &piece, Square source, Square target) {
_piece_remove(board, piece, source);
_piece_set(board, piece, target);
}
@@ -40,8 +39,7 @@ int move_make(Move move, Board &board, int flag) {
const Color color = board.get_side();
const Square source = static_cast<Square>(move_source(move));
const Square target = static_cast<Square>(move_target(move));
- const Square ntarget = static_cast<Square>(
- move_target(move) + (color == Color::WHITE ? -8 : +8));
+ const Square ntarget = static_cast<Square>(move_target(move) + (color == Color::WHITE ? -8 : +8));
if (!move_capture(move)) {
if (move_promote(move)) {
@@ -68,16 +66,11 @@ int move_make(Move move, Board &board, int flag) {
board.set_enpassant(move_double(move) ? ntarget : Square::no_sq);
if (move_castle(move)) {
- static const piece::Piece &rook =
- piece::get(piece::Type::ROOK, board.get_side());
- if (target == Square::g1)
- _piece_move(board, rook, Square::h1, Square::f1);
- if (target == Square::c1)
- _piece_move(board, rook, Square::a1, Square::d1);
- if (target == Square::g8)
- _piece_move(board, rook, Square::h8, Square::f8);
- if (target == Square::c8)
- _piece_move(board, rook, Square::a8, Square::d8);
+ static const piece::Piece &rook = piece::get(piece::Type::ROOK, board.get_side());
+ if (target == Square::g1) _piece_move(board, rook, Square::h1, Square::f1);
+ if (target == Square::c1) _piece_move(board, rook, Square::a1, Square::d1);
+ if (target == Square::g8) _piece_move(board, rook, Square::h8, Square::f8);
+ if (target == Square::c8) _piece_move(board, rook, Square::a8, Square::d8);
}
board.xor_hash(zobrist_key_castle(board.get_castle()));
diff --git a/src/perft/CMakeLists.txt b/src/perft/CMakeLists.txt
@@ -6,10 +6,8 @@ if(WITH_FULL_COUNT)
endif()
target_link_libraries(perft
- PRIVATE attacks
PRIVATE board
PRIVATE moves
- PRIVATE piece
PRIVATE random
)
diff --git a/src/perft/perft.cpp b/src/perft/perft.cpp
@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <unistd.h>
-#include "attacks.hpp"
+#include "attack.hpp"
#include "board.hpp"
#include "moves.hpp"
#include "perft.hpp"
@@ -12,8 +12,7 @@
#include "zobrist.hpp"
// FEN debug positions
-#define tricky_position \
- "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 "
+#define tricky_position "r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 1 "
void perft_result_print(PerftResult res) {
printf(" - Perft Results -\n\n");
@@ -48,17 +47,16 @@ void perft_result_add(PerftResult *base, PerftResult *add) {
typedef std::vector<MoveE> MoveList;
-void perft_driver(Board &board, MoveList *moveList, int depth,
- PerftResult *result) {
- moveList[depth] = move_list_generate(board);
+void perft_driver(Board &board, int depth, PerftResult *result) {
+ MoveList moveList = move_list_generate(board);
Board copy;
- for (const auto [move, _] : moveList[depth]) {
+ for (const auto [move, _] : moveList) {
copy = board;
if (!move_make(move, copy, 0)) continue;
if (depth != 1) {
- perft_driver(copy, moveList, depth - 1, result);
+ perft_driver(copy, depth - 1, result);
} else {
result->node++;
#ifdef USE_FULL_COUNT
@@ -85,8 +83,6 @@ struct perf_shared {
void *perft_thread(void *arg) {
PerftResult result = {0};
perf_shared *shared = (perf_shared *)arg;
- MoveList moveList[shared->depth + 1];
-
Board board = Board(shared->fen), copy;
while (1) {
@@ -99,13 +95,14 @@ void *perft_thread(void *arg) {
Move move = shared->list[shared->index++].move;
pthread_mutex_unlock(&shared->mutex);
- result = (PerftResult){0};
+ result = {0};
copy = board;
if (!move_make(move, copy, 0)) continue;
+ // std::cout << copy << std::endl;
if (shared->depth != 1) {
- perft_driver(copy, moveList, shared->depth - 1, &result);
+ perft_driver(copy, shared->depth - 1, &result);
} else {
result.node++;
#ifdef USE_FULL_COUNT
@@ -121,8 +118,8 @@ void *perft_thread(void *arg) {
}
PerftResult perft_test(const char *fen, int depth, int thread_num) {
- pthread_t threads[thread_num];
- perf_shared shared = (perf_shared){
+ pthread_t *threads = new pthread_t(thread_num);
+ perf_shared shared = {
.list = move_list_generate(Board(fen)),
.depth = depth,
.fen = fen,
@@ -135,13 +132,14 @@ PerftResult perft_test(const char *fen, int depth, int thread_num) {
for (int i = 0; i < thread_num; i++)
pthread_join(threads[i], NULL);
+ delete threads;
return shared.result;
}
int main(int argc, char *argv[]) {
int c, depth = 1, thread_num = 1;
- std::string s(tricky_position);
+ std::string s(start_position);
const char *fen = s.data();
while ((c = getopt(argc, argv, "t:f:d:")) != -1) {
switch (c) {
@@ -161,7 +159,6 @@ int main(int argc, char *argv[]) {
}
}
- attacks_init();
zobrist_init();
PerftResult res = perft_test(fen, depth, thread_num);
diff --git a/src/piece/CMakeLists.txt b/src/piece/CMakeLists.txt
@@ -1,7 +0,0 @@
-add_library(piece OBJECT
- piece.cpp
-)
-
-target_include_directories(piece
- PUBLIC "${PROJECT_SOURCE_DIR}/src/include"
-)
diff --git a/src/piece/piece.cpp b/src/piece/piece.cpp
@@ -1 +0,0 @@
-#include "piece.hpp"
diff --git a/src/utils/random.cpp b/src/utils/random.cpp
@@ -2,7 +2,9 @@
U32 state = C32(1804289383);
-void random_state_reset() { state = C32(1804289383); }
+void random_state_reset() {
+ state = C32(1804289383);
+}
U32 random_get_U32() {
U32 number = state;