use shogi_core::Square;
use super::{DIAGONAL_DOWN_LINE, DIAGONAL_UP_LINE, LineKind, RANK_LINE, walk_line};
use crate::bitboard::Bitboard;
static RANK_MASK: [Bitboard; 81] = line_masks(RANK_LINE);
static DIAGONAL_UP_MASK: [Bitboard; 81] = line_masks(DIAGONAL_UP_LINE);
static DIAGONAL_DOWN_MASK: [Bitboard; 81] = line_masks(DIAGONAL_DOWN_LINE);
const fn line_masks(line: LineKind) -> [Bitboard; 81] {
let mut table = [Bitboard::EMPTY; 81];
let mut index = 0;
while index < 81 {
table[index] = Bitboard::from_bits(walk_line(index, 0, line));
index += 1;
}
table
}
#[inline(always)]
const fn mirror(bits: u128) -> u128 {
bits.reverse_bits() >> 47
}
#[inline(always)]
fn line_attacks(index: usize, occupied: Bitboard, mask: Bitboard) -> u128 {
let mask = mask.bits();
let occupied = occupied.bits() & mask;
let upward = occupied.wrapping_sub(1u128 << (index + 1));
let downward = mirror(mirror(occupied).wrapping_sub(1u128 << (81 - index)));
(upward ^ downward) & mask
}
pub(crate) fn bishop_attacks(square: Square, occupied: Bitboard) -> Bitboard {
let index = square.array_index();
Bitboard::from_bits(
line_attacks(index, occupied, DIAGONAL_UP_MASK[index])
| line_attacks(index, occupied, DIAGONAL_DOWN_MASK[index]),
)
}
pub(crate) fn rook_attacks(square: Square, occupied: Bitboard) -> Bitboard {
let index = square.array_index();
Bitboard::from_bits(
line_attacks(index, occupied, RANK_MASK[index])
| super::file_attacks(square, occupied).bits(),
)
}