use std::{str::Chars, fmt::Display}; use crate::{square::Square, bitboard::BitboardFns, board::piece::Piece}; #[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) } }