Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 0 additions & 30 deletions .github/workflows/clang-format.yml

This file was deleted.

24 changes: 24 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,31 @@ on:
- '**.hpp'

jobs:
format:
if: github.actor != 'github-actions[bot]'
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
commit_sha: ${{ steps.auto-commit.outputs.commit_hash }}

steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}

- name: Install clang-format
run: sudo apt-get update && sudo apt-get install -y clang-format

- name: Run clang-format
run: clang-format -i $(git ls-files '*.cpp' '*.hpp' '*.h' '*.c')

- name: Commit and push changes
id: auto-commit
uses: stefanzweifel/git-auto-commit-action@v7

build:
needs: format
runs-on: ${{ matrix.os }}

strategy:
Expand Down
21 changes: 14 additions & 7 deletions attacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ namespace chess::attacks {
#ifndef GENERATE_AT_RUNTIME
#define _POSSIBLY_CONSTEXPR constexpr
#else
#define _POSSIBLY_CONSTEXPR const
#define _POSSIBLY_CONSTEXPR
#endif
// clang-format off
_POSSIBLY_CONSTEXPR std::array<uint64_t, 64> RookMagics = {
Expand Down Expand Up @@ -140,7 +140,6 @@ _POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, TableS
std::array<Bitboard, TableSize> attacks{};

size_t offset = 0;

for (Square sq = SQ_A1; sq < SQ_NONE; ++sq) {
Bitboard occ = 0;
Bitboard edges = ((attacks::MASK_RANK[0] | attacks::MASK_RANK[7]) & ~attacks::MASK_RANK[rank_of(sq)]) |
Expand All @@ -165,6 +164,7 @@ _POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, TableS

// Carry-rippler loop over all blocker subsets
occ = 0;

do {
size_t idx = entry(occ);
attacks[offset + idx] = AttackFunc(static_cast<Square>(sq), occ);
Expand All @@ -173,7 +173,6 @@ _POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, TableS

offset += (1ULL << bits);
}

return std::pair{ table, attacks };
}
_POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, 0x1480>> bishopData =
Expand All @@ -185,14 +184,22 @@ _POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, 0x1900
generate_magic_table<_chess::_HyperbolaRookAttacks, 0x19000, false>();
_POSSIBLY_CONSTEXPR std::array<Magic, 64> RookTable = rookData.first;
_POSSIBLY_CONSTEXPR std::array<Bitboard, 0x19000> RookAttacks = rookData.second;

[[nodiscard]] Bitboard bishop(Square sq, Bitboard occupied) {
return BishopAttacks[BishopTable[(int)sq].index + BishopTable[(int)sq](occupied)];
}

[[nodiscard]] Bitboard rook(Square sq, Bitboard occupied) {
return RookAttacks[RookTable[(int)sq].index + RookTable[(int)sq](occupied)];
}
} // namespace chess::attacks
namespace chess::movegen {
inline static Bitboard att(PieceType pt, Square sq, Bitboard occ) {
return (pt == BISHOP) ? chess::_chess::_HyperbolaBishopAttacks(sq, occ) : chess::_chess::_HyperbolaRookAttacks(sq, occ);
}

inline static std::array<std::array<Bitboard, SQ_NONE + 1>, SQ_NONE + 1> generate_between() {
std::array<std::array<Bitboard, SQ_NONE + 1>, SQ_NONE + 1> squares_between_bb{};
inline static std::array<std::array<Bitboard, 64>, 64> generate_between() {
std::array<std::array<Bitboard, 64>, 64> squares_between_bb{};

for (int sq1 = 0; sq1 < 64; ++sq1) {
for (PieceType pt : { BISHOP, ROOK }) {
Expand All @@ -207,5 +214,5 @@ inline static std::array<std::array<Bitboard, SQ_NONE + 1>, SQ_NONE + 1> generat

return squares_between_bb;
}
std::array<std::array<Bitboard, SQ_NONE + 1>, SQ_NONE + 1> SQUARES_BETWEEN_BB = generate_between();
} // namespace chess::movegen
std::array<std::array<Bitboard, 64>, 64> SQUARES_BETWEEN_BB = generate_between();
} // namespace chess::movegen
23 changes: 5 additions & 18 deletions attacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "types.h"
#include <array>
#include <immintrin.h>
#include <vector>
namespace chess::attacks {
// clang-format off
// pre-calculated lookup table for pawn attacks
Expand Down Expand Up @@ -110,13 +111,9 @@ namespace chess::attacks {
0x101010101010101, 0x202020202020202, 0x404040404040404, 0x808080808080808,
0x1010101010101010, 0x2020202020202020, 0x4040404040404040, 0x8080808080808080,
};
extern const std::array<uint64_t, 64> BishopMagics;
extern const std::array<uint64_t, 64> RookMagics;
// clang-format on
#ifdef __BMI2__
constexpr uint64_t software_pext_u64(uint64_t val, uint64_t mask) {
if (!is_constant_evaluated())
return ~0ULL;
uint64_t result = 0;
uint64_t bit_position = 0;

Expand Down Expand Up @@ -153,10 +150,6 @@ struct Magic {

} // namespace chess::attacks
namespace chess::attacks {
extern const std::array<Magic, 64> RookTable;
extern const std::array<Bitboard, 0x19000> RookAttacks;
extern const std::array<Magic, 64> BishopTable;
extern const std::array<Bitboard, 0x1480> BishopAttacks;
/**
* @brief Shifts a bitboard in a given direction
* @tparam direction
Expand Down Expand Up @@ -293,34 +286,28 @@ template <Color c> [[nodiscard]] constexpr Bitboard pawn(const Bitboard pawns) {
Bitboard h2 = l2 | r2; // 2-square horizontal shifts
return (h1 << 16) | (h1 >> 16) | (h2 << 8) | (h2 >> 8); // vertical shifts: +2,+1,-2,-1
}

/**
* @brief Returns the bishop attacks for a given square
* @param sq
* @param occupied
* @return
*/
[[nodiscard]] constexpr Bitboard bishop(Square sq, Bitboard occupied) {
return BishopAttacks[BishopTable[(int)sq].index + BishopTable[(int)sq](occupied)];
}
[[nodiscard]] Bitboard bishop(Square sq, Bitboard occupied);

/**
* @brief Returns the rook attacks for a given square
* @param sq
* @param occupied
* @return
*/
[[nodiscard]] constexpr Bitboard rook(Square sq, Bitboard occupied) {
return RookAttacks[RookTable[(int)sq].index + RookTable[(int)sq](occupied)];
}

[[nodiscard]] Bitboard rook(Square sq, Bitboard occupied);
/**
* @brief Returns the queen attacks for a given square
* @param sq
* @param occupied
* @return
*/
[[nodiscard]] constexpr Bitboard queen(Square sq, Bitboard occupied) { return bishop(sq, occupied) | rook(sq, occupied); }
[[nodiscard]] inline Bitboard queen(Square sq, Bitboard occupied) { return bishop(sq, occupied) | rook(sq, occupied); }

/**
* @brief Returns the king attacks for a given square
Expand All @@ -336,7 +323,7 @@ template <Color c> [[nodiscard]] constexpr Bitboard pawn(const Bitboard pawns) {
* @tparam pt
* @return
*/
template <PieceType pt> [[nodiscard]] constexpr Bitboard slider(Square sq, Bitboard occupied) {
template <PieceType pt> [[nodiscard]] inline Bitboard slider(Square sq, Bitboard occupied) {
static_assert(pt == PieceType::BISHOP || pt == PieceType::ROOK || pt == PieceType::QUEEN, "PieceType must be a slider!");

if constexpr (pt == PieceType::BISHOP)
Expand Down
35 changes: 19 additions & 16 deletions chess960_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ template <typename T, MoveGenType mt, bool EnableDiv = false> uint64_t perft(_Po
pos.template legals<mt>(moves);
uint64_t total = 0;
for (const Move &m : moves) {
pos.template doMove<false>(m);
pos.template do_move<false>(m);
#if !IS_RELEASE
{
const auto pre_nm_hash_1 = pos.hash();
const auto pre_nm_fen_1 = pos.fen();
if (pos.zobrist() != pos.hash())
REQUIRE(pos.zobrist() == pos.hash());
pos.doNullMove();
pos.undoMove();
pos.do_null_move();
pos.undo_move();
if (!(pos.hash() == pre_nm_hash_1 && pos.fen() == pre_nm_fen_1 && pos.zobrist() == pre_nm_hash_1)) {
REQUIRE(pos.hash() == pre_nm_hash_1);
REQUIRE(pos.fen() == pre_nm_fen_1);
Expand All @@ -77,16 +77,16 @@ template <typename T, MoveGenType mt, bool EnableDiv = false> uint64_t perft(_Po
const auto pre_nm_fen_1 = pos.fen();
if (pos.zobrist() != pos.hash())
REQUIRE(pos.zobrist() == pos.hash());
pos.doNullMove();
pos.undoMove();
pos.do_null_move();
pos.undo_move();
if (!(pos.hash() == pre_nm_hash_1 && pos.fen() == pre_nm_fen_1 && pos.zobrist() == pre_nm_hash_1)) {
REQUIRE(pos.hash() == pre_nm_hash_1);
REQUIRE(pos.fen() == pre_nm_fen_1);
REQUIRE(pos.zobrist() == pre_nm_hash_1);
}
}
#endif
pos.undoMove();
pos.undo_move();
if constexpr (EnableDiv)
std::cout << m << ": " << nodes << '\n';
total += nodes;
Expand All @@ -112,13 +112,22 @@ auto split_testcases(std::vector<TestEntry<std::string, perft_t>> &entries) {
bucket3.push_back(e);
}

size_t n1 = std::min(bucket1.size(), size_t(2000));
size_t n1 = std::min(bucket1.size(), size_t(1000));
optimized.insert(optimized.end(), bucket1.begin(), bucket1.begin() + n1);
#if defined(_WIN32)
size_t size = 5;
#else
size_t size = 15;
#endif
size_t n2 = std::min(bucket2.size(), size); // GitHub Actions having slowdown on Windows runners

size_t n2 = std::min(bucket2.size(), size_t(30));
optimized.insert(optimized.end(), bucket2.begin(), bucket2.begin() + n2);

size_t n3 = std::min(bucket3.size(), size_t(5));
#if defined(_WIN32)
size = 0;
#else
size = 1;
#endif
size_t n3 = std::min(bucket3.size(), size);
if (n3 > 0) {
optimized.insert(optimized.end(), bucket3.end() - n3, bucket3.end());
}
Expand All @@ -137,12 +146,6 @@ void check_perfts(std::vector<TestEntry<std::string, perft_t>> &entries) {
auto start_time = high_resolution_clock::now();
for (auto &entry : entries) {
std::cerr << entry.input << " (chess960=true) " << entry.info.depth;
#if !IS_RELEASE
if (entry.info.nodes > 1e6) {
std::cerr << "(skipped)\n";
continue;
}
#endif
std::cerr << '\n';
{
_Position<PolyglotPiece> pos(entry.input, true);
Expand Down
21 changes: 11 additions & 10 deletions movegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ inline Move *splat_moves(Move *moveList, Square from, Bitboard to_bb) {
namespace chess {
template <typename T, Color c> void movegen::genEP(const _Position<T, void> &pos, Movelist &mv) {

const Square king_sq = pos.kingSq(c);
const Square king_sq = pos.king_sq(c);
const Square ep_sq = pos.ep_square();
if (ep_sq == SQ_NONE)
return;
Expand All @@ -139,12 +139,12 @@ template <typename T, Color c> void movegen::genEP(const _Position<T, void> &pos
const Bitboard ep_mask = (1ULL << ep_pawn_sq) | (1ULL << ep_sq);
// ASSUME(popcount(candidates) <= 32);

Bitboard occ_all = pos.occ();
while (candidates) {
Square from = static_cast<Square>(pop_lsb(candidates));

// Remove the EP pawn and this attacker from occupancy
Bitboard occ_temp = pos.occ();
occ_temp ^= (1ULL << from) | ep_mask;
Bitboard occ_temp = occ_all ^ ((1ULL << from) | ep_mask);

// attackers check
Bitboard atks = 0;
Expand All @@ -165,7 +165,7 @@ void movegen::genPawnDoubleMoves(const _Position<T, void> &pos, Movelist &moves,
Bitboard pawns = pos.template pieces<PAWN, c>() & RANK_2;

// Split pin types
Bitboard pin_file = pin_mask & attacks::MASK_FILE[file_of(pos.kingSq(c))];
Bitboard pin_file = pin_mask & attacks::MASK_FILE[file_of(pos.king_sq(c))];

Bitboard unpinned = pawns & ~pin_mask;
Bitboard file_pinned = pawns & pin_file;
Expand Down Expand Up @@ -283,7 +283,7 @@ void movegen::genKnightMoves(const _Position<T, void> &pos, Movelist &list, Bitb
template <typename T, Color c, bool capturesOnly>
void movegen::genKingMoves(const _Position<T, void> &pos, Movelist &out, Bitboard _pin_mask) {
constexpr Color them = ~c;
const Square kingSq = pos.kingSq(c);
const Square kingSq = pos.king_sq(c);
const Bitboard occAll = pos.occ();
const Bitboard myOcc = pos.occ(c);

Expand All @@ -307,7 +307,7 @@ void movegen::genKingMoves(const _Position<T, void> &pos, Movelist &out, Bitboar
enemyAttacks |= attacks::pawn<them>(pos.template pieces<PAWN, them>());

// Enemy king (adjacent control squares)
enemyAttacks |= attacks::king(pos.kingSq(them));
enemyAttacks |= attacks::king(pos.king_sq(them));

Bitboard moves = attacks::king(kingSq) & ~myOcc & ~enemyAttacks;
if constexpr (capturesOnly)
Expand All @@ -322,11 +322,11 @@ void movegen::genKingMoves(const _Position<T, void> &pos, Movelist &out, Bitboar
Bitboard enemy_attacks = enemyAttacks;
constexpr CastlingRights kingRights = KING_SIDE & (c == WHITE ? WHITE_CASTLING : BLACK_CASTLING),
queenRights = QUEEN_SIDE & (c == WHITE ? WHITE_CASTLING : BLACK_CASTLING);
Bitboard OO_EMPTY = pos.getCastlingPath(c, true);
Bitboard OO_EMPTY = pos.get_castling_path(c, true);
Bitboard OO_SAFE = between(kingSq, castling_king_square(c, true));
Bitboard OOO_EMPTY = pos.getCastlingPath(c, false);
Bitboard OOO_EMPTY = pos.get_castling_path(c, false);
Bitboard OOO_SAFE = between(kingSq, castling_king_square(c, false));
Square rookKing = pos.getCastlingMetadata(c).rook_start_ks, rookQueen = pos.getCastlingMetadata(c).rook_start_qs;
Square rookKing = pos.get_castling_metadata(c).rook_start_ks, rookQueen = pos.get_castling_metadata(c).rook_start_qs;

if (pos.castlingRights() & kingRights &&
!(occupancy & OO_EMPTY || enemy_attacks & OO_SAFE || _pin_mask & 1ULL << rookKing)) {
Expand All @@ -350,6 +350,7 @@ void movegen::genSlidingMoves(
sliders &= ~rook_pinners;
if constexpr (pt == ROOK)
sliders &= ~bishop_pinners;
Bitboard occ_opp = pos.occ(~c);
Bitboard filter_list = ~pos.occ(c) & _check_mask;
while (sliders) {
Square from = static_cast<Square>(pop_lsb(sliders));
Expand All @@ -368,7 +369,7 @@ void movegen::genSlidingMoves(
Bitboard filtered_pin = pin_mask & filter_list;
Bitboard targets = func(from, occ_all) & filtered_pin;
if constexpr (capturesOnly)
targets &= pos.occ(~c);
targets &= occ_opp;
_chess::splat_moves(moves.data() + moves.size_, from, targets);
moves.size_ += popcount(targets);
}
Expand Down
2 changes: 1 addition & 1 deletion movegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void genKnightMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard);
template <typename T, Color c, bool capturesOnly = false> void genKingMoves(const _Position<T, void> &, Movelist &, Bitboard);
template <typename T, Color c, PieceType pt, bool capturesOnly = false>
void genSlidingMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard, Bitboard);
extern std::array<std::array<Bitboard, 65>, 65> SQUARES_BETWEEN_BB;
extern std::array<std::array<Bitboard, 64>, 64> SQUARES_BETWEEN_BB;
/*
* [(file(sq1), rank(sq1)), (file(sq2), rank(sq2))] -> bitboard of squares between sq1 and sq2, excluding sq1 and sq2
*/
Expand Down
Loading
Loading