primitive_chess_game 0.1.0

A primitive chess game engine in Rust
use std::io::{self, Write};

#[derive(Clone, Copy)]
struct Board {
    squares: [[Option<Piece>; 8]; 8],
}

#[derive(Clone, Copy)]
struct Piece {
    kind: PieceKind,
    color: Color,
}

#[derive(Clone, Copy, PartialEq)]
enum PieceKind {
    Pawn,
    Rook,
    Knight,
    Bishop,
    Queen,
    King,
}

#[derive(Clone, Copy, PartialEq)]
enum Color {
    White,
    Black,
}

impl Board {
    fn new() -> Self {
        let mut board = Board {
            squares: [[None; 8]; 8],
        };

        for i in 0..8 {
            board.squares[1][i] = Some(Piece {
                kind: PieceKind::Pawn,
                color: Color::Black,
            });
            board.squares[6][i] = Some(Piece {
                kind: PieceKind::Pawn,
                color: Color::White,
            });
        }

        let black_back = [
            PieceKind::Rook,
            PieceKind::Knight,
            PieceKind::Bishop,
            PieceKind::Queen,
            PieceKind::King,
            PieceKind::Bishop,
            PieceKind::Knight,
            PieceKind::Rook,
        ];
        for i in 0..8 {
            board.squares[0][i] = Some(Piece {
                kind: black_back[i],
                color: Color::Black,
            });
        }

        let white_back = [
            PieceKind::Rook,
            PieceKind::Knight,
            PieceKind::Bishop,
            PieceKind::Queen,
            PieceKind::King,
            PieceKind::Bishop,
            PieceKind::Knight,
            PieceKind::Rook,
        ];
        for i in 0..8 {
            board.squares[7][i] = Some(Piece {
                kind: white_back[i],
                color: Color::White,
            });
        }

        board
    }

    fn print(&self) {
        println!("\n  a b c d e f g h");
        for rank in (0..8).rev() {
            print!("{} ", rank + 1);
            for file in 0..8 {
                match self.squares[rank][file] {
                    Some(piece) => {
                        let symbol = match piece.kind {
                            PieceKind::Pawn => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                            PieceKind::Rook => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                            PieceKind::Knight => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                            PieceKind::Bishop => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                            PieceKind::Queen => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                            PieceKind::King => {
                                if piece.color == Color::White {
                                    ''
                                } else {
                                    ''
                                }
                            }
                        };
                        print!("{} ", symbol);
                    }
                    None => print!(". "),
                }
            }
            println!("{}", rank + 1);
        }
        println!("  a b c d e f g h\n");
    }

    fn move_piece(&mut self, from: (usize, usize), to: (usize, usize)) -> bool {
        let piece = match self.squares[from.0][from.1] {
            Some(p) => p,
            None => return false,
        };

        if let Some(target) = self.squares[to.0][to.1] {
            if target.color == piece.color {
                return false;
            }
        }

        let row_diff = (to.0 as i32 - from.0 as i32).abs();
        let col_diff = (to.1 as i32 - from.1 as i32).abs();

        let valid = match piece.kind {
            PieceKind::Pawn => {
                let dir = if piece.color == Color::White { -1 } else { 1 };
                let new_row = from.0 as i32 + dir;
                
                if new_row == to.0 as i32 && col_diff == 0 && self.squares[to.0][to.1].is_none() {
                    true
                } else if new_row == to.0 as i32 && col_diff == 1 && self.squares[to.0][to.1].is_some() {
                    true
                } else {
                    false
                }
            }
            PieceKind::Rook => from.0 == to.0 || from.1 == to.1,
            PieceKind::Knight => (row_diff == 2 && col_diff == 1) || (row_diff == 1 && col_diff == 2),
            PieceKind::Bishop => row_diff == col_diff,
            PieceKind::Queen => from.0 == to.0 || from.1 == to.1 || row_diff == col_diff,
            PieceKind::King => row_diff <= 1 && col_diff <= 1,
        };

        if valid {
            self.squares[to.0][to.1] = self.squares[from.0][from.1];
            self.squares[from.0][from.1] = None;
            true
        } else {
            false
        }
    }

    fn get_square_coords(input: &str) -> Option<(usize, usize)> {
        let chars: Vec<char> = input.trim().to_lowercase().chars().collect();
        if chars.len() != 2 {
            return None;
        }

        let file = match chars[0] {
            'a' => 0,
            'b' => 1,
            'c' => 2,
            'd' => 3,
            'e' => 4,
            'f' => 5,
            'g' => 6,
            'h' => 7,
            _ => return None,
        };

        let rank = match chars[1].to_digit(10) {
            Some(r) if (1..=8).contains(&r) => (r - 1) as usize,
            _ => return None,
        };

        Some((rank, file))
    }
}

fn main() {
    let mut board = Board::new();
    let mut turn = Color::White;

    println!("=== ШАХМАТЫ ДЛЯ ПЯТИЛЕТКИ ===");
    println!("Вводи ходы как: e2 e4");
    println!("Белые ходят первыми\n");

    loop {
        board.print();

        let color_name = if turn == Color::White { "Белые" } else { "Черные" };
        print!("{}: ", color_name);
        io::stdout().flush().unwrap();

        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();

        let parts: Vec<&str> = input.trim().split_whitespace().collect();
        if parts.len() != 2 {
            println!("Непонятно. Пиши как: e2 e4\n");
            continue;
        }

        let from = Board::get_square_coords(parts[0]);
        let to = Board::get_square_coords(parts[1]);

        match (from, to) {
            (Some(f), Some(t)) => {
                if let Some(piece) = board.squares[f.0][f.1] {
                    if piece.color != turn {
                        println!("Сейчас ходят {}!\n", color_name);
                        continue;
                    }
                }

                if board.move_piece(f, t) {
                    turn = if turn == Color::White {
                        Color::Black
                    } else {
                        Color::White
                    };
                } else {
                    println!("Так нельзя! Попробуй еще раз\n");
                }
            }
            _ => {
                println!("Неправильные координаты. Используй a1, b2 и т.д.\n");
            }
        }
    }
}