#include #include #include #include #include #include #include #include #include #include #include #define MAX_BITS 12 #define MAX_SIZE (1 << MAX_BITS) #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() { return rand_64() & rand_64() & rand_64(); } static uint_least8_t countOnes(uint_least64_t n) { int count = 0; while (n != 0) { n = n & (n - 1); count++; } return count; } static void printerMagic(FILE *file, struct magic_t magic) { fprintf(file, "{ 0, %" PRIuLEAST64 "u, %" PRIuLEAST64 "u, %" PRIuLEAST8 "}", magic.mask, magic.magicNumber, magic.shift); } static bool tryMagicNum(uint_least8_t field, struct magic_t *magic, uint_least64_t magicNumber, 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; for(uint_least8_t shift = magic->shift + 1;; ++shift) { uint_least64_t attackTable[MAX_SIZE]; for(size_t i = 0; i < LENGTH(attackTable); ++i) { attackTable[i] = UINT_LEAST64_MAX; } bool validMagic = true; uint_least64_t pieceArrangement = 0; size_t j = 0; do { const uint_least64_t i = (pieceArrangement * magicNumber) >> shift; const uint_least64_t storedAttack = attackTable[i]; const uint_least64_t calcAttack = preClacAttack[j]; if(storedAttack != UINT_LEAST64_MAX && storedAttack != calcAttack) { validMagic = false; break; } attackTable[i] = calcAttack; pieceArrangement = (pieceArrangement - magic->mask) & magic->mask; ++j; } while(pieceArrangement != 0); if(validMagic) { magic->shift = shift; magic->magicNumber = magicNumber; usedMagic = true; } else break; } return usedMagic; } static void initMagicField(uint_least64_t *attackMask, struct magic_t *magicTable, uint_least8_t field, const uint_least8_t *direction, uint_least8_t directionLength) { struct magic_t *magic = magicTable + field; attackMask += field * MAX_SIZE; /* & 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 { attackMask[i] = slidingMovementMask(direction, directionLength, field, pieceArrangement); pieceArrangement = (pieceArrangement - magic->mask) & magic->mask; ++i; } while(pieceArrangement != 0); } int main() { 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, ROOK_DIRECTION, LENGTH(ROOK_DIRECTION)); initMagicField(bishopAttackMask, bishopMagicTable, field, BISHOP_DIRECTION, LENGTH(BISHOP_DIRECTION)); } srand(time(NULL)); for(;;) { uint_least64_t magicNumber = randFewBits(); bool isMagic = false; for(uint_least8_t field = 0; field < TOTAL_BOARD_SIZE; ++field) { { struct magic_t *magic = rookMagicTable + field; isMagic |= tryMagicNum(field, magic, magicNumber, rookAttackMask, ROOK_DIRECTION); } { struct magic_t *magic = bishopMagicTable + field; isMagic |= tryMagicNum(field, magic, magicNumber, bishopAttackMask, BISHOP_DIRECTION); } } if(isMagic) { FILE *file = fopen("src/chess/magicNumber.h", "w"); if (file == NULL) { perror("Error opening file"); return 1; } fprintf(file, "#include \n"); fdefineArray(file, "static struct magic_t rookMagic", printerMagic, rookMagicTable); fdefineArray(file, "static struct magic_t bishopMagic", printerMagic, bishopMagicTable); fclose(file); } } }