Compare commits
9 Commits
a649db77ef
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4458fb6491 | |||
| 924e7d5eed | |||
| 6ccd2a4efe | |||
| 6e61a14cdb | |||
| 2c3d1bc021 | |||
| 6c5ef0586f | |||
| db958dcac1 | |||
| 4d2a86c7b7 | |||
| 5209dfec92 |
3
.gitignore
vendored
3
.gitignore
vendored
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
11
README.md
11
README.md
@ -69,5 +69,12 @@ Alpha-Beta is based on [minimax](https://en.wikipedia.org/wiki/Minimax) with an
|
|||||||
added upper and lower bound for the position score with makes it much faster
|
added upper and lower bound for the position score with makes it much faster
|
||||||
than minimax.
|
than minimax.
|
||||||
|
|
||||||
The evaluation is currently simple because the only keeps track of the material
|
The engine has a partly implemented UCI interface with its code in `src/uci.c`.
|
||||||
and checkmate. Here is currently the most room for optimizations.
|
|
||||||
|
To detect repetitions we need a way to easily lookup, if the position already accrued. This done by
|
||||||
|
calculating a [Zobrist Hash](https://www.chessprogramming.org/Zobrist_Hashing) for the board
|
||||||
|
position. Zobrist Hashing is really nice because it allows incremental updating. With this hash the
|
||||||
|
engine has implemented its own hash tables, which allow for detecting repetitions. Later on this can
|
||||||
|
also be used for a [transposition table](https://www.chessprogramming.org/Transposition_Table).
|
||||||
|
|
||||||
|
The evaluation is currently simple. Here is currently the most room for optimizations.
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <chess/types.h>
|
#include <chess/types.h>
|
||||||
|
|
||||||
bool bitsetGet(uint_least64_t bitset, uint_least8_t i);
|
#define REPETETION_TABLE_LENGTH 1024
|
||||||
uint_least64_t bitsetClear(uint_least64_t bitset, uint_least8_t i);
|
#define START_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
|
||||||
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);
|
||||||
@ -13,4 +13,6 @@ uint_least64_t bitboardMaskAllPieces(const uint_least64_t *board);
|
|||||||
void bitboardClear(uint_least64_t *board, struct piece_t piece, uint_least8_t i);
|
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,
|
||||||
|
struct zobristTableElement *repetitionTableStore, const char *FEN);
|
||||||
|
struct gameState_t parseFen(uint_least64_t *board, const char *FEN);
|
||||||
|
|||||||
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 {
|
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();
|
||||||
@ -24,8 +25,8 @@ uint_least8_t validMoves(struct gameState_t gameState, struct move_t *moves);
|
|||||||
uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece, uint_least8_t src,
|
uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece, uint_least8_t src,
|
||||||
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(struct gameState_t gameState, 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);
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#define BOARD_SIZE 8
|
#define BOARD_SIZE 8
|
||||||
#define TOTAL_BOARD_SIZE (BOARD_SIZE * BOARD_SIZE)
|
#define TOTAL_BOARD_SIZE (BOARD_SIZE * BOARD_SIZE)
|
||||||
@ -35,6 +36,16 @@ enum directions {
|
|||||||
NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST, EAST, NORTHEAST, DIRECTION_LENGTH
|
NORTH, NORTHWEST, WEST, SOUTHWEST, SOUTH, SOUTHEAST, EAST, NORTHEAST, DIRECTION_LENGTH
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct zobristTableElement {
|
||||||
|
uint_least64_t hash;
|
||||||
|
int_least16_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct zobristTable {
|
||||||
|
struct zobristTableElement *arr;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
struct moveDst_t {
|
struct moveDst_t {
|
||||||
uint_least8_t length;
|
uint_least8_t length;
|
||||||
uint_least8_t dst[8];
|
uint_least8_t dst[8];
|
||||||
@ -53,6 +64,8 @@ struct castle_t {
|
|||||||
|
|
||||||
struct gameState_t {
|
struct gameState_t {
|
||||||
uint_least64_t *board;
|
uint_least64_t *board;
|
||||||
|
uint_least64_t zobrist;
|
||||||
|
struct zobristTable repetitionTable;
|
||||||
bool color; // color to move
|
bool color; // color to move
|
||||||
struct castle_t canCastle[2];
|
struct castle_t canCastle[2];
|
||||||
|
|
||||||
|
|||||||
18
include/chess/util.h
Normal file
18
include/chess/util.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef CHESS_UTIL_H
|
||||||
|
#define CHESS_UTIL_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#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);
|
||||||
|
|
||||||
|
struct zobristTable initZobirstTable(struct zobristTableElement *table, size_t length);
|
||||||
|
void zobristTableIter(const struct zobristTable table, const uint_least64_t key, void *result,
|
||||||
|
void (*callback)(struct zobristTableElement *element, const uint_least64_t key, void *result));
|
||||||
|
|
||||||
|
#endif
|
||||||
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
|
||||||
@ -9,16 +9,16 @@
|
|||||||
#define INT_16_SAFE_MAX (INT_LEAST16_MAX - 1)
|
#define INT_16_SAFE_MAX (INT_LEAST16_MAX - 1)
|
||||||
|
|
||||||
#ifdef __GNUC__ // Check if using GCC or compatible compiler
|
#ifdef __GNUC__ // Check if using GCC or compatible compiler
|
||||||
static int_least16_t countOnes(uint_least64_t num) {
|
static int_least16_t countOnes(const uint_least64_t num) {
|
||||||
return __builtin_popcountll(num); // Use GCC built-in function if available
|
return __builtin_popcountll(num); // Use GCC built-in function if available
|
||||||
}
|
}
|
||||||
#elif defined(_MSC_VER) // Check if using Microsoft Visual C++
|
#elif defined(_MSC_VER) // Check if using Microsoft Visual C++
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
static int_least16_t countOnes(uint_least64_t num) {
|
static int_least16_t countOnes(const uint_least64_t num) {
|
||||||
return __popcnt64(num); // Use MSVC intrinsic if available
|
return __popcnt64(num); // Use MSVC intrinsic if available
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int_least16_t countOnes(uint_least64_t num) {
|
static int_least16_t countOnes(const uint_least64_t num) {
|
||||||
int_least16_t count = 0;
|
int_least16_t count = 0;
|
||||||
while(num) {
|
while(num) {
|
||||||
count += num & 1;
|
count += num & 1;
|
||||||
@ -29,6 +29,7 @@ static int_least16_t countOnes(uint_least64_t num) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int_least16_t evaluate(const struct gameState_t gameState) {
|
static int_least16_t evaluate(const struct gameState_t gameState) {
|
||||||
|
if(gameState.halfMoveCounter == 50) return 0;
|
||||||
int_least16_t value = 0;
|
int_least16_t value = 0;
|
||||||
const uint_least64_t *board = gameState.board;
|
const uint_least64_t *board = gameState.board;
|
||||||
int_least16_t pieceValues[PIECES_LENGTH];
|
int_least16_t pieceValues[PIECES_LENGTH];
|
||||||
@ -63,7 +64,7 @@ static int_least16_t alphaBeta(const struct gameState_t gameState, int_fast16_t
|
|||||||
const struct move_t move = moves[i];
|
const struct move_t move = moves[i];
|
||||||
const struct gameState_t newGameState = makeMove(gameState, move);
|
const struct gameState_t newGameState = makeMove(gameState, move);
|
||||||
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
||||||
undoMove(gameState.board, move, gameState.color);
|
undoMove(newGameState, move, gameState.color);
|
||||||
if(score >= beta) {
|
if(score >= beta) {
|
||||||
return beta; // beta-cutoff
|
return beta; // beta-cutoff
|
||||||
}
|
}
|
||||||
@ -84,7 +85,7 @@ static struct move_t searchRoot(const struct gameState_t gameState, uint_least8_
|
|||||||
const struct move_t move = moves[i];
|
const struct move_t move = moves[i];
|
||||||
const struct gameState_t newGameState = makeMove(gameState, move);
|
const struct gameState_t newGameState = makeMove(gameState, move);
|
||||||
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
const int_least16_t score = -alphaBeta(newGameState, -beta, -alpha, depth - 1);
|
||||||
undoMove(gameState.board, move, gameState.color);
|
undoMove(newGameState, move, gameState.color);
|
||||||
if(score > alpha) {
|
if(score > alpha) {
|
||||||
alpha = score; // alpha acts like max in MiniMax
|
alpha = score; // alpha acts like max in MiniMax
|
||||||
selectedMove = move;
|
selectedMove = move;
|
||||||
|
|||||||
@ -10,9 +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"
|
|
||||||
|
|
||||||
struct drawData_t {
|
struct drawData_t {
|
||||||
RsvgHandle **piecesSvg;
|
RsvgHandle **piecesSvg;
|
||||||
@ -30,24 +28,21 @@ struct drawData_t {
|
|||||||
const uint_least8_t PROMOTION_PIECES[] = {QUEEN, KNIGHT, BISHOP, ROOK};
|
const uint_least8_t PROMOTION_PIECES[] = {QUEEN, KNIGHT, BISHOP, ROOK};
|
||||||
|
|
||||||
static uint_least8_t pieceToSvgI(struct piece_t piece) {
|
static uint_least8_t pieceToSvgI(struct piece_t piece) {
|
||||||
return piece.color == WHITE ? piece.type | 8 : piece.type;
|
return piece.color == WHITE ? PIECES_LENGTH + piece.type : piece.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drawPiece(struct drawData_t *ctx, cairo_t *cr, uint_least8_t field, struct piece_t piece) {
|
static void drawPiece(struct drawData_t *ctx, cairo_t *cr, uint_least8_t field, struct piece_t piece) {
|
||||||
const uint_least8_t file = field % BOARD_SIZE;
|
const RsvgRectangle rect = {ctx->xOffset + getFile(field)* ctx->fieldSize,
|
||||||
const uint_least8_t rank = field / BOARD_SIZE;
|
ctx->yOffset + getRank(field) * ctx->fieldSize, ctx->fieldSize, ctx->fieldSize};
|
||||||
const RsvgRectangle rect = {ctx->xOffset + file * ctx->fieldSize, ctx->yOffset + rank * ctx->fieldSize, ctx->fieldSize, ctx->fieldSize};\
|
|
||||||
rsvg_handle_render_document(ctx->piecesSvg[pieceToSvgI(piece)], cr, &rect, NULL);
|
rsvg_handle_render_document(ctx->piecesSvg[pieceToSvgI(piece)], cr, &rect, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void selectCircle(cairo_t *cr, const struct drawData_t *drawData, uint_least8_t field, double radius) {
|
static void selectCircle(cairo_t *cr, const struct drawData_t *drawData, uint_least8_t field, double radius) {
|
||||||
uint_least8_t file = field % BOARD_SIZE;
|
const double xOffset = drawData->xOffset;
|
||||||
uint_least8_t rank = field / BOARD_SIZE;
|
const double yOffset = drawData->yOffset;
|
||||||
double xOffset = drawData->xOffset;
|
const double fieldSize = drawData->fieldSize;
|
||||||
double yOffset = drawData->yOffset;
|
cairo_arc(cr, xOffset + (getFile(field) + 0.5) * fieldSize, yOffset + (getRank(field) + 0.5) * fieldSize, radius, 0, 2 * M_PI);
|
||||||
double fieldSize = drawData->fieldSize;
|
|
||||||
cairo_arc(cr, xOffset + (file + 0.5) * fieldSize, yOffset + (rank + 0.5) * fieldSize, radius, 0, 2 * M_PI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct gameState_t userMove(struct gameState_t gameState, struct move_t move) {
|
static struct gameState_t userMove(struct gameState_t gameState, struct move_t move) {
|
||||||
@ -67,6 +62,13 @@ static uint_least8_t promotionUiPos(uint_least8_t dst, bool color) {
|
|||||||
return uiPos;
|
return uiPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void drawRetangle(cairo_t *cr, struct drawData_t *drawData, uint_least8_t field, double width) {
|
||||||
|
const double fieldSize = drawData->fieldSize;
|
||||||
|
cairo_rectangle(cr, drawData->xOffset + getFile(field) * fieldSize,
|
||||||
|
drawData->yOffset + getRank(field) * fieldSize, width, fieldSize);
|
||||||
|
cairo_fill(cr);
|
||||||
|
}
|
||||||
|
|
||||||
static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data) {
|
static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height, gpointer data) {
|
||||||
const double fieldSize = (double)(width < height ? width : height) / BOARD_SIZE;
|
const double fieldSize = (double)(width < height ? width : height) / BOARD_SIZE;
|
||||||
const double xOffset = (width - fieldSize * BOARD_SIZE) / 2;
|
const double xOffset = (width - fieldSize * BOARD_SIZE) / 2;
|
||||||
@ -81,10 +83,9 @@ static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height,
|
|||||||
for(uint_least8_t file = 0; file < BOARD_SIZE; ++file) {
|
for(uint_least8_t file = 0; file < BOARD_SIZE; ++file) {
|
||||||
for(uint_least8_t rank = 0; rank < BOARD_SIZE; ++rank) {
|
for(uint_least8_t rank = 0; rank < BOARD_SIZE; ++rank) {
|
||||||
const uint_least8_t field = rank * BOARD_SIZE + file;
|
const uint_least8_t field = rank * BOARD_SIZE + file;
|
||||||
cairo_rectangle(cr, xOffset + file * fieldSize, yOffset + rank * fieldSize, fieldSize, fieldSize);
|
|
||||||
if((file + rank) & 1) cairo_set_source_rgb(cr, 0.46274, 0.5882, 0.3373);
|
if((file + rank) & 1) cairo_set_source_rgb(cr, 0.46274, 0.5882, 0.3373);
|
||||||
else cairo_set_source_rgb(cr, 0.9333, 0.9333, 0.8235);
|
else cairo_set_source_rgb(cr, 0.9333, 0.9333, 0.8235);
|
||||||
cairo_fill(cr);
|
drawRetangle(cr, drawData, field, fieldSize);
|
||||||
if(bitboardGetAllPieces(board, field)) {
|
if(bitboardGetAllPieces(board, field)) {
|
||||||
const struct piece_t piece = pieceAtField(board, rank * BOARD_SIZE + file);
|
const struct piece_t piece = pieceAtField(board, rank * BOARD_SIZE + file);
|
||||||
drawPiece(drawData, cr, field, piece);
|
drawPiece(drawData, cr, field, piece);
|
||||||
@ -104,8 +105,7 @@ static void draw_event(GtkDrawingArea *area, cairo_t *cr, int width, int height,
|
|||||||
if(drawData->selectDst != NOT_SELECTED) {
|
if(drawData->selectDst != NOT_SELECTED) {
|
||||||
uint_least8_t uiPos = promotionUiPos(drawData->selectDst, gameState->color);
|
uint_least8_t uiPos = promotionUiPos(drawData->selectDst, gameState->color);
|
||||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
||||||
cairo_rectangle(cr, xOffset + uiPos * fieldSize, yOffset, 4 * fieldSize, fieldSize);
|
drawRetangle(cr, drawData, uiPos, 4 * fieldSize);
|
||||||
cairo_fill(cr);
|
|
||||||
for(uint_least8_t i = 0; i < LENGTH(PROMOTION_PIECES); ++i) {
|
for(uint_least8_t i = 0; i < LENGTH(PROMOTION_PIECES); ++i) {
|
||||||
const struct piece_t piece = {PROMOTION_PIECES[i], gameState->color};
|
const struct piece_t piece = {PROMOTION_PIECES[i], gameState->color};
|
||||||
drawPiece(drawData, cr, uiPos + i, piece);
|
drawPiece(drawData, cr, uiPos + i, piece);
|
||||||
@ -186,10 +186,11 @@ static void on_click(GtkGestureClick *gesture, int n_press, double x, double y,
|
|||||||
|
|
||||||
static void app_activate(GApplication *app, gpointer data) {
|
static void app_activate(GApplication *app, gpointer data) {
|
||||||
GtkWindow *window = GTK_WINDOW(gtk_window_new());
|
GtkWindow *window = GTK_WINDOW(gtk_window_new());
|
||||||
static RsvgHandle *piecesSvg[16];
|
static RsvgHandle *piecesSvg[2 * PIECES_LENGTH];
|
||||||
static uint_least64_t board[BITBOARD_LENGTH];
|
static uint_least64_t board[BITBOARD_LENGTH];
|
||||||
|
static struct zobristTableElement repetitionTableStore[REPETETION_TABLE_LENGTH];
|
||||||
static struct gameState_t gameState;
|
static struct gameState_t gameState;
|
||||||
gameState = newGameState(board, START_FEN);
|
gameState = newGameState(board, repetitionTableStore, START_FEN);
|
||||||
{
|
{
|
||||||
static struct move_t moves[TOTAL_BOARD_SIZE];
|
static struct move_t moves[TOTAL_BOARD_SIZE];
|
||||||
static struct drawData_t drawData = {piecesSvg, &gameState, NOT_SELECTED, moves, 0, NOT_SELECTED};
|
static struct drawData_t drawData = {piecesSvg, &gameState, NOT_SELECTED, moves, 0, NOT_SELECTED};
|
||||||
|
|||||||
135
src/chess/move.c
135
src/chess/move.c
@ -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;
|
||||||
@ -154,7 +158,16 @@ static void castleMoveRook(uint_least64_t *board, uint_least8_t spezialMove, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void undoMove(uint_least64_t *board, struct move_t move, bool color) {
|
static void zobristTableUndoMoveCallback(struct zobristTableElement *element, const uint_least64_t key,
|
||||||
|
void *resultVoid) {
|
||||||
|
if(element->hash == key) {
|
||||||
|
if(--element->value == 0) element->hash = 0;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Error: Position does not in repetitionTable in undoMove (move.c)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void undoMove(const struct gameState_t gameState, struct move_t move, bool color) {
|
||||||
|
uint_least64_t *board = gameState.board;
|
||||||
const struct piece_t srcPiece = {move.srcPiece, color};
|
const struct piece_t srcPiece = {move.srcPiece, color};
|
||||||
const struct piece_t dstPiece = {move.dstPiece, color};
|
const struct piece_t dstPiece = {move.dstPiece, color};
|
||||||
bitboardSet(board, srcPiece, move.src);
|
bitboardSet(board, srcPiece, move.src);
|
||||||
@ -164,38 +177,95 @@ void undoMove(uint_least64_t *board, struct move_t move, bool color) {
|
|||||||
bitboardSet(board, piece, getCapturePos(move.src, move.dst, move.spezialMove));
|
bitboardSet(board, piece, getCapturePos(move.src, move.dst, move.spezialMove));
|
||||||
}
|
}
|
||||||
castleMoveRook(board, move.spezialMove, color, true);
|
castleMoveRook(board, move.spezialMove, color, true);
|
||||||
|
zobristTableIter(gameState.repetitionTable, gameState.zobrist, NULL, zobristTableUndoMoveCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
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};
|
const struct piece_t pieceAll = {ALL_PIECES, movedPiece.color};
|
||||||
if(bitboardGet(board, pieceAll, dst)) return;
|
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 pieceAllOtherColor = {ALL_PIECES, !movedPiece.color};
|
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;
|
||||||
|
}
|
||||||
|
struct gameState_t newGameState = 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;
|
||||||
}
|
}
|
||||||
undoMove(board, move, color);
|
undoMove(newGameState, move, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +373,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(src / BOARD_SIZE == (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 +407,17 @@ 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) {
|
static void zobristTableMakeMoveCallback(struct zobristTableElement *element, const uint_least64_t key,
|
||||||
switch(posOnRank) {
|
void *resultVoid) {
|
||||||
case 0:
|
if(element->hash == key) {
|
||||||
canCastle->longCastle = false;
|
++element->value;
|
||||||
break;
|
return;
|
||||||
case BOARD_SIZE - 1:
|
|
||||||
canCastle->shortCastle = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
element->hash = key;
|
||||||
|
element->value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
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 +428,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 +436,7 @@ 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;
|
||||||
|
zobristTableIter(gameState.repetitionTable, gameState.zobrist, NULL, zobristTableMakeMoveCallback);
|
||||||
return gameState;
|
return gameState;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,20 +1,12 @@
|
|||||||
|
#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;
|
#include <chess/bitboard.h>
|
||||||
}
|
|
||||||
|
|
||||||
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];
|
||||||
@ -75,8 +67,8 @@ 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 parseFen(uint_least64_t *board, const 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;
|
||||||
}
|
}
|
||||||
@ -111,16 +103,25 @@ struct gameState_t newGameState(uint_least64_t *board, char *FEN) {
|
|||||||
}
|
}
|
||||||
if(isalpha(*FEN)) piece.color = isupper(*FEN);
|
if(isalpha(*FEN)) piece.color = isupper(*FEN);
|
||||||
bitboardSet(board, piece, field);
|
bitboardSet(board, piece, field);
|
||||||
|
gameState.zobrist ^= ZOBRIST_PIECE[zobristPieceI(piece, field)];
|
||||||
++field;
|
++field;
|
||||||
}
|
}
|
||||||
gameState.color = *++FEN == 'w' ? WHITE : BLACK;
|
gameState.color = *++FEN == 'w' ? WHITE : BLACK;
|
||||||
|
if(gameState.color == BLACK) gameState.zobrist ^= ZOBRIST_BLACK_MOVE;
|
||||||
FEN += 2;
|
FEN += 2;
|
||||||
if(*FEN == '-') ++FEN;
|
if(*FEN == '-') ++FEN;
|
||||||
else {
|
else {
|
||||||
for(; *FEN != ' '; ++FEN) {
|
for(; *FEN != ' '; ++FEN) {
|
||||||
struct castle_t *playerCastle = gameState.canCastle + (isupper(*FEN) ? WHITE : BLACK);
|
const bool color = isupper(*FEN) ? WHITE : BLACK;
|
||||||
if(tolower(*FEN) == 'k') playerCastle->shortCastle = true;
|
struct castle_t *playerCastle = gameState.canCastle + color;
|
||||||
else playerCastle->longCastle = true;
|
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 == '-'){
|
if(*++FEN == '-'){
|
||||||
@ -128,9 +129,18 @@ struct gameState_t newGameState(uint_least64_t *board, char *FEN) {
|
|||||||
gameState.enPassantTo = NOT_SELECTED;
|
gameState.enPassantTo = NOT_SELECTED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gameState.enPassantTo = *FEN++ - 'a';
|
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.enPassantTo += (BOARD_SIZE - *FEN++) * BOARD_SIZE;
|
||||||
}
|
}
|
||||||
gameState.halfMoveCounter = atoi(++FEN);
|
gameState.halfMoveCounter = atoi(++FEN);
|
||||||
return gameState;
|
return gameState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct gameState_t newGameState(uint_least64_t *board,
|
||||||
|
struct zobristTableElement *repetitionTableStore, const char *FEN) {
|
||||||
|
struct gameState_t gameState = parseFen(board, FEN);
|
||||||
|
gameState.repetitionTable = initZobirstTable(repetitionTableStore, REPETETION_TABLE_LENGTH);
|
||||||
|
return gameState;
|
||||||
|
}
|
||||||
@ -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) {
|
||||||
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 "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);
|
||||||
@ -23,8 +24,8 @@ void printPieceMask(uint_least64_t mask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void fieldToString(uint_least8_t field, char *output) {
|
void fieldToString(uint_least8_t field, char *output) {
|
||||||
output[0] = 'a' + field % BOARD_SIZE;
|
output[0] = 'a' + getFile(field);
|
||||||
output[1] = '0' + BOARD_SIZE - field / BOARD_SIZE;
|
output[1] = '0' + BOARD_SIZE - getRank(field);
|
||||||
output[2] = '\0';
|
output[2] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
78
src/common/preCodeGen/util.c
Normal file
78
src/common/preCodeGen/util.c
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include "chess/types.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.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;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zobristTable initZobirstTable(struct zobristTableElement *table, size_t length) {
|
||||||
|
for(size_t i = 0; i < length; ++i) {
|
||||||
|
table[i].hash = 0;
|
||||||
|
}
|
||||||
|
return (struct zobristTable){table, length};
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t zobristTableInitialI(const struct zobristTable table, const uint_least64_t key) {
|
||||||
|
return key % table.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zobristTableIter(const struct zobristTable table, const uint_least64_t key, void *result,
|
||||||
|
void (*callback)(struct zobristTableElement *element, const uint_least64_t key, void *result)) {
|
||||||
|
const size_t initI = zobristTableInitialI(table, key);
|
||||||
|
size_t i = initI;
|
||||||
|
do {
|
||||||
|
struct zobristTableElement *element = table.arr + i;
|
||||||
|
if(element->hash == 0 || element->hash == key) {
|
||||||
|
callback(element, key, result);
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
if(i >= table.length) i = 0;
|
||||||
|
} while(i != initI);
|
||||||
|
fprintf(stderr, "Error: zobrist table is full");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void zobristTableItemPtrCallback(struct zobristTableElement *element, const uint_least64_t key,
|
||||||
|
void *resultVoid) {
|
||||||
|
struct zobristTableElement **result = resultVoid;
|
||||||
|
if(element->hash == key) {
|
||||||
|
*result = element;
|
||||||
|
return;
|
||||||
|
} // if(hash == 0)
|
||||||
|
*result = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct zobristTableElement* zobristTableItemPtr(const struct zobristTable table, const uint_least64_t key) {
|
||||||
|
struct zobristTableElement *result;
|
||||||
|
zobristTableIter(table, key, &result, zobristTableItemPtrCallback);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zobristTableDelete(struct zobristTable table, const uint_least64_t key) {
|
||||||
|
struct zobristTableElement *element = zobristTableItemPtr(table, key);
|
||||||
|
if(element != NULL) element->hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int_least16_t* zobristTableGetPtr(const struct zobristTable table, const uint_least64_t key) {
|
||||||
|
struct zobristTableElement *element = zobristTableItemPtr(table, key);
|
||||||
|
if(element == NULL) return NULL;
|
||||||
|
return &element->value;
|
||||||
|
}
|
||||||
@ -9,18 +9,13 @@
|
|||||||
#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/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)
|
||||||
#define ATTACK_TABLE_LENGTH (2 * MAX_SIZE * TOTAL_BOARD_SIZE)
|
#define ATTACK_TABLE_LENGTH (2 * MAX_SIZE * TOTAL_BOARD_SIZE)
|
||||||
|
|
||||||
static 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint_least64_t randFewBits() {
|
static uint_least64_t randFewBits() {
|
||||||
return rand_64() & rand_64() & rand_64();
|
return rand_64() & rand_64() & rand_64();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
@ -36,8 +37,8 @@ int main() {
|
|||||||
);
|
);
|
||||||
uint_least8_t directionOffset[TOTAL_BOARD_SIZE * DIRECTION_LENGTH];
|
uint_least8_t directionOffset[TOTAL_BOARD_SIZE * DIRECTION_LENGTH];
|
||||||
for(uint_least16_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
for(uint_least16_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
||||||
uint_least8_t file = field % BOARD_SIZE;
|
uint_least8_t file = getFile(field);
|
||||||
uint_least8_t rank = field / BOARD_SIZE;
|
uint_least8_t rank = getRank(field);
|
||||||
uint_least8_t *offsetField = directionOffset + field * DIRECTION_LENGTH;
|
uint_least8_t *offsetField = directionOffset + field * DIRECTION_LENGTH;
|
||||||
offsetField[NORTH] = rank;
|
offsetField[NORTH] = rank;
|
||||||
offsetField[WEST] = file;
|
offsetField[WEST] = file;
|
||||||
|
|||||||
39
src/generateCode/zobrist.c
Normal file
39
src/generateCode/zobrist.c
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#include "chess/types.h"
|
||||||
|
#include "chess/zobristConsts.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <chess/util.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <chess/print.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
srand(0xc0229b8e);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
src/uci.c
Normal file
72
src/uci.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "chess/move.h"
|
||||||
|
#include "chess/types.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <chess/bitboard.h>
|
||||||
|
|
||||||
|
atomic_bool searchShouldStop;
|
||||||
|
|
||||||
|
#define customStrCmp(input, cmd) customStrCmpFunc(&(input), cmd, sizeof(cmd))
|
||||||
|
static bool customStrCmpFunc(char **input, const char *cmd, const size_t length) {
|
||||||
|
bool result = strncmp(*input, cmd, length) == 0;
|
||||||
|
if(result) *input += length + 1;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
char input[4096];
|
||||||
|
struct gameState_t gameState;
|
||||||
|
uint_least64_t board[TOTAL_BOARD_SIZE];
|
||||||
|
gameState.repetitionTable = (struct zobristTable){NULL};
|
||||||
|
initMagicTable();
|
||||||
|
while(true) {
|
||||||
|
char *inputPtr = input;
|
||||||
|
if(fgets(input, sizeof input, stdin) == NULL) {
|
||||||
|
perror("Error: reading stdin: ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "uci")) {
|
||||||
|
printf(
|
||||||
|
"id name NoNameChessEngine\n"
|
||||||
|
"id author MrGeorgen\n"
|
||||||
|
"uciok\n"
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "isready")) {
|
||||||
|
printf("readyok\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "position")) {
|
||||||
|
if(gameState.repetitionTable.arr == NULL) {
|
||||||
|
fprintf(stderr, "Error: required uicnewgame before a position command\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "startpos")) {
|
||||||
|
gameState = parseFen(board, START_FEN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "fen")) {
|
||||||
|
gameState = parseFen(board, inputPtr);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "quit")) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "go")) {
|
||||||
|
while(*inputPtr != '\0') {
|
||||||
|
//if(customStrCmp(inputPtr, "wtime"))
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(customStrCmp(inputPtr, "stop")) {
|
||||||
|
searchShouldStop = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -21,14 +21,15 @@ static uint_least64_t perft(const struct gameState_t gameState, const uint_least
|
|||||||
for(uint_least8_t i = 0; i < movesLength; ++i) {
|
for(uint_least8_t i = 0; i < movesLength; ++i) {
|
||||||
const struct gameState_t newGameState = makeMove(gameState, moves[i]);
|
const struct gameState_t newGameState = makeMove(gameState, moves[i]);
|
||||||
nodes += perft(newGameState, depth - 1);
|
nodes += perft(newGameState, depth - 1);
|
||||||
undoMove(gameState.board, moves[i], gameState.color);
|
undoMove(newGameState, moves[i], gameState.color);
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test(struct perf_t perf, const uint_least8_t i) {
|
static void test(struct perf_t perf, const uint_least8_t i) {
|
||||||
uint_least64_t board[BITBOARD_LENGTH];
|
uint_least64_t board[BITBOARD_LENGTH];
|
||||||
const struct gameState_t gameState = newGameState(board, perf.FEN);
|
struct zobristTableElement repetitionTableStore[REPETETION_TABLE_LENGTH];
|
||||||
|
const struct gameState_t gameState = newGameState(board, repetitionTableStore, perf.FEN);
|
||||||
const uint_least64_t nodes = perft(gameState, perf.depth);
|
const uint_least64_t nodes = perft(gameState, perf.depth);
|
||||||
if(perf.nodes != nodes) {
|
if(perf.nodes != nodes) {
|
||||||
printf("Test %" PRIuLEAST16 " failed: FEN: %s, depth: %" PRIuLEAST8 " calculated nodes: %" PRIuLEAST64
|
printf("Test %" PRIuLEAST16 " failed: FEN: %s, depth: %" PRIuLEAST8 " calculated nodes: %" PRIuLEAST64
|
||||||
@ -38,7 +39,7 @@ static void test(struct perf_t perf, const uint_least8_t i) {
|
|||||||
for(uint_least8_t j = 0; j < movesLength; ++j) {
|
for(uint_least8_t j = 0; j < movesLength; ++j) {
|
||||||
const struct gameState_t newGameState = makeMove(gameState, moves[j]);
|
const struct gameState_t newGameState = makeMove(gameState, moves[j]);
|
||||||
const uint_least64_t nodes = perft(newGameState, perf.depth - 1);
|
const uint_least64_t nodes = perft(newGameState, perf.depth - 1);
|
||||||
undoMove(gameState.board, moves[j], gameState.color);
|
undoMove(newGameState, moves[j], gameState.color);
|
||||||
{
|
{
|
||||||
printMove(moves[j]);
|
printMove(moves[j]);
|
||||||
printf(" %" PRIuLEAST64 "\n", nodes);
|
printf(" %" PRIuLEAST64 "\n", nodes);
|
||||||
|
|||||||
Reference in New Issue
Block a user