zobrist hashing

This commit is contained in:
2024-09-22 11:45:30 +02:00
parent 4d2a86c7b7
commit db958dcac1
21 changed files with 273 additions and 176 deletions

3
.gitignore vendored
View File

@ -1,6 +1,6 @@
/* /*
!/src !/src
/include/chess/generated/* /src/generated
!/CMakeLists.txt !/CMakeLists.txt
!/README.md !/README.md
!/LICENSE !/LICENSE
@ -8,5 +8,6 @@
!/lib !/lib
!.gitkeep !.gitkeep
!/include !/include
/include/chess/generated/*
!/.gitignore !/.gitignore
!/test !/test

View File

@ -1,29 +1,36 @@
cmake_minimum_required(VERSION 3.18) cmake_minimum_required(VERSION 3.18)
project(chess C) project(chess C)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_STANDARD 99)
include_directories(include) include_directories(include)
file(GLOB SOURCES "src/chess/*.c") 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 add_executable(genMoveConsts src/generateCode/moveConsts.c ${CODE_GEN_LIB_SOURCES})
src/common/print.c)
add_custom_command( add_custom_command(
OUTPUT moveConsts.h # Output file from code generation OUTPUT moveConsts.h # Output file from code generation
COMMAND genMoveConsts > include/chess/generated/moveConsts.h COMMAND genMoveConsts > include/chess/generated/moveConsts.h
DEPENDS genMoveConsts # Depends on the code generation executable 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) find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4) pkg_check_modules(GTK4 REQUIRED IMPORTED_TARGET gtk4)
pkg_check_modules(LIBRSVG REQUIRED IMPORTED_TARGET librsvg-2.0) pkg_check_modules(LIBRSVG REQUIRED IMPORTED_TARGET librsvg-2.0)
add_executable(findMagicNumber src/findMagicNumber.c ${LIB_SOURCES}) add_executable(findMagicNumber src/findMagicNumber.c ${LIB_SOURCES})
set_property(TARGET findMagicNumber PROPERTY C_STANDARD 99)
add_dependencies(findMagicNumber generateCode) add_dependencies(findMagicNumber generateCode)
add_executable(${PROJECT_NAME} ${SOURCES} ${LIB_SOURCES}) 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) target_link_libraries(${PROJECT_NAME} PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG)
add_dependencies(${PROJECT_NAME} generateCode) add_dependencies(${PROJECT_NAME} generateCode)
@ -39,11 +46,9 @@ if(CMAKE_BUILD_TYPE MATCHES "Release")
endif() endif()
add_executable(chessNoComputer ${SOURCES} ${LIB_SOURCES}) add_executable(chessNoComputer ${SOURCES} ${LIB_SOURCES})
set_property(TARGET chessNoComputer PROPERTY C_STANDARD 99)
target_link_libraries(chessNoComputer PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG) target_link_libraries(chessNoComputer PRIVATE PkgConfig::GTK4 PkgConfig::LIBRSVG)
add_dependencies(chessNoComputer generateCode) add_dependencies(chessNoComputer generateCode)
target_compile_definitions(chessNoComputer PUBLIC NO_COMPUTER) target_compile_definitions(chessNoComputer PUBLIC NO_COMPUTER)
add_executable(moveGenTest test/moveGen.c src/chess/move.c ${LIB_SOURCES}) 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) add_test(NAME moveGen COMMAND moveGenTest)

View File

@ -2,9 +2,6 @@
#include <stdint.h> #include <stdint.h>
#include <chess/types.h> #include <chess/types.h>
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); 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); 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); 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); 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 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 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);

6
include/chess/bitset.h Normal file
View File

@ -0,0 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
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);

View File

@ -17,6 +17,7 @@ enum spezialMoves {
struct move_t { struct move_t {
uint_least8_t src, dst, spezialMove; uint_least8_t src, dst, spezialMove;
uint_least8_t srcPiece, dstPiece, capturedPiece; uint_least8_t srcPiece, dstPiece, capturedPiece;
uint_least64_t hash;
}; };
void genDirectionConsts(); void genDirectionConsts();
@ -25,7 +26,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece
struct move_t *moves, bool promotion); struct move_t *moves, bool promotion);
void undoMove(uint_least64_t *board, struct move_t move, bool color); 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(); void initMagicTable();
bool kingInCheck(const uint_least64_t *board, const bool color); bool kingInCheck(const uint_least64_t *board, const bool color);
uint_least8_t getBaseRankI(bool color); uint_least8_t getBaseRankI(bool color);

View File

@ -2,26 +2,29 @@
#include <stdint.h> #include <stdint.h>
#include <chess/move.h> #include <chess/move.h>
#define fprintArray(file, printer, arr) \ #define fprintArrayCustomLength(file, printer, arr, length) \
do { \ do { \
fprintf(file, "{"); \ fprintf(file, "{"); \
for(size_t i = 0; i < LENGTH(arr); ++i) { \ for(size_t i = 0; i < length; ++i) { \
printer(file, arr[i]); \ printer(file, arr[i]); \
if (i < LENGTH(arr) - 1) { \ if (i < length - 1) { \
fprintf(file, ", "); \ fprintf(file, ", "); \
} \ } \
} \ } \
fprintf(file, " }"); \ fprintf(file, " }"); \
} while(0) } 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 { \ do { \
fprintf(file, "%s[%zu] = ", declaration, LENGTH(arr)); \ fprintf(file, "%s[%zu] = ", declaration, length); \
fprintArray(file, printer, arr); \ fprintArrayCustomLength(file, printer, arr, length); \
fprintf(file, ";\n"); \ fprintf(file, ";\n"); \
} while(0) } 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 printerll(FILE *file, long long num);
void printerull(FILE *file, unsigned long long num); void printerull(FILE *file, unsigned long long num);

View File

@ -1,3 +0,0 @@
#include <stdint.h>
uint_least64_t rand_64();

View File

@ -53,6 +53,7 @@ struct castle_t {
struct gameState_t { struct gameState_t {
uint_least64_t *board; uint_least64_t *board;
uint_least64_t zobrist;
bool color; // color to move bool color; // color to move
struct castle_t canCastle[2]; struct castle_t canCastle[2];

7
include/chess/util.h Normal file
View File

@ -0,0 +1,7 @@
#include <stdint.h>
#include <chess/types.h>
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);

View File

@ -0,0 +1,16 @@
#ifndef CHESS_ZOBRIST_CONSTS_H
#define CHESS_ZOBRIST_CONSTS_H
#include "chess/types.h"
#include <stdint.h>
#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

View File

@ -10,6 +10,7 @@
#include <chess/move.h> #include <chess/move.h>
#include <chess/bitboard.h> #include <chess/bitboard.h>
#include "evaluate.h" #include "evaluate.h"
#include <chess/util.h>
#define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" #define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"

View File

@ -9,6 +9,10 @@
#include <stdio.h> #include <stdio.h>
#include "magicNumber.h" #include "magicNumber.h"
#include <chess/magic.h> #include <chess/magic.h>
#include <chess/util.h>
#include <chess/bitset.h>
#include <chess/zobristConsts.h>
#include <string.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#include <intrin.h> #include <intrin.h>
@ -29,7 +33,7 @@ static uint_least8_t trailingBits(uint_least64_t num) {
unsigned long i; unsigned long i;
_BitScanForward(&i, num); _BitScanForward(&i, num);
return i; return i;
#elif #else
uint_least8_t count = 0; uint_least8_t count = 0;
while ((num & 1) == 0) { // Keep shifting num right until the least significant bit is 1 while ((num & 1) == 0) { // Keep shifting num right until the least significant bit is 1
num >>= 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); 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, 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_least8_t dst, uint_least8_t spezialMove, uint_least8_t promotionPiece) {
uint_least64_t *board = ctx.gameState.board; struct gameState_t gameState = ctx.gameState;
uint_least8_t *movesLength = ctx.movesLength; uint_least64_t *board = gameState.board;
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;
{ {
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); const uint_least8_t capturePos = getCapturePos(src, dst, spezialMove);
if(bitboardGet(board, pieceAllOtherColor, capturePos)) { if(bitboardGet(board, pieceAllOtherColor, capturePos)) {
for(uint_least8_t pieceType = QUEEN; pieceType < PIECES_LENGTH; ++pieceType) { for(uint_least8_t pieceType = QUEEN; pieceType < PIECES_LENGTH; ++pieceType) {
const struct piece_t piece = {pieceType, !movedPiece.color}; const struct piece_t piece = {pieceType, !movedPiece.color};
if(bitboardGet(board, piece, capturePos)) { if(bitboardGet(board, piece, capturePos)) {
capturedPiece = pieceType; const struct piece_t capturedPiece = {pieceType, otherColor};
hash ^= ZOBRIST_PIECE[zobristPieceI(capturedPiece, dst)];
capturedPieceType = pieceType;
break; break;
} }
} }
} }
} }
const struct move_t move = {src, dst, spezialMove, movedPiece.type, dstPiece, capturedPiece}; if(gameState.enPassantTo != NOT_SELECTED) hash ^= ZOBRIST_EN_PASSENT_FILE[getFile(gameState.enPassantTo)];
makeMove(ctx.gameState, move); 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)) { if(!kingInCheck(board, color)) {
ctx.moves[*movesLength] = move; ctx.moves[*movesLength] = move;
++*movesLength; ++*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]; uint_least8_t dst = src + DIRECTION_MODIFIER[pawnDirection];
if(!bitboardGetAllPieces(board, dst)) { if(!bitboardGetAllPieces(board, dst)) {
movePawn(addmoveCtx, piece.color, src, dst, promotion, 0); 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]; dst += DIRECTION_MODIFIER[pawnDirection];
if(!bitboardGetAllPieces(board, dst)) { if(!bitboardGetAllPieces(board, dst)) {
movePawn(addmoveCtx, piece.color, src, dst, promotion, FUTURE_EN_PASSANT); 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; return movesLength;
} }
static void setCastleInfo(struct castle_t *canCastle, uint_least8_t posOnRank) { struct gameState_t makeMove(struct gameState_t gameState, const struct move_t move) {
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) {
uint_least64_t *board = gameState.board; uint_least64_t *board = gameState.board;
const struct piece_t srcPiece = {move.srcPiece, gameState.color}; const struct piece_t srcPiece = {move.srcPiece, gameState.color};
const struct piece_t dstPiece = {move.dstPiece, 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)); bitboardClear(board, capturedPiece, getCapturePos(move.src, move.dst, move.spezialMove));
} }
castleMoveRook(board, move.spezialMove, gameState.color, false); castleMoveRook(board, move.spezialMove, gameState.color, false);
{ setCastleInfo(gameState.canCastle, gameState.color, move);
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));
}
}
{ {
const int_least8_t dist = (int_least8_t)move.dst - (int_least8_t)move.src; 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; 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; if(move.capturedPiece != NOT_SELECTED || srcPiece.type == PAWN) gameState.halfMoveCounter = 0;
else ++gameState.halfMoveCounter; else ++gameState.halfMoveCounter;
gameState.color = !gameState.color; gameState.color = !gameState.color;
gameState.zobrist ^= move.hash;
return gameState; return gameState;
} }

View File

@ -1,20 +1,11 @@
#include "chess/zobristConsts.h"
#include <ctype.h> #include <ctype.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <chess/types.h> #include <chess/types.h>
#include <stdlib.h> #include <stdlib.h>
#include <chess/util.h>
bool bitsetGet(uint_least64_t bitset, uint_least8_t i) { #include <chess/bitset.h>
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);
}
uint_least64_t bitboardGetMask(const uint_least64_t *board, struct piece_t piece) { uint_least64_t bitboardGetMask(const uint_least64_t *board, struct piece_t piece) {
return board[piece.color * PIECES_LENGTH + piece.type]; 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 newGameState(uint_least64_t *board, char *FEN) {
struct gameState_t gameState = {board}; struct gameState_t gameState = {board, 0};
for(uint_least8_t i = 0; i < BITBOARD_LENGTH; ++i) { for(uint_least8_t i = 0; i < BITBOARD_LENGTH; ++i) {
board[i] = 0; 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;
} }
for(uint_least8_t field = 0; *FEN != ' '; ++FEN) {
uint_least8_t getFile(const uint_least8_t field) { struct piece_t piece;
return field % BOARD_SIZE; switch(tolower(*FEN)) {
} case 'k':
piece.type = KING;
uint_least8_t getRank(const uint_least8_t field) { break;
return field / BOARD_SIZE; 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;
} }

View File

@ -1,7 +1,7 @@
#include <stdint.h> #include <stdint.h>
#include <chess/types.h> #include <chess/types.h>
#include <chess/generated/moveConsts.h> #include <chess/generated/moveConsts.h>
#include <chess/bitboard.h> #include <chess/bitset.h>
uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength, uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength,
uint_least8_t field, uint_least64_t blockMask) { uint_least8_t field, uint_least64_t blockMask) {

View File

@ -0,0 +1,14 @@
#include <chess/bitset.h>
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);
}

View File

@ -2,7 +2,8 @@
#include "chess/types.h" #include "chess/types.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <chess/bitboard.h> #include <chess/bitset.h>
#include <chess/util.h>
void printerll(FILE *file, long long num) { void printerll(FILE *file, long long num) {
fprintf(file, "%lld", num); fprintf(file, "%lld", num);

View File

@ -0,0 +1,22 @@
#include <stdint.h>
#include <stdlib.h>
#include <chess/util.h>
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;
}

View File

@ -1,10 +0,0 @@
#include <stdint.h>
#include <stdlib.h>
#include <chess/rand.h>
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);
}

View File

@ -9,7 +9,8 @@
#include <chess/magic.h> #include <chess/magic.h>
#include <chess/generated/moveConsts.h> #include <chess/generated/moveConsts.h>
#include <chess/bitboard.h> #include <chess/bitboard.h>
#include <chess/rand.h> #include <chess/bitset.h>
#include <chess/util.h>
#define MAX_BITS 12 #define MAX_BITS 12
#define MAX_SIZE (1 << MAX_BITS) #define MAX_SIZE (1 << MAX_BITS)

View File

@ -2,8 +2,9 @@
#include <chess/types.h> #include <chess/types.h>
#include <stdint.h> #include <stdint.h>
#include <inttypes.h> #include <inttypes.h>
#include <chess/bitboard.h> #include <chess/bitset.h>
#include <chess/print.h> #include <chess/print.h>
#include <chess/util.h>
static void printerMoveDst(FILE *file, struct moveDst_t moveDst) { static void printerMoveDst(FILE *file, struct moveDst_t moveDst) {
fprintf(file, "{ %" PRIuLEAST8 ", ", moveDst.length); fprintf(file, "{ %" PRIuLEAST8 ", ", moveDst.length);

View File

@ -1,30 +1,39 @@
#include "chess/types.h" #include "chess/types.h"
#include "chess/zobristConsts.h"
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <chess/rand.h> #include <chess/util.h>
#include <stdlib.h> #include <stdlib.h>
#include <chess/print.h> #include <chess/print.h>
#include <inttypes.h> #include <inttypes.h>
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() { int main() {
uint_least64_t zobristPiece[TOTAL_BOARD_SIZE * 2 * PIECES_LENGTH];
srand(0xc0229b8e); srand(0xc0229b8e);
printf("#ifndef CHESS_GENERATED_ZOBRIST_H\n" printf("#include <stdint.h>\n");
"#define CHESS_GENERATED_ZOBRIST_H\n" {
"#include <stdint.h>\n" uint_least64_t zobristPiece[ZOBRIST_PIECE_LENGTH];
); for(uint_least8_t color = BLACK; color <= WHITE; ++color) {
for(uint_least8_t color = BLACK; color <= WHITE; ++color) { for(uint_least8_t pieceType = KING; pieceType < PIECES_LENGTH; ++pieceType) {
for(uint_least8_t pieceType = KING; pieceType < PIECES_LENGTH; ++pieceType) { const struct piece_t piece = {pieceType, color};
const struct piece_t piece = {pieceType, color}; for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) { zobristPiece[zobristPieceI(piece, field)] = rand_64();
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());
} }