Add basic UCI support

This commit is contained in:
2024-07-31 23:59:09 +03:00
parent 1c80db695f
commit 48cf03fd9d
5 changed files with 209 additions and 2 deletions

View File

@@ -1,7 +1,9 @@
use core::fmt;
use crate::{
bitboard::{have_common_bit, lsb, square_to_bitboard},
board::{Board, Color, Kind, Piece},
square::Square,
square::{coords_to_square, square_to_algebraic, Square},
state::Castle,
};
@@ -24,13 +26,36 @@ pub enum MoveType {
Castle,
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub struct Move {
pub src: usize,
pub dst: usize,
pub move_type: MoveType,
}
impl fmt::Debug for Move {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}{}",
square_to_algebraic(self.src),
square_to_algebraic(self.dst)
)?;
if let MoveType::Promotion(piece) | MoveType::PromotionCapture(piece) = &self.move_type {
let promote_char = match piece {
Promote::Knight => 'n',
Promote::Bishop => 'b',
Promote::Rook => 'r',
Promote::Queen => 'q',
};
write!(f, "{}", promote_char)?;
}
Ok(())
}
}
impl Move {
pub const fn new(src: usize, dst: usize) -> Self {
Self {
@@ -47,6 +72,39 @@ impl Move {
move_type,
}
}
pub fn parse_from_str(mv: &str) -> Result<Self, String> {
if mv.len() != 4 && mv.len() != 5 {
return Err("Invalid move characters length".to_string());
}
let mut mv_chars = mv.chars();
let src_file = (mv_chars.next().unwrap() as usize) - ('a' as usize);
let src_rank = (mv_chars.next().unwrap() as usize) - ('1' as usize);
let dst_file = (mv_chars.next().unwrap() as usize) - ('a' as usize);
let dst_rank = (mv_chars.next().unwrap() as usize) - ('1' as usize);
let src = coords_to_square(src_rank, src_file);
let dst = coords_to_square(dst_rank, dst_file);
if mv.len() == 5 {
let promotion_move = match mv_chars.next().unwrap() {
'n' => Self::new_with_type(src, dst, MoveType::Promotion(Promote::Knight)),
'b' => Self::new_with_type(src, dst, MoveType::Promotion(Promote::Bishop)),
'r' => Self::new_with_type(src, dst, MoveType::Promotion(Promote::Rook)),
'q' => Self::new_with_type(src, dst, MoveType::Promotion(Promote::Queen)),
_ => return Err("Unrecongisable character in promotion piece index".to_string()),
};
return Ok(promotion_move);
}
Ok(Self::new(src, dst))
}
pub fn parse_into_str(&self) -> String {
format!("{:?}", self)
}
}
impl Board {
@@ -170,6 +228,7 @@ mod tests {
board::Color,
fen::from_fen,
r#move::{Move, MoveType, Promote},
square::Square,
};
const FEN_QUIET: [&str; 2] = [
@@ -274,4 +333,26 @@ mod tests {
assert_eq!(game, from_fen(FEN_CASTLE[1])?);
Ok(())
}
#[test]
fn test_parse_from_str() -> Result<(), String> {
let mv_str = "a1a8";
let actual = Move::parse_from_str(&mv_str)?;
let expected = Move::new(Square::A1, Square::A8);
assert_eq!(actual, expected);
let mv_str = "b7b8q";
let actual = Move::parse_from_str(&mv_str)?;
let expected =
Move::new_with_type(Square::B7, Square::B8, MoveType::Promotion(Promote::Queen));
assert_eq!(actual, expected);
Ok(())
}
#[test]
#[should_panic(expected = "Invalid move characters length")]
fn test_parse_from_str_panic() -> () {
Move::parse_from_str(&"a7a8qk").unwrap();
}
}