Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sat, 26 Jun 2021 14:04:59 +0000 (16:04 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sat, 26 Jun 2021 14:32:50 +0000 (16:32 +0200)
bench: 5173306

1  2 
src/movegen.cpp

diff --cc src/movegen.cpp
@@@ -120,10 -61,10 +120,10 @@@ namespace 
      Bitboard emptySquares;
  
      Bitboard pawnsOn7    = pos.pieces(Us, PAWN) &  TRank7BB;
 -    Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & ~TRank7BB;
 +    Bitboard pawnsNotOn7 = pos.pieces(Us, PAWN) & (pos.mandatory_pawn_promotion() ? ~TRank7BB : AllSquares);
  
-     Bitboard enemies = (Type == EVASIONS ? pos.checkers():
-                         Type == CAPTURES ? target : pos.pieces(Them));
+     Bitboard enemies = (Type == EVASIONS ? pos.checkers()
+                      :  Type == CAPTURES ? target : pos.pieces(Them));
  
      // Single and double pawn pushes, no promotions
      if (Type != CAPTURES)
    }
  
  
-   template<bool Checks>
-   ExtMove* generate_moves(const Position& pos, ExtMove* moveList, PieceType Pt, Bitboard piecesToMove, Bitboard target) {
 -  template<Color Us, PieceType Pt, bool Checks>
 -  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Bitboard target) {
++  template<Color Us, bool Checks>
++  ExtMove* generate_moves(const Position& pos, ExtMove* moveList, PieceType Pt, Bitboard target) {
  
 -    static_assert(Pt != KING && Pt != PAWN, "Unsupported piece type in generate_moves()");
 +    assert(Pt != KING && Pt != PAWN);
  
-     Color us = pos.side_to_move();
-     Bitboard bb = piecesToMove & pos.pieces(Pt);
+     Bitboard bb = pos.pieces(Us, Pt);
  
      while (bb)
      {
          Square from = pop_lsb(bb);
  
-         Bitboard b1 = (  (pos.attacks_from(us, Pt, from) & pos.pieces())
-                        | (pos.moves_from(us, Pt, from) & ~pos.pieces())) & target;
 -        Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
 -        if (Checks && (Pt == QUEEN || !(pos.blockers_for_king(~Us) & from)))
 -            b &= pos.check_squares(Pt);
++        Bitboard b1 = (  (pos.attacks_from(Us, Pt, from) & pos.pieces())
++                       | (pos.moves_from(Us, Pt, from) & ~pos.pieces())) & target;
 +        PieceType promPt = pos.promoted_piece_type(Pt);
-         Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(us, promPt)) ? b1 : Bitboard(0);
++        Bitboard b2 = promPt && (!pos.promotion_limit(promPt) || pos.promotion_limit(promPt) > pos.count(Us, promPt)) ? b1 : Bitboard(0);
 +        Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0);
  
 -        while (b)
 -            *moveList++ = make_move(from, pop_lsb(b));
 +        if (Checks)
 +        {
 +            b1 &= pos.check_squares(Pt);
 +            if (b2)
 +                b2 &= pos.check_squares(pos.promoted_piece_type(Pt));
 +            if (b3)
 +                b3 &= pos.check_squares(type_of(pos.unpromoted_piece_on(from)));
 +        }
 +
 +        // Restrict target squares considering promotion zone
 +        if (b2 | b3)
 +        {
-             Bitboard promotion_zone = zone_bb(us, pos.promotion_rank(), pos.max_rank());
++            Bitboard promotion_zone = zone_bb(Us, pos.promotion_rank(), pos.max_rank());
 +            if (pos.mandatory_piece_promotion())
 +                b1 &= (promotion_zone & from ? Bitboard(0) : ~promotion_zone) | (pos.piece_promotion_on_capture() ? ~pos.pieces() : Bitboard(0));
 +            // Exclude quiet promotions/demotions
 +            if (pos.piece_promotion_on_capture())
 +            {
 +                b2 &= pos.pieces();
 +                b3 &= pos.pieces();
 +            }
 +            // Consider promotions/demotions into promotion zone
 +            if (!(promotion_zone & from))
 +            {
 +                b2 &= promotion_zone;
 +                b3 &= promotion_zone;
 +            }
 +        }
 +
 +        while (b1)
-             moveList = make_move_and_gating<NORMAL>(pos, moveList, us, from, pop_lsb(b1));
++            moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, from, pop_lsb(b1));
 +
 +        // Shogi-style piece promotions
 +        while (b2)
 +            *moveList++ = make<PIECE_PROMOTION>(from, pop_lsb(b2));
 +
 +        // Piece demotions
 +        while (b3)
 +            *moveList++ = make<PIECE_DEMOTION>(from, pop_lsb(b3));
      }
  
      return moveList;
      static_assert(Type != LEGAL, "Unsupported type in generate_all()");
  
      constexpr bool Checks = Type == QUIET_CHECKS; // Reduce template instantiations
-     Bitboard target, piecesToMove = pos.pieces(Us);
 -    const Square ksq = pos.square<KING>(Us);
++    const Square ksq = pos.count<KING>(Us) ? pos.square<KING>(Us) : SQ_NONE;
+     Bitboard target;
 -    if (Type == EVASIONS && more_than_one(pos.checkers()))
++    if (Type == EVASIONS && more_than_one(pos.checkers() & ~pos.non_sliding_riders()))
+         goto kingMoves; // Double check, only a king move can save the day
  
-     if(Type == QUIET_CHECKS)
-         piecesToMove &= ~pos.blockers_for_king(~Us);
+     target = Type == EVASIONS     ?  between_bb(ksq, lsb(pos.checkers()))
+            : Type == NON_EVASIONS ? ~pos.pieces( Us)
+            : Type == CAPTURES     ?  pos.pieces(~Us)
+                                   : ~pos.pieces(   ); // QUIETS || QUIET_CHECKS
  
-     switch (Type)
++    if (Type == EVASIONS)
 +    {
-         case CAPTURES:
-             target =  pos.pieces(~Us);
-             break;
-         case QUIETS:
-         case QUIET_CHECKS:
-             target = ~pos.pieces();
-             break;
-         case EVASIONS:
-         {
-             if (pos.checkers() & pos.non_sliding_riders())
-             {
-                 target = ~pos.pieces(Us);
-                 break;
-             }
-             target = between_bb(pos.square<KING>(Us), lsb(pos.checkers()));
-             // Leaper attacks can not be blocked
-             Square checksq = lsb(pos.checkers());
-             if (LeaperAttacks[~Us][type_of(pos.piece_on(checksq))][checksq] & pos.square<KING>(Us))
-                 target = pos.checkers();
-             break;
-         }
-         case NON_EVASIONS:
++        if (pos.checkers() & pos.non_sliding_riders())
 +            target = ~pos.pieces(Us);
-             break;
++        // Leaper attacks can not be blocked
++        Square checksq = lsb(pos.checkers());
++        if (LeaperAttacks[~Us][type_of(pos.piece_on(checksq))][checksq] & pos.square<KING>(Us))
++            target = pos.checkers();
 +    }
++
 +    target &= pos.board_bb();
 +
      moveList = generate_pawn_moves<Us, Type>(pos, moveList, target);
 -    moveList = generate_moves<Us, KNIGHT, Checks>(pos, moveList, target);
 -    moveList = generate_moves<Us, BISHOP, Checks>(pos, moveList, target);
 -    moveList = generate_moves<Us,   ROOK, Checks>(pos, moveList, target);
 -    moveList = generate_moves<Us,  QUEEN, Checks>(pos, moveList, target);
 +    for (PieceType pt : pos.piece_types())
 +        if (pt != PAWN && pt != KING)
-             moveList = generate_moves<Checks>(pos, moveList, pt, piecesToMove, target);
++            moveList = generate_moves<Us, Checks>(pos, moveList, pt, target);
 +    // generate drops
 +    if (pos.piece_drops() && Type != CAPTURES && (pos.count_in_hand(Us, ALL_PIECES) > 0 || pos.two_boards()))
 +        for (PieceType pt : pos.piece_types())
 +            moveList = generate_drops<Us, Type>(pos, moveList, pt, target & ~pos.pieces(~Us));
 +
-     if (Type != QUIET_CHECKS && Type != EVASIONS && pos.count<KING>(Us))
-     {
-         Square ksq = pos.square<KING>(Us);
-         Bitboard b = (  (pos.attacks_from(Us, KING, ksq) & pos.pieces())
-                       | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & target;
-         while (b)
-             moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, ksq, pop_lsb(b));
-         // Passing move by king
-         if (pos.pass())
-             *moveList++ = make<SPECIAL>(ksq, ksq);
-         if ((Type != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
-             for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
-                 if (!pos.castling_impeded(cr) && pos.can_castle(cr))
-                     moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, pos.castling_rook_square(cr));
-     }
-     // Workaround for passing: Execute a non-move with any piece
-     else if (pos.pass() && !pos.count<KING>(Us) && pos.pieces(Us))
-         *moveList++ = make<SPECIAL>(lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
 +    // Castling with non-king piece
 +    if (!pos.count<KING>(Us) && Type != CAPTURES && pos.can_castle(Us & ANY_CASTLING))
 +    {
 +        Square from = pos.castling_king_square(Us);
 +        for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
 +            if (!pos.castling_impeded(cr) && pos.can_castle(cr))
 +                moveList = make_move_and_gating<CASTLING>(pos, moveList, Us, from, pos.castling_rook_square(cr));
 +    }
  
 -kingMoves:
 -    if (!Checks || pos.blockers_for_king(~Us) & ksq)
 +    // Special moves
 +    if (pos.cambodian_moves() && pos.gates(Us))
      {
 -        Bitboard b = attacks_bb<KING>(ksq) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
 -        if (Checks)
 -            b &= ~attacks_bb<QUEEN>(pos.square<KING>(~Us));
 +        if (Type != CAPTURES && Type != EVASIONS && (pos.pieces(Us, KING) & pos.gates(Us)))
 +        {
 +            Square from = pos.square<KING>(Us);
 +            Bitboard b = PseudoAttacks[WHITE][KNIGHT][from] & rank_bb(rank_of(from + (Us == WHITE ? NORTH : SOUTH)))
 +                        & target & ~pos.pieces();
 +            while (b)
 +                moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, pop_lsb(b));
 +        }
 +
 +        Bitboard b = pos.pieces(Us, FERS) & pos.gates(Us);
 +        while (b)
 +        {
 +            Square from = pop_lsb(b);
 +            Square to = from + 2 * (Us == WHITE ? NORTH : SOUTH);
 +            if (is_ok(to) && (target & to))
 +                moveList = make_move_and_gating<SPECIAL>(pos, moveList, Us, from, to);
 +        }
 +    }
  
++    // Workaround for passing: Execute a non-move with any piece
++    if (pos.pass() && !pos.count<KING>(Us) && pos.pieces(Us))
++        *moveList++ = make<SPECIAL>(lsb(pos.pieces(Us)), lsb(pos.pieces(Us)));
++
++kingMoves:
++    if (pos.count<KING>(Us) && (!Checks || pos.blockers_for_king(~Us) & ksq))
++    {
++        Bitboard b = (  (pos.attacks_from(Us, KING, ksq) & pos.pieces())
++                      | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & (Type == EVASIONS ? ~pos.pieces(Us) : target);
+         while (b)
 -            *moveList++ = make_move(ksq, pop_lsb(b));
++            moveList = make_move_and_gating<NORMAL>(pos, moveList, Us, ksq, pop_lsb(b));
++
++        // Passing move by king
++        if (pos.pass())
++            *moveList++ = make<SPECIAL>(ksq, ksq);
+         if ((Type == QUIETS || Type == NON_EVASIONS) && pos.can_castle(Us & ANY_CASTLING))
+             for (CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
+                 if (!pos.castling_impeded(cr) && pos.can_castle(cr))
 -                    *moveList++ = make<CASTLING>(ksq, pos.castling_rook_square(cr));
++                    moveList = make_move_and_gating<CASTLING>(pos, moveList, Us,ksq, pos.castling_rook_square(cr));
+     }
      return moveList;
    }