|
@@ -310,34 +310,39 @@ pub fn generate_legal_moves_old(game: &mut Game, side: Side) -> Vec<Move> {
|
|
|
moves.into_iter().filter(check_legality).collect::<Vec<Move>>()
|
|
|
}
|
|
|
|
|
|
-fn possibly_pinned_pieces(king: Bitboard, friends: Bitboard, enemies: Bitboard) -> Bitboard {
|
|
|
- let check_ray = |ray_func: fn(Bitboard) -> Bitboard| -> Bitboard {
|
|
|
+fn possibly_pinned_pieces(king: Bitboard, friends: Bitboard, diag_enemies: Bitboard, straight_enemies: Bitboard, all_enemies: Bitboard) -> [Bitboard; 8] {
|
|
|
+ let check_ray = |ray_func: fn(Bitboard) -> Bitboard, diagonal: bool| -> Bitboard {
|
|
|
let mut pos = king;
|
|
|
- let mut ray = king;
|
|
|
+ let mut ray = 0;
|
|
|
let mut one_friend = false;
|
|
|
+
|
|
|
+ let enemies = if diagonal { diag_enemies } else { straight_enemies };
|
|
|
+ let blockers = friends | all_enemies;
|
|
|
+
|
|
|
for _ in 0..7 {
|
|
|
pos = ray_func(pos);
|
|
|
+ ray |= pos;
|
|
|
if pos & friends != 0 && !one_friend {
|
|
|
one_friend = true;
|
|
|
- } else if pos & friends != 0 && one_friend {
|
|
|
- return 0;
|
|
|
} else if pos & enemies != 0 && one_friend {
|
|
|
return ray;
|
|
|
+ } else if pos & blockers != 0 && !one_friend {
|
|
|
+ return 0;
|
|
|
+ } else if pos & blockers != 0 && one_friend {
|
|
|
+ return 0;
|
|
|
}
|
|
|
- ray |= pos;
|
|
|
}
|
|
|
return 0;
|
|
|
};
|
|
|
|
|
|
- return
|
|
|
- check_ray(north_one)
|
|
|
- | check_ray(south_one)
|
|
|
- | check_ray(east_one)
|
|
|
- | check_ray(west_one)
|
|
|
- | check_ray(northeast_one)
|
|
|
- | check_ray(northwest_one)
|
|
|
- | check_ray(southeast_one)
|
|
|
- | check_ray(southwest_one);
|
|
|
+ return [check_ray(north_one, false),
|
|
|
+ check_ray(south_one, false),
|
|
|
+ check_ray(east_one, false),
|
|
|
+ check_ray(west_one, false),
|
|
|
+ check_ray(northeast_one, true),
|
|
|
+ check_ray(northwest_one, true),
|
|
|
+ check_ray(southeast_one, true),
|
|
|
+ check_ray(southwest_one, true)];
|
|
|
}
|
|
|
|
|
|
|
|
@@ -351,21 +356,35 @@ pub fn generate_legal_moves(game: &mut Game, side: Side, captures_only: bool) ->
|
|
|
|
|
|
let check = is_check(game, side);
|
|
|
let king = game.kings(side);
|
|
|
- let possible_pins = possibly_pinned_pieces(king, game.get_all_side(side), game.get_all_side(!side));
|
|
|
+
|
|
|
+ let straight_enemies = game.queens(!side) | game.rooks(!side);
|
|
|
+ let diag_enemies = game.queens(!side) | game.bishops(!side);
|
|
|
+
|
|
|
+ let pin_rays = possibly_pinned_pieces(king, game.get_all_side(side), diag_enemies, straight_enemies, game.get_all_side(!side));
|
|
|
+ let possible_pins = king | pin_rays.iter().fold(0, |a, b| a | b);
|
|
|
|
|
|
let check_legality = |m: &Move| {
|
|
|
if !check {
|
|
|
match m {
|
|
|
- Move::Default { mov, piece_type, captured: _ } => {
|
|
|
- // check whether piece is not pinned and is not a king
|
|
|
- if from_square(mov.from) & possible_pins == 0 && *piece_type != KING {
|
|
|
- return true;
|
|
|
- }
|
|
|
- },
|
|
|
+ Move::Default { mov, piece_type: _, captured: _ } |
|
|
|
Move::Promotion { mov, promote_to: _, captured: _ } => {
|
|
|
- if from_square(mov.from) & possible_pins == 0 {
|
|
|
+ let from = from_square(mov.from);
|
|
|
+ if from & possible_pins == 0 && from != king {
|
|
|
return true;
|
|
|
}
|
|
|
+ else {
|
|
|
+ let to = from_square(mov.to);
|
|
|
+ for pin_ray in pin_rays {
|
|
|
+ if from & pin_ray != 0 {
|
|
|
+ if to & pin_ray != 0 {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
_ => {}
|
|
|
}
|