|
@@ -8,6 +8,7 @@ use std::iter::Iterator;
|
|
use std::sync::Arc;
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
use std::sync::Mutex;
|
|
|
|
|
|
|
|
+use crate::bitboard;
|
|
use crate::magic::magic_bishop;
|
|
use crate::magic::magic_bishop;
|
|
use crate::search::CountermoveTable;
|
|
use crate::search::CountermoveTable;
|
|
use crate::ttable::CacheEntry;
|
|
use crate::ttable::CacheEntry;
|
|
@@ -293,7 +294,7 @@ impl MoveGenerator {
|
|
pub fn generate_legal_moves(game: &mut Board, ce: Option<&CacheEntry>, killers: &[Move], last_move: Option<Move>, counters_table: Arc<Mutex<CountermoveTable>>, side: Side) -> Self {
|
|
pub fn generate_legal_moves(game: &mut Board, ce: Option<&CacheEntry>, killers: &[Move], last_move: Option<Move>, counters_table: Arc<Mutex<CountermoveTable>>, side: Side) -> Self {
|
|
MoveGenerator {
|
|
MoveGenerator {
|
|
board: game.clone(),
|
|
board: game.clone(),
|
|
- moves: generate_legal_moves(game, side, false),
|
|
|
|
|
|
+ moves: generate_legal_moves_new(game, side, false),
|
|
side,
|
|
side,
|
|
captures: Vec::with_capacity(32),
|
|
captures: Vec::with_capacity(32),
|
|
counters: Vec::with_capacity(32),
|
|
counters: Vec::with_capacity(32),
|
|
@@ -542,6 +543,369 @@ fn pinned_rays(king: Bitboard, friends: Bitboard, diag_enemies: Bitboard, straig
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+pub fn generate_legal_moves_new(board: &mut Board, side: Side, captures_only: bool) -> Vec<Move> {
|
|
|
|
+ let king = board.kings(side);
|
|
|
|
+ let king_square = square(king);
|
|
|
|
+
|
|
|
|
+ let friends = board.get_all_side(side);
|
|
|
|
+ let opponents = board.get_all_side(!side);
|
|
|
|
+
|
|
|
|
+ if king == 0 {
|
|
|
|
+ return Vec::new();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let all_pieces = friends | opponents;
|
|
|
|
+
|
|
|
|
+ let king_knights = get_knight_targets(king_square);
|
|
|
|
+ let king_bishops = crate::magic::magic_bishop(king_square, all_pieces);
|
|
|
|
+ let king_rooks = crate::magic::magic_rook(king_square, all_pieces);
|
|
|
|
+
|
|
|
|
+ let king_pawns =
|
|
|
|
+ if side == BLACK { southeast_one(king) | southwest_one(king) }
|
|
|
|
+ else { northeast_one(king) | northwest_one(king) };
|
|
|
|
+
|
|
|
|
+ let king_kings = get_king_targets(king);
|
|
|
|
+
|
|
|
|
+ let check_doers =
|
|
|
|
+ (king_knights & board.knights(!side))
|
|
|
|
+ | (king_bishops & (board.bishops(!side) | board.queens(!side)))
|
|
|
|
+ | (king_rooks & (board.rooks(!side) | board.queens(!side)))
|
|
|
|
+ | (king_pawns & board.pawns(!side))
|
|
|
|
+ | (king_kings & board.kings(!side));
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if check_doers != 0 {
|
|
|
|
+ return generate_legal_moves(board, side, captures_only);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*let check_mask =
|
|
|
|
+ if check_doers.count_ones() == 0 {
|
|
|
|
+ !0u64
|
|
|
|
+ }
|
|
|
|
+ else if check_doers.count_ones() == 1 {
|
|
|
|
+ return generate_legal_moves(board, side, captures_only);
|
|
|
|
+ } else {
|
|
|
|
+ return generate_legal_moves(board, side, captures_only);
|
|
|
|
+ };*/
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let king_diag_all = crate::magic::magic_bishop(king_square, all_pieces);
|
|
|
|
+ let king_straight_all = crate::magic::magic_rook(king_square, all_pieces);
|
|
|
|
+
|
|
|
|
+ let diag_pin_mask = crate::magic::magic_bishop(king_square, opponents);
|
|
|
|
+ let straight_pin_mask = crate::magic::magic_rook(king_square, opponents);
|
|
|
|
+
|
|
|
|
+ let mut diag_attack: Bitboard = 0;
|
|
|
|
+ let mut straight_attack: Bitboard = 0;
|
|
|
|
+
|
|
|
|
+ for dg in BitboardIterator((board.queens(!side) | board.bishops(!side)) & diag_pin_mask) {
|
|
|
|
+ diag_attack |= crate::magic::magic_bishop(square(dg), all_pieces) | dg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for sg in BitboardIterator((board.queens(!side) | board.rooks(!side)) & straight_pin_mask) {
|
|
|
|
+ straight_attack |= crate::magic::magic_rook(square(sg), all_pieces) | sg;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let diag_pinned_pieces = diag_attack & king_diag_all;
|
|
|
|
+ let straight_pinned_pieces = straight_attack & king_straight_all;
|
|
|
|
+ let all_pinned_pieces = diag_pinned_pieces | straight_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ //let diag_pins = crate::magic::magic_bishop(king_square, all_pieces & !king_diagonals);
|
|
|
|
+ //let straight_pins = crate::magic::magic_rook(king_square, all_pieces & !king_straights);
|
|
|
|
+ // let straight_pins = 0u64;//crate::magic::magic_rook(king_square, all_pieces & !king_straights);
|
|
|
|
+
|
|
|
|
+ /*println!("{}", board.beautiful_print());
|
|
|
|
+ println!("diag_pins:\n{}", bitboard::print_board(diag_pins));
|
|
|
|
+ println!("straight_pins:\n{}", bitboard::print_board(straight_pins));*/
|
|
|
|
+
|
|
|
|
+ let pawns = board.pawns(side);
|
|
|
|
+ let knights = board.knights(side);
|
|
|
|
+ let bishops = board.bishops(side);
|
|
|
|
+ let rooks = board.rooks(side);
|
|
|
|
+ let queens = board.queens(side);
|
|
|
|
+
|
|
|
|
+ let pawns_straight_pinned = pawns & straight_pinned_pieces;
|
|
|
|
+ let pawns_diag_pinned = pawns & diag_pinned_pieces;
|
|
|
|
+ let pawns_unpinned = pawns & !all_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ let _knights_pinned= knights & all_pinned_pieces; // pinned knights can never move
|
|
|
|
+ let knights_unpinned = knights & !all_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ let bishops_pinned = bishops & diag_pinned_pieces;
|
|
|
|
+ let bishops_unpinned = bishops & !all_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ let rooks_pinned = rooks & straight_pinned_pieces;
|
|
|
|
+ let rooks_unpinned = rooks & !all_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ let queens_diag_pinned = queens & diag_pinned_pieces;
|
|
|
|
+ let queens_straight_pinned = queens & straight_pinned_pieces;
|
|
|
|
+ let queens_unpinned = queens & !all_pinned_pieces;
|
|
|
|
+
|
|
|
|
+ let mut moves: Vec<Move>= Vec::with_capacity(64);
|
|
|
|
+ let mut testmoves = Vec::<Move>::with_capacity(64);
|
|
|
|
+
|
|
|
|
+ let promotion_mask = ROW_1 | ROW_8;
|
|
|
|
+ for pawn in BitboardIterator(pawns_diag_pinned | pawns_unpinned) {
|
|
|
|
+ let psquare = square(pawn);
|
|
|
|
+ let pc1 = if side == WHITE { northeast_one(pawn) } else { southeast_one(pawn) };
|
|
|
|
+ let pc2 = if side == WHITE { northwest_one(pawn) } else { southwest_one(pawn) };
|
|
|
|
+ for cap in [pc1, pc2] {
|
|
|
|
+ if pawn & pawns_diag_pinned != 0 {
|
|
|
|
+ if cap & diag_pin_mask == 0 {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ let capture = cap & opponents;
|
|
|
|
+ if capture != 0 {
|
|
|
|
+ if capture & promotion_mask != 0 {
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(capture) } , pc: PieceCaptureType::new(QUEEN, board.find_piece(capture)) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(capture) } , pc: PieceCaptureType::new(ROOK, board.find_piece(capture)) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(capture) } , pc: PieceCaptureType::new(BISHOP, board.find_piece(capture)) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(capture) } , pc: PieceCaptureType::new(KNIGHT, board.find_piece(capture)) });
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: psquare, to: square(capture) } , pc: PieceCaptureType::new(PAWN, board.find_piece(capture)) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let pushed_pawns = if side == WHITE { north_one(pawns_unpinned) } else { south_one(pawns_unpinned) } & !all_pieces;
|
|
|
|
+ for pawn in BitboardIterator(pushed_pawns) {
|
|
|
|
+ let tsquare = square(pawn);
|
|
|
|
+ let origin = if side == BLACK { north_one(pawn) } else { south_one(pawn) };
|
|
|
|
+ let psquare = square(origin);
|
|
|
|
+
|
|
|
|
+ if pawn & promotion_mask != 0 {
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: tsquare }, pc: PieceCaptureType::new(QUEEN, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: tsquare }, pc: PieceCaptureType::new(ROOK, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: tsquare }, pc: PieceCaptureType::new(BISHOP, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: tsquare }, pc: PieceCaptureType::new(KNIGHT, None) });
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: psquare, to: tsquare }, pc: PieceCaptureType::new(PAWN, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for pawn in BitboardIterator(pawns_straight_pinned) {
|
|
|
|
+ let psquare = square(pawn);
|
|
|
|
+ let pushed_pawn = if side == WHITE { north_one(pawn) } else { south_one(pawn) };
|
|
|
|
+ if pushed_pawn & straight_pin_mask == 0 {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ if pushed_pawn & all_pieces == 0 {
|
|
|
|
+ if pushed_pawn & promotion_mask != 0 {
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(pushed_pawn) }, pc: PieceCaptureType::new(QUEEN, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(pushed_pawn) }, pc: PieceCaptureType::new(ROOK, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(pushed_pawn) }, pc: PieceCaptureType::new(BISHOP, None) });
|
|
|
|
+ moves.push(Move::Promotion { mov: SimpleMove { from: psquare, to: square(pushed_pawn) }, pc: PieceCaptureType::new(KNIGHT, None) });
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: psquare, to: square(pushed_pawn) }, pc: PieceCaptureType::new(PAWN, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let double_push_row = if side == WHITE { ROW_2 } else { ROW_7 };
|
|
|
|
+ let double_pushables = (pawns_straight_pinned | pawns_unpinned) & double_push_row;
|
|
|
|
+ let dpushed_pawns = if side == WHITE { north_one(north_one(double_pushables) & !all_pieces) } else { south_one(south_one(double_pushables) & !all_pieces) } & !all_pieces;
|
|
|
|
+ for pawn in BitboardIterator(dpushed_pawns) {
|
|
|
|
+ let psquare = square(pawn);
|
|
|
|
+ let origin = if side == BLACK { north_one(north_one(pawn)) } else { south_one(south_one(pawn)) };
|
|
|
|
+
|
|
|
|
+ if (origin & straight_pinned_pieces != 0) && (pawn & straight_pin_mask == 0) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: square(origin), to: psquare }, pc: PieceCaptureType::new(PAWN, None) });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*for pawn in BitboardIterator(pawns_diag_pinned & !promote_row) {
|
|
|
|
+ let psquare = square(pawn);
|
|
|
|
+ let pc1 = if side == WHITE { northeast_one(pawn) } else { southeast_one(pawn) };
|
|
|
|
+ let pc2 = if side == WHITE { northwest_one(pawn) } else { southwest_one(pawn) };
|
|
|
|
+ if pc1 & diag_pins & opponents != 0 {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: psquare, to: square(pc1) } , pc: PieceCaptureType::new(PAWN, board.find_piece(pc1)) });
|
|
|
|
+ }
|
|
|
|
+ if pc2 & diag_pins & opponents != 0 {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: psquare, to: square(pc2) } , pc: PieceCaptureType::new(PAWN, board.find_piece(pc2)) });
|
|
|
|
+ }
|
|
|
|
+ }*/
|
|
|
|
+
|
|
|
|
+ generate_knight_moves_new(board, friends, opponents, knights_unpinned, &mut moves, captures_only);
|
|
|
|
+
|
|
|
|
+ for bishop in BitboardIterator(bishops_pinned) {
|
|
|
|
+ let bsq = square(bishop);
|
|
|
|
+ let pt = crate::magic::magic_bishop(bsq, all_pieces) & !friends & diag_pin_mask;
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: bsq, to: square(target) } , pc: PieceCaptureType::new(BISHOP, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: bsq, to: square(target) } , pc: PieceCaptureType::new(BISHOP, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for bishop in BitboardIterator(bishops_unpinned) {
|
|
|
|
+ let bsq = square(bishop);
|
|
|
|
+ let pt = crate::magic::magic_bishop(bsq, all_pieces) & !friends;
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: bsq, to: square(target) } , pc: PieceCaptureType::new(BISHOP, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: bsq, to: square(target) } , pc: PieceCaptureType::new(BISHOP, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for rook in BitboardIterator(rooks_pinned | rooks_unpinned) {
|
|
|
|
+ let rsq = square(rook);
|
|
|
|
+ let pt = crate::magic::magic_rook(rsq, all_pieces) & !friends &
|
|
|
|
+ if rook & rooks_pinned != 0 {
|
|
|
|
+ straight_pin_mask
|
|
|
|
+ } else {
|
|
|
|
+ !0u64
|
|
|
|
+ };
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: rsq, to: square(target) } , pc: PieceCaptureType::new(ROOK, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: rsq, to: square(target) } , pc: PieceCaptureType::new(ROOK, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for dqueen in BitboardIterator(queens_diag_pinned) {
|
|
|
|
+ let qsq = square(dqueen);
|
|
|
|
+ let pt = crate::magic::magic_bishop(qsq, all_pieces) & !friends & diag_pin_mask;
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for squeen in BitboardIterator(queens_straight_pinned) {
|
|
|
|
+ let qsq = square(squeen);
|
|
|
|
+ let pt = crate::magic::magic_rook(qsq, all_pieces) & !friends & straight_pin_mask;
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ for queen in BitboardIterator(queens_unpinned) {
|
|
|
|
+ let qsq = square(queen);
|
|
|
|
+ let pt = (crate::magic::magic_rook(qsq, all_pieces) |
|
|
|
|
+ crate::magic::magic_bishop(qsq, all_pieces)) & !friends;
|
|
|
|
+ for target in BitboardIterator(pt & opponents) {
|
|
|
|
+ let mov = Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, board.find_piece(target)) };
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, board.find_piece(target)) });
|
|
|
|
+ }
|
|
|
|
+ for target in BitboardIterator(pt & !opponents) {
|
|
|
|
+ moves.push(Move::Default { mov: SimpleMove { from: qsq, to: square(target) } , pc: PieceCaptureType::new(QUEEN, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*if pawns_straight_pinned != 0 {
|
|
|
|
+ println!("{}", board.beautiful_print());
|
|
|
|
+ println!("{}", print_board(pawns_straight_pinned));
|
|
|
|
+ println!("{}", print_board(straight_pin_mask));
|
|
|
|
+ println!("{}", print_board(straight_pinned_pieces));
|
|
|
|
+ println!("{}", print_board(straight_attack));
|
|
|
|
+ panic!("asfsadf");
|
|
|
|
+ }*/
|
|
|
|
+
|
|
|
|
+ //generate_pawn_pushes(board, side, &mut testmoves);
|
|
|
|
+ //generate_pawn_doublepushes(board, side, &mut testmoves);
|
|
|
|
+ //generate_pawn_captures(board, side, &mut testmoves);
|
|
|
|
+
|
|
|
|
+ generate_en_passant(board, side, &mut testmoves);
|
|
|
|
+
|
|
|
|
+ //generate_promotions(board, side, &mut moves);
|
|
|
|
+ /*generate_knight_moves(board, side, &mut testmoves, false);
|
|
|
|
+ generate_bishop_moves(board, side, &mut testmoves, false);
|
|
|
|
+ generate_rook_moves(board, side, &mut testmoves, false);
|
|
|
|
+ generate_queen_moves(board, side, &mut testmoves, false);*/
|
|
|
|
+ generate_king_moves(board, side, &mut testmoves, false);
|
|
|
|
+ generate_castling_moves(board, side, &mut testmoves);
|
|
|
|
+
|
|
|
|
+ let mut is_legal = |m: &Move| {
|
|
|
|
+ let undo = board.apply(*m);
|
|
|
|
+ let legal = !is_check(board, side);
|
|
|
|
+ board.undo_move(undo);
|
|
|
|
+ return legal;
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ /*for m in &moves {
|
|
|
|
+ if !is_legal(m) {
|
|
|
|
+ println!("{}", board.beautiful_print());
|
|
|
|
+ println!("{}", m.to_string());
|
|
|
|
+ println!("{}", print_board(pawns_straight_pinned));
|
|
|
|
+ println!("{}", print_board(straight_pin_mask));
|
|
|
|
+ panic!("asfsadf");
|
|
|
|
+ }
|
|
|
|
+ }*/
|
|
|
|
+ testmoves.retain(is_legal);
|
|
|
|
+ moves.append(&mut testmoves);
|
|
|
|
+
|
|
|
|
+ moves
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+fn generate_knight_moves_new(board: &Board,
|
|
|
|
+ friends: Bitboard,
|
|
|
|
+ others: Bitboard,
|
|
|
|
+ knights: Bitboard, move_list: &mut Vec<Move>, captures_only: bool) {
|
|
|
|
+
|
|
|
|
+ for k in BitboardIterator(knights) {
|
|
|
|
+ let cap_targets = BitboardIterator(get_knight_targets(square(k)) & (!friends & others));
|
|
|
|
+ let nocap_targets = BitboardIterator(get_knight_targets(square(k)) & (!friends & !others));
|
|
|
|
+
|
|
|
|
+ for target in cap_targets {
|
|
|
|
+ let simple_move = SimpleMove { from: square(k), to: square(target) };
|
|
|
|
+ let captured = board.find_piece(target);
|
|
|
|
+ move_list.push(Move::Default{ mov: simple_move, pc: PieceCaptureType::new(KNIGHT, captured) });
|
|
|
|
+ }
|
|
|
|
+ if !captures_only {
|
|
|
|
+ for target in nocap_targets {
|
|
|
|
+ let simple_move = SimpleMove { from: square(k), to: square(target) };
|
|
|
|
+ move_list.push(Move::Default{ mov: simple_move, pc: PieceCaptureType::new(KNIGHT, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+fn generate_moves_single_piece(board: &Board,
|
|
|
|
+ friends: Bitboard,
|
|
|
|
+ others: Bitboard,
|
|
|
|
+ pin_mask: Bitboard,
|
|
|
|
+ piece_type: PieceType,
|
|
|
|
+ piece: Bitboard,
|
|
|
|
+ targets: Bitboard,
|
|
|
|
+ move_list: &mut Vec<Move>, captures_only: bool) {
|
|
|
|
+
|
|
|
|
+ let cap_targets = BitboardIterator(targets & (!friends & others));
|
|
|
|
+ let nocap_targets = BitboardIterator(targets & (!friends & !others));
|
|
|
|
+
|
|
|
|
+ let psquare = square(piece);
|
|
|
|
+
|
|
|
|
+ for target in cap_targets {
|
|
|
|
+ let simple_move = SimpleMove { from: psquare, to: square(target) };
|
|
|
|
+ let captured = board.find_piece(target);
|
|
|
|
+ move_list.push(Move::Default{ mov: simple_move, pc: PieceCaptureType::new(piece_type, captured) });
|
|
|
|
+ }
|
|
|
|
+ if !captures_only {
|
|
|
|
+ for target in nocap_targets {
|
|
|
|
+ let simple_move = SimpleMove { from: psquare, to: square(target) };
|
|
|
|
+ move_list.push(Move::Default{ mov: simple_move, pc: PieceCaptureType::new(piece_type, None) });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
pub fn generate_legal_moves(game: &mut Board, side: Side, captures_only: bool) -> Vec<Move> {
|
|
pub fn generate_legal_moves(game: &mut Board, side: Side, captures_only: bool) -> Vec<Move> {
|
|
let moves =
|
|
let moves =
|
|
if captures_only {
|
|
if captures_only {
|
|
@@ -1050,6 +1414,12 @@ pub fn get_knight_targets(square: Square) -> Bitboard {
|
|
TARGETS[square as usize]
|
|
TARGETS[square as usize]
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+pub fn get_king_targets(king: Bitboard) -> Bitboard {
|
|
|
|
+ let row = king | east_one(king) | west_one(king);
|
|
|
|
+
|
|
|
|
+ row | north_one(row) | south_one(row)
|
|
|
|
+}
|
|
|
|
+
|
|
fn generate_bishop_moves(game: &Board, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
|
|
fn generate_bishop_moves(game: &Board, side: Side, move_list: &mut Vec<Move>, captures_only: bool) {
|
|
let friends = game.get_all_side(side);
|
|
let friends = game.get_all_side(side);
|
|
let others = game.get_all_side(!side);
|
|
let others = game.get_all_side(!side);
|