working move gen
This commit is contained in:
@ -3,10 +3,10 @@ project(chess C)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include_directories(include)
|
||||
file(GLOB SOURCES "src/chess/*.c")
|
||||
file(GLOB LIB_SOURCES "lib/chess/*.c")
|
||||
file(GLOB LIB_SOURCES "src/common/*.c")
|
||||
|
||||
add_executable(genMoveConsts src/generateCode/moveConsts.c lib/chess/bitboard.c
|
||||
lib/chess/print.c)
|
||||
add_executable(genMoveConsts src/generateCode/moveConsts.c src/common/bitboard.c
|
||||
src/common/print.c)
|
||||
add_custom_command(
|
||||
OUTPUT moveConsts.h # Output file from code generation
|
||||
COMMAND genMoveConsts > include/chess/generated/moveConsts.h
|
||||
|
||||
@ -13,3 +13,4 @@ uint_least64_t bitboardMaskAllPieces(const uint_least64_t *board);
|
||||
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);
|
||||
|
||||
@ -14,25 +14,11 @@ enum spezialMoves {
|
||||
LONG_CASTLE,
|
||||
};
|
||||
|
||||
struct castle_t {
|
||||
bool shortCastle, longCastle;
|
||||
};
|
||||
|
||||
struct move_t {
|
||||
uint_least8_t src, dst, spezialMove;
|
||||
uint_least8_t srcPiece, dstPiece, capturedPiece;
|
||||
};
|
||||
|
||||
struct gameState_t {
|
||||
uint_least64_t *board;
|
||||
bool color; // color to move
|
||||
struct castle_t canCastle[2];
|
||||
|
||||
// The number of halfmoves since the last capture or pawn advance, used for the fifty-move rule.
|
||||
uint_least8_t halfMoveCounter;
|
||||
uint_least8_t enPassantTo; // index of the destination for a possible en passant capture
|
||||
};
|
||||
|
||||
void genDirectionConsts();
|
||||
uint_least8_t validMoves(struct gameState_t gameState, bool color, struct move_t *moves);
|
||||
uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece, uint_least8_t src,
|
||||
@ -8,6 +8,7 @@
|
||||
#define TOTAL_BOARD_SIZE (BOARD_SIZE * BOARD_SIZE)
|
||||
#define LENGTH(array) (sizeof array / sizeof *array)
|
||||
#define NOT_SELECTED UINT_LEAST8_MAX
|
||||
#define BITBOARD_LENGTH 2 * PIECES_LENGTH
|
||||
|
||||
enum pieces {
|
||||
ALL_PIECES,
|
||||
@ -46,4 +47,18 @@ struct magic_t {
|
||||
uint_least8_t shift;
|
||||
};
|
||||
|
||||
struct castle_t {
|
||||
bool shortCastle, longCastle;
|
||||
};
|
||||
|
||||
struct gameState_t {
|
||||
uint_least64_t *board;
|
||||
bool color; // color to move
|
||||
struct castle_t canCastle[2];
|
||||
|
||||
// The number of halfmoves since the last capture or pawn advance, used for the fifty-move rule.
|
||||
uint_least8_t halfMoveCounter;
|
||||
uint_least8_t enPassantTo; // index of the destination for a possible en passant capture
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
3
src/chess/magicNumber.h
Normal file
3
src/chess/magicNumber.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include <chess/types.h>
|
||||
static struct magic_t rookMagic[64] = {{ 0, 126u, 585504314899303506u, 58}, { 0, 144680345676153468u, 9241404028087189504u, 53}, { 0, 289360691352306810u, 612524733837086720u, 53}, { 0, 578721382704613494u, 72092812853645312u, 53}, { 0, 1157442765409226862u, 1188953050539099136u, 53}, { 0, 2314885530818453598u, 72058693583372296u, 53}, { 0, 4629771061636907070u, 1188970094051459328u, 53}, { 0, 126u, 585504314899303506u, 58}, { 0, 32256u, 4573969545971713u, 58}, { 0, 144680345676184578u, 9223442680478961664u, 54}, { 0, 289360691352336900u, 2392606057169024u, 54}, { 0, 578721382704641544u, 140806208356480u, 54}, { 0, 1157442765409250832u, 1153062791918127104u, 54}, { 0, 2314885530818469408u, 140754676613632u, 54}, { 0, 4629771061636906560u, 14411660094863311104u, 54}, { 0, 32256u, 4573969545971713u, 58}, { 0, 8257536u, 4035243133187982848u, 58}, { 0, 144680345684148738u, 9223442680478961664u, 54}, { 0, 289360691360039940u, 71468792942848u, 54}, { 0, 578721382711822344u, 143486535927808u, 54}, { 0, 1157442765415387152u, 1153062791918127104u, 54}, { 0, 2314885530822516768u, 141287311278592u, 54}, { 0, 4629771061636776000u, 4398063813136u, 54}, { 0, 8257536u, 4035243133187982848u, 58}, { 0, 2113929216u, 9799832806609265699u, 58}, { 0, 144680347722973698u, 35186523766912u, 54}, { 0, 289360693332018180u, 2324376172109952u, 54}, { 0, 578721384550107144u, 8798241554560u, 54}, { 0, 1157442766986285072u, 8798248895488u, 54}, { 0, 2314885531858640928u, 4400202383872u, 54}, { 0, 4629771061603352640u, 9223513925395025944u, 54}, { 0, 2113929216u, 9799832806609265699u, 58}, { 0, 541165879296u, 8623489186u, 58}, { 0, 144680869662163458u, 211174972989440u, 54}, { 0, 289361198158447620u, 422349979521024u, 54}, { 0, 578721855151015944u, 8798248898560u, 54}, { 0, 1157443169136152592u, 8798248895488u, 54}, { 0, 2314885797106425888u, 176196872635408u, 54}, { 0, 4629771053046972480u, 864693334524825672u, 54}, { 0, 541165879296u, 8623489186u, 58}, { 0, 138538465099776u, 1152923704242602112u, 58}, { 0, 144814486094742018u, 87961467109376u, 54}, { 0, 289490433724384260u, 35184640557184u, 54}, { 0, 578842328983668744u, 17592320295040u, 54}, { 0, 1157546119502237712u, 1152930300767010944u, 54}, { 0, 2314953700539375648u, 2199090397312u, 54}, { 0, 4629768862613651520u, 71477114437768u, 54}, { 0, 138538465099776u, 1152923704242602112u, 58}, { 0, 35465847065542656u, 145139880169537u, 58}, { 0, 179020292834853378u, 35186523766912u, 54}, { 0, 322574738604164100u, 71468792942848u, 54}, { 0, 609683630142785544u, 2305880667756036608u, 54}, { 0, 1183901413220028432u, 4400194519168u, 54}, { 0, 2332336979374514208u, 3458905259899093120u, 54}, { 0, 4629208111683485760u, 123149731628032u, 54}, { 0, 35465847065542656u, 145139880169537u, 58}, { 0, 9079256848778919936u, 145139880169537u, 58}, { 0, 8935706818303361538u, 22548582572802u, 53}, { 0, 8792156787827803140u, 9223443505379549185u, 53}, { 0, 8505056726876686344u, 281492694499337u, 53}, { 0, 7930856604974452752u, 3298862563377u, 53}, { 0, 6782456361169985568u, 576478370259304706u, 52}, { 0, 4485655873561051200u, 17715716818948u, 53}, { 0, 9079256848778919936u, 145139880169537u, 58} };
|
||||
static struct magic_t bishopMagic[64] = {{ 0, 18049651735527936u, 450387485566996608u, 58}, { 0, 70506452091904u, 292736183996786692u, 59}, { 0, 275415828992u, 15764799564551168u, 59}, { 0, 1075975168u, 633872748382213u, 59}, { 0, 38021120u, 565217696169988u, 59}, { 0, 8657588224u, 571754770663745u, 59}, { 0, 2216338399232u, 564393097077764u, 59}, { 0, 567382630219776u, 4647745618985488384u, 58}, { 0, 4620710844295151618u, 151878701417476u, 59}, { 0, 18049651735527428u, 9605338177241346u, 59}, { 0, 70506452221962u, 9223495332494639169u, 59}, { 0, 275449643028u, 9223446873539363073u, 59}, { 0, 9733406760u, 572125077307650u, 59}, { 0, 2216342585424u, 2305915585839759872u, 59}, { 0, 567382630203424u, 576608090351732752u, 59}, { 0, 145249953336262720u, 154635866112u, 59}, { 0, 2310355422147510788u, 18084841411575936u, 59}, { 0, 4620710844295021576u, 4516828160236544u, 59}, { 0, 18049651768822288u, 9225629402954698769u, 57}, { 0, 70515108615202u, 2251975928381472u, 57}, { 0, 2491752130628u, 4611967513004083360u, 57}, { 0, 567383701868552u, 281550407600400u, 57}, { 0, 145249953332076560u, 6920908969368159235u, 59}, { 0, 290499906664153120u, 703829253328896u, 59}, { 0, 1155177711057110024u, 1143497474336784u, 59}, { 0, 2310355422114220048u, 317758928062976u, 59}, { 0, 4620710852818505760u, 1155175507755663872u, 57}, { 0, 18051867805491776u, 5764897794523414784u, 55}, { 0, 637888545440770u, 4785350622855232u, 55}, { 0, 145250227678349316u, 570096847160448u, 57}, { 0, 290499905592496136u, 9223519374650978432u, 59}, { 0, 580999811184992272u, 1153062792136247296u, 59}, { 0, 577588851267340304u, 4521260600263744u, 59}, { 0, 1155177702534680608u, 3124159228940288u, 59}, { 0, 2310357604126171200u, 74775381671976u, 57}, { 0, 4621278158205894656u, 4647717016617615488u, 55}, { 0, 163299467632837120u, 9277415507529629952u, 55}, { 0, 290570138238321666u, 4503917455229184u, 57}, { 0, 580999536840804356u, 36600586291970176u, 59}, { 0, 1161999073681608712u, 2261146400784640u, 59}, { 0, 288793334762704928u, 1127136992038912u, 59}, { 0, 577586669525409856u, 1695455559819264u, 59}, { 0, 1155736297594175488u, 13880314514376704u, 57}, { 0, 2455587783297728512u, 144397496285665280u, 57}, { 0, 4911175566587199488u, 4612011478231285824u, 57}, { 0, 598979094172140032u, 9042384708960320u, 57}, { 0, 1161928841569502210u, 18876832271040768u, 59}, { 0, 2323857683139004420u, 1127275689020928u, 59}, { 0, 144117404414255168u, 72576638388224u, 59}, { 0, 288234808828510208u, 720646618495844352u, 59}, { 0, 720587004756099072u, 146371669538381824u, 59}, { 0, 1441174018093744128u, 11538239838684184576u, 59}, { 0, 2882348034073559040u, 9223975260183924736u, 59}, { 0, 5764695518391435264u, 4899987047395164192u, 59}, { 0, 2305878262439739904u, 3461051790072611360u, 59}, { 0, 4611756524879479810u, 72624959419465760u, 59}, { 0, 567382630219776u, 4647745618985488384u, 58}, { 0, 1134765260406784u, 2312598961229660688u, 59}, { 0, 2832480465846272u, 10376295759300608386u, 59}, { 0, 5667157807464448u, 1152930369692107270u, 59}, { 0, 11333774449049600u, 1152930369692107270u, 59}, { 0, 22526811443298304u, 36421940281888u, 59}, { 0, 9024825867763712u, 151878701417476u, 59}, { 0, 18049651735527936u, 450387485566996608u, 58} };
|
||||
@ -1,4 +1,3 @@
|
||||
#include <ctype.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
#include <librsvg/rsvg.h>
|
||||
@ -8,7 +7,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <chess/types.h>
|
||||
#include "move.h"
|
||||
#include <chess/move.h>
|
||||
#include <chess/bitboard.h>
|
||||
|
||||
#define drawPiece(file, rank, piece) do { \
|
||||
@ -179,43 +178,7 @@ static void app_activate(GApplication *app, gpointer data) {
|
||||
static RsvgHandle *piecesSvg[16];
|
||||
static uint_least64_t board[2 * PIECES_LENGTH] = {};
|
||||
static struct gameState_t gameState = {board, WHITE, {{true, true}, {true, true}}, 0, NOT_SELECTED};
|
||||
{
|
||||
struct piece_t piece;
|
||||
const char startFEN[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
uint_least8_t field = 0;
|
||||
for(const char *c = startFEN; *c != ' '; ++c) {
|
||||
switch(tolower(*c)) {
|
||||
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(*c)) {
|
||||
field += *c - '0';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(isalpha(*c)) piece.color = isupper(*c);
|
||||
bitboardSet(board, piece, field);
|
||||
++field;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
static struct move_t moves[TOTAL_BOARD_SIZE];
|
||||
static struct drawData_t drawData = {piecesSvg, &gameState, NOT_SELECTED, moves, 0, NOT_SELECTED};
|
||||
|
||||
@ -282,7 +282,9 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece
|
||||
movePawn(addmoveCtx, piece.color, src, dst, promotion, 0);
|
||||
if(src / BOARD_SIZE == (piece.color == WHITE ? BOARD_SIZE - 2 : 1)) {
|
||||
dst += DIRECTION_MODIFIER[pawnDirection];
|
||||
movePawn(addmoveCtx, piece.color, src, dst, promotion, FUTURE_EN_PASSANT);
|
||||
if(!bitboardGetAllPieces(board, dst)) {
|
||||
movePawn(addmoveCtx, piece.color, src, dst, promotion, FUTURE_EN_PASSANT);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
#include <bits/stdint-least.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;
|
||||
@ -73,3 +74,61 @@ struct piece_t pieceAtField(const uint_least64_t *board, uint_least8_t i) {
|
||||
return pieceError;
|
||||
}
|
||||
}
|
||||
|
||||
struct gameState_t newGameState(uint_least64_t *board, char *FEN) {
|
||||
const char startFEN[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
|
||||
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, ++field) {
|
||||
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.color = *++FEN == 'w' ? WHITE : BLACK;
|
||||
struct castle_t canCastle[2] = {};
|
||||
FEN += 2;
|
||||
if(*FEN == '-') ++FEN;
|
||||
else {
|
||||
for(; *FEN != ' '; ++FEN) {
|
||||
struct castle_t *playerCastle = canCastle + (isupper(*FEN) ? WHITE : BLACK);
|
||||
if(tolower(*FEN) == 'k') playerCastle->shortCastle = true;
|
||||
else playerCastle->longCastle = true;
|
||||
}
|
||||
}
|
||||
if(*++FEN == '-') ++FEN;
|
||||
else {
|
||||
gameState.enPassantTo = *FEN++ - 'a';
|
||||
gameState.enPassantTo += (BOARD_SIZE - *FEN++) * BOARD_SIZE;
|
||||
}
|
||||
gameState.halfMoveCounter = atoi(++FEN);
|
||||
return gameState;
|
||||
}
|
||||
@ -11,7 +11,7 @@ uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t
|
||||
for(uint_least8_t j = 0; j < directionLength; ++j) {
|
||||
const int_least8_t modifier = DIRECTION_MODIFIER[direction[j]];
|
||||
for(uint_least8_t currentField = field + modifier, i = 0;
|
||||
i < localDirectionOffset[direction[j]] - 1; ++i, currentField += modifier) {
|
||||
i < localDirectionOffset[direction[j]]; ++i, currentField += modifier) {
|
||||
movementMask = bitsetSet(movementMask, currentField);
|
||||
if(bitsetGet(blockMask, currentField)) break;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
#include "chess/types.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <chess/bitboard.h>
|
||||
|
||||
@ -13,8 +13,8 @@ void printerull(FILE *file, unsigned long long num) {
|
||||
|
||||
// for debugging
|
||||
void printPieceMask(uint_least64_t mask) {
|
||||
for(uint_least8_t i = 0; i < sizeof mask; ++i, mask >>= CHAR_BIT) {
|
||||
for(uint_least8_t j = 0; j < CHAR_BIT; ++j) {
|
||||
for(uint_least8_t i = 0; i < BOARD_SIZE; ++i, mask >>= BOARD_SIZE) {
|
||||
for(uint_least8_t j = 0; j < BOARD_SIZE; ++j) {
|
||||
printf("%d ", bitsetGet(mask, j));
|
||||
}
|
||||
printf("\n");
|
||||
@ -56,7 +56,6 @@ static bool tryMagicNum(uint_least8_t field, struct magic_t *magic, uint_least64
|
||||
const uint_least64_t i = (pieceArrangement * magicNumber) >> shift;
|
||||
const uint_least64_t storedAttack = attackTable[i];
|
||||
const uint_least64_t calcAttack = preClacAttack[j];
|
||||
//assert(slidingMovementMask(direction, 4, field, pieceArrangement) == calcAttack);
|
||||
if(storedAttack != UINT_LEAST64_MAX && storedAttack != calcAttack) {
|
||||
validMagic = false;
|
||||
break;
|
||||
@ -79,14 +78,15 @@ static void initMagicField(uint_least64_t *attackMask, struct magic_t *magicTabl
|
||||
const uint_least8_t *direction, uint_least8_t directionLength) {
|
||||
struct magic_t *magic = magicTable + field;
|
||||
attackMask += field * MAX_SIZE;
|
||||
magic->mask = slidingMovementMask(direction, directionLength, field, 0);
|
||||
|
||||
/* & 0x7e... because we dont care about the outer ring of pieces, because the pieces are threated as
|
||||
enemy pieces. */
|
||||
magic->mask = slidingMovementMask(direction, directionLength, field, 0) & 0x7e7e7e7e7e7e7e7e;
|
||||
magic->shift = 64 - MAX_BITS - 1;
|
||||
uint_least64_t pieceArrangement = 0;
|
||||
size_t i = 0;
|
||||
do {
|
||||
assert(i < MAX_SIZE);
|
||||
attackMask[i] = slidingMovementMask(direction, directionLength, field, pieceArrangement);
|
||||
assert(countOnes(attackMask[i]) <= 12);
|
||||
pieceArrangement = (pieceArrangement - magic->mask) & magic->mask;
|
||||
++i;
|
||||
} while(pieceArrangement != 0);
|
||||
|
||||
Reference in New Issue
Block a user