Ключевое слово
27 | 01 | 2023
Новости Библиотеки
Шахматы Онлайн
Welcome, Guest
Username: Password: Remember me

TOPIC: Bitboard в программировании шахмат №2

Bitboard в программировании шахмат №2 23 Янв 2023 19:57 #121

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
10 урок - нахождение индекса младшего значащего бита и возвращение его координаты в шахматной нотации
program bbc;

{$APPTYPE CONSOLE}

uses
  SysUtils,Windows,TypInfo;
type
    U64 = UInt64;
    TBoard_squares = (
    a8, b8, c8, d8, e8, f8, g8, h8,
    a7, b7, c7, d7, e7, f7, g7, h7,
    a6, b6, c6, d6, e6, f6, g6, h6,
    a5, b5, c5, d5, e5, f5, g5, h5,
    a4, b4, c4, d4, e4, f4, g4, h4,
    a3, b3, c3, d3, e3, f3, g3, h3,
    a2, b2, c2, d2, e2, f2, g2, h2,
    a1, b1, c1, d1, e1, f1, g1, h1
    );
    TSide = (white, black);
    //Первый индекс обозначает номер строки в матрице, второй индекс – номер столбца
    TPawn_attacks=array[TSide,TBoard_squares] of U64;
    TChip_attacks=array[TBoard_squares] of U64;
var
 bitboard:U64=0;
 block:U64=0;
 // pawn attacks table [side][square]
 pawn_attacks:TPawn_attacks;
 // knight attacks table [square]
 knight_attacks:TChip_attacks;
 // king attacks table [square]
 king_attacks:TChip_attacks;
 square:TBoard_squares;
const
{/*
        not A file
  8  0 1 1 1 1 1 1 1
  7  0 1 1 1 1 1 1 1
  6  0 1 1 1 1 1 1 1
  5  0 1 1 1 1 1 1 1
  4  0 1 1 1 1 1 1 1
  3  0 1 1 1 1 1 1 1
  2  0 1 1 1 1 1 1 1
  1  0 1 1 1 1 1 1 1
     a b c d e f g h
        not H file
  8  1 1 1 1 1 1 1 0
  7  1 1 1 1 1 1 1 0
  6  1 1 1 1 1 1 1 0
  5  1 1 1 1 1 1 1 0
  4  1 1 1 1 1 1 1 0
  3  1 1 1 1 1 1 1 0
  2  1 1 1 1 1 1 1 0
  1  1 1 1 1 1 1 1 0
     a b c d e f g h
       not HG file
  8  1 1 1 1 1 1 0 0
  7  1 1 1 1 1 1 0 0
  6  1 1 1 1 1 1 0 0
  5  1 1 1 1 1 1 0 0
  4  1 1 1 1 1 1 0 0
  3  1 1 1 1 1 1 0 0
  2  1 1 1 1 1 1 0 0
  1  1 1 1 1 1 1 0 0
     a b c d e f g h
       not AB file
  8  0 0 1 1 1 1 1 1
  7  0 0 1 1 1 1 1 1
  6  0 0 1 1 1 1 1 1
  5  0 0 1 1 1 1 1 1
  4  0 0 1 1 1 1 1 1
  3  0 0 1 1 1 1 1 1
  2  0 0 1 1 1 1 1 1
  1  0 0 1 1 1 1 1 1
     a b c d e f g h
*/}

// not A file constant
not_a_file:U64 = $FEFEFEFEFEFEFEFE;//18374403900871474942;
// not H file constant
not_h_file:U64 = $7F7F7F7F7F7F7F7F;//9187201950435737471;
// not HG file constant
not_hg_file:U64 =$3F3F3F3F3F3F3F3F;//4557430888798830399;
// not AB file constant
not_ab_file:U64 =$FCFCFCFCFCFCFCFC;//18229723555195321596;
square_to_coordinates: array [0..63]  of  string =  (
    'a8', 'b8', 'c8', 'd8', 'e8', 'f8', 'g8', 'h8',
    'a7', 'b7', 'c7', 'd7', 'e7', 'f7', 'g7', 'h7',
    'a6', 'b6', 'c6', 'd6', 'e6', 'f6', 'g6', 'h6',
    'a5', 'b5', 'c5', 'd5', 'e5', 'f5', 'g5', 'h5',
    'a4', 'b4', 'c4', 'd4', 'e4', 'f4', 'g4', 'h4',
    'a3', 'b3', 'c3', 'd3', 'e3', 'f3', 'g3', 'h3',
    'a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2',
    'a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1'
);
{/**********************************\
 ==================================
 
          Bit manipulations
 
 ==================================
\**********************************/}
// set/get/pop
function get_bit(bb:U64;const sq:integer):integer;
begin
get_bit:=(bb shr sq) and 1;
end;
procedure set_bit(var bb:U64;const sq:TBoard_squares);
begin
bb:=bb or ($8000000000000000 shr (63-Ord(sq)));
end;
procedure pop_bit(var bb:U64;const sq:TBoard_squares);
begin
if get_bit(bb,Ord(sq))>0 then bb:=bb xor ($8000000000000000 shr (63-Ord(sq)));
end;
// count bits within a bitboard (Brian Kernighan's way)
function count_bits(bb:U64):integer;
var
count:integer;
begin
    // bit counter
    count := 0;
    // consecutively reset least significant 1st bit
     while bb>0
     do  begin
         // increment count
         Inc(count);
         // reset least significant 1st bit
         bb := bb and (bb - 1);
         end;
count_bits:=count;
end;
// get least significant 1st bit index
function  get_ls1b_index(bb:U64):integer;
begin
  // make sure bitboard is not 0
 if bb<>0 then
 // count trailing bits before LS1B
 result:=count_bits((bb and (-bb))-1)
 // return illegal index
 else result:=-1;
end;
{/**********************************\
 ==================================
 
           Input & Output
 
 ==================================
\**********************************/}
// print bitboard
procedure print_bitboard(bb:U64);
var
rank_,file_,sq:integer;
begin
Writeln('');
  // loop over board ranks
  for rank_ := 0 to 7 do  begin
        // loop over board files
        for file_ := 0 to 7 do  begin
           // convert file & rank into square index
           sq:=rank_*8 + file_;
           //// print ranks
           if file_ = 0 then begin
           Write(8 - rank_);Write(' ');
           end;
           Write(' ');
           // print bit state (either 1 or 0)
           Write(get_bit(bb,sq));
        end;
        // print new line every rank
        Writeln('');
  end;
  // print new line
  Writeln('');
  // print board files
  Writeln('   a b c d e f g h');
  Writeln('');
  // print bitboard as unsigned decimal number
  Write('bitboard = ',bb);
  Writeln('');
end;
{/**********************************\
 ==================================

              Attacks

 ==================================
\**********************************/}
// generate pawn attacks
function mask_pawn_attacks(side:TSide;square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // white pawns
    if (side=white) then begin
      if ((bitboard shr 7) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 7);
      if ((bitboard shr 9) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 9);
    end
    // black pawns
    else  begin
      if ((bitboard shl 7) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 7);
      if ((bitboard shl 9) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 9);
    end;
// return attack map
mask_pawn_attacks:=attacks;
end;
// generate knight attacks
function  mask_knight_attacks(square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // generate knight attacks
    if ((bitboard shr 17) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 17);
    if ((bitboard shr 15) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 15);
    if ((bitboard shr 10) and not_hg_file)>0 then  attacks:=attacks or (bitboard shr 10);
    if ((bitboard shr 6) and not_ab_file)>0 then  attacks:=attacks or (bitboard shr 6);
    if ((bitboard shl 17) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 17);
    if ((bitboard shl 15) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 15);
    if ((bitboard shl 10) and not_ab_file)>0 then  attacks:=attacks or (bitboard shl 10);
    if ((bitboard shl 6) and not_hg_file)>0 then  attacks:=attacks or (bitboard shl 6);
// return attack map
mask_knight_attacks:=attacks;
end;
// generate king attacks
function  mask_king_attacks(square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // generate king attacks
    if (bitboard shr 8)>0 then  attacks:=attacks or (bitboard shr 8);
    if ((bitboard shr 9) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 9);
    if ((bitboard shr 1) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 1);
    if ((bitboard shr 7) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 7);
    if (bitboard shl 8)>0 then  attacks:=attacks or (bitboard shl 8);
    if ((bitboard shl 9) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 9);
    if ((bitboard shl 1) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 1);
    if ((bitboard shl 7) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 7);
// return attack map
mask_king_attacks:=attacks;
end;
//урок 6-masking relevant bishop occupancy bits to form a key for MAGIC BITBOARDS
// mask bishop attacks
function   mask_bishop_attacks(square:TBoard_squares):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // mask relevant bishop occupancy bits
    f:=tf+1;
    for r:=tr+1 to 6 do begin
       if f>6 then break;
       attacks := attacks or (n shl (r*8+f));
       Inc(f);
    end;
    f:=tf+1;
    for r:=tr-1 downto 1 do begin
       if f>6 then break;
       attacks := attacks or (n shl (r*8+f));
       Inc(f);
    end;
    f:=tf-1;
    for r:=tr+1 to 6 do begin
       if f<1 then break;
       attacks := attacks or (n shl (r*8+f));
       Dec(f);
    end;
    f:=tf-1;
    for r:=tr-1 downto 1 do begin
       if f<1 then break;
       attacks := attacks or (n shl (r*8+f));
       Dec(f);
    end;
// return attack map
mask_bishop_attacks:=attacks;
end;
//урок 7-masking relevant ROOK OCCUPANCY BITS to form a key for MAGIC BITBOARDS
// mask rook attacks
function   mask_rook_attacks(square:TBoard_squares):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // mask relevant bishop occupancy bits
    for r:=tr+1 to 6 do attacks := attacks or (n shl (r*8+tf));
    for r:=tr-1 downto 1 do attacks := attacks or (n shl (r*8+tf));
    for f:=tf+1 to 6 do attacks := attacks or (n shl (tr*8+f));
    for f:=tf-1 downto 1 do attacks := attacks or (n shl (tr*8+f));
// return attack map
mask_rook_attacks:=attacks;
end;
//урок 8-generating SLIDER PIECES ATTACKS on the fly for MAGIC BITBOARD purposes
// generate bishop attacks on the fly
function  bishop_attacks_on_the_fly(square:TBoard_squares;blk:U64):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // generate bishop atacks
    f:=tf+1;
    for r:=tr+1 to 7 do begin
       if f>7 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Inc(f);
    end;
        f:=tf+1;
    for r:=tr-1 downto 0 do begin
       if f>7 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Inc(f);
    end;
    f:=tf-1;
    for r:=tr+1 to 7 do begin
       if f<0 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Dec(f);
    end;
    f:=tf-1;
    for r:=tr-1 downto 0 do begin
       if f<0 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Dec(f);
    end;
// return attack map
bishop_attacks_on_the_fly:=attacks;
end;
// generate rook attacks on the fly
function  rook_attacks_on_the_fly(square:TBoard_squares;blk:U64):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // generate rook attacks
    for r:=tr+1 to 7 do begin
    attacks := attacks or (n shl (r*8+tf));
    if ((n shl (r*8+tf)) and blk)>0 then  break;
    end;
    for r:=tr-1 downto 0 do begin
    attacks := attacks or (n shl (r*8+tf));
    if ((n shl (r*8+tf)) and blk)>0 then  break;
    end;
    for f:=tf+1 to 7 do begin
    attacks := attacks or (n shl (tr*8+f));
    if ((n shl (tr*8+f)) and blk)>0 then  break;
    end;
    for f:=tf-1 downto 0 do begin
    attacks := attacks or (n shl (tr*8+f));
    if ((n shl (tr*8+f)) and blk)>0 then  break;
    end;
// return attack map
rook_attacks_on_the_fly:=attacks;
end;
// init leaper pieces attacks
procedure init_leapers_attacks();
var
square:TBoard_squares;
begin
    // loop over 64 board squares
    for square := a8 to h1 do  begin
//урок 3-generating pre-calculated PAWN ATTACK tables
       // init pawn attacks
       pawn_attacks[white][square] := mask_pawn_attacks(white,square);
       pawn_attacks[black][square] := mask_pawn_attacks(black,square);
//урок 4-generating pre-calculated KNIGHT ATTACK table
       // init knight attacks
       knight_attacks[square] := mask_knight_attacks(square);
//урок 5-generating pre-calculated KING ATTACK tables
       // init king attacks
       king_attacks[square] := mask_king_attacks(square);
    end;
end;
{/**********************************\
 ==================================

             Main driver
 
 ==================================
\**********************************/}
 begin
  //Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  //Если после переключения русские буквы показываются неверно,
  //следует открыть системное меню консольного окна - щелчком мыши в левом
  //верхнем углу окна консоли. И выбрать:
  //Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
// ==================================
  init_leapers_attacks();
  block:=4512464976740352;
  print_bitboard(block);
  square:=TBoard_squares(get_ls1b_index(block));
  Write('get_ls1b_index:',get_ls1b_index(block));
  Writeln('  coordinate:',square_to_coordinates[Ord(square)]);
  set_bit(bitboard,square);
  print_bitboard(bitboard);
  Writeln('Нажмите <ENTER>, чтобы выйти ...');
  Readln;
end.

Bitboard в программировании шахмат №2 24 Янв 2023 09:47 #122

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
Разобрался с 11 уроком - Bitboard CHESS ENGINE in C: populating OCCUPANCY sets to multiply them later by MAGIC NUMBERS.
Пока это все подготовка к реализации Magic Bitboards
В этом уроке описывается функция нызываемая - начальными занятиями (set_occupancy).
По сути это комбинация всех различных расположений фигур на линии атаки скользящей фигуры (ладьи, слона).







8/8/8/8/8/8/8/R7
Например при ладье на a1 и ее атаках по линиям A2-A7 и B1-G1 (края доски не учитываются), теоретически эти поля могут быть заняты другими фигурами в различных комбинациях. По сути мы имеем дело с 6 клетками по вертикали и 6 по горизонали.
6 клеток это число с 6 включенными битами, соответствует числу 63.
Правило умножения (основная формула комбинаторики)
Общее число N способов, которыми можно выбрать по одному элементу из каждой группы и расставить их в определенном порядке (то есть получить упорядоченную совокупность a,b,c,d), равно:
N=n1*n2*n3* ... nk
T.e. в нашел случае при ладье на a1
N=64*64=4096 различных комбинаций занятости этих линий.
В двоичном виде это число выглядит так

41.jpg


По сути пробегая в цикле от нуля до 4095 мы получим все эти различные комбинации перестановок
block:=mask_rook_attacks(a1);
  print_bitboard(block);
  for i:=0 to 4095 do begin
  block:=mask_rook_attacks(a1);
  bitboard:=set_occupancy(i,count_bits(block),block);
  print_bitboard(bitboard);
  Readln;
  end;
  Writeln('Нажмите <ENTER>, чтобы выйти ...');
  Readln;
// make sure occupancy is on board
               if (index and (1 shl count))>0 then
                   occupancy:=occupancy or (n shl integer(square_));
Index -это как раз число перестановок (в конкретном случае - 4096)
Т.е. пробигая по вариантам занятости for i:=0 to 4095 при условии - i and (1 shl count) мы находим установленный бит и и получаем конкретную занятость для i.
Короче вот реализация на Делфи
// set occupancies
//перебираем по очереди биты в attack_mask
function set_occupancy(index,bits_in_mask:integer;var attack_mask:U64):U64;
var
occupancy,n:U64;
count:integer;
square_:TBoard_squares;
begin
n:=1;
// occupancy map
occupancy:=0;
            // loop over the range of bits within attack mask
            for count:=0 to bits_in_mask-1 do begin
               // get LS1B index of attacks mask
               square_:=TBoard_squares(get_ls1b_index(attack_mask));
               // pop LS1B in attack map
               pop_bit(attack_mask,square_);
               // make sure occupancy is on board
               if (index and (n shl count))>0 then
                   occupancy:=occupancy or (n shl integer(square_));
            end;
set_occupancy:=occupancy;
end;
Last Edit: 24 Янв 2023 10:02 by alexlaw.

Bitboard в программировании шахмат №2 24 Янв 2023 11:08 #123

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
12 урок - Bitboard CHESS ENGINE in C: generating relevant OCCUPANCY BIT COUNT lookup tables for sliding pieces

Просто заполнение таблицы количеста атакуемых клеток скользящих фигур из каждой клетки доски
// bishop relevant occupancy bit count for every square on board
bishop_relevant_bits: array [0..63]  of  integer =(
    6, 5, 5, 5, 5, 5, 5, 6,
    5, 5, 5, 5, 5, 5, 5, 5, 
    5, 5, 7, 7, 7, 7, 5, 5, 
    5, 5, 7, 9, 9, 7, 5, 5, 
    5, 5, 7, 9, 9, 7, 5, 5, 
    5, 5, 7, 7, 7, 7, 5, 5, 
    5, 5, 5, 5, 5, 5, 5, 5, 
    6, 5, 5, 5, 5, 5, 5, 6
);

// rook relevant occupancy bit count for every square on board
rook_relevant_bits: array [0..63]  of  integer =(
    12, 11, 11, 11, 11, 11, 11, 12, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    12, 11, 11, 11, 11, 11, 11, 12
);
Writeln('bishop_relevant_bits');
  for square := a8 to h1 do  begin
    if (((integer(square) mod 8)=0) and (square > a8)) then  Writeln('');
     Write(count_bits(mask_bishop_attacks(square))); Write(' ');
  end;
  Writeln('');
  Writeln('rook_relevant_bits');
    for square := a8 to h1 do  begin
    if (((integer(square) mod 8)=0) and (square > a8)) then  Writeln('');
     Write(count_bits(mask_rook_attacks(square))); Write(' ');
  end;
  Writeln('');
  Writeln('Нажмите <ENTER>, чтобы выйти ...');
  Readln;

42.jpg

Bitboard в программировании шахмат №2 25 Янв 2023 05:11 #124

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
Уроки 13 и 14
13.Bitboard CHESS ENGINE in C: implementing pseudo RANDOM NUMBER generator using XORSHIFT32 algorithm
14.Bitboard CHESS ENGINE in C: generating MAGIC NUMBER candidates

Макс рассказывает как сгенерировать числа - кандитаты в магические числа.
По сути - это псевдослучайные числа.
И самое интересное, далее он расскажет, как их использовать в качестве магических чисел.
{/**********************************\
 ==================================
 
           Random numbers
 
 ==================================
\**********************************/}
// generate 32-bit pseudo legal numbers
function  get_random_U32_number():cardinal;
begin
// XOR shift algorithm
stateU32:=stateU32 xor (stateU32 shl 13);
stateU32:=stateU32 xor (stateU32 shr 17);
stateU32:=stateU32 xor (stateU32 shl 5);
get_random_U32_number:=stateU32;
end;
// generate 64-bit pseudo legal numbers
function  get_random_U64_number():U64;
var
// define 4 random numbers
n1,n2,n3,n4:U64;
begin
n1:=0;n2:=0;n3:=0; n4:=0;
// init random numbers slicing 16 bits from MS1B side
n1:=n1 or (get_random_U32_number() and $FFFF);
n2:=n2 or (get_random_U32_number() and $FFFF);
n3:=n3 or (get_random_U32_number() and $FFFF);
n4:=n4 or (get_random_U32_number() and $FFFF);
// return random number
get_random_U64_number:=n1 or (n2 shl 16) or (n3 shl 32) or (n4 shl 48);
end;
// generate magic number candidate
function generate_magic_number():U64;
begin
  result:=get_random_U64_number() and get_random_U64_number() and get_random_U64_number();
end;

Хотя эти числа всегда одни и те же, но раз это работает, то делаем так же.

43.jpg


44.jpg

Bitboard в программировании шахмат №2 25 Янв 2023 13:24 #125

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
Попытка объяснить Magic Bitboard

Bitboard в программировании шахмат №2 27 Янв 2023 12:53 #126

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
Урок 15.Bitboard CHESS ENGINE in C: generating MAGIC NUMBERS via brute force trial and error method.
Разобрался с этим уроком - генерация магических чисел.
Попробую рассказать свое понимание этого.
Итак, какие исходные данные есть у нас.
1. Позиция дальнобойной фигуры (например ладья на a1)
TBoard_squares = (
a8, b8, c8, d8, e8, f8, g8, h8,
a7, b7, c7, d7, e7, f7, g7, h7,
a6, b6, c6, d6, e6, f6, g6, h6,
a5, b5, c5, d5, e5, f5, g5, h5,
a4, b4, c4, d4, e4, f4, g4, h4,
a3, b3, c3, d3, e3, f3, g3, h3,
a2, b2, c2, d2, e2, f2, g2, h2,
a1, b1, c1, d1, e1, f1, g1, h1
);
2. Количество атакуемых клеток из этой позиции при отсутствии блокирующих фигур (края доски не учитываются)
(ладья на a1 атакует 6 клеток по горизонтали, 6 по вертикали: всего 12)
// rook relevant occupancy bit count for every square on board
rook_relevant_bits: array [0..63] of integer =(
12, 11, 11, 11, 11, 11, 11, 12,
11, 10, 10, 10, 10, 10, 10, 11,
11, 10, 10, 10, 10, 10, 10, 11,
11, 10, 10, 10, 10, 10, 10, 11,
11, 10, 10, 10, 10, 10, 10, 11,
11, 10, 10, 10, 10, 10, 10, 11,
11, 10, 10, 10, 10, 10, 10, 11,
12, 11, 11, 11, 11, 11, 11, 12
);

Производные от первоначальных данных
1.битбоард атаки (ладьи) этих 12 клеток
attack_mask:=mask_bishop_attacks(square)
2. Количество перестановок блокирующих фигур на атакуемых ладьей полях
occupancy_indicies:integer;
- 64*64
- 2 в степени 12
- 1 << 12
occupancy_indicies:=1 shl relevant_bits;
3.Комбинации занятости блокирующих фигур
occupancies:array[0..4095] of U64;
4.Самое важное это атаки с учетом блокирующих фигур
// init attack tables
attacks:array[0..4095] of U64;

Вроде бы все прекрасно - эти атаки нам и нужны в идеале.
Но есть одно большое НО.
Чтобы найти их в таблице array[0..4095], придется долго и упорно ее перелапачивать.

Умные люди решили проблему так -
Придумать такую хэш функция, чтобы с помощью простого ключа быстро находить нужные атаки в таблице.
Ключ, это и есть - магическое число с простыми манипуляциями с ним.
Это как подойти к реальной двери, глянуть на скважину замка, достать отмычку, туда сюда ее изогнуть на глаз и пробовать открыть замок.

Этот урок Макса, как раз и есть, описание способа, гнуть отмычку туда сюда , чтобы получить ключ.
Способ такой.
1.Создается массив
// init used attacks
used_attacks:array[0..4095] of U64;
Инициализируется 0.
FillChar(used_attacks, 4096*SizeOf(UInt64), n); - делфи
memset(used_attacks, 0ULL, sizeof(used_attacks)); - СИ
2.U64 magic_number - генерируем 64 битные случайные числа
3.Подставляем ключ в хэш функцию
magic_index := integer((occupancies[index] * magic_number) shr (64 - relevant_bits)); - делфи
int magic_index = (int)((occupancies[index] * magic_number) >> (64 - relevant_bits)); - Си

Пробуем полученный ключ - если уже был другой ключ, то это коллизия ( ключ выбрасываем)

Как то так в моем понимании.

Bitboard в программировании шахмат №2 27 Янв 2023 12:54 #127

  • alexlaw
  • alexlaw's Avatar
  • OFFLINE
  • Жилец
  • Posts: 67
  • Karma: 0
На языке Си (Макс)
/**********************************\
 ==================================

             Didactic
       BITBOARD CHESS ENGINE

                by

         Code Monkey King

 ==================================
\**********************************/

// system headers
#include <stdio.h>
#include <string.h>

// define bitboard data type
#define U64 unsigned long long

// board squares
enum {
    a8, b8, c8, d8, e8, f8, g8, h8,
    a7, b7, c7, d7, e7, f7, g7, h7,
    a6, b6, c6, d6, e6, f6, g6, h6,
    a5, b5, c5, d5, e5, f5, g5, h5,
    a4, b4, c4, d4, e4, f4, g4, h4,
    a3, b3, c3, d3, e3, f3, g3, h3,
    a2, b2, c2, d2, e2, f2, g2, h2,
    a1, b1, c1, d1, e1, f1, g1, h1
};

// sides to move (colors)
enum { white, black };

// bishop and rook
enum { rook, bishop };

// convert squares to coordinates
const char *square_to_coordinates[] = {
    "a8", "b8", "c8", "d8", "e8", "f8", "g8", "h8",
    "a7", "b7", "c7", "d7", "e7", "f7", "g7", "h7",
    "a6", "b6", "c6", "d6", "e6", "f6", "g6", "h6",
    "a5", "b5", "c5", "d5", "e5", "f5", "g5", "h5",
    "a4", "b4", "c4", "d4", "e4", "f4", "g4", "h4",
    "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3",
    "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2",
    "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1",
};


/**********************************\
 ==================================

           Random numbers

 ==================================
\**********************************/

// pseudo random number state
unsigned int random_state = 1804289383;

// generate 32-bit pseudo legal numbers
unsigned int get_random_U32_number()
{
    // get current state
    unsigned int number = random_state;

    // XOR shift algorithm
    number ^= number << 13;
    number ^= number >> 17;
    number ^= number << 5;

    // update random number state
    random_state = number;

    // return random number
    return number;
}

// generate 64-bit pseudo legal numbers
U64 get_random_U64_number()
{
    // define 4 random numbers
    U64 n1, n2, n3, n4;

    // init random numbers slicing 16 bits from MS1B side
    n1 = (U64)(get_random_U32_number()) & 0xFFFF;
    n2 = (U64)(get_random_U32_number()) & 0xFFFF;
    n3 = (U64)(get_random_U32_number()) & 0xFFFF;
    n4 = (U64)(get_random_U32_number()) & 0xFFFF;

    // return random number
    return n1 | (n2 << 16) | (n3 << 32) | (n4 << 48);
}

// generate magic number candidate
U64 generate_magic_number()
{
    return get_random_U64_number() & get_random_U64_number() & get_random_U64_number();
}


/**********************************\
 ==================================

          Bit manipulations

 ==================================
\**********************************/

// set/get/pop bit macros
#define set_bit(bitboard, square) (bitboard |= (1ULL << square))
#define get_bit(bitboard, square) (bitboard & (1ULL << square))
#define pop_bit(bitboard, square) (get_bit(bitboard, square) ? bitboard ^= (1ULL << square) : 0)

// count bits within a bitboard (Brian Kernighan's way)
static inline int count_bits(U64 bitboard)
{
    // bit counter
    int count = 0;

    // consecutively reset least significant 1st bit
    while (bitboard)
    {
        // increment count
        count++;

        // reset least significant 1st bit
        bitboard &= bitboard - 1;
    }

    // return bit count
    return count;
}

// get least significant 1st bit index
static inline int get_ls1b_index(U64 bitboard)
{
    // make sure bitboard is not 0
    if (bitboard)
    {
        // count trailing bits before LS1B
        return count_bits((bitboard & -bitboard) - 1);
    }

    //otherwise
    else
        // return illegal index
        return -1;
}

/**********************************\
 ==================================

           Input & Output

 ==================================
\**********************************/

// print bitboard
void print_bitboard(U64 bitboard)
{
    printf("\n");

    // loop over board ranks
    for (int rank = 0; rank < 8; rank++)
    {
        // loop over board files
        for (int file = 0; file < 8; file++)
        {
            // convert file & rank into square index
            int square = rank * 8 + file;

            // print ranks
            if (!file)
                printf("  %d ", 8 - rank);

            // print bit state (either 1 or 0)
            printf(" %d", get_bit(bitboard, square) ? 1 : 0);

        }

        // print new line every rank
        printf("\n");
    }

    // print board files
    printf("\n     a b c d e f g h\n\n");

    // print bitboard as unsigned decimal number
    printf("     Bitboard: %llud\n\n", bitboard);
}


/**********************************\
 ==================================

              Attacks

 ==================================
\**********************************/

/*
        not A file
  8  0 1 1 1 1 1 1 1
  7  0 1 1 1 1 1 1 1
  6  0 1 1 1 1 1 1 1
  5  0 1 1 1 1 1 1 1
  4  0 1 1 1 1 1 1 1
  3  0 1 1 1 1 1 1 1
  2  0 1 1 1 1 1 1 1
  1  0 1 1 1 1 1 1 1
     a b c d e f g h
        not H file

  8  1 1 1 1 1 1 1 0
  7  1 1 1 1 1 1 1 0
  6  1 1 1 1 1 1 1 0
  5  1 1 1 1 1 1 1 0
  4  1 1 1 1 1 1 1 0
  3  1 1 1 1 1 1 1 0
  2  1 1 1 1 1 1 1 0
  1  1 1 1 1 1 1 1 0
     a b c d e f g h
       not HG file
  8  1 1 1 1 1 1 0 0
  7  1 1 1 1 1 1 0 0
  6  1 1 1 1 1 1 0 0
  5  1 1 1 1 1 1 0 0
  4  1 1 1 1 1 1 0 0
  3  1 1 1 1 1 1 0 0
  2  1 1 1 1 1 1 0 0
  1  1 1 1 1 1 1 0 0
     a b c d e f g h
       not AB file
  8  0 0 1 1 1 1 1 1
  7  0 0 1 1 1 1 1 1
  6  0 0 1 1 1 1 1 1
  5  0 0 1 1 1 1 1 1
  4  0 0 1 1 1 1 1 1
  3  0 0 1 1 1 1 1 1
  2  0 0 1 1 1 1 1 1
  1  0 0 1 1 1 1 1 1
     a b c d e f g h
*/

// not A file constant
const U64 not_a_file = 18374403900871474942ULL;

// not H file constant
const U64 not_h_file = 9187201950435737471ULL;

// not HG file constant
const U64 not_hg_file = 4557430888798830399ULL;

// not AB file constant
const U64 not_ab_file = 18229723555195321596ULL;

// bishop relevant occupancy bit count for every square on board
const int bishop_relevant_bits[64] = {
    6, 5, 5, 5, 5, 5, 5, 6,
    5, 5, 5, 5, 5, 5, 5, 5,
    5, 5, 7, 7, 7, 7, 5, 5,
    5, 5, 7, 9, 9, 7, 5, 5,
    5, 5, 7, 9, 9, 7, 5, 5,
    5, 5, 7, 7, 7, 7, 5, 5,
    5, 5, 5, 5, 5, 5, 5, 5,
    6, 5, 5, 5, 5, 5, 5, 6
};

// rook relevant occupancy bit count for every square on board
const int rook_relevant_bits[64] = {
    12, 11, 11, 11, 11, 11, 11, 12,
    11, 10, 10, 10, 10, 10, 10, 11,
    11, 10, 10, 10, 10, 10, 10, 11,
    11, 10, 10, 10, 10, 10, 10, 11,
    11, 10, 10, 10, 10, 10, 10, 11,
    11, 10, 10, 10, 10, 10, 10, 11,
    11, 10, 10, 10, 10, 10, 10, 11,
    12, 11, 11, 11, 11, 11, 11, 12
};

// rook magic numbers
U64 rook_magic_numbers[64] = {
    0x8a80104000800020ULL,
    0x140002000100040ULL,
    0x2801880a0017001ULL,
    0x100081001000420ULL,
    0x200020010080420ULL,
    0x3001c0002010008ULL,
    0x8480008002000100ULL,
    0x2080088004402900ULL,
    0x800098204000ULL,
    0x2024401000200040ULL,
    0x100802000801000ULL,
    0x120800800801000ULL,
    0x208808088000400ULL,
    0x2802200800400ULL,
    0x2200800100020080ULL,
    0x801000060821100ULL,
    0x80044006422000ULL,
    0x100808020004000ULL,
    0x12108a0010204200ULL,
    0x140848010000802ULL,
    0x481828014002800ULL,
    0x8094004002004100ULL,
    0x4010040010010802ULL,
    0x20008806104ULL,
    0x100400080208000ULL,
    0x2040002120081000ULL,
    0x21200680100081ULL,
    0x20100080080080ULL,
    0x2000a00200410ULL,
    0x20080800400ULL,
    0x80088400100102ULL,
    0x80004600042881ULL,
    0x4040008040800020ULL,
    0x440003000200801ULL,
    0x4200011004500ULL,
    0x188020010100100ULL,
    0x14800401802800ULL,
    0x2080040080800200ULL,
    0x124080204001001ULL,
    0x200046502000484ULL,
    0x480400080088020ULL,
    0x1000422010034000ULL,
    0x30200100110040ULL,
    0x100021010009ULL,
    0x2002080100110004ULL,
    0x202008004008002ULL,
    0x20020004010100ULL,
    0x2048440040820001ULL,
    0x101002200408200ULL,
    0x40802000401080ULL,
    0x4008142004410100ULL,
    0x2060820c0120200ULL,
    0x1001004080100ULL,
    0x20c020080040080ULL,
    0x2935610830022400ULL,
    0x44440041009200ULL,
    0x280001040802101ULL,
    0x2100190040002085ULL,
    0x80c0084100102001ULL,
    0x4024081001000421ULL,
    0x20030a0244872ULL,
    0x12001008414402ULL,
    0x2006104900a0804ULL,
    0x1004081002402ULL
};

// bishop magic numbers
U64 bishop_magic_numbers[64] = {
    0x40040844404084ULL,
    0x2004208a004208ULL,
    0x10190041080202ULL,
    0x108060845042010ULL,
    0x581104180800210ULL,
    0x2112080446200010ULL,
    0x1080820820060210ULL,
    0x3c0808410220200ULL,
    0x4050404440404ULL,
    0x21001420088ULL,
    0x24d0080801082102ULL,
    0x1020a0a020400ULL,
    0x40308200402ULL,
    0x4011002100800ULL,
    0x401484104104005ULL,
    0x801010402020200ULL,
    0x400210c3880100ULL,
    0x404022024108200ULL,
    0x810018200204102ULL,
    0x4002801a02003ULL,
    0x85040820080400ULL,
    0x810102c808880400ULL,
    0xe900410884800ULL,
    0x8002020480840102ULL,
    0x220200865090201ULL,
    0x2010100a02021202ULL,
    0x152048408022401ULL,
    0x20080002081110ULL,
    0x4001001021004000ULL,
    0x800040400a011002ULL,
    0xe4004081011002ULL,
    0x1c004001012080ULL,
    0x8004200962a00220ULL,
    0x8422100208500202ULL,
    0x2000402200300c08ULL,
    0x8646020080080080ULL,
    0x80020a0200100808ULL,
    0x2010004880111000ULL,
    0x623000a080011400ULL,
    0x42008c0340209202ULL,
    0x209188240001000ULL,
    0x400408a884001800ULL,
    0x110400a6080400ULL,
    0x1840060a44020800ULL,
    0x90080104000041ULL,
    0x201011000808101ULL,
    0x1a2208080504f080ULL,
    0x8012020600211212ULL,
    0x500861011240000ULL,
    0x180806108200800ULL,
    0x4000020e01040044ULL,
    0x300000261044000aULL,
    0x802241102020002ULL,
    0x20906061210001ULL,
    0x5a84841004010310ULL,
    0x4010801011c04ULL,
    0xa010109502200ULL,
    0x4a02012000ULL,
    0x500201010098b028ULL,
    0x8040002811040900ULL,
    0x28000010020204ULL,
    0x6000020202d0240ULL,
    0x8918844842082200ULL,
    0x4010011029020020ULL
};

// pawn attacks table [side][square]
U64 pawn_attacks[2][64];

// knight attacks table [square]
U64 knight_attacks[64];

// king attacks table [square]
U64 king_attacks[64];

// generate pawn attacks
U64 mask_pawn_attacks(int side, int square)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // piece bitboard
    U64 bitboard = 0ULL;

    // set piece on board
    set_bit(bitboard, square);

    // white pawns
    if (!side)
    {
        // generate pawn attacks
        if ((bitboard >> 7) & not_a_file) attacks |= (bitboard >> 7);
        if ((bitboard >> 9) & not_h_file) attacks |= (bitboard >> 9);
    }

    // black pawns
    else
    {
        // generate pawn attacks
        if ((bitboard << 7) & not_h_file) attacks |= (bitboard << 7);
        if ((bitboard << 9) & not_a_file) attacks |= (bitboard << 9);
    }

    // return attack map
    return attacks;
}

// generate knight attacks
U64 mask_knight_attacks(int square)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // piece bitboard
    U64 bitboard = 0ULL;

    // set piece on board
    set_bit(bitboard, square);

    // generate knight attacks
    if ((bitboard >> 17) & not_h_file) attacks |= (bitboard >> 17);
    if ((bitboard >> 15) & not_a_file) attacks |= (bitboard >> 15);
    if ((bitboard >> 10) & not_hg_file) attacks |= (bitboard >> 10);
    if ((bitboard >> 6) & not_ab_file) attacks |= (bitboard >> 6);
    if ((bitboard << 17) & not_a_file) attacks |= (bitboard << 17);
    if ((bitboard << 15) & not_h_file) attacks |= (bitboard << 15);
    if ((bitboard << 10) & not_ab_file) attacks |= (bitboard << 10);
    if ((bitboard << 6) & not_hg_file) attacks |= (bitboard << 6);

    // return attack map
    return attacks;
}

// generate king attacks
U64 mask_king_attacks(int square)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // piece bitboard
    U64 bitboard = 0ULL;

    // set piece on board
    set_bit(bitboard, square);

    // generate king attacks
    if (bitboard >> 8) attacks |= (bitboard >> 8);
    if ((bitboard >> 9) & not_h_file) attacks |= (bitboard >> 9);
    if ((bitboard >> 7) & not_a_file) attacks |= (bitboard >> 7);
    if ((bitboard >> 1) & not_h_file) attacks |= (bitboard >> 1);
    if (bitboard << 8) attacks |= (bitboard << 8);
    if ((bitboard << 9) & not_a_file) attacks |= (bitboard << 9);
    if ((bitboard << 7) & not_h_file) attacks |= (bitboard << 7);
    if ((bitboard << 1) & not_a_file) attacks |= (bitboard << 1);

    // return attack map
    return attacks;
}

// mask bishop attacks
U64 mask_bishop_attacks(int square)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // init ranks & files
    int r, f;

    // init target rank & files
    int tr = square / 8;
    int tf = square % 8;

    // mask relevant bishop occupancy bits
    for (r = tr + 1, f = tf + 1; r <= 6 && f <= 6; r++, f++) attacks |= (1ULL << (r * 8 + f));
    for (r = tr - 1, f = tf + 1; r >= 1 && f <= 6; r--, f++) attacks |= (1ULL << (r * 8 + f));
    for (r = tr + 1, f = tf - 1; r <= 6 && f >= 1; r++, f--) attacks |= (1ULL << (r * 8 + f));
    for (r = tr - 1, f = tf - 1; r >= 1 && f >= 1; r--, f--) attacks |= (1ULL << (r * 8 + f));

    // return attack map
    return attacks;
}

// mask rook attacks
U64 mask_rook_attacks(int square)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // init ranks & files
    int r, f;

    // init target rank & files
    int tr = square / 8;
    int tf = square % 8;

    // mask relevant rook occupancy bits
    for (r = tr + 1; r <= 6; r++) attacks |= (1ULL << (r * 8 + tf));
    for (r = tr - 1; r >= 1; r--) attacks |= (1ULL << (r * 8 + tf));
    for (f = tf + 1; f <= 6; f++) attacks |= (1ULL << (tr * 8 + f));
    for (f = tf - 1; f >= 1; f--) attacks |= (1ULL << (tr * 8 + f));

    // return attack map
    return attacks;
}

// generate bishop attacks on the fly
U64 bishop_attacks_on_the_fly(int square, U64 block)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // init ranks & files
    int r, f;

    // init target rank & files
    int tr = square / 8;
    int tf = square % 8;

    // generate bishop atacks
    for (r = tr + 1, f = tf + 1; r <= 7 && f <= 7; r++, f++)
    {
        attacks |= (1ULL << (r * 8 + f));
        if ((1ULL << (r * 8 + f)) & block) break;
    }

    for (r = tr - 1, f = tf + 1; r >= 0 && f <= 7; r--, f++)
    {
        attacks |= (1ULL << (r * 8 + f));
        if ((1ULL << (r * 8 + f)) & block) break;
    }

    for (r = tr + 1, f = tf - 1; r <= 7 && f >= 0; r++, f--)
    {
        attacks |= (1ULL << (r * 8 + f));
        if ((1ULL << (r * 8 + f)) & block) break;
    }

    for (r = tr - 1, f = tf - 1; r >= 0 && f >= 0; r--, f--)
    {
        attacks |= (1ULL << (r * 8 + f));
        if ((1ULL << (r * 8 + f)) & block) break;
    }

    // return attack map
    return attacks;
}

// generate rook attacks on the fly
U64 rook_attacks_on_the_fly(int square, U64 block)
{
    // result attacks bitboard
    U64 attacks = 0ULL;

    // init ranks & files
    int r, f;

    // init target rank & files
    int tr = square / 8;
    int tf = square % 8;

    // generate rook attacks
    for (r = tr + 1; r <= 7; r++)
    {
        attacks |= (1ULL << (r * 8 + tf));
        if ((1ULL << (r * 8 + tf)) & block) break;
    }

    for (r = tr - 1; r >= 0; r--)
    {
        attacks |= (1ULL << (r * 8 + tf));
        if ((1ULL << (r * 8 + tf)) & block) break;
    }

    for (f = tf + 1; f <= 7; f++)
    {
        attacks |= (1ULL << (tr * 8 + f));
        if ((1ULL << (tr * 8 + f)) & block) break;
    }

    for (f = tf - 1; f >= 0; f--)
    {
        attacks |= (1ULL << (tr * 8 + f));
        if ((1ULL << (tr * 8 + f)) & block) break;
    }

    // return attack map
    return attacks;
}

// init leaper pieces attacks
void init_leapers_attacks()
{
    // loop over 64 board squares
    for (int square = 0; square < 64; square++)
    {
        // init pawn attacks
        pawn_attacks[white][square] = mask_pawn_attacks(white, square);
        pawn_attacks[black][square] = mask_pawn_attacks(black, square);

        // init knight attacks
        knight_attacks[square] = mask_knight_attacks(square);

        // init king attacks
        king_attacks[square] = mask_king_attacks(square);
    }
}

// set occupancies
U64 set_occupancy(int index, int bits_in_mask, U64 attack_mask)
{
    // occupancy map
    U64 occupancy = 0ULL;

    // loop over the range of bits within attack mask
    for (int count = 0; count < bits_in_mask; count++)
    {
        // get LS1B index of attacks mask
        int square = get_ls1b_index(attack_mask);

        // pop LS1B in attack map
        pop_bit(attack_mask, square);

        // make sure occupancy is on board
        if (index & (1 << count))
            // populate occupancy map
            occupancy |= (1ULL << square);
    }

    // return occupancy map
    return occupancy;
}


/**********************************\
 ==================================

               Magics

 ==================================
\**********************************/

// find appropriate magic number
U64 find_magic_number(int square, int relevant_bits, int bishop)
{
    // init occupancies
    U64 occupancies[4096];

    // init attack tables
    U64 attacks[4096];

    // init used attacks
    U64 used_attacks[4096];

    // init attack mask for a current piece
    U64 attack_mask = bishop ? mask_bishop_attacks(square) : mask_rook_attacks(square);

    // init occupancy indicies
    int occupancy_indicies = 1 << relevant_bits;

    // loop over occupancy indicies
    for (int index = 0; index < occupancy_indicies; index++)
    {
        // init occupancies
        occupancies[index] = set_occupancy(index, relevant_bits, attack_mask);

        // init attacks
        attacks[index] = bishop ? bishop_attacks_on_the_fly(square, occupancies[index]) :
                                    rook_attacks_on_the_fly(square, occupancies[index]);
    }

    // test magic numbers loop
    for (int random_count = 0; random_count < 100000000; random_count++)
    {
        // generate magic number candidate
        U64 magic_number = generate_magic_number();

        // skip inappropriate magic numbers
        if (count_bits((attack_mask * magic_number) & 0xFF00000000000000) < 6) continue;

        // init used attacks
        memset(used_attacks, 0ULL, sizeof(used_attacks));

        // init index & fail flag
        int index, fail;

        // test magic index loop
        for (index = 0, fail = 0; !fail && index < occupancy_indicies; index++)
        {
            // init magic index
            int magic_index = (int)((occupancies[index] * magic_number) >> (64 - relevant_bits));
            //printf("occupancies[%d] = %llud\n\n",index,occupancies[index]);
            //printf("magic_index = %d\n\n", magic_index);
            //printf("magic_number = %llud\n\n", magic_number);
            //getchar();
            // if magic index works
            if (used_attacks[magic_index] == 0ULL)
                // init used attacks
                used_attacks[magic_index] = attacks[index];

            // otherwise
            else if (used_attacks[magic_index] != attacks[index])
                // magic index doesn't work
                fail = 1;
        }

        // if magic number works
        if (!fail)
            // return it
            return magic_number;
    }

    // if magic number doesn't work
    printf("  Magic number fails!\n");
    return 0ULL;
}

// init magic numbers
void init_magic_numbers()
{
    // loop over 64 board squares
    for (int square = 0; square < 64; square++)
        // init rook magic numbers
        rook_magic_numbers[square] = find_magic_number(square, rook_relevant_bits[square], rook);

    // loop over 64 board squares
    for (int square = 0; square < 64; square++)
        // init bishop magic numbers
        bishop_magic_numbers[square] = find_magic_number(square, bishop_relevant_bits[square], bishop);
}


/**********************************\
 ==================================

              Init all

 ==================================
\**********************************/

// init all variables
void init_all()
{
    // init leaper pieces attacks
    init_leapers_attacks();

    // init magic numbers
    init_magic_numbers();
}

/**********************************\
 ==================================

             Main driver

 ==================================
\**********************************/

int main()
{
    // init all
    init_all();


    return 0;
}





Делфи
program bbc;

{$APPTYPE CONSOLE}

uses
  SysUtils,Windows,TypInfo;
type
    U64 = UInt64;
    TBoard_squares = (
    a8, b8, c8, d8, e8, f8, g8, h8,
    a7, b7, c7, d7, e7, f7, g7, h7,
    a6, b6, c6, d6, e6, f6, g6, h6,
    a5, b5, c5, d5, e5, f5, g5, h5,
    a4, b4, c4, d4, e4, f4, g4, h4,
    a3, b3, c3, d3, e3, f3, g3, h3,
    a2, b2, c2, d2, e2, f2, g2, h2,
    a1, b1, c1, d1, e1, f1, g1, h1
    );
    // sides to move (colors)
    TSide = (white, black);
    // bishop and rook
    Tbishop = (rook, bishop);
    //Первый индекс обозначает номер строки в матрице, второй индекс – номер столбца
    TPawn_attacks=array[TSide,TBoard_squares] of U64;
    TChip_attacks=array[TBoard_squares] of U64;
var
 bitboard:U64=0;
 block:U64=0;
 // pawn attacks table [side][square]
 pawn_attacks:TPawn_attacks;
 // knight attacks table [square]
 knight_attacks:TChip_attacks;
 // king attacks table [square]
 king_attacks:TChip_attacks;
 square:TBoard_squares;
 // pseudo random number state
 //cardinal - беззнаковое целое
 stateU32:cardinal = 1804289383;
const
{/*
        not A file
  8  0 1 1 1 1 1 1 1
  7  0 1 1 1 1 1 1 1
  6  0 1 1 1 1 1 1 1
  5  0 1 1 1 1 1 1 1
  4  0 1 1 1 1 1 1 1
  3  0 1 1 1 1 1 1 1
  2  0 1 1 1 1 1 1 1
  1  0 1 1 1 1 1 1 1
     a b c d e f g h
        not H file
  8  1 1 1 1 1 1 1 0
  7  1 1 1 1 1 1 1 0
  6  1 1 1 1 1 1 1 0
  5  1 1 1 1 1 1 1 0
  4  1 1 1 1 1 1 1 0
  3  1 1 1 1 1 1 1 0
  2  1 1 1 1 1 1 1 0
  1  1 1 1 1 1 1 1 0
     a b c d e f g h
       not HG file
  8  1 1 1 1 1 1 0 0
  7  1 1 1 1 1 1 0 0
  6  1 1 1 1 1 1 0 0
  5  1 1 1 1 1 1 0 0
  4  1 1 1 1 1 1 0 0
  3  1 1 1 1 1 1 0 0
  2  1 1 1 1 1 1 0 0
  1  1 1 1 1 1 1 0 0
     a b c d e f g h
       not AB file
  8  0 0 1 1 1 1 1 1
  7  0 0 1 1 1 1 1 1
  6  0 0 1 1 1 1 1 1
  5  0 0 1 1 1 1 1 1
  4  0 0 1 1 1 1 1 1
  3  0 0 1 1 1 1 1 1
  2  0 0 1 1 1 1 1 1
  1  0 0 1 1 1 1 1 1
     a b c d e f g h
*/}

// not A file constant
not_a_file:U64 = $FEFEFEFEFEFEFEFE;//18374403900871474942;
// not H file constant
not_h_file:U64 = $7F7F7F7F7F7F7F7F;//9187201950435737471;
// not HG file constant
not_hg_file:U64 =$3F3F3F3F3F3F3F3F;//4557430888798830399;
// not AB file constant
not_ab_file:U64 =$FCFCFCFCFCFCFCFC;//18229723555195321596;
square_to_coordinates: array [0..63]  of  string =  (
    'a8', 'b8', 'c8', 'd8', 'e8', 'f8', 'g8', 'h8',
    'a7', 'b7', 'c7', 'd7', 'e7', 'f7', 'g7', 'h7',
    'a6', 'b6', 'c6', 'd6', 'e6', 'f6', 'g6', 'h6',
    'a5', 'b5', 'c5', 'd5', 'e5', 'f5', 'g5', 'h5',
    'a4', 'b4', 'c4', 'd4', 'e4', 'f4', 'g4', 'h4',
    'a3', 'b3', 'c3', 'd3', 'e3', 'f3', 'g3', 'h3',
    'a2', 'b2', 'c2', 'd2', 'e2', 'f2', 'g2', 'h2',
    'a1', 'b1', 'c1', 'd1', 'e1', 'f1', 'g1', 'h1'
);
// bishop relevant occupancy bit count for every square on board
bishop_relevant_bits: array [0..63]  of  integer =(
    6, 5, 5, 5, 5, 5, 5, 6,
    5, 5, 5, 5, 5, 5, 5, 5, 
    5, 5, 7, 7, 7, 7, 5, 5, 
    5, 5, 7, 9, 9, 7, 5, 5, 
    5, 5, 7, 9, 9, 7, 5, 5, 
    5, 5, 7, 7, 7, 7, 5, 5, 
    5, 5, 5, 5, 5, 5, 5, 5, 
    6, 5, 5, 5, 5, 5, 5, 6
);

// rook relevant occupancy bit count for every square on board
rook_relevant_bits: array [0..63]  of  integer =(
    12, 11, 11, 11, 11, 11, 11, 12, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    11, 10, 10, 10, 10, 10, 10, 11, 
    12, 11, 11, 11, 11, 11, 11, 12
);
{/**********************************\
 ==================================
 
           Random numbers
 
 ==================================
\**********************************/}
// generate 32-bit pseudo legal numbers
function  get_random_U32_number():cardinal;
begin
// XOR shift algorithm
stateU32:=stateU32 xor (stateU32 shl 13);
stateU32:=stateU32 xor (stateU32 shr 17);
stateU32:=stateU32 xor (stateU32 shl 5);
get_random_U32_number:=stateU32;
end;
// generate 64-bit pseudo legal numbers
function  get_random_U64_number():U64;
var
// define 4 random numbers
n1,n2,n3,n4:U64;
begin
n1:=0;n2:=0;n3:=0; n4:=0;
// init random numbers slicing 16 bits from MS1B side
n1:=(n1 or (get_random_U32_number())) and $FFFF;
n2:=(n2 or (get_random_U32_number())) and $FFFF;
n3:=(n3 or (get_random_U32_number())) and $FFFF;
n4:=(n4 or (get_random_U32_number())) and $FFFF;
// return random number
get_random_U64_number:=n1 or (n2 shl 16) or (n3 shl 32) or (n4 shl 48);
end;
// generate magic number candidate
function generate_magic_number():U64;
begin
  result:=get_random_U64_number() and get_random_U64_number() and get_random_U64_number();
end;
{/**********************************\
 ==================================
 
          Bit manipulations
 
 ==================================
\**********************************/}
// set/get/pop
function get_bit(bb:U64;const sq:integer):integer;
begin
get_bit:=(bb shr sq) and 1;
end;
procedure set_bit(var bb:U64;const sq:TBoard_squares);
begin
bb:=bb or ($8000000000000000 shr (63-Ord(sq)));
end;
procedure pop_bit(var bb:U64;const sq:TBoard_squares);
begin
if get_bit(bb,Ord(sq))>0 then bb:=bb xor ($8000000000000000 shr (63-Ord(sq)));
end;
// count bits within a bitboard (Brian Kernighan's way)
function count_bits(bb:U64):integer;
var
count:integer;
begin
    // bit counter
    count := 0;
    // consecutively reset least significant 1st bit
     while bb>0
     do  begin
         // increment count
         Inc(count);
         // reset least significant 1st bit
         bb := bb and (bb - 1);
         end;
count_bits:=count;
end;
// get least significant 1st bit index
function  get_ls1b_index(bb:U64):integer;
begin
  // make sure bitboard is not 0
 if bb<>0 then
 // count trailing bits before LS1B
 result:=count_bits((bb and (-bb))-1)
 // return illegal index
 else result:=-1;
end;
{/**********************************\
 ==================================
 
           Input & Output
 
 ==================================
\**********************************/}
// print bitboard
procedure print_bitboard(bb:U64);
var
rank_,file_,sq:integer;
begin
Writeln('');
  // loop over board ranks
  for rank_ := 0 to 7 do  begin
        // loop over board files
        for file_ := 0 to 7 do  begin
           // convert file & rank into square index
           sq:=rank_*8 + file_;
           //// print ranks
           if file_ = 0 then begin
           Write(8 - rank_);Write(' ');
           end;
           Write(' ');
           // print bit state (either 1 or 0)
           Write(get_bit(bb,sq));
        end;
        // print new line every rank
        Writeln('');
  end;
  // print new line
  Writeln('');
  // print board files
  Writeln('   a b c d e f g h');
  Writeln('');
  // print bitboard as unsigned decimal number
  Write('bitboard = ',bb);
  Writeln('');
end;
{/**********************************\
 ==================================

              Attacks

 ==================================
\**********************************/}
// generate pawn attacks
function mask_pawn_attacks(side:TSide;square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // white pawns
    if (side=white) then begin
      if ((bitboard shr 7) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 7);
      if ((bitboard shr 9) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 9);
    end
    // black pawns
    else  begin
      if ((bitboard shl 7) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 7);
      if ((bitboard shl 9) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 9);
    end;
// return attack map
mask_pawn_attacks:=attacks;
end;
// generate knight attacks
function  mask_knight_attacks(square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // generate knight attacks
    if ((bitboard shr 17) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 17);
    if ((bitboard shr 15) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 15);
    if ((bitboard shr 10) and not_hg_file)>0 then  attacks:=attacks or (bitboard shr 10);
    if ((bitboard shr 6) and not_ab_file)>0 then  attacks:=attacks or (bitboard shr 6);
    if ((bitboard shl 17) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 17);
    if ((bitboard shl 15) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 15);
    if ((bitboard shl 10) and not_ab_file)>0 then  attacks:=attacks or (bitboard shl 10);
    if ((bitboard shl 6) and not_hg_file)>0 then  attacks:=attacks or (bitboard shl 6);
// return attack map
mask_knight_attacks:=attacks;
end;
// generate king attacks
function  mask_king_attacks(square:TBoard_squares):U64;
var
attacks,bitboard:U64;
begin
// result attacks bitboard
attacks := 0;
// piece bitboard
bitboard := 0;
// set piece on board
set_bit(bitboard, square);
    // generate king attacks
    if (bitboard shr 8)>0 then  attacks:=attacks or (bitboard shr 8);
    if ((bitboard shr 9) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 9);
    if ((bitboard shr 1) and not_h_file)>0 then  attacks:=attacks or (bitboard shr 1);
    if ((bitboard shr 7) and not_a_file)>0 then  attacks:=attacks or (bitboard shr 7);
    if (bitboard shl 8)>0 then  attacks:=attacks or (bitboard shl 8);
    if ((bitboard shl 9) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 9);
    if ((bitboard shl 1) and not_a_file)>0 then  attacks:=attacks or (bitboard shl 1);
    if ((bitboard shl 7) and not_h_file)>0 then  attacks:=attacks or (bitboard shl 7);
// return attack map
mask_king_attacks:=attacks;
end;
//урок 6-masking relevant bishop occupancy bits to form a key for MAGIC BITBOARDS
// mask bishop attacks
function   mask_bishop_attacks(square:TBoard_squares):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // mask relevant bishop occupancy bits
    f:=tf+1;
    for r:=tr+1 to 6 do begin
       if f>6 then break;
       attacks := attacks or (n shl (r*8+f));
       Inc(f);
    end;
    f:=tf+1;
    for r:=tr-1 downto 1 do begin
       if f>6 then break;
       attacks := attacks or (n shl (r*8+f));
       Inc(f);
    end;
    f:=tf-1;
    for r:=tr+1 to 6 do begin
       if f<1 then break;
       attacks := attacks or (n shl (r*8+f));
       Dec(f);
    end;
    f:=tf-1;
    for r:=tr-1 downto 1 do begin
       if f<1 then break;
       attacks := attacks or (n shl (r*8+f));
       Dec(f);
    end;
// return attack map
mask_bishop_attacks:=attacks;
end;
//урок 7-masking relevant ROOK OCCUPANCY BITS to form a key for MAGIC BITBOARDS
// mask rook attacks
function   mask_rook_attacks(square:TBoard_squares):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // mask relevant bishop occupancy bits
    for r:=tr+1 to 6 do attacks := attacks or (n shl (r*8+tf));
    for r:=tr-1 downto 1 do attacks := attacks or (n shl (r*8+tf));
    for f:=tf+1 to 6 do attacks := attacks or (n shl (tr*8+f));
    for f:=tf-1 downto 1 do attacks := attacks or (n shl (tr*8+f));
// return attack map
mask_rook_attacks:=attacks;
end;
//урок 8-generating SLIDER PIECES ATTACKS on the fly for MAGIC BITBOARD purposes
// generate bishop attacks on the fly
function  bishop_attacks_on_the_fly(square:TBoard_squares;blk:U64):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // generate bishop atacks
    f:=tf+1;
    for r:=tr+1 to 7 do begin
       if f>7 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Inc(f);
    end;
        f:=tf+1;
    for r:=tr-1 downto 0 do begin
       if f>7 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Inc(f);
    end;
    f:=tf-1;
    for r:=tr+1 to 7 do begin
       if f<0 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Dec(f);
    end;
    f:=tf-1;
    for r:=tr-1 downto 0 do begin
       if f<0 then break;
       attacks := attacks or (n shl (r*8+f));
       if ((n shl (r*8+f)) and blk)>0 then  break;
       Dec(f);
    end;
// return attack map
bishop_attacks_on_the_fly:=attacks;
end;
// generate rook attacks on the fly
function  rook_attacks_on_the_fly(square:TBoard_squares;blk:U64):U64;
var
attacks,n:U64;
r,f,tr,tf:integer;
begin
n:=1;
// result attacks bitboard
attacks := 0;
    // init target rank & files
    tr := Ord(square) div 8;//целочисленное деление
    tf := Ord(square) mod 8;//остаток от деления
    // generate rook attacks
    for r:=tr+1 to 7 do begin
    attacks := attacks or (n shl (r*8+tf));
    if ((n shl (r*8+tf)) and blk)>0 then  break;
    end;
    for r:=tr-1 downto 0 do begin
    attacks := attacks or (n shl (r*8+tf));
    if ((n shl (r*8+tf)) and blk)>0 then  break;
    end;
    for f:=tf+1 to 7 do begin
    attacks := attacks or (n shl (tr*8+f));
    if ((n shl (tr*8+f)) and blk)>0 then  break;
    end;
    for f:=tf-1 downto 0 do begin
    attacks := attacks or (n shl (tr*8+f));
    if ((n shl (tr*8+f)) and blk)>0 then  break;
    end;
// return attack map
rook_attacks_on_the_fly:=attacks;
end;
// init leaper pieces attacks
procedure init_leapers_attacks();
var
square:TBoard_squares;
begin
    // loop over 64 board squares
    for square := a8 to h1 do  begin
//урок 3-generating pre-calculated PAWN ATTACK tables
       // init pawn attacks
       pawn_attacks[white][square] := mask_pawn_attacks(white,square);
       pawn_attacks[black][square] := mask_pawn_attacks(black,square);
//урок 4-generating pre-calculated KNIGHT ATTACK table
       // init knight attacks
       knight_attacks[square] := mask_knight_attacks(square);
//урок 5-generating pre-calculated KING ATTACK tables
       // init king attacks
       king_attacks[square] := mask_king_attacks(square);
    end;
end;
// set occupancies
//перебираем по очереди биты в attack_mask
//испр. ошибка - было -var attack_mask:U64, стало-attack_mask:U64
function set_occupancy(index,bits_in_mask:integer;attack_mask:U64):U64;
var
occupancy,n:U64;
count:integer;
square_:TBoard_squares;
begin
n:=1;
// occupancy map
occupancy:=0;
            // loop over the range of bits within attack mask
            for count:=0 to bits_in_mask-1 do begin
               // get LS1B index of attacks mask
               square_:=TBoard_squares(get_ls1b_index(attack_mask));
               // pop LS1B in attack map
               pop_bit(attack_mask,square_);
               // make sure occupancy is on board
               if (index and (n shl count))>0 then
                   occupancy:=occupancy or (n shl integer(square_));
            end;
set_occupancy:=occupancy;
end;
{/**********************************\
 ==================================

               Magics
 function  rook_attacks_on_the_fly(square:TBoard_squares;blk:U64):U64;
 ==================================
\**********************************/}
// find appropriate magic number
function find_magic_number(square:TBoard_squares;relevant_bits:integer;bishop_flag:Tbishop):U64;
//function find_magic_number():U64;
var
// init occupancies
occupancies:array[0..4095] of U64;
// init attack tables
attacks:array[0..4095] of U64;
// init used attacks
used_attacks:array[0..4095] of U64;
n:Byte;
// init attack mask for a current piece
attack_mask:U64;
// init occupancy indicies
occupancy_indicies:integer;
magic_index:integer;
index,fail,random_count:integer;
magic_number:U64;
//memset
//https://metanit.com/c/tutorial/8.3.php?ysclid=ldc20xz850854644891
begin
attack_mask:=0;
 // init attack mask for a current piece
 if bishop_flag=bishop then attack_mask:=mask_bishop_attacks(square)
                       else attack_mask:=mask_rook_attacks(square);
 // init occupancy indicies  напр. ладья на a1 - rook_relevant_bits: array [ ] = 12
 // 1 shl 12 = 4096
 occupancy_indicies:=1 shl relevant_bits;
 // loop over occupancy indicies
 for index:=0 to occupancy_indicies-1 do begin
    // init occupancies
    occupancies[index] := set_occupancy(index,relevant_bits,attack_mask);
    // init attacks
    if bishop_flag=bishop then attacks[index]:= bishop_attacks_on_the_fly(square, occupancies[index])
                          else attacks[index]:= rook_attacks_on_the_fly(square, occupancies[index]);
 end;
 // test magic numbers loop
 n:=0;
 for random_count:= 0 to 100000000 do begin
     // generate magic number candidate
     magic_number := generate_magic_number();
     // skip inappropriate magic numbers
     if (count_bits((attack_mask * magic_number) and $FF00000000000000) < 6) then continue;
//http://www.delphibasics.ru/FillChar.php
// procedure FillChar ( var Buffer; FillCount : Integer; FillValue : Byte ) ;
{Процедура FillChar заполняет раздел памяти Buffer
тем же самым байтом или символом FillValue FillCount раз.
Это используется, преимущественно, для инициализирования массивов чисел.}
   // Теперь заполняем массив used_attacks значением 0
   // UInt64 - 8 байт
   FillChar(used_attacks, 4096*SizeOf(UInt64), n);
   fail := 0;
   for index:=0 to occupancy_indicies-1 do begin
      // init magic index
      magic_index := integer((occupancies[index] * magic_number) shr (64 - relevant_bits));
      {Writeln('occupancies[',index,'] = ',occupancies[index]);
      Writeln('magic_index = ',magic_index);
      Writeln('magic_number = ',magic_number);
      Readln;}
            // if magic index works
            if (used_attacks[magic_index] = 0) then
                // init used attacks
                used_attacks[magic_index] := attacks[index]
            // otherwise
            else if (used_attacks[magic_index] <> attacks[index])  then  begin
                // magic index doesn't work
                 fail := 1;break;
            end;
    end;
// if magic number works
if (fail=0) then  begin
// return it
result:=magic_number;
exit;
end;
 end;
   // if magic number doesn't work
   Writeln(' Magic number fails! ');
   result:=0;
end;
// init magic numbers
procedure init_magic_numbers();
var
tem64:U64;
temp32:integer;
begin
 // loop over 64 board squares
  for square := a8 to h1 do  begin
    tem64:=find_magic_number(square,rook_relevant_bits[integer(square)],rook);
    Write('0x');Write(Format('%x',[tem64]));Write('ULL');
    Writeln('');
    //Write(tem64);
    //Readln;
  end;
  Writeln('====================');
  for square := a8 to h1 do  begin
    tem64:=find_magic_number(square,bishop_relevant_bits[integer(square)],bishop);
    Write('0x');Write(Format('%x',[tem64]));Write('ULL');
    Writeln('');
    //Write(tem64);
    //Readln;
  end;
end;
{/**********************************\
 ==================================

             Main driver
 
 ==================================
\**********************************/}
 begin
  //Переключение окна консоли на кодовую страницу CP1251 (Win-1251).
  //Если после переключения русские буквы показываются неверно,
  //следует открыть системное меню консольного окна - щелчком мыши в левом
  //верхнем углу окна консоли. И выбрать:
  //Свойства - закладка "Шрифт" - выбрать шрифт: "Lucida Console".
  SetConsoleCP(1251);
  SetConsoleOutputCP(1251);
// ==================================
  init_leapers_attacks(); 
  init_magic_numbers();
  Writeln('Нажмите <ENTER>, чтобы выйти ...');
  Readln;
end.
  {print_bitboard(get_random_U32_number());
  print_bitboard(get_random_U32_number());
  print_bitboard(get_random_U64_number());
  print_bitboard(generate_magic_number());}
  {Writeln('bishop_relevant_bits');
  for square := a8 to h1 do  begin
    if (integer(square) mod 8)=0 then  Writeln('');
     Write(count_bits(mask_bishop_attacks(square))); Write(' ');
  end;
  Writeln('');
  Writeln('rook_relevant_bits');
    for square := a8 to h1 do  begin
    if (integer(square) mod 8)=0 then  Writeln('');
     Write(count_bits(mask_rook_attacks(square))); Write(' ');
  end;
  Writeln('');}
   { block:=4512464976740352;
  print_bitboard(block);
  square:=TBoard_squares(get_ls1b_index(block));
  Write('get_ls1b_index:',integer(square));
  Writeln('  coordinate:',square_to_coordinates[integer(square)]);
  set_bit(bitboard,square);
  print_bitboard(bitboard);}
  //ZobristKey[i][j][z]=rd.nextLong()^(rd.nextLong()<<15)^(rd.nextLong()<<30)^(rd.nextLong()<<45)^(rd.nextLong()<<60);
  //<< shl

Магические числа, полученные с помощью кода адаптированного на Делфи
0x8A80104000800020ULL
0x140002000100040ULL
0x2801880A0017001ULL
0x100081001000420ULL
0x200020010080420ULL
0x3001C0002010008ULL
0x8480008002000100ULL
0x2080088004402900ULL
0x800098204000ULL
0x2024401000200040ULL
0x100802000801000ULL
0x120800800801000ULL
0x208808088000400ULL
0x2802200800400ULL
0x2200800100020080ULL
0x801000060821100ULL
0x80044006422000ULL
0x100808020004000ULL
0x12108A0010204200ULL
0x140848010000802ULL
0x481828014002800ULL
0x8094004002004100ULL
0x4010040010010802ULL
0x20008806104ULL
0x100400080208000ULL
0x2040002120081000ULL
0x21200680100081ULL
0x20100080080080ULL
0x2000A00200410ULL
0x20080800400ULL
0x80088400100102ULL
0x80004600042881ULL
0x4040008040800020ULL
0x440003000200801ULL
0x4200011004500ULL
0x188020010100100ULL
0x14800401802800ULL
0x2080040080800200ULL
0x124080204001001ULL
0x200046502000484ULL
0x480400080088020ULL
0x1000422010034000ULL
0x30200100110040ULL
0x100021010009ULL
0x2002080100110004ULL
0x202008004008002ULL
0x20020004010100ULL
0x2048440040820001ULL
0x101002200408200ULL
0x40802000401080ULL
0x4008142004410100ULL
0x2060820C0120200ULL
0x1001004080100ULL
0x20C020080040080ULL
0x2935610830022400ULL
0x44440041009200ULL
0x280001040802101ULL
0x2100190040002085ULL
0x80C0084100102001ULL
0x4024081001000421ULL
0x20030A0244872ULL
0x12001008414402ULL
0x2006104900A0804ULL
0x1004081002402ULL
====================
0x40040844404084ULL
0x2004208A004208ULL
0x10190041080202ULL
0x108060845042010ULL
0x581104180800210ULL
0x2112080446200010ULL
0x1080820820060210ULL
0x3C0808410220200ULL
0x4050404440404ULL
0x21001420088ULL
0x24D0080801082102ULL
0x1020A0A020400ULL
0x40308200402ULL
0x4011002100800ULL
0x401484104104005ULL
0x801010402020200ULL
0x400210C3880100ULL
0x404022024108200ULL
0x810018200204102ULL
0x4002801A02003ULL
0x85040820080400ULL
0x810102C808880400ULL
0xE900410884800ULL
0x8002020480840102ULL
0x220200865090201ULL
0x2010100A02021202ULL
0x152048408022401ULL
0x20080002081110ULL
0x4001001021004000ULL
0x800040400A011002ULL
0xE4004081011002ULL
0x1C004001012080ULL
0x8004200962A00220ULL
0x8422100208500202ULL
0x2000402200300C08ULL
0x8646020080080080ULL
0x80020A0200100808ULL
0x2010004880111000ULL
0x623000A080011400ULL
0x42008C0340209202ULL
0x209188240001000ULL
0x400408A884001800ULL
0x110400A6080400ULL
0x1840060A44020800ULL
0x90080104000041ULL
0x201011000808101ULL
0x1A2208080504F080ULL
0x8012020600211212ULL
0x500861011240000ULL
0x180806108200800ULL
0x4000020E01040044ULL
0x300000261044000AULL
0x802241102020002ULL
0x20906061210001ULL
0x5A84841004010310ULL
0x4010801011C04ULL
0xA010109502200ULL
0x4A02012000ULL
0x500201010098B028ULL
0x8040002811040900ULL
0x28000010020204ULL
0x6000020202D0240ULL
0x8918844842082200ULL
0x4010011029020020ULL
Нажмите <ENTER>, чтобы выйти ...

Вроде такие же, как у Макса
Last Edit: 27 Янв 2023 12:58 by alexlaw.
Moderators: Grigoriy
Рейтинг@Mail.ru

Научно-шахматный клуб КвантоФорум