not working: check
This commit is contained in:
@ -8,7 +8,7 @@ file(GLOB LIB_SOURCES "lib/chess/*.c")
|
||||
add_executable(genMoveConsts src/generateCode/moveConsts.c ${LIB_SOURCES})
|
||||
add_custom_command(
|
||||
OUTPUT moveConsts.h # Output file from code generation
|
||||
COMMAND genMoveConsts > src/chess/generated/moveConsts.h
|
||||
COMMAND genMoveConsts > include/chess/generated/moveConsts.h
|
||||
DEPENDS genMoveConsts # Depends on the code generation executable
|
||||
)
|
||||
add_custom_target(generateCode DEPENDS moveConsts.h)
|
||||
|
||||
10
include/chess/magic.h
Normal file
10
include/chess/magic.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef CHESS_MAGIC_H
|
||||
#define CHESS_MAGIC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <chess/types.h>
|
||||
|
||||
uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength,
|
||||
uint_least8_t field, uint_least64_t blockMask);
|
||||
uint_least64_t* getMagicAttackPtr(const uint_least64_t mask, const struct magic_t magic);
|
||||
#endif
|
||||
@ -5,7 +5,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define BOARD_SIZE 8
|
||||
#define TOTAL_BOARD_SIZE BOARD_SIZE * BOARD_SIZE
|
||||
#define TOTAL_BOARD_SIZE (BOARD_SIZE * BOARD_SIZE)
|
||||
#define LENGTH(array) (sizeof array / sizeof *array)
|
||||
#define NOT_SELECTED UINT_LEAST8_MAX
|
||||
|
||||
|
||||
24
lib/chess/magic.c
Normal file
24
lib/chess/magic.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include <stdint.h>
|
||||
#include <chess/types.h>
|
||||
#include <chess/generated/moveConsts.h>
|
||||
#include <chess/bitboard.h>
|
||||
|
||||
uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength,
|
||||
uint_least8_t field, uint_least64_t blockMask) {
|
||||
defineDirectionOffset;
|
||||
const uint_least8_t *localDirectionOffset = DIRECTION_OFFSET + field * DIRECTION_LENGTH;
|
||||
uint_least64_t movementMask = 0;
|
||||
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) {
|
||||
movementMask = bitsetSet(movementMask, currentField);
|
||||
if(bitsetGet(blockMask, currentField)) break;
|
||||
}
|
||||
}
|
||||
return movementMask;
|
||||
}
|
||||
|
||||
uint_least64_t* getMagicAttackPtr(const uint_least64_t mask, const struct magic_t magic) {
|
||||
return magic.attackTable + ((mask * magic.magicNumber) >> magic.shift);
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
#include <bits/stdint-least.h>
|
||||
#include <ctype.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <cairo.h>
|
||||
@ -47,7 +46,7 @@ static void selectCircle(cairo_t *cr, const struct drawData_t *drawData, uint_le
|
||||
}
|
||||
|
||||
static struct gameState_t userMove(struct gameState_t gameState, struct move_t move) {
|
||||
gameState = makeMove(gameState, turn, move);
|
||||
gameState = makeMove(gameState, move);
|
||||
#ifdef NO_COMPUTER
|
||||
turn = !turn;
|
||||
#else
|
||||
@ -179,7 +178,7 @@ static void app_activate(GApplication *app, gpointer data) {
|
||||
GtkWindow *window = GTK_WINDOW(gtk_window_new());
|
||||
static RsvgHandle *piecesSvg[16];
|
||||
static uint_least64_t board[2 * PIECES_LENGTH] = {};
|
||||
static struct gameState_t gameState = {board, {{true, true}, {true, true}}, 0, NOT_SELECTED};
|
||||
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";
|
||||
|
||||
173
src/chess/move.c
173
src/chess/move.c
@ -1,15 +1,19 @@
|
||||
#include <bits/stdint-least.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <chess/types.h>
|
||||
#include "move.h"
|
||||
#include <chess/bitboard.h>
|
||||
#include "generated/moveConsts.h"
|
||||
#include <chess/generated/moveConsts.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "magicNumber.h"
|
||||
#include <chess/magic.h>
|
||||
|
||||
#define trailingBits(num) __builtin_ctzll(num)
|
||||
|
||||
struct addMoveCtx_t {
|
||||
uint_least64_t *board;
|
||||
struct gameState_t gameState;
|
||||
struct move_t *moves;
|
||||
uint_least8_t *movesLength;
|
||||
};
|
||||
@ -21,6 +25,38 @@ static uint_least8_t getDirectionOffset(uint_least8_t field, uint_least8_t direc
|
||||
return DIRECTION_OFFSET[field * DIRECTION_LENGTH + direction];
|
||||
}
|
||||
|
||||
static uint_least8_t getMagicSize(const struct magic_t magic) {
|
||||
return 1 << (64 - magic.shift);
|
||||
}
|
||||
|
||||
static size_t getTotalMagicSize(const struct magic_t *magic) {
|
||||
size_t size = 0;
|
||||
for(uint_least8_t i = 0; i < TOTAL_BOARD_SIZE; ++i) {
|
||||
size += getMagicSize(magic[i]);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void initMagicTable() {
|
||||
size_t size = getTotalMagicSize(rookMagic) + getTotalMagicSize(bishopMagic);
|
||||
uint_least64_t *attackTable = malloc(size * sizeof *attackTable);
|
||||
if(attackTable == NULL) {
|
||||
perror("failed to allocate memory: ");
|
||||
exit(1);
|
||||
}
|
||||
for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
||||
struct magic_t *magic = rookMagic + field;
|
||||
attackTable += getMagicSize(*magic);
|
||||
magic->attackTable = attackTable;
|
||||
uint_least64_t pieceArangement = 0;
|
||||
do { // https://stackoverflow.com/questions/7277554/what-is-a-good-way-to-iterate-a-number-through-all-the-possible-values-of-a-mask
|
||||
const uint_least64_t attackMask = slidingMovementMask(ROOK_DIRECTION, LENGTH(ROOK_DIRECTION), field, pieceArangement);
|
||||
*getMagicAttackPtr(pieceArangement, *magic) = attackMask;
|
||||
pieceArangement = (pieceArangement - magic->mask) & magic->mask;
|
||||
} while(pieceArangement != 0);
|
||||
}
|
||||
}
|
||||
|
||||
static uint_least8_t getCapturePos(uint_least8_t src, uint_least8_t dst, uint_least8_t spezialMove) {
|
||||
if(spezialMove != EN_PASSANT) return dst;
|
||||
const uint_least8_t file = dst % 8;
|
||||
@ -28,21 +64,76 @@ static uint_least8_t getCapturePos(uint_least8_t src, uint_least8_t dst, uint_le
|
||||
return rank * BOARD_SIZE + file;
|
||||
}
|
||||
|
||||
static bool inCheck(uint_least64_t *board, uint_least8_t field, bool color) {
|
||||
defineKnightCheck;
|
||||
defineKingCheck;
|
||||
definePawnCheck;
|
||||
const struct piece_t knight = {KNIGHT, !color};
|
||||
const struct piece_t pawn = {PAWN, !color};
|
||||
const struct piece_t king = {KING, !color};
|
||||
return bitboardGetMask(board, knight) & KNIGHT_CHECK[field] ||
|
||||
bitboardGetMask(board, pawn) & PAWN_CHECK[2 * field + color] ||
|
||||
bitboardGetMask(board, king) & KING_CHECK[field];
|
||||
static bool checkMagic(const uint_least64_t *board, const struct piece_t attackPiece,
|
||||
const struct magic_t *magic, const uint_least64_t kingMask) {
|
||||
uint_least8_t attackerField;
|
||||
for(uint_least64_t attackerMask = bitboardGetMask(board, attackPiece); attackerMask != 0;
|
||||
attackerMask = bitsetClear(attackerMask, attackerField)) {
|
||||
attackerField = trailingBits(attackerMask);
|
||||
const struct magic_t magicField = magic[attackerField];
|
||||
const uint_least64_t checkMask = *getMagicAttackPtr(bitboardMaskAllPieces(board) & magicField.mask, magicField);
|
||||
if(checkMask & kingMask) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkSimpleLookup(const uint_least64_t *board, const uint_least8_t field, const bool color) {
|
||||
defineKnightCheck;
|
||||
defineKingCheck;
|
||||
definePawnCheck;
|
||||
const struct piece_t knight = {KNIGHT, !color};
|
||||
const struct piece_t pawn = {PAWN, !color};
|
||||
const struct piece_t king = {KING, !color};
|
||||
return bitboardGetMask(board, knight) & KNIGHT_CHECK[field] ||
|
||||
bitboardGetMask(board, pawn) & PAWN_CHECK[2 * field + color] ||
|
||||
bitboardGetMask(board, king) & KING_CHECK[field];
|
||||
}
|
||||
|
||||
static bool inCheck(const uint_least64_t *board, const uint_least64_t kingMask, const bool color) {
|
||||
const struct piece_t rook = {ROOK, !color};
|
||||
const struct piece_t bishop = {BISHOP, !color};
|
||||
const struct piece_t queen = {QUEEN, !color};
|
||||
uint_least8_t field;
|
||||
for(uint_least64_t mask = kingMask; mask != 0; mask = bitsetClear(mask, field)) {
|
||||
field = trailingBits(mask);
|
||||
if(checkSimpleLookup(board, field, color)) return true;
|
||||
}
|
||||
return checkMagic(board, rook, rookMagic, kingMask) || checkMagic(board, bishop, bishopMagic, kingMask) ||
|
||||
checkMagic(board, queen, rookMagic, kingMask) || checkMagic(board, queen, bishopMagic, kingMask);
|
||||
}
|
||||
|
||||
static uint_least8_t getCastleRankI(bool color) {
|
||||
if(color == WHITE) {
|
||||
return (BOARD_SIZE - 1) * BOARD_SIZE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void castleMoveRook(uint_least64_t *board, uint_least8_t spezialMove, bool color, bool undo) {
|
||||
if(spezialMove == SHORT_CASTLE || spezialMove == LONG_CASTLE) {
|
||||
const uint_least8_t rookSrc = getCastleRankI(color) + (spezialMove == SHORT_CASTLE ? BOARD_SIZE - 1 : 0);
|
||||
const uint_least8_t rookDst = getCastleRankI(color) + (spezialMove == SHORT_CASTLE ? 5 : 3);
|
||||
const struct piece_t rook = {ROOK, color};
|
||||
bitboardSet(board, rook, undo ? rookSrc : rookDst);
|
||||
bitboardClear(board, rook, undo ? rookDst : rookSrc);
|
||||
}
|
||||
}
|
||||
|
||||
static void undoMove(uint_least64_t *board, struct move_t move, bool color) {
|
||||
const struct piece_t srcPiece = {move.srcPiece, color};
|
||||
const struct piece_t dstPiece = {move.dstPiece, color};
|
||||
bitboardSet(board, srcPiece, move.src);
|
||||
bitboardClear(board, dstPiece, move.dst);
|
||||
if(move.capturedPiece != NOT_SELECTED) {
|
||||
const struct piece_t piece = {move.capturedPiece, !color};
|
||||
bitboardSet(board, piece, move.dst);
|
||||
}
|
||||
castleMoveRook(board, move.spezialMove, color, true);
|
||||
}
|
||||
|
||||
static void addMove(struct addMoveCtx_t ctx, struct piece_t movedPiece, uint_least8_t src,
|
||||
uint_least8_t dst, uint_least8_t spezialMove) {
|
||||
uint_least64_t *board = ctx.board;
|
||||
uint_least64_t *board = ctx.gameState.board;
|
||||
uint_least8_t *movesLength = ctx.movesLength;
|
||||
uint_least8_t capturedPiece = NOT_SELECTED;
|
||||
const struct piece_t pieceAll = {ALL_PIECES, movedPiece.color};
|
||||
@ -61,9 +152,16 @@ static void addMove(struct addMoveCtx_t ctx, struct piece_t movedPiece, uint_lea
|
||||
}
|
||||
}
|
||||
const struct move_t move = {src, dst, spezialMove, movedPiece.type, movedPiece.type, capturedPiece};
|
||||
ctx.moves[*movesLength] = move;
|
||||
++*movesLength;
|
||||
return;
|
||||
makeMove(ctx.gameState, move);
|
||||
{
|
||||
const bool color = ctx.gameState.color;
|
||||
const struct piece_t king = {KING, color};
|
||||
if(!inCheck(board, bitboardGetMask(board, king), color)) {
|
||||
ctx.moves[*movesLength] = move;
|
||||
++*movesLength;
|
||||
}
|
||||
undoMove(board, move, color);
|
||||
}
|
||||
}
|
||||
|
||||
static void addPreGenMoves(struct addMoveCtx_t ctx, const struct moveDst_t *moveDst,
|
||||
@ -76,7 +174,7 @@ static void addPreGenMoves(struct addMoveCtx_t ctx, const struct moveDst_t *move
|
||||
|
||||
static void moveSliding(const uint_least8_t *direction, uint_least8_t directionLength, struct addMoveCtx_t ctx,
|
||||
uint_least8_t field, struct piece_t movedPiece) {
|
||||
uint_least64_t *board = ctx.board;
|
||||
uint_least64_t *board = ctx.gameState.board;
|
||||
|
||||
for(uint_least8_t j = 0; j < directionLength; ++j) {
|
||||
const int_least8_t modifier = DIRECTION_MODIFIER[direction[j]];
|
||||
@ -93,7 +191,7 @@ static void moveSliding(const uint_least8_t *direction, uint_least8_t directionL
|
||||
|
||||
static void movePawn(struct addMoveCtx_t ctx, bool color, uint_least8_t src, uint_least8_t dst,
|
||||
bool promotion, uint_least8_t spezialMove) {
|
||||
uint_least64_t *board = ctx.board;
|
||||
uint_least64_t *board = ctx.gameState.board;
|
||||
struct move_t *moves = ctx.moves;
|
||||
uint_least8_t *movesLength = ctx.movesLength;
|
||||
const struct piece_t piece = {PAWN, color};
|
||||
@ -112,7 +210,7 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece
|
||||
struct move_t *moves, bool promotion) {
|
||||
uint_least64_t *board = gameState.board;
|
||||
uint_least8_t movesLength = 0;
|
||||
struct addMoveCtx_t addmoveCtx = {board, moves, &movesLength};
|
||||
struct addMoveCtx_t addmoveCtx = {gameState, moves, &movesLength};
|
||||
switch(piece.type) {
|
||||
case KING:
|
||||
{
|
||||
@ -123,10 +221,10 @@ uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece
|
||||
const uint_least8_t rankShift = piece.color == WHITE ? BOARD_SIZE * (BOARD_SIZE - 1) : 0;
|
||||
const uint_least64_t shortCastleMask = (uint_least64_t)0b11 << (5 + rankShift);
|
||||
const uint_least64_t longCastleMask = (uint_least64_t)0b111 << (1 + rankShift);
|
||||
if(canCastle.shortCastle && !(allPiecesMask & shortCastleMask)) {
|
||||
if(canCastle.shortCastle && !(allPiecesMask & shortCastleMask) && !inCheck(board, shortCastleMask, piece.color)) {
|
||||
addMove(addmoveCtx, piece, src, src + 2 * DIRECTION_MODIFIER[EAST], SHORT_CASTLE);
|
||||
}
|
||||
if(canCastle.longCastle && !(allPiecesMask & longCastleMask)) {
|
||||
if(canCastle.longCastle && !(allPiecesMask & longCastleMask) && !inCheck(board, longCastleMask, piece.color)) {
|
||||
addMove(addmoveCtx, piece, src, src + 2 * DIRECTION_MODIFIER[WEST], LONG_CASTLE);
|
||||
}
|
||||
break;
|
||||
@ -212,53 +310,48 @@ static void setCastleInfo(struct castle_t *canCastle, uint_least8_t posOnRank) {
|
||||
}
|
||||
}
|
||||
|
||||
struct gameState_t makeMove(struct gameState_t gameState, bool color, struct move_t move) {
|
||||
struct gameState_t makeMove(struct gameState_t gameState, struct move_t move) {
|
||||
uint_least64_t *board = gameState.board;
|
||||
const uint_least8_t castleRankI[2] = {0, (BOARD_SIZE - 1) * BOARD_SIZE};
|
||||
const struct piece_t srcPiece = {move.srcPiece, color};
|
||||
const struct piece_t dstPiece = {move.dstPiece, color};
|
||||
const struct piece_t srcPiece = {move.srcPiece, gameState.color};
|
||||
const struct piece_t dstPiece = {move.dstPiece, gameState.color};
|
||||
bitboardClear(board, srcPiece, move.src);
|
||||
bitboardSet(board, dstPiece, move.dst);
|
||||
if(move.capturedPiece != NOT_SELECTED) {
|
||||
const struct piece_t capturedPiece = {move.capturedPiece, !color};
|
||||
const struct piece_t capturedPiece = {move.capturedPiece, !gameState.color};
|
||||
bitboardClear(board, capturedPiece, getCapturePos(move.src, move.dst, move.spezialMove));
|
||||
}
|
||||
if(move.spezialMove == SHORT_CASTLE || move.spezialMove == LONG_CASTLE) {
|
||||
const uint_least8_t rookSrc = castleRankI[color] + (move.spezialMove == SHORT_CASTLE ? BOARD_SIZE - 1 : 0);
|
||||
const uint_least8_t rookDst = castleRankI[color] + (move.spezialMove == SHORT_CASTLE ? 5 : 3);
|
||||
const struct piece_t rook = {ROOK, color};
|
||||
bitboardSet(board, rook, rookDst);
|
||||
bitboardClear(board, rook, rookSrc);
|
||||
}
|
||||
castleMoveRook(board, move.spezialMove, gameState.color, false);
|
||||
{
|
||||
struct castle_t *canCastleCurrentPlayer = gameState.canCastle + color;
|
||||
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 - castleRankI[color]);
|
||||
setCastleInfo(canCastleCurrentPlayer, move.src - getCastleRankI(gameState.color));
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
// if the rook is captured
|
||||
struct castle_t *canCastleOther = gameState.canCastle + !color;
|
||||
struct castle_t *canCastleOther = gameState.canCastle + !gameState.color;
|
||||
if(canCastleOther->longCastle || canCastleOther->shortCastle) {
|
||||
setCastleInfo(canCastleOther, move.dst - castleRankI[!color]);
|
||||
setCastleInfo(canCastleOther, move.dst - getCastleRankI(!gameState.color));
|
||||
}
|
||||
}
|
||||
{
|
||||
const int_least8_t dist = (int_least8_t)move.dst - (int_least8_t)move.src;
|
||||
gameState.enPassantTo = FUTURE_EN_PASSANT ? move.src + dist / 2 : NOT_SELECTED;
|
||||
}
|
||||
++gameState.halfMoveCounter;
|
||||
if(move.capturedPiece != NOT_SELECTED || srcPiece.type == PAWN) gameState.halfMoveCounter = 0;
|
||||
else ++gameState.halfMoveCounter;
|
||||
gameState.color = !gameState.color;
|
||||
return gameState;
|
||||
}
|
||||
|
||||
struct gameState_t computerMove(struct gameState_t gameState) {
|
||||
struct move_t moves[MAX_VALID_MOVES];
|
||||
validMoves(gameState, false, moves);
|
||||
return makeMove(gameState, BLACK, moves[0]);
|
||||
return makeMove(gameState, moves[0]);
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ struct move_t {
|
||||
|
||||
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.
|
||||
@ -37,7 +38,7 @@ uint_least8_t validMoves(struct gameState_t gameState, bool color, struct move_t
|
||||
uint_least8_t pieceValidMoves(struct gameState_t gameState, struct piece_t piece, uint_least8_t src,
|
||||
struct move_t *moves, bool promotion);
|
||||
|
||||
struct gameState_t makeMove(struct gameState_t gameState, bool color, struct move_t move);
|
||||
struct gameState_t makeMove(struct gameState_t gameState, struct move_t move);
|
||||
struct gameState_t computerMove(struct gameState_t gameState);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
#include <chess/types.h>
|
||||
#include <bits/stdint-least.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
#include "chess/generated/moveConsts.h"
|
||||
#include <chess/bitboard.h>
|
||||
#include <chess/print.h>
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include <chess/magic.h>
|
||||
#include <chess/generated/moveConsts.h>
|
||||
|
||||
#define MAX_BITS 12
|
||||
#define MAX_SIZE (1 << MAX_BITS)
|
||||
@ -35,27 +35,12 @@ static uint_least8_t countOnes(uint_least64_t n) {
|
||||
}
|
||||
|
||||
static void printerMagic(FILE *file, struct magic_t magic) {
|
||||
fprintf(file, "{ NULL, %" PRIuLEAST64 ", %" PRIuLEAST64 ", %" PRIuLEAST8 "}", magic.mask, magic.magicNumber, magic.shift);
|
||||
fprintf(file, "{ 0, %" PRIuLEAST64 "u, %" PRIuLEAST64 "u, %" PRIuLEAST8 "}", magic.mask, magic.magicNumber, magic.shift);
|
||||
}
|
||||
|
||||
static uint_least64_t slidingMovementMask(const uint_least8_t *direction, uint_least8_t directionLength,
|
||||
uint_least8_t field, uint_least64_t blockMask) {
|
||||
defineDirectionOffset;
|
||||
const uint_least8_t *localDirectionOffset = DIRECTION_OFFSET + field * DIRECTION_LENGTH;
|
||||
uint_least64_t movementMask = 0;
|
||||
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]]; ++i, currentField += modifier) {
|
||||
movementMask = bitsetSet(movementMask, currentField);
|
||||
if(bitsetGet(blockMask, currentField)) break;
|
||||
}
|
||||
}
|
||||
return movementMask;
|
||||
}
|
||||
|
||||
static bool tryMagicNum(uint_least8_t field, struct magic_t *magic, uint_least64_t magicNumber,
|
||||
const uint_least64_t *preClacAttack) {
|
||||
const uint_least64_t *preClacAttack, const uint_least8_t *direction) {
|
||||
preClacAttack += field * MAX_SIZE;
|
||||
bool usedMagic = false;
|
||||
if(countOnes((magic->mask * magicNumber) & 0xFF00000000000000ULL) < 6) return false;
|
||||
@ -65,20 +50,21 @@ static bool tryMagicNum(uint_least8_t field, struct magic_t *magic, uint_least64
|
||||
attackTable[i] = UINT_LEAST64_MAX;
|
||||
}
|
||||
bool validMagic = true;
|
||||
uint_least64_t pieceArangement = 0;
|
||||
uint_least64_t pieceArrangement = 0;
|
||||
size_t j = 0;
|
||||
do {
|
||||
const uint_least32_t i = (pieceArangement * magicNumber) >> shift;
|
||||
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;
|
||||
}
|
||||
attackTable[i] = calcAttack;
|
||||
pieceArangement = (pieceArangement - magic->mask) & magic->mask;
|
||||
pieceArrangement = (pieceArrangement - magic->mask) & magic->mask;
|
||||
++j;
|
||||
} while(pieceArangement != 0);
|
||||
} while(pieceArrangement != 0);
|
||||
if(validMagic) {
|
||||
magic->shift = shift;
|
||||
magic->magicNumber = magicNumber;
|
||||
@ -95,26 +81,26 @@ static void initMagicField(uint_least64_t *attackMask, struct magic_t *magicTabl
|
||||
attackMask += field * MAX_SIZE;
|
||||
magic->mask = slidingMovementMask(direction, directionLength, field, 0);
|
||||
magic->shift = 64 - MAX_BITS - 1;
|
||||
uint_least64_t pieceArangement = 0;
|
||||
uint_least64_t pieceArrangement = 0;
|
||||
size_t i = 0;
|
||||
do {
|
||||
attackMask[i] = slidingMovementMask(direction, directionLength, field, pieceArangement);
|
||||
pieceArangement = (pieceArangement - magic->mask) & magic->mask;
|
||||
assert(i < MAX_SIZE);
|
||||
attackMask[i] = slidingMovementMask(direction, directionLength, field, pieceArrangement);
|
||||
assert(countOnes(attackMask[i]) <= 12);
|
||||
pieceArrangement = (pieceArrangement - magic->mask) & magic->mask;
|
||||
++i;
|
||||
} while(pieceArangement != 0);
|
||||
} while(pieceArrangement != 0);
|
||||
}
|
||||
|
||||
int main() {
|
||||
const uint_least8_t rookDirection[] = {NORTH, SOUTH, EAST, WEST};
|
||||
const uint_least8_t bishopDirection[] = {NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST};
|
||||
struct magic_t rookMagicTable[TOTAL_BOARD_SIZE] = {};
|
||||
struct magic_t bishopMagicTable[TOTAL_BOARD_SIZE] = {};
|
||||
uint_least64_t *attackMask = malloc(ATTACK_TABLE_LENGTH * sizeof *attackMask);
|
||||
uint_least64_t *rookAttackMask = attackMask;
|
||||
uint_least64_t *bishopAttackMask = attackMask + TOTAL_BOARD_SIZE * MAX_SIZE;
|
||||
for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
||||
initMagicField(rookAttackMask, rookMagicTable, field, rookDirection, LENGTH(rookDirection));
|
||||
initMagicField(bishopAttackMask, bishopMagicTable, field, bishopDirection, LENGTH(bishopDirection));
|
||||
initMagicField(rookAttackMask, rookMagicTable, field, ROOK_DIRECTION, LENGTH(ROOK_DIRECTION));
|
||||
initMagicField(bishopAttackMask, bishopMagicTable, field, BISHOP_DIRECTION, LENGTH(BISHOP_DIRECTION));
|
||||
}
|
||||
srand(time(NULL));
|
||||
for(;;) {
|
||||
@ -123,11 +109,11 @@ int main() {
|
||||
for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
||||
{
|
||||
struct magic_t *magic = rookMagicTable + field;
|
||||
isMagic |= tryMagicNum(field, magic, magicNumber, rookAttackMask);
|
||||
isMagic |= tryMagicNum(field, magic, magicNumber, rookAttackMask, ROOK_DIRECTION);
|
||||
}
|
||||
{
|
||||
struct magic_t *magic = bishopMagicTable + field;
|
||||
isMagic |= tryMagicNum(field, magic, magicNumber, bishopAttackMask);
|
||||
isMagic |= tryMagicNum(field, magic, magicNumber, bishopAttackMask, BISHOP_DIRECTION);
|
||||
}
|
||||
}
|
||||
if(isMagic) {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
#include <stdio.h>
|
||||
#include <chess/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <chess/bitboard.h>
|
||||
@ -31,7 +30,10 @@ int main() {
|
||||
printf("#ifndef CHESS_GENERATED_MOVE_CONSTS_H\n"
|
||||
"#define CHESS_GENERATED_MOVE_CONSTS_H\n"
|
||||
"#include <stdint.h>\n"
|
||||
"#include <chess/types.h>\n");
|
||||
"#include <chess/types.h>\n"
|
||||
"const static uint_least8_t ROOK_DIRECTION[] = {NORTH, SOUTH, EAST, WEST};\n"
|
||||
"const static uint_least8_t BISHOP_DIRECTION[] = {NORTHEAST, NORTHWEST, SOUTHEAST, SOUTHWEST};\n"
|
||||
);
|
||||
uint_least8_t directionOffset[TOTAL_BOARD_SIZE * DIRECTION_LENGTH];
|
||||
for(uint_least16_t field = 0; field < TOTAL_BOARD_SIZE; ++field) {
|
||||
uint_least8_t file = field % BOARD_SIZE;
|
||||
@ -56,7 +58,7 @@ int main() {
|
||||
directionModifier[SOUTHWEST] = directionModifier[SOUTH] + directionModifier[WEST];
|
||||
directionModifier[NORTHEAST] = directionModifier[NORTH] + directionModifier[EAST];
|
||||
directionModifier[NORTHWEST] = directionModifier[NORTH] + directionModifier[WEST];
|
||||
defineArray("const int_least8_t DIRECTION_MODIFIER", printerll, directionModifier);
|
||||
defineArray("const static int_least8_t DIRECTION_MODIFIER", printerll, directionModifier);
|
||||
{
|
||||
uint_least64_t knightCheck[TOTAL_BOARD_SIZE];
|
||||
struct moveDst_t knightMoves[TOTAL_BOARD_SIZE] = {};
|
||||
|
||||
Reference in New Issue
Block a user