// АВТОР Бренкман Андрей (Copyright (C) 2006-2012 Brenkman Andrey)
// ПОСЛЕДНЕЕ ИЗМЕНЕНИЕ 21.02.2009 21.11.2010 18.09.2011 27.09.2011
#include "_include_standard_header.h"
#include "_search_switch.h"
#include "b_constants.h"
#include "move_generation.h"
#include "b_move_generation_const.h"
#include "history_heuristic.h"
#include "test_chess_bitboard.h"
uint64_t bishop_attacks_masks_database[64][512]; /// 1<<9
uint64_t rook_attacks_masks_database[64][4096]; /// 1<<12
// для функции bit_scan_forward
const uint64_t magic = 285870213051386505;
// для функции bit_scan_forward
const unsigned int magictable[64] =
{
0, 1, 48, 2, 57, 49, 28, 3,
61, 58, 50, 42, 38, 29, 17, 4,
62, 55, 59, 36, 53, 51, 43, 22,
45, 39, 33, 30, 24, 18, 12, 5,
63, 47, 56, 27, 60, 41, 37, 16,
54, 35, 52, 21, 44, 32, 23, 11,
46, 26, 40, 15, 34, 20, 31, 10,
25, 14, 19, 9, 13, 8, 7, 6,
};
// ===================================================================
//
void Move_generation::ini_attacks_magic_masks_database()
{
int number_on_bit[64];
int count_bishop_attack_squares;// считаем атакованные слоном поля в маске bishop_masks
uint64_t bishop_masks;// маска атак слоном на пустой доске
uint64_t deg_masks;
int index;
int count_rook_attack_squares;// считаем атакованные ладьей поля в маске rook_masks
uint64_t rook_masks;// маска атак ладьей на пустой доске
//----------------------------------------------------
// для слона
for( int square = 0; square < 64; square++ )
{
count_bishop_attack_squares = 0;
bishop_masks = bishop_full_masks[square];
// посчитали атакованные слоном биты (count_bishop_attack_squares)
// и записали позицию каждого взведенного бита (number_on_bit[])
while ( bishop_masks )
{
number_on_bit[count_bishop_attack_squares++] = bit_scan_forward(bishop_masks);
bishop_masks = bishop_masks & (bishop_masks - 1);
}
// здесь мы находим 2 в степени количества атакованных слоном полей
// т.е. через move_masks считаем степень :)
// таким образом мы определяем количество возможных комбинаций битов
uint64_t deg = move_masks[count_bishop_attack_squares];
for(uint64_t i = 0; i < deg; i++ )
{
// выдаем всевозможные маски атакованных битов (в данном случае слоном)
// каждый раз одну маску но в итоге перебираем все возможные комбинации битов
deg_masks = ini_deg_masks(number_on_bit,count_bishop_attack_squares,i);
index = ( deg_masks * bishop_magics[square] ) >> BISHOP_BITS_SHIFT;
bishop_attacks_masks_database[square][index] = ini_bishop_attacks_masks(square,deg_masks);
}
}
//----------------------------------------------------
// для ладьи
for( int square = 0; square < 64; square++ )
{
count_rook_attack_squares = 0;
rook_masks = rook_full_masks[square];
while ( rook_masks )
{
number_on_bit[count_rook_attack_squares++] = bit_scan_forward(rook_masks);
rook_masks = rook_masks & (rook_masks - 1);
}
uint64_t deg = move_masks[count_rook_attack_squares];
//deg = 20;
for( uint64_t i = 0; i < deg; i++ )
{
deg_masks = ini_deg_masks(number_on_bit,count_rook_attack_squares,i);
index = ( deg_masks * rook_magics[square] ) >> ROOK_BITS_SHIFT;
rook_attacks_masks_database[square][index] = ini_rook_attacks_masks(square,deg_masks);
}
}
}
// ===================================================================
//
uint64_t Move_generation::ini_deg_masks
(
const int number_on_bit[],
const int count_attack_squares,
const uint64_t deg
)
{
uint64_t deg_masks = 0;
/*
основа заключается в том что битовая маска чисел следующая
1, // 0 bit т.е. ....0001
2, // 1 bit т.е. ....0010
2, // т.е. ....0011
4, // 2 bit т.е. ....0100
и т.д.
т.е. мы имеем всевозможные комбинации взведенных битов
в нашем случае роль такого числа играет deg
осталось только отобразить это многообразие на маску атаки фигур
в нашем случае слонов и ладьей
*/
for( int i = 0; i < count_attack_squares; i++ )
{
if( deg & move_masks[i] )
{
deg_masks = deg_masks | move_masks[ number_on_bit[i] ];
}
}
return deg_masks;
}
// ===================================================================
// генерируем маску атак ладьи
uint64_t Move_generation::ini_rook_attacks_masks
(
const int square,
const uint64_t deg_masks
)
{
uint64_t rook_attacks_masks = 0;
uint64_t blocking_square_mask;
int blocking_coordinate;
// луч вверх------------------------------------------------------------------
blocking_square_mask = deg_masks & rook_up_masks[square];
if (blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_forward(blocking_square_mask);
rook_attacks_masks = rook_attacks_masks | (rook_up_masks[square] ^ rook_up_masks[blocking_coordinate]);
}
else
{
rook_attacks_masks = rook_attacks_masks | rook_up_masks[square];
}
// луч влево-----------------------------------------------------------------
blocking_square_mask = deg_masks & rook_left_masks[square];
if (blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_reverse(blocking_square_mask);
rook_attacks_masks = rook_attacks_masks | (rook_left_masks[square] ^ rook_left_masks[blocking_coordinate]);
}
else
{
rook_attacks_masks = rook_attacks_masks | rook_left_masks[square];
}
// луч вниз------------------------------------------------------------------
blocking_square_mask = deg_masks & rook_down_masks[square];
if (blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_reverse(blocking_square_mask);
rook_attacks_masks = rook_attacks_masks | (rook_down_masks[square] ^ rook_down_masks[blocking_coordinate]);
}
else
{
rook_attacks_masks = rook_attacks_masks | rook_down_masks[square];
}
// луч вправо-----------------------------------------------------------------
blocking_square_mask = deg_masks & rook_right_masks[square];
if (blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_forward(blocking_square_mask);
rook_attacks_masks = rook_attacks_masks | (rook_right_masks[square] ^ rook_right_masks[blocking_coordinate]);
}
else
{
rook_attacks_masks = rook_attacks_masks | rook_right_masks[square];
}
return rook_attacks_masks;
}
// ===================================================================
// генерируем маску атак слона
uint64_t Move_generation::ini_bishop_attacks_masks
(
const int square,
const uint64_t deg_masks
)
{
uint64_t bishop_attacks_masks = 0;
uint64_t blocking_square_mask; // маска блокированных полей
int blocking_coordinate; // координата блокированного поля
// смотрим в четырех различных направлениях (по типу слона)
// луч вверх - вправо--------------------------------------------------------
blocking_square_mask = deg_masks & bishop_up_right_masks[square];
if(blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_forward(blocking_square_mask);
bishop_attacks_masks = bishop_attacks_masks | ( bishop_up_right_masks[square] ^ bishop_up_right_masks[blocking_coordinate] );
}
else
{
bishop_attacks_masks = bishop_attacks_masks | bishop_up_right_masks[square];
}
// луч вверх - влево---------------------------------------------------------
blocking_square_mask = deg_masks & bishop_up_left_masks[square];
if(blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_forward(blocking_square_mask);
bishop_attacks_masks = bishop_attacks_masks | ( bishop_up_left_masks[square] ^ bishop_up_left_masks[blocking_coordinate] );
}
else
{
bishop_attacks_masks = bishop_attacks_masks | bishop_up_left_masks[square];
}
// луч вниз - влево----------------------------------------------------------
blocking_square_mask = deg_masks & bishop_down_left_masks[square];
if(blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_reverse(blocking_square_mask);
bishop_attacks_masks = bishop_attacks_masks | ( bishop_down_left_masks[square] ^ bishop_down_left_masks[blocking_coordinate] );
}
else
{
bishop_attacks_masks = bishop_attacks_masks | bishop_down_left_masks[square];
}
// луч вниз - вправо---------------------------------------------------------
blocking_square_mask = deg_masks & bishop_down_right_masks[square];
if (blocking_square_mask != 0)
{
blocking_coordinate = bit_scan_reverse(blocking_square_mask);
bishop_attacks_masks = bishop_attacks_masks | ( bishop_down_right_masks[square] ^ bishop_down_right_masks[blocking_coordinate] );
}
else
{
bishop_attacks_masks = bishop_attacks_masks | bishop_down_right_masks[square];
}
return bishop_attacks_masks;
}
// ===================================================================
//
uint64_t Move_generation::get_bishop_attacks_masks_magic
(
const unsigned char & square,/// расположение фигуры
const uint64_t & position_all_piece ///
)
{
int index =
( ( position_all_piece & bishop_full_masks[square] ) * bishop_magics[square] )
>> BISHOP_BITS_SHIFT ;
return bishop_attacks_masks_database[square][index];
}
// ===================================================================
//
uint64_t Move_generation::get_rook_attacks_masks_magic
(
const unsigned char & square,/// расположение фигуры
const uint64_t & position_all_piece ///
)
{
int index =
( ( position_all_piece & rook_full_masks[square] ) * rook_magics[square] )
>> ROOK_BITS_SHIFT ;
return rook_attacks_masks_database[square][index];
}
// ===================================================================
// генерируем список взятий + превращения пешки (для белых)
void Move_generation::generator_captures_white
(
struct List & list,// представление списка ходов
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t one_pawn_mask; // маска расположения одной пешки
uint64_t move_conversion_mask; // маска ходов пешки с превращеинем
uint64_t captures_conversion_mask; // маска взятий пешки с превращениями
uint64_t captures_mask; // маска взятий
uint64_t attack_mask;
unsigned char p; // счетчик ходов в списке
unsigned char from; // координата поля откуда фигура ходит
unsigned char to; // координата поля куда фигура ходит
// генерируем ходы белых фигур
p = 0;
// ходы пешки----------------------------------------------------------------------------------
from_mask = position.white_piece[N_PAWN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
//выделяем одну пешку
one_pawn_mask = from_mask & move_masks[from];
from_mask = from_mask & (from_mask - 1);
/*
отображение доски напрямую задаем формулой:
line_index = 8 * rank_index + file_index
to = 8 * position.taking_passage_y + position.taking_passage_x;
обратное отображение прямой на доску:
file_index = line_index modulo 8 = line_index % 8 = line_index & 7
rank_index = line_index div 8 = line_index / 8 = line_index >> 3
здесь у нас:
line_index – координата одномерной доски (от 0 до 63)
rank_index – координата доски по вертикали(от 0 до 7)
file_index – координата доски по горизонтали (от 0 до 7)
*/
// считаем ходы с превращением и взятия с превращением
if ( from / 8 == 6 )// если мы на предпоследней горизонтали т.е. следующий ход
// пешки с превращением
{
// 1 находим простые ходы белых пешек на одно поле вперед
move_conversion_mask = (one_pawn_mask << 8) & (~(position.all_piece));
// взятия с превращением
captures_conversion_mask = pawn_capture_white[from] & position.all_black_piece;
// находим координаты ходов с превращением пешки
while (move_conversion_mask != 0)
{
to = bit_scan_forward(move_conversion_mask);
move_conversion_mask = move_conversion_mask & (move_conversion_mask - 1);
// отмечаем превращение пешки
// превращение в ферзь 15,превращение в ладью 14,превращение в слона 13,превращение в коня 12
list_record_special(list,N_PAWN,TRANSFORMATION_IN_QUEEN,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_ROOK,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_BISHOP,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_KNIGHT,p,from,to,0);
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
}
// находим координаты взятий с превращением пешки
while (captures_conversion_mask != 0)
{
to = bit_scan_forward(captures_conversion_mask);
captures_conversion_mask = captures_conversion_mask & (captures_conversion_mask - 1);
// отмечаем превращение пешки с взятием
// превращение в ферзь 25,превращение в ладью 24,превращение в слона 23,превращение в коня 22
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_QUEEN,p,from,to,position.black_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_ROOK,p,from,to,position.black_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_BISHOP,p,from,to,position.black_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_KNIGHT,p,from,to,position.black_name_from_coord[to]);
#if KONTROL_B
KONTROL_captures_W(position,from,to,p,120);
#endif//KONTROL_B
}
}
else
{
// считаем взятия пешкой
captures_mask = pawn_capture_white[from] & position.all_black_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
list_capture_white(list,N_PAWN,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// 4 находим взятия на проходе
if (position.taking_passage_yes == 1)
{
// черная пешка может сходить на два поля только с начальной позиции
// значит только если белая пешка стоит на 4 считая с нуля горизонтали
// черная пешка может схотить через битое поле т.е.
// нужно проверять взятие на проходе
if ( from / 8 == 4 )
{
to = 8 * position.taking_passage_y + position.taking_passage_x;
// смотрим взятие на право. пешка не должна быть на самой правой вертикали
if (((from - to) == -9) && (from % 8 != 7))
{
list_record_special(list,N_PAWN,TAKING_PASSAGE,p,from,to,position.black_name_from_coord[to - 8]);
#if KONTROL_B
to = to - 8;
KONTROL_captures_W(position,from,to,p,130);
#endif//KONTROL_B
}
// смотрим взятие на налево. пешка не должна быть на самой левой вертикали
if (((from - to) == -7) && (from % 8 != 0))
{
list_record_special(list,N_PAWN,TAKING_PASSAGE,p,from,to,position.black_name_from_coord[to - 8]);
#if KONTROL_B
to = to - 8;
KONTROL_captures_W(position,from,to,p,130);
#endif//KONTROL_B
}
}
}
}
// пешки----------------------------------------------------------------------------------
// ходы коня ----------------------------------------------------------------------------------
// находим месторасположение коня в битовом списке и пока оно не нулевое бежим по маске
// расположения коней обнуляя тот бит который мы уже посмотрели
from_mask = position.white_piece[N_KNIGHT];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
captures_mask = (position.all_black_piece & knigt_moves_masks[from]);
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
list_capture_white(list,N_KNIGHT,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// коня ----------------------------------------------------------------------------------
// ходы слона----------------------------------------------------------------------------------
from_mask = position.white_piece[N_BISHOP];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
captures_mask = attack_mask & position.all_black_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_white(list,N_BISHOP,CAPTURE_MOVE,from,to,p,position);
}
}
// слона----------------------------------------------------------------------------------
// ходы ладьи---------------------------------------------------------------------------------
from_mask = position.white_piece[N_ROOK];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
attack_mask = get_rook_attacks_masks_magic(from,position.all_piece);
captures_mask = attack_mask & position.all_black_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_white(list,N_ROOK,CAPTURE_MOVE,from,to,p,position);
}
}
// ладьи----------------------------------------------------------------------------------
// ходы ферзя---------------------------------------------------------------------------------
// маска расположения белого ферзя
from_mask = position.white_piece[N_QUEEN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
captures_mask = get_rook_attacks_masks_magic(from,position.all_piece);
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
captures_mask = (captures_mask | attack_mask) & position.all_black_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_white(list,N_QUEEN,CAPTURE_MOVE,from,to,p,position);
}
}
// ферзя--------------------------------------------------------------------------------------
// ходы короля--------------------------------------------------------------------------------
// маска расположения белого короля
from_mask = position.white_piece[N_KING];
if (from_mask != 0)
{
// находим координату фигуры(самый первый(для нашего отображения правый ) установленный бит)
from = bit_scan_forward(from_mask);
// находим маску взятий короля
captures_mask = (position.all_black_piece & king_moves_masks[from]);
while (captures_mask != 0)
{
// Заполняем список ходов
to = bit_scan_forward(captures_mask);
list_capture_white(list,N_KING,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// ходы короля--------------------------------------------------------------------------------
list.end_list = p;
list.end_captures = p;
}
// ===================================================================
// генерируем список взятий + превращения пешки (для черных)
void Move_generation::generator_captures_black
(
struct List & list,// представление списка ходов
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t one_pawn_mask; // маска расположения одной пешки
uint64_t move_conversion_mask; // маска ходов пешки с превращеинем
uint64_t captures_conversion_mask; // маска взятий пешки с превращениями
uint64_t captures_mask; // маска взятий
uint64_t attack_mask;
unsigned char p; // счетчик ходов в списке
unsigned char from; // координата поля откуда фигура ходит
unsigned char to; // координата поля куда фигура ходит
// генерируем ходы черных фигур
p = 0;
// ходы пешки----------------------------------------------------------------------------------
from_mask = position.black_piece[N_PAWN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
// выделяем одну пешку
one_pawn_mask = from_mask & move_masks[from];
from_mask = from_mask & (from_mask - 1);
if ( from / 8 == 1 )
{
// считаем ходы с превращением и взятия с превращением
// 1 находим простые ходы черных пешек на одно поле вперед
move_conversion_mask = (one_pawn_mask >> 8) & (~(position.all_piece));
// взятия с превращением
captures_conversion_mask = pawn_capture_black[from] & position.all_white_piece;
// находим координаты ходов с превращением пешки
while (move_conversion_mask != 0)
{
to = bit_scan_forward(move_conversion_mask);
move_conversion_mask = move_conversion_mask & (move_conversion_mask - 1);
// отмечаем превращение пешки
// превращение в ферзь 15,превращение в ладью 14,превращение в слона 13,
// превращение в коня 12
list_record_special(list,N_PAWN,TRANSFORMATION_IN_QUEEN,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_ROOK,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_BISHOP,p,from,to,0);
list_record_special(list,N_PAWN,TRANSFORMATION_IN_KNIGHT,p,from,to,0);
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
}
// находим координаты взятий с превращением пешки
// находим координаты взятий с превращением пешки
while (captures_conversion_mask != 0)
{
to = bit_scan_forward(captures_conversion_mask);
captures_conversion_mask = captures_conversion_mask & (captures_conversion_mask - 1);
// отмечаем превращение пешки с взятием
// превращение в ферзь 25,превращение в ладью 24,превращение в слона 23,
// превращение в коня 22
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_QUEEN,p,from,to,position.white_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_ROOK,p,from,to,position.white_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_BISHOP,p,from,to,position.white_name_from_coord[to]);
list_record_special(list,N_PAWN,CAPTURE_WITH_TRANSFORMATION_IN_KNIGHT,p,from,to,position.white_name_from_coord[to]);
#if KONTROL_B
KONTROL_captures_B(position,from,to,p,120);
#endif//KONTROL_B
}
}
else
{
// считаем взятия пешкой
captures_mask = pawn_capture_black[from] & position.all_white_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
list_capture_black(list,N_PAWN,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// 4 находим взятия на проходе
if (position.taking_passage_yes == 1)
{
if ( from / 8 == 3 )
{
to = 8 * position.taking_passage_y + position.taking_passage_x;
if (((from - to) == 9) && (from % 8 != 0))
{
list_record_special(list,N_PAWN,TAKING_PASSAGE,p,from,to,position.white_name_from_coord[to + 8]);
#if KONTROL_B
to = to + 8;
KONTROL_captures_B(position,from,to,p,130);
#endif//KONTROL_B
}
if (((from - to) == 7) && (from % 8 != 7))
{
list_record_special(list,N_PAWN,TAKING_PASSAGE,p,from,to,position.white_name_from_coord[to + 8]);
#if KONTROL_B
to = to + 8;
KONTROL_captures_B(position,from,to,p,130);
#endif//KONTROL_B
}
}
}
}
// пешки----------------------------------------------------------------------------------
// ходы коня ----------------------------------------------------------------------------------
// находим месторасположение коня в битовом списке и пока оно не нулевое бежим по маске
// расположения коней обнуляя тот бит который мы уже посмотрели
// Генерируем ходы
from_mask = position.black_piece[N_KNIGHT];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
captures_mask = (position.all_white_piece & knigt_moves_masks[from]);
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
list_capture_black(list,N_KNIGHT,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// коня ----------------------------------------------------------------------------------
// ходы слона----------------------------------------------------------------------------------
from_mask = position.black_piece[N_BISHOP];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
captures_mask = attack_mask & position.all_white_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_black(list,N_BISHOP,CAPTURE_MOVE,from,to,p,position);
}
}
// слона----------------------------------------------------------------------------------
// ходы ладьи---------------------------------------------------------------------------------
from_mask = position.black_piece[N_ROOK];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
attack_mask = get_rook_attacks_masks_magic(from,position.all_piece);
captures_mask = attack_mask & position.all_white_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_black(list,N_ROOK,CAPTURE_MOVE,from,to,p,position);
}
}
// ладьи----------------------------------------------------------------------------------
// ходы ферзя---------------------------------------------------------------------------------
from_mask = position.black_piece[N_QUEEN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
captures_mask = get_rook_attacks_masks_magic(from,position.all_piece);
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
captures_mask = (captures_mask | attack_mask) & position.all_white_piece;
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
captures_mask = captures_mask & (captures_mask - 1);
list_capture_black(list,N_QUEEN,CAPTURE_MOVE,from,to,p,position);
}
}
// ферзя--------------------------------------------------------------------------------------
// ходы короля---------------------------------------------------------------------------------
from_mask = position.black_piece[N_KING];
if (from_mask != 0)
{
from = bit_scan_forward(from_mask);
captures_mask = (position.all_white_piece & king_moves_masks[from]);
while (captures_mask != 0)
{
to = bit_scan_forward(captures_mask);
list_capture_black(list,N_KING,CAPTURE_MOVE,from,to,p,position);
captures_mask = captures_mask & (captures_mask - 1);
}
}
// короля---------------------------------------------------------------------------------
list.end_list = p;
list.end_captures = p;
}
// ===================================================================
// генерируем список остальных ходов (т.е. всех ходов кроме взятий + превращения пешки)
//(для белых)
void Move_generation::generator_move_white
(
struct List & list,// представление списка ходов
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t move_mask; //
uint64_t one_pawn_mask; // маска расположения одной пешки
uint64_t move_mask_d; // маска хода пешки на два поля
unsigned char p; // счетчик ходов в списке
unsigned char from; // координата поля откуда фигура ходит
unsigned char to; // координата поля куда фигура ходит
p = list.end_list;
// генерируем ходы белых фигур
// ходы короля--------------------------------------------------------------------------------
// маска расположения белого короля
from_mask = position.white_piece[N_KING];
if (from_mask != 0)
{
// находим координату фигуры(самый первый(для нашего отображения правый )
// установленный бит)
from = bit_scan_forward(from_mask);
// находим маску ходов короля(без взятий)
move_mask = king_moves_masks[from] & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_KING,SIMPLE_MOVE,from,to,p,position);
}
// рокировки белого короля
// если длинная рокировка разрешена
if (position.castling_Q)
{
//
to = C1;
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
// поля 1 2 3 пустые то добавляем ход
if (((~position.all_piece) & CASTLING_Q ) == CASTLING_Q)
{
// длинная рокировка белых 0-0-0 проверяем под боем ли поля 2 3 4
if ((white_check_square(C1,position) == 0)
&& (white_check_square(D1,position) == 0)
&& (white_check_square(E1,position) == 0))
{
list_record_special(list,N_KING,LONG_CASTLING,p,from,to,0);
}
}
}
// если короткая рокировка разрешена то добавляем ход
if (position.castling_K)
{
to = G1;
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
//поля 5 6 пустые то добавляем ход
if (((~position.all_piece) & CASTLING_K ) == CASTLING_K)
{
// короткая рокировка белых 0-0 проверяем под боем ли поля 4 5 6
if ((white_check_square(E1,position) == 0)
&& (white_check_square(F1,position) == 0)
&& (white_check_square(G1,position) == 0))
{
list_record_special(list,N_KING,SHORT_CASTLING,p,from,to,0);
}
}
}
}
// ходы ферзя----------------------------------------------------------------------------------
// маска расположения белого ферзя
from_mask = position.white_piece[N_QUEEN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
// надо пояснить что конструкция типа b = b & (b-1)
// сбрасывает самый правый единичный бит
from_mask = from_mask & (from_mask - 1);
uint64_t mobility_mask = 0; // маска мобильности
move_mask = get_rook_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
mobility_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
//mobility_mask = mobility_mask ^ (position.all_piece & mobility_mask);
mobility_mask = mobility_mask & (~position.all_piece);
move_mask = move_mask | mobility_mask;
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_QUEEN,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы ладьи----------------------------------------------------------------------------------
from_mask = position.white_piece[N_ROOK];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = get_rook_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_ROOK,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы слона----------------------------------------------------------------------------------
from_mask = position.white_piece[N_BISHOP];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_BISHOP,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы коня ----------------------------------------------------------------------------------
// находим месторасположение коня в битовом списке и пока оно не нулевое бежим по маске
// расположения коней обнуляя тот бит который мы уже посмотрели
from_mask = position.white_piece[N_KNIGHT];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = knigt_moves_masks[from] & (~position.all_piece); // маска мобильности
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_KNIGHT,SIMPLE_MOVE,from,to,p,position);
}
}
// коды пешки----------------------------------------------------------------------------------
from_mask = position.white_piece[N_PAWN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
//выделяем одну пешку
one_pawn_mask = from_mask & move_masks[from];
from_mask = from_mask & (from_mask - 1);
// 1 находим простые ходы белых пешек на одно поле вперед
move_mask = (one_pawn_mask << 8) & (~(position.all_piece));
// 2 находим ходы пешек на 2 поля вперед
// в начале оставляем только пешки стоящие на 2 горизонтали
move_mask_d = one_pawn_mask & LINE_1;
// отметаем пешки если они чем то заблокированны
move_mask_d = (move_mask_d << 8) & (~(position.all_piece));
// оставшимися пешками делаем ход
move_mask_d = (move_mask_d << 8) & (~(position.all_piece));
// здесь все ходы пешки как на одно так на два поля вперед
move_mask = (move_mask | move_mask_d) ;
// ходы без превращений
move_mask = move_mask & ~LINE_7;
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_white(list,N_PAWN,SIMPLE_MOVE,from,to,p,position);
}
}
list.end_list = p;
}
// ===================================================================
// генерируем список остальных ходов (т.е. всех ходов кроме взятий + превращения пешки)(для черных)
void Move_generation::generator_move_black
(
struct List & list,// представление списка ходов
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t move_mask; // маска ходов здесь только для ходов пешки с превращением
uint64_t one_pawn_mask; // маска расположения одной пешки
uint64_t move_mask_d; // маска хода пешки на два поля
unsigned char p; // счетчик ходов в списке
unsigned char from; // координата поля откуда фигура ходит
unsigned char to; // координата поля куда фигура ходит
p = list.end_list;
// генерируем ходы черных фигур
// ходы короля---------------------------------------------------------------------------------
from_mask = position.black_piece[N_KING];
if (from_mask != 0)
{
from = bit_scan_forward(from_mask);
// находим маску ходов короля(без взятий)
move_mask = king_moves_masks[from] & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_KING,SIMPLE_MOVE,from,to,p,position);
}
// рокировки черного короля
// если длинная рокировка разрешена
if (position.castling_q)
{
to = C8;
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
// и поля 1 2 3 пустые то добавляем ход
if ((~(position.all_piece) & CASTLING_q )== CASTLING_q)
{
// длинная рокировка черных проверяем 0-0-0 58 59 60
if ((black_check_square(C8,position) == 0)
&& (black_check_square(D8,position) == 0)
&& (black_check_square(E8,position) == 0))
{
list_record_special(list,N_KING,LONG_CASTLING,p,from,to,0);
}
}
}
// если короткая рокировка разрешена то добавляем ход
if (position.castling_k)
{
to = G8;
#if KONTROL_B
KONTROL_move(from,to,p);
#endif//KONTROL_B
// и поля 5 6 пустые то добавляем ход
if ((~(position.all_piece) & CASTLING_k )== CASTLING_k)
{
// короткая рокировка черных проверяем 0-0 60 61 62
if ((black_check_square(E8,position) == 0)
&& (black_check_square(F8,position) == 0)
&&(black_check_square(G8,position) == 0))
{
list_record_special(list,N_KING,SHORT_CASTLING,p,from,to,0);
}
}
}
}
// ходы ферзя----------------------------------------------------------------------------------
// маска расположения ферзя
from_mask = position.black_piece[N_QUEEN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
// надо пояснить что конструкция типа b = b & (b-1) сбрасывает
//самый правый единичный бит
from_mask = from_mask & (from_mask - 1);
uint64_t mobility_mask = 0; // маска мобильности
move_mask = get_rook_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
mobility_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
//mobility_mask = mobility_mask ^ (position.all_piece & mobility_mask);
mobility_mask = mobility_mask & (~position.all_piece);
move_mask = move_mask | mobility_mask;
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_QUEEN,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы ладьи----------------------------------------------------------------------------------
from_mask = position.black_piece[N_ROOK];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = get_rook_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_ROOK,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы слона----------------------------------------------------------------------------------
from_mask = position.black_piece[N_BISHOP];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
//move_mask = move_mask ^ (position.all_piece & move_mask);
move_mask = move_mask & (~position.all_piece);
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_BISHOP,SIMPLE_MOVE,from,to,p,position);
}
}
// ходы коня ----------------------------------------------------------------------------------
// находим месторасположение коня в битовом списке и пока оно не нулевое бежим по маске
// расположения коней обнуляя тот бит который мы уже посмотрели
from_mask = position.black_piece[N_KNIGHT];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
from_mask = from_mask & (from_mask - 1);
move_mask = knigt_moves_masks[from] & (~position.all_piece); // маска мобильности
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_KNIGHT,SIMPLE_MOVE,from,to,p,position);
}
}
// коды пешки----------------------------------------------------------------------------------
from_mask = position.black_piece[N_PAWN];
while (from_mask != 0)
{
from = bit_scan_forward(from_mask);
one_pawn_mask = from_mask & move_masks[from];
from_mask = from_mask & (from_mask - 1);
// 1 находим простые ходы черных пешек на одно поле вперед
move_mask = (one_pawn_mask >> 8) & (~(position.all_piece));
// 2 находим ходы пешек на 2 поля вперед
// в начале оставляем только пешки стоящие на 7 горизонтали
move_mask_d = one_pawn_mask & LINE_6;
// отметаем пешки если они чем то заблокированны
move_mask_d = (move_mask_d >> 8) & (~(position.all_piece));
// оставшимися пешками делаем ход
move_mask_d = (move_mask_d >> 8) & (~(position.all_piece));
// здесь все ходы пешки как на одно так на два поля вперед
move_mask = (move_mask | move_mask_d) ;
// ходы без превращений
move_mask = move_mask & ~LINE_0;
while (move_mask != 0)
{
to = bit_scan_forward(move_mask);
move_mask = move_mask & (move_mask - 1);
list_record_move_black(list,N_PAWN,SIMPLE_MOVE,from,to,p,position);
}
}
list.end_list = p;
}
// ===================================================================
// под боем ли король если шаха нет то функция возвращает 0 иначе цифру шахующей фигуры
unsigned char Move_generation::king_white_check
(
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t attack_mask; // маска блокированных полей
uint64_t capture_mask; // маска взятий
unsigned char from; // координата поля откуда фигура ходит
// маска расположения белого короля
from_mask = position.white_piece[N_KING];
// находим координату фигуры(самый первый(для нашего отображения правый ) установленный бит)
from = bit_scan_forward(from_mask);
// все атаки ладьи
attack_mask = get_rook_attacks_masks_magic(from,position.all_piece);
// теперь смотрим есть ли в их числе черные ладьи
capture_mask = attack_mask & position.black_piece[N_ROOK];
if (capture_mask != 0) return N_ROOK;
// теперь смотрим есть ли в их числе черные ферзи
capture_mask = attack_mask & position.black_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки слона
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
// теперь смотрим есть ли в их числе черные слоны
capture_mask = attack_mask & position.black_piece[N_BISHOP];
if (capture_mask != 0) return N_BISHOP;
// теперь смотрим есть ли в их числе черные ферзи
capture_mask = attack_mask & position.black_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки коня
capture_mask = (knigt_moves_masks[from] & position.black_piece[N_KNIGHT]);
if (capture_mask != 0) return N_KNIGHT;
// по типу короля
capture_mask = (king_moves_masks[from] & position.black_piece[N_KING]);
if (capture_mask != 0) return N_KING;
// пешки считаем напрямую
if ((from / 7) < 8)
{
if (from % 8 != 0)
{
if (position.black_name_from_coord[from + 7] == N_PAWN)
{
return N_PAWN;
}
}
if (from % 8 != 7)
{
if (position.black_name_from_coord[from + 9] == N_PAWN)
{
return N_PAWN;
}
}
}
return 0;
}
// ===================================================================
// под боем ли король если шаха нет то функция возвращает 0 иначе цифру шахующей фигуры
unsigned char Move_generation::king_black_check
(
const struct Position & position // представление доски
)
{
uint64_t from_mask; // маска расположения фигур одного типа
uint64_t attack_mask; // маска блокированных полей
uint64_t capture_mask; // маска взятий
unsigned char from; // координата поля откуда фигура ходит
// маска расположения черного короля
from_mask = position.black_piece[N_KING];
// находим координату фигуры(самый первый(для нашего отображения правый ) установленный бит)
from = bit_scan_forward(from_mask);
// все атаки ладьи
attack_mask = get_rook_attacks_masks_magic(from,position.all_piece);
// теперь смотрим есть ли в их числе белые ладьи
capture_mask = attack_mask & position.white_piece[N_ROOK];
if (capture_mask != 0) return N_ROOK;
// теперь смотрим есть ли в их числе белые ферзи
capture_mask = attack_mask & position.white_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки слона
attack_mask = get_bishop_attacks_masks_magic(from,position.all_piece);
// теперь смотрим есть ли в их числе белые слоны
capture_mask = attack_mask & position.white_piece[N_BISHOP];
if (capture_mask != 0) return N_BISHOP;
// теперь смотрим есть ли в их числе белые ферзи
capture_mask = attack_mask & position.white_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки коня
capture_mask = (knigt_moves_masks[from] & position.white_piece[N_KNIGHT]);
if (capture_mask != 0) return N_KNIGHT;
// по типу короля
capture_mask = (king_moves_masks[from] & position.white_piece[N_KING]);
if (capture_mask != 0) return N_KING;
// пешки считаем напрямую
if ((from / 7) > 1 )
{
if (from % 8 != 7)
{
if (position.white_name_from_coord[from - 7] == N_PAWN)
{
return N_PAWN;
}
}
if (from % 8 != 0)
{
if (position.white_name_from_coord[from - 9] == N_PAWN)
{
return N_PAWN;
}
}
}
return 0;
}
//private
// ===================================================================
// под боем ли поля белых если шаха нет то функция возвращает 0
// иначе цифру шахующей фигуры
inline unsigned char Move_generation::white_check_square
(
const unsigned char & sq,//индекс проверяемого поля(0-63)
const struct Position & position // представление доски
)
{
uint64_t attack_mask; // маска блокированных полей
uint64_t capture_mask; // маска взятий
// все атаки ладьи
attack_mask = get_rook_attacks_masks_magic(sq,position.all_piece);
// теперь смотрим есть ли в их числе черные ладьи
capture_mask = attack_mask & position.black_piece[N_ROOK];
if (capture_mask != 0) return N_ROOK;
// теперь смотрим есть ли в их числе черные ферзи
capture_mask = attack_mask & position.black_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки слона
attack_mask = get_bishop_attacks_masks_magic(sq,position.all_piece);
// теперь смотрим есть ли в их числе черные слоны
capture_mask = attack_mask & position.black_piece[N_BISHOP];
if (capture_mask != 0) return N_BISHOP;
// теперь смотрим есть ли в их числе черные ферзи
capture_mask = attack_mask & position.black_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки коня
capture_mask = (knigt_moves_masks[sq] & position.black_piece[N_KNIGHT]);
if (capture_mask != 0) return N_KNIGHT;
// по типу короля
capture_mask = (king_moves_masks[sq] & position.black_piece[N_KING]);
if (capture_mask != 0) return N_KING;
// пешки считаем напрямую
if ((sq / 7) < 8)
{
if (sq % 8 != 0)
{
if (position.black_name_from_coord[sq + 7] == N_PAWN)
{
return N_PAWN;
}
}
if (sq % 8 != 7)
{
if (position.black_name_from_coord[sq + 9] == N_PAWN)
{
return N_PAWN;
}
}
}
return 0;
}
// ===================================================================
// под боем ли поля черных если шаха нет
// то функция возвращает 0 иначе цифру шахующей фигуры
inline unsigned char Move_generation::black_check_square
(
const unsigned char & sq,//индекс проверяемого поля(0-63)
const struct Position & position // представление доски
)
{
uint64_t attack_mask; // маска блокированных полей
uint64_t capture_mask; // маска взятий
// все атаки ладьи
attack_mask = get_rook_attacks_masks_magic(sq,position.all_piece);
// теперь смотрим есть ли в их числе белые ладьи
capture_mask = attack_mask & position.white_piece[N_ROOK];
if (capture_mask != 0) return N_ROOK;
// теперь смотрим есть ли в их числе белые ферзи
capture_mask = attack_mask & position.white_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки слона
attack_mask = get_bishop_attacks_masks_magic(sq,position.all_piece);
// теперь смотрим есть ли в их числе белые слоны
capture_mask = attack_mask & position.white_piece[N_BISHOP];
if (capture_mask != 0) return N_BISHOP;
// теперь смотрим есть ли в их числе белые ферзи
capture_mask = attack_mask & position.white_piece[N_QUEEN];
if (capture_mask != 0) return N_QUEEN;
// все атаки коня
capture_mask = (knigt_moves_masks[sq] & position.white_piece[N_KNIGHT]);
if (capture_mask != 0) return N_KNIGHT;
// по типу короля
capture_mask = (king_moves_masks[sq] & position.white_piece[N_KING]);
if (capture_mask != 0) return N_KING;
// пешки считаем напрямую
if ((sq / 7) > 1 )
{
if (sq % 8 != 7)
{
if (position.white_name_from_coord[sq - 7] == N_PAWN)
{
return N_PAWN;
}
}
if (sq % 8 != 0)
{
if (position.white_name_from_coord[sq - 9] == N_PAWN)
{
return N_PAWN;
}
}
}
return 0;
}
// ===================================================================
// заполняем список ходов - взятия за белых
// две функции только из за разного контроля списков(строки взятия)
inline void Move_generation::list_capture_white
(
struct List & list,// представление списка ходов
const unsigned char name,// имя ходящей фигуры
const unsigned char type_move,// тип хода
const unsigned char & from,// откуда ходим
const unsigned char & to,// куда ходим
unsigned char & count,// номер хода в списке
const struct Position & position // представление доски
)
{
unsigned char capture;// взятая фигура
#if KONTROL_B
KONTROL_captures_W(position,from,to,count,name);
#endif//KONTROL_B
// взятая фигура
capture = position.black_name_from_coord[to];
// записываем оценку взятия(mvv/lva в моем понимании) для последующей сортировки
list.sorting_score[count] = 10 * capture - name;
// 6 бит
// записали имя взятой фигуры (1 - пешка 2 - конь 3 - слон 4 - ладья 5 - ферзь
// 6 - король)
list.move[count] = capture
// 6 бит
// записали тип хода (0 - нет хода 1 – простой ход 2 – взятие 3 – длинная рокировка
//4 – короткая рокировка 5 – взятие на проходе
//12 - превращение в конь 13 - превращение в слон 14 - превращение в ладья
//15 - превращение в ферзь
//22 - взятие с превращением в конь 23 - взятие с превращением в слон
//24 - взятие с превращением в ладья
//25 - взятие с превращением в ферзь )
| (type_move << 6)
// 6 бит
// записали откуда ходим (0 -63)
| (from << 12)
// 6 бит
// записали куда ходим (0 -63)
| (to << 18)
// 3 бит
// ходящая фигура (0 - 6)
| (name << 24);
//-------------------------------------------------------------------------------
//std::cout << "move[count]= "<< move[count] << std::endl;
//
//std::cout << "position.black_name_from_coord[to]= "<< position.black_name_from_coord[to] << std::endl;
//std::cout << "position.black_name_from_coord[to]= "<< ( move[p] & 63) << std::endl;
//
//std::cout << "type_move= "<< type_move << std::endl;
//std::cout << "type_move= "<< ((move[count]>>6)& 63) << std::endl;
//
//std::cout << "from= "<< from << std::endl;
//std::cout << "from= "<< ((move[count]>>12)& 63) << std::endl;
//
//std::cout << "to= "<< to << std::endl;
//std::cout << "to= "<< ((move[count]>>18)& 63) << std::endl;
//
//std::cout << "name= "<< name << std::endl;
//std::cout << "name= "<< ((move[count]>>24)& 7) << std::endl;
//-------------------------------------------------------------------------------
count = count + 1;
}
// ===================================================================
// заполняем список ходов - взятия за черных
// две функции только из за разного контроля списков(строки взятия)
inline void Move_generation::list_capture_black
(
struct List & list,// представление списка ходов
const unsigned char name,// имя ходящей фигуры
const unsigned char type_move,// тип хода
const unsigned char & from,// откуда ходим
const unsigned char & to,// куда ходим
unsigned char & count,// номер хода в списке
const struct Position & position // представление доски
)
{
unsigned char capture;// взятая фигура
#if KONTROL_B
KONTROL_captures_B(position,from,to,count,name);
#endif//KONTROL_B
// взятая фигура
capture = position.white_name_from_coord[to];
// записываем оценку взятия(mvv/lva в моем понимании) для последующей сортировки
list.sorting_score[count] = 10 * capture - name;
// 6 бит
// записали имя взятой фигуры (1 - пешка 2 - конь 3 - слон 4 - ладья 5 - ферзь 6 - король)
list.move[count] = capture
// 6 бит
// записали тип хода (0 - нет хода 1 – простой ход 2 – взятие 3 – длинная рокировка
//4 – короткая рокировка 5 – взятие на проходе
//12 - превращение в конь 13 - превращение в слон 14 - превращение в ладья 15 - превращение в ферзь
//22 - взятие с превращением в конь 23 - взятие с превращением в слон 24 - взятие с превращением в ладья
//25 - взятие с превращением в ферзь )
| (type_move << 6)
// 6 бит
// записали откуда ходим (0 -63)
| (from << 12)
// 6 бит
// записали куда ходим (0 -63)
| (to << 18)
// 3 бит
// ходящая фигура (0 - 6)
| (name << 24);
//-------------------------------------------------------------------------------
//std::cout << "move[count]= "<< move[count] << std::endl;
//
//std::cout << "position.white_name_from_coord[to]= "<< position.white_name_from_coord[to] << std::endl;
//std::cout << "position.white_name_from_coord[to]= "<< ( move[p] & 63) << std::endl;
//
//std::cout << "type_move= "<< type_move << std::endl;
//std::cout << "type_move= "<< ((move[count]>>6)& 63) << std::endl;
//
//std::cout << "from= "<< from << std::endl;
//std::cout << "from= "<< ((move[count]>>12)& 63) << std::endl;
//
//std::cout << "to= "<< to << std::endl;
//std::cout << "to= "<< ((move[count]>>18)& 63) << std::endl;
//
//std::cout << "name= "<< name << std::endl;
//std::cout << "name= "<< ((move[count]>>24)& 7) << std::endl;
//-------------------------------------------------------------------------------
count = count + 1;
}
// ===================================================================
// заполняем список ходов
inline void Move_generation::list_record_move_white
(
struct List & list,// представление списка ходов
const unsigned char name,// имя ходящей фигуры
const unsigned char type_move,// тип хода
const unsigned char & from,// откуда ходим
const unsigned char & to,// куда ходим
unsigned char & count,// номер хода в списке
const struct Position & position // представление доски
)
{
#if KONTROL_B
KONTROL_move(from,to,count);
#endif//KONTROL_B
#if SW_HISTORY
// записываем историю
list.sorting_score[count] = History_heuristic::get_white_history(name,to);
#endif//#if SW_HISTORY
// 6 бит
// взятая фигура 0
list.move[count] = 0
// 6 бит
// записали тип хода (0 - нет хода 1 – простой ход 2 – взятие 3 – длинная рокировка
//4 – короткая рокировка 5 – взятие на проходе
//12 - превращение в конь 13 - превращение в слон 14 - превращение в ладья 15 - превращение в ферзь
//22 - взятие с превращением в конь 23 - взятие с превращением в слон 24 - взятие с превращением в ладья
//25 - взятие с превращением в ферзь )
| (type_move << 6)
// 6 бит
// записали откуда ходим (0 -63)
| (from << 12)
// 6 бит
// записали куда ходим (0 -63)
| (to << 18)
// 3 бит
// ходящая фигура (0 - 6)
| (name << 24);
//-------------------------------------------------------------------------------
//std::cout << "move[p]= "<< move[p] << std::endl;
//
//std::cout << "0= "<< 0 << std::endl;
//std::cout << "0= "<< ( move[p] & 63) << std::endl;
//
//std::cout << "d_m= "<< d_m << std::endl;
//std::cout << "d_m= "<< ((move[p]>>6)& 63) << std::endl;
//
//std::cout << "from= "<< from << std::endl;
//std::cout << "from= "<< ((move[p]>>12)& 63) << std::endl;
//
//std::cout << "to= "<< to << std::endl;
//std::cout << "to= "<< ((move[p]>>18)& 63) << std::endl;
//
//std::cout << "name= "<< name << std::endl;
//std::cout << "name= "<< ((move[p]>>24)& 7) << std::endl;
//-------------------------------------------------------------------------------
count = count + 1;
}
// ===================================================================
// заполняем список ходов
inline void Move_generation::list_record_move_black
(
struct List & list,// представление списка ходов
const unsigned char name,// имя ходящей фигуры
const unsigned char type_move,// тип хода
const unsigned char & from,// откуда ходим
const unsigned char & to,// куда ходим
unsigned char & count,// номер хода в списке
const struct Position & position // представление доски
)
{
#if KONTROL_B
KONTROL_move(from,to,count);
#endif//KONTROL_B
#if SW_HISTORY
// записываем историю
list.sorting_score[count] = History_heuristic::get_black_history(name,to);
#endif//#if SW_HISTORY
// 6 бит
// взятая фигура 0
list.move[count] = 0
// 6 бит
// записали тип хода (0 - нет хода 1 – простой ход 2 – взятие 3 – длинная рокировка
//4 – короткая рокировка 5 – взятие на проходе
//12 - превращение в конь 13 - превращение в слон 14 - превращение в ладья 15 - превращение в ферзь
//22 - взятие с превращением в конь 23 - взятие с превращением в слон 24 - взятие с превращением в ладья
//25 - взятие с превращением в ферзь )
| (type_move << 6)
// 6 бит
// записали откуда ходим (0 -63)
| (from << 12)
// 6 бит
// записали куда ходим (0 -63)
| (to << 18)
// 3 бит
// ходящая фигура (0 - 6)
| (name << 24);
//-------------------------------------------------------------------------------
//std::cout << "move[p]= "<< move[p] << std::endl;
//
//std::cout << "0= "<< 0 << std::endl;
//std::cout << "0= "<< ( move[p] & 63) << std::endl;
//
//std::cout << "d_m= "<< d_m << std::endl;
//std::cout << "d_m= "<< ((move[p]>>6)& 63) << std::endl;
//
//std::cout << "from= "<< from << std::endl;
//std::cout << "from= "<< ((move[p]>>12)& 63) << std::endl;
//
//std::cout << "to= "<< to << std::endl;
//std::cout << "to= "<< ((move[p]>>18)& 63) << std::endl;
//
//std::cout << "name= "<< name << std::endl;
//std::cout << "name= "<< ((move[p]>>24)& 7) << std::endl;
//-------------------------------------------------------------------------------
count = count + 1;
}
// ===================================================================
// заполняем список ходов для особых случаев типа рокировки взятия на проходе и превращений пешек
inline void Move_generation::list_record_special
(
struct List & list,// представление списка ходов
const unsigned char name,// имя ходящей фигуры
const unsigned char d_m,// тип хода
unsigned char & count,// номер хода в списке
const unsigned char & from,// откуда ходим
const unsigned char to,// куда ходим
const unsigned char capture// имя взятой фигуры
)
{
// Заполняем список ходов+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// тут рокировка превращение пешек взятие на проходе
// таких ходов мало и лучше их посмотреть первыми среди простых
list.sorting_score[count] = 110000; //d_m;
// 6 бит
// взятая фигура 0
list.move[count] = capture
// 6 бит
// записали тип хода (0 - нет хода 1 – простой ход 2 – взятие 3 – длинная рокировка
//4 – короткая рокировка 5 – взятие на проходе
//12 - превращение в конь 13 - превращение в слон 14 - превращение в ладья 15 - превращение в ферзь
//22 - взятие с превращением в конь 23 - взятие с превращением в слон 24 - взятие с превращением в ладья
//25 - взятие с превращением в ферзь )
| (d_m << 6)
// 6 бит
// записали откуда ходим (0 -63)
| (from << 12)
// 6 бит
// записали куда ходим (0 -63)
| (to << 18)
// 3 бит
// ходящая фигура (0 - 6)
| (name << 24);
//-------------------------------------------------------------------------------
//std::cout << "move[p]= "<< move[p] << std::endl;
//
//std::cout << "0= "<< 0 << std::endl;
//std::cout << "0= "<< ( move[p] & 63) << std::endl;
//
//std::cout << "d_m= "<< d_m << std::endl;
//std::cout << "d_m= "<< ((move[p]>>6)& 63) << std::endl;
//
//std::cout << "from= "<< from << std::endl;
//std::cout << "from= "<< ((move[p]>>12)& 63) << std::endl;
//
//std::cout << "to= "<< to << std::endl;
//std::cout << "to= "<< ((move[p]>>18)& 63) << std::endl;
//
//std::cout << "name= "<< name << std::endl;
//std::cout << "name= "<< ((move[p]>>24)& 7) << std::endl;
//-------------------------------------------------------------------------------
count = count + 1;
}
// ===================================================================
// контролируем выход за пределы доски, за пределы списка а также пустые взятия
// все это для белых фигур генератора взятий
inline void Move_generation::KONTROL_captures_W
(
const struct Position & position, // представление доски
const unsigned char & from,// откуда ходит фигура
const unsigned char & to,// куда ходит фигура
const unsigned char & p,// номер хода в списке
const unsigned char name_figure// имя ходящей фигуры
)
{
#if KONTROL_B
///////////////////////////////////////////////////////////////////////////////////
if ((p < 0)||(p > 256))
{
std::cout << "W ERROR Generator_captures p= " << p << std::endl;
}
if ((from < 0)||(from > 63))
{
std::cout << "W ERROR Generator_captures from= " << from << std::endl;
}
if ((to < 0)||(to > 63))
{
std::cout << "W ERROR Generator_captures to= " << to << std::endl;
}
if ((position.white_name_from_coord[from] < 1)
||(position.white_name_from_coord[from] > 6))
{
std::cout << "W ERROR Generator_captures position.white_name_from_coord[*from] = "
<< position.white_name_from_coord[from]<< std::endl;
}
if ((position.black_name_from_coord[to] < 1)
||(position.black_name_from_coord[to] > 6))
{
std::cout << "W ERROR Generator_captures position.black_name_from_coord[*to]= "
<< position.black_name_from_coord[to] << std::endl;
std::cout << "W ERROR Generator_captures from= "<< from << std::endl;
std::cout << "W ERROR Generator_captures to= " << to << std::endl;
std::cout << "W ERROR Generator_captures name_figure= " << name_figure << std::endl;
position_print(position);
}
//if (position.black_name_from_coord[to] ==6)
//{
//std::cout << "ERROR Generator_captures name_figure KING " << std::endl;
//}
///////////////////////////////////////////////////////////////////////////////////
#endif//KONTROL_B
}
// ===================================================================
// контролируем выход за пределы доски, за пределы списка а также пустые взятия
// все это для черных фигур генератора взятий
inline void Move_generation::KONTROL_captures_B
(
const struct Position & position, // представление доски
const unsigned char & from,// откуда ходит фигура
const unsigned char & to,// куда ходит фигура
const unsigned char & p,// номер хода в списке
const unsigned char name_figure// имя ходящей фигуры
)
{
#if KONTROL_B
///////////////////////////////////////////////////////////////////////////////////
if ((p < 0)||(p > 256))
{
std::cout << "B ERROR Generator_captures p= " << p << std::endl;
}
if ((from < 0)||(from > 63))
{
std::cout << "B ERROR Generator_captures from= " << from << std::endl;
}
if ((to < 0)||(to > 63))
{
std::cout << "B ERROR Generator_captures to= " << to << std::endl;
}
if ((position.black_name_from_coord[from] < 1)
||(position.black_name_from_coord[from] > 6))
{
std::cout << "B ERROR Generator_captures position.black_name_from_coord[from] = "
<< position.black_name_from_coord[from] << std::endl;
}
if ((position.white_name_from_coord[to] < 1)
||(position.white_name_from_coord[to] > 6))
{
std::cout << "B ERROR Generator_captures position.white_name_from_coord[to]= "
<< position.white_name_from_coord[to] << std::endl;
std::cout << "B ERROR Generator_captures from= "<< from << std::endl;
std::cout << "B ERROR Generator_captures to= " << to << std::endl;
std::cout << "B ERROR Generator_captures name_figure= " << name_figure << std::endl;
position_print(position);
}
//if (position.white_name_from_coord[to] ==6)
//{
//std::cout << "B ERROR Generator_captures name_figure KING " << std::endl;
//}
///////////////////////////////////////////////////////////////////////////////////
#endif//KONTROL_B
}
// ===================================================================
// контролируем выход за пределы доски, за пределы списка
// для генератора ходов
inline void Move_generation::KONTROL_move
(
const unsigned char & from,// откуда ходит фигура
const unsigned char & to,// куда ходит фигура
const unsigned char & p// номер хода в списке
)
{
#if KONTROL_B
///////////////////////////////////////////////////////////////////////////////////
if ((p < 0)||(p > 256))
{
std::cout << "ERROR Generator_move p= " << p << std::endl;
}
if ((from < 0)||(from > 63))
{
std::cout << "ERROR Generator_move from= " << from << std::endl;
}
if ((to < 0)||(to > 63))
{
std::cout << "ERROR Generator_move to= " << to << std::endl;
}
///////////////////////////////////////////////////////////////////////////////////
#endif//KONTROL_B
}
/*
ищем первый установленный бит(т.е. бежим справа)
реализацию добавил Jim Ablett
*/
inline int Move_generation::bit_scan_forward(const uint64_t bb){
//assert (bb != 0);
if (bb == 0) return 0;
return magictable[((bb&-bb)*magic) >> 58];
}
/*
ищем последний установленный бит(т.е. бежим слева)
реализацию добавил Jim Ablett
*/
inline int Move_generation::bit_scan_reverse(const uint64_t bb){
union {
double d;
struct {
unsigned int mantissal : 32;
unsigned int mantissah : 20;
unsigned int exponent : 11;
unsigned int sign : 1;
};
} ud;
ud.d = (double)(uint64_t)(bb & ~(bb >> 32));
int idx = (ud.exponent - 1023) | (63*ud.sign);
return idx;
}
/*
логика
и & 0 0 1 первый операнд
0 1 1 второй операнд
-----
0 0 1 результат
или | 0 0 1
0 1 1
-----
0 1 1
исключающее ^ 0 0 1
или 0 1 1
-----
0 1 0
*/