1use crate::constants::{
2 movements::{diagonal_movement, l_movement, linear_movement, max_movement, movement_direction},
3 Color, PieceType, Position,
4};
5
6#[derive(Debug, Clone, Copy, PartialEq)]
21pub struct Piece {
22 pub color: Color,
23 pub piece_type: PieceType,
24}
25
26impl Piece {
27 pub fn new(color: Color, piece_type: PieceType) -> Piece {
47 Piece { color, piece_type }
48 }
49
50 pub fn from_fen(char: char) -> Piece {
70 let color = match char.is_uppercase() {
71 true => Color::White,
72 false => Color::Black,
73 };
74
75 let piece_type = match char.to_lowercase().to_string().as_str() {
76 "p" => PieceType::Pawn,
77 "n" => PieceType::Knight,
78 "b" => PieceType::Bishop,
79 "r" => PieceType::Rook,
80 "q" => PieceType::Queen,
81 "k" => PieceType::King,
82 _ => panic!("Invalid piece type"),
83 };
84
85 Piece::new(color, piece_type)
86 }
87}
88
89impl ToString for Piece {
90 fn to_string(&self) -> String {
106 let char = match self.piece_type {
107 PieceType::Pawn => "p",
108 PieceType::Knight => "n",
109 PieceType::Bishop => "b",
110 PieceType::Rook => "r",
111 PieceType::Queen => "q",
112 PieceType::King => "k",
113 }
114 .to_string();
115
116 match self.color {
117 Color::White => char.to_uppercase(),
118 Color::Black => char,
119 }
120 }
121}
122
123fn pawn_movement(color: Color, start_pos: &Position, end_pos: &Position) -> bool {
134 let direction;
135 let starting_row;
136
137 match color {
138 Color::White => {
139 direction = 1;
140 starting_row = 1;
141 }
142 Color::Black => {
143 direction = -1;
144 starting_row = 6;
145 }
146 }
147
148 if max_movement(start_pos, end_pos, 1) {
149 movement_direction(start_pos, end_pos, (0, direction))
150 || movement_direction(start_pos, end_pos, (1, direction))
151 || movement_direction(start_pos, end_pos, (-1, direction))
152 } else if max_movement(start_pos, end_pos, 2) {
153 movement_direction(start_pos, end_pos, (0, direction)) && start_pos.row == starting_row
154 } else {
155 false
156 }
157}
158
159fn knight_movement(start_pos: &Position, end_pos: &Position) -> bool {
169 l_movement(start_pos, end_pos)
170}
171
172fn bishop_movement(start_pos: &Position, end_pos: &Position) -> bool {
182 diagonal_movement(start_pos, end_pos)
183}
184
185fn rook_movement(start_pos: &Position, end_pos: &Position) -> bool {
195 linear_movement(start_pos, end_pos)
196}
197
198fn queen_movement(start_pos: &Position, end_pos: &Position) -> bool {
208 linear_movement(start_pos, end_pos) || diagonal_movement(start_pos, end_pos)
209}
210
211fn king_movement(start_pos: &Position, end_pos: &Position) -> bool {
221 max_movement(start_pos, end_pos, 1)
222}
223
224pub fn piece_movement(piece: &Piece, start_pos: &Position, end_pos: &Position) -> bool {
247 match piece.piece_type {
248 PieceType::Pawn => pawn_movement(piece.color, start_pos, end_pos),
249 PieceType::Knight => knight_movement(start_pos, end_pos),
250 PieceType::Bishop => bishop_movement(start_pos, end_pos),
251 PieceType::Rook => rook_movement(start_pos, end_pos),
252 PieceType::Queen => queen_movement(start_pos, end_pos),
253 PieceType::King => king_movement(start_pos, end_pos),
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::{
260 bishop_movement, king_movement, knight_movement, pawn_movement, queen_movement,
261 rook_movement, Piece,
262 };
263 use crate::constants::{Color, PieceType, Position};
264
265 #[test]
266 fn test_pawn_movement() {
267 assert!(pawn_movement(
268 Color::White,
269 &Position::from_string("e2"),
270 &Position::from_string("e3")
271 ));
272 assert!(pawn_movement(
273 Color::White,
274 &Position::from_string("e2"),
275 &Position::from_string("e4")
276 ));
277 assert!(pawn_movement(
278 Color::White,
279 &Position::from_string("e2"),
280 &Position::from_string("d3")
281 ));
282 assert!(pawn_movement(
283 Color::White,
284 &Position::from_string("e2"),
285 &Position::from_string("f3")
286 ));
287 assert!(pawn_movement(
288 Color::Black,
289 &Position::from_string("e7"),
290 &Position::from_string("e6")
291 ));
292 assert!(pawn_movement(
293 Color::Black,
294 &Position::from_string("e7"),
295 &Position::from_string("e5")
296 ));
297 assert!(pawn_movement(
298 Color::Black,
299 &Position::from_string("e7"),
300 &Position::from_string("d6")
301 ));
302 assert!(pawn_movement(
303 Color::Black,
304 &Position::from_string("e7"),
305 &Position::from_string("f6")
306 ));
307 assert!(!pawn_movement(
308 Color::White,
309 &Position::from_string("e4"),
310 &Position::from_string("e4")
311 ));
312 assert!(!pawn_movement(
313 Color::White,
314 &Position::from_string("e2"),
315 &Position::from_string("e5")
316 ));
317 assert!(!pawn_movement(
318 Color::White,
319 &Position::from_string("e2"),
320 &Position::from_string("d4")
321 ));
322 assert!(!pawn_movement(
323 Color::White,
324 &Position::from_string("e2"),
325 &Position::from_string("f4")
326 ));
327 assert!(!pawn_movement(
328 Color::Black,
329 &Position::from_string("e4"),
330 &Position::from_string("e4")
331 ));
332 assert!(!pawn_movement(
333 Color::Black,
334 &Position::from_string("e7"),
335 &Position::from_string("e4")
336 ));
337 assert!(!pawn_movement(
338 Color::Black,
339 &Position::from_string("e7"),
340 &Position::from_string("d5")
341 ));
342 assert!(!pawn_movement(
343 Color::Black,
344 &Position::from_string("e7"),
345 &Position::from_string("f5")
346 ));
347 }
348
349 #[test]
350 fn test_knight_movement() {
351 assert!(knight_movement(
352 &Position::from_string("e4"),
353 &Position::from_string("f6")
354 ));
355 assert!(knight_movement(
356 &Position::from_string("e4"),
357 &Position::from_string("g5")
358 ));
359 assert!(knight_movement(
360 &Position::from_string("e4"),
361 &Position::from_string("g3")
362 ));
363 assert!(knight_movement(
364 &Position::from_string("e4"),
365 &Position::from_string("f2")
366 ));
367 assert!(knight_movement(
368 &Position::from_string("e4"),
369 &Position::from_string("d2")
370 ));
371 assert!(knight_movement(
372 &Position::from_string("e4"),
373 &Position::from_string("c3")
374 ));
375 assert!(knight_movement(
376 &Position::from_string("e4"),
377 &Position::from_string("c5")
378 ));
379 assert!(knight_movement(
380 &Position::from_string("e4"),
381 &Position::from_string("d6")
382 ));
383 assert!(!knight_movement(
384 &Position::from_string("e4"),
385 &Position::from_string("e4")
386 ));
387 assert!(!knight_movement(
388 &Position::from_string("e4"),
389 &Position::from_string("e6")
390 ));
391 assert!(!knight_movement(
392 &Position::from_string("e4"),
393 &Position::from_string("g6")
394 ));
395 assert!(!knight_movement(
396 &Position::from_string("e4"),
397 &Position::from_string("g4")
398 ));
399 assert!(!knight_movement(
400 &Position::from_string("e4"),
401 &Position::from_string("f3")
402 ));
403 assert!(!knight_movement(
404 &Position::from_string("e4"),
405 &Position::from_string("d3")
406 ));
407 }
408
409 #[test]
410 fn test_bishop_movement() {
411 assert!(bishop_movement(
412 &Position::from_string("e4"),
413 &Position::from_string("f5")
414 ));
415 assert!(bishop_movement(
416 &Position::from_string("e4"),
417 &Position::from_string("g6")
418 ));
419 assert!(bishop_movement(
420 &Position::from_string("e4"),
421 &Position::from_string("h7")
422 ));
423 assert!(bishop_movement(
424 &Position::from_string("e4"),
425 &Position::from_string("f3")
426 ));
427 assert!(bishop_movement(
428 &Position::from_string("e4"),
429 &Position::from_string("g2")
430 ));
431 assert!(bishop_movement(
432 &Position::from_string("e4"),
433 &Position::from_string("h1")
434 ));
435 assert!(bishop_movement(
436 &Position::from_string("e4"),
437 &Position::from_string("d3")
438 ));
439 assert!(bishop_movement(
440 &Position::from_string("e4"),
441 &Position::from_string("c2")
442 ));
443 assert!(bishop_movement(
444 &Position::from_string("e4"),
445 &Position::from_string("b1")
446 ));
447 assert!(bishop_movement(
448 &Position::from_string("e4"),
449 &Position::from_string("d5")
450 ));
451 assert!(bishop_movement(
452 &Position::from_string("e4"),
453 &Position::from_string("c6")
454 ));
455 assert!(bishop_movement(
456 &Position::from_string("e4"),
457 &Position::from_string("b7")
458 ));
459 assert!(!bishop_movement(
460 &Position::from_string("e4"),
461 &Position::from_string("e4")
462 ));
463 assert!(!bishop_movement(
464 &Position::from_string("e4"),
465 &Position::from_string("e5")
466 ));
467 assert!(!bishop_movement(
468 &Position::from_string("e4"),
469 &Position::from_string("f6")
470 ));
471 assert!(!bishop_movement(
472 &Position::from_string("e4"),
473 &Position::from_string("g7")
474 ));
475 }
476
477 #[test]
478 fn test_rook_movement() {
479 assert!(rook_movement(
480 &Position::from_string("e4"),
481 &Position::from_string("e5")
482 ));
483 assert!(rook_movement(
484 &Position::from_string("e4"),
485 &Position::from_string("e6")
486 ));
487 assert!(rook_movement(
488 &Position::from_string("e4"),
489 &Position::from_string("e7")
490 ));
491 assert!(rook_movement(
492 &Position::from_string("e4"),
493 &Position::from_string("e8")
494 ));
495 assert!(rook_movement(
496 &Position::from_string("e4"),
497 &Position::from_string("e3")
498 ));
499 assert!(rook_movement(
500 &Position::from_string("e4"),
501 &Position::from_string("e2")
502 ));
503 assert!(rook_movement(
504 &Position::from_string("e4"),
505 &Position::from_string("e1")
506 ));
507 assert!(rook_movement(
508 &Position::from_string("e4"),
509 &Position::from_string("f4")
510 ));
511 assert!(rook_movement(
512 &Position::from_string("e4"),
513 &Position::from_string("g4")
514 ));
515 assert!(rook_movement(
516 &Position::from_string("e4"),
517 &Position::from_string("h4")
518 ));
519 assert!(rook_movement(
520 &Position::from_string("e4"),
521 &Position::from_string("d4")
522 ));
523 assert!(rook_movement(
524 &Position::from_string("e4"),
525 &Position::from_string("c4")
526 ));
527 assert!(rook_movement(
528 &Position::from_string("e4"),
529 &Position::from_string("b4")
530 ));
531 assert!(rook_movement(
532 &Position::from_string("e4"),
533 &Position::from_string("a4")
534 ));
535 assert!(!rook_movement(
536 &Position::from_string("e4"),
537 &Position::from_string("e4")
538 ));
539 assert!(!rook_movement(
540 &Position::from_string("e4"),
541 &Position::from_string("f5")
542 ));
543 assert!(!rook_movement(
544 &Position::from_string("e4"),
545 &Position::from_string("g6")
546 ));
547 assert!(!rook_movement(
548 &Position::from_string("e4"),
549 &Position::from_string("h7")
550 ));
551 assert!(!rook_movement(
552 &Position::from_string("e4"),
553 &Position::from_string("d3")
554 ));
555 assert!(!rook_movement(
556 &Position::from_string("e4"),
557 &Position::from_string("c2")
558 ));
559 assert!(!rook_movement(
560 &Position::from_string("e4"),
561 &Position::from_string("b1")
562 ));
563 }
564
565 #[test]
566 fn test_queen_movement() {
567 assert!(queen_movement(
568 &Position::from_string("e4"),
569 &Position::from_string("f5")
570 ));
571 assert!(queen_movement(
572 &Position::from_string("e4"),
573 &Position::from_string("g6")
574 ));
575 assert!(queen_movement(
576 &Position::from_string("e4"),
577 &Position::from_string("h7")
578 ));
579 assert!(queen_movement(
580 &Position::from_string("e4"),
581 &Position::from_string("f3")
582 ));
583 assert!(queen_movement(
584 &Position::from_string("e4"),
585 &Position::from_string("g2")
586 ));
587 assert!(queen_movement(
588 &Position::from_string("e4"),
589 &Position::from_string("h1")
590 ));
591 assert!(queen_movement(
592 &Position::from_string("e4"),
593 &Position::from_string("d3")
594 ));
595 assert!(queen_movement(
596 &Position::from_string("e4"),
597 &Position::from_string("c2")
598 ));
599 assert!(queen_movement(
600 &Position::from_string("e4"),
601 &Position::from_string("b1")
602 ));
603 assert!(queen_movement(
604 &Position::from_string("e4"),
605 &Position::from_string("d5")
606 ));
607 assert!(queen_movement(
608 &Position::from_string("e4"),
609 &Position::from_string("c6")
610 ));
611 assert!(queen_movement(
612 &Position::from_string("e4"),
613 &Position::from_string("b7")
614 ));
615 assert!(queen_movement(
616 &Position::from_string("e4"),
617 &Position::from_string("e5")
618 ));
619 assert!(queen_movement(
620 &Position::from_string("e4"),
621 &Position::from_string("e6")
622 ));
623 assert!(queen_movement(
624 &Position::from_string("e4"),
625 &Position::from_string("e7")
626 ));
627 assert!(queen_movement(
628 &Position::from_string("e4"),
629 &Position::from_string("e8")
630 ));
631 assert!(queen_movement(
632 &Position::from_string("e4"),
633 &Position::from_string("e3")
634 ));
635 assert!(queen_movement(
636 &Position::from_string("e4"),
637 &Position::from_string("e2")
638 ));
639 assert!(queen_movement(
640 &Position::from_string("e4"),
641 &Position::from_string("e1")
642 ));
643 assert!(queen_movement(
644 &Position::from_string("e4"),
645 &Position::from_string("f4")
646 ));
647 assert!(queen_movement(
648 &Position::from_string("e4"),
649 &Position::from_string("g4")
650 ));
651 assert!(queen_movement(
652 &Position::from_string("e4"),
653 &Position::from_string("h4")
654 ));
655 assert!(queen_movement(
656 &Position::from_string("e4"),
657 &Position::from_string("d4")
658 ));
659 assert!(queen_movement(
660 &Position::from_string("e4"),
661 &Position::from_string("c4")
662 ));
663 assert!(queen_movement(
664 &Position::from_string("e4"),
665 &Position::from_string("b4")
666 ));
667 assert!(queen_movement(
668 &Position::from_string("e4"),
669 &Position::from_string("a4")
670 ));
671 assert!(!queen_movement(
672 &Position::from_string("e4"),
673 &Position::from_string("e4")
674 ));
675 assert!(!queen_movement(
676 &Position::from_string("e4"),
677 &Position::from_string("d7")
678 ));
679 assert!(!queen_movement(
680 &Position::from_string("e4"),
681 &Position::from_string("d1")
682 ));
683 assert!(!queen_movement(
684 &Position::from_string("e4"),
685 &Position::from_string("f7")
686 ));
687 assert!(!queen_movement(
688 &Position::from_string("e4"),
689 &Position::from_string("f1")
690 ));
691 assert!(!queen_movement(
692 &Position::from_string("e4"),
693 &Position::from_string("g7")
694 ));
695 assert!(!queen_movement(
696 &Position::from_string("e4"),
697 &Position::from_string("g1")
698 ));
699 assert!(!queen_movement(
700 &Position::from_string("e4"),
701 &Position::from_string("h8")
702 ));
703 }
704
705 #[test]
706 fn test_king_movement() {
707 assert!(king_movement(
708 &Position::from_string("e4"),
709 &Position::from_string("f5")
710 ));
711 assert!(king_movement(
712 &Position::from_string("e4"),
713 &Position::from_string("e5")
714 ));
715 assert!(king_movement(
716 &Position::from_string("e4"),
717 &Position::from_string("d5")
718 ));
719 assert!(king_movement(
720 &Position::from_string("e4"),
721 &Position::from_string("d4")
722 ));
723 assert!(king_movement(
724 &Position::from_string("e4"),
725 &Position::from_string("d3")
726 ));
727 assert!(king_movement(
728 &Position::from_string("e4"),
729 &Position::from_string("e3")
730 ));
731 assert!(king_movement(
732 &Position::from_string("e4"),
733 &Position::from_string("f3")
734 ));
735 assert!(king_movement(
736 &Position::from_string("e4"),
737 &Position::from_string("f4")
738 ));
739 assert!(!king_movement(
740 &Position::from_string("e4"),
741 &Position::from_string("e4")
742 ));
743 assert!(!king_movement(
744 &Position::from_string("e4"),
745 &Position::from_string("e6")
746 ));
747 assert!(!king_movement(
748 &Position::from_string("e4"),
749 &Position::from_string("f6")
750 ));
751 assert!(!king_movement(
752 &Position::from_string("e4"),
753 &Position::from_string("g6")
754 ));
755 assert!(!king_movement(
756 &Position::from_string("e4"),
757 &Position::from_string("g5")
758 ));
759 assert!(!king_movement(
760 &Position::from_string("e4"),
761 &Position::from_string("g4")
762 ));
763 assert!(!king_movement(
764 &Position::from_string("e4"),
765 &Position::from_string("g3")
766 ));
767 assert!(!king_movement(
768 &Position::from_string("e4"),
769 &Position::from_string("f2")
770 ));
771 assert!(!king_movement(
772 &Position::from_string("e4"),
773 &Position::from_string("e2")
774 ));
775 assert!(!king_movement(
776 &Position::from_string("e4"),
777 &Position::from_string("d2")
778 ));
779 assert!(!king_movement(
780 &Position::from_string("e4"),
781 &Position::from_string("d6")
782 ));
783 }
784
785 #[test]
786 fn test_from_fen() {
787 let wpawn = Piece::from_fen('P');
788 assert_eq!(wpawn.color, Color::White);
789 assert_eq!(wpawn.piece_type, PieceType::Pawn);
790
791 let bpawn = Piece::from_fen('p');
792 assert_eq!(bpawn.color, Color::Black);
793 assert_eq!(bpawn.piece_type, PieceType::Pawn);
794
795 let wrook = Piece::from_fen('R');
796 assert_eq!(wrook.color, Color::White);
797 assert_eq!(wrook.piece_type, PieceType::Rook);
798
799 let brook = Piece::from_fen('r');
800 assert_eq!(brook.color, Color::Black);
801 assert_eq!(brook.piece_type, PieceType::Rook);
802
803 let wknight = Piece::from_fen('N');
804 assert_eq!(wknight.color, Color::White);
805 assert_eq!(wknight.piece_type, PieceType::Knight);
806
807 let bknight = Piece::from_fen('n');
808 assert_eq!(bknight.color, Color::Black);
809 assert_eq!(bknight.piece_type, PieceType::Knight);
810
811 let wbishop = Piece::from_fen('B');
812 assert_eq!(wbishop.color, Color::White);
813 assert_eq!(wbishop.piece_type, PieceType::Bishop);
814
815 let bbishop = Piece::from_fen('b');
816 assert_eq!(bbishop.color, Color::Black);
817 assert_eq!(bbishop.piece_type, PieceType::Bishop);
818
819 let wqueen = Piece::from_fen('Q');
820 assert_eq!(wqueen.color, Color::White);
821 assert_eq!(wqueen.piece_type, PieceType::Queen);
822
823 let bqueen = Piece::from_fen('q');
824 assert_eq!(bqueen.color, Color::Black);
825 assert_eq!(bqueen.piece_type, PieceType::Queen);
826
827 let wking = Piece::from_fen('K');
828 assert_eq!(wking.color, Color::White);
829 assert_eq!(wking.piece_type, PieceType::King);
830
831 let bking = Piece::from_fen('k');
832 assert_eq!(bking.color, Color::Black);
833 assert_eq!(bking.piece_type, PieceType::King);
834 }
835
836 #[test]
837 fn test_to_fen() {
838 let wpawn = Piece {
839 color: Color::White,
840 piece_type: PieceType::Pawn,
841 };
842 assert_eq!(wpawn.to_string(), String::from("P"));
843
844 let bpawn = Piece {
845 color: Color::Black,
846 piece_type: PieceType::Pawn,
847 };
848 assert_eq!(bpawn.to_string(), String::from("p"));
849
850 let wrook = Piece {
851 color: Color::White,
852 piece_type: PieceType::Rook,
853 };
854 assert_eq!(wrook.to_string(), String::from("R"));
855
856 let brook = Piece {
857 color: Color::Black,
858 piece_type: PieceType::Rook,
859 };
860 assert_eq!(brook.to_string(), String::from("r"));
861
862 let wknight = Piece {
863 color: Color::White,
864 piece_type: PieceType::Knight,
865 };
866 assert_eq!(wknight.to_string(), String::from("N"));
867
868 let bknight = Piece {
869 color: Color::Black,
870 piece_type: PieceType::Knight,
871 };
872 assert_eq!(bknight.to_string(), String::from("n"));
873
874 let wbishop = Piece {
875 color: Color::White,
876 piece_type: PieceType::Bishop,
877 };
878 assert_eq!(wbishop.to_string(), String::from("B"));
879
880 let bbishop = Piece {
881 color: Color::Black,
882 piece_type: PieceType::Bishop,
883 };
884 assert_eq!(bbishop.to_string(), String::from("b"));
885
886 let wqueen = Piece {
887 color: Color::White,
888 piece_type: PieceType::Queen,
889 };
890 assert_eq!(wqueen.to_string(), String::from("Q"));
891
892 let bqueen = Piece {
893 color: Color::Black,
894 piece_type: PieceType::Queen,
895 };
896 assert_eq!(bqueen.to_string(), String::from("q"));
897
898 let wking = Piece {
899 color: Color::White,
900 piece_type: PieceType::King,
901 };
902 assert_eq!(wking.to_string(), String::from("K"));
903
904 let bking = Piece {
905 color: Color::Black,
906 piece_type: PieceType::King,
907 };
908 assert_eq!(bking.to_string(), String::from("k"));
909 }
910}