|  | @@ -2,6 +2,7 @@ use bitboard::Bitboard;
 | 
	
		
			
				|  |  |  use bitboard::Square;
 | 
	
		
			
				|  |  |  use bitboard::*;
 | 
	
		
			
				|  |  |  use game::Game;
 | 
	
		
			
				|  |  | +use log::info;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub type Side = bool;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -28,7 +29,7 @@ pub struct SimpleMove {
 | 
	
		
			
				|  |  |  pub enum Move {
 | 
	
		
			
				|  |  |      Default { mov: SimpleMove, piece_type: PieceType },
 | 
	
		
			
				|  |  |      Castling { side: Side, left: bool },
 | 
	
		
			
				|  |  | -    EnPassant { side: Side, column: u8 },
 | 
	
		
			
				|  |  | +    EnPassant { mov: SimpleMove, beaten: Square },
 | 
	
		
			
				|  |  |      Promotion { mov: SimpleMove, promote_to: PieceType },
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -65,8 +66,25 @@ impl Move {
 | 
	
		
			
				|  |  |              Move::Default{ mov, piece_type } => {
 | 
	
		
			
				|  |  |                  Self::square_to_string(mov.from) + &Self::square_to_string(mov.to)
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  | -            Move::Castling{ side, left } => { "castling not implemented".to_owned() },
 | 
	
		
			
				|  |  | -            Move::EnPassant{ side, column } => { "en passant not implemented".to_owned() },
 | 
	
		
			
				|  |  | +            Move::Castling{ side, left } => {
 | 
	
		
			
				|  |  | +                match (side, left) {
 | 
	
		
			
				|  |  | +                    (&WHITE, false) => {
 | 
	
		
			
				|  |  | +                        Self::square_to_string(3) + &Self::square_to_string(1)
 | 
	
		
			
				|  |  | +                    },
 | 
	
		
			
				|  |  | +                    (&WHITE, true) => {
 | 
	
		
			
				|  |  | +                        Self::square_to_string(3) + &Self::square_to_string(5)
 | 
	
		
			
				|  |  | +                    },
 | 
	
		
			
				|  |  | +                    (&BLACK, false) => {
 | 
	
		
			
				|  |  | +                        Self::square_to_string(56 + 3) + &Self::square_to_string(56 + 1)
 | 
	
		
			
				|  |  | +                    },
 | 
	
		
			
				|  |  | +                    (&BLACK, true) => {
 | 
	
		
			
				|  |  | +                        Self::square_to_string(56 + 3) + &Self::square_to_string(56 + 5)
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  | +            Move::EnPassant{ mov, beaten } => {
 | 
	
		
			
				|  |  | +                Self::square_to_string(mov.from) + &Self::square_to_string(mov.to)
 | 
	
		
			
				|  |  | +            },
 | 
	
		
			
				|  |  |              Move::Promotion{ mov, promote_to } => {
 | 
	
		
			
				|  |  |                  Self::square_to_string(mov.from) + &Self::square_to_string(mov.to) + 
 | 
	
		
			
				|  |  |                  if *promote_to == QUEEN { "Q" }
 | 
	
	
		
			
				|  | @@ -109,21 +127,42 @@ impl SimpleMove {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub fn generate_moves(game: &Game, side: Side) -> Vec<Move> {
 | 
	
		
			
				|  |  | -    let mut moves: Vec<Move> = Vec::new();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let mut moves: Vec<Move> = Vec::with_capacity(128);
 | 
	
		
			
				|  |  |      generate_pawn_pushes(game, side, &mut moves);
 | 
	
		
			
				|  |  |      generate_pawn_doublepushes(game, side, &mut moves);
 | 
	
		
			
				|  |  |      generate_pawn_captures(game, side, &mut moves);
 | 
	
		
			
				|  |  | -    generate_knight_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | -    generate_bishop_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | -    generate_rook_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | -    generate_queen_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | -    generate_king_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_promotions(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_en_passant(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_knight_moves(game, side, &mut moves, false);
 | 
	
		
			
				|  |  | +    generate_bishop_moves(game, side, &mut moves, false);
 | 
	
		
			
				|  |  | +    generate_rook_moves(game, side, &mut moves, false);
 | 
	
		
			
				|  |  | +    generate_queen_moves(game, side, &mut moves, false);
 | 
	
		
			
				|  |  | +    generate_king_moves(game, side, &mut moves, false);
 | 
	
		
			
				|  |  | +    generate_castling_moves(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    return moves;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +/**
 | 
	
		
			
				|  |  | + * generates moves that could possibly attack a king,
 | 
	
		
			
				|  |  | + * this function is used to check if the king is in check
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +pub fn generate_possattacking_moves(game: &Game, side: Side) -> Vec<Move> {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let mut moves: Vec<Move> = Vec::with_capacity(32);
 | 
	
		
			
				|  |  | +    generate_pawn_captures(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_promotions(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_knight_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_bishop_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_rook_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_queen_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_king_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  |      return moves;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub fn generate_legal_moves(game: &Game, side: Side) -> Vec<Move> {
 | 
	
		
			
				|  |  | -    let mut moves = generate_moves(game, side);
 | 
	
		
			
				|  |  | +    let moves = generate_moves(game, side);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      moves.into_iter().filter(|mov| {
 | 
	
		
			
				|  |  |          let tryout = super::search::apply_move(game, *mov);
 | 
	
	
		
			
				|  | @@ -132,6 +171,32 @@ pub fn generate_legal_moves(game: &Game, side: Side) -> Vec<Move> {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +pub fn generate_attacking_moves(game: &Game, side: Side) -> Vec<Move> {
 | 
	
		
			
				|  |  | +    let mut moves: Vec<Move> = Vec::with_capacity(32);
 | 
	
		
			
				|  |  | +    generate_pawn_captures(game, side, &mut moves);
 | 
	
		
			
				|  |  | +    generate_knight_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_bishop_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_rook_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_queen_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    generate_king_moves(game, side, &mut moves, true);
 | 
	
		
			
				|  |  | +    return moves;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub fn sort_moves(game: &Game, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +    let all_pieces = game.get_all_side(WHITE) | game.get_all_side(BLACK);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    move_list.sort_by_key(|mov| {
 | 
	
		
			
				|  |  | +        match mov {
 | 
	
		
			
				|  |  | +            Move::Default { mov, piece_type } => if (from_square(mov.to) & all_pieces) != 0 { -10 } else { 0 },
 | 
	
		
			
				|  |  | +            Move::Castling { side: _, left: _ } => 0,
 | 
	
		
			
				|  |  | +            Move::Promotion { mov, promote_to } => -5,
 | 
	
		
			
				|  |  | +            Move::EnPassant { mov: _, beaten: _ } => -10,
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |  pub fn generate_pawn_moves(game: &Game, side: Side) -> Bitboard {
 | 
	
		
			
				|  |  |      let pushed = generate_pawn_pushes(game, side);
 | 
	
	
		
			
				|  | @@ -219,7 +284,68 @@ fn generate_pawn_captures(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn generate_knight_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +fn generate_promotions(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +    let pawns = game.pawns(side);
 | 
	
		
			
				|  |  | +    let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  | +    let pieces = game.get_all_side(side);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let moved_pawns =
 | 
	
		
			
				|  |  | +        match side {
 | 
	
		
			
				|  |  | +            WHITE => north_one(pawns),
 | 
	
		
			
				|  |  | +            BLACK => south_one(pawns)
 | 
	
		
			
				|  |  | +        } & (ROW_1 | ROW_8) & !(others | pieces);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let iter = BitboardIterator { board: moved_pawns };
 | 
	
		
			
				|  |  | +    for p in iter {
 | 
	
		
			
				|  |  | +        let origin = match side {
 | 
	
		
			
				|  |  | +            WHITE => south_one(p),
 | 
	
		
			
				|  |  | +            BLACK => north_one(p)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        let movement = SimpleMove { from: square(origin), to: square(p) };
 | 
	
		
			
				|  |  | +        //move_list.push(Move::Default { mov: SimpleMove { from: square(origin), to: square(p) }, piece_type: PAWN });
 | 
	
		
			
				|  |  | +        move_list.push(Move::Promotion { mov: movement, promote_to: QUEEN });
 | 
	
		
			
				|  |  | +        move_list.push(Move::Promotion { mov: movement, promote_to: ROOK });
 | 
	
		
			
				|  |  | +        move_list.push(Move::Promotion { mov: movement, promote_to: BISHOP });
 | 
	
		
			
				|  |  | +        move_list.push(Move::Promotion { mov: movement, promote_to: KNIGHT });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fn generate_en_passant(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +    if let Some(ep) = game.en_passant {
 | 
	
		
			
				|  |  | +        let pawncolumn = A_FILE >> ep;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let pawnrow: Bitboard = match side {
 | 
	
		
			
				|  |  | +            WHITE => ROW_5,
 | 
	
		
			
				|  |  | +            BLACK => ROW_4
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let beaten_pawn = pawncolumn & pawnrow;
 | 
	
		
			
				|  |  | +        if beaten_pawn & game.get_piece(PAWN, !side) == 0 {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let pawn_left = (beaten_pawn << 1) & pawnrow;
 | 
	
		
			
				|  |  | +        let pawn_right = (beaten_pawn >> 1) & pawnrow;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        let attacking_pawns = game.get_piece(PAWN, side);
 | 
	
		
			
				|  |  | +        let target_square = pawncolumn & match side {
 | 
	
		
			
				|  |  | +            WHITE => ROW_6,
 | 
	
		
			
				|  |  | +            BLACK => ROW_3
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if pawn_left & attacking_pawns != 0 {
 | 
	
		
			
				|  |  | +            let mov = Move::EnPassant{ mov: SimpleMove{ from: square(pawn_left), to: square(target_square) }, beaten: square(beaten_pawn) };
 | 
	
		
			
				|  |  | +            move_list.push(mov);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if pawn_right & attacking_pawns != 0 {
 | 
	
		
			
				|  |  | +            let mov = Move::EnPassant{ mov: SimpleMove{ from: square(pawn_right), to: square(target_square) }, beaten: square(beaten_pawn) };
 | 
	
		
			
				|  |  | +            move_list.push(mov);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fn generate_knight_moves(game: &Game, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  |      let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -227,7 +353,12 @@ fn generate_knight_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |      let knight_iter = BitboardIterator{ board: knights };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      for k in knight_iter {
 | 
	
		
			
				|  |  | -        let targets = BitboardIterator { board: get_knight_targets(square(k)) & !friends };
 | 
	
		
			
				|  |  | +        let target_mask = if captures_only {
 | 
	
		
			
				|  |  | +            !friends & others
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            !friends
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        let targets = BitboardIterator { board: get_knight_targets(square(k)) & target_mask };
 | 
	
		
			
				|  |  |          for target in targets {
 | 
	
		
			
				|  |  |              let simple_move = SimpleMove { from: square(k), to: square(target) };
 | 
	
		
			
				|  |  |              move_list.push(Move::Default{ mov: simple_move, piece_type: KNIGHT });
 | 
	
	
		
			
				|  | @@ -235,7 +366,7 @@ fn generate_knight_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn get_knight_targets(square: Square) -> Bitboard {
 | 
	
		
			
				|  |  | +pub fn get_knight_targets(square: Square) -> Bitboard {
 | 
	
		
			
				|  |  |      /// @brief array containing the possible targets for a knight on each square.
 | 
	
		
			
				|  |  |      /// entry at index i is a bitboard with all bits set where a knight on square i can jump
 | 
	
		
			
				|  |  |      const TARGETS: [Bitboard; 64] = [132096, 329728, 659712, 1319424, 2638848, 5277696, 10489856,
 | 
	
	
		
			
				|  | @@ -254,34 +385,36 @@ fn get_knight_targets(square: Square) -> Bitboard {
 | 
	
		
			
				|  |  |      TARGETS[square as usize]
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn generate_bishop_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +fn generate_bishop_moves(game: &Game, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  |      let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    generate_sliding_moves(friends, others, game.bishops(side), BISHOP, false, true, move_list);
 | 
	
		
			
				|  |  | +    generate_sliding_moves(friends, others, game.bishops(side), BISHOP, false, true, move_list, captures_only);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn generate_rook_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +fn generate_rook_moves(game: &Game, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  |      let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    generate_sliding_moves(friends, others, game.rooks(side), ROOK, true, false, move_list);
 | 
	
		
			
				|  |  | +    generate_sliding_moves(friends, others, game.rooks(side), ROOK, true, false, move_list, captures_only);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn generate_queen_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +fn generate_queen_moves(game: &Game, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  |      let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    generate_sliding_moves(friends, others, game.queens(side), QUEEN, true, true, move_list);
 | 
	
		
			
				|  |  | +    generate_sliding_moves(friends, others, game.queens(side), QUEEN, true, true, move_list, captures_only);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  fn generate_sliding_moves(friends: Bitboard, others: Bitboard, pieces: Bitboard, piece_type: PieceType,
 | 
	
		
			
				|  |  | -                          straight: bool, diagonal: bool, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +                          straight: bool, diagonal: bool, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let pieces_iter = BitboardIterator { board: pieces };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    let mask = if captures_only { others } else { !(0 as Bitboard) };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      for piece in pieces_iter {
 | 
	
		
			
				|  |  |          let destinations = generate_sliding_destinations(friends, others, piece, straight, diagonal);
 | 
	
		
			
				|  |  | -        let dest_iter = BitboardIterator { board: destinations };
 | 
	
		
			
				|  |  | +        let dest_iter = BitboardIterator { board: destinations & mask };
 | 
	
		
			
				|  |  |          for dest in dest_iter {
 | 
	
		
			
				|  |  |              let smove = SimpleMove{ from: square(piece), to: square(dest) };
 | 
	
		
			
				|  |  |              move_list.push(Move::Default { mov: smove, piece_type: piece_type});
 | 
	
	
		
			
				|  | @@ -326,7 +459,7 @@ fn generate_direction(piece: Bitboard, direction: fn(Bitboard) -> Bitboard, occu
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -fn generate_king_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +fn generate_king_moves(game: &Game, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
 | 
	
		
			
				|  |  |      let friends = game.get_all_side(side);
 | 
	
		
			
				|  |  |      let others = game.get_all_side(!side);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -336,6 +469,14 @@ fn generate_king_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if king.count_ones() != 1 { return; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    let mask =
 | 
	
		
			
				|  |  | +        if captures_only {
 | 
	
		
			
				|  |  | +            !friends & others
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            !friends
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      let area = (north_one(king)
 | 
	
		
			
				|  |  |                | south_one(king)
 | 
	
		
			
				|  |  |                | east_one(king)
 | 
	
	
		
			
				|  | @@ -344,7 +485,7 @@ fn generate_king_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |                | northwest_one(king)
 | 
	
		
			
				|  |  |                | southwest_one(king)
 | 
	
		
			
				|  |  |                | southeast_one(king))
 | 
	
		
			
				|  |  | -            & !friends;
 | 
	
		
			
				|  |  | +            & mask;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      let area_iter = BitboardIterator { board: area };
 | 
	
		
			
				|  |  |      for destination in area_iter {
 | 
	
	
		
			
				|  | @@ -353,12 +494,57 @@ fn generate_king_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fn generate_castling_moves(game: &Game, side: Side, move_list: &mut Vec<Move>) {
 | 
	
		
			
				|  |  | +    let c1 = Move::Castling{ side: side, left: false };
 | 
	
		
			
				|  |  | +    let c2 = Move::Castling{ side: side, left: true };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let legal_castlings: &[bool] = match side {
 | 
	
		
			
				|  |  | +        WHITE => &game.castling_rights[0..2],
 | 
	
		
			
				|  |  | +        BLACK => &game.castling_rights[2..4],
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let all_pieces = game.get_all_side(WHITE) | game.get_all_side(BLACK);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // kingside castling
 | 
	
		
			
				|  |  | +    if legal_castlings[0] {
 | 
	
		
			
				|  |  | +        //info!("possible castling? {} {} {}", game.get_piece(KING, side), game.get_piece(ROOK, side), ((game.get_piece(KING, side) >> 3) & game.get_piece(ROOK, side)));
 | 
	
		
			
				|  |  | +        if ((game.get_piece(KING, side) >> 3) & game.get_piece(ROOK, side)) != 0 &&
 | 
	
		
			
				|  |  | +            ((game.get_piece(KING, side) >> 1) | (game.get_piece(KING, side) >> 2)) & all_pieces == 0 {
 | 
	
		
			
				|  |  | +                let mut tg1 = game.clone();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                *tg1.get_piece_mut(KING, side) = game.get_piece(KING, side) >> 1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if !is_check(game, side) && !is_check(&tg1, side) {
 | 
	
		
			
				|  |  | +                    move_list.push(c1);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    // queenside
 | 
	
		
			
				|  |  | +    if legal_castlings[1] {
 | 
	
		
			
				|  |  | +        //info!("possible castling? {} {} {}", game.get_piece(KING, side), game.get_piece(ROOK, side), ((game.get_piece(KING, side) >> 3) & game.get_piece(ROOK, side)));
 | 
	
		
			
				|  |  | +        if ((game.get_piece(KING, side) << 4) & game.get_piece(ROOK, side)) != 0 &&
 | 
	
		
			
				|  |  | +            ((game.get_piece(KING, side) << 1) | (game.get_piece(KING, side) << 2) | (game.get_piece(KING, side) << 3)) & all_pieces == 0 {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                let mut tg1 = game.clone();
 | 
	
		
			
				|  |  | +                let mut tg2 = game.clone();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                *tg1.get_piece_mut(KING, side) = game.get_piece(KING, side) << 1;
 | 
	
		
			
				|  |  | +                *tg2.get_piece_mut(KING, side) = game.get_piece(KING, side) << 2;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if !is_check(game, side) && !is_check(&tg1, side) && !is_check(&tg2, side) {
 | 
	
		
			
				|  |  | +                    move_list.push(c2);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /**
 | 
	
		
			
				|  |  |   * checks if side's king is in check
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  pub fn is_check(game: &Game, side: Side) -> bool {
 | 
	
		
			
				|  |  |      let king_square = square(game.get_piece(KING, side));
 | 
	
		
			
				|  |  | -    let possible_attacks = generate_moves(game, !side);
 | 
	
		
			
				|  |  | +    let possible_attacks = generate_possattacking_moves(game, !side);
 | 
	
		
			
				|  |  |      for mov in possible_attacks {
 | 
	
		
			
				|  |  |          if let Move::Default{ mov, piece_type: _ } = mov {
 | 
	
		
			
				|  |  |              if mov.to == king_square {
 |