Consider duple check in is_check
authorFabian Fichter <ianfab@users.noreply.github.com>
Fri, 31 Mar 2023 22:09:24 +0000 (00:09 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Fri, 31 Mar 2023 22:09:24 +0000 (00:09 +0200)
src/position.cpp
test.py

index 3c1ff5d..d9e798f 100644 (file)
@@ -985,17 +985,37 @@ Bitboard Position::attackers_to(Square s, Bitboard occupied) const {
 /// Position::attackers_to_pseudo_royals computes a bitboard of all pieces
 /// of a particular color attacking at least one opposing pseudo-royal piece
 Bitboard Position::attackers_to_pseudo_royals(Color c) const {
+  assert(extinction_pseudo_royal());
   Bitboard attackers = 0;
   Bitboard pseudoRoyals = st->pseudoRoyals & pieces(~c);
   Bitboard pseudoRoyalsTheirs = st->pseudoRoyals & pieces(c);
-  while (pseudoRoyals) {
+  while (pseudoRoyals)
+  {
       Square sr = pop_lsb(pseudoRoyals);
-      if (blast_on_capture()
+      if (   blast_on_capture()
           && pseudoRoyalsTheirs & attacks_bb<KING>(sr))
           // skip if capturing this piece would blast all of the attacker's pseudo-royal pieces
           continue;
       attackers |= attackers_to(sr, c);
   }
+  // Look for duple check
+  if (var->dupleCheck)
+  {
+      Bitboard b;
+      Bitboard allAttackers = 0;
+      Bitboard pseudoRoyalCandidates = st->pseudoRoyalCandidates & pieces(~c);
+      while (pseudoRoyalCandidates)
+      {
+          Square sr = pop_lsb(pseudoRoyalCandidates);
+          if (!(blast_on_capture() && (pseudoRoyalsTheirs & attacks_bb<KING>(sr)))
+              && (b = attackers_to(sr, c)))
+              allAttackers |= b;
+          else
+              // If at least one isn't attacked, it is not a duple check
+              return attackers;
+      }
+      attackers |= allAttackers;
+  }
   return attackers;
 }
 
diff --git a/test.py b/test.py
index 3294bb5..f1c4cdc 100644 (file)
--- a/test.py
+++ b/test.py
@@ -856,6 +856,14 @@ class TestPyffish(unittest.TestCase):
         result = sf.gives_check("atomic", "8/8/kK6/8/8/8/Q7/8 b - - 0 1", [])
         self.assertFalse(result)
 
+        # pseudo-royal duple check
+        result = sf.gives_check("spartan", "lgkcckw1/hhhhhhhh/1N3lN1/8/8/8/PPPPPPPP/R1BQKB1R b KQ - 11 6", [])
+        self.assertTrue(result)
+        result = sf.gives_check("spartan", "lgkcckwl/hhhhhhhh/6N1/8/8/8/PPPPPPPP/RNBQKB1R b KQ - 5 3", [])
+        self.assertFalse(result)
+        result = sf.gives_check("spartan", "lgkcckwl/hhhhhhhh/8/8/8/8/PPPPPPPP/RNBQKBNR w KQ - 0 1", [])
+        self.assertFalse(result)
+
         # Shako castling discovered check
         result = sf.gives_check("shako", "10/5r4/2p3pBk1/1p6Pr/p3p5/9e/1PP2P4/P2P2PP2/ER3K2R1/8C1 w K - 7 38", ["f2h2"])
         self.assertTrue(result)