Обрезка краев на битборде

Я использую битовые доски для создания таблиц атак для ладей, слонов и ферзей. Во время моего исследования магических битовых досок мне кажется, что мне нужно обрезать края всех моих таблиц атак. Я храню свои битборды в длинном, где квадрат a1 является младшим битом, а квадрат h8 — старшим битом, перемещаясь строка за строкой. Вот пример таблицы атаки ладьей на поле с2:

[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, 1, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 1, 1, 1, 1]
[0, 0, 1, 0, 0, 0, 0, 0]

Моя проблема в том, что мне нужно сделать все те, что на краю битовой доски, равными 0. Сначала я попытался заполнить каждую таблицу атак двоичным кодом long, представляющим бордюрный клип, который выглядит следующим образом:

[0, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 1, 1, 1, 1, 1, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 0]

Теперь это работает для большинства квадратов в центре, но для таблиц атаки по краям обрезает по ошибке. ТАК для ладьи на h8:

Начальная таблица атаки:

[1, 1, 1, 1, 1, 1, 1, 0]
[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, 1]
[0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 0, 0, 1]

Ожидаемый результат:

[0, 1, 1, 1, 1, 1, 1, 0]
[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, 1]
[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, 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]

Как мне подойти к этому, чтобы он обрезал только конец каждого луча атаки? Я понимаю, что моя битовая логика отключена. Спасибо.


person Community    schedule 12.03.2021    source источник
comment
Почему вам нужно сделать внешние ячейки нулями?   -  person akuzminykh    schedule 12.03.2021
comment
Пожалуйста, объясните, как вы храните таблицу. Из того, что я прочитал, я догадался, что вы храните 64 бита в long. Однако порядок битов остается неясным. Вы используете строки или столбцы? Где MSB и где LSB? Возможно, вы можете добавить long представление каждого графического примера в своем вопросе, редактируя. Это бы очень помогло.   -  person Socowi    schedule 12.03.2021


Ответы (1)


Вместо того, чтобы маскировать биты на границе с помощью постоянной маски, используйте динамически генерируемую маску.

Например, ладья () находится на поле F6, поэтому мы создаем маску, где F1, F8, A6 и H6. Затем мы используем эту маску, чтобы включить эти биты в шаблон атаки.

0 0 0 0 0 1 0 0   8
0 0 0 0 0 0 0 0   7
1 0 0 0 0 ♜ 0 1   6
0 0 0 0 0 0 0 0   5
0 0 0 0 0 0 0 0   4
0 0 0 0 0 0 0 0   3
0 0 0 0 0 0 0 0   2
0 0 0 0 0 1 0 0   1

A B C D E F G H

В этом решении я предполагаю, что вы кодируете 64 квадрата построчно внутри long. Квадрат A1 — это младший бит, а квадрат H8 — это старший бит. Поэтому приведенный выше пример будет представлен 2305984846213677088L = 0x2000810000000020L = 0b0000010000000000000100000010000000000000000000000000000000000100000L

/** 
 * @param x 0-based index for the columns A to H (0=A_, 1=B_, ...)
 * @param y 0-based index for the rows 1 to 8 (0=_1, 1=_2, ...)
 */
long rookEndpoints(int x, int y) {
  long topBtm = 1L << x;
  return (0b10000001L << (8 * y)) | (topBtm << (8 * 7)) | topBtm; 
}

...
attackPattern &= ~rookEndpoints(x, y)
person Socowi    schedule 12.03.2021