|
||
БИТОВЫЙ ГЕНЕРАТОР ОСТАЛЬНЫХ ХОДОВ Ходы короля и коня реализуются элементарно // ходы короля-------------------------------------------------------------------------------- // маска расположения белого короля: 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){ |