Skip to content

Commit 9942ae8

Browse files
authored
add support for SAN notation parsing and generation (#30)
Fixes #29, #31, #24
1 parent 66278aa commit 9942ae8

17 files changed

Lines changed: 2797 additions & 1550 deletions

.github/workflows/clang-format.yml

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
1-
name: clang-format check
1+
name: clang-format
22

3-
uses: jidicula/clang-format-action@v4.16.0
43
on:
54
pull_request:
6-
branches: [ "main" ]
5+
branches: [ "main" ]
6+
7+
jobs:
8+
format:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
contents: write # required to push back into PR
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
with:
16+
token: ${{ secrets.GITHUB_TOKEN }}
17+
18+
- name: Run clang-format
19+
run: |
20+
clang-format -i $(git ls-files '*.cpp' '*.hpp' '*.h' '*.c')
21+
22+
- name: Commit and push changes
23+
run: |
24+
if ! git diff --quiet; then
25+
git config user.email "actions@github.com"
26+
git.config user.name "GitHub Actions"
27+
git add .
28+
git commit -m "Apply clang-format"
29+
git push
30+
fi

.github/workflows/cmake-multi-platform.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ jobs:
7575
shell: bash
7676
run: |
7777
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
78-
ctest --build-config ${{ matrix.build_type }} --verbose
78+
ctest --build-config ${{ matrix.build_type }} --verbose -j 4
7979
else
80-
ctest --verbose
80+
ctest --verbose -j 4
8181
fi

CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ FetchContent_MakeAvailable(doctest)
5656
add_executable(test_chess
5757
tests.cpp
5858
)
59+
add_executable(NonImportantTests
60+
non_core_tests.cpp
61+
)
5962
target_link_libraries(test_chess PRIVATE chesslib)
6063
target_include_directories(test_chess PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${doctest_SOURCE_DIR})
61-
add_test(NAME tests COMMAND test_chess)
64+
target_link_libraries(NonImportantTests PRIVATE chesslib)
65+
target_include_directories(NonImportantTests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${doctest_SOURCE_DIR})
66+
add_test(NAME test_core COMMAND test_chess)
67+
add_test(NAME api_tests COMMAND NonImportantTests)

attacks.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,30 @@ _POSSIBLY_CONSTEXPR std::pair<std::array<Magic, 64>, std::array<Bitboard, 0x1900
167167
generate_magic_table<_chess::_HyperbolaRookAttacks, 0x19000, false>();
168168
_POSSIBLY_CONSTEXPR std::array<Magic, 64> RookTable = rookData.first;
169169
_POSSIBLY_CONSTEXPR std::array<Bitboard, 0x19000> RookAttacks = rookData.second;
170-
} // namespace chess::attacks
170+
} // namespace chess::attacks
171+
namespace chess::movegen {
172+
inline static Bitboard att(PieceType pt, Square sq, Bitboard occ) {
173+
return (pt == BISHOP) ? chess::_chess::_HyperbolaBishopAttacks(sq, occ) : chess::_chess::_HyperbolaRookAttacks(sq, occ);
174+
}
175+
176+
inline static std::array<std::array<Bitboard, 64>, 64> generate_between() {
177+
assert(att(BISHOP, SQ_A1, 0) == 9241421688590303744ULL &&
178+
"Well... this is a debug message, but this is a landmine that the magic bitboards are NOT initialized before this, "
179+
"wontwork\n");
180+
std::array<std::array<Bitboard, 64>, 64> squares_between_bb{};
181+
182+
for (int sq1 = 0; sq1 < 64; ++sq1) {
183+
for (PieceType pt : { BISHOP, ROOK }) {
184+
for (int sq2 = 0; sq2 < 64; ++sq2) {
185+
if (att(pt, Square(sq1), 0) & (1ULL << sq2)) {
186+
squares_between_bb[sq1][sq2] = att(pt, Square(sq1), 1ULL << (sq2)) & att(pt, Square(sq2), 1ULL << (sq1));
187+
}
188+
squares_between_bb[sq1][sq2] |= 1ULL << (sq2);
189+
}
190+
}
191+
}
192+
193+
return squares_between_bb;
194+
}
195+
std::array<std::array<Bitboard, 64>, 64> SQUARES_BETWEEN_BB = generate_between();
196+
} // namespace chess::movegen

attacks.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,8 @@ extern const std::array<Bitboard, 0x1480> BishopAttacks;
144144
* @return
145145
*/
146146
template <Direction direction> [[nodiscard]] static constexpr Bitboard shift(const Bitboard b) {
147-
ASSUME(direction == NORTH || direction == EAST || direction == SOUTH || direction == WEST || direction == NORTH_EAST || direction == SOUTH_EAST || direction == SOUTH_WEST || direction == NORTH_WEST);
147+
ASSUME(direction == NORTH || direction == EAST || direction == SOUTH || direction == WEST || direction == NORTH_EAST ||
148+
direction == SOUTH_EAST || direction == SOUTH_WEST || direction == NORTH_WEST);
148149
switch (direction) {
149150
case Direction::NORTH:
150151
return b << 8;
@@ -240,15 +241,19 @@ template <Color c> [[nodiscard]] constexpr Bitboard pawn(const Bitboard pawns) {
240241
* @param occupied
241242
* @return
242243
*/
243-
[[nodiscard]] constexpr Bitboard bishop(Square sq, Bitboard occupied) { return BishopAttacks[BishopTable[(int)sq].index + BishopTable[(int)sq](occupied)]; }
244+
[[nodiscard]] constexpr Bitboard bishop(Square sq, Bitboard occupied) {
245+
return BishopAttacks[BishopTable[(int)sq].index + BishopTable[(int)sq](occupied)];
246+
}
244247

245248
/**
246249
* @brief Returns the rook attacks for a given square
247250
* @param sq
248251
* @param occupied
249252
* @return
250253
*/
251-
[[nodiscard]] constexpr Bitboard rook(Square sq, Bitboard occupied) { return RookAttacks[RookTable[(int)sq].index + RookTable[(int)sq](occupied)]; }
254+
[[nodiscard]] constexpr Bitboard rook(Square sq, Bitboard occupied) {
255+
return RookAttacks[RookTable[(int)sq].index + RookTable[(int)sq](occupied)];
256+
}
252257

253258
/**
254259
* @brief Returns the queen attacks for a given square

fwd_decl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ enum MoveType : uint16_t;
1515
enum File : int8_t;
1616
enum Rank : int8_t;
1717
class Move;
18-
enum class MoveGenType : uint8_t;
18+
enum class MoveGenType : uint16_t;
1919
template <typename T, typename> class _Position;
20-
using Bitboard=uint64_t;
20+
using Bitboard = uint64_t;
2121
using Key = uint64_t;
2222
template <typename T, std::size_t MaxSize> class ValueList;
2323
using Movelist = ValueList<Move, 256>;

movegen.cpp

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Move *splat_moves(Move *moveList, Square from, Bitboard to_bb) {
3737
return moveList;
3838
}
3939

40-
template <int offset> Move *splat_pawn_moves(Move *moveList, Bitboard to_bb) {
40+
template <Direction offset> Move *splat_pawn_moves(Move *moveList, Bitboard to_bb) {
4141
const auto *table = reinterpret_cast<const __m512i *>(SPLAT_PAWN_TABLE<offset>.data.data());
4242
moveList = write_moves(moveList, static_cast<uint32_t>(to_bb >> 0), _mm512_load_si512(table + 0));
4343
moveList = write_moves(moveList, static_cast<uint32_t>(to_bb >> 32), _mm512_load_si512(table + 1));
@@ -435,37 +435,28 @@ template Move *chess::_chess::splat_pawn_moves<SOUTH_WEST>(Move *, Bitboard);
435435
Movelist &, \
436436
Bitboard, \
437437
Bitboard, \
438-
Bitboard); \
439-
template void chess::movegen::genKnightMoves<PieceC, Color::WHITE, true>(const _Position<PieceC, void>&, Movelist&, Bitboard, Bitboard); \
440-
template void chess::movegen::genKnightMoves<PieceC, Color::BLACK, true>(const _Position<PieceC, void>&, Movelist&, Bitboard, Bitboard); \
441-
template void chess::movegen::genKnightMoves<PieceC, Color::WHITE, false>(const _Position<PieceC, void>&, Movelist&, Bitboard, Bitboard); \
442-
template void chess::movegen::genKnightMoves<PieceC, Color::BLACK, false>(const _Position<PieceC, void>&, Movelist&, Bitboard, Bitboard); \
443-
template void chess::movegen::genKingMoves<PieceC, Color::WHITE, true>(const _Position<PieceC, void>&, Movelist&); \
444-
template void chess::movegen::genKingMoves<PieceC, Color::BLACK, true>(const _Position<PieceC, void>&, Movelist&); \
445-
template void chess::movegen::genKingMoves<PieceC, Color::WHITE, false>(const _Position<PieceC, void>&, Movelist&); \
446-
template void chess::movegen::genKingMoves<PieceC, Color::BLACK, false>(const _Position<PieceC, void>&, Movelist&);
438+
Bitboard); \
439+
template void chess::movegen::genKnightMoves<PieceC, Color::WHITE, true>(const _Position<PieceC, void> &, \
440+
Movelist &, \
441+
Bitboard, \
442+
Bitboard); \
443+
template void chess::movegen::genKnightMoves<PieceC, Color::BLACK, true>(const _Position<PieceC, void> &, \
444+
Movelist &, \
445+
Bitboard, \
446+
Bitboard); \
447+
template void chess::movegen::genKnightMoves<PieceC, Color::WHITE, false>(const _Position<PieceC, void> &, \
448+
Movelist &, \
449+
Bitboard, \
450+
Bitboard); \
451+
template void chess::movegen::genKnightMoves<PieceC, Color::BLACK, false>(const _Position<PieceC, void> &, \
452+
Movelist &, \
453+
Bitboard, \
454+
Bitboard); \
455+
template void chess::movegen::genKingMoves<PieceC, Color::WHITE, true>(const _Position<PieceC, void> &, Movelist &); \
456+
template void chess::movegen::genKingMoves<PieceC, Color::BLACK, true>(const _Position<PieceC, void> &, Movelist &); \
457+
template void chess::movegen::genKingMoves<PieceC, Color::WHITE, false>(const _Position<PieceC, void> &, Movelist &); \
458+
template void chess::movegen::genKingMoves<PieceC, Color::BLACK, false>(const _Position<PieceC, void> &, Movelist &);
447459
INSTANTIATE(EnginePiece)
448460
INSTANTIATE(PolyglotPiece)
449461
INSTANTIATE(ContiguousMappingPiece)
450-
inline static Bitboard att(PieceType pt, Square sq, Bitboard occ) {
451-
return (pt == BISHOP) ? attacks::bishop(sq, occ) : attacks::rook(sq, occ);
452-
}
453-
454-
inline static std::array<std::array<Bitboard, 64>, 64> generate_between() {
455-
std::array<std::array<Bitboard, 64>, 64> squares_between_bb{};
456-
457-
for (int sq1 = 0; sq1 < 64; ++sq1) {
458-
for (PieceType pt : { BISHOP, ROOK }) {
459-
for (int sq2 = 0; sq2 < 64; ++sq2) {
460-
if (att(pt, Square(sq1), 0) & (1ULL << sq2)) {
461-
squares_between_bb[sq1][sq2] = att(pt, Square(sq1), 1ULL << (sq2)) & att(pt, Square(sq2), 1ULL << (sq1));
462-
}
463-
squares_between_bb[sq1][sq2] |= 1ULL << (sq2);
464-
}
465-
}
466-
}
467-
468-
return squares_between_bb;
469-
}
470-
std::array<std::array<Bitboard, 64>, 64> movegen::SQUARES_BETWEEN_BB = generate_between();
471-
} // namespace chess
462+
} // namespace chess

movegen.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
#pragma once
22
#include "fwd_decl.h"
33
#include <array>
4-
namespace chess::_chess{
5-
template <Direction offset> extern Move *splat_pawn_moves(Move *moveList, Bitboard to_bb);
6-
extern Move *splat_moves(Move *moveList, Square from, Bitboard to_bb);
7-
}
4+
namespace chess::_chess {
5+
template <Direction offset> extern Move *splat_pawn_moves(Move *moveList, Bitboard to_bb);
6+
extern Move *splat_moves(Move *moveList, Square from, Bitboard to_bb);
7+
} // namespace chess::_chess
88
namespace chess::movegen {
9-
10-
template <typename T, Color c> void genEP(const _Position<T, void>&, Movelist&);
11-
template <typename T, Color c> void genPawnDoubleMoves(const _Position<T, void>&, Movelist &, Bitboard, Bitboard);
12-
template <typename T, Color c, bool capturesOnly = false> void genPawnSingleMoves(const _Position<T, void>&, Movelist &, Bitboard, Bitboard, Bitboard);
13-
template <typename T, Color c, bool capturesOnly = false> void genKnightMoves(const _Position<T, void>&, Movelist &, Bitboard, Bitboard);
14-
template <typename T, Color c, bool capturesOnly = false> void genKingMoves(const _Position<T, void>&, Movelist &);
15-
template <typename T, Color c, PieceType pt, bool capturesOnly = false> void genSlidingMoves(const _Position<T, void>&, Movelist &, Bitboard, Bitboard, Bitboard);
16-
extern std::array<std::array<Bitboard, 64>, 64> SQUARES_BETWEEN_BB;
17-
[[nodiscard]] inline Bitboard between(Square sq1, Square sq2) noexcept { return SQUARES_BETWEEN_BB[sq1][sq2]; }
9+
10+
template <typename T, Color c> void genEP(const _Position<T, void> &, Movelist &);
11+
template <typename T, Color c> void genPawnDoubleMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard);
12+
template <typename T, Color c, bool capturesOnly = false>
13+
void genPawnSingleMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard, Bitboard);
14+
template <typename T, Color c, bool capturesOnly = false>
15+
void genKnightMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard);
16+
template <typename T, Color c, bool capturesOnly = false> void genKingMoves(const _Position<T, void> &, Movelist &);
17+
template <typename T, Color c, PieceType pt, bool capturesOnly = false>
18+
void genSlidingMoves(const _Position<T, void> &, Movelist &, Bitboard, Bitboard, Bitboard);
19+
extern std::array<std::array<Bitboard, 64>, 64> SQUARES_BETWEEN_BB;
20+
[[nodiscard]] inline Bitboard between(Square sq1, Square sq2) noexcept { return SQUARES_BETWEEN_BB[sq1][sq2]; }
1821
} // namespace chess::movegen

0 commit comments

Comments
 (0)