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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use color::*;

pub type Piece = u8;

#[allow(dead_code)]
pub const LEAPER: Piece = 0b0000;

#[allow(dead_code)]
pub const SLIDER: Piece = 0b1000;

pub const EMPTY:  Piece = 0b0000; // 0
pub const PAWN:   Piece = 0b0010; // 2
pub const KNIGHT: Piece = 0b0100; // 4
pub const KING:   Piece = 0b0110; // 6
pub const BISHOP: Piece = 0b1000; // 8
pub const ROOK:   Piece = 0b1010; // 10
pub const QUEEN:  Piece = 0b1100; // 12

pub const PIECES: [Piece; 6] = [PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING];

pub const WHITE_PAWN:   Piece = WHITE | PAWN;
pub const WHITE_KNIGHT: Piece = WHITE | KNIGHT;
pub const WHITE_BISHOP: Piece = WHITE | BISHOP;
pub const WHITE_ROOK:   Piece = WHITE | ROOK;
pub const WHITE_QUEEN:  Piece = WHITE | QUEEN;
pub const WHITE_KING:   Piece = WHITE | KING;
pub const BLACK_PAWN:   Piece = BLACK | PAWN;
pub const BLACK_KNIGHT: Piece = BLACK | KNIGHT;
pub const BLACK_BISHOP: Piece = BLACK | BISHOP;
pub const BLACK_ROOK:   Piece = BLACK | ROOK;
pub const BLACK_QUEEN:  Piece = BLACK | QUEEN;
pub const BLACK_KING:   Piece = BLACK | KING;

pub trait PieceChar {
    fn from_char(c: char) -> Self;
    fn to_char(&self) -> char;
}

impl PieceChar for Piece {
    fn from_char(c: char) -> Piece {
        match c {
            'P' => WHITE_PAWN,
            'N' => WHITE_KNIGHT,
            'B' => WHITE_BISHOP,
            'R' => WHITE_ROOK,
            'Q' => WHITE_QUEEN,
            'K' => WHITE_KING,
            'p' => BLACK_PAWN,
            'n' => BLACK_KNIGHT,
            'b' => BLACK_BISHOP,
            'r' => BLACK_ROOK,
            'q' => BLACK_QUEEN,
            'k' => BLACK_KING,
            _   => EMPTY // FIXME
        }
    }

    fn to_char(&self) -> char {
        match *self {
            WHITE_PAWN   => 'P',
            WHITE_KNIGHT => 'N',
            WHITE_BISHOP => 'B',
            WHITE_ROOK   => 'R',
            WHITE_QUEEN  => 'Q',
            WHITE_KING   => 'K',
            BLACK_PAWN   => 'p',
            BLACK_KNIGHT => 'n',
            BLACK_BISHOP => 'b',
            BLACK_ROOK   => 'r',
            BLACK_QUEEN  => 'q',
            BLACK_KING   => 'k',
            EMPTY        => ' ', // FIXME: not really for FEN format
            _            => '?' // FIXME
        }
    }
}

pub trait PieceAttr {
    /// Get the color of a piece
    fn color(&self) -> Color;

    /// Get a piece without its color
    fn kind(&self) -> Piece;

    fn is_pawn(&self) -> bool;
    fn is_knight(&self) -> bool;
    fn is_bishop(&self) -> bool;
    fn is_rook(&self) -> bool;
    fn is_queen(&self) -> bool;
    fn is_king(&self) -> bool;
}

impl PieceAttr for Piece {
    fn color(&self) -> Color {
        *self & 0b0001
    }
    fn kind(&self) -> Piece {
        *self & 0b1110
    }
    fn is_pawn(&self) -> bool {
        self.kind() == PAWN
    }
    fn is_knight(&self) -> bool {
        self.kind() == KNIGHT
    }
    fn is_bishop(&self) -> bool {
        self.kind() == BISHOP
    }
    fn is_rook(&self) -> bool {
        self.kind() == ROOK
    }
    fn is_queen(&self) -> bool {
        self.kind() == QUEEN
    }
    fn is_king(&self) -> bool {
        self.kind() == KING
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_piece() {
        assert_eq!(LEAPER & PAWN,   LEAPER);
        assert_eq!(LEAPER & KNIGHT, LEAPER);
        assert_eq!(LEAPER & KING,   LEAPER);
        assert_eq!(LEAPER & BISHOP, EMPTY);
        assert_eq!(LEAPER & ROOK,   EMPTY);
        assert_eq!(LEAPER & QUEEN,  EMPTY);

        assert_eq!(SLIDER & PAWN,   EMPTY);
        assert_eq!(SLIDER & KNIGHT, EMPTY);
        assert_eq!(SLIDER & KING,   EMPTY);
        assert_eq!(SLIDER & BISHOP, SLIDER);
        assert_eq!(SLIDER & ROOK,   SLIDER);
        assert_eq!(SLIDER & QUEEN,  SLIDER);
    }
}