stellar

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

commit 11aa12bf92ffa2c1f685a8ec4f9dfe4135223e7a
parent 4bb56bb0a5e36c56ed28b9b2affbef0a0f0e0c38
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Fri, 28 Jul 2023 19:22:22 +0200

Refactor move encoding to use bit fields

Diffstat:
Msrc/engine.c | 86+++++++++++++++++++++++++++++++++++++++++++------------------------------------
1 file changed, 47 insertions(+), 39 deletions(-)

diff --git a/src/engine.c b/src/engine.c @@ -1,4 +1,5 @@ #include <ctype.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -23,42 +24,49 @@ #define cmk_position \ "r2q1rk1/ppp2ppp/2n1bn2/2b1p3/3pP3/3P1NPP/PPP1NPB1/R1BQ1RK1 b - - 0 9 " -typedef U32 Move; +typedef struct Move Move; +struct Move { + unsigned source : 6; + unsigned target : 6; + unsigned piece : 5; + unsigned piece_capture : 5; + unsigned piece_promote : 5; + unsigned dbl : 1; + unsigned enpassant : 1; + unsigned castle : 1; + unsigned capture : 1; + unsigned promote : 1; +}; + +int Move_cmp(Move a, Move b) { return *(uint32_t *)&a == *(uint32_t *)&b; } Move Move_encode(Square src, Square tgt, Piece_T Piece, Piece_T Capture, Piece_T Promote, int dbl, int enpassant, int castle) { - Move move = C32(0); - move |= - (src) | (tgt << 6) | (dbl << 27) | (enpassant << 28) | (castle << 29); - move |= (Piece_index(Piece) << 12); - if (Capture != NULL) { - move |= (Piece_index(Capture) << 17); - move |= (1 << 30); - } - - if (Promote != NULL) { - move |= (Piece_index(Promote) << 22); - move |= (1 << 31); - } - - return move; + return (Move){ + .source = src, + .target = tgt, + .dbl = dbl, + .enpassant = enpassant, + .castle = castle, + .capture = Capture != NULL, + .promote = Promote != NULL, + .piece = Piece_index(Piece), + .piece_capture = Capture ? Piece_index(Capture) : 0, + .piece_promote = Promote ? Piece_index(Promote) : 0, + }; } -#define Move_source(move) (((move)&C32(0x0000003f))) -#define Move_target(move) (((move)&C32(0x00000fc0)) >> 6) -#define Move_double(move) (((move)&C32(0x08000000)) >> 27) -#define Move_enpassant(move) (((move)&C32(0x10000000)) >> 28) -#define Move_castle(move) (((move)&C32(0x20000000)) >> 29) -#define Move_capture(move) (((move)&C32(0x40000000)) >> 30) -#define Move_promote(move) (((move)&C32(0x80000000)) >> 31) - -#define Move_piece(move) (Piece_fromIndex(((move)&C32(0x0001F000)) >> 12)) -#define Move_piece_capture(move) \ - (assert(Move_capture(move)), \ - Piece_fromIndex(((move)&C32(0x003E0000)) >> 17)) -#define Move_piece_promote(move) \ - (assert(Move_promote(move)), \ - Piece_fromIndex(((move)&C32(0x07C00000)) >> 22)) +#define Move_source(move) (move.source) +#define Move_target(move) (move.target) +#define Move_double(move) (move.dbl) +#define Move_enpassant(move) (move.enpassant) +#define Move_castle(move) (move.castle) +#define Move_capture(move) (move.capture) +#define Move_promote(move) (move.promote) + +#define Move_piece(move) (Piece_fromIndex(move.piece)) +#define Move_piece_capture(move) (Piece_fromIndex(move.piece_capture)) +#define Move_piece_promote(move) (Piece_fromIndex(move.piece_promote)) // clang-format off const int castling_rights[64] = { @@ -196,7 +204,7 @@ struct Stats_T { int pv_length[MAX_PLY]; Move pv_table[MAX_PLY][MAX_PLY]; Move killer_moves[2][MAX_PLY]; - Move history_moves[16][64]; + U32 history_moves[16][64]; }; Stats_T Stats_new(void) { @@ -212,9 +220,9 @@ int Move_score(Stats_T stats, Move move) { return Score_capture(Piece_piece(Move_piece(move)), Piece_piece(Move_piece_capture(move))); } else { - if (stats->killer_moves[0][stats->ply] == move) + if (!Move_cmp(stats->killer_moves[0][stats->ply], move)) return 9000; - else if (stats->killer_moves[1][stats->ply] == move) + else if (!Move_cmp(stats->killer_moves[1][stats->ply], move)) return 8000; else return stats->history_moves[Piece_index(Move_piece(move))] @@ -716,7 +724,7 @@ char *Instruction_token_next(Instruction_T self) { } Move parse_move(CBoard_T board, char *move_string) { - Move result = 0; + Move result = {0}; MoveList_T moves; Square source, target; @@ -771,7 +779,7 @@ CBoard_T Instruction_parse(Instruction_T self, CBoard_T board) { if (strcmp(token, "moves") == 0) { while ((token = Instruction_token_next(self))) { Move move = parse_move(board, token); - if (move) { + if (!Move_cmp(move, (Move){0})) { Move_make(move, board, 0); } else { printf("Invalid move %s!\n", token); @@ -969,10 +977,10 @@ int main(void) { init_all(); CBoard_T board = NULL; - board = CBoard_fromFEN(board, start_position); + board = CBoard_fromFEN(board, tricky_position); CBoard_print(board); - // perft_test(board, 7); - perft_test_threaded(board, 7); + // perft_test(board, 6); + perft_test_threaded(board, 5); CBoard_free(&board); return 0; }