use crate::board::bitboard::BitBoard;
use crate::board::types::{Action, Position};
#[derive(Debug)]
pub struct LegalActionIter {
adapter: LegalActionIterAdapter,
}
impl LegalActionIter {
pub(crate) fn with_put_iter(iter: LegalPutIter) -> Self {
Self {
adapter: LegalActionIterAdapter::LegalPutIter(iter),
}
}
pub(crate) fn with_move_iter(iter: LegalMoveIter) -> Self {
Self {
adapter: LegalActionIterAdapter::LegalMoveIter(iter),
}
}
}
#[derive(Debug)]
enum LegalActionIterAdapter {
LegalPutIter(LegalPutIter),
LegalMoveIter(LegalMoveIter),
}
impl Iterator for LegalActionIter {
type Item = Action;
fn next(&mut self) -> Option<Self::Item> {
use LegalActionIterAdapter::*;
match &mut self.adapter {
LegalPutIter(iter) => iter.next(),
LegalMoveIter(iter) => iter.next(),
}
}
}
#[derive(Debug)]
pub(crate) struct LegalPutIter {
bit_iter: BitLegalPutIter,
}
impl LegalPutIter {
pub(crate) fn new(bit_iter: BitLegalPutIter) -> Self {
LegalPutIter { bit_iter }
}
}
impl Iterator for LegalPutIter {
type Item = Action;
fn next(&mut self) -> Option<Self::Item> {
let (pos, color) = self.bit_iter.next()?;
let pos = unsafe { Position::from_u32_unchecked(pos) };
Some(Action::Put(pos, color.into()))
}
}
#[derive(Debug)]
pub(crate) struct LegalMoveIter {
bit_iter: BitLegalMoveIter,
}
impl LegalMoveIter {
pub(crate) fn new(bit_iter: BitLegalMoveIter) -> Self {
LegalMoveIter { bit_iter }
}
}
impl Iterator for LegalMoveIter {
type Item = Action;
fn next(&mut self) -> Option<Self::Item> {
let (from, to) = self.bit_iter.next()?;
let from = unsafe { Position::from_u32_unchecked(from) };
let to = unsafe { Position::from_u32_unchecked(to) };
Some(Action::Move(from, to))
}
}
#[derive(Debug)]
pub struct BitLegalPutIter {
pos_iter: HotBitIter,
color: bool,
}
impl BitLegalPutIter {
pub(crate) fn new(board: BitBoard, color: bool) -> Self {
let pos_iter = HotBitIter::new((board.bits() << 3) & 0x8888_8888); Self { pos_iter, color }
}
}
impl Iterator for BitLegalPutIter {
type Item = (u32, bool);
fn next(&mut self) -> Option<Self::Item> {
let pos = self.pos_iter.next()?;
Some((pos, self.color))
}
}
#[derive(Debug)]
pub struct BitLegalMoveIter {
from_iter: HotBitIter,
to_filter: u32,
from: u32,
to_iter: HotBitIter,
}
impl BitLegalMoveIter {
pub(crate) fn new(board: BitBoard, color: bool) -> Self {
let bits = if color {
board.bits()
} else {
!board.bits() - 0x1111_1111
};
Self {
from_iter: HotBitIter::new(bits & 0x8888_8888), to_filter: (bits << 3) & 0x8888_8888, from: 0, to_iter: HotBitIter::new(0), }
}
}
impl Iterator for BitLegalMoveIter {
type Item = (u32, u32);
fn next(&mut self) -> Option<Self::Item> {
const TO_BITS_BASE: u32 = 0x1001_0010;
loop {
if let Some(to) = self.to_iter.next() {
return Some((self.from, to));
}
let from = self.from_iter.next()?;
let to_bits = TO_BITS_BASE.rotate_left(from.trailing_zeros()) & self.to_filter;
(self.from, self.to_iter) = (from, HotBitIter::new(to_bits))
}
}
}
#[derive(Debug)]
pub(crate) struct HotBitIter {
bits: u32,
}
impl HotBitIter {
pub(crate) fn new(bits: u32) -> Self {
Self { bits }
}
}
impl Iterator for HotBitIter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
if self.bits == 0 {
return None;
}
let bit = self.bits & (!self.bits + 1);
self.bits ^= bit;
Some(bit)
}
}
impl std::iter::FusedIterator for HotBitIter {}
impl std::iter::FusedIterator for BitLegalPutIter {}
impl std::iter::FusedIterator for BitLegalMoveIter {}
impl std::iter::FusedIterator for LegalPutIter {}
impl std::iter::FusedIterator for LegalMoveIter {}
impl std::iter::FusedIterator for LegalActionIter {}