1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use bevy::prelude::Component;

use crate::chess_board::{BoardPosition, BOARD_SIZE};

use super::{Piece, PieceColor, PieceType};

#[derive(Component, Clone, Debug)]
pub(super) struct Pawn {
    color: PieceColor,
    starting_position: BoardPosition,
    position: BoardPosition,
}

impl Pawn {
    pub(super) fn new(position: BoardPosition, color: PieceColor) -> Box<Self> {
        Box::new(Pawn {
            color,
            starting_position: position,
            position,
        })
    }

    fn move_direction(&self) -> i32 {
        match self.color {
            PieceColor::White => -1,
            PieceColor::Black => 1,
        }
    }
}

impl Piece for Pawn {
    fn get_type(&self) -> &PieceType {
        &PieceType::Pawn
    }

    fn get_color(&self) -> &PieceColor {
        &self.color
    }

    fn get_position(&self) -> &BoardPosition {
        &self.position
    }

    fn set_position(&mut self, new_position: &BoardPosition) {
        self.position = *new_position;
    }

    fn get_moves(&self, include_captures: &bool) -> Vec<BoardPosition> {
        let mut moves = Vec::new();
        if (self.position.rank != 0) && (self.position.rank != (BOARD_SIZE - 1)) {
            // Can move forward 1
            moves.push(BoardPosition::new(
                (self.position.rank as i32 + self.move_direction()) as usize,
                self.position.file,
            ));
            if *include_captures {
                if self.position.file != BOARD_SIZE - 1 {
                    moves.push(BoardPosition::new(
                        (self.position.rank as i32 + self.move_direction()) as usize,
                        (self.position.file as i32 + 1) as usize,
                    ));
                }
                if self.position.file != 0 {
                    moves.push(BoardPosition::new(
                        (self.position.rank as i32 + self.move_direction()) as usize,
                        (self.position.file as i32 - 1) as usize,
                    ));
                }
            }
        }
        if ((self.color == PieceColor::White) && (*self.position.rank() == 6))
            || ((self.color == PieceColor::Black) && (*self.position.rank() == 1))
        {
            // Can move forward 2
            moves.push(BoardPosition::new(
                (self.position.rank as i32 + 2 * self.move_direction()) as usize,
                self.position.file,
            ));
        }
        moves
    }

    fn is_sliding(&self) -> bool {
        true
    }

    fn get_starting_position(&self) -> &BoardPosition {
        &self.starting_position
    }

    fn valid_move(&self, end_position: &BoardPosition) -> bool {
        let valid_moves = self.get_moves(&false);
        valid_moves.contains(end_position)
    }

    fn valid_capture(&self, end_position: &BoardPosition) -> bool {
        if (0 <= self.position.rank as i32 + self.move_direction())
            && (self.position.rank as i32 + self.move_direction() < 8)
            && (self.position.rank as i32 + self.move_direction() == end_position.rank as i32)
            && (((self.position.file > 0) && (end_position.file == self.position.file - 1))
                || ((self.position.file < 7) && (end_position.file == self.position.file + 1)))
        {
            return true;
        }
        false
    }
}