Kaynağa Gözat

improve legality checks even further

Nicolas Winkler 2 yıl önce
ebeveyn
işleme
4ccc2daf58
1 değiştirilmiş dosya ile 42 ekleme ve 23 silme
  1. 42 23
      src/movegen.rs

+ 42 - 23
src/movegen.rs

@@ -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;
+                                }
+                            }
+                        }
+                    }
                 },
                 _ => {}
             }