]> git.sesse.net Git - stockfish/blobdiff - src/position.cpp
Extend move_is_legal() to work also when in check
[stockfish] / src / position.cpp
index 1fe723aec461e20a303582484349b9696ca9c552..412a7782462c3ee203bdbf296747896dba888f88 100644 (file)
@@ -458,19 +458,11 @@ void Position::find_checkers() {
 
 /// Position::pl_move_is_legal() tests whether a pseudo-legal move is legal
 
-bool Position::pl_move_is_legal(Move m) const {
-
-  // If we're in check, all pseudo-legal moves are legal, because our
-  // check evasion generator only generates true legal moves.
-  return is_check() || pl_move_is_legal(m, pinned_pieces(side_to_move()));
-}
-
 bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
 
   assert(is_ok());
   assert(move_is_ok(m));
   assert(pinned == pinned_pieces(side_to_move()));
-  assert(!is_check());
 
   // Castling moves are checked for legality during move generation.
   if (move_is_castle(m))
@@ -482,7 +474,7 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
   assert(color_of_piece_on(from) == us);
   assert(piece_on(king_square(us)) == piece_of_color_and_type(us, KING));
 
-  // En passant captures are a tricky special case.  Because they are
+  // En passant captures are a tricky special case. Because they are
   // rather uncommon, we do it simply by testing whether the king is attacked
   // after the move is made
   if (move_is_ep(m))
@@ -519,6 +511,32 @@ bool Position::pl_move_is_legal(Move m, Bitboard pinned) const {
 }
 
 
+/// Position::pl_move_is_evasion() tests whether a pseudo-legal move is a legal evasion
+
+bool Position::pl_move_is_evasion(Move m, Bitboard pinned) const
+{
+  assert(pos.is_check());
+
+  Color us = side_to_move();
+  Square from = move_from(m);
+  Square to = move_to(m);
+
+  // King moves and en-passant captures are verified in pl_move_is_legal()
+  if (type_of_piece_on(from) == KING || move_is_ep(m))
+      return pl_move_is_legal(m, pinned);
+
+  Bitboard target = checkers();
+  Square checksq = pop_1st_bit(&target);
+
+  if (target) // double check ?
+      return false;
+
+  // Our move must be a blocking evasion or a capture of the checking piece
+  target = squares_between(checksq, king_square(us)) | checkers();
+  return bit_is_set(target, to) && pl_move_is_legal(m, pinned);
+}
+
+
 /// Position::move_is_check() tests whether a pseudo-legal move is a check
 
 bool Position::move_is_check(Move m) const {
@@ -1300,13 +1318,13 @@ void Position::undo_null_move() {
 int Position::see(Square to) const {
 
   assert(square_is_ok(to));
-  return see(SQ_NONE, to, false);
+  return see(SQ_NONE, to);
 }
 
 int Position::see(Move m) const {
 
   assert(move_is_ok(m));
-  return see(move_from(m), move_to(m), false);
+  return see(move_from(m), move_to(m));
 }
 
 int Position::see_sign(Move m) const {
@@ -1322,10 +1340,10 @@ int Position::see_sign(Move m) const {
       && type_of_piece_on(from) != KING)
          return 1;
 
-  return see(from, to, true);
+  return see(from, to);
 }
 
-int Position::see(Square from, Square to, bool shortcut) const {
+int Position::see(Square from, Square to) const {
 
   // Material values
   static const int seeValues[18] = {
@@ -1337,9 +1355,7 @@ int Position::see(Square from, Square to, bool shortcut) const {
   };
 
   Bitboard attackers, stmAttackers, b;
-  int pieceDiff = 0;
 
-  assert(!shortcut || from != SQ_NONE);
   assert(square_is_ok(from) || from == SQ_NONE);
   assert(square_is_ok(to));
 
@@ -1356,22 +1372,6 @@ int Position::see(Square from, Square to, bool shortcut) const {
   if (type_of_piece(piece) == KING)
       return seeValues[capture];
 
-  // If captured piece is defended by enemy pawns or knights then SEE is negative
-  // when captured piece value does not compensate the lost of capturing one.
-  if (shortcut)
-  {
-      pieceDiff = seeValues[piece] - seeValues[capture];
-
-      if (   pieceDiff > seeValues[PAWN]
-          &&(attacks_from<PAWN>(to, us) & pieces(PAWN, them)))
-          return -(pieceDiff - seeValues[PAWN] / 2);
-
-      if (   pieceDiff > seeValues[KNIGHT]
-          && pieces(KNIGHT, them)
-          &&(pieces(KNIGHT, them) & attacks_from<KNIGHT>(to)))
-          return -(pieceDiff - seeValues[KNIGHT] / 2);
-  }
-
   // Handle en passant moves
   if (st->epSquare == to && type_of_piece_on(from) == PAWN)
   {
@@ -1442,15 +1442,6 @@ int Position::see(Square from, Square to, bool shortcut) const {
       for (pt = PAWN; !(stmAttackers & pieces(pt)); pt++)
           assert(pt < KING);
 
-      // If captured piece is defended by an enemy piece then SEE is negative
-      // if captured piece value does not compensate the lost of capturing one.
-      if (pieceDiff > seeValues[pt])
-      {
-          assert(shortcut);
-          return -(pieceDiff - seeValues[pt] / 2);
-      } else
-          pieceDiff = 0; // Only first cycle
-
       // Remove the attacker we just found from the 'attackers' bitboard,
       // and scan for new X-ray attacks behind the attacker.
       b = stmAttackers & pieces(pt);
@@ -1732,8 +1723,7 @@ bool Position::is_draw() const {
 bool Position::is_mate() const {
 
   MoveStack moves[256];
-
-  return is_check() && (generate_evasions(*this, moves, pinned_pieces(sideToMove)) == moves);
+  return is_check() && (generate_moves(*this, moves, false) == moves);
 }
 
 
@@ -1754,11 +1744,10 @@ bool Position::has_mate_threat(Color c) {
 
   MoveStack mlist[120];
   bool result = false;
-  Bitboard dc = discovered_check_candidates(sideToMove);
   Bitboard pinned = pinned_pieces(sideToMove);
 
   // Generate pseudo-legal non-capture and capture check moves
-  MoveStack* last = generate_non_capture_checks(*this, mlist, dc);
+  MoveStack* last = generate_non_capture_checks(*this, mlist);
   last = generate_captures(*this, last);
 
   // Loop through the moves, and see if one of them is mate