Cleanup and optimize Position::has_mate_threat()
authorMarco Costalba <mcostalba@gmail.com>
Mon, 9 Aug 2010 10:45:02 +0000 (11:45 +0100)
committerMarco Costalba <mcostalba@gmail.com>
Mon, 9 Aug 2010 11:30:33 +0000 (12:30 +0100)
There is a functional change because we now skip
more moves and because do_move() / undo_move() is
well known to be not reversible we end up with a
change in node count, although there is actually
no change but a bit speed up.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/position.cpp
src/position.h
src/search.cpp

index 35e2627634ed2f9f0926dfc9216bb6e9382f3dfd..c8132d5e513d2a1b2d4aa6a711f96e1440b0b5f7 100644 (file)
@@ -1733,82 +1733,79 @@ bool Position::is_draw() const {
 bool Position::is_mate() const {
 
   MoveStack moves[256];
-  return is_check() && (generate_moves(*this, moves, false) == moves);
+  return is_check() && (generate_moves(*this, moves) == moves);
 }
 
 
-/// Position::has_mate_threat() tests whether a given color has a mate in one
-/// from the current position.
+/// Position::has_mate_threat() tests whether the side to move is under
+/// a threat of being mated in one from the current position.
 
-bool Position::has_mate_threat(Color c) {
+bool Position::has_mate_threat() {
 
+  MoveStack mlist[256], *last, *cur;
   StateInfo st1, st2;
-  Color stm = side_to_move();
+  bool mateFound = false;
 
+  // If we are under check it's up to evasions to do the job
   if (is_check())
       return false;
 
-  // If the input color is not equal to the side to move, do a null move
-  if (c != stm)
-      do_null_move(st1);
+  // First pass the move to our opponent doing a null move
+  do_null_move(st1);
 
-  MoveStack mlist[120];
-  bool result = false;
-  Bitboard pinned = pinned_pieces(sideToMove);
-
-  // Generate pseudo-legal non-capture and capture check moves
-  MoveStack* last = generate_non_capture_checks(*this, mlist);
+  // Then generate pseudo-legal moves that give check
+  last = generate_non_capture_checks(*this, mlist);
   last = generate_captures(*this, last);
 
-  // Loop through the moves, and see if one of them is mate
-  for (MoveStack* cur = mlist; cur != last; cur++)
+  // Loop through the moves, and see if one of them gives mate
+  Bitboard pinned = pinned_pieces(sideToMove);
+  CheckInfo ci(*this);
+  for (cur = mlist; cur != last && !mateFound; cur++)
   {
       Move move = cur->move;
-      if (!pl_move_is_legal(move, pinned))
+      if (   !pl_move_is_legal(move, pinned)
+          || !move_is_check(move, ci))
           continue;
 
-      do_move(move, st2);
+      do_move(move, st2, ci, true);
+
       if (is_mate())
-          result = true;
+          mateFound = true;
 
       undo_move(move);
   }
 
-  // Undo null move, if necessary
-  if (c != stm)
-      undo_null_move();
-
-  return result;
+  undo_null_move();
+  return mateFound;
 }
 
 
-/// Position::init_zobrist() is a static member function which initializes the
-/// various arrays used to compute hash keys.
+/// Position::init_zobrist() is a static member function which initializes at
+/// startup the various arrays used to compute hash keys.
 
 void Position::init_zobrist() {
 
-  for (int i = 0; i < 2; i++)
-      for (int j = 0; j < 8; j++)
-          for (int k = 0; k < 64; k++)
-              zobrist[i][j][k] = Key(genrand_int64());
+  int i,j, k;
 
-  for (int i = 0; i < 64; i++)
+  for (i = 0; i < 2; i++) for (j = 0; j < 8; j++) for (k = 0; k < 64; k++)
+      zobrist[i][j][k] = Key(genrand_int64());
+
+  for (i = 0; i < 64; i++)
       zobEp[i] = Key(genrand_int64());
 
-  for (int i = 0; i < 16; i++)
-      zobCastle[i] = genrand_int64();
+  for (i = 0; i < 16; i++)
+      zobCastle[i] = Key(genrand_int64());
 
-  zobSideToMove = genrand_int64();
-  zobExclusion = genrand_int64();
+  zobSideToMove = Key(genrand_int64());
+  zobExclusion  = Key(genrand_int64());
 }
 
 
 /// Position::init_piece_square_tables() initializes the piece square tables.
-/// This is a two-step operation:
-/// First, the white halves of the tables are
-/// copied from the MgPST[][] and EgPST[][] arrays.
-/// Second, the black halves of the tables are initialized by mirroring
-/// and changing the sign of the corresponding white scores.
+/// This is a two-step operation: First, the white halves of the tables are
+/// copied from the MgPST[][] and EgPST[][] arrays. Second, the black halves
+/// of the tables are initialized by mirroring and changing the sign of the
+/// corresponding white scores.
 
 void Position::init_piece_square_tables() {
 
index e921b350cd7270f2fed7b632f0cc64821caf59fc..6d7ea0ef30bcd990b98f9d976137d091575f04cb 100644 (file)
@@ -264,8 +264,8 @@ public:
   bool is_mate() const;
   bool is_draw() const;
 
-  // Check if one side threatens a mate in one
-  bool has_mate_threat(Color c);
+  // Check if side to move could be mated in one
+  bool has_mate_threat();
 
   // Number of plies since the last non-reversible move
   int rule_50_counter() const;
index 97ed340d4efd419ef1dbf3a70d2bc132a16d5ef0..652893282ca35bc51767bcee3d535aa2328ff10f 100644 (file)
@@ -1168,7 +1168,7 @@ namespace {
 
     // Expensive mate threat detection (only for PV nodes)
     if (PvNode)
-        mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move()));
+        mateThreat = pos.has_mate_threat();
 
     // Initialize a MovePicker object for the current position
     MovePicker mp = MovePicker(pos, ttMove, depth, H, ss, (PvNode ? -VALUE_INFINITE : beta));