Связка, это когда в тройке средняя фигура ограничена в движениях.
По разным причинам.
Если за ней король, то очень сильно.
А если это притом конь, то абсолютно.
Но если не король, то формально фигура может двигаться как хочет. Но это может привести к потере материала.
Только это уже часть игры и большие главы в учебниках.
Вот это связка черной пешки. Она не может двигаться абсолютно
8/7k/6p1/8/8/3B4/2K5/8 w - - 2 1
А это не абсолютно. Пешка может пойти, но потеряется ладья
8/5k1r/6p1/8/8/3B4/2K5/8 w - - 2 1
А это мифическая связка. Пешка может пойти, ладья потеряется, но пешка станет ферзем
8/5k2/8/8/8/3R2pr/2K5/8 w - - 2 1
Поэтому Вам придется двинуться тут очень глубоко с программой. Это сложно. Нужна оценка позиции и граф ходов.
Без этого понятие связки смысла не имеет.
Сейчас я использую такой алгоритм
1. Убираем свои фигуры
2. Ставим ферзя на место своего короля
3. Находим атаки этого ферзя (из таблиц атак)
4. Находим атакуемых врагов.
5. Подставляем на место своего ферзя (короля) тип врага
6. Находим его атаки
7. Пересечение атак - это луч атаки между врагом и своим королем
8. Ставим свои фигуры на место
9. Если на зтом луче есть одна своя фигура, то она связана
Алгоритм в коде
Warning: Spoiler![ Click to expand ][ Click to hide ]
Конечно хотел бы его оптимизировать, может быть есть идеи?
Мои 2 млн позиций в сек просто детский лепет в сравнение с этими ребятами и похоже, что и девчатами.
Их код написанный на си++ даёт 16 млрд в сек, это просто очуметь github.com/ankan-ban/perft_gpu?utm_source=pocket_mylist
Warning: Spoiler![ Click to expand ][ Click to hide ]
Warning: Spoiler![ Click to expand ][ Click to hide ]
связки
Warning: Spoiler![ Click to expand ][ Click to hide ]
P=1, N=2, K=3, B=5, R=6 и Q=7.
При анализе этих чисел проверяется результат piece_type&4,
и если результат ненулевой, это дальнобойная фигура.
Далее, если результат piece_type&1 отличен от нуля, эта фигура ходит по диагонали,
а если результат piece_type&2 ненулевой, то фигура может двигаться вдоль горизонталей/вертикалей.
Warning: Spoiler![ Click to expand ][ Click to hide ]
Принципиального прорыва нет, надо хотя бы на порядок увеличить скорость.
Warning: Spoiler![ Click to expand ][ Click to hide ]
34-16042023perft_final_ver1 —optim3
r4rk1/1pp1qppp/p1np1n2/2b1p1B1/2B1P1b1/P1NP1N2/1PP1QPPP/R4RK1 w - - 0 10
depth=6
2 mNPS, time 00:01:15.125
move:g1h1 nodes:185814143
2 mNPS, time 00:01:01.921
move:c3b5 nodes:155091031
2 mNPS, time 00:00:59.344
move:c3d5 nodes:150408509
2 mNPS, time 00:00:57.781
move:c3a4 nodes:145901696
2 mNPS, time 00:00:54.844
move:c3a2 nodes:139790508
2 mNPS, time 00:00:45.937
move:c3b1 nodes:116929754
2 mNPS, time 00:00:43.641
move:c3d1 nodes:111037907
2 mNPS, time 00:01:30.937
move:f3e5 nodes:232071766
2 mNPS, time 00:01:16.485
move:f3d4 nodes:193771826
2 mNPS, time 00:01:02.875
move:f3h4 nodes:160120978
2 mNPS, time 00:01:00.640
move:f3d2 nodes:153852099
2 mNPS, time 00:00:47.704
move:f3e1 nodes:120878737
2 mNPS, time 00:00:52.250
move:g5f6 nodes:131843920
2 mNPS, time 00:01:03.093
move:g5h6 nodes:160697720
2 mNPS, time 00:01:14.312
move:g5f4 nodes:190475207
2 mNPS, time 00:00:55.922
move:g5h4 nodes:140387576
2 mNPS, time 00:01:07.812
move:g5e3 nodes:169667794
2 mNPS, time 00:01:03.672
move:g5d2 nodes:159717941
2 mNPS, time 00:00:53.312
move:g5c1 nodes:135129087
3 mNPS, time 00:00:05.922
move:c4f7 nodes:15419754
2 mNPS, time 00:01:01.562
move:c4a6 nodes:154993570
2 mNPS, time 00:01:05.563
move:c4e6 nodes:163121291
2 mNPS, time 00:00:58.718
move:c4b5 nodes:148366194
2 mNPS, time 00:00:56.360
move:c4d5 nodes:141887829
2 mNPS, time 00:00:57.375
move:c4b3 nodes:145229052
2 mNPS, time 00:00:57.922
move:c4a2 nodes:145263213
2 mNPS, time 00:00:53.078
move:a1a2 nodes:133922153
2 mNPS, time 00:00:58.344
move:a1b1 nodes:145385666
2 mNPS, time 00:00:55.734
move:a1c1 nodes:138896335
2 mNPS, time 00:00:52.375
move:a1d1 nodes:133298101
2 mNPS, time 00:00:48.828
move:a1e1 nodes:121398772
2 mNPS, time 00:00:58.125
move:f1b1 nodes:146897544
2 mNPS, time 00:01:00.297
move:f1c1 nodes:152755851
2 mNPS, time 00:01:02.953
move:f1d1 nodes:159584922
2 mNPS, time 00:01:03.468
move:f1e1 nodes:159122939
2 mNPS, time 00:01:08.672
move:e2e3 nodes:170109488
2 mNPS, time 00:01:05.766
move:e2d2 nodes:166188430
2 mNPS, time 00:00:55.078
move:e2d1 nodes:140617699
2 mNPS, time 00:00:57.531
move:e2e1 nodes:146804426
2 mNPS, time 00:01:03.937
move:a3a4 nodes:163249972
2 mNPS, time 00:01:11.703
move:d3d4 nodes:181902399
2 mNPS, time 00:00:56.485
move:b2b3 nodes:144074317
2 mNPS, time 00:01:04.328
move:g2g3 nodes:163654893
2 mNPS, time 00:01:09.219
move:h2h3 nodes:176357821
2 mNPS, time 00:01:00.469
move:b2b4 nodes:153651939
2 mNPS, time 00:01:01.734
move:h2h4 nodes:157308368
nodes=6923051137
Время: Часы:0, Минуты: 45, Секунды: 39, Миллисекунды: 406
Гдето я прочитал, что наибольшее количество легальных ходов в шахматной позиции составляет 218 ходов.
Но на вскидку не нашел эту позицию.
Какая она, эта позиция?
Мне оч даже любопытно.
Вот эта позиция
3Q4/1Q4Q1/4Q3/2Q4R/Q4Q2/3Q4/1Q4Rp/1K1BBNNk w - - 0 1
Warning: Spoiler![ Click to expand ][ Click to hide ]
А первая очень очень сомнительна. У черных два хода пешкой всего легальных последних. Жрать ей нечего, у белых весь комплект
Король на h1 под пулями попасть не сможет там.
понял, что мои вычесления линий атак между клетками, необходимо свеси в таблицу.
В таблицы будет находится линия атаки между двумя клетками.
Получается таблица 64 на 64, и ее надо инициализировать в начале программы.
Об этом же написано в CPW
B Шахматной википедии описано, как это сделать.
Я сделал по своему , т.к. эта таблица будет заполнена при запуске проги, то скорость не критична.
1.Сначала заполняем массивы лучей из каждой клетки во все 8 направлений
Warning: Spoiler![ Click to expand ][ Click to hide ]
Буквы в названии Line - указывают направление.
2.Далее перебираем все пары клеток и находим лучи между ними
Warning: Spoiler![ Click to expand ][ Click to hide ]
3.Важно, при нахождении луча между клетками, в виде пересечений двух лучей LineXY - выбрать правильное направление
Warning: Spoiler![ Click to expand ][ Click to hide ]
Лучи должны быть направлены друг к другу, иначе пересечение будет равно нулю.
Warning: Spoiler![ Click to expand ][ Click to hide ]
Для вертикалей и горизонталей не составит труда узнать, равны или нет они для дух клеток.
Для диагоналей и антидиагоналей алгоритм такой.
Всего на доске 15 диагоналей и 15 антидиагоналей
Warning: Spoiler![ Click to expand ][ Click to hide ]
Для наглядности повернем доску влево на 45 градусов
Warning: Spoiler![ Click to expand ][ Click to hide ]
Warning: Spoiler![ Click to expand ][ Click to hide ]
Для быстрого нахождения нужных диагоналей введем два массива
В которых находятся номера диагоналей и антидиагоналей.
Теперь, чтобы узнать на одной диагонали или нет, расположены две клетки, нужно обратится к этим массивам и если индексы совпадают, то на одном
Выше на рисунке один слон на c6 (поле - 18), слон на g2 (поле - 54)
Warning: Spoiler![ Click to expand ][ Click to hide ]
Нет - это не тот путь
Пробовал разные оптимизации участков кода, но хочется скачка, а его пока нет.
Из последнего попробовал последовательность товарища де Брейна (он же де Бройн,он же де Брюйн,он же де Брюин,он же Гоша)
для нахождения самого младшего бита
Попытался поразбираться c PEXT и PDEP
а именно програмно определить поддерживает процессор или нет.
Как следует из Набор инструкций битовой манипуляции - Bit manipulation instruction set эти инструкции входят в набор - BMI2 (набор команд управления битами 2).
POPCNT - подсчет бит - это ABM (Advanced Bit Manipulation), Intel считает POPCNTчастью SSE4.2, а LZCNT- частью BMI1.
Сразу столкнулся с непоняткой - первым делом нужно определить поддерживает ли процессор cpuid.
Для этого нужно проверить бит 21
function TestCPUID: Boolean;
begin
asm
mov Result, 0
Pushfd // Press EFLAGS Stack
POP EAX // Remove EFLAGS
mov ecx, eax
XOR EAX, 200000H // Modify 21st
push eax
POPFD // Put the changed EFLAGS in the extension flag
pushfd
POP EAX // Remove EFLAGS again
XOR EAX, ECX // Judgment Whether
jz @end
mov Result, 1
@end:
end;
end;
Итак у меня поддерживает.
Дальше проверяем поддержку POPCNT - бит 23 и опа ...
Вроде у меня не поддерживает, но протестил вышеупомянутых девочек и мальчиков (у них есть скомпилированные проги в гитхаб)
Видно что у меня поддерживат POPCNT.
Пока не понял, что с этим делать.
Кстати кому интересно можете почитать диссертацию одного товарища, как обойтись без PEXT и PDEP
Warning: Spoiler![ Click to expand ][ Click to hide ]
function IsPextPdepSupported: Boolean;
asm
// Проверка поддержки инструкций PDEP и PEXT на процессоре
// Загрузка значения 0 в регистр EAX для проверки поддержки инструкции PDEP
XOR EAX, EAX
// Выполнение инструкции PDEP с помощью битовой маски 0xAAAA на регистре EAX
MOV EDX, EAX
MOV ECX, $AAAA
DB $66, $0F, $F5, $CA // PDEP EAX, EDX
// Проверка результата выполнения инструкции PDEP
CMP EAX, $AAAA
JNE @NotSupported
// Выполнение инструкции PEXT с помощью битовой маски 0xAAAA на регистре EAX
MOV EDX, EAX
MOV ECX, $AAAA
DB $66, $0F, $F5, $D0 // PEXT EAX, EDX
// Проверка результата выполнения инструкции PEXT
CMP EAX, $AAAA
JNE @NotSupported
// Поддержка инструкций PEXT и PDEP обнаружена
MOV AL, 1
JMP @Exit
@NotSupported:
// Инструкции PEXT и PDEP не поддерживаются
XOR AL, AL
@Exit:
end;
Warning: Spoiler![ Click to expand ][ Click to hide ]
function IsPopcntSupported: Boolean;
asm
// Проверка поддержки инструкции POPCNT на процессоре
// Загрузка значения 0 в регистр EAX для проверки поддержки инструкции POPCNT
XOR EAX, EAX
// Выполнение инструкции POPCNT на регистре EAX
DB $F3, $0F, $B8, $C0 // POPCNT EAX, EAX
// Проверка результата выполнения инструкции POPCNT
TEST EAX, EAX
JZ @NotSupported
// Поддержка инструкции POPCNT обнаружена
MOV AL, 1
JMP @Exit
@NotSupported:
// Инструкция POPCNT не поддерживается
XOR AL, AL
@Exit:
end;
Warning: Spoiler![ Click to expand ][ Click to hide ]
function IsPopcntSupported: Boolean;
asm
// Проверка поддержки инструкции POPCNT на процессоре
// Загрузка значения 0 в регистр EAX для проверки поддержки инструкции POPCNT
XOR EAX, EAX
// Выполнение инструкции POPCNT на регистре EAX
DB $F3, $0F, $B8, $C0 // POPCNT EAX, EAX
// Установка флага CF в 0 после выполнения инструкции POPCNT
CLC
// Проверка флага CF
LAHF
AND AH, 1
JZ @NotSupported
// Поддержка инструкции POPCNT обнаружена
MOV AL, 1
JMP @Exit
@NotSupported:
// Инструкция POPCNT не поддерживается
XOR AL, AL
@Exit:
end;
Fancy Magic и Magic Bitboard являются двумя разными подходами к нахождению атак скользящих фигур в шахматах. Оба метода используют принцип "магических чисел" для эффективного вычисления атаки фигуры на определенные позиции на шахматной доске.
Основное отличие между Fancy Magic и Magic Bitboard заключается в способе организации магических чисел и их применении.
Magic Bitboard:
Magic Bitboard основан на использовании магических чисел и таблицы сдвигов (shift table). Каждая клетка шахматной доски имеет связанный с ней битовый набор (bitboard), где биты представляют наличие или отсутствие фигуры на данной клетке. Затем для каждой скользящей фигуры (такой как ладья, слон или ферзь) вычисляются магические числа, которые позволяют эффективно определить атаки фигуры на различные позиции на доске. При помощи таблицы сдвигов и магических чисел производится быстрое и эффективное вычисление возможных атак фигуры.
Fancy Magic:
Fancy Magic, с другой стороны, представляет собой более совершенный и продвинутый метод для вычисления атак скользящих фигур. Он использует несколько более сложные алгоритмы и структуры данных, чтобы достичь более высокой производительности. Fancy Magic применяет понятие "разорванных индексов" (disjoint indices), которое позволяет эффективно разбить таблицу атаки на несколько меньших таблиц и применять к ним вычисления с помощью битовых операций. Это улучшает кэширование и уменьшает необходимое количество памяти для хранения таблицы атак.
В обоих случаях использование магических чисел и таблиц сдвигов позволяет существенно ускорить вычисления атак скользящих фигур. Fancy Magic может предоставить еще большую эффективность и производительность по сравнению с Magic Bitboard за счет использования более сложных алгоритмов и структур данных.
Вот пример псевдокода, демонстрирующего применение Fancy Magic для вычисления атаки скользящих фигур (например, ладьи) на шахматной доске:
Warning: Spoiler![ Click to expand ][ Click to hide ]
// Определение магических чисел для каждой позиции на доске
magicNumbers = [magicNumber1, magicNumber2, ..., magicNumber64]
// Определение таблицы сдвигов для каждой позиции на доске
shiftTable = [shifts1, shifts2, ..., shifts64]
// Определение таблицы атаки для каждой позиции на доске
attackTable = [attacks1, attacks2, ..., attacks64]
function initializeMagicBitboard() {
for each square in the board {
relevantOccupancy = generateRelevantOccupancy(square)
index = computeMagicIndex(relevantOccupancy, magicNumbers[square])
attackTable[square][index] = computeAttacks(square, relevantOccupancy)
}
}
function generateRelevantOccupancy(square) {
occupancy = 0
relevantSquares = getRelevantSquares(square)
for each relevantSquare in relevantSquares {
if pieceExistsOn(relevantSquare) {
occupancy |= 1 << relevantSquare
}
}
return occupancy
}
function computeMagicIndex(occupancy, magicNumber) {
return (occupancy * magicNumber) >> shiftTable[square]
}
function computeAttacks(square, occupancy) {
// Вычисление атаки фигуры на данной позиции с учетом занятости клеток
// ...
// Выполнение соответствующих операций для вычисления атаки (например, ладьи)
// ...
return attacks
}
// Использование Fancy Magic для вычисления атаки
function getAttackMoves(piece, square, occupancy) {
relevantOccupancy = generateRelevantOccupancy(square)
index = computeMagicIndex(relevantOccupancy, magicNumbers[square])
attacks = attackTable[square][index]
validAttacks = attacks & occupancy
return validAttacks
}
Это примерный псевдокод, который демонстрирует основные шаги Fancy Magic: инициализацию магических чисел и таблиц сдвигов, генерацию релевантной занятости для каждой позиции, вычисление магического индекса, вычисление атаки фигуры с учетом занятости клеток и, наконец, использование Fancy Magic для получения возможных атак. Обратите внимание, что детали реализации Fancy Magic могут отличаться в зависимости от конкретной реализации и используемого языка программирования.
Warning: Spoiler![ Click to expand ][ Click to hide ]
/**
*magicmoves.h
*
*Source file for magic move bitboard generation.
*
*See header file for instructions on usage.
*
*The magic keys are not optimal for all squares but they are very close
*to optimal.
*
*Copyright (C) 2007 Pradyumna Kannan.
*
*This code is provided 'as-is', without any express or implied warranty.
*In no event will the authors be held liable for any damages arising from
*the use of this code. Permission is granted to anyone to use this
*code for any purpose, including commercial applications, and to alter
*it and redistribute it freely, subject to the following restrictions:
*
*1. The origin of this code must not be misrepresented; you must not
*claim that you wrote the original code. If you use this code in a
*product, an acknowledgment in the product documentation would be
*appreciated but is not required.
*
*2. Altered source versions must be plainly marked as such, and must not be
*misrepresented as being the original code.
*
*3. This notice may not be removed or altered from any source distribution.
*/
#include "magicmoves.h"
#ifdef _MSC_VER
#pragma message("MSC compatible compiler detected -- turning off warning 4312,4146")
#pragma warning( disable : 4312)
#pragma warning( disable : 4146)
#endif
//For rooks
//original 12 bit keys
//C64(0x0000002040810402) - H8 12 bit
//C64(0x0000102040800101) - A8 12 bit
//C64(0x0000102040008101) - B8 11 bit
//C64(0x0000081020004101) - C8 11 bit
//Adapted Grant Osborne's keys
//C64(0x0001FFFAABFAD1A2) - H8 11 bit
//C64(0x00FFFCDDFCED714A) - A8 11 bit
//C64(0x007FFCDDFCED714A) - B8 10 bit
//C64(0x003FFFCDFFD88096) - C8 10 bit
const unsigned int magicmoves_r_shift[64]=
{
52, 53, 53, 53, 53, 53, 53, 52,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 53, 53, 53, 53, 53
};
const U64 magicmoves_r_magics[64]=
{
C64(0x0080001020400080), C64(0x0040001000200040), C64(0x0080081000200080), C64(0x0080040800100080),
C64(0x0080020400080080), C64(0x0080010200040080), C64(0x0080008001000200), C64(0x0080002040800100),
C64(0x0000800020400080), C64(0x0000400020005000), C64(0x0000801000200080), C64(0x0000800800100080),
C64(0x0000800400080080), C64(0x0000800200040080), C64(0x0000800100020080), C64(0x0000800040800100),
C64(0x0000208000400080), C64(0x0000404000201000), C64(0x0000808010002000), C64(0x0000808008001000),
C64(0x0000808004000800), C64(0x0000808002000400), C64(0x0000010100020004), C64(0x0000020000408104),
C64(0x0000208080004000), C64(0x0000200040005000), C64(0x0000100080200080), C64(0x0000080080100080),
C64(0x0000040080080080), C64(0x0000020080040080), C64(0x0000010080800200), C64(0x0000800080004100),
C64(0x0000204000800080), C64(0x0000200040401000), C64(0x0000100080802000), C64(0x0000080080801000),
C64(0x0000040080800800), C64(0x0000020080800400), C64(0x0000020001010004), C64(0x0000800040800100),
C64(0x0000204000808000), C64(0x0000200040008080), C64(0x0000100020008080), C64(0x0000080010008080),
C64(0x0000040008008080), C64(0x0000020004008080), C64(0x0000010002008080), C64(0x0000004081020004),
C64(0x0000204000800080), C64(0x0000200040008080), C64(0x0000100020008080), C64(0x0000080010008080),
C64(0x0000040008008080), C64(0x0000020004008080), C64(0x0000800100020080), C64(0x0000800041000080),
C64(0x00FFFCDDFCED714A), C64(0x007FFCDDFCED714A), C64(0x003FFFCDFFD88096), C64(0x0000040810002101),
C64(0x0001000204080011), C64(0x0001000204000801), C64(0x0001000082000401), C64(0x0001FFFAABFAD1A2)
};
const U64 magicmoves_r_mask[64]=
{
C64(0x000101010101017E), C64(0x000202020202027C), C64(0x000404040404047A), C64(0x0008080808080876),
C64(0x001010101010106E), C64(0x002020202020205E), C64(0x004040404040403E), C64(0x008080808080807E),
C64(0x0001010101017E00), C64(0x0002020202027C00), C64(0x0004040404047A00), C64(0x0008080808087600),
C64(0x0010101010106E00), C64(0x0020202020205E00), C64(0x0040404040403E00), C64(0x0080808080807E00),
C64(0x00010101017E0100), C64(0x00020202027C0200), C64(0x00040404047A0400), C64(0x0008080808760800),
C64(0x00101010106E1000), C64(0x00202020205E2000), C64(0x00404040403E4000), C64(0x00808080807E8000),
C64(0x000101017E010100), C64(0x000202027C020200), C64(0x000404047A040400), C64(0x0008080876080800),
C64(0x001010106E101000), C64(0x002020205E202000), C64(0x004040403E404000), C64(0x008080807E808000),
C64(0x0001017E01010100), C64(0x0002027C02020200), C64(0x0004047A04040400), C64(0x0008087608080800),
C64(0x0010106E10101000), C64(0x0020205E20202000), C64(0x0040403E40404000), C64(0x0080807E80808000),
C64(0x00017E0101010100), C64(0x00027C0202020200), C64(0x00047A0404040400), C64(0x0008760808080800),
C64(0x00106E1010101000), C64(0x00205E2020202000), C64(0x00403E4040404000), C64(0x00807E8080808000),
C64(0x007E010101010100), C64(0x007C020202020200), C64(0x007A040404040400), C64(0x0076080808080800),
C64(0x006E101010101000), C64(0x005E202020202000), C64(0x003E404040404000), C64(0x007E808080808000),
C64(0x7E01010101010100), C64(0x7C02020202020200), C64(0x7A04040404040400), C64(0x7608080808080800),
C64(0x6E10101010101000), C64(0x5E20202020202000), C64(0x3E40404040404000), C64(0x7E80808080808000)
};
//my original tables for bishops
const unsigned int magicmoves_b_shift[64]=
{
58, 59, 59, 59, 59, 59, 59, 58,
59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 57, 57, 57, 57, 59, 59,
59, 59, 57, 55, 55, 57, 59, 59,
59, 59, 57, 55, 55, 57, 59, 59,
59, 59, 57, 57, 57, 57, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59,
58, 59, 59, 59, 59, 59, 59, 58
};
const U64 magicmoves_b_magics[64]=
{
C64(0x0002020202020200), C64(0x0002020202020000), C64(0x0004010202000000), C64(0x0004040080000000),
C64(0x0001104000000000), C64(0x0000821040000000), C64(0x0000410410400000), C64(0x0000104104104000),
C64(0x0000040404040400), C64(0x0000020202020200), C64(0x0000040102020000), C64(0x0000040400800000),
C64(0x0000011040000000), C64(0x0000008210400000), C64(0x0000004104104000), C64(0x0000002082082000),
C64(0x0004000808080800), C64(0x0002000404040400), C64(0x0001000202020200), C64(0x0000800802004000),
C64(0x0000800400A00000), C64(0x0000200100884000), C64(0x0000400082082000), C64(0x0000200041041000),
C64(0x0002080010101000), C64(0x0001040008080800), C64(0x0000208004010400), C64(0x0000404004010200),
C64(0x0000840000802000), C64(0x0000404002011000), C64(0x0000808001041000), C64(0x0000404000820800),
C64(0x0001041000202000), C64(0x0000820800101000), C64(0x0000104400080800), C64(0x0000020080080080),
C64(0x0000404040040100), C64(0x0000808100020100), C64(0x0001010100020800), C64(0x0000808080010400),
C64(0x0000820820004000), C64(0x0000410410002000), C64(0x0000082088001000), C64(0x0000002011000800),
C64(0x0000080100400400), C64(0x0001010101000200), C64(0x0002020202000400), C64(0x0001010101000200),
C64(0x0000410410400000), C64(0x0000208208200000), C64(0x0000002084100000), C64(0x0000000020880000),
C64(0x0000001002020000), C64(0x0000040408020000), C64(0x0004040404040000), C64(0x0002020202020000),
C64(0x0000104104104000), C64(0x0000002082082000), C64(0x0000000020841000), C64(0x0000000000208800),
C64(0x0000000010020200), C64(0x0000000404080200), C64(0x0000040404040400), C64(0x0002020202020200)
};
const U64 magicmoves_b_mask[64]=
{
C64(0x0040201008040200), C64(0x0000402010080400), C64(0x0000004020100A00), C64(0x0000000040221400),
C64(0x0000000002442800), C64(0x0000000204085000), C64(0x0000020408102000), C64(0x0002040810204000),
C64(0x0020100804020000), C64(0x0040201008040000), C64(0x00004020100A0000), C64(0x0000004022140000),
C64(0x0000000244280000), C64(0x0000020408500000), C64(0x0002040810200000), C64(0x0004081020400000),
C64(0x0010080402000200), C64(0x0020100804000400), C64(0x004020100A000A00), C64(0x0000402214001400),
C64(0x0000024428002800), C64(0x0002040850005000), C64(0x0004081020002000), C64(0x0008102040004000),
C64(0x0008040200020400), C64(0x0010080400040800), C64(0x0020100A000A1000), C64(0x0040221400142200),
C64(0x0002442800284400), C64(0x0004085000500800), C64(0x0008102000201000), C64(0x0010204000402000),
C64(0x0004020002040800), C64(0x0008040004081000), C64(0x00100A000A102000), C64(0x0022140014224000),
C64(0x0044280028440200), C64(0x0008500050080400), C64(0x0010200020100800), C64(0x0020400040201000),
C64(0x0002000204081000), C64(0x0004000408102000), C64(0x000A000A10204000), C64(0x0014001422400000),
C64(0x0028002844020000), C64(0x0050005008040200), C64(0x0020002010080400), C64(0x0040004020100800),
C64(0x0000020408102000), C64(0x0000040810204000), C64(0x00000A1020400000), C64(0x0000142240000000),
C64(0x0000284402000000), C64(0x0000500804020000), C64(0x0000201008040200), C64(0x0000402010080400),
C64(0x0002040810204000), C64(0x0004081020400000), C64(0x000A102040000000), C64(0x0014224000000000),
C64(0x0028440200000000), C64(0x0050080402000000), C64(0x0020100804020000), C64(0x0040201008040200)
};
#ifdef MINIMIZE_MAGIC
U64 magicmovesbdb[5248];
const U64* magicmoves_b_indices[64]=
{
magicmovesbdb+4992, magicmovesbdb+2624, magicmovesbdb+256, magicmovesbdb+896,
magicmovesbdb+1280, magicmovesbdb+1664, magicmovesbdb+4800, magicmovesbdb+5120,
magicmovesbdb+2560, magicmovesbdb+2656, magicmovesbdb+288, magicmovesbdb+928,
magicmovesbdb+1312, magicmovesbdb+1696, magicmovesbdb+4832, magicmovesbdb+4928,
magicmovesbdb+0, magicmovesbdb+128, magicmovesbdb+320, magicmovesbdb+960,
magicmovesbdb+1344, magicmovesbdb+1728, magicmovesbdb+2304, magicmovesbdb+2432,
magicmovesbdb+32, magicmovesbdb+160, magicmovesbdb+448, magicmovesbdb+2752,
magicmovesbdb+3776, magicmovesbdb+1856, magicmovesbdb+2336, magicmovesbdb+2464,
magicmovesbdb+64, magicmovesbdb+192, magicmovesbdb+576, magicmovesbdb+3264,
magicmovesbdb+4288, magicmovesbdb+1984, magicmovesbdb+2368, magicmovesbdb+2496,
magicmovesbdb+96, magicmovesbdb+224, magicmovesbdb+704, magicmovesbdb+1088,
magicmovesbdb+1472, magicmovesbdb+2112, magicmovesbdb+2400, magicmovesbdb+2528,
magicmovesbdb+2592, magicmovesbdb+2688, magicmovesbdb+832, magicmovesbdb+1216,
magicmovesbdb+1600, magicmovesbdb+2240, magicmovesbdb+4864, magicmovesbdb+4960,
magicmovesbdb+5056, magicmovesbdb+2720, magicmovesbdb+864, magicmovesbdb+1248,
magicmovesbdb+1632, magicmovesbdb+2272, magicmovesbdb+4896, magicmovesbdb+5184
};
#else
#ifndef PERFECT_MAGIC_HASH
U64 magicmovesbdb[64][1<<9];
#else
U64 magicmovesbdb[1428];
PERFECT_MAGIC_HASH magicmoves_b_indices[64][1<<9];
#endif
#endif
#ifdef MINIMIZE_MAGIC
U64 magicmovesrdb[102400];
const U64* magicmoves_r_indices[64]=
{
magicmovesrdb+86016, magicmovesrdb+73728, magicmovesrdb+36864, magicmovesrdb+43008,
magicmovesrdb+47104, magicmovesrdb+51200, magicmovesrdb+77824, magicmovesrdb+94208,
magicmovesrdb+69632, magicmovesrdb+32768, magicmovesrdb+38912, magicmovesrdb+10240,
magicmovesrdb+14336, magicmovesrdb+53248, magicmovesrdb+57344, magicmovesrdb+81920,
magicmovesrdb+24576, magicmovesrdb+33792, magicmovesrdb+6144, magicmovesrdb+11264,
magicmovesrdb+15360, magicmovesrdb+18432, magicmovesrdb+58368, magicmovesrdb+61440,
magicmovesrdb+26624, magicmovesrdb+4096, magicmovesrdb+7168, magicmovesrdb+0,
magicmovesrdb+2048, magicmovesrdb+19456, magicmovesrdb+22528, magicmovesrdb+63488,
magicmovesrdb+28672, magicmovesrdb+5120, magicmovesrdb+8192, magicmovesrdb+1024,
magicmovesrdb+3072, magicmovesrdb+20480, magicmovesrdb+23552, magicmovesrdb+65536,
magicmovesrdb+30720, magicmovesrdb+34816, magicmovesrdb+9216, magicmovesrdb+12288,
magicmovesrdb+16384, magicmovesrdb+21504, magicmovesrdb+59392, magicmovesrdb+67584,
magicmovesrdb+71680, magicmovesrdb+35840, magicmovesrdb+39936, magicmovesrdb+13312,
magicmovesrdb+17408, magicmovesrdb+54272, magicmovesrdb+60416, magicmovesrdb+83968,
magicmovesrdb+90112, magicmovesrdb+75776, magicmovesrdb+40960, magicmovesrdb+45056,
magicmovesrdb+49152, magicmovesrdb+55296, magicmovesrdb+79872, magicmovesrdb+98304
};
#else
#ifndef PERFECT_MAGIC_HASH
U64 magicmovesrdb[64][1<<12];
#else
U64 magicmovesrdb[4900];
PERFECT_MAGIC_HASH magicmoves_r_indices[64][1<<12];
#endif
#endif
U64 initmagicmoves_occ(const int* squares, const int numSquares, const U64 linocc)
{
int i;
U64 ret=0;
for(i=0;i<numSquares;i++)
if(linocc&(((U64)(1))<<i)) ret|=(((U64)(1))<<squares[i]);
return ret;
}
U64 initmagicmoves_Rmoves(const int square, const U64 occ)
{
U64 ret=0;
U64 bit;
U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
bit=(((U64)(1))<<square);
do
{
bit<<=8;
ret|=bit;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit>>=8;
ret|=bit;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit<<=1;
if(bit&rowbits) ret|=bit;
else break;
}while(!(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit>>=1;
if(bit&rowbits) ret|=bit;
else break;
}while(!(bit&occ));
return ret;
}
U64 initmagicmoves_Bmoves(const int square, const U64 occ)
{
U64 ret=0;
U64 bit;
U64 bit2;
U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit<<=8-1;
bit2>>=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit<<=8+1;
bit2<<=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit>>=8-1;
bit2<<=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit>>=8+1;
bit2>>=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
return ret;
}
//used so that the original indices can be left as const so that the compiler can optimize better
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
#define BmagicNOMASK2(square, occupancy) *(magicmoves_b_indices2[square]+(((occupancy)*magicmoves_b_magics[square])>>magicmoves_b_shift[square]))
#define RmagicNOMASK2(square, occupancy) *(magicmoves_r_indices2[square]+(((occupancy)*magicmoves_r_magics[square])>>magicmoves_r_shift[square]))
#else
#define BmagicNOMASK2(square, occupancy) magicmovesbdb[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]
#define RmagicNOMASK2(square, occupancy) magicmovesrdb[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]
#endif
/*#else
#define BmagicNOMASK2(square, occupancy) magicmovesbdb[magicmoves_b_indices[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT]]
#define RmagicNOMASK2(square, occupancy) magicmovesrdb[magicmoves_r_indices[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT]]
*/
#endif
void initmagicmoves(void)
{
int i;
//for bitscans :
//initmagicmoves_bitpos64_database[(x*C64(0x07EDD5E59A4E28C2))>>58]
int initmagicmoves_bitpos64_database[64]={
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5};
#ifdef MINIMIZE_MAGIC
//identical to magicmove_x_indices except without the const modifer
U64* magicmoves_b_indices2[64]=
{
magicmovesbdb+4992, magicmovesbdb+2624, magicmovesbdb+256, magicmovesbdb+896,
magicmovesbdb+1280, magicmovesbdb+1664, magicmovesbdb+4800, magicmovesbdb+5120,
magicmovesbdb+2560, magicmovesbdb+2656, magicmovesbdb+288, magicmovesbdb+928,
magicmovesbdb+1312, magicmovesbdb+1696, magicmovesbdb+4832, magicmovesbdb+4928,
magicmovesbdb+0, magicmovesbdb+128, magicmovesbdb+320, magicmovesbdb+960,
magicmovesbdb+1344, magicmovesbdb+1728, magicmovesbdb+2304, magicmovesbdb+2432,
magicmovesbdb+32, magicmovesbdb+160, magicmovesbdb+448, magicmovesbdb+2752,
magicmovesbdb+3776, magicmovesbdb+1856, magicmovesbdb+2336, magicmovesbdb+2464,
magicmovesbdb+64, magicmovesbdb+192, magicmovesbdb+576, magicmovesbdb+3264,
magicmovesbdb+4288, magicmovesbdb+1984, magicmovesbdb+2368, magicmovesbdb+2496,
magicmovesbdb+96, magicmovesbdb+224, magicmovesbdb+704, magicmovesbdb+1088,
magicmovesbdb+1472, magicmovesbdb+2112, magicmovesbdb+2400, magicmovesbdb+2528,
magicmovesbdb+2592, magicmovesbdb+2688, magicmovesbdb+832, magicmovesbdb+1216,
magicmovesbdb+1600, magicmovesbdb+2240, magicmovesbdb+4864, magicmovesbdb+4960,
magicmovesbdb+5056, magicmovesbdb+2720, magicmovesbdb+864, magicmovesbdb+1248,
magicmovesbdb+1632, magicmovesbdb+2272, magicmovesbdb+4896, magicmovesbdb+5184
};
U64* magicmoves_r_indices2[64]=
{
magicmovesrdb+86016, magicmovesrdb+73728, magicmovesrdb+36864, magicmovesrdb+43008,
magicmovesrdb+47104, magicmovesrdb+51200, magicmovesrdb+77824, magicmovesrdb+94208,
magicmovesrdb+69632, magicmovesrdb+32768, magicmovesrdb+38912, magicmovesrdb+10240,
magicmovesrdb+14336, magicmovesrdb+53248, magicmovesrdb+57344, magicmovesrdb+81920,
magicmovesrdb+24576, magicmovesrdb+33792, magicmovesrdb+6144, magicmovesrdb+11264,
magicmovesrdb+15360, magicmovesrdb+18432, magicmovesrdb+58368, magicmovesrdb+61440,
magicmovesrdb+26624, magicmovesrdb+4096, magicmovesrdb+7168, magicmovesrdb+0,
magicmovesrdb+2048, magicmovesrdb+19456, magicmovesrdb+22528, magicmovesrdb+63488,
magicmovesrdb+28672, magicmovesrdb+5120, magicmovesrdb+8192, magicmovesrdb+1024,
magicmovesrdb+3072, magicmovesrdb+20480, magicmovesrdb+23552, magicmovesrdb+65536,
magicmovesrdb+30720, magicmovesrdb+34816, magicmovesrdb+9216, magicmovesrdb+12288,
magicmovesrdb+16384, magicmovesrdb+21504, magicmovesrdb+59392, magicmovesrdb+67584,
magicmovesrdb+71680, magicmovesrdb+35840, magicmovesrdb+39936, magicmovesrdb+13312,
magicmovesrdb+17408, magicmovesrdb+54272, magicmovesrdb+60416, magicmovesrdb+83968,
magicmovesrdb+90112, magicmovesrdb+75776, magicmovesrdb+40960, magicmovesrdb+45056,
magicmovesrdb+49152, magicmovesrdb+55296, magicmovesrdb+79872, magicmovesrdb+98304
};
#endif // MINIMIZE_MAGIC
#ifdef PERFECT_MAGIC_HASH
for(i=0;i<1428;i++)
magicmovesbdb[i]=0;
for(i=0;i<4900;i++)
magicmovesrdb[i]=0;
#endif
for(i=0;i<64;i++)
{
int squares[64];
int numsquares=0;
U64 temp=magicmoves_b_mask[i];
while(temp)
{
U64 bit=temp&-temp;
squares[numsquares++]=initmagicmoves_bitpos64_database[(bit*C64(0x07EDD5E59A4E28C2))>>58];
temp^=bit;
}
for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
{
U64 tempocc=initmagicmoves_occ(squares,numsquares,temp);
#ifndef PERFECT_MAGIC_HASH
BmagicNOMASK2(i,tempocc)=initmagicmoves_Bmoves(i,tempocc);
#else
U64 moves=initmagicmoves_Bmoves(i,tempocc);
U64 index=(((tempocc)*magicmoves_b_magics[i])>>MINIMAL_B_BITS_SHIFT);
int j;
for(j=0;j<1428;j++)
{
if(!magicmovesbdb[j])
{
magicmovesbdb[j]=moves;
magicmoves_b_indices[i][index]=j;
break;
}
else if(magicmovesbdb[j]==moves)
{
magicmoves_b_indices[i][index]=j;
break;
}
}
#endif
}
}
for(i=0;i<64;i++)
{
int squares[64];
int numsquares=0;
U64 temp=magicmoves_r_mask[i];
while(temp)
{
U64 bit=temp&-temp;
squares[numsquares++]=initmagicmoves_bitpos64_database[(bit*C64(0x07EDD5E59A4E28C2))>>58];
temp^=bit;
}
for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
{
U64 tempocc=initmagicmoves_occ(squares,numsquares,temp);
#ifndef PERFECT_MAGIC_HASH
RmagicNOMASK2(i,tempocc)=initmagicmoves_Rmoves(i,tempocc);
#else
U64 moves=initmagicmoves_Rmoves(i,tempocc);
U64 index=(((tempocc)*magicmoves_r_magics[i])>>MINIMAL_R_BITS_SHIFT);
int j;
for(j=0;j<4900;j++)
{
if(!magicmovesrdb[j])
{
magicmovesrdb[j]=moves;
magicmoves_r_indices[i][index]=j;
break;
}
else if(magicmovesrdb[j]==moves)
{
magicmoves_r_indices[i][index]=j;
break;
}
}
#endif
}
}
}
Warning: Spoiler![ Click to expand ][ Click to hide ]
/**
*magicmoves.h
*
*Header file for magic move bitboard generation. Include this in any files
*need this functionality.
*
*Usage:
*You must first initialize the generator with a call to initmagicmoves().
*Then you can use the following macros for generating move bitboards by
*giving them a square and an occupancy. The macro will then "return"
*the correct move bitboard for that particular square and occupancy. It
*has been named Rmagic and Bmagic so that it will not conflict with
*any functions/macros in your chess program called Rmoves/Bmoves. You
*can macro Bmagic/Rmagic to Bmoves/Rmoves if you wish. If you want to
*minimize the size of the bitboards, make MINIMIZE_MAGIC uncommented in this
*header (more info on this later). Where you typedef your unsigned 64-bit
*integer declare __64_BIT_INTEGER_DEFINED__. If USE_INLINING is uncommented,
*the macros will be expressed as MMINLINEd functions. If PERFECT_MAGIC_HASH is
*uncomment, the move generator will use an additional indrection to make the
*table sizes smaller : (~50kb+((original size)/sizeof(PERFECT_MAGIC_HASH)).
*The size listed from here on out are the sizes without PERFECT_MAGIC_HASH.
*
*Bmagic(square, occupancy)
*Rmagic(square, occupancy)
*
*Square is an integer that is greater than or equal to zero and less than 64.
*Occupancy is any unsigned 64-bit integer that describes which squares on
*the board are occupied.
*
*The following macros are identical to Rmagic and Bmagic except that the
*occupancy is assumed to already have been "masked". Look at the following
*source or read up on the internet about magic bitboard move generation to
*understand the usage of these macros and what it means by "an occupancy that
*has already been masked". Using the following macros when possible might be
*a tiny bit faster than using Rmagic and Bmagic because it avoids an array
*access and a 64-bit & operation.
*
*BmagicNOMASK(square, occupancy)
*RmagicNOMASK(square, occupancy)
*
*Unsigned 64 bit integers are referenced by this generator as U64.
*Edit the beginning lines of this header for the defenition of a 64 bit
*integer if necessary.
*
*If MINIMIZE_MAGIC is defined before including this file:
*The move bitboard generator will use up 841kb of memory.
*41kb of memory is used for the bishop database and 800kb is used for the rook
*database. If you feel the 800kb rook database is too big, then comment it out
*and use a more traditional move bitboard generator in conjunction with the
*magic move bitboard generator for bishops.
*
*If MINIMIAZE_MAGIC is not defined before including this file:
*The move bitboard generator will use up 2304kb of memory but might perform a bit
*faster.
*
*Copyright (C) 2007 Pradyumna Kannan.
*
*This code is provided 'as-is', without any expressed or implied warranty.
*In no event will the authors be held liable for any damages arising from
*the use of this code. Permission is granted to anyone to use this
*code for any purpose, including commercial applications, and to alter
*it and redistribute it freely, subject to the following restrictions:
*
*1. The origin of this code must not be misrepresented; you must not
*claim that you wrote the original code. If you use this code in a
*product, an acknowledgment in the product documentation would be
*appreciated but is not required.
*
*2. Altered source versions must be plainly marked as such, and must not be
*misrepresented as being the original code.
*
*3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _magicmovesh
#define _magicmovesh
/*********MODIFY THE FOLLOWING IF NECESSARY********/
//the default configuration is the best
//Uncommont either one of the following or none
#define MINIMIZE_MAGIC
//#define PERFECT_MAGIC_HASH unsigned short
//the following works only for perfect magic hash or no defenitions above
//it uses variable shift for each square
//#define VARIABLE_SHIFT
#define USE_INLINING /*the MMINLINE keyword is assumed to be available*/
#ifndef __64_BIT_INTEGER_DEFINED__
#define __64_BIT_INTEGER_DEFINED__
#if defined(_MSC_VER) && _MSC_VER<1300
typedef unsigned __int64 U64; //For the old microsoft compilers
#else
typedef unsigned long long U64; //Supported by MSC 13.00+ and C99
#endif //defined(_MSC_VER) && _MSC_VER<1300
#endif //__64_BIT_INTEGER_DEFINED__
/***********MODIFY THE ABOVE IF NECESSARY**********/
/*Defining the inlining keyword*/
#ifdef USE_INLINING
#ifdef _MSC_VER
#define MMINLINE __forceinline
#elif defined(__GNUC__)
#define MMINLINE __inline__ __attribute__((always_inline))
#else
#define MMINLINE inline
#endif
#endif
#ifndef C64
#if (!defined(_MSC_VER) || _MSC_VER>1300)
#define C64(constantU64) constantU64##ULL
#else
#define C64(constantU64) constantU64
#endif
#endif
extern const U64 magicmoves_r_magics[64];
extern const U64 magicmoves_r_mask[64];
extern const U64 magicmoves_b_magics[64];
extern const U64 magicmoves_b_mask[64];
extern const unsigned int magicmoves_b_shift[64];
extern const unsigned int magicmoves_r_shift[64];
#ifndef VARIABLE_SHIFT
#define MINIMAL_B_BITS_SHIFT(square) 55
#define MINIMAL_R_BITS_SHIFT(square) 52
#else
#define MINIMAL_B_BITS_SHIFT(square) magicmoves_b_shift[square]
#define MINIMAL_R_BITS_SHIFT(square) magicmoves_r_shift[square]
#endif
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
#ifndef USE_INLINING
#define Bmagic(square, occupancy) *(magicmoves_b_indices[square]+((((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>magicmoves_b_shift[square]))
#define Rmagic(square, occupancy) *(magicmoves_r_indices[square]+((((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>magicmoves_r_shift[square]))
#define BmagicNOMASK(square, occupancy) *(magicmoves_b_indices[square]+(((occupancy)*magicmoves_b_magics[square])>>magicmoves_b_shift[square]))
#define RmagicNOMASK(square, occupancy) *(magicmoves_r_indices[square]+(((occupancy)*magicmoves_r_magics[square])>>magicmoves_r_shift[square]))
#endif //USE_INLINING
//extern U64 magicmovesbdb[5248];
extern const U64* magicmoves_b_indices[64];
//extern U64 magicmovesrdb[102400];
extern const U64* magicmoves_r_indices[64];
#else //Don't Minimize database size
#ifndef USE_INLINING
#define Bmagic(square, occupancy) magicmovesbdb[square][(((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]
#define Rmagic(square, occupancy) magicmovesrdb[square][(((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]
#define BmagicNOMASK(square, occupancy) magicmovesbdb[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]
#define RmagicNOMASK(square, occupancy) magicmovesrdb[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]
#endif //USE_INLINING
extern U64 magicmovesbdb[64][1<<9];
extern U64 magicmovesrdb[64][1<<12];
#endif //MINIMIAZE_MAGICMOVES
#else //PERFCT_MAGIC_HASH defined
#ifndef MINIMIZE_MAGIC
#ifndef USE_INLINING
#define Bmagic(square, occupancy) magicmovesbdb[magicmoves_b_indices[square][(((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]]
#define Rmagic(square, occupancy) magicmovesrdb[magicmoves_r_indices[square][(((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]]
#define BmagicNOMASK(square, occupancy) magicmovesbdb[magicmoves_b_indices[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]]
#define RmagicNOMASK(square, occupancy) magicmovesrdb[magicmoves_r_indices[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]]
#endif //USE_INLINING
extern U64 magicmovesbdb[1428];
extern U64 magicmovesrdb[4900];
extern PERFECT_MAGIC_HASH magicmoves_b_indices[64][1<<9];
extern PERFECT_MAGIC_HASH magicmoves_r_indices[64][1<<12];
#else
#error magicmoves - MINIMIZED_MAGIC and PERFECT_MAGIC_HASH cannot be used together
#endif
#endif //PERFCT_MAGIC_HASH
#ifdef USE_INLINING
static MMINLINE U64 Bmagic(const unsigned int square,const U64 occupancy)
{
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
return *(magicmoves_b_indices[square]+(((occupancy&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>magicmoves_b_shift[square]));
#else
return magicmovesbdb[square][(((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)];
#endif
#else
return magicmovesbdb[magicmoves_b_indices[square][(((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]];
#endif
}
static MMINLINE U64 Rmagic(const unsigned int square,const U64 occupancy)
{
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
return *(magicmoves_r_indices[square]+(((occupancy&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>magicmoves_r_shift[square]));
#else
return magicmovesrdb[square][(((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)];
#endif
#else
return magicmovesrdb[magicmoves_r_indices[square][(((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]];
#endif
}
static MMINLINE U64 BmagicNOMASK(const unsigned int square,const U64 occupancy)
{
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
return *(magicmoves_b_indices[square]+(((occupancy)*magicmoves_b_magics[square])>>magicmoves_b_shift[square]));
#else
return magicmovesbdb[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)];
#endif
#else
return magicmovesbdb[magicmoves_b_indices[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]];
#endif
}
static MMINLINE U64 RmagicNOMASK(const unsigned int square, const U64 occupancy)
{
#ifndef PERFECT_MAGIC_HASH
#ifdef MINIMIZE_MAGIC
return *(magicmoves_r_indices[square]+(((occupancy)*magicmoves_r_magics[square])>>magicmoves_r_shift[square]));
#else
return magicmovesrdb[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)];
#endif
#else
return magicmovesrdb[magicmoves_r_indices[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]];
#endif
}
static MMINLINE U64 Qmagic(const unsigned int square,const U64 occupancy)
{
return Bmagic(square,occupancy)|Rmagic(square,occupancy);
}
static MMINLINE U64 QmagicNOMASK(const unsigned int square, const U64 occupancy)
{
return BmagicNOMASK(square,occupancy)|RmagicNOMASK(square,occupancy);
}
#else //!USE_INLINING
#define Qmagic(square, occupancy) (Bmagic(square,occupancy)|Rmagic(square,occupancy))
#define QmagicNOMASK(square, occupancy) (BmagicNOMASK(square,occupancy)|RmagicNOMASK(square,occupancy))
#endif //USE_INLINING
void initmagicmoves(void);
#endif //_magicmoveshvesh
Постарался убрать ненужные для моего компилятора директивы препроцессора.
Препроцессор C/C++ (англ. pre processor, предобработчик) — программа, подготавливающая код программы на языке C/C++ к компиляции.
Хочу код (C) 2007 Pradyumna Kannan использовать в своей проге на делфи.
Так легче преобразовать с одного языка на другой.
magicmoves.c
Warning: Spoiler![ Click to expand ][ Click to hide ]
/**
*magicmoves.h
*
*Source file for magic move bitboard generation.
*
*See header file for instructions on usage.
*
*The magic keys are not optimal for all squares but they are very close
*to optimal.
*
*Copyright (C) 2007 Pradyumna Kannan.
*
*This code is provided 'as-is', without any express or implied warranty.
*In no event will the authors be held liable for any damages arising from
*the use of this code. Permission is granted to anyone to use this
*code for any purpose, including commercial applications, and to alter
*it and redistribute it freely, subject to the following restrictions:
*
*1. The origin of this code must not be misrepresented; you must not
*claim that you wrote the original code. If you use this code in a
*product, an acknowledgment in the product documentation would be
*appreciated but is not required.
*
*2. Altered source versions must be plainly marked as such, and must not be
*misrepresented as being the original code.
*
*3. This notice may not be removed or altered from any source distribution.
*/
#include "magicmoves.h"
//For rooks
//original 12 bit keys
//C64(0x0000002040810402) - H8 12 bit
//C64(0x0000102040800101) - A8 12 bit
//C64(0x0000102040008101) - B8 11 bit
//C64(0x0000081020004101) - C8 11 bit
//Adapted Grant Osborne's keys
//C64(0x0001FFFAABFAD1A2) - H8 11 bit
//C64(0x00FFFCDDFCED714A) - A8 11 bit
//C64(0x007FFCDDFCED714A) - B8 10 bit
//C64(0x003FFFCDFFD88096) - C8 10 bit
const unsigned int magicmoves_r_shift[64]=
{
52, 53, 53, 53, 53, 53, 53, 52,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 54, 54, 54, 54, 53,
53, 54, 54, 53, 53, 53, 53, 53
};
const U64 magicmoves_r_magics[64]=
{
C64(0x0080001020400080), C64(0x0040001000200040), C64(0x0080081000200080), C64(0x0080040800100080),
C64(0x0080020400080080), C64(0x0080010200040080), C64(0x0080008001000200), C64(0x0080002040800100),
C64(0x0000800020400080), C64(0x0000400020005000), C64(0x0000801000200080), C64(0x0000800800100080),
C64(0x0000800400080080), C64(0x0000800200040080), C64(0x0000800100020080), C64(0x0000800040800100),
C64(0x0000208000400080), C64(0x0000404000201000), C64(0x0000808010002000), C64(0x0000808008001000),
C64(0x0000808004000800), C64(0x0000808002000400), C64(0x0000010100020004), C64(0x0000020000408104),
C64(0x0000208080004000), C64(0x0000200040005000), C64(0x0000100080200080), C64(0x0000080080100080),
C64(0x0000040080080080), C64(0x0000020080040080), C64(0x0000010080800200), C64(0x0000800080004100),
C64(0x0000204000800080), C64(0x0000200040401000), C64(0x0000100080802000), C64(0x0000080080801000),
C64(0x0000040080800800), C64(0x0000020080800400), C64(0x0000020001010004), C64(0x0000800040800100),
C64(0x0000204000808000), C64(0x0000200040008080), C64(0x0000100020008080), C64(0x0000080010008080),
C64(0x0000040008008080), C64(0x0000020004008080), C64(0x0000010002008080), C64(0x0000004081020004),
C64(0x0000204000800080), C64(0x0000200040008080), C64(0x0000100020008080), C64(0x0000080010008080),
C64(0x0000040008008080), C64(0x0000020004008080), C64(0x0000800100020080), C64(0x0000800041000080),
C64(0x00FFFCDDFCED714A), C64(0x007FFCDDFCED714A), C64(0x003FFFCDFFD88096), C64(0x0000040810002101),
C64(0x0001000204080011), C64(0x0001000204000801), C64(0x0001000082000401), C64(0x0001FFFAABFAD1A2)
};
const U64 magicmoves_r_mask[64]=
{
C64(0x000101010101017E), C64(0x000202020202027C), C64(0x000404040404047A), C64(0x0008080808080876),
C64(0x001010101010106E), C64(0x002020202020205E), C64(0x004040404040403E), C64(0x008080808080807E),
C64(0x0001010101017E00), C64(0x0002020202027C00), C64(0x0004040404047A00), C64(0x0008080808087600),
C64(0x0010101010106E00), C64(0x0020202020205E00), C64(0x0040404040403E00), C64(0x0080808080807E00),
C64(0x00010101017E0100), C64(0x00020202027C0200), C64(0x00040404047A0400), C64(0x0008080808760800),
C64(0x00101010106E1000), C64(0x00202020205E2000), C64(0x00404040403E4000), C64(0x00808080807E8000),
C64(0x000101017E010100), C64(0x000202027C020200), C64(0x000404047A040400), C64(0x0008080876080800),
C64(0x001010106E101000), C64(0x002020205E202000), C64(0x004040403E404000), C64(0x008080807E808000),
C64(0x0001017E01010100), C64(0x0002027C02020200), C64(0x0004047A04040400), C64(0x0008087608080800),
C64(0x0010106E10101000), C64(0x0020205E20202000), C64(0x0040403E40404000), C64(0x0080807E80808000),
C64(0x00017E0101010100), C64(0x00027C0202020200), C64(0x00047A0404040400), C64(0x0008760808080800),
C64(0x00106E1010101000), C64(0x00205E2020202000), C64(0x00403E4040404000), C64(0x00807E8080808000),
C64(0x007E010101010100), C64(0x007C020202020200), C64(0x007A040404040400), C64(0x0076080808080800),
C64(0x006E101010101000), C64(0x005E202020202000), C64(0x003E404040404000), C64(0x007E808080808000),
C64(0x7E01010101010100), C64(0x7C02020202020200), C64(0x7A04040404040400), C64(0x7608080808080800),
C64(0x6E10101010101000), C64(0x5E20202020202000), C64(0x3E40404040404000), C64(0x7E80808080808000)
};
//my original tables for bishops
const unsigned int magicmoves_b_shift[64]=
{
58, 59, 59, 59, 59, 59, 59, 58,
59, 59, 59, 59, 59, 59, 59, 59,
59, 59, 57, 57, 57, 57, 59, 59,
59, 59, 57, 55, 55, 57, 59, 59,
59, 59, 57, 55, 55, 57, 59, 59,
59, 59, 57, 57, 57, 57, 59, 59,
59, 59, 59, 59, 59, 59, 59, 59,
58, 59, 59, 59, 59, 59, 59, 58
};
const U64 magicmoves_b_magics[64]=
{
C64(0x0002020202020200), C64(0x0002020202020000), C64(0x0004010202000000), C64(0x0004040080000000),
C64(0x0001104000000000), C64(0x0000821040000000), C64(0x0000410410400000), C64(0x0000104104104000),
C64(0x0000040404040400), C64(0x0000020202020200), C64(0x0000040102020000), C64(0x0000040400800000),
C64(0x0000011040000000), C64(0x0000008210400000), C64(0x0000004104104000), C64(0x0000002082082000),
C64(0x0004000808080800), C64(0x0002000404040400), C64(0x0001000202020200), C64(0x0000800802004000),
C64(0x0000800400A00000), C64(0x0000200100884000), C64(0x0000400082082000), C64(0x0000200041041000),
C64(0x0002080010101000), C64(0x0001040008080800), C64(0x0000208004010400), C64(0x0000404004010200),
C64(0x0000840000802000), C64(0x0000404002011000), C64(0x0000808001041000), C64(0x0000404000820800),
C64(0x0001041000202000), C64(0x0000820800101000), C64(0x0000104400080800), C64(0x0000020080080080),
C64(0x0000404040040100), C64(0x0000808100020100), C64(0x0001010100020800), C64(0x0000808080010400),
C64(0x0000820820004000), C64(0x0000410410002000), C64(0x0000082088001000), C64(0x0000002011000800),
C64(0x0000080100400400), C64(0x0001010101000200), C64(0x0002020202000400), C64(0x0001010101000200),
C64(0x0000410410400000), C64(0x0000208208200000), C64(0x0000002084100000), C64(0x0000000020880000),
C64(0x0000001002020000), C64(0x0000040408020000), C64(0x0004040404040000), C64(0x0002020202020000),
C64(0x0000104104104000), C64(0x0000002082082000), C64(0x0000000020841000), C64(0x0000000000208800),
C64(0x0000000010020200), C64(0x0000000404080200), C64(0x0000040404040400), C64(0x0002020202020200)
};
const U64 magicmoves_b_mask[64]=
{
C64(0x0040201008040200), C64(0x0000402010080400), C64(0x0000004020100A00), C64(0x0000000040221400),
C64(0x0000000002442800), C64(0x0000000204085000), C64(0x0000020408102000), C64(0x0002040810204000),
C64(0x0020100804020000), C64(0x0040201008040000), C64(0x00004020100A0000), C64(0x0000004022140000),
C64(0x0000000244280000), C64(0x0000020408500000), C64(0x0002040810200000), C64(0x0004081020400000),
C64(0x0010080402000200), C64(0x0020100804000400), C64(0x004020100A000A00), C64(0x0000402214001400),
C64(0x0000024428002800), C64(0x0002040850005000), C64(0x0004081020002000), C64(0x0008102040004000),
C64(0x0008040200020400), C64(0x0010080400040800), C64(0x0020100A000A1000), C64(0x0040221400142200),
C64(0x0002442800284400), C64(0x0004085000500800), C64(0x0008102000201000), C64(0x0010204000402000),
C64(0x0004020002040800), C64(0x0008040004081000), C64(0x00100A000A102000), C64(0x0022140014224000),
C64(0x0044280028440200), C64(0x0008500050080400), C64(0x0010200020100800), C64(0x0020400040201000),
C64(0x0002000204081000), C64(0x0004000408102000), C64(0x000A000A10204000), C64(0x0014001422400000),
C64(0x0028002844020000), C64(0x0050005008040200), C64(0x0020002010080400), C64(0x0040004020100800),
C64(0x0000020408102000), C64(0x0000040810204000), C64(0x00000A1020400000), C64(0x0000142240000000),
C64(0x0000284402000000), C64(0x0000500804020000), C64(0x0000201008040200), C64(0x0000402010080400),
C64(0x0002040810204000), C64(0x0004081020400000), C64(0x000A102040000000), C64(0x0014224000000000),
C64(0x0028440200000000), C64(0x0050080402000000), C64(0x0020100804020000), C64(0x0040201008040200)
};
U64 magicmovesbdb[64][1<<9];
U64 magicmovesrdb[64][1<<12];
U64 initmagicmoves_occ(const int* squares, const int numSquares, const U64 linocc)
{
int i;
U64 ret=0;
for(i=0;i<numSquares;i++)
if(linocc&(((U64)(1))<<i)) ret|=(((U64)(1))<<squares[i]);
return ret;
}
U64 initmagicmoves_Rmoves(const int square, const U64 occ)
{
U64 ret=0;
U64 bit;
U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
bit=(((U64)(1))<<square);
do
{
bit<<=8;
ret|=bit;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit>>=8;
ret|=bit;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit<<=1;
if(bit&rowbits) ret|=bit;
else break;
}while(!(bit&occ));
bit=(((U64)(1))<<square);
do
{
bit>>=1;
if(bit&rowbits) ret|=bit;
else break;
}while(!(bit&occ));
return ret;
}
U64 initmagicmoves_Bmoves(const int square, const U64 occ)
{
U64 ret=0;
U64 bit;
U64 bit2;
U64 rowbits=(((U64)0xFF)<<(8*(square/8)));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit<<=8-1;
bit2>>=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit<<=8+1;
bit2<<=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit>>=8-1;
bit2<<=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
bit=(((U64)(1))<<square);
bit2=bit;
do
{
bit>>=8+1;
bit2>>=1;
if(bit2&rowbits) ret|=bit;
else break;
}while(bit && !(bit&occ));
return ret;
}
//used so that the original indices can be left as const so that the compiler can optimize better
#define BmagicNOMASK2(square, occupancy) magicmovesbdb[square][((occupancy)*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]
#define RmagicNOMASK2(square, occupancy) magicmovesrdb[square][((occupancy)*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]
void initmagicmoves(void)
{
int i;
//for bitscans :
//initmagicmoves_bitpos64_database[(x*C64(0x07EDD5E59A4E28C2))>>58]
int initmagicmoves_bitpos64_database[64]={
63, 0, 58, 1, 59, 47, 53, 2,
60, 39, 48, 27, 54, 33, 42, 3,
61, 51, 37, 40, 49, 18, 28, 20,
55, 30, 34, 11, 43, 14, 22, 4,
62, 57, 46, 52, 38, 26, 32, 41,
50, 36, 17, 19, 29, 10, 13, 21,
56, 45, 25, 31, 35, 16, 9, 12,
44, 24, 15, 8, 23, 7, 6, 5};
for(i=0;i<64;i++)
{
int squares[64];
int numsquares=0;
U64 temp=magicmoves_b_mask[i];
while(temp)
{
U64 bit=temp&-temp;
squares[numsquares++]=initmagicmoves_bitpos64_database[(bit*C64(0x07EDD5E59A4E28C2))>>58];
temp^=bit;
}
for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
{
U64 tempocc=initmagicmoves_occ(squares,numsquares,temp);
BmagicNOMASK2(i,tempocc)=initmagicmoves_Bmoves(i,tempocc);
}
}
for(i=0;i<64;i++)
{
int squares[64];
int numsquares=0;
U64 temp=magicmoves_r_mask[i];
while(temp)
{
U64 bit=temp&-temp;
squares[numsquares++]=initmagicmoves_bitpos64_database[(bit*C64(0x07EDD5E59A4E28C2))>>58];
temp^=bit;
}
for(temp=0;temp<(((U64)(1))<<numsquares);temp++)
{
U64 tempocc=initmagicmoves_occ(squares,numsquares,temp);
RmagicNOMASK2(i,tempocc)=initmagicmoves_Rmoves(i,tempocc);
}
}
}
magicmoves.h
Warning: Spoiler![ Click to expand ][ Click to hide ]
/**
*magicmoves.h
*
*Header file for magic move bitboard generation. Include this in any files
*need this functionality.
*
*Usage:
*You must first initialize the generator with a call to initmagicmoves().
*Then you can use the following macros for generating move bitboards by
*giving them a square and an occupancy. The macro will then "return"
*the correct move bitboard for that particular square and occupancy. It
*has been named Rmagic and Bmagic so that it will not conflict with
*any functions/macros in your chess program called Rmoves/Bmoves. You
*can macro Bmagic/Rmagic to Bmoves/Rmoves if you wish. If you want to
*minimize the size of the bitboards, make MINIMIZE_MAGIC uncommented in this
*header (more info on this later). Where you typedef your unsigned 64-bit
*integer declare __64_BIT_INTEGER_DEFINED__. If USE_INLINING is uncommented,
*the macros will be expressed as MMINLINEd functions. If PERFECT_MAGIC_HASH is
*uncomment, the move generator will use an additional indrection to make the
*table sizes smaller : (~50kb+((original size)/sizeof(PERFECT_MAGIC_HASH)).
*The size listed from here on out are the sizes without PERFECT_MAGIC_HASH.
*
*Bmagic(square, occupancy)
*Rmagic(square, occupancy)
*
*Square is an integer that is greater than or equal to zero and less than 64.
*Occupancy is any unsigned 64-bit integer that describes which squares on
*the board are occupied.
*
*The following macros are identical to Rmagic and Bmagic except that the
*occupancy is assumed to already have been "masked". Look at the following
*source or read up on the internet about magic bitboard move generation to
*understand the usage of these macros and what it means by "an occupancy that
*has already been masked". Using the following macros when possible might be
*a tiny bit faster than using Rmagic and Bmagic because it avoids an array
*access and a 64-bit & operation.
*
*BmagicNOMASK(square, occupancy)
*RmagicNOMASK(square, occupancy)
*
*Unsigned 64 bit integers are referenced by this generator as U64.
*Edit the beginning lines of this header for the defenition of a 64 bit
*integer if necessary.
*
*If MINIMIZE_MAGIC is defined before including this file:
*The move bitboard generator will use up 841kb of memory.
*41kb of memory is used for the bishop database and 800kb is used for the rook
*database. If you feel the 800kb rook database is too big, then comment it out
*and use a more traditional move bitboard generator in conjunction with the
*magic move bitboard generator for bishops.
*
*If MINIMIAZE_MAGIC is not defined before including this file:
*The move bitboard generator will use up 2304kb of memory but might perform a bit
*faster.
*
*Copyright (C) 2007 Pradyumna Kannan.
*
*This code is provided 'as-is', without any expressed or implied warranty.
*In no event will the authors be held liable for any damages arising from
*the use of this code. Permission is granted to anyone to use this
*code for any purpose, including commercial applications, and to alter
*it and redistribute it freely, subject to the following restrictions:
*
*1. The origin of this code must not be misrepresented; you must not
*claim that you wrote the original code. If you use this code in a
*product, an acknowledgment in the product documentation would be
*appreciated but is not required.
*
*2. Altered source versions must be plainly marked as such, and must not be
*misrepresented as being the original code.
*
*3. This notice may not be removed or altered from any source distribution.
*/
/*********MODIFY THE FOLLOWING IF NECESSARY********/
//the default configuration is the best
//Uncommont either one of the following or none
//#define MINIMIZE_MAGIC
//#define PERFECT_MAGIC_HASH unsigned short
//the following works only for perfect magic hash or no defenitions above
//it uses variable shift for each square
#define VARIABLE_SHIFT
//#define USE_INLINING /*the MMINLINE keyword is assumed to be available*/
typedef unsigned long long U64; //Supported by MSC 13.00+ and C99
/***********MODIFY THE ABOVE IF NECESSARY**********/
#define C64(constantU64) constantU64
#define MINIMAL_B_BITS_SHIFT(square) magicmoves_b_shift[square]
#define MINIMAL_R_BITS_SHIFT(square) magicmoves_r_shift[square]
#define Bmagic(square, occupancy) magicmovesbdb[square][(((occupancy)&magicmoves_b_mask[square])*magicmoves_b_magics[square])>>MINIMAL_B_BITS_SHIFT(square)]
#define Rmagic(square, occupancy) magicmovesrdb[square][(((occupancy)&magicmoves_r_mask[square])*magicmoves_r_magics[square])>>MINIMAL_R_BITS_SHIFT(square)]
extern const U64 magicmoves_r_magics[64];
extern const U64 magicmoves_r_mask[64];
extern const U64 magicmoves_b_magics[64];
extern const U64 magicmoves_b_mask[64];
extern const unsigned int magicmoves_b_shift[64];
extern const unsigned int magicmoves_r_shift[64];
extern U64 magicmovesbdb[64][1<<9];
extern U64 magicmovesrdb[64][1<<12];
void initmagicmoves(void);
На самом деле, я не пытаюсь изобрести что-то новое.
Как раз и хочу взять и реализовать у себя, лучшее из того, что придумали умные люди за 50-70 лет.
И вообще, я получаю от этого удовольствие