Bitmap generation others moves

на главную страницу


БИТОВЫЙ ГЕНЕРАТОР ОСТАЛЬНЫХ ХОДОВ

Ходы короля и коня реализуются элементарно

// ходы короля--------------------------------------------------------------------------------
// маска расположения белого короля:
from_mask = bitboard->white_piece[N_KING];
// находим координату фигуры (самый первый(для нашего отображения правый ) установленный бит)
from = first_one(from_mask);
// находим маску ходов короля (без взятий):
move_mask = king_moves_masks[from] & (~bitboard->all_piece);

Пишем ходы в список:
while (move_mask !=0){
    to = first_one(move_mask);
    move_mask = move_mask & (move_mask-1);
    list_record_move(N_KING,1,from,to,p,bitboard,list_surplus_moves);
}//while (move_mask !=0){
//---------------------------------------------------------------------------

Для коня аналогично.
Для короля следует посчитать еще и рокировки

// рокировки белого короля
// если длинная рокировка разрешена
if(bitboard->castling_Q){
   to = 2;
   #if KONTROL_B
       KONTROL_move(&from,&to,&p);
   #endif//KONTROL_B
   // поля 1, 2, 3 пустые то добавляем ход
   if(((~bitboard->all_piece) & CASTLING_Q ) == CASTLING_Q ){
      // длинная рокировка белых 0-0-0 - проверяем под боем ли поля 2, 3, 4
      if((White_check_square(2,bitboard)==0)&&(White_check_square(3,bitboard)==0)&&(White_check_square(4,bitboard)==0)){
         list_record_os(N_KING,3,p,from,2,0,list_surplus_moves);
      }
  }
}

// если короткая рокировка разрешена, то добавляем ход
if(bitboard->castling_K){
   to = 6;
   #if KONTROL_B
       KONTROL_move(&from,&to,&p);
   #endif//KONTROL_B
   //поля 5, 6 пустые то добавляем ход
   if( ( (~bitboard->all_piece) & CASTLING_K ) == CASTLING_K ){
       // короткая рокировка белых 0-0 - проверяем под боем ли поля 4, 5, 6
       if((White_check_square(4,bitboard)==0)&&(White_check_square(5,bitboard)==0)&&(White_check_square(6,bitboard)==0)){
           list_record_os(N_KING,4,p,from,6,0,list_surplus_moves);
       }
   }
}


Ходы слайдеров, т.е. ферзя, ладьи, слона

// ходы ферзя----------------------------------------------------------------------------------
// маска расположения белого ферзя
from_mask = bitboard->white_piece[N_QUEEN];
while(from_mask != 0){
   from = first_one(from_mask);
// надо пояснить, что конструкция типа b = b & (b-1) сбрасывает самый правый единичный бит
   from_mask = from_mask & (from_mask-1);

// смотрим в четырех различных направлениях (по типу ладьи)
//   луч вверх-----------------------------------------------------------------
//   1) находим блокированные биты.
     blocking_square_mask = bitboard->all_piece & rook_up_masks[from];
     if(blocking_square_mask != 0){
//       2) находим координату первого блокированного бита
         blocking_coordinate = first_one(blocking_square_mask);
         move_mask = rook_up_masks[from] ^ rook_up_masks[blocking_coordinate] ^ move_masks[blocking_coordinate];
     }else{
         move_mask = rook_up_masks[from];
     }//if(blocking_square_mask != 0){

     while (move_mask !=0){
         to = first_one(move_mask);
         move_mask = move_mask & (move_mask-1);
         list_record_move(N_QUEEN,1,from,to,p,bitboard,list_surplus_moves);
     }//while (move_mask !=0){
//---------------------------------------------------------------------------

// луч влево-----------------------------------------------------------------
    blocking_square_mask = bitboard->all_piece & rook_left_masks[from];
    if(blocking_square_mask != 0){
        blocking_coordinate = last_one(blocking_square_mask);
        move_mask = rook_left_masks[from] ^ rook_left_masks[blocking_coordinate] ^ move_masks[blocking_coordinate];
    }else{
        move_mask = rook_left_masks[from];
    }//if(blocking_square_mask != 0){

    while (move_mask !=0){
         to = first_one(move_mask);
         move_mask = move_mask & (move_mask-1);
         list_record_move(N_QUEEN,1,from,to,p,bitboard,list_surplus_moves);
     }//while (move_mask !=0){
//---------------------------------------------------------------------------



В приведенном коде все очевидно. Поясню на примере идею генерации.

Допустим, мы хотим посчитать ходы ферзя вверх, а на пути стоит конь.
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 n 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 q 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Позиция коня дает нам блокированный бит.
Сначала находим блокированные биты.
blocking_square_mask = bitboard->all_piece & rook_up_masks[from];

Находим координату первого блокированного бита
blocking_coordinate = first_one(blocking_square_mask);

теперь у нас есть матрицы:
rook_up_masks[from]
1 ходов ферзя вверх
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 q 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

rook_up_masks[blocking_coordinate]
2 хода вверх из блокированного бита
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 n 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

move_masks[blocking_coordinate]
3 просто блокированный бит
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Составляя композицию матриц через «исключающее или», получаем матрицу ходов.
move_mask = rook_up_masks[from] ^ rook_up_masks[blocking_coordinate] ^ move_masks[blocking_coordinate];

В данном случае это один ход.
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

Осталось только извлечь из нее ходы и записать их в список
while (move_mask !=0){
to = first_one(move_mask);
move_mask = move_mask & (move_mask-1);
list_record_move(N_QUEEN,1,from,to,p,bitboard,list_surplus_moves);
}//while (move_mask !=0){

Остальные направления аналогично двум вышерассмотренным.


Ходы пешки

from_mask = bitboard->white_piece[N_PAWN];
while(from_mask != 0){
     from = first_one(from_mask);
    //выделяем одну пешку
    one_pawn_mask = from_mask & move_masks[from];
    from_mask = from_mask & (from_mask-1);

// 1 находим простые ходы белых пешек на одно поле вперед
    move_mask = (one_pawn_mask << 8) & (~(bitboard->all_piece));
//  2 находим ходы пешек на 2 поля вперед
//  в начале оставляем только пешки, стоящие на 2 горизонтали
    move_mask_d = one_pawn_mask & LINE_1;
//  отметаем пешки, если они чем-то заблокированы
    move_mask_d = (move_mask_d <<8) & (~(bitboard->all_piece));
//  оставшимися пешками делаем ход
    move_mask_d = (move_mask_d << 8) & (~(bitboard->all_piece));

//  здесь все ходы пешки как на одно, так и на два поля вперед
    move_mask = (move_mask | move_mask_d) ;

//  ходы без превращений
    move_mask = move_mask & ~LINE_7;

    while (move_mask !=0){
         to = first_one(move_mask);
         move_mask = move_mask & (move_mask-1);
         list_record_move(N_PAWN,1,from,to,p,bitboard,list_surplus_moves);
     }//while (move_mask !=0){
}//while(from_mask != 0){