From db958dcac199ceab152dab840424d81bacd290a8 Mon Sep 17 00:00:00 2001 From: MrGeorgen Date: Sun, 22 Sep 2024 11:45:30 +0200 Subject: [PATCH] zobrist hashing --- .gitignore | 3 +- CMakeLists.txt | 21 ++-- include/chess/bitboard.h | 5 - include/chess/bitset.h | 6 + include/chess/move.h | 3 +- include/chess/print.h | 17 +-- include/chess/rand.h | 3 - include/chess/types.h | 1 + include/chess/util.h | 7 ++ include/chess/zobristConsts.h | 16 +++ src/chess/main.c | 1 + src/chess/move.c | 120 ++++++++++++------- src/common/{ => postCodeGen}/bitboard.c | 146 ++++++++++++------------ src/common/{ => postCodeGen}/magic.c | 2 +- src/common/preCodeGen/bitset.c | 14 +++ src/common/{ => preCodeGen}/print.c | 3 +- src/common/preCodeGen/util.c | 22 ++++ src/common/rand.c | 10 -- src/findMagicNumber.c | 3 +- src/generateCode/moveConsts.c | 3 +- src/generateCode/zobrist.c | 43 ++++--- 21 files changed, 273 insertions(+), 176 deletions(-) create mode 100644 include/chess/bitset.h delete mode 100644 include/chess/rand.h create mode 100644 include/chess/util.h create mode 100644 include/chess/zobristConsts.h rename src/common/{ => postCodeGen}/bitboard.c (56%) rename src/common/{ => postCodeGen}/magic.c (97%) create mode 100644 src/common/preCodeGen/bitset.c rename src/common/{ => preCodeGen}/print.c (95%) create mode 100644 src/common/preCodeGen/util.c delete mode 100644 src/common/rand.c diff --git a/.gitignore b/.gitignore index 28fd64d..f7f564f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /* !/src -/include/chess/generated/* +/src/generated !/CMakeLists.txt !/README.md !/LICENSE @@ -8,5 +8,6 @@ !/lib !.gitkeep !/include +/include/chess/generated/* !/.gitignore !/test diff --git a/CMakeLists.txt b/CMakeLists.txt index 346a63a..b6d9a12 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,29 +1,36 @@ cmake_minimum_required(VERSION 3.18) project(chess C) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +set(CMAKE_C_STANDARD 99) include_directories(include) file(GLOB SOURCES "src/chess/*.c") -file(GLOB LIB_SOURCES "src/common/*.c") +file(GLOB CODE_GEN_LIB_SOURCES "src/common/preCodeGen/*.c") +file(GLOB LIB_SOURCES "src/common/*/*.c" "src/generated/*.c") -add_executable(genMoveConsts src/generateCode/moveConsts.c src/common/bitboard.c - src/common/print.c) +add_executable(genMoveConsts src/generateCode/moveConsts.c ${CODE_GEN_LIB_SOURCES}) add_custom_command( OUTPUT moveConsts.h # Output file from code generation COMMAND genMoveConsts > include/chess/generated/moveConsts.h DEPENDS genMoveConsts # Depends on the code generation executable ) -add_custom_target(generateCode DEPENDS moveConsts.h) + +add_executable(genZobrist src/generateCode/zobrist.c ${CODE_GEN_LIB_SOURCES}) +add_custom_command( + OUTPUT zobristConsts.c # Output file from code generation + COMMAND genZobrist > src/generated/zobristConsts.c + DEPENDS genZobrist # Depends on the code generation executable + ) + +add_custom_target(generateCode DEPENDS moveConsts.h zobristConsts.c) find_package(PkgConfig REQUIRED) pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4) pkg_check_modules(LIBRSVG REQUIRED IMPORTED_TARGET librsvg-2.0) add_executable(findMagicNumber src/findMagicNumber.c ${LIB_SOURCES}) -set_property(TARGET findMagicNumber PROPERTY C_STANDARD 99) add_dependencies(findMagicNumber generateCode) add_executable(${PROJECT_NAME} ${SOURCES} ${LIB_SOURCES}) -set_property(TARGET ${PROJECT_NAME} PROPERTY C_STANDARD 99) target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG) add_dependencies(${PROJECT_NAME} generateCode) @@ -39,11 +46,9 @@ if(CMAKE_BUILD_TYPE MATCHES "Release") endif() add_executable(chessNoComputer ${SOURCES} ${LIB_SOURCES}) -set_property(TARGET chessNoComputer PROPERTY C_STANDARD 99) target_link_libraries(chessNoComputer PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG) add_dependencies(chessNoComputer generateCode) target_compile_definitions(chessNoComputer PUBLIC NO_COMPUTER) add_executable(moveGenTest test/moveGen.c src/chess/move.c ${LIB_SOURCES}) -set_property(TARGET moveGenTest PROPERTY C_STANDARD 99) add_test(NAME moveGen COMMAND moveGenTest) diff --git a/include/chess/bitboard.h b/include/chess/bitboard.h index b1e5507..f8fce21 100644 --- a/include/chess/bitboard.h +++ b/include/chess/bitboard.h @@ -2,9 +2,6 @@ #include #include -bool bitsetGet(uint_least64_t bitset, uint_least8_t i); -uint_least64_t bitsetClear(uint_least64_t bitset, uint_least8_t i); -uint_least64_t bitsetSet(uint_least64_t bitset, uint_least8_t i); bool bitboardGet(const uint_least64_t *board, struct piece_t piece, uint_least8_t i); uint_least64_t bitboardGetMask(const uint_least64_t *board, struct piece_t piece); void bitboardSetMask(uint_least64_t *board, struct piece_t piece, uint_least64_t value); @@ -14,5 +11,3 @@ void bitboardClear(uint_least64_t *board, struct piece_t piece, uint_least8_t i) void bitboardSet(uint_least64_t *board, struct piece_t piece, uint_least8_t i); struct piece_t pieceAtField(const uint_least64_t *board, uint_least8_t i); struct gameState_t newGameState(uint_least64_t *board, char *FEN); -uint_least8_t getFile(const uint_least8_t field); -uint_least8_t getRank(const uint_least8_t field); diff --git a/include/chess/bitset.h b/include/chess/bitset.h new file mode 100644 index 0000000..130236d --- /dev/null +++ b/include/chess/bitset.h @@ -0,0 +1,6 @@ +#include +#include + +bool bitsetGet(uint_least64_t bitset, uint_least8_t i); +uint_least64_t bitsetClear(uint_least64_t bitset, uint_least8_t i); +uint_least64_t bitsetSet(uint_least64_t bitset, uint_least8_t i); diff --git a/include/chess/move.h b/include/chess/move.h index 6000d07..8cd836f 100644 --- a/include/chess/move.h +++ b/include/chess/move.h @@ -17,6 +17,7 @@ enum spezialMoves { struct move_t { uint_least8_t src, dst, spezialMove; uint_least8_t srcPiece, dstPiece, capturedPiece; + uint_least64_t hash; }; void genDirectionConsts(); @@ -25,7 +26,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece struct move_t *moves, bool promotion); void undoMove(uint_least64_t *board, struct move_t move, bool color); -struct gameState_t makeMove(struct gameState_t gameState, struct move_t move); +struct gameState_t makeMove(struct gameState_t gameState, const struct move_t move); void initMagicTable(); bool kingInCheck(const uint_least64_t *board, const bool color); uint_least8_t getBaseRankI(bool color); diff --git a/include/chess/print.h b/include/chess/print.h index 4063fa6..2abd632 100644 --- a/include/chess/print.h +++ b/include/chess/print.h @@ -2,26 +2,29 @@ #include #include -#define fprintArray(file, printer, arr) \ +#define fprintArrayCustomLength(file, printer, arr, length) \ do { \ fprintf(file, "{"); \ - for(size_t i = 0; i < LENGTH(arr); ++i) { \ + for(size_t i = 0; i < length; ++i) { \ printer(file, arr[i]); \ - if (i < LENGTH(arr) - 1) { \ + if (i < length - 1) { \ fprintf(file, ", "); \ } \ } \ fprintf(file, " }"); \ } while(0) +#define fprintArray(file, printer, arr) fprintArrayCustomLength(file, printer, arr, LENGTH(arr)) -#define fdefineArray(file, declaration, printer, arr) \ +#define fdefineArrayCustomLength(file, declaration, printer, arr, length) \ do { \ - fprintf(file, "%s[%zu] = ", declaration, LENGTH(arr)); \ - fprintArray(file, printer, arr); \ + fprintf(file, "%s[%zu] = ", declaration, length); \ + fprintArrayCustomLength(file, printer, arr, length); \ fprintf(file, ";\n"); \ } while(0) +#define fdefineArray(file, declaration, printer, arr) fdefineArrayCustomLength(file, declaration, printer, arr, LENGTH(arr)) -#define defineArray(declaration, printer, arr) fdefineArray(stdout, declaration, printer, arr) +#define defineArrayCustomLength(declaration, printer, arr, length) fdefineArrayCustomLength(stdout, declaration, printer, arr, length) +#define defineArray(declaration, printer, arr) defineArrayCustomLength(declaration, printer, arr, LENGTH(arr)) void printerll(FILE *file, long long num); void printerull(FILE *file, unsigned long long num); diff --git a/include/chess/rand.h b/include/chess/rand.h deleted file mode 100644 index c786646..0000000 --- a/include/chess/rand.h +++ /dev/null @@ -1,3 +0,0 @@ -#include - -uint_least64_t rand_64(); diff --git a/include/chess/types.h b/include/chess/types.h index 53d658e..5a39093 100644 --- a/include/chess/types.h +++ b/include/chess/types.h @@ -53,6 +53,7 @@ struct castle_t { struct gameState_t { uint_least64_t *board; + uint_least64_t zobrist; bool color; // color to move struct castle_t canCastle[2]; diff --git a/include/chess/util.h b/include/chess/util.h new file mode 100644 index 0000000..28dc2cd --- /dev/null +++ b/include/chess/util.h @@ -0,0 +1,7 @@ +#include +#include + +uint_least64_t rand_64(); +uint_least64_t zobristPieceI(struct piece_t piece, uint_least8_t field); +uint_least8_t getFile(const uint_least8_t field); +uint_least8_t getRank(const uint_least8_t field); diff --git a/include/chess/zobristConsts.h b/include/chess/zobristConsts.h new file mode 100644 index 0000000..4cc6f7e --- /dev/null +++ b/include/chess/zobristConsts.h @@ -0,0 +1,16 @@ +#ifndef CHESS_ZOBRIST_CONSTS_H +#define CHESS_ZOBRIST_CONSTS_H + +#include "chess/types.h" +#include + +#define ZOBRIST_CASTLE_LENGTH 2 +#define ZOBRIST_PIECE_LENGTH (TOTAL_BOARD_SIZE * 2 * PIECES_LENGTH) + +extern const uint_least64_t ZOBRIST_PIECE[]; +extern const uint_least64_t ZOBRIST_BLACK_MOVE; +extern const uint_least64_t ZOBRIST_SHORT_CASTLE[ZOBRIST_CASTLE_LENGTH]; +extern const uint_least64_t ZOBRIST_LONG_CASTLE[ZOBRIST_CASTLE_LENGTH]; +extern const uint_least64_t ZOBRIST_EN_PASSENT_FILE[BOARD_SIZE]; + +#endif diff --git a/src/chess/main.c b/src/chess/main.c index 819596e..f375728 100644 --- a/src/chess/main.c +++ b/src/chess/main.c @@ -10,6 +10,7 @@ #include #include #include "evaluate.h" +#include #define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" diff --git a/src/chess/move.c b/src/chess/move.c index b76a3c7..60f1e70 100644 --- a/src/chess/move.c +++ b/src/chess/move.c @@ -9,6 +9,10 @@ #include #include "magicNumber.h" #include +#include +#include +#include +#include #ifdef _MSC_VER #include @@ -29,7 +33,7 @@ static uint_least8_t trailingBits(uint_least64_t num) { unsigned long i; _BitScanForward(&i, num); return i; -#elif +#else uint_least8_t count = 0; while ((num & 1) == 0) { // Keep shifting num right until the least significant bit is 1 num >>= 1; @@ -166,31 +170,87 @@ void undoMove(uint_least64_t *board, struct move_t move, bool color) { castleMoveRook(board, move.spezialMove, color, true); } +static void setCastleInfoRook(struct castle_t *canCastle, uint_least8_t posOnRank) { + switch(posOnRank) { + case 0: + canCastle->longCastle = false; + break; + case BOARD_SIZE - 1: + canCastle->shortCastle = false; + break; + } +} + +static void setCastleInfo(struct castle_t *canCastle, const bool color, const struct move_t move) { + { + struct castle_t *canCastleCurrentPlayer = canCastle + color; + if(canCastleCurrentPlayer->longCastle || canCastleCurrentPlayer->shortCastle) { + if(move.dstPiece == KING) { + canCastleCurrentPlayer->longCastle = false; + canCastleCurrentPlayer->shortCastle = false; + } + else { + setCastleInfoRook(canCastleCurrentPlayer, move.src - getBaseRankI(color)); + } + } + } + { + // if the rook is captured + struct castle_t *canCastleOther = canCastle + !color; + if(canCastleOther->longCastle || canCastleOther->shortCastle) { + setCastleInfoRook(canCastleOther, move.dst - getBaseRankI(!color)); + } + } +} + static void addMove(struct addMoveCtx_t ctx, struct piece_t movedPiece, uint_least8_t src, uint_least8_t dst, uint_least8_t spezialMove, uint_least8_t promotionPiece) { - uint_least64_t *board = ctx.gameState.board; - uint_least8_t *movesLength = ctx.movesLength; - uint_least8_t capturedPiece = NOT_SELECTED; - const uint_least8_t dstPiece = promotionPiece == NOT_SELECTED ? movedPiece.type : promotionPiece; - const struct piece_t pieceAll = {ALL_PIECES, movedPiece.color}; - if(bitboardGet(board, pieceAll, dst)) return; + struct gameState_t gameState = ctx.gameState; + uint_least64_t *board = gameState.board; { - const struct piece_t pieceAllOtherColor = {ALL_PIECES, !movedPiece.color}; + const struct piece_t pieceAll = {ALL_PIECES, movedPiece.color}; + if(bitboardGet(board, pieceAll, dst)) return; + } + uint_least8_t *movesLength = ctx.movesLength; + uint_least8_t capturedPieceType = NOT_SELECTED; + const uint_least8_t dstPieceType = promotionPiece == NOT_SELECTED ? movedPiece.type : promotionPiece; + uint_least64_t hash = ZOBRIST_PIECE[zobristPieceI(movedPiece, src)] ^ ZOBRIST_BLACK_MOVE; + { + const struct piece_t dstPiece = {dstPieceType, movedPiece.color}; + hash ^= ZOBRIST_PIECE[zobristPieceI(dstPiece, dst)]; + } + { + const bool otherColor = !movedPiece.color; + const struct piece_t pieceAllOtherColor = {ALL_PIECES, otherColor}; const uint_least8_t capturePos = getCapturePos(src, dst, spezialMove); if(bitboardGet(board, pieceAllOtherColor, capturePos)) { for(uint_least8_t pieceType = QUEEN; pieceType < PIECES_LENGTH; ++pieceType) { const struct piece_t piece = {pieceType, !movedPiece.color}; if(bitboardGet(board, piece, capturePos)) { - capturedPiece = pieceType; + const struct piece_t capturedPiece = {pieceType, otherColor}; + hash ^= ZOBRIST_PIECE[zobristPieceI(capturedPiece, dst)]; + capturedPieceType = pieceType; break; } } } } - const struct move_t move = {src, dst, spezialMove, movedPiece.type, dstPiece, capturedPiece}; - makeMove(ctx.gameState, move); + if(gameState.enPassantTo != NOT_SELECTED) hash ^= ZOBRIST_EN_PASSENT_FILE[getFile(gameState.enPassantTo)]; + if(spezialMove == FUTURE_EN_PASSANT) hash ^= ZOBRIST_EN_PASSENT_FILE[getFile(src)]; + struct move_t move = {src, dst, spezialMove, movedPiece.type, dstPieceType, capturedPieceType, hash}; { - const bool color = ctx.gameState.color; + struct castle_t canCastle[2]; + memcpy(canCastle, gameState.canCastle, sizeof canCastle); + setCastleInfo(canCastle, gameState.color, move); + for(uint_least8_t color = BLACK; color <= WHITE; ++color) { + if(canCastle[color].shortCastle != gameState.canCastle[color].shortCastle) hash ^= ZOBRIST_SHORT_CASTLE[color]; + if(canCastle[color].longCastle != gameState.canCastle[color].longCastle) hash ^= ZOBRIST_LONG_CASTLE[color]; + } + move.hash = hash; + } + makeMove(gameState, move); + { + const bool color = gameState.color; if(!kingInCheck(board, color)) { ctx.moves[*movesLength] = move; ++*movesLength; @@ -303,7 +363,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece uint_least8_t dst = src + DIRECTION_MODIFIER[pawnDirection]; if(!bitboardGetAllPieces(board, dst)) { movePawn(addmoveCtx, piece.color, src, dst, promotion, 0); - if(getFile(src) == (piece.color == WHITE ? BOARD_SIZE - 2 : 1)) { + if(getRank(src) == (piece.color == WHITE ? BOARD_SIZE - 2 : 1)) { dst += DIRECTION_MODIFIER[pawnDirection]; if(!bitboardGetAllPieces(board, dst)) { movePawn(addmoveCtx, piece.color, src, dst, promotion, FUTURE_EN_PASSANT); @@ -337,18 +397,7 @@ uint_least8_t validMoves(struct gameState_t gameState, struct move_t *moves) { return movesLength; } -static void setCastleInfo(struct castle_t *canCastle, uint_least8_t posOnRank) { - switch(posOnRank) { - case 0: - canCastle->longCastle = false; - break; - case BOARD_SIZE - 1: - canCastle->shortCastle = false; - break; - } -} - -struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) { +struct gameState_t makeMove(struct gameState_t gameState, const struct move_t move) { uint_least64_t *board = gameState.board; const struct piece_t srcPiece = {move.srcPiece, gameState.color}; const struct piece_t dstPiece = {move.dstPiece, gameState.color}; @@ -359,25 +408,7 @@ struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) { bitboardClear(board, capturedPiece, getCapturePos(move.src, move.dst, move.spezialMove)); } castleMoveRook(board, move.spezialMove, gameState.color, false); - { - struct castle_t *canCastleCurrentPlayer = gameState.canCastle + gameState.color; - if(canCastleCurrentPlayer->longCastle || canCastleCurrentPlayer->shortCastle) { - if(move.dstPiece == KING) { - canCastleCurrentPlayer->longCastle = false; - canCastleCurrentPlayer->shortCastle = false; - } - else { - setCastleInfo(canCastleCurrentPlayer, move.src - getBaseRankI(gameState.color)); - } - } - } - { - // if the rook is captured - struct castle_t *canCastleOther = gameState.canCastle + !gameState.color; - if(canCastleOther->longCastle || canCastleOther->shortCastle) { - setCastleInfo(canCastleOther, move.dst - getBaseRankI(!gameState.color)); - } - } + setCastleInfo(gameState.canCastle, gameState.color, move); { const int_least8_t dist = (int_least8_t)move.dst - (int_least8_t)move.src; gameState.enPassantTo = move.spezialMove == FUTURE_EN_PASSANT ? move.src + dist / 2 : NOT_SELECTED; @@ -385,5 +416,6 @@ struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) { if(move.capturedPiece != NOT_SELECTED || srcPiece.type == PAWN) gameState.halfMoveCounter = 0; else ++gameState.halfMoveCounter; gameState.color = !gameState.color; + gameState.zobrist ^= move.hash; return gameState; } diff --git a/src/common/bitboard.c b/src/common/postCodeGen/bitboard.c similarity index 56% rename from src/common/bitboard.c rename to src/common/postCodeGen/bitboard.c index 5cfb02e..1be1599 100644 --- a/src/common/bitboard.c +++ b/src/common/postCodeGen/bitboard.c @@ -1,20 +1,11 @@ +#include "chess/zobristConsts.h" #include #include #include #include #include - -bool bitsetGet(uint_least64_t bitset, uint_least8_t i) { - return (bitset >> i) & 1u; -} - -uint_least64_t bitsetClear(uint_least64_t bitset, uint_least8_t i) { - return bitset & ~((uint_least64_t)1 << i); -} - -uint_least64_t bitsetSet(uint_least64_t bitset, uint_least8_t i) { - return bitset | ((uint_least64_t)1 << i); -} +#include +#include uint_least64_t bitboardGetMask(const uint_least64_t *board, struct piece_t piece) { return board[piece.color * PIECES_LENGTH + piece.type]; @@ -76,69 +67,72 @@ struct piece_t pieceAtField(const uint_least64_t *board, uint_least8_t i) { } struct gameState_t newGameState(uint_least64_t *board, char *FEN) { - struct gameState_t gameState = {board}; - for(uint_least8_t i = 0; i < BITBOARD_LENGTH; ++i) { - board[i] = 0; - } - for(uint_least8_t field = 0; *FEN != ' '; ++FEN) { - struct piece_t piece; - switch(tolower(*FEN)) { - case 'k': - piece.type = KING; - break; - case 'q': - piece.type = QUEEN; - break; - case 'r': - piece.type = ROOK; - break; - case 'n': - piece.type = KNIGHT; - break; - case 'b': - piece.type = BISHOP; - break; - case 'p': - piece.type = PAWN; - break; - case '/': - continue; - default: - if(isdigit(*FEN)) { - field += *FEN - '0'; - } - continue; - } - if(isalpha(*FEN)) piece.color = isupper(*FEN); - bitboardSet(board, piece, field); - ++field; - } - gameState.color = *++FEN == 'w' ? WHITE : BLACK; - FEN += 2; - if(*FEN == '-') ++FEN; - else { - for(; *FEN != ' '; ++FEN) { - struct castle_t *playerCastle = gameState.canCastle + (isupper(*FEN) ? WHITE : BLACK); - if(tolower(*FEN) == 'k') playerCastle->shortCastle = true; - else playerCastle->longCastle = true; - } - } - if(*++FEN == '-'){ - ++FEN; - gameState.enPassantTo = NOT_SELECTED; - } - else { - gameState.enPassantTo = *FEN++ - 'a'; - gameState.enPassantTo += (BOARD_SIZE - *FEN++) * BOARD_SIZE; - } - gameState.halfMoveCounter = atoi(++FEN); - return gameState; + struct gameState_t gameState = {board, 0}; + for(uint_least8_t i = 0; i < BITBOARD_LENGTH; ++i) { + board[i] = 0; } - -uint_least8_t getFile(const uint_least8_t field) { - return field % BOARD_SIZE; -} - -uint_least8_t getRank(const uint_least8_t field) { - return field / BOARD_SIZE; + for(uint_least8_t field = 0; *FEN != ' '; ++FEN) { + struct piece_t piece; + switch(tolower(*FEN)) { + case 'k': + piece.type = KING; + break; + case 'q': + piece.type = QUEEN; + break; + case 'r': + piece.type = ROOK; + break; + case 'n': + piece.type = KNIGHT; + break; + case 'b': + piece.type = BISHOP; + break; + case 'p': + piece.type = PAWN; + break; + case '/': + continue; + default: + if(isdigit(*FEN)) { + field += *FEN - '0'; + } + continue; + } + if(isalpha(*FEN)) piece.color = isupper(*FEN); + bitboardSet(board, piece, field); + gameState.zobrist ^= ZOBRIST_PIECE[zobristPieceI(piece, field)]; + ++field; + } + gameState.color = *++FEN == 'w' ? WHITE : BLACK; + if(gameState.color == BLACK) gameState.zobrist ^= ZOBRIST_BLACK_MOVE; + FEN += 2; + if(*FEN == '-') ++FEN; + else { + for(; *FEN != ' '; ++FEN) { + const bool color = isupper(*FEN) ? WHITE : BLACK; + struct castle_t *playerCastle = gameState.canCastle + color; + if(tolower(*FEN) == 'k') { + playerCastle->shortCastle = true; + gameState.zobrist ^= ZOBRIST_SHORT_CASTLE[color]; + } + else { + playerCastle->longCastle = true; + gameState.zobrist ^= ZOBRIST_LONG_CASTLE[color]; + } + } + } + if(*++FEN == '-'){ + ++FEN; + gameState.enPassantTo = NOT_SELECTED; + } + else { + const uint_least8_t enPassentFile = *FEN++ - 'a'; + gameState.zobrist ^= ZOBRIST_EN_PASSENT_FILE[enPassentFile]; + gameState.enPassantTo = enPassentFile; + gameState.enPassantTo += (BOARD_SIZE - *FEN++) * BOARD_SIZE; + } + gameState.halfMoveCounter = atoi(++FEN); + return gameState; } diff --git a/src/common/magic.c b/src/common/postCodeGen/magic.c similarity index 97% rename from src/common/magic.c rename to src/common/postCodeGen/magic.c index ab046fb..2f88bcf 100644 --- a/src/common/magic.c +++ b/src/common/postCodeGen/magic.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength, uint_least8_t field, uint_least64_t blockMask) { diff --git a/src/common/preCodeGen/bitset.c b/src/common/preCodeGen/bitset.c new file mode 100644 index 0000000..5e5a6e8 --- /dev/null +++ b/src/common/preCodeGen/bitset.c @@ -0,0 +1,14 @@ +#include + +bool bitsetGet(uint_least64_t bitset, uint_least8_t i) { + return (bitset >> i) & 1u; +} + +uint_least64_t bitsetClear(uint_least64_t bitset, uint_least8_t i) { + return bitset & ~((uint_least64_t)1 << i); +} + +uint_least64_t bitsetSet(uint_least64_t bitset, uint_least8_t i) { + return bitset | ((uint_least64_t)1 << i); +} + diff --git a/src/common/print.c b/src/common/preCodeGen/print.c similarity index 95% rename from src/common/print.c rename to src/common/preCodeGen/print.c index 943bcab..4c50a6e 100644 --- a/src/common/print.c +++ b/src/common/preCodeGen/print.c @@ -2,7 +2,8 @@ #include "chess/types.h" #include #include -#include +#include +#include void printerll(FILE *file, long long num) { fprintf(file, "%lld", num); diff --git a/src/common/preCodeGen/util.c b/src/common/preCodeGen/util.c new file mode 100644 index 0000000..111ac50 --- /dev/null +++ b/src/common/preCodeGen/util.c @@ -0,0 +1,22 @@ +#include +#include +#include + +uint_least64_t rand_64() { + uint_least64_t u1, u2, u3, u4; + u1 = (uint_least64_t)(rand()) & 0xFFFF; u2 = (uint_least64_t)(rand()) & 0xFFFF; + u3 = (uint_least64_t)(rand()) & 0xFFFF; u4 = (uint_least64_t)(rand()) & 0xFFFF; + return u1 | (u2 << 16) | (u3 << 32) | (u4 << 48); +} + +uint_least64_t zobristPieceI(struct piece_t piece, uint_least8_t field) { + return field * 2 * PIECES_LENGTH + piece.color * PIECES_LENGTH + piece.type; +} + +uint_least8_t getFile(const uint_least8_t field) { + return field % BOARD_SIZE; +} + +uint_least8_t getRank(const uint_least8_t field) { + return field / BOARD_SIZE; +} diff --git a/src/common/rand.c b/src/common/rand.c deleted file mode 100644 index 6f30c43..0000000 --- a/src/common/rand.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include -#include - -uint_least64_t rand_64() { - uint_least64_t u1, u2, u3, u4; - u1 = (uint_least64_t)(rand()) & 0xFFFF; u2 = (uint_least64_t)(rand()) & 0xFFFF; - u3 = (uint_least64_t)(rand()) & 0xFFFF; u4 = (uint_least64_t)(rand()) & 0xFFFF; - return u1 | (u2 << 16) | (u3 << 32) | (u4 << 48); -} diff --git a/src/findMagicNumber.c b/src/findMagicNumber.c index 7cda657..20e9598 100644 --- a/src/findMagicNumber.c +++ b/src/findMagicNumber.c @@ -9,7 +9,8 @@ #include #include #include -#include +#include +#include #define MAX_BITS 12 #define MAX_SIZE (1 << MAX_BITS) diff --git a/src/generateCode/moveConsts.c b/src/generateCode/moveConsts.c index 163e0d3..08df2e3 100644 --- a/src/generateCode/moveConsts.c +++ b/src/generateCode/moveConsts.c @@ -2,8 +2,9 @@ #include #include #include -#include +#include #include +#include static void printerMoveDst(FILE *file, struct moveDst_t moveDst) { fprintf(file, "{ %" PRIuLEAST8 ", ", moveDst.length); diff --git a/src/generateCode/zobrist.c b/src/generateCode/zobrist.c index a7ac819..c1eb5e2 100644 --- a/src/generateCode/zobrist.c +++ b/src/generateCode/zobrist.c @@ -1,30 +1,39 @@ #include "chess/types.h" +#include "chess/zobristConsts.h" #include #include -#include +#include #include #include #include -static uint_least64_t zobristPieceI(struct piece_t piece, uint_least8_t field) { - return field * 2 * PIECES_LENGTH + piece.color * PIECES_LENGTH + piece.type; -} - int main() { - uint_least64_t zobristPiece[TOTAL_BOARD_SIZE * 2 * PIECES_LENGTH]; srand(0xc0229b8e); - printf("#ifndef CHESS_GENERATED_ZOBRIST_H\n" - "#define CHESS_GENERATED_ZOBRIST_H\n" - "#include \n" - ); - for(uint_least8_t color = BLACK; color <= WHITE; ++color) { - for(uint_least8_t pieceType = KING; pieceType < PIECES_LENGTH; ++pieceType) { - const struct piece_t piece = {pieceType, color}; - for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) { - zobristPiece[zobristPieceI(piece, field)] = rand_64(); + printf("#include \n"); + { + uint_least64_t zobristPiece[ZOBRIST_PIECE_LENGTH]; + for(uint_least8_t color = BLACK; color <= WHITE; ++color) { + for(uint_least8_t pieceType = KING; pieceType < PIECES_LENGTH; ++pieceType) { + const struct piece_t piece = {pieceType, color}; + for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) { + zobristPiece[zobristPieceI(piece, field)] = rand_64(); + } } } + defineArray("const uint_least64_t ZOBRIST_PIECE", printerull, zobristPiece); + } + printf("const uint_least64_t ZOBRIST_BLACK_MOVE = %" PRIuLEAST64 "u;\n", rand_64()); + { + uint_least64_t zobristRest[4 + BOARD_SIZE]; // 4 for castling + for(uint_least8_t i = 0; i < LENGTH(zobristRest); ++i) { + zobristRest[i] = rand_64(); + } + uint_least64_t *zobristRestPtr = zobristRest; + const size_t castleLength = 2; + defineArrayCustomLength("const uint_least64_t ZOBRIST_SHORT_CASTLE", printerull, zobristRestPtr, castleLength); + zobristRestPtr += castleLength; + defineArrayCustomLength("const uint_least64_t ZOBRIST_LONG_CASTLE", printerull, zobristRestPtr, castleLength); + zobristRestPtr += castleLength; + defineArrayCustomLength("const uint_least64_t ZOBRIST_EN_PASSENT_FILE", printerull, zobristRestPtr, (size_t)BOARD_SIZE); } - defineArray("#define defineZobristPiece const static uint_least64_t ZOBRIST_PIECE", printerull, zobristPiece); - printf("#define defineZobristBlackMove const uint_least64_t ZOBRIST_BLACK_MOVE = %" PRIuLEAST64 "\n", rand_64()); }