Spaces:
Runtime error
Runtime error
| use crate::types::*; | |
| use crate::bitboard::{Bitboard, EMPTY, pop_lsb}; | |
| use crate::position::Position; | |
| pub fn knight_mask(sq: Square) -> Bitboard { | |
| let b: Bitboard = 1 << (sq as u8); | |
| let mut mask = EMPTY; | |
| mask |= (b << 17) & !crate::bitboard::FILE_A; | |
| mask |= (b << 10) & !(crate::bitboard::FILE_A | 0x0202020202020202); | |
| mask |= (b >> 6) & !(crate::bitboard::FILE_A | 0x0202020202020202); | |
| mask |= (b >> 15) & !crate::bitboard::FILE_A; | |
| mask |= (b << 15) & !crate::bitboard::FILE_H; | |
| mask |= (b << 6) & !(crate::bitboard::FILE_H | 0x4040404040404040); | |
| mask |= (b >> 10) & !(crate::bitboard::FILE_H | 0x4040404040404040); | |
| mask |= (b >> 17) & !crate::bitboard::FILE_H; | |
| mask | |
| } | |
| pub fn king_mask(sq: Square) -> Bitboard { | |
| let b: Bitboard = 1 << (sq as u8); | |
| let mut mask = EMPTY; | |
| mask |= (b << 8) | (b >> 8); | |
| mask |= (b << 1) & !crate::bitboard::FILE_A; | |
| mask |= (b >> 7) & !crate::bitboard::FILE_A; | |
| mask |= (b << 9) & !crate::bitboard::FILE_A; | |
| mask |= (b >> 1) & !crate::bitboard::FILE_H; | |
| mask |= (b >> 9) & !crate::bitboard::FILE_H; | |
| mask |= (b << 7) & !crate::bitboard::FILE_H; | |
| mask | |
| } | |
| pub fn pawn_attack_mask(sq: Square, side: Color) -> Bitboard { | |
| let b: Bitboard = 1 << (sq as u8); | |
| let mut mask = EMPTY; | |
| if side == Color::White { | |
| mask |= (b << 7) & !crate::bitboard::FILE_H; | |
| mask |= (b << 9) & !crate::bitboard::FILE_A; | |
| } else { | |
| mask |= (b >> 9) & !crate::bitboard::FILE_H; | |
| mask |= (b >> 7) & !crate::bitboard::FILE_A; | |
| } | |
| mask | |
| } | |
| pub fn sliding_attacks(sq: Square, occ: Bitboard, diagonal: bool) -> Bitboard { | |
| let mut attacks = EMPTY; | |
| let r = (sq as u8) / 8; | |
| let f = (sq as u8) % 8; | |
| let dirs: &[(i8, i8)] = if diagonal { | |
| &[(1, 1), (1, -1), (-1, 1), (-1, -1)] | |
| } else { | |
| &[(1, 0), (-1, 0), (0, 1), (0, -1)] | |
| }; | |
| for &(dr, df) in dirs { | |
| let mut nr = r as i8 + dr; | |
| let mut nf = f as i8 + df; | |
| while nr >= 0 && nr < 8 && nf >= 0 && nf < 8 { | |
| let n_sq = nr * 8 + nf; | |
| attacks |= 1 << n_sq; | |
| if (occ & (1 << n_sq)) != 0 { | |
| break; | |
| } | |
| nr += dr; | |
| nf += df; | |
| } | |
| } | |
| attacks | |
| } | |
| pub fn generate_moves(pos: &Position, list: &mut Vec<Move>) { | |
| let us = pos.side_to_move; | |
| let occ = pos.colors[0] | pos.colors[1]; | |
| let target = !pos.colors[us as usize]; | |
| let mut knights = pos.pieces[PieceType::Knight as usize] & pos.colors[us as usize]; | |
| while knights != EMPTY { | |
| let from_sq = pop_lsb(&mut knights); | |
| let mut attacks = knight_mask(Square::from_u8(from_sq)) & target; | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| let mut king = pos.pieces[PieceType::King as usize] & pos.colors[us as usize]; | |
| if king != EMPTY { | |
| let from_sq = pop_lsb(&mut king); | |
| let mut attacks = king_mask(Square::from_u8(from_sq)) & target; | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| let mut sliders = (pos.pieces[PieceType::Bishop as usize] | pos.pieces[PieceType::Queen as usize]) & pos.colors[us as usize]; | |
| while sliders != EMPTY { | |
| let from_sq = pop_lsb(&mut sliders); | |
| let mut attacks = sliding_attacks(Square::from_u8(from_sq), occ, true) & target; | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| let mut straights = (pos.pieces[PieceType::Rook as usize] | pos.pieces[PieceType::Queen as usize]) & pos.colors[us as usize]; | |
| while straights != EMPTY { | |
| let from_sq = pop_lsb(&mut straights); | |
| let mut attacks = sliding_attacks(Square::from_u8(from_sq), occ, false) & target; | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| let mut pawns = pos.pieces[PieceType::Pawn as usize] & pos.colors[us as usize]; | |
| while pawns != EMPTY { | |
| let from_sq = pop_lsb(&mut pawns); | |
| let f_rank = from_sq / 8; | |
| if us == Color::White { | |
| let single_push = from_sq + 8; | |
| if (occ & (1 << single_push)) == 0 { | |
| if f_rank == 6 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Queen)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Rook)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Bishop)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Knight)); | |
| } else { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::None)); | |
| let double_push = from_sq + 16; | |
| if f_rank == 1 && (occ & (1 << double_push)) == 0 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(double_push), PieceType::None)); | |
| } | |
| } | |
| } | |
| let mut attacks = pawn_attack_mask(Square::from_u8(from_sq), Color::White) & pos.colors[Color::Black as usize]; | |
| if pos.ep_square != Square::None && (pawn_attack_mask(Square::from_u8(from_sq), Color::White) & (1 << (pos.ep_square as u8))) != 0 { | |
| attacks |= 1 << (pos.ep_square as u8); | |
| } | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| if f_rank == 6 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::Queen)); | |
| } else { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| } else { | |
| let single_push = from_sq - 8; | |
| if (occ & (1 << single_push)) == 0 { | |
| if f_rank == 1 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Queen)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Rook)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Bishop)); | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::Knight)); | |
| } else { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(single_push), PieceType::None)); | |
| let double_push = from_sq - 16; | |
| if f_rank == 6 && (occ & (1 << double_push)) == 0 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(double_push), PieceType::None)); | |
| } | |
| } | |
| } | |
| let mut attacks = pawn_attack_mask(Square::from_u8(from_sq), Color::Black) & pos.colors[Color::White as usize]; | |
| if pos.ep_square != Square::None && (pawn_attack_mask(Square::from_u8(from_sq), Color::Black) & (1 << (pos.ep_square as u8))) != 0 { | |
| attacks |= 1 << (pos.ep_square as u8); | |
| } | |
| while attacks != EMPTY { | |
| let to_sq = pop_lsb(&mut attacks); | |
| if f_rank == 1 { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::Queen)); | |
| } else { | |
| list.push(Move::new(Square::from_u8(from_sq), Square::from_u8(to_sq), PieceType::None)); | |
| } | |
| } | |
| } | |
| } | |
| } | |