stellar

Stellar - UCI Chess engine written in C++20
git clone git://git.dimitrijedobrota.com/stellar.git
Log | Files | Refs | README | LICENSE

commit 64a67cd47dc75e777739555b0380a7134fe1cef8
parent 55197a63e49580de502e4ec9885ea85a10ef5049
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Mon,  7 Aug 2023 17:27:17 +0200

Split moves into generation and make file

Diffstat:
Msrc/moves/CMakeLists.txt | 2++
Msrc/moves/moves.c | 225-------------------------------------------------------------------------------
Asrc/moves/moves_generate.c | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/moves/moves_make.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 232 insertions(+), 225 deletions(-)

diff --git a/src/moves/CMakeLists.txt b/src/moves/CMakeLists.txt @@ -1,5 +1,7 @@ add_library(moves OBJECT moves.c + moves_make.c + moves_generate.c ) target_include_directories(moves diff --git a/src/moves/moves.c b/src/moves/moves.c @@ -6,7 +6,6 @@ #include "board.h" #include "moves.h" -#include "zobrist.h" int move_cmp(Move a, Move b) { return *(uint32_t *)&a == *(uint32_t *)&b; } @@ -63,227 +62,3 @@ void move_list_print(const MoveList *self) { printf("Total: %d\n", self->count); } -#define pawn_canPromote(color, source) \ - ((color == WHITE && source >= a7 && source <= h7) || \ - (color == BLACK && source >= a2 && source <= h2)) - -#define pawn_onStart(color, source) \ - ((color == BLACK && source >= a7 && source <= h7) || \ - (color == WHITE && source >= a2 && source <= h2)) - -#define pawn_promote(source, target, Piece, Capture) \ - for (int i = 1; i < 5; i++) { \ - move = move_encode(source, target, Piece, Capture, \ - piece_get(i, color), 0, 0, 0); \ - move_list_add(moves, move); \ - } - -MoveList *move_list_generate(MoveList *moves, const Board *board) { - Move move; - Square src, tgt; - eColor color = board_side(board); - - if (!moves) - moves = move_list_new(); - else - move_list_reset(moves); - - // pawn moves - Piece piece = piece_get(PAWN, color); - U64 bitboard = board_pieceSet(board, piece); - bitboard_for_each_bit(src, bitboard) { - { // quiet - int add = (color == WHITE) ? +8 : -8; - tgt = src + add; - if (!board_square_isOccupied(board, tgt)) { - if (pawn_canPromote(color, src)) { - pawn_promote(src, tgt, piece, 0); - } else { - move_list_add(moves, - move_encode(src, tgt, piece, 0, 0, 0, 0, 0)); - - // two ahead - if (pawn_onStart(color, src) && - !board_square_isOccupied(board, tgt += add)) - move_list_add( - moves, move_encode(src, tgt, piece, 0, 0, 1, 0, 0)); - } - } - } - { // capture - U64 attack = board_piece_attacks(board, piece, src) & - board_color(board, !color); - bitboard_for_each_bit(tgt, attack) { - if (pawn_canPromote(color, src)) { - pawn_promote(src, tgt, piece, - board_square_piece(board, tgt, !color)); - } else { - move_list_add(moves, move_encode(src, tgt, piece, - board_square_piece( - board, tgt, !color), - 0, 0, 0, 0)); - } - } - } - - { // en passant - if (board_enpassant(board) != no_sq && - board_piece_attacks(board, piece, src) & - (C64(1) << board_enpassant(board))) - move_list_add(moves, - move_encode(src, board_enpassant(board), piece, - piece_get(PAWN, !color), 0, 0, 1, 0)); - } - } - - // All piece move - for (int piece_idx = 1; piece_idx < 6; piece_idx++) { - Piece piece = piece_get(piece_idx, color); - U64 bitboard = board_pieceSet(board, piece); - bitboard_for_each_bit(src, bitboard) { - U64 attack = board_piece_attacks(board, piece, src) & - ~board_color(board, color); - bitboard_for_each_bit(tgt, attack) { - move_list_add( - moves, move_encode(src, tgt, piece, - board_square_piece(board, tgt, !color), - 0, 0, 0, 0)); - } - } - } - - // Castling - if (color == WHITE) { - Piece piece = piece_get(KING, WHITE); - if (board_castle(board) & WK) { - if (!board_square_isOccupied(board, f1) && - !board_square_isOccupied(board, g1) && - !board_square_isAttack(board, e1, BLACK) && - !board_square_isAttack(board, f1, BLACK)) - move_list_add(moves, move_encode(e1, g1, piece, 0, 0, 0, 0, 1)); - } - if (board_castle(board) & WQ) { - if (!board_square_isOccupied(board, d1) && - !board_square_isOccupied(board, c1) && - !board_square_isOccupied(board, b1) && - !board_square_isAttack(board, e1, BLACK) && - !board_square_isAttack(board, d1, BLACK)) - move_list_add(moves, move_encode(e1, c1, piece, 0, 0, 0, 0, 1)); - } - } else { - Piece piece = piece_get(KING, BLACK); - if (board_castle(board) & BK) { - if (!board_square_isOccupied(board, f8) && - !board_square_isOccupied(board, g8) && - !board_square_isAttack(board, e8, WHITE) && - !board_square_isAttack(board, f8, WHITE)) - move_list_add(moves, move_encode(e8, g8, piece, 0, 0, 0, 0, 1)); - } - if (board_castle(board) & BQ) { - if (!board_square_isOccupied(board, d8) && - !board_square_isOccupied(board, c8) && - !board_square_isOccupied(board, b8) && - !board_square_isAttack(board, e8, WHITE) && - !board_square_isAttack(board, d8, WHITE)) - move_list_add(moves, move_encode(e8, c8, piece, 0, 0, 0, 0, 1)); - } - } - - return moves; -} - -// clang-format off -const int castling_rights[64] = { - 13, 15, 15, 15, 12, 15, 15, 14, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, - 7, 15, 15, 15, 3, 15, 15, 11, -}; -// clang-format on - -void _piece_remove(Board *self, Piece piece, Square square) { - board_piece_pop(self, piece, square); - self->hash ^= zobrist_key_piece(piece, square); -} - -void _piece_set(Board *self, Piece piece, Square square) { - board_piece_set(self, piece, square); - self->hash ^= zobrist_key_piece(piece, square); -} - -void _piece_move(Board *self, Piece piece, Square source, Square target) { - _piece_remove(self, piece, source); - _piece_set(self, piece, target); -} - -int move_make(Move move, Board *board, int flag) { - if (flag) { - if (move_capture(move)) return move_make(move, board, 0); - return 0; - } else { - Piece piece = move_piece(move); - eColor color = board_side(board); - Square source = move_source(move); - Square target = move_target(move); - Square ntarget = target + (color == WHITE ? -8 : +8); - - if (!move_capture(move)) { - if (move_promote(move)) { - _piece_remove(board, piece, source); - _piece_set(board, move_piece_promote(move), target); - } else { - _piece_move(board, piece, source, target); - } - } else { - if (move_enpassant(move)) { - _piece_move(board, piece, source, target); - _piece_remove(board, move_piece_capture(move), ntarget); - } else if (move_promote(move)) { - _piece_remove(board, piece, source); - _piece_remove(board, move_piece_capture(move), target); - _piece_set(board, move_piece_promote(move), target); - } else { - _piece_remove(board, piece, source); - _piece_remove(board, move_piece_capture(move), target); - _piece_set(board, piece, target); - } - } - - board_enpassant_set(board, move_double(move) ? ntarget : no_sq); - - if (move_castle(move)) { - Piece Rook = piece_get(ROOK, board_side(board)); - switch (target) { - case g1: - _piece_move(board, Rook, h1, f1); - break; - case c1: - _piece_move(board, Rook, a1, d1); - break; - case g8: - _piece_move(board, Rook, h8, f8); - break; - case c8: - _piece_move(board, Rook, a8, d8); - break; - default: - break; - } - } - - board->hash ^= zobrist_key_castle(board_castle(board)); - board_castle_and(board, castling_rights[source]); - board_castle_and(board, castling_rights[target]); - board->hash ^= zobrist_key_castle(board_castle(board)); - - if (!board_isCheck(board)) { - board_side_switch(board); - return 1; - } - return 0; - } -} diff --git a/src/moves/moves_generate.c b/src/moves/moves_generate.c @@ -0,0 +1,131 @@ +#include "board.h" +#include "moves.h" + +#define pawn_canPromote(color, source) \ + ((color == WHITE && source >= a7 && source <= h7) || \ + (color == BLACK && source >= a2 && source <= h2)) + +#define pawn_onStart(color, source) \ + ((color == BLACK && source >= a7 && source <= h7) || \ + (color == WHITE && source >= a2 && source <= h2)) + +#define pawn_promote(source, target, Piece, Capture) \ + for (int i = 1; i < 5; i++) { \ + move = move_encode(source, target, Piece, Capture, \ + piece_get(i, color), 0, 0, 0); \ + move_list_add(moves, move); \ + } + +MoveList *move_list_generate(MoveList *moves, const Board *board) { + Move move; + Square src, tgt; + eColor color = board_side(board); + + if (!moves) + moves = move_list_new(); + else + move_list_reset(moves); + + // pawn moves + Piece piece = piece_get(PAWN, color); + U64 bitboard = board_pieceSet(board, piece); + bitboard_for_each_bit(src, bitboard) { + { // quiet + int add = (color == WHITE) ? +8 : -8; + tgt = src + add; + if (!board_square_isOccupied(board, tgt)) { + if (pawn_canPromote(color, src)) { + pawn_promote(src, tgt, piece, 0); + } else { + move_list_add(moves, + move_encode(src, tgt, piece, 0, 0, 0, 0, 0)); + + // two ahead + if (pawn_onStart(color, src) && + !board_square_isOccupied(board, tgt += add)) + move_list_add( + moves, move_encode(src, tgt, piece, 0, 0, 1, 0, 0)); + } + } + } + { // capture + U64 attack = board_piece_attacks(board, piece, src) & + board_color(board, !color); + bitboard_for_each_bit(tgt, attack) { + if (pawn_canPromote(color, src)) { + pawn_promote(src, tgt, piece, + board_square_piece(board, tgt, !color)); + } else { + move_list_add(moves, move_encode(src, tgt, piece, + board_square_piece( + board, tgt, !color), + 0, 0, 0, 0)); + } + } + } + + { // en passant + if (board_enpassant(board) != no_sq && + board_piece_attacks(board, piece, src) & + (C64(1) << board_enpassant(board))) + move_list_add(moves, + move_encode(src, board_enpassant(board), piece, + piece_get(PAWN, !color), 0, 0, 1, 0)); + } + } + + // All piece move + for (int piece_idx = 1; piece_idx < 6; piece_idx++) { + Piece piece = piece_get(piece_idx, color); + U64 bitboard = board_pieceSet(board, piece); + bitboard_for_each_bit(src, bitboard) { + U64 attack = board_piece_attacks(board, piece, src) & + ~board_color(board, color); + bitboard_for_each_bit(tgt, attack) { + move_list_add( + moves, move_encode(src, tgt, piece, + board_square_piece(board, tgt, !color), + 0, 0, 0, 0)); + } + } + } + + // Castling + if (color == WHITE) { + Piece piece = piece_get(KING, WHITE); + if (board_castle(board) & WK) { + if (!board_square_isOccupied(board, f1) && + !board_square_isOccupied(board, g1) && + !board_square_isAttack(board, e1, BLACK) && + !board_square_isAttack(board, f1, BLACK)) + move_list_add(moves, move_encode(e1, g1, piece, 0, 0, 0, 0, 1)); + } + if (board_castle(board) & WQ) { + if (!board_square_isOccupied(board, d1) && + !board_square_isOccupied(board, c1) && + !board_square_isOccupied(board, b1) && + !board_square_isAttack(board, e1, BLACK) && + !board_square_isAttack(board, d1, BLACK)) + move_list_add(moves, move_encode(e1, c1, piece, 0, 0, 0, 0, 1)); + } + } else { + Piece piece = piece_get(KING, BLACK); + if (board_castle(board) & BK) { + if (!board_square_isOccupied(board, f8) && + !board_square_isOccupied(board, g8) && + !board_square_isAttack(board, e8, WHITE) && + !board_square_isAttack(board, f8, WHITE)) + move_list_add(moves, move_encode(e8, g8, piece, 0, 0, 0, 0, 1)); + } + if (board_castle(board) & BQ) { + if (!board_square_isOccupied(board, d8) && + !board_square_isOccupied(board, c8) && + !board_square_isOccupied(board, b8) && + !board_square_isAttack(board, e8, WHITE) && + !board_square_isAttack(board, d8, WHITE)) + move_list_add(moves, move_encode(e8, c8, piece, 0, 0, 0, 0, 1)); + } + } + + return moves; +} diff --git a/src/moves/moves_make.c b/src/moves/moves_make.c @@ -0,0 +1,99 @@ +#include "board.h" +#include "moves.h" +#include "zobrist.h" + +// clang-format off +const int castling_rights[64] = { + 13, 15, 15, 15, 12, 15, 15, 14, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, + 7, 15, 15, 15, 3, 15, 15, 11, +}; +// clang-format on + +void _piece_remove(Board *self, Piece piece, Square square) { + board_piece_pop(self, piece, square); + self->hash ^= zobrist_key_piece(piece, square); +} + +void _piece_set(Board *self, Piece piece, Square square) { + board_piece_set(self, piece, square); + self->hash ^= zobrist_key_piece(piece, square); +} + +void _piece_move(Board *self, Piece piece, Square source, Square target) { + _piece_remove(self, piece, source); + _piece_set(self, piece, target); +} + +int move_make(Move move, Board *board, int flag) { + if (flag) { + if (move_capture(move)) return move_make(move, board, 0); + return 0; + } else { + Piece piece = move_piece(move); + eColor color = board_side(board); + Square source = move_source(move); + Square target = move_target(move); + Square ntarget = target + (color == WHITE ? -8 : +8); + + if (!move_capture(move)) { + if (move_promote(move)) { + _piece_remove(board, piece, source); + _piece_set(board, move_piece_promote(move), target); + } else { + _piece_move(board, piece, source, target); + } + } else { + if (move_enpassant(move)) { + _piece_move(board, piece, source, target); + _piece_remove(board, move_piece_capture(move), ntarget); + } else if (move_promote(move)) { + _piece_remove(board, piece, source); + _piece_remove(board, move_piece_capture(move), target); + _piece_set(board, move_piece_promote(move), target); + } else { + _piece_remove(board, piece, source); + _piece_remove(board, move_piece_capture(move), target); + _piece_set(board, piece, target); + } + } + + board_enpassant_set(board, move_double(move) ? ntarget : no_sq); + + if (move_castle(move)) { + Piece Rook = piece_get(ROOK, board_side(board)); + switch (target) { + case g1: + _piece_move(board, Rook, h1, f1); + break; + case c1: + _piece_move(board, Rook, a1, d1); + break; + case g8: + _piece_move(board, Rook, h8, f8); + break; + case c8: + _piece_move(board, Rook, a8, d8); + break; + default: + break; + } + } + + board->hash ^= zobrist_key_castle(board_castle(board)); + board_castle_and(board, castling_rights[source]); + board_castle_and(board, castling_rights[target]); + board->hash ^= zobrist_key_castle(board_castle(board)); + + if (!board_isCheck(board)) { + board_side_switch(board); + return 1; + } + return 0; + } +}