use alloc::vec::Vec;
use super::MovablePositions;
use cetkaik_fundamental::Profession;
use cetkaik_traits::{CetkaikRepresentation, IsBoard, IsPieceWithSide};
pub mod iter;
pub mod vec;
pub fn is_tam_hue_relative<T: CetkaikRepresentation>(
coord: T::RelativeCoord,
board: T::RelativeBoard,
tam_itself_is_tam_hue: bool,
) -> bool {
if T::is_tam_hue_by_default(coord) {
return true;
}
if tam_itself_is_tam_hue && board.peek(coord) == Some(T::relative_tam2()) {
return true;
}
iter::eight_neighborhood::<T>(coord).any(|coord| board.peek(coord) == Some(T::relative_tam2()))
}
#[must_use]
pub fn calculate_movable_positions_for_either_side<T: CetkaikRepresentation>(
coord: T::RelativeCoord,
piece: T::RelativePiece,
board: T::RelativeBoard,
tam_itself_is_tam_hue: bool,
) -> MovablePositions<T::RelativeCoord> {
piece.match_on_piece_and_apply(
&|| calculate_movable_positions_for_tam::<T>(coord),
&|_color, prof, side| {
calculate_movable_positions_for_nontam::<T>(
coord,
prof,
board,
tam_itself_is_tam_hue,
side,
)
},
)
}
pub fn calculate_movable_positions_for_tam<T: CetkaikRepresentation>(
coord: T::RelativeCoord,
) -> MovablePositions<T::RelativeCoord> {
MovablePositions {
finite: vec::eight_neighborhood::<T>(coord),
infinite: vec![],
}
}
pub fn calculate_movable_positions_for_nontam<T: CetkaikRepresentation>(
coord: T::RelativeCoord,
prof: Profession,
board: T::RelativeBoard,
tam_itself_is_tam_hue: bool,
side: T::RelativeSide,
) -> MovablePositions<T::RelativeCoord> {
const DIAGONAL: [[isize; 2]; 32] = [
[-8, -8],
[-7, -7],
[-6, -6],
[-5, -5],
[-4, -4],
[-3, -3],
[-2, -2],
[-1, -1],
[-8, 8],
[-7, 7],
[-6, 6],
[-5, 5],
[-4, 4],
[-3, 3],
[-2, 2],
[-1, 1],
[8, -8],
[7, -7],
[6, -6],
[5, -5],
[4, -4],
[3, -3],
[2, -2],
[1, -1],
[8, 8],
[7, 7],
[6, 6],
[5, 5],
[4, 4],
[3, 3],
[2, 2],
[1, 1],
];
const UP: [[isize; 2]; 8] = [
[-1, 0],
[-2, 0],
[-3, 0],
[-4, 0],
[-5, 0],
[-6, 0],
[-7, 0],
[-8, 0],
];
const DOWN: [[isize; 2]; 8] = [
[1, 0],
[2, 0],
[3, 0],
[4, 0],
[5, 0],
[6, 0],
[7, 0],
[8, 0],
];
const LEFT_RIGHT: [[isize; 2]; 16] = [
[0, -1],
[0, -2],
[0, -3],
[0, -4],
[0, -5],
[0, -6],
[0, -7],
[0, -8],
[0, 1],
[0, 2],
[0, 3],
[0, 4],
[0, 5],
[0, 6],
[0, 7],
[0, 8],
];
let piece_prof = prof;
if is_tam_hue_relative::<T>(coord, board, tam_itself_is_tam_hue) {
match piece_prof {
Profession::Io | Profession::Uai1 => MovablePositions { finite: vec::eight_neighborhood::<T>(coord), infinite: vec![] },
Profession::Kaun1 =>
MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[
[-2, -2],
[-2, 2],
[2, 2],
[2, -2]
]),
infinite: vec![]
}, Profession::Kauk2 => MovablePositions {
finite: [
&vec::apply_deltas::<T>(coord, &[
[-1, 0],
[0, -1],
[0, 1],
[1, 0]
])[..],
&vec::apply_single_delta_if_no_intervention::<T>(coord, if T::is_upward(side) {[-2, 0]} else {[2,0]}, board)[..]
].concat(),
infinite: vec![]
},
Profession::Nuak1 => MovablePositions {
finite: [
&vec::apply_deltas::<T>(coord, &[
[0, -1],
[0, 1]
])[..],
&vec::apply_deltas_if_no_intervention::<T>(
coord,
&[
[0, -2],
[0, 2]
],
board
)[..]
].concat(),
infinite: vec::apply_deltas_if_no_intervention::<T>(coord, &[&UP[..], &DOWN[..]].concat(), board)
},
Profession::Gua2 | Profession::Dau2 => MovablePositions {
finite: vec![],
infinite: vec::apply_deltas_if_no_intervention::<T>(
coord,
&DIAGONAL,
board
)
},
Profession::Maun1 => {
const HORSE_DELTAS: [[isize; 2] ; 28] = [
[-8, -8],
[-7, -7],
[-6, -6],
[-5, -5],
[-4, -4],
[-3, -3],
[-2, -2],
[-8, 8],
[-7, 7],
[-6, 6],
[-5, 5],
[-4, 4],
[-3, 3],
[-2, 2],
[8, -8],
[7, -7],
[6, -6],
[5, -5],
[4, -4],
[3, -3],
[2, -2],
[8, 8],
[7, 7],
[6, 6],
[5, 5],
[4, 4],
[3, 3],
[2, 2]
];
let mut inf: Vec<T::RelativeCoord> = vec![];
for delta in &HORSE_DELTAS {
let blocker_deltas = crate::get_blocker_deltas::ultrafast(*delta).filter(
|d|
!((d[0] == -1 || d[0] == 1) && (d[1] == -1 || d[1] == 1))
);
let mut blocker = iter::apply_deltas::<T>(coord, blocker_deltas);
if blocker.all(|block| board.peek(block).is_none()) {
inf.append(&mut vec::apply_deltas::<T>(coord, &[*delta]));
}
}
MovablePositions {
finite: vec![],
infinite: inf
}
}
Profession::Kua2 => MovablePositions {
finite: vec![],
infinite: vec::apply_deltas_if_no_intervention::<T>(
coord,
&[&UP[..], &DOWN[..], &LEFT_RIGHT[..]].concat(),
board
)
},
Profession::Tuk2 => MovablePositions {
finite: vec![],
infinite: vec::apply_deltas_if_zero_or_one_intervention::<T>(
coord,
&[
&UP[..],
&DOWN[..],
&LEFT_RIGHT[..],
&DIAGONAL[..]
].concat(),
board
)
},
}
} else {
match piece_prof {
Profession::Io => MovablePositions {
finite: vec::eight_neighborhood::<T>(coord),
infinite: vec![],
},
Profession::Kauk2 => MovablePositions {
finite: vec::apply_deltas::<T>(
coord,
&[if T::is_upward(side) { [-1, 0] } else { [1, 0] }],
),
infinite: vec![],
}, Profession::Kaun1 => MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[[-2, 0], [2, 0], [0, -2], [0, 2]]),
infinite: vec![],
},
Profession::Dau2 =>
{
MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[[-1, -1], [-1, 1], [1, -1], [1, 1]]),
infinite: vec![],
}
}
Profession::Maun1 =>
{
MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[[-2, -2], [-2, 2], [2, 2], [2, -2]]),
infinite: vec![],
}
}
Profession::Nuak1 =>
{
MovablePositions {
finite: vec![],
infinite: vec::apply_deltas_if_no_intervention::<T>(
coord,
if T::is_upward(side) { &UP } else { &DOWN },
board,
),
}
}
Profession::Gua2 =>
{
MovablePositions {
finite: vec![],
infinite: vec::apply_deltas_if_no_intervention::<T>(
coord,
&[&UP[..], &DOWN[..], &LEFT_RIGHT[..]].concat(),
board,
),
}
}
Profession::Kua2 =>
{
MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[[0, -1], [0, 1]]),
infinite: vec::apply_deltas_if_no_intervention::<T>(
coord,
&[&UP[..], &DOWN[..]].concat(),
board,
),
}
}
Profession::Tuk2 =>
{
MovablePositions {
finite: vec::apply_deltas::<T>(coord, &[[-1, 0], [1, 0]]),
infinite: vec::apply_deltas_if_no_intervention::<T>(coord, &LEFT_RIGHT, board),
}
}
Profession::Uai1 =>
{
MovablePositions {
finite: vec::apply_deltas::<T>(
coord,
&[
[-1, -1],
if T::is_upward(side) { [-1, 0] } else { [1, 0] },
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 1],
],
),
infinite: vec![],
}
}
}
}
}