Skip to main content

chess_lab/core/
piece.rs

1use std::fmt::{self, Display, Formatter};
2
3use crate::{
4    core::{Color, Position},
5    errors::PieceReprError,
6    utils::movements::{
7        diagonal_movement, l_movement, linear_movement, max_movement, movement_direction,
8    },
9};
10
11/// Represents the type of a chess piece
12///
13#[derive(Debug, PartialEq, Eq, Clone, Copy)]
14pub enum PieceType {
15    /// A pawn
16    Pawn,
17    /// A knight
18    Knight,
19    /// A bishop
20    Bishop,
21    /// A rook
22    Rook,
23    /// A queen
24    Queen,
25    /// A king
26    King,
27}
28
29impl PieceType {
30    /// Gets the [piece type](PieceType) from a character
31    ///
32    /// # Arguments
33    /// * `c`: The character to convert
34    ///
35    /// # Returns
36    /// The [piece type](PieceType) if the character is valid, otherwise `None`
37    ///
38    /// # Example
39    /// ```
40    /// use chess_lab::core::PieceType;
41    ///
42    /// assert_eq!(PieceType::from_char('P'), Some(PieceType::Pawn));
43    /// assert_eq!(PieceType::from_char('N'), Some(PieceType::Knight));
44    /// assert_eq!(PieceType::from_char('B'), Some(PieceType::Bishop));
45    /// assert_eq!(PieceType::from_char('R'), Some(PieceType::Rook));
46    /// assert_eq!(PieceType::from_char('Q'), Some(PieceType::Queen));
47    /// assert_eq!(PieceType::from_char('K'), Some(PieceType::King));
48    ///
49    /// assert_eq!(PieceType::from_char('X'), None);
50    /// assert_eq!(PieceType::from_char('y'), None);
51    /// assert_eq!(PieceType::from_char('p'), Some(PieceType::Pawn));
52    /// ```
53    ///
54    pub fn from_char(c: char) -> Option<PieceType> {
55        match c {
56            'P' | 'p' => Some(PieceType::Pawn),
57            'N' | 'n' => Some(PieceType::Knight),
58            'B' | 'b' => Some(PieceType::Bishop),
59            'R' | 'r' => Some(PieceType::Rook),
60            'Q' | 'q' => Some(PieceType::Queen),
61            'K' | 'k' => Some(PieceType::King),
62            _ => None,
63        }
64    }
65
66    /// Gets the character representation of the [piece type](PieceType)
67    ///
68    /// # Returns
69    /// The character representation of the [piece type](PieceType) (uppercase)
70    ///
71    /// # Example
72    /// ```
73    /// use chess_lab::core::PieceType;
74    ///
75    /// assert_eq!(PieceType::Pawn.to_char(), 'P');
76    /// assert_eq!(PieceType::Knight.to_char(), 'N');
77    /// assert_eq!(PieceType::Bishop.to_char(), 'B');
78    /// assert_eq!(PieceType::Rook.to_char(), 'R');
79    /// assert_eq!(PieceType::Queen.to_char(), 'Q');
80    /// assert_eq!(PieceType::King.to_char(), 'K');
81    /// ```
82    ///
83    pub fn to_char(&self) -> char {
84        match self {
85            PieceType::Pawn => 'P',
86            PieceType::Knight => 'N',
87            PieceType::Bishop => 'B',
88            PieceType::Rook => 'R',
89            PieceType::Queen => 'Q',
90            PieceType::King => 'K',
91        }
92    }
93}
94
95/// Represents a piece on the board with a color and a piece type
96///
97/// # Examples
98/// ```
99/// use chess_lab::core::{Color, PieceType, Piece};
100///
101/// let piece = Piece::new(Color::White, PieceType::Pawn);
102///
103/// assert_eq!(piece.color, Color::White);
104/// assert_eq!(piece.piece_type, PieceType::Pawn);
105/// assert_eq!(piece.to_string(), "P");
106/// ```
107///
108#[derive(Debug, Clone, Copy, PartialEq)]
109pub struct Piece {
110    /// The color of the piece
111    pub color: Color,
112    /// The type of the piece
113    pub piece_type: PieceType,
114}
115
116impl Piece {
117    /// Creates a new piece with a given color and piece type
118    ///
119    /// # Arguments
120    /// * `color`: The color of the piece
121    /// * `piece_type`: The type of the piece
122    ///
123    /// # Returns
124    /// A new piece with the given color and piece type
125    ///
126    /// # Examples
127    /// ```
128    /// use chess_lab::core::{Color, PieceType, Piece};
129    ///
130    /// let piece = Piece::new(Color::White, PieceType::Pawn);
131    ///
132    /// assert_eq!(piece.color, Color::White);
133    /// assert_eq!(piece.piece_type, PieceType::Pawn);
134    /// ```
135    pub fn new(color: Color, piece_type: PieceType) -> Piece {
136        Piece { color, piece_type }
137    }
138
139    /// Creates a new piece from a FEN character
140    ///
141    /// # Arguments
142    /// * `char`: The FEN character representing the piece
143    ///
144    /// # Returns
145    /// A `Result<Piece, PieceReprError>` object
146    /// * `Ok(Piece)`: The new piece
147    /// * `Err(PieceReprError)`: If the FEN character is invalid
148    ///
149    /// # Examples
150    /// ```
151    /// use chess_lab::core::{Color, PieceType, Piece};
152    ///
153    /// let piece = Piece::from_fen('P').unwrap();
154    ///
155    /// assert_eq!(piece.color, Color::White);
156    /// assert_eq!(piece.piece_type, PieceType::Pawn);
157    /// ```
158    ///
159    pub fn from_fen(char: char) -> Result<Piece, PieceReprError> {
160        let color = match char.is_uppercase() {
161            true => Color::White,
162            false => Color::Black,
163        };
164
165        let piece_type = match char.to_lowercase().to_string().as_str() {
166            "p" => PieceType::Pawn,
167            "n" => PieceType::Knight,
168            "b" => PieceType::Bishop,
169            "r" => PieceType::Rook,
170            "q" => PieceType::Queen,
171            "k" => PieceType::King,
172            _ => return Err(PieceReprError::new(char)),
173        };
174
175        Ok(Piece::new(color, piece_type))
176    }
177}
178
179impl Display for Piece {
180    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
181        let char = match self.piece_type {
182            PieceType::Pawn => "p",
183            PieceType::Knight => "n",
184            PieceType::Bishop => "b",
185            PieceType::Rook => "r",
186            PieceType::Queen => "q",
187            PieceType::King => "k",
188        }
189        .to_string();
190
191        match self.color {
192            Color::White => write!(f, "{}", char.to_uppercase()),
193            Color::Black => write!(f, "{}", char),
194        }
195    }
196}
197
198/// Returns true if the movement is valid for a pawn
199///
200/// # Arguments
201/// * `color`: The color of the pawn
202/// * `start_pos`: The starting position of the pawn
203/// * `end_pos`: The ending position of the pawn
204///
205/// # Returns
206/// Whether the movement is valid for a pawn
207///
208fn pawn_movement(color: Color, start_pos: &Position, end_pos: &Position) -> bool {
209    let direction;
210    let starting_row;
211
212    match color {
213        Color::White => {
214            direction = 1;
215            starting_row = 1;
216        }
217        Color::Black => {
218            direction = -1;
219            starting_row = 6;
220        }
221    }
222
223    if max_movement(start_pos, end_pos, 1) {
224        movement_direction(start_pos, end_pos, (0, direction))
225            || movement_direction(start_pos, end_pos, (1, direction))
226            || movement_direction(start_pos, end_pos, (-1, direction))
227    } else if max_movement(start_pos, end_pos, 2) {
228        movement_direction(start_pos, end_pos, (0, direction)) && start_pos.row == starting_row
229    } else {
230        false
231    }
232}
233
234/// Returns true if the movement is valid for a knight
235///
236/// # Arguments
237/// * `start_pos`: The starting position of the knight
238/// * `end_pos`: The ending position of the knight
239///
240/// # Returns
241/// Whether the movement is valid for a knight
242///
243fn knight_movement(start_pos: &Position, end_pos: &Position) -> bool {
244    l_movement(start_pos, end_pos)
245}
246
247/// Returns true if the movement is valid for a bishop
248///
249/// # Arguments
250/// * `start_pos`: The starting position of the bishop
251/// * `end_pos`: The ending position of the bishop
252///
253/// # Returns
254/// Whether the movement is valid for a bishop
255///
256fn bishop_movement(start_pos: &Position, end_pos: &Position) -> bool {
257    diagonal_movement(start_pos, end_pos)
258}
259
260/// Returns true if the movement is valid for a rook
261///
262/// # Arguments
263/// * `start_pos`: The starting position of the rook
264/// * `end_pos`: The ending position of the rook
265///
266/// # Returns
267/// Whether the movement is valid for a rook
268///
269fn rook_movement(start_pos: &Position, end_pos: &Position) -> bool {
270    linear_movement(start_pos, end_pos)
271}
272
273/// Returns true if the movement is valid for a queen
274///
275/// # Arguments
276/// * `start_pos`: The starting position of the queen
277/// * `end_pos`: The ending position of the queen
278///
279/// # Returns
280/// Whether the movement is valid for a queen
281///
282fn queen_movement(start_pos: &Position, end_pos: &Position) -> bool {
283    linear_movement(start_pos, end_pos) || diagonal_movement(start_pos, end_pos)
284}
285
286/// Returns true if the movement is valid for a king
287///
288/// # Arguments
289/// * `start_pos`: The starting position of the king
290/// * `end_pos`: The ending position of the king
291///
292/// # Returns
293/// Whether the movement is valid for a king
294///
295fn king_movement(start_pos: &Position, end_pos: &Position) -> bool {
296    max_movement(start_pos, end_pos, 1)
297}
298
299/// Returns the movement function for a given piece type
300///
301/// # Arguments
302/// * `piece`: The piece to get the movement function for
303/// * `start_pos`: The starting position of the piece
304/// * `end_pos`: The ending position of the piece
305///
306/// # Returns
307/// Whether the movement is valid for the piece
308///
309/// # Examples
310/// ```
311/// use chess_lab::core::{Color, PieceType, Position, Piece, piece_movement};
312///
313/// let piece = Piece::new(Color::White, PieceType::Pawn);
314/// let start_pos = Position::new(0, 1).unwrap();
315/// let end_pos = Position::new(0, 2).unwrap();
316///
317/// assert_eq!(piece_movement(&piece, &start_pos, &end_pos), true);
318/// ```
319///
320pub fn piece_movement(piece: &Piece, start_pos: &Position, end_pos: &Position) -> bool {
321    match piece.piece_type {
322        PieceType::Pawn => pawn_movement(piece.color, start_pos, end_pos),
323        PieceType::Knight => knight_movement(start_pos, end_pos),
324        PieceType::Bishop => bishop_movement(start_pos, end_pos),
325        PieceType::Rook => rook_movement(start_pos, end_pos),
326        PieceType::Queen => queen_movement(start_pos, end_pos),
327        PieceType::King => king_movement(start_pos, end_pos),
328    }
329}
330
331#[cfg(test)]
332mod tests {
333    use crate::core::{Color, PieceType, Position};
334
335    use super::*;
336
337    #[test]
338    fn test_from_char() {
339        assert_eq!(PieceType::from_char('p'), Some(PieceType::Pawn));
340        assert_eq!(PieceType::from_char('P'), Some(PieceType::Pawn));
341        assert_eq!(PieceType::from_char('N'), Some(PieceType::Knight));
342        assert_eq!(PieceType::from_char('n'), Some(PieceType::Knight));
343        assert_eq!(PieceType::from_char('B'), Some(PieceType::Bishop));
344        assert_eq!(PieceType::from_char('b'), Some(PieceType::Bishop));
345        assert_eq!(PieceType::from_char('R'), Some(PieceType::Rook));
346        assert_eq!(PieceType::from_char('r'), Some(PieceType::Rook));
347        assert_eq!(PieceType::from_char('Q'), Some(PieceType::Queen));
348        assert_eq!(PieceType::from_char('q'), Some(PieceType::Queen));
349        assert_eq!(PieceType::from_char('K'), Some(PieceType::King));
350        assert_eq!(PieceType::from_char('k'), Some(PieceType::King));
351
352        assert_eq!(PieceType::from_char('X'), None);
353        assert_eq!(PieceType::from_char('y'), None);
354    }
355
356    #[test]
357    fn test_to_char() {
358        assert_eq!(PieceType::Pawn.to_char(), 'P');
359        assert_eq!(PieceType::Knight.to_char(), 'N');
360        assert_eq!(PieceType::Bishop.to_char(), 'B');
361        assert_eq!(PieceType::Rook.to_char(), 'R');
362        assert_eq!(PieceType::Queen.to_char(), 'Q');
363        assert_eq!(PieceType::King.to_char(), 'K');
364    }
365
366    #[test]
367    fn test_pawn_movement() {
368        assert!(pawn_movement(
369            Color::White,
370            &Position::from_string("e2").unwrap(),
371            &Position::from_string("e3").unwrap()
372        ));
373        assert!(pawn_movement(
374            Color::White,
375            &Position::from_string("e2").unwrap(),
376            &Position::from_string("e4").unwrap()
377        ));
378        assert!(pawn_movement(
379            Color::White,
380            &Position::from_string("e2").unwrap(),
381            &Position::from_string("d3").unwrap()
382        ));
383        assert!(pawn_movement(
384            Color::White,
385            &Position::from_string("e2").unwrap(),
386            &Position::from_string("f3").unwrap()
387        ));
388        assert!(pawn_movement(
389            Color::Black,
390            &Position::from_string("e7").unwrap(),
391            &Position::from_string("e6").unwrap()
392        ));
393        assert!(pawn_movement(
394            Color::Black,
395            &Position::from_string("e7").unwrap(),
396            &Position::from_string("e5").unwrap()
397        ));
398        assert!(pawn_movement(
399            Color::Black,
400            &Position::from_string("e7").unwrap(),
401            &Position::from_string("d6").unwrap()
402        ));
403        assert!(pawn_movement(
404            Color::Black,
405            &Position::from_string("e7").unwrap(),
406            &Position::from_string("f6").unwrap()
407        ));
408        assert!(!pawn_movement(
409            Color::White,
410            &Position::from_string("e4").unwrap(),
411            &Position::from_string("e4").unwrap()
412        ));
413        assert!(!pawn_movement(
414            Color::White,
415            &Position::from_string("e2").unwrap(),
416            &Position::from_string("e5").unwrap()
417        ));
418        assert!(!pawn_movement(
419            Color::White,
420            &Position::from_string("e2").unwrap(),
421            &Position::from_string("d4").unwrap()
422        ));
423        assert!(!pawn_movement(
424            Color::White,
425            &Position::from_string("e2").unwrap(),
426            &Position::from_string("f4").unwrap()
427        ));
428        assert!(!pawn_movement(
429            Color::Black,
430            &Position::from_string("e4").unwrap(),
431            &Position::from_string("e4").unwrap()
432        ));
433        assert!(!pawn_movement(
434            Color::Black,
435            &Position::from_string("e7").unwrap(),
436            &Position::from_string("e4").unwrap()
437        ));
438        assert!(!pawn_movement(
439            Color::Black,
440            &Position::from_string("e7").unwrap(),
441            &Position::from_string("d5").unwrap()
442        ));
443        assert!(!pawn_movement(
444            Color::Black,
445            &Position::from_string("e7").unwrap(),
446            &Position::from_string("f5").unwrap()
447        ));
448        assert!(!pawn_movement(
449            Color::Black,
450            &Position::from_string("a6").unwrap(),
451            &Position::from_string("b7").unwrap()
452        ));
453    }
454
455    #[test]
456    fn test_knight_movement() {
457        assert!(knight_movement(
458            &Position::from_string("e4").unwrap(),
459            &Position::from_string("f6").unwrap()
460        ));
461        assert!(knight_movement(
462            &Position::from_string("e4").unwrap(),
463            &Position::from_string("g5").unwrap()
464        ));
465        assert!(knight_movement(
466            &Position::from_string("e4").unwrap(),
467            &Position::from_string("g3").unwrap()
468        ));
469        assert!(knight_movement(
470            &Position::from_string("e4").unwrap(),
471            &Position::from_string("f2").unwrap()
472        ));
473        assert!(knight_movement(
474            &Position::from_string("e4").unwrap(),
475            &Position::from_string("d2").unwrap()
476        ));
477        assert!(knight_movement(
478            &Position::from_string("e4").unwrap(),
479            &Position::from_string("c3").unwrap()
480        ));
481        assert!(knight_movement(
482            &Position::from_string("e4").unwrap(),
483            &Position::from_string("c5").unwrap()
484        ));
485        assert!(knight_movement(
486            &Position::from_string("e4").unwrap(),
487            &Position::from_string("d6").unwrap()
488        ));
489        assert!(!knight_movement(
490            &Position::from_string("e4").unwrap(),
491            &Position::from_string("e4").unwrap()
492        ));
493        assert!(!knight_movement(
494            &Position::from_string("e4").unwrap(),
495            &Position::from_string("e6").unwrap()
496        ));
497        assert!(!knight_movement(
498            &Position::from_string("e4").unwrap(),
499            &Position::from_string("g6").unwrap()
500        ));
501        assert!(!knight_movement(
502            &Position::from_string("e4").unwrap(),
503            &Position::from_string("g4").unwrap()
504        ));
505        assert!(!knight_movement(
506            &Position::from_string("e4").unwrap(),
507            &Position::from_string("f3").unwrap()
508        ));
509        assert!(!knight_movement(
510            &Position::from_string("e4").unwrap(),
511            &Position::from_string("d3").unwrap()
512        ));
513    }
514
515    #[test]
516    fn test_bishop_movement() {
517        assert!(bishop_movement(
518            &Position::from_string("e4").unwrap(),
519            &Position::from_string("f5").unwrap()
520        ));
521        assert!(bishop_movement(
522            &Position::from_string("e4").unwrap(),
523            &Position::from_string("g6").unwrap()
524        ));
525        assert!(bishop_movement(
526            &Position::from_string("e4").unwrap(),
527            &Position::from_string("h7").unwrap()
528        ));
529        assert!(bishop_movement(
530            &Position::from_string("e4").unwrap(),
531            &Position::from_string("f3").unwrap()
532        ));
533        assert!(bishop_movement(
534            &Position::from_string("e4").unwrap(),
535            &Position::from_string("g2").unwrap()
536        ));
537        assert!(bishop_movement(
538            &Position::from_string("e4").unwrap(),
539            &Position::from_string("h1").unwrap()
540        ));
541        assert!(bishop_movement(
542            &Position::from_string("e4").unwrap(),
543            &Position::from_string("d3").unwrap()
544        ));
545        assert!(bishop_movement(
546            &Position::from_string("e4").unwrap(),
547            &Position::from_string("c2").unwrap()
548        ));
549        assert!(bishop_movement(
550            &Position::from_string("e4").unwrap(),
551            &Position::from_string("b1").unwrap()
552        ));
553        assert!(bishop_movement(
554            &Position::from_string("e4").unwrap(),
555            &Position::from_string("d5").unwrap()
556        ));
557        assert!(bishop_movement(
558            &Position::from_string("e4").unwrap(),
559            &Position::from_string("c6").unwrap()
560        ));
561        assert!(bishop_movement(
562            &Position::from_string("e4").unwrap(),
563            &Position::from_string("b7").unwrap()
564        ));
565        assert!(!bishop_movement(
566            &Position::from_string("e4").unwrap(),
567            &Position::from_string("e4").unwrap()
568        ));
569        assert!(!bishop_movement(
570            &Position::from_string("e4").unwrap(),
571            &Position::from_string("e5").unwrap()
572        ));
573        assert!(!bishop_movement(
574            &Position::from_string("e4").unwrap(),
575            &Position::from_string("f6").unwrap()
576        ));
577        assert!(!bishop_movement(
578            &Position::from_string("e4").unwrap(),
579            &Position::from_string("g7").unwrap()
580        ));
581    }
582
583    #[test]
584    fn test_rook_movement() {
585        assert!(rook_movement(
586            &Position::from_string("e4").unwrap(),
587            &Position::from_string("e5").unwrap()
588        ));
589        assert!(rook_movement(
590            &Position::from_string("e4").unwrap(),
591            &Position::from_string("e6").unwrap()
592        ));
593        assert!(rook_movement(
594            &Position::from_string("e4").unwrap(),
595            &Position::from_string("e7").unwrap()
596        ));
597        assert!(rook_movement(
598            &Position::from_string("e4").unwrap(),
599            &Position::from_string("e8").unwrap()
600        ));
601        assert!(rook_movement(
602            &Position::from_string("e4").unwrap(),
603            &Position::from_string("e3").unwrap()
604        ));
605        assert!(rook_movement(
606            &Position::from_string("e4").unwrap(),
607            &Position::from_string("e2").unwrap()
608        ));
609        assert!(rook_movement(
610            &Position::from_string("e4").unwrap(),
611            &Position::from_string("e1").unwrap()
612        ));
613        assert!(rook_movement(
614            &Position::from_string("e4").unwrap(),
615            &Position::from_string("f4").unwrap()
616        ));
617        assert!(rook_movement(
618            &Position::from_string("e4").unwrap(),
619            &Position::from_string("g4").unwrap()
620        ));
621        assert!(rook_movement(
622            &Position::from_string("e4").unwrap(),
623            &Position::from_string("h4").unwrap()
624        ));
625        assert!(rook_movement(
626            &Position::from_string("e4").unwrap(),
627            &Position::from_string("d4").unwrap()
628        ));
629        assert!(rook_movement(
630            &Position::from_string("e4").unwrap(),
631            &Position::from_string("c4").unwrap()
632        ));
633        assert!(rook_movement(
634            &Position::from_string("e4").unwrap(),
635            &Position::from_string("b4").unwrap()
636        ));
637        assert!(rook_movement(
638            &Position::from_string("e4").unwrap(),
639            &Position::from_string("a4").unwrap()
640        ));
641        assert!(!rook_movement(
642            &Position::from_string("e4").unwrap(),
643            &Position::from_string("e4").unwrap()
644        ));
645        assert!(!rook_movement(
646            &Position::from_string("e4").unwrap(),
647            &Position::from_string("f5").unwrap()
648        ));
649        assert!(!rook_movement(
650            &Position::from_string("e4").unwrap(),
651            &Position::from_string("g6").unwrap()
652        ));
653        assert!(!rook_movement(
654            &Position::from_string("e4").unwrap(),
655            &Position::from_string("h7").unwrap()
656        ));
657        assert!(!rook_movement(
658            &Position::from_string("e4").unwrap(),
659            &Position::from_string("d3").unwrap()
660        ));
661        assert!(!rook_movement(
662            &Position::from_string("e4").unwrap(),
663            &Position::from_string("c2").unwrap()
664        ));
665        assert!(!rook_movement(
666            &Position::from_string("e4").unwrap(),
667            &Position::from_string("b1").unwrap()
668        ));
669    }
670
671    #[test]
672    fn test_queen_movement() {
673        assert!(queen_movement(
674            &Position::from_string("e4").unwrap(),
675            &Position::from_string("f5").unwrap()
676        ));
677        assert!(queen_movement(
678            &Position::from_string("e4").unwrap(),
679            &Position::from_string("g6").unwrap()
680        ));
681        assert!(queen_movement(
682            &Position::from_string("e4").unwrap(),
683            &Position::from_string("h7").unwrap()
684        ));
685        assert!(queen_movement(
686            &Position::from_string("e4").unwrap(),
687            &Position::from_string("f3").unwrap()
688        ));
689        assert!(queen_movement(
690            &Position::from_string("e4").unwrap(),
691            &Position::from_string("g2").unwrap()
692        ));
693        assert!(queen_movement(
694            &Position::from_string("e4").unwrap(),
695            &Position::from_string("h1").unwrap()
696        ));
697        assert!(queen_movement(
698            &Position::from_string("e4").unwrap(),
699            &Position::from_string("d3").unwrap()
700        ));
701        assert!(queen_movement(
702            &Position::from_string("e4").unwrap(),
703            &Position::from_string("c2").unwrap()
704        ));
705        assert!(queen_movement(
706            &Position::from_string("e4").unwrap(),
707            &Position::from_string("b1").unwrap()
708        ));
709        assert!(queen_movement(
710            &Position::from_string("e4").unwrap(),
711            &Position::from_string("d5").unwrap()
712        ));
713        assert!(queen_movement(
714            &Position::from_string("e4").unwrap(),
715            &Position::from_string("c6").unwrap()
716        ));
717        assert!(queen_movement(
718            &Position::from_string("e4").unwrap(),
719            &Position::from_string("b7").unwrap()
720        ));
721        assert!(queen_movement(
722            &Position::from_string("e4").unwrap(),
723            &Position::from_string("e5").unwrap()
724        ));
725        assert!(queen_movement(
726            &Position::from_string("e4").unwrap(),
727            &Position::from_string("e6").unwrap()
728        ));
729        assert!(queen_movement(
730            &Position::from_string("e4").unwrap(),
731            &Position::from_string("e7").unwrap()
732        ));
733        assert!(queen_movement(
734            &Position::from_string("e4").unwrap(),
735            &Position::from_string("e8").unwrap()
736        ));
737        assert!(queen_movement(
738            &Position::from_string("e4").unwrap(),
739            &Position::from_string("e3").unwrap()
740        ));
741        assert!(queen_movement(
742            &Position::from_string("e4").unwrap(),
743            &Position::from_string("e2").unwrap()
744        ));
745        assert!(queen_movement(
746            &Position::from_string("e4").unwrap(),
747            &Position::from_string("e1").unwrap()
748        ));
749        assert!(queen_movement(
750            &Position::from_string("e4").unwrap(),
751            &Position::from_string("f4").unwrap()
752        ));
753        assert!(queen_movement(
754            &Position::from_string("e4").unwrap(),
755            &Position::from_string("g4").unwrap()
756        ));
757        assert!(queen_movement(
758            &Position::from_string("e4").unwrap(),
759            &Position::from_string("h4").unwrap()
760        ));
761        assert!(queen_movement(
762            &Position::from_string("e4").unwrap(),
763            &Position::from_string("d4").unwrap()
764        ));
765        assert!(queen_movement(
766            &Position::from_string("e4").unwrap(),
767            &Position::from_string("c4").unwrap()
768        ));
769        assert!(queen_movement(
770            &Position::from_string("e4").unwrap(),
771            &Position::from_string("b4").unwrap()
772        ));
773        assert!(queen_movement(
774            &Position::from_string("e4").unwrap(),
775            &Position::from_string("a4").unwrap()
776        ));
777        assert!(!queen_movement(
778            &Position::from_string("e4").unwrap(),
779            &Position::from_string("e4").unwrap()
780        ));
781        assert!(!queen_movement(
782            &Position::from_string("e4").unwrap(),
783            &Position::from_string("d7").unwrap()
784        ));
785        assert!(!queen_movement(
786            &Position::from_string("e4").unwrap(),
787            &Position::from_string("d1").unwrap()
788        ));
789        assert!(!queen_movement(
790            &Position::from_string("e4").unwrap(),
791            &Position::from_string("f7").unwrap()
792        ));
793        assert!(!queen_movement(
794            &Position::from_string("e4").unwrap(),
795            &Position::from_string("f1").unwrap()
796        ));
797        assert!(!queen_movement(
798            &Position::from_string("e4").unwrap(),
799            &Position::from_string("g7").unwrap()
800        ));
801        assert!(!queen_movement(
802            &Position::from_string("e4").unwrap(),
803            &Position::from_string("g1").unwrap()
804        ));
805        assert!(!queen_movement(
806            &Position::from_string("e4").unwrap(),
807            &Position::from_string("h8").unwrap()
808        ));
809    }
810
811    #[test]
812    fn test_king_movement() {
813        assert!(king_movement(
814            &Position::from_string("e4").unwrap(),
815            &Position::from_string("f5").unwrap()
816        ));
817        assert!(king_movement(
818            &Position::from_string("e4").unwrap(),
819            &Position::from_string("e5").unwrap()
820        ));
821        assert!(king_movement(
822            &Position::from_string("e4").unwrap(),
823            &Position::from_string("d5").unwrap()
824        ));
825        assert!(king_movement(
826            &Position::from_string("e4").unwrap(),
827            &Position::from_string("d4").unwrap()
828        ));
829        assert!(king_movement(
830            &Position::from_string("e4").unwrap(),
831            &Position::from_string("d3").unwrap()
832        ));
833        assert!(king_movement(
834            &Position::from_string("e4").unwrap(),
835            &Position::from_string("e3").unwrap()
836        ));
837        assert!(king_movement(
838            &Position::from_string("e4").unwrap(),
839            &Position::from_string("f3").unwrap()
840        ));
841        assert!(king_movement(
842            &Position::from_string("e4").unwrap(),
843            &Position::from_string("f4").unwrap()
844        ));
845        assert!(!king_movement(
846            &Position::from_string("e4").unwrap(),
847            &Position::from_string("e4").unwrap()
848        ));
849        assert!(!king_movement(
850            &Position::from_string("e4").unwrap(),
851            &Position::from_string("e6").unwrap()
852        ));
853        assert!(!king_movement(
854            &Position::from_string("e4").unwrap(),
855            &Position::from_string("f6").unwrap()
856        ));
857        assert!(!king_movement(
858            &Position::from_string("e4").unwrap(),
859            &Position::from_string("g6").unwrap()
860        ));
861        assert!(!king_movement(
862            &Position::from_string("e4").unwrap(),
863            &Position::from_string("g5").unwrap()
864        ));
865        assert!(!king_movement(
866            &Position::from_string("e4").unwrap(),
867            &Position::from_string("g4").unwrap()
868        ));
869        assert!(!king_movement(
870            &Position::from_string("e4").unwrap(),
871            &Position::from_string("g3").unwrap()
872        ));
873        assert!(!king_movement(
874            &Position::from_string("e4").unwrap(),
875            &Position::from_string("f2").unwrap()
876        ));
877        assert!(!king_movement(
878            &Position::from_string("e4").unwrap(),
879            &Position::from_string("e2").unwrap()
880        ));
881        assert!(!king_movement(
882            &Position::from_string("e4").unwrap(),
883            &Position::from_string("d2").unwrap()
884        ));
885        assert!(!king_movement(
886            &Position::from_string("e4").unwrap(),
887            &Position::from_string("d6").unwrap()
888        ));
889    }
890
891    #[test]
892    fn test_from_fen() {
893        let wpawn = Piece::from_fen('P').unwrap();
894        assert_eq!(wpawn.color, Color::White);
895        assert_eq!(wpawn.piece_type, PieceType::Pawn);
896
897        let bpawn = Piece::from_fen('p').unwrap();
898        assert_eq!(bpawn.color, Color::Black);
899        assert_eq!(bpawn.piece_type, PieceType::Pawn);
900
901        let wrook = Piece::from_fen('R').unwrap();
902        assert_eq!(wrook.color, Color::White);
903        assert_eq!(wrook.piece_type, PieceType::Rook);
904
905        let brook = Piece::from_fen('r').unwrap();
906        assert_eq!(brook.color, Color::Black);
907        assert_eq!(brook.piece_type, PieceType::Rook);
908
909        let wknight = Piece::from_fen('N').unwrap();
910        assert_eq!(wknight.color, Color::White);
911        assert_eq!(wknight.piece_type, PieceType::Knight);
912
913        let bknight = Piece::from_fen('n').unwrap();
914        assert_eq!(bknight.color, Color::Black);
915        assert_eq!(bknight.piece_type, PieceType::Knight);
916
917        let wbishop = Piece::from_fen('B').unwrap();
918        assert_eq!(wbishop.color, Color::White);
919        assert_eq!(wbishop.piece_type, PieceType::Bishop);
920
921        let bbishop = Piece::from_fen('b').unwrap();
922        assert_eq!(bbishop.color, Color::Black);
923        assert_eq!(bbishop.piece_type, PieceType::Bishop);
924
925        let wqueen = Piece::from_fen('Q').unwrap();
926        assert_eq!(wqueen.color, Color::White);
927        assert_eq!(wqueen.piece_type, PieceType::Queen);
928
929        let bqueen = Piece::from_fen('q').unwrap();
930        assert_eq!(bqueen.color, Color::Black);
931        assert_eq!(bqueen.piece_type, PieceType::Queen);
932
933        let wking = Piece::from_fen('K').unwrap();
934        assert_eq!(wking.color, Color::White);
935        assert_eq!(wking.piece_type, PieceType::King);
936
937        let bking = Piece::from_fen('k').unwrap();
938        assert_eq!(bking.color, Color::Black);
939        assert_eq!(bking.piece_type, PieceType::King);
940    }
941
942    #[test]
943    fn test_from_fen_invalid() {
944        let result = Piece::from_fen('X');
945        assert!(result.is_err());
946    }
947
948    #[test]
949    fn test_to_fen() {
950        let wpawn = Piece {
951            color: Color::White,
952            piece_type: PieceType::Pawn,
953        };
954        assert_eq!(wpawn.to_string(), String::from("P"));
955
956        let bpawn = Piece {
957            color: Color::Black,
958            piece_type: PieceType::Pawn,
959        };
960        assert_eq!(bpawn.to_string(), String::from("p"));
961
962        let wrook = Piece {
963            color: Color::White,
964            piece_type: PieceType::Rook,
965        };
966        assert_eq!(wrook.to_string(), String::from("R"));
967
968        let brook = Piece {
969            color: Color::Black,
970            piece_type: PieceType::Rook,
971        };
972        assert_eq!(brook.to_string(), String::from("r"));
973
974        let wknight = Piece {
975            color: Color::White,
976            piece_type: PieceType::Knight,
977        };
978        assert_eq!(wknight.to_string(), String::from("N"));
979
980        let bknight = Piece {
981            color: Color::Black,
982            piece_type: PieceType::Knight,
983        };
984        assert_eq!(bknight.to_string(), String::from("n"));
985
986        let wbishop = Piece {
987            color: Color::White,
988            piece_type: PieceType::Bishop,
989        };
990        assert_eq!(wbishop.to_string(), String::from("B"));
991
992        let bbishop = Piece {
993            color: Color::Black,
994            piece_type: PieceType::Bishop,
995        };
996        assert_eq!(bbishop.to_string(), String::from("b"));
997
998        let wqueen = Piece {
999            color: Color::White,
1000            piece_type: PieceType::Queen,
1001        };
1002        assert_eq!(wqueen.to_string(), String::from("Q"));
1003
1004        let bqueen = Piece {
1005            color: Color::Black,
1006            piece_type: PieceType::Queen,
1007        };
1008        assert_eq!(bqueen.to_string(), String::from("q"));
1009
1010        let wking = Piece {
1011            color: Color::White,
1012            piece_type: PieceType::King,
1013        };
1014        assert_eq!(wking.to_string(), String::from("K"));
1015
1016        let bking = Piece {
1017            color: Color::Black,
1018            piece_type: PieceType::King,
1019        };
1020        assert_eq!(bking.to_string(), String::from("k"));
1021    }
1022}