diff --git a/2 b/2 new file mode 100644 index 0000000..f5b8b55 --- /dev/null +++ b/2 @@ -0,0 +1,110 @@ +use crate::constants::{ + BitBoard, BB_A_FILE, BB_B_FILE, BB_G_FILE, BB_H_FILE, BOARD_SQUARES, KING_MOVES, + PAWN_ATTACK_SQUARES, +}; + +// rewrite whole fucking pawn move generation + +pub fn generate_pawn_moves( + pawns: Vec<(u32, u32)>, + bb_friendly_pieces: BitBoard, + bb_enemy_pieces: BitBoard, + bb_en_passant: BitBoard, +) -> Vec { + let mut bb_moves_vec: Vec = vec![]; + + let bb_fullboard = bb_friendly_pieces | bb_enemy_pieces; + + for pawn in pawns.iter() { + let mut bb_pawn_moves: BitBoard = 0; + + let attack_squares = PAWN_ATTACK_SQUARES[pawn.0 as usize][pawn.1 as usize]; + + // en passant + if pawn.0 == 0 { + if bb_enemy_pieces | (bb_en_passant << 8) == bb_enemy_pieces + && bb_en_passant | attack_squares == attack_squares + { + // black pawn can get passanted + bb_pawn_moves |= bb_en_passant; + } + } else { + if bb_enemy_pieces | (bb_en_passant >> 8) == bb_enemy_pieces + && bb_en_passant | attack_squares == attack_squares + { + // white pawn can get passanted + bb_pawn_moves |= bb_en_passant; + } + } + + // forward moves generation + // if pawn is white + if pawn.0 == 0 { + if (BOARD_SQUARES[pawn.1 as usize] >> 8) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] >> 8; + } + if pawn.1 >= 48 && pawn.1 <= 55 { + if (BOARD_SQUARES[pawn.1 as usize] >> 16) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] >> 16; + } + } + } else { + // black pawn + if (BOARD_SQUARES[pawn.1 as usize] << 8) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] << 8; + } + + // if pawn is on 2th rank + if pawn.1 >= 8 && pawn.1 <= 15 { + if (BOARD_SQUARES[pawn.1 as usize] << 16) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] << 16; + } + } + } + + bb_moves_vec.push(bb_pawn_moves); + } + + bb_moves_vec +} + +pub fn generate_king_moves(bb_king: Vec<(u32, u32)>, bb_enemy_pieces: BitBoard) -> BitBoard { + let bb_moves: BitBoard = KING_MOVES[bb_king[0].1 as usize]; + + bb_moves ^ bb_enemy_pieces +} + +pub fn generate_knight_moves() { + for square in 0..64 { + let mut bb_moves: BitBoard = 0; + let BB_GH_FILES: BitBoard = BB_H_FILE & BB_G_FILE; + let BB_AB_FILES: BitBoard = BB_A_FILE & BB_B_FILE; + + let bb_square: BitBoard = BOARD_SQUARES[square as usize]; + + if bb_square >> 15 & BB_A_FILE != 0 { + bb_moves |= bb_square >> 15; + } + + if bb_square << 17 & BB_A_FILE != 0 { + bb_moves |= bb_square << 17; + } + + if bb_square >> 17 & BB_H_FILE != 0 { + bb_moves |= bb_square >> 17; + } + + if bb_square << 15 & BB_H_FILE != 0 { + bb_moves |= bb_square << 15; + } + + let visualize: Vec<&str> = String::from(format!("{:b}", bb_moves)).split(" ").collect(); + let vis_vec: Vec<&str> = visualize.chunks(8).collect(); + + for line in vis_vec.iter() { + println!("{}", line); + } + + println!("\n\n\n"); + } +} diff --git a/src/board.rs b/src/board.rs index 8b5d8f0..2da6a0e 100644 --- a/src/board.rs +++ b/src/board.rs @@ -53,26 +53,11 @@ impl BoardState { col += char.to_digit(10).unwrap(); } else { match char { - 'P' => { - bb_white_pawns = - bb_white_pawns | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'N' => { - bb_white_knights = - bb_white_knights | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'B' => { - bb_white_bishops = - bb_white_bishops | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'R' => { - bb_white_rooks = - bb_white_rooks | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'Q' => { - bb_white_queens = - bb_white_queens | BOARD_SQUARES[8 * row as usize + col as usize] - } + 'P' => bb_white_pawns |= BOARD_SQUARES[8 * row as usize + col as usize], + 'N' => bb_white_knights |= BOARD_SQUARES[8 * row as usize + col as usize], + 'B' => bb_white_bishops |= BOARD_SQUARES[8 * row as usize + col as usize], + 'R' => bb_white_rooks |= BOARD_SQUARES[8 * row as usize + col as usize], + 'Q' => bb_white_queens |= BOARD_SQUARES[8 * row as usize + col as usize], 'K' => { if white_king_count > 1 { return Err( @@ -80,30 +65,14 @@ impl BoardState { ); } - bb_white_king = - bb_white_king | BOARD_SQUARES[8 * row as usize + col as usize]; + bb_white_king |= BOARD_SQUARES[8 * row as usize + col as usize]; white_king_count += 1; } - 'p' => { - bb_black_pawns = - bb_black_pawns | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'n' => { - bb_black_knights = - bb_black_knights | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'b' => { - bb_black_bishops = - bb_black_bishops | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'r' => { - bb_black_rooks = - bb_black_rooks | BOARD_SQUARES[8 * row as usize + col as usize] - } - 'q' => { - bb_black_queens = - bb_black_queens | BOARD_SQUARES[8 * row as usize + col as usize] - } + 'p' => bb_black_pawns |= BOARD_SQUARES[8 * row as usize + col as usize], + 'n' => bb_black_knights |= BOARD_SQUARES[8 * row as usize + col as usize], + 'b' => bb_black_bishops |= BOARD_SQUARES[8 * row as usize + col as usize], + 'r' => bb_black_rooks |= BOARD_SQUARES[8 * row as usize + col as usize], + 'q' => bb_black_queens |= BOARD_SQUARES[8 * row as usize + col as usize], 'k' => { if black_king_count > 1 { return Err( @@ -111,8 +80,7 @@ impl BoardState { ); } - bb_black_king = - bb_black_king | BOARD_SQUARES[8 * row as usize + col as usize]; + bb_black_king |= BOARD_SQUARES[8 * row as usize + col as usize]; black_king_count += 1; } @@ -185,7 +153,7 @@ impl BoardState { } if en_passant.len() == 2 { - bb_en_passant = bb_en_passant | BOARD_SQUARES[63 - (en_passant[1] * 8 + en_passant[0])]; + bb_en_passant |= BOARD_SQUARES[63 - (en_passant[1] * 8 + (7 - en_passant[0]))]; } // halfmove parsing diff --git a/src/constants.rs b/src/constants.rs index 3d222a1..a1aed15 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -2,8 +2,10 @@ pub const DEFAULT_FEN_STRING: &str = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBN pub type BitBoard = u64; -// pub const BB_A_FILE: u64 = 18374403900871474942; -// pub const BB_H_FILE: u64 = 9187201950435737471; +// pub const BB_A_FILE: BitBoard = 18374403900871474942; +// pub const BB_B_FILE: BitBoard = 18302063728033398269; +// pub const BB_G_FILE: BitBoard = 13816973012072644543; +// pub const BB_H_FILE: BitBoard = 9187201950435737471; pub const BOARD_SQUARES: [u64; 64] = [ 1, @@ -206,3 +208,137 @@ pub const PAWN_ATTACK_SQUARES: [[u64; 64]; 2] = [ 0, ], ]; + +pub const KING_MOVES: [BitBoard; 64] = [ + 770, + 1797, + 3594, + 7188, + 14376, + 28752, + 57504, + 49216, + 197123, + 460039, + 920078, + 1840156, + 3680312, + 7360624, + 14721248, + 12599488, + 50463488, + 117769984, + 235539968, + 471079936, + 942159872, + 1884319744, + 3768639488, + 3225468928, + 12918652928, + 30149115904, + 60298231808, + 120596463616, + 241192927232, + 482385854464, + 964771708928, + 825720045568, + 3307175149568, + 7718173671424, + 15436347342848, + 30872694685696, + 61745389371392, + 123490778742784, + 246981557485568, + 211384331665408, + 846636838289408, + 1975852459884544, + 3951704919769088, + 7903409839538176, + 15806819679076352, + 31613639358152704, + 63227278716305408, + 54114388906344448, + 216739030602088448, + 505818229730443264, + 1011636459460886528, + 2023272918921773056, + 4046545837843546112, + 8093091675687092224, + 16186183351374184448, + 13853283560024178688, + 144959613005987840, + 362258295026614272, + 724516590053228544, + 1449033180106457088, + 2898066360212914176, + 5796132720425828352, + 11592265440851656704, + 4665729213955833856, +]; + +pub const KNIGHT_MOVES: [BitBoard; 64] = [ + 132096, + 329728, + 659712, + 1319424, + 2638848, + 5277696, + 10489856, + 4202496, + 33816580, + 84410376, + 168886289, + 337772578, + 675545156, + 1351090312, + 2685403152, + 1075839008, + 8657044482, + 21609056261, + 43234889994, + 86469779988, + 172939559976, + 345879119952, + 687463207072, + 275414786112, + 2216203387392, + 5531918402816, + 11068131838464, + 22136263676928, + 44272527353856, + 88545054707712, + 175990581010432, + 70506185244672, + 567348067172352, + 1416171111120896, + 2833441750646784, + 5666883501293568, + 11333767002587136, + 22667534005174272, + 45053588738670592, + 18049583422636032, + 145241105196122112, + 362539804446949376, + 725361088165576704, + 1450722176331153408, + 2901444352662306816, + 5802888705324613632, + 11533718717099671552, + 4620693356194824192, + 288234782788157440, + 576469569871282176, + 1224997833292120064, + 2449995666584240128, + 4899991333168480256, + 9799982666336960512, + 1152939783987658752, + 2305878468463689728, + 1128098930098176, + 2257297371824128, + 4796069720358912, + 9592139440717824, + 19184278881435648, + 38368557762871296, + 4679521487814656, + 9077567998918656, +]; diff --git a/src/main.rs b/src/main.rs index 8d7b83e..9026c8e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ use std::process::exit; mod constants; +use move_generation::generate_king_moves; + use crate::constants::DEFAULT_FEN_STRING; mod board; @@ -10,7 +12,7 @@ mod piece_parsing; use crate::piece_parsing::parse_bitboards_into_vector; mod move_generation; -use crate::move_generation::generate_pawn_moves; +use crate::move_generation::{generate_knight_moves, generate_pawn_moves}; fn main() { let board = BoardState::from_fen(DEFAULT_FEN_STRING).unwrap_or_else(|err| { @@ -18,10 +20,21 @@ fn main() { exit(1); }); - // generate pseudo legal moves for black pawns - let pawn_moves = generate_pawn_moves( - parse_bitboards_into_vector(1, board.bb_pieces[1][0]), + // generate pseudo legal moves + let white_pawn_moves = generate_pawn_moves( + parse_bitboards_into_vector(0, board.bb_pieces[0][0]), + board.bb_colors[0], board.bb_colors[1], + board.bb_en_passant, + ); + + let white_king_moves = generate_king_moves( + parse_bitboards_into_vector(0, board.bb_pieces[0][5]), + board.bb_colors[1], + ); + + let white_knight_moves = generate_knight_moves( + parse_bitboards_into_vector(0, board.bb_pieces[0][2]), board.bb_colors[0], ); } diff --git a/src/move_generation.rs b/src/move_generation.rs index 7355bda..2e04e7c 100644 --- a/src/move_generation.rs +++ b/src/move_generation.rs @@ -1,9 +1,12 @@ -use crate::constants::{BitBoard, BOARD_SQUARES, PAWN_ATTACK_SQUARES}; +use crate::constants::{BitBoard, BOARD_SQUARES, KING_MOVES, KNIGHT_MOVES, PAWN_ATTACK_SQUARES}; + +// rewrite whole fucking pawn move generation pub fn generate_pawn_moves( pawns: Vec<(u32, u32)>, bb_friendly_pieces: BitBoard, bb_enemy_pieces: BitBoard, + bb_en_passant: BitBoard, ) -> Vec { let mut bb_moves_vec: Vec = vec![]; @@ -14,52 +17,49 @@ pub fn generate_pawn_moves( let attack_squares = PAWN_ATTACK_SQUARES[pawn.0 as usize][pawn.1 as usize]; - // pseudo legal pawn forward moves + // if pawn can attack + bb_pawn_moves |= (attack_squares ^ bb_friendly_pieces) & (attack_squares & bb_enemy_pieces); + + // moves generation forward and en passant if pawn.0 == 0 { - // if pawn can move 1 square forward - if bb_fullboard | BOARD_SQUARES[pawn.1 as usize] >> 8 != bb_fullboard { + // white pawn + if (BOARD_SQUARES[pawn.1 as usize] >> 8) | bb_fullboard != bb_fullboard { bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] >> 8; } - // if pawn can move 2 squares forward - if bb_fullboard | BOARD_SQUARES[pawn.1 as usize] >> 16 != bb_fullboard { - bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] >> 16; + + // if pawn is on 2nd rank + if pawn.1 >= 48 && pawn.1 <= 55 { + if (BOARD_SQUARES[pawn.1 as usize] >> 16) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] >> 16; + } + } + + // en passant + if bb_enemy_pieces | (bb_en_passant << 8) == bb_enemy_pieces + && bb_en_passant | attack_squares == attack_squares + { + // black pawn can get passanted + bb_pawn_moves |= bb_en_passant; } } else { - // if pawn can move 1 square forward - if bb_fullboard | BOARD_SQUARES[pawn.1 as usize] << 8 != bb_fullboard { + // black pawn + if (BOARD_SQUARES[pawn.1 as usize] << 8) | bb_fullboard != bb_fullboard { bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] << 8; } - // if pawn can move 2 squares forward - if bb_fullboard | BOARD_SQUARES[pawn.1 as usize] << 16 != bb_fullboard { - bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] << 16; - } - } - // pseudo legal pawn attacks - if bb_fullboard | attack_squares != bb_fullboard - || bb_friendly_pieces | attack_squares == bb_friendly_pieces - { - // all attack squares are empty or - // all attack squares are occupied by friendly pieces - } else if bb_enemy_pieces | attack_squares == bb_enemy_pieces { - // all attack squares are occupied by enemy pieces - bb_pawn_moves |= attack_squares; - } else { - let mut attack_squares_copy = attack_squares.clone(); - - while attack_squares_copy != 0 { - let attack_square_index = attack_squares_copy.trailing_zeros(); - - // if picked attacked square empty or not - if bb_fullboard | BOARD_SQUARES[attack_square_index as usize] == bb_fullboard { - if bb_friendly_pieces | BOARD_SQUARES[attack_square_index as usize] - != bb_friendly_pieces - { - bb_pawn_moves |= BOARD_SQUARES[attack_square_index as usize]; - } + // if pawn is on 7th rank + if pawn.1 >= 8 && pawn.1 <= 15 { + if (BOARD_SQUARES[pawn.1 as usize] << 16) | bb_fullboard != bb_fullboard { + bb_pawn_moves |= BOARD_SQUARES[pawn.1 as usize] << 16; } + } - attack_squares_copy ^= BOARD_SQUARES[attack_square_index as usize]; + // en passant + if bb_enemy_pieces | (bb_en_passant >> 8) == bb_enemy_pieces + && bb_en_passant | attack_squares == attack_squares + { + // white pawn can get passanted + bb_pawn_moves |= bb_en_passant; } } @@ -68,3 +68,24 @@ pub fn generate_pawn_moves( bb_moves_vec } + +pub fn generate_king_moves(bb_king: Vec<(u32, u32)>, bb_friendly_pieces: BitBoard) -> BitBoard { + let bb_moves: BitBoard = KING_MOVES[bb_king[0].1 as usize]; + + (bb_moves ^ bb_friendly_pieces) & bb_moves +} + +pub fn generate_knight_moves( + knights: Vec<(u32, u32)>, + bb_friendly_pieces: BitBoard, +) -> Vec { + let mut bb_moves_vec: Vec = vec![]; + + for knight in knights.iter() { + let bb_moves: BitBoard = KNIGHT_MOVES[knight.1 as usize]; + + bb_moves_vec.push((bb_moves ^ bb_friendly_pieces) & bb_moves); + } + + bb_moves_vec +}