VeloCT_Base / src /movegen.rs
Taperx's picture
Deploy Base model with clean official lichess-bot folder
3014f14
Raw
History Blame Contribute Delete
8.08 kB
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));
}
}
}
}
}