From 068f5248cd4e8d01741b86b7dade6dd47559405d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Varga=20D=C3=A1vid=20Lajos?= Date: Fri, 21 Nov 2025 22:56:02 +0200 Subject: [PATCH] implemented api function get_available_moves --- engine/src/bitboard.rs | 4 +- engine/src/boardsquare.rs | 2 +- engine/src/chessmove.rs | 4 +- engine/src/lib.rs | 105 ++++++++++++++++++++++++++++++++++++-- engine/src/piecetype.rs | 2 +- 5 files changed, 108 insertions(+), 9 deletions(-) diff --git a/engine/src/bitboard.rs b/engine/src/bitboard.rs index 9779d93..7da5b04 100644 --- a/engine/src/bitboard.rs +++ b/engine/src/bitboard.rs @@ -3,8 +3,8 @@ mod utils; mod legality; mod checkinfo; mod attacks; -mod movebuffer; mod movegen; pub mod board; -pub(in super) mod bitmove; \ No newline at end of file +pub(in super) mod bitmove; +pub(in super) mod movebuffer; \ No newline at end of file diff --git a/engine/src/boardsquare.rs b/engine/src/boardsquare.rs index 2e0b57f..3682c51 100644 --- a/engine/src/boardsquare.rs +++ b/engine/src/boardsquare.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub struct BoardSquare { pub x: usize, pub y: usize, diff --git a/engine/src/chessmove.rs b/engine/src/chessmove.rs index 7ea0e1c..ec14ef2 100644 --- a/engine/src/chessmove.rs +++ b/engine/src/chessmove.rs @@ -4,7 +4,7 @@ use super::boardsquare::BoardSquare; use super::piecetype::PieceType; use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] /*pub struct ChessMove { pub move_type: MoveType, pub piece_type: PieceType, @@ -94,7 +94,7 @@ impl ChessMove { }; } - pub(in super) fn from_bitmove(bitmove: &BitMove, board: Board) -> Self { + pub(in super) fn from_bitmove(bitmove: &BitMove, board: &Board) -> Self { match bitmove.move_type() { BitMoveType::Quiet => { let from_square_index = bitmove.from_square(); diff --git a/engine/src/lib.rs b/engine/src/lib.rs index 4e18990..dab9ee1 100644 --- a/engine/src/lib.rs +++ b/engine/src/lib.rs @@ -7,10 +7,23 @@ pub mod gameend; use chessmove::ChessMove; use gameend::GameEnd; +use bitboard::board::Board; +use bitboard::movebuffer::MoveBuffer; pub fn get_available_moves(fen: &str) -> Vec { - println!("get_available_moves answered"); - return vec![]; + let mut board = Board::build(fen); + let mut buffer = MoveBuffer::new(); + let mut temp_buffer = MoveBuffer::new(); + let mut generated_moves: Vec = vec![]; + + board.collect_moves(&mut buffer, &mut temp_buffer); + + for idx in 0..buffer.count() { + generated_moves.push(ChessMove::from_bitmove(buffer.get(idx), &board)); + } + + println!("get_available_moves resulted in {} moves", generated_moves.len()); + return generated_moves; } pub fn is_game_over(fen: &str) -> Option { @@ -25,6 +38,9 @@ pub fn get_board_after_move(fen: &str, chess_move: &ChessMove) -> String { #[cfg(test)] mod tests { + use crate::boardsquare::BoardSquare; + use crate::piecetype::PieceType::*; + use super::*; impl PartialEq for ChessMove { @@ -61,5 +77,88 @@ mod tests { } } - + #[test] + fn get_available_moves_test() { + let boards: [&str; 2] = [ + "rnbqkbnr/pppppppp/8/1B6/4P3/5P1N/PPPP2PP/RNBQK2R w KQkq e6 0 1", + "6Bn/B2Pk3/8/p1r3NK/3p4/b6P/3p2n1/2R5 w - - 0 1" + ]; + let mut expected_moves: Vec> = vec![ + vec![ + ChessMove::capture(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(3, 6), BlackPawn, None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(0, 1), BoardSquare::from_coord(0, 2), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(0, 1), BoardSquare::from_coord(0, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(1, 1), BoardSquare::from_coord(1, 2), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(1, 1), BoardSquare::from_coord(1, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(2, 1), BoardSquare::from_coord(2, 2), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(2, 1), BoardSquare::from_coord(2, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 1), BoardSquare::from_coord(3, 2), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 1), BoardSquare::from_coord(3, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(4, 3), BoardSquare::from_coord(4, 4), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(5, 2), BoardSquare::from_coord(5, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(6, 1), BoardSquare::from_coord(6, 2), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(6, 1), BoardSquare::from_coord(6, 3), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(1, 0), BoardSquare::from_coord(0, 2), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(1, 0), BoardSquare::from_coord(2, 2), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(7, 2), BoardSquare::from_coord(6, 0), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(7, 2), BoardSquare::from_coord(5, 1), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(7, 2), BoardSquare::from_coord(5, 3), None), + ChessMove::quiet(WhiteKnight, BoardSquare::from_coord(7, 2), BoardSquare::from_coord(6, 4), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(5, 0), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(4, 1), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(3, 2), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(2, 3), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(0, 3), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(0, 5), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(1, 4), BoardSquare::from_coord(2, 5), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(7, 0), BoardSquare::from_coord(6, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(7, 0), BoardSquare::from_coord(5, 0), None), + ChessMove::quiet(WhiteQueen, BoardSquare::from_coord(3, 0), BoardSquare::from_coord(4, 1), None), + ChessMove::quiet(WhiteKing, BoardSquare::from_coord(4, 0), BoardSquare::from_coord(4, 1), None), + ChessMove::quiet(WhiteKing, BoardSquare::from_coord(4, 0), BoardSquare::from_coord(5, 1), None), + ChessMove::quiet(WhiteKing, BoardSquare::from_coord(4, 0), BoardSquare::from_coord(5, 0), None), + ChessMove::castle(WhiteKing, BoardSquare::from_coord(4, 0), BoardSquare::from_coord(6, 0), WhiteRook, BoardSquare::from_coord(7, 0), BoardSquare::from_coord(5, 0)) + ], + vec![ + ChessMove::capture(WhiteBishop, BoardSquare::from_coord(0, 6), BoardSquare::from_coord(2, 4), BlackRook, None), + ChessMove::capture(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(2, 4), BlackRook, None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(7, 2), BoardSquare::from_coord(7, 3), None), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 6), BoardSquare::from_coord(3, 7), Some(WhiteQueen)), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 6), BoardSquare::from_coord(3, 7), Some(WhiteRook)), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 6), BoardSquare::from_coord(3, 7), Some(WhiteBishop)), + ChessMove::quiet(WhitePawn, BoardSquare::from_coord(3, 6), BoardSquare::from_coord(3, 7), Some(WhiteKnight)), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(0, 6), BoardSquare::from_coord(1, 5), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(0, 6), BoardSquare::from_coord(1, 7), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(7, 6), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(5, 6), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(4, 5), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(3, 4), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(2, 3), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(1, 2), None), + ChessMove::quiet(WhiteBishop, BoardSquare::from_coord(6, 7), BoardSquare::from_coord(0, 1), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(0, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(1, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(3, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(4, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(5, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(6, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(7, 0), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(2, 1), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(2, 2), None), + ChessMove::quiet(WhiteRook, BoardSquare::from_coord(2, 0), BoardSquare::from_coord(2, 3), None), + ChessMove::quiet(WhiteKing, BoardSquare::from_coord(7, 4), BoardSquare::from_coord(6, 3), None), + ChessMove::quiet(WhiteKing, BoardSquare::from_coord(7, 4), BoardSquare::from_coord(7, 5), None) + ] + ]; + + for case in 0..2 { + + let mut generated_moves = get_available_moves(boards[case]); + + generated_moves.sort(); + expected_moves[case].sort(); + assert_eq!(generated_moves.len(), expected_moves[case].len()); + assert_eq!(generated_moves, expected_moves[case]); + } + } } \ No newline at end of file diff --git a/engine/src/piecetype.rs b/engine/src/piecetype.rs index 92a7e7b..7a6fc5f 100644 --- a/engine/src/piecetype.rs +++ b/engine/src/piecetype.rs @@ -1,6 +1,6 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Debug)] pub enum PieceType { WhitePawn, WhiteKnight,