zobrist hashing
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -2,9 +2,6 @@
|
||||
#include <stdint.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);
|
||||
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);
|
||||
|
||||
6
include/chess/bitset.h
Normal file
6
include/chess/bitset.h
Normal 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);
|
||||
@ -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);
|
||||
|
||||
@ -2,26 +2,29 @@
|
||||
#include <stdint.h>
|
||||
#include <chess/move.h>
|
||||
|
||||
#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);
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint_least64_t rand_64();
|
||||
@ -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];
|
||||
|
||||
|
||||
7
include/chess/util.h
Normal file
7
include/chess/util.h
Normal 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);
|
||||
16
include/chess/zobristConsts.h
Normal file
16
include/chess/zobristConsts.h
Normal 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
|
||||
@ -10,6 +10,7 @@
|
||||
#include <chess/move.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include "evaluate.h"
|
||||
#include <chess/util.h>
|
||||
|
||||
#define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||
|
||||
|
||||
120
src/chess/move.c
120
src/chess/move.c
@ -9,6 +9,10 @@
|
||||
#include <stdio.h>
|
||||
#include "magicNumber.h"
|
||||
#include <chess/magic.h>
|
||||
#include <chess/util.h>
|
||||
#include <chess/bitset.h>
|
||||
#include <chess/zobristConsts.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1,20 +1,11 @@
|
||||
#include "chess/zobristConsts.h"
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <chess/types.h>
|
||||
#include <stdlib.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);
|
||||
}
|
||||
#include <chess/util.h>
|
||||
#include <chess/bitset.h>
|
||||
|
||||
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;
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
#include <stdint.h>
|
||||
#include <chess/types.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_least8_t field, uint_least64_t blockMask) {
|
||||
14
src/common/preCodeGen/bitset.c
Normal file
14
src/common/preCodeGen/bitset.c
Normal 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);
|
||||
}
|
||||
|
||||
@ -2,7 +2,8 @@
|
||||
#include "chess/types.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include <chess/bitset.h>
|
||||
#include <chess/util.h>
|
||||
|
||||
void printerll(FILE *file, long long num) {
|
||||
fprintf(file, "%lld", num);
|
||||
22
src/common/preCodeGen/util.c
Normal file
22
src/common/preCodeGen/util.c
Normal 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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -9,7 +9,8 @@
|
||||
#include <chess/magic.h>
|
||||
#include <chess/generated/moveConsts.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include <chess/rand.h>
|
||||
#include <chess/bitset.h>
|
||||
#include <chess/util.h>
|
||||
|
||||
#define MAX_BITS 12
|
||||
#define MAX_SIZE (1 << MAX_BITS)
|
||||
|
||||
@ -2,8 +2,9 @@
|
||||
#include <chess/types.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <chess/bitboard.h>
|
||||
#include <chess/bitset.h>
|
||||
#include <chess/print.h>
|
||||
#include <chess/util.h>
|
||||
|
||||
static void printerMoveDst(FILE *file, struct moveDst_t moveDst) {
|
||||
fprintf(file, "{ %" PRIuLEAST8 ", ", moveDst.length);
|
||||
|
||||
@ -1,30 +1,39 @@
|
||||
#include "chess/types.h"
|
||||
#include "chess/zobristConsts.h"
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <chess/rand.h>
|
||||
#include <chess/util.h>
|
||||
#include <stdlib.h>
|
||||
#include <chess/print.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() {
|
||||
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 <stdint.h>\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 <stdint.h>\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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user