gen magic Number

This commit is contained in:
2024-03-17 10:41:26 +01:00
parent e21fabb94c
commit 2e813e5744
13 changed files with 376 additions and 103 deletions

145
src/findMagicNumber.c Normal file
View File

@ -0,0 +1,145 @@
#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>
#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, "{ NULL, %" PRIuLEAST64 ", %" PRIuLEAST64 ", %" 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) {
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 pieceArangement = 0;
size_t j = 0;
do {
const uint_least32_t i = (pieceArangement * 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;
pieceArangement = (pieceArangement - magic->mask) & magic->mask;
++j;
} while(pieceArangement != 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;
magic->mask = slidingMovementMask(direction, directionLength, field, 0);
magic->shift = 64 - MAX_BITS - 1;
uint_least64_t pieceArangement = 0;
size_t i = 0;
do {
attackMask[i] = slidingMovementMask(direction, directionLength, field, pieceArangement);
pieceArangement = (pieceArangement - magic->mask) & magic->mask;
++i;
} while(pieceArangement != 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));
}
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);
}
{
struct magic_t *magic = bishopMagicTable + field;
isMagic |= tryMagicNum(field, magic, magicNumber, bishopAttackMask);
}
}
if(isMagic) {
FILE *file = fopen("src/chess/magicNumber.h", "w");
if (file == NULL) {
perror("Error opening file");
return 1;
}
fprintf(file, "#include <chess/types.h>\n");
fdefineArray(file, "static struct magic_t rookMagic", printerMagic, rookMagicTable);
fdefineArray(file, "static struct magic_t bishopMagic", printerMagic, bishopMagicTable);
fclose(file);
}
}
}