145 lines
4.0 KiB
C
145 lines
4.0 KiB
C
#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);
|
|
}
|
|
|
|
uint_least64_t bitboardGetMask(const uint_least64_t *board, struct piece_t piece) {
|
|
return board[piece.color * PIECES_LENGTH + piece.type];
|
|
}
|
|
|
|
void bitboardSetMask(uint_least64_t *board, struct piece_t piece, uint_least64_t value) {
|
|
board[piece.color * PIECES_LENGTH + piece.type] = value;
|
|
}
|
|
|
|
uint_least64_t bitboardMaskAllPieces(const uint_least64_t *board) {
|
|
const struct piece_t blackPiece = {ALL_PIECES, BLACK};
|
|
const struct piece_t whitePiece = {ALL_PIECES, WHITE};
|
|
return bitboardGetMask(board, blackPiece) | bitboardGetMask(board, whitePiece);
|
|
}
|
|
|
|
bool bitboardGetAllPieces(const uint_least64_t *board, uint_least8_t i) {
|
|
return bitsetGet(bitboardMaskAllPieces(board), i);
|
|
}
|
|
|
|
bool bitboardGet(const uint_least64_t *board, struct piece_t piece, uint_least8_t i) {
|
|
return bitsetGet(bitboardGetMask(board, piece), i);
|
|
}
|
|
|
|
static void bitboardClearHelper(uint_least64_t *board, struct piece_t piece, uint_least8_t i) {
|
|
const uint_least64_t newMask = bitsetClear(bitboardGetMask(board, piece), i);
|
|
bitboardSetMask(board, piece, newMask);
|
|
}
|
|
|
|
void bitboardClear(uint_least64_t *board, struct piece_t piece, uint_least8_t i) {
|
|
const struct piece_t allPiece = {ALL_PIECES, piece.color};
|
|
bitboardClearHelper(board, allPiece, i);
|
|
bitboardClearHelper(board, piece, i);
|
|
}
|
|
|
|
static void bitboardSetHelper(uint_least64_t *board, struct piece_t piece, uint_least8_t i) {
|
|
const uint_least64_t newMask = bitsetSet(bitboardGetMask(board, piece), i);
|
|
bitboardSetMask(board, piece, newMask);
|
|
}
|
|
|
|
void bitboardSet(uint_least64_t *board, struct piece_t piece, uint_least8_t i) {
|
|
const struct piece_t allPiece = {ALL_PIECES, piece.color};
|
|
bitboardSetHelper(board, allPiece, i);
|
|
bitboardSetHelper(board, piece, i);
|
|
}
|
|
|
|
struct piece_t pieceAtField(const uint_least64_t *board, uint_least8_t i) {
|
|
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};
|
|
if(bitboardGet(board, piece, i)) {
|
|
return piece;
|
|
}
|
|
}
|
|
}
|
|
{
|
|
const struct piece_t pieceError = {NOT_SELECTED, BLACK};
|
|
return pieceError;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|