use std::{fmt::Display, str::Chars}; use crate::{bitboard::BitboardFns, board::piece::Piece, square::Square}; #[derive(Debug, Clone, PartialEq, Eq, Copy)] pub enum MoveKind { Quiet, Capture, Castle, EnPassant, DoublePush, Promotion(Piece), } #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Move { pub source: Square, pub target: Square, pub kind: MoveKind, } impl Move { pub fn print(&self) { let bb = self.source.to_bitboard() | self.target.to_bitboard(); bb.print(format!("{:?}", self).as_str()); } /// Tactical move is a move that changes material score pub fn is_tactical(&self) -> bool { matches!( self.kind, MoveKind::Capture | MoveKind::EnPassant | MoveKind::Promotion(_) ) } pub fn from_notation(mut notation: Chars) -> Self { let source = Square::from_notation(&mut notation).unwrap(); let target = Square::from_notation(&mut notation).unwrap(); if let Some(promotion) = notation.next() { let piece = match promotion { 'r' => Piece::Rook, 'q' => Piece::Queen, 'b' => Piece::Bishop, 'n' => Piece::Knight, _ => panic!("Illegal promotion piece: {:?}", promotion), }; return Move { source, target, kind: MoveKind::Promotion(piece), }; } Move { source, target, kind: MoveKind::Quiet, } } } impl Display for Move { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let promotion_postfix = match self.kind { MoveKind::Promotion(piece) => match piece.without_color() { Piece::Rook => "r", Piece::Queen => "q", Piece::Bishop => "b", Piece::Knight => "n", _ => panic!("Illegal promotion piece: {:?}", piece), }, _ => "", }; write!(f, "{}{}{}", self.source, self.target, promotion_postfix) } }