diff --git a/src/board.rs b/src/board.rs index 970df37..eba6354 100644 --- a/src/board.rs +++ b/src/board.rs @@ -5,11 +5,13 @@ use crate::{ generate_queen_moves, generate_rook_moves, }, piece_parsing::parse_bitboards, - utils::{opposite_color, print_bitboard}, + utils::{number_to_color, number_to_piece, opposite_color}, }; +use std::process::exit; -pub type Move = u16; +pub type EncodedMove = u32; pub type Bitboard = u64; +pub type DecodedMove = (Bitboard, Bitboard, Piece, Color, Piece, bool); #[derive(Debug, Copy, Clone)] pub enum Color { @@ -38,112 +40,91 @@ pub struct BoardState { pub bb_en_passant: Bitboard, pub halfmove: u32, pub fullmove: u32, - pub move_history: Vec, + pub move_history: Vec, } impl BoardState { - pub fn encode_move(&self, from_bb: u8, to_bb: u8, capture: Piece) -> u16 { - from_bb as u16 | ((to_bb as u16) << 6) | ((capture as u16) << 12) - } - pub fn decode_move( - &self, - piece_move: Move, - is_undoing_doing_move: bool, - ) -> (Bitboard, Bitboard, Piece, Color, Piece, bool) { - let start_bb: Bitboard = - BOARD_SQUARES[((piece_move & !(1 << 7 | 1 << 8 | 1 << 6)) as u8) as usize]; - let end_bb: Bitboard = - BOARD_SQUARES[((piece_move >> 6 & !(1 << 7 | 1 << 8)) as u8) as usize]; - let captured_piece_index: u8 = ((piece_move) >> 12 & (1 | 1 << 1 | 1 << 2)) as u8; - let captured_piece = match captured_piece_index { - 0 => Piece::Pawn, - 1 => Piece::Knight, - 2 => Piece::Bishop, - 3 => Piece::Rook, - 4 => Piece::Queen, - 5 => Piece::King, - _ => Piece::None, - }; - let is_promotion: bool = (piece_move >> 15 & 1) as u8 == 1; - let mut piece: Piece = Piece::None; - let color: Color = match is_undoing_doing_move { - false => self.to_move, - true => opposite_color(self.to_move), - }; - - if is_undoing_doing_move == true { - for piece_index in 0..6 { - if self.bb_pieces[color as usize][piece_index as usize] & end_bb != 0 { - piece = match piece_index { - 0 => Piece::Pawn, - 1 => Piece::Knight, - 2 => Piece::Bishop, - 3 => Piece::Rook, - 4 => Piece::Queen, - 5 => Piece::King, - _ => Piece::None, - }; - } - } - } else { - for piece_index in 0..6 { - if self.bb_pieces[color as usize][piece_index as usize] & start_bb != 0 { - piece = match piece_index { - 0 => Piece::Pawn, - 1 => Piece::Knight, - 2 => Piece::Bishop, - 3 => Piece::Rook, - 4 => Piece::Queen, - 5 => Piece::King, - _ => Piece::None, - }; - } + pub fn get_captured_piece(&self, to_bb: Bitboard) -> Piece { + for index in 0..6 { + if self.bb_pieces[opposite_color(self.to_move) as usize][index] & to_bb != 0 { + return number_to_piece(index as u32).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); } } - // print_bitboard(self.bb_colors[Color::White as usize]); - // print_bitboard(self.bb_colors[Color::Black as usize]); - // print_bitboard(start_bb); - // print_bitboard(end_bb); - // println!("\n\n\n"); - - // piece making move can not be none - if matches!(piece, Piece::None) { - // print_bitboard(self.bb_fullboard); - // print_bitboard(self.get_color_bb(color)); - // print_bitboard(end_bb); - // print_bitboard(self.get_piece_bb(Color::White, Piece::Pawn)); - panic!("Piece::None when decoding move!"); + + Piece::None + } + + pub fn encode_move( + &self, + from_pos: u8, + to_pos: u8, + piece: Piece, + color: Color, + captured_piece: Piece, + is_promotion: bool, + ) -> Result { + if from_pos & !63 != 0 || to_pos & !63 != 0 { + return Err("Incorrect move positions!"); } - // println!("piece: {:?}", piece); - // println!("piece color: {:?}", color); - // println!("captured piece: {:?}\n\n", captured_piece); + // those ands are just another layer of error hanlding + Ok((from_pos as u32) & 63 + | ((to_pos as u32) & 63) << 6 + | ((piece as u32) & 7) << 12 + | (color as u32) << 15 + | (captured_piece as u32) << 18 + | (is_promotion as u32) << 19) + } - (start_bb, end_bb, piece, color, captured_piece, is_promotion) + pub fn decode_move(&self, piece_move: EncodedMove) -> Result { + let start_bb: Bitboard = BOARD_SQUARES[(piece_move & 63) as usize]; + let end_bb: Bitboard = BOARD_SQUARES[((piece_move >> 6) & 63) as usize]; + let piece: Piece = number_to_piece((piece_move >> 12) & 7).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); + let color: Color = number_to_color((piece_move >> 15) & 1).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); + let captured_piece: Piece = number_to_piece((piece_move >> 16) & 7).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); + let is_promotion = (piece_move >> 19) & 1 == 1; + + Ok((start_bb, end_bb, piece, color, captured_piece, is_promotion)) } - pub fn is_in_check(self, color: Color) -> bool { + + pub fn is_in_check(&self, color: &Color) -> bool { let all_attacks = self - .generate_moves_by_color(&opposite_color(color)) + .generate_moves_by_color(&opposite_color(*color)) .iter() - .fold(0, |acc, cur| { - acc | BOARD_SQUARES[((cur >> 6 & !(1 << 8 | 1 << 7)) as u8) as usize] + .fold(0, |all_moves, cur_move| { + all_moves | BOARD_SQUARES[((cur_move >> 6) & 63) as usize] }); - all_attacks & self.get_piece_bb(color, Piece::King) != 0 + all_attacks & self.get_piece_bb(*color, Piece::King) != 0 } - pub fn make_move(&mut self, encoded_move: Move) { - let (start_pos, end_pos, piece, color, captured_piece, _) = - self.decode_move(encoded_move, false); + pub fn make_move(&mut self, piece_move: EncodedMove) { + let (start_bb, end_bb, piece, color, captured_piece, _) = + self.decode_move(piece_move).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); // delete piece on the move square if there is one if !matches!(captured_piece, Piece::None) { match color { Color::White => { - self.bb_pieces[1][captured_piece as usize] &= !end_pos; + self.bb_pieces[1][captured_piece as usize] &= !end_bb; } Color::Black => { - self.bb_pieces[0][captured_piece as usize] &= !end_pos; + self.bb_pieces[0][captured_piece as usize] &= !end_bb; } } } @@ -151,18 +132,18 @@ impl BoardState { // delete piece from color bitboards match color { Color::White => { - self.bb_colors[Color::White as usize] &= !start_pos; - self.bb_colors[Color::White as usize] |= end_pos; + self.bb_colors[Color::White as usize] &= !start_bb; + self.bb_colors[Color::White as usize] |= end_bb; - self.bb_colors[Color::Black as usize] &= !start_pos; - self.bb_colors[Color::Black as usize] &= !end_pos; + self.bb_colors[Color::Black as usize] &= !start_bb; + self.bb_colors[Color::Black as usize] &= !end_bb; } Color::Black => { - self.bb_colors[Color::Black as usize] &= !start_pos; - self.bb_colors[Color::Black as usize] |= end_pos; + self.bb_colors[Color::Black as usize] &= !start_bb; + self.bb_colors[Color::Black as usize] |= end_bb; - self.bb_colors[Color::White as usize] &= !start_pos; - self.bb_colors[Color::White as usize] &= !end_pos; + self.bb_colors[Color::White as usize] &= !start_bb; + self.bb_colors[Color::White as usize] &= !end_bb; } } @@ -177,26 +158,27 @@ impl BoardState { self.bb_castling_rigths[color as usize][0] = 0; } Piece::Rook => { - self.bb_castling_rigths[color as usize][1] &= !start_pos; - self.bb_castling_rigths[color as usize][0] &= !start_pos; + self.bb_castling_rigths[color as usize][1] &= !start_bb; + self.bb_castling_rigths[color as usize][0] &= !start_bb; } Piece::Pawn => { - if start_pos >> 16 == end_pos && matches!(color, Color::White) { - self.bb_en_passant |= start_pos >> 8; + if start_bb >> 16 == end_bb && matches!(color, Color::White) { + self.bb_en_passant |= start_bb >> 8; } - if start_pos << 16 == end_pos && matches!(color, Color::Black) { - self.bb_en_passant |= start_pos << 8; + if start_bb << 16 == end_bb && matches!(color, Color::Black) { + self.bb_en_passant |= start_bb << 8; } } _ => (), } // make a move - self.bb_pieces[color as usize][piece as usize] |= end_pos; - self.bb_colors[color as usize] |= end_pos; - self.bb_fullboard |= end_pos; + self.bb_pieces[color as usize][piece as usize] |= end_bb; + self.bb_pieces[color as usize][piece as usize] ^= start_bb; + self.bb_colors[color as usize] |= end_bb; + self.bb_fullboard |= end_bb; - self.move_history.push(encoded_move); + self.move_history.push(piece_move); // println!("{}", format!("{:016b}", encoded_move)); // println!("{:?}", piece); @@ -212,11 +194,13 @@ impl BoardState { } pub fn undo_move(&mut self) -> Result<(), &str> { - println!("undoing move"); let last_move = self.move_history.pop().expect("No more moves found!"); - let (start_pos, end_pos, piece, color, captured_piece, _) = - self.decode_move(last_move, true); + let (start_bb, end_bb, piece, color, captured_piece, is_promotion) = + self.decode_move(last_move).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); // check for castling and castling avaliability match piece { @@ -224,24 +208,23 @@ impl BoardState { match color { Color::White => { // if piece was previosly of fourth rank - if start_pos & FOURTH_RANK != 0 { - self.bb_en_passant |= start_pos << 8; + if start_bb & FOURTH_RANK != 0 { + self.bb_en_passant |= start_bb << 8; } } Color::Black => { // if piece was previosly of fifth rank - if start_pos & FIFTH_RANK != 0 { - self.bb_en_passant |= start_pos >> 8; + if start_bb & FIFTH_RANK != 0 { + self.bb_en_passant |= start_bb >> 8; } } } } Piece::Rook => { for index in 0..2 { - if (self.bb_castling_rigths[color as usize][index] | start_pos).count_ones() - == 1 + if (self.bb_castling_rigths[color as usize][index] | start_bb).count_ones() == 1 { - self.bb_castling_rigths[color as usize][index] = start_pos; + self.bb_castling_rigths[color as usize][index] = start_bb; } } } @@ -266,19 +249,19 @@ impl BoardState { } // undo move - self.bb_pieces[color as usize][piece as usize] |= start_pos; - self.bb_pieces[color as usize][piece as usize] ^= end_pos; + self.bb_pieces[color as usize][piece as usize] |= start_bb; + self.bb_pieces[color as usize][piece as usize] ^= end_bb; // undo move in colors bb - self.bb_colors[color as usize] |= start_pos; - self.bb_colors[color as usize] ^= end_pos; + self.bb_colors[color as usize] |= start_bb; + self.bb_colors[color as usize] ^= end_bb; // if move captured piece if !matches!(captured_piece, Piece::None) { // if captured piece is not empty - self.bb_pieces[opposite_color(color) as usize][captured_piece as usize] |= end_pos; - self.bb_colors[opposite_color(color) as usize] |= end_pos; - self.bb_fullboard |= end_pos; + self.bb_pieces[opposite_color(color) as usize][captured_piece as usize] |= end_bb; + self.bb_colors[opposite_color(color) as usize] |= end_bb; + self.bb_fullboard |= end_bb; } // undo move in fullboard @@ -299,13 +282,13 @@ impl BoardState { Ok(()) } - pub fn generate_moves_by_color(&self, color: &Color) -> Vec { + pub fn generate_moves_by_color(&self, color: &Color) -> Vec { let opposite_color: &Color = match *color { Color::White => &Color::Black, Color::Black => &Color::White, }; - let mut moves_vec: Vec = vec![]; + let mut moves_vec: Vec = vec![]; // generate pseudo legal moves let pawns_moves = generate_pawn_moves( @@ -321,11 +304,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - piece_move.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); + moves_vec.push( + self.encode_move( + piece_move.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::Pawn, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } @@ -342,11 +335,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - king.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); + moves_vec.push( + self.encode_move( + king.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::King, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } @@ -363,11 +366,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - piece_move.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); + moves_vec.push( + self.encode_move( + piece_move.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::Knight, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } @@ -385,12 +398,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - piece_move.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); - + moves_vec.push( + self.encode_move( + piece_move.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::Bishop, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } } @@ -407,11 +429,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - piece_move.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); + moves_vec.push( + self.encode_move( + piece_move.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::Rook, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } @@ -429,11 +461,21 @@ impl BoardState { while move_bb != 0 { let least_sign_bit = move_bb.trailing_zeros(); - moves_vec.push(self.encode_move( - piece_move.0.trailing_zeros() as u8, - least_sign_bit as u8, - Piece::None, - )); + moves_vec.push( + self.encode_move( + piece_move.0.trailing_zeros() as u8, + least_sign_bit as u8, + Piece::Queen, + *color, + self.get_captured_piece(BOARD_SQUARES[least_sign_bit as usize]), + false, + // later implement promotion + ) + .unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }), + ); move_bb ^= BOARD_SQUARES[least_sign_bit as usize]; } diff --git a/src/eval.rs b/src/eval.rs index 2d3abe6..aacd629 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -7,9 +7,8 @@ use crate::{ piece_parsing::parse_bitboards, }; -pub const WHITE_CHECKMATE: i32 = 10_000; pub const DRAW: i32 = 0; -pub const BLACK_CHECKMATE: i32 = -10_000; +pub const CHECKMATE: i32 = 10_000; pub const PAWN: i32 = 100; pub const KNIGHT: i32 = 310; diff --git a/src/magic.rs b/src/magic.rs index 97eab2d..1be1cac 100644 --- a/src/magic.rs +++ b/src/magic.rs @@ -1,5 +1,6 @@ -// i decided not to leave magics generationg +// i decided not to leave magics generationg fns here // dunno if you did want to see it here tho + use crate::{ board::Bitboard, constants::{BISHOP_MOVES, ROOK_MOVES}, diff --git a/src/main.rs b/src/main.rs index 5b2dd6e..f91a69e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,19 +12,17 @@ mod utils; use board::BoardState; use constants::DEFAULT_FEN_STRING; -use crate::board::Color; -// use search::negamax; -// use utils::print_bitboard; +use search::negamax; fn main() { - // let _board = BoardState::from_fen(DEFAULT_FEN_STRING).unwrap_or_else(|err| { - // println!("{}", err); - // exit(1); - // }); - let board = - BoardState::from_fen("rnbqkbnr/ppppp1pp/8/5p1Q/4P3/8/PPPP1PPP/RNB1KBNR w KQkq f6 0 1") - .expect("Fail during board setup"); - println!("{}", board.is_in_check(Color::Black)); + let mut board = BoardState::from_fen(DEFAULT_FEN_STRING).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); + + let score = negamax(&mut board, 3); + + println!("{}", score); } #[cfg(test)] diff --git a/src/move_generation.rs b/src/move_generation.rs index 8ed904b..cf64ea7 100644 --- a/src/move_generation.rs +++ b/src/move_generation.rs @@ -5,7 +5,7 @@ use crate::constants::{ use crate::magic::{get_bishop_move, get_rook_move}; pub fn generate_pawn_moves( - pawns: Vec<(u32, u32)>, + pawns: Vec<(u8, u8)>, bb_friendly_pieces: Bitboard, bb_enemy_pieces: Bitboard, bb_en_passant: Bitboard, @@ -72,7 +72,7 @@ pub fn generate_pawn_moves( } pub fn generate_king_moves( - kings: Vec<(u32, u32)>, + kings: Vec<(u8, u8)>, bb_friendly_pieces: Bitboard, ) -> Vec<(Bitboard, Bitboard)> { let mut bb_moves_vec: Vec<(Bitboard, Bitboard)> = vec![]; @@ -90,7 +90,7 @@ pub fn generate_king_moves( } pub fn generate_knight_moves( - knights: Vec<(u32, u32)>, + knights: Vec<(u8, u8)>, bb_friendly_pieces: Bitboard, ) -> Vec<(Bitboard, Bitboard)> { let mut bb_moves_vec: Vec<(Bitboard, Bitboard)> = vec![]; @@ -108,7 +108,7 @@ pub fn generate_knight_moves( } pub fn generate_rook_moves( - rooks: Vec<(u32, u32)>, + rooks: Vec<(u8, u8)>, bb_friendly_pieces: Bitboard, bb_fullboard: Bitboard, ) -> Vec<(Bitboard, Bitboard)> { @@ -125,7 +125,7 @@ pub fn generate_rook_moves( } pub fn generate_bishop_moves( - bishops: Vec<(u32, u32)>, + bishops: Vec<(u8, u8)>, bb_friendly_pieces: Bitboard, bb_fullboard: Bitboard, ) -> Vec<(Bitboard, Bitboard)> { @@ -142,7 +142,7 @@ pub fn generate_bishop_moves( } pub fn generate_queen_moves( - queens: Vec<(u32, u32)>, + queens: Vec<(u8, u8)>, bb_fullboard: Bitboard, bb_friendly_pieces: Bitboard, ) -> Vec<(Bitboard, Bitboard)> { diff --git a/src/piece_parsing.rs b/src/piece_parsing.rs index fb9296d..1e949d6 100644 --- a/src/piece_parsing.rs +++ b/src/piece_parsing.rs @@ -1,20 +1,20 @@ use crate::board::{Bitboard, Color}; use crate::constants::BOARD_SQUARES; -pub fn parse_bitboards(color: Color, bitboards: Bitboard) -> Vec<(u32, u32)> { +pub fn parse_bitboards(color: Color, bitboards: Bitboard) -> Vec<(u8, u8)> { let piece_color = match color { Color::White => 0, Color::Black => 1, }; - let mut pieces_vector: Vec<(u32, u32)> = vec![]; + let mut pieces_vector: Vec<(u8, u8)> = vec![]; let mut bb_pieces: u64 = bitboards.clone(); while bb_pieces != 0 { let square_index: u32 = bb_pieces.trailing_zeros(); - pieces_vector.push((piece_color, square_index)); + pieces_vector.push((piece_color, square_index as u8)); bb_pieces ^= BOARD_SQUARES[square_index as usize]; } diff --git a/src/search.rs b/src/search.rs index 614c3a0..9d3aab9 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,46 +1,49 @@ use crate::{ - board::{BoardState, Color, Move}, - eval::evaluate, + board::BoardState, + eval::{evaluate, CHECKMATE, DRAW}, }; +use std::process::exit; -pub fn negamax(board: &mut BoardState, depth: u8, moves: Vec) -> (i32, Move) { - let mut max: i32 = -100_000; - let mut best_move: Move = 0; +pub fn negamax(board: &mut BoardState, depth: u8) -> i32 { + let mut max: i32 = -100_000_000; if depth == 0 { let score = evaluate(board); - return (score, best_move); + return score; + } + + let moves = board.generate_moves_by_color(&board.to_move); + + if moves.is_empty() { + if board.is_in_check(&board.to_move) { + return CHECKMATE; + } + + return DRAW; } for piece_move in moves.iter() { - let (_, _, _, color, _, _) = board.decode_move(*piece_move, false); - board.make_move(*piece_move); + let (_, _, _, color, _, _) = board.decode_move(*piece_move).unwrap_or_else(|err| { + println!("{}", err); + exit(1); + }); - let opposite_color: Color = match color { - Color::White => Color::Black, - Color::Black => Color::White, - }; + board.make_move(*piece_move); - if board.clone().is_in_check(opposite_color) { + if board.is_in_check(&color) { let _ = board.undo_move(); continue; } - let score = -(negamax( - board, - depth - 1, - board.generate_moves_by_color(&board.to_move), - ) - .0); + let score = negamax(board, depth - 1); - if score > max { - best_move = *piece_move; - max = score; + if -score > max { + max = -score; } let _ = board.undo_move(); } - (max, best_move) + max } diff --git a/src/test.rs b/src/test.rs index 1bf2d65..ebdedb8 100644 --- a/src/test.rs +++ b/src/test.rs @@ -22,31 +22,7 @@ fn in_check() { let board = BoardState::from_fen("rnbqkbnr/ppppp1pp/8/5p1Q/4P3/8/PPPP1PPP/RNB1KBNR w KQkq f6 0 1") .expect("Fail during board setup"); - assert!(board.is_in_check(Color::Black)) -} - -#[test] -fn encoding_test() { - let board = BoardState::from_fen(DEFAULT_FEN_STRING).expect("Fail during board setup"); - - let moves = board.encode_move(62, 52, Piece::None); - // choose a white right knight move - - assert_eq!(moves, 27966); -} - -#[test] -fn decoding_test() { - let board = BoardState::from_fen(DEFAULT_FEN_STRING).expect("Fail during board setup"); - - let moves = board.decode_move(board.generate_moves_by_color(&Color::White)[18], false); - // choose a white right knight move - - assert_eq!(moves.0, BOARD_SQUARES[62]); - assert_eq!(moves.1, BOARD_SQUARES[45]); - assert!(matches!(moves.2, Piece::Knight)); - assert!(matches!(moves.3, Color::White)); - assert!(matches!(moves.4, Piece::None)); + assert!(board.is_in_check(&Color::Black)) } #[test] diff --git a/src/utils.rs b/src/utils.rs index d59bb28..021d102 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,4 +1,4 @@ -use crate::board::{Bitboard, Color}; +use crate::board::{Bitboard, Color, Piece}; pub fn print_bitboard(bb: Bitboard) { let formatted_bb: String = format!("{:064b}", bb); @@ -36,3 +36,24 @@ pub fn opposite_color(color: Color) -> Color { Color::Black => Color::White, } } + +pub fn number_to_piece(piece: u32) -> Result { + match piece { + 0 => Ok(Piece::Pawn), + 1 => Ok(Piece::Knight), + 2 => Ok(Piece::Bishop), + 3 => Ok(Piece::Rook), + 4 => Ok(Piece::Queen), + 5 => Ok(Piece::King), + 6 => Ok(Piece::None), + _ => Err("Piece wasn't found when converting!"), + } +} + +pub fn number_to_color(color: u32) -> Result { + match color { + 0 => Ok(Color::White), + 1 => Ok(Color::Black), + _ => Err("Color wasn't found when converting!"), + } +}