!(
            f,
            "{}",
            self.castle_rights[Color::White.to_index()].to_string(Color::White)
        )?;
        write!(
            f,
            "{}",
            self.castle_rights[Color::Black.to_index()].to_string(Color::Black)
        )?;
        if self.castle_rights[0] == CastleRights::NoRights
            && self.castle_rights[1] == CastleRights::NoRights
        {
            write!(f, "-")?;
        }

        write!(f, " ")?;
        if let Some(sq) = self.get_en_passant() {
            write!(f, "{}", sq)?;
        } else {
            write!(f, "-")?;
        }

        write!(f, " 0 1")
    }
}

impl Default for BoardBuilder {
    fn default() -> BoardBuilder {
        BoardBuilder::from_str("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1").unwrap()
    }
}

impl FromStr for BoardBuilder {
    type Err = Error;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        let mut cur_rank = Rank::Eighth;
        let mut cur_file = File::A;
        let mut fen = &mut BoardBuilder::new();

        let tokens: Vec<&str> = value.split(' ').collect();
        if tokens.len() < 4 {
            return Err(Error::InvalidFen {
                fen: value.to_string(),
            });
        }

        let pieces = tokens[0];
        let side = tokens[1];
        let castles = tokens[2];
        let ep = tokens[3];

        for x in pieces.chars() {
            match x {
                '/' => {
                    cur_rank = cur_rank.down();
                    cur_file = File::A;
                }
                '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' => {
                    cur_file =
                        File::from_index(cur_file.to_index() + (x as usize) - ('0' as usize));
                }
                'r' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Rook, Color::Black));
                    cur_file = cur_file.right();
                }
                'R' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Rook, Color::White));
                    cur_file = cur_file.right();
                }
                'n' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Knight, Color::Black));
                    cur_file = cur_file.right();
                }
                'N' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Knight, Color::White));
                    cur_file = cur_file.right();
                }
                'b' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Bishop, Color::Black));
                    cur_file = cur_file.right();
                }
                'B' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Bishop, Color::White));
                    cur_file = cur_file.right();
                }
                'p' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Pawn, Color::Black));
                    cur_file = cur_file.right();
                }
                'P' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Pawn, Color::White));
                    cur_file = cur_file.right();
                }
                'q' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Queen, Color::Black));
                    cur_file = cur_file.right();
                }
                'Q' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::Queen, Color::White));
                    cur_file = cur_file.right();
                }
                'k' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::King, Color::Black));
                    cur_file = cur_file.right();
                }
                'K' => {
                    fen[Square::make_square(cur_rank, cur_file)] =
                        Some((Piece::King, Color::White));
                    cur_file = cur_file.right();
                }
                _ => {
                    return Err(Error::InvalidFen {
                        fen: value.to_string(),
                    });
                }
            }
        }
        match side {
            "w" | "W" => fen = fen.side_to_move(Color::White),
            "b" | "B" => fen = fen.side_to_move(Color::Black),
            _ => {
                return Err(Error::InvalidFen {
                    fen: value.to_string(),
                })
            }
        }

        if castles.contains("K") && castles.contains("Q") {
            fen.castle_rights[Color::White.to_index()] = CastleRights::Both;
        } else if castles.contains("K") {
            fen.castle_rights[Color::White.to_index()] = CastleRights::KingSide;
        } else if castles.contains("Q") {
            fen.castle_rights[Color::White.to_index()] = CastleRights::QueenSide;
        } else {
            fen.castle_rights[Color::White.to_index()] = CastleRights::NoRights;
        }

        if castles.contains("k") && castles.contains("q") {
            fen.castle_rights[Color::Black.to_index()] = CastleRights::Both;
        } else if castles.contains("k") {
            fen.castle_rights[Color::Black.to_index()] = CastleRights::KingSide;
        } else if castles.contains("q") {
            fen.castle_rights[Color::Black.to_index()] = CastleRights::QueenSide;
        } else {
            fen.castle_rights[Color::Black.to_index()] = CastleRights::NoRights;
        }

        if let Ok(sq) = Square::from_str(&ep) {
            fen = fen.en_passant(Some(sq.get_file()));
        }

        Ok(*fen)
    }
}

impl From<&Board> for BoardBuilder {
    fn from(board: &Board) -> Self {
        let mut pieces = vec![];
        for sq in ALL_SQUARES.iter() {
            if let Some(piece) = board.piece_on(*sq) {
                let color = board.color_on(*sq).unwrap();
                pieces.push((*sq, piece, color));
            }
        }

        BoardBuilder::setup(
            &pieces,
            board.side_to_move(),
            board.castle_rights(Color::White),
            board.castle_rights(Color::Black),
            board.en_passant().map(|sq| sq.get_file()),
        )
    }
}

impl From<Board> for BoardBuilder {
    fn from(board: Board) -> Self {
        (&board).into()
    }
}

#[cfg(test)]
use crate::bitboard::BitBoard;
#[cfg(test)]
use std::convert::TryInto;

#[test]
fn check_initial_position() {
    let initial_fen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
    let fen: BoardBuilder = Board::default().into();
    let computed_initial