Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Thu, 11 Feb 2021 22:20:23 +0000 (23:20 +0100)
committerFabian Fichter <ianfab@users.noreply.github.com>
Thu, 11 Feb 2021 22:20:23 +0000 (23:20 +0100)
No functional change.

1  2 
src/position.cpp

@@@ -955,56 -530,23 +955,54 @@@ bool Position::legal(Move m) const 
        Direction step = to > from ? WEST : EAST;
  
        for (Square s = to; s != from; s += step)
 -          if (attackers_to(s) & pieces(~us))
 +          if (attackers_to(s, ~us))
                return false;
  
 +      // TODO: need to consider touching kings
 +      if (var->extinctionPseudoRoyal && attackers_to(from, ~us))
 +          return false;
 +
 +      // Will the gate be blocked by king or rook?
 +      Square rto = to + (to_sq(m) > from_sq(m) ? WEST : EAST);
 +      if (is_gating(m) && (gating_square(m) == to || gating_square(m) == rto))
 +          return false;
 +
-       // In case of Chess960, verify that when moving the castling rook we do
-       // not discover some hidden checker.
+       // In case of Chess960, verify if the Rook blocks some checks
        // For instance an enemy queen in SQ_A1 when castling rook is in SQ_B1.
-       return   !chess960
-             || !(attackers_to(to, pieces() ^ to_sq(m), ~us));
 -      return !chess960 || !(blockers_for_king(us) & to_sq(m));
++      return !chess960 || !attackers_to(to, pieces() ^ to_sq(m), ~us);
    }
  
 -  // If the moving piece is a king, check whether the destination square is
 -  // attacked by the opponent.
 -  if (type_of(piece_on(from)) == KING)
 -      return !(attackers_to(to) & pieces(~us));
 +  Bitboard occupied = (type_of(m) != DROP ? pieces() ^ from : pieces()) | to;
 +
 +  // Flying general rule and bikjang
 +  // In case of bikjang passing is always allowed, even when in check
 +  if (st->bikjang && is_pass(m))
 +      return true;
 +  if ((var->flyingGeneral && count<KING>(us)) || st->bikjang)
 +  {
 +      Square s = type_of(moved_piece(m)) == KING ? to : square<KING>(us);
 +      if (attacks_bb(~us, ROOK, s, occupied) & pieces(~us, KING) & ~square_bb(to))
 +          return false;
 +  }
  
 -  // A non-king move is legal if and only if it is not pinned or it
 -  // is moving along the ray towards or away from the king.
 -  return   !(blockers_for_king(us) & from)
 -        ||  aligned(from, to, square<KING>(us));
 +  // Makpong rule
 +  if (var->makpongRule && checkers() && type_of(moved_piece(m)) == KING && (checkers() ^ to))
 +      return false;
 +
 +  // If the moving piece is a king, check whether the destination
 +  // square is attacked by the opponent. Castling moves are checked
 +  // for legality during move generation.
 +  if (type_of(moved_piece(m)) == KING)
 +      return type_of(m) == CASTLING || !attackers_to(to, occupied, ~us);
 +
 +  Bitboard janggiCannons = pieces(JANGGI_CANNON);
 +  if (type_of(moved_piece(m)) == JANGGI_CANNON)
 +      janggiCannons = (type_of(m) == DROP ? janggiCannons : janggiCannons ^ from) | to;
 +  else if (janggiCannons & to)
 +      janggiCannons ^= to;
 +
 +  // A non-king move is legal if the king is not under attack after the move.
 +  return !count<KING>(us) || !(attackers_to(square<KING>(us), occupied, ~us, janggiCannons) & ~SquareBB[to]);
  }
  
  
@@@ -1019,33 -561,14 +1017,35 @@@ bool Position::pseudo_legal(const Move 
    Square to = to_sq(m);
    Piece pc = moved_piece(m);
  
 +  // Illegal moves to squares outside of board
 +  if (!(board_bb() & to))
 +      return false;
 +
 +  // Use a fast check for piece drops
 +  if (type_of(m) == DROP)
 +      return   piece_drops()
 +            && pc != NO_PIECE
 +            && color_of(pc) == us
 +            && count_in_hand(us, in_hand_piece_type(m))
 +            && (drop_region(us, type_of(pc)) & ~pieces() & to)
 +            && (   type_of(pc) == in_hand_piece_type(m)
 +                || (drop_promoted() && type_of(pc) == promoted_piece_type(in_hand_piece_type(m))));
 +
    // Use a slower but simpler function for uncommon cases
+   // yet we skip the legality check of MoveList<LEGAL>().
 -  if (type_of(m) != NORMAL)
 +  if (type_of(m) != NORMAL || is_gating(m) || arrow_gating())
-       return MoveList<LEGAL>(*this).contains(m);
+       return checkers() ? MoveList<    EVASIONS>(*this).contains(m)
+                         : MoveList<NON_EVASIONS>(*this).contains(m);
  
 +  // Handle the case where a mandatory piece promotion/demotion is not taken
 +  if (    mandatory_piece_promotion()
 +      && (is_promoted(from) ? piece_demotion() : promoted_piece_type(type_of(pc)) != NO_PIECE_TYPE)
 +      && (zone_bb(us, promotion_rank(), max_rank()) & (SquareBB[from] | to))
 +      && (!piece_promotion_on_capture() || capture(m)))
 +      return false;
 +
    // Is not a promotion, so promotion piece must be empty
 -  if (promotion_type(m) - KNIGHT != NO_PIECE_TYPE)
 +  if (promotion_type(m) != NO_PIECE_TYPE)
        return false;
  
    // If the 'from' square is not occupied by a piece belonging to the side to
@@@ -1191,21 -660,18 +1191,19 @@@ bool Position::gives_check(Move m) cons
        Square capsq = make_square(file_of(to), rank_of(from));
        Bitboard b = (pieces() ^ from ^ capsq) | to;
  
 -      return  (attacks_bb<  ROOK>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, ROOK))
 -            | (attacks_bb<BISHOP>(square<KING>(~sideToMove), b) & pieces(sideToMove, QUEEN, BISHOP));
 +      return attackers_to(square<KING>(~sideToMove), b) & pieces(sideToMove) & b;
    }
-   case CASTLING:
+   default: //CASTLING
    {
+       // Castling is encoded as 'king captures the rook'
 -      Square ksq = square<KING>(~sideToMove);
 -      Square rto = relative_square(sideToMove, to > from ? SQ_F1 : SQ_D1);
 +      Square kfrom = from;
-       Square rfrom = to; // Castling is encoded as 'king captures the rook'
++      Square rfrom = to;
 +      Square kto = make_square(rfrom > kfrom ? castling_kingside_file() : castling_queenside_file(), castling_rank(sideToMove));
 +      Square rto = kto + (rfrom > kfrom ? WEST : EAST);
  
 -      return   (attacks_bb<ROOK>(rto) & ksq)
 -            && (attacks_bb<ROOK>(rto, pieces() ^ from ^ to) & ksq);
 +      return   (PseudoAttacks[sideToMove][type_of(piece_on(rfrom))][rto] & square<KING>(~sideToMove))
 +            && (attacks_bb(sideToMove, type_of(piece_on(rfrom)), rto, (pieces() ^ kfrom ^ rfrom) | rto | kto) & square<KING>(~sideToMove));
    }
-   default:
-       assert(false);
-       return false;
    }
  }