Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Thu, 3 Sep 2020 19:12:25 +0000 (21:12 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Thu, 3 Sep 2020 19:12:25 +0000 (21:12 +0200)
bench: 4777225

1  2 
src/evaluate.cpp
src/movegen.cpp
src/movepick.cpp
src/pawns.cpp
src/search.cpp

@@@ -131,12 -126,9 +131,13 @@@ namespace 
      S(0, 0), S(10, 28), S(17, 33), S(15, 41), S(62, 72), S(168, 177), S(276, 260)
    };
  
 +  // KingProximity contains a penalty according to distance from king
 +  constexpr Score KingProximity = S(2, 4);
 +  constexpr Score EndgameKingProximity = S(0, 10);
 +
    // Assorted bonuses and penalties
    constexpr Score BishopPawns         = S(  3,  7);
+   constexpr Score BishopOnKingRing    = S( 24,  0);
    constexpr Score BishopXRayPawns     = S(  4,  5);
    constexpr Score CorneredBishop      = S( 50, 50);
    constexpr Score FlankAttacks        = S(  8,  0);
          if (b & kingRing[Them])
          {
              kingAttackersCount[Us]++;
 -            kingAttackersWeight[Us] += KingAttackWeights[Pt];
 +            kingAttackersWeight[Us] += KingAttackWeights[std::min(int(Pt), QUEEN + 1)];
              kingAttacksCount[Us] += popcount(b & attackedBy[Them][KING]);
          }
          else if (Pt == ROOK && (file_bb(s) & kingRing[Them]))
              score += RookOnKingRing;
  
+         else if (Pt == BISHOP && (attacks_bb<BISHOP>(s, pos.pieces(PAWN)) & kingRing[Them]))
+             score += BishopOnKingRing;
 +        if (Pt > QUEEN)
 +             b = (b & pos.pieces()) | (pos.moves_from(Us, Pt, s) & ~pos.pieces() & pos.board_bb());
 +
          int mob = popcount(b & mobilityArea[Us]);
  
 -        mobility[Us] += MobilityBonus[Pt - 2][mob];
 +        if (Pt <= QUEEN)
 +            mobility[Us] += MobilityBonus[Pt - 2][mob];
 +        else
 +            mobility[Us] += MaxMobility * (mob - 2) / (8 + mob);
 +
 +        // Piece promotion bonus
 +        if (pos.promoted_piece_type(Pt) != NO_PIECE_TYPE)
 +        {
 +            if (promotion_zone_bb(Us, pos.promotion_rank(), pos.max_rank()) & (b | s))
 +                score += make_score(PieceValue[MG][pos.promoted_piece_type(Pt)] - PieceValue[MG][Pt],
 +                                    PieceValue[EG][pos.promoted_piece_type(Pt)] - PieceValue[EG][Pt]) / 10;
 +        }
 +        else if (pos.piece_demotion() && pos.unpromoted_piece_on(s))
 +            score -= make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
 +                                PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 4;
 +        else if (pos.captures_to_hand() && pos.unpromoted_piece_on(s))
 +            score += make_score(PieceValue[MG][Pt] - PieceValue[MG][pos.unpromoted_piece_on(s)],
 +                                PieceValue[EG][Pt] - PieceValue[EG][pos.unpromoted_piece_on(s)]) / 8;
 +
 +        // Penalty if the piece is far from the kings in drop variants
 +        if ((pos.captures_to_hand() || pos.two_boards()) && pos.count<KING>(Them) && pos.count<KING>(Us))
 +            score -= KingProximity * distance(s, pos.square<KING>(Us)) * distance(s, pos.square<KING>(Them));
 +
 +        else if (pos.count<KING>(Us) && (Pt == FERS || Pt == SILVER))
 +            score -= EndgameKingProximity * (distance(s, pos.square<KING>(Us)) - 2);
  
          if (Pt == BISHOP || Pt == KNIGHT)
          {
diff --cc src/movegen.cpp
@@@ -265,65 -179,32 +265,64 @@@ namespace 
    }
  
  
-   template<bool Checks>
-   ExtMove* generate_moves(const Position& pos, ExtMove* moveList, Color us, PieceType pt,
-                           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);
  
-     const Square* pl = pos.squares(us, pt);
 -    const Square* pl = pos.squares<Pt>(Us);
++    const Square* pl = pos.squares(Us, pt);
  
      for (Square from = *pl; from != SQ_NONE; from = *++pl)
      {
 +        // Avoid generating discovered checks twice
-         if (Checks && (pos.blockers_for_king(~us) & from))
++        if (Checks && (pos.blockers_for_king(~Us) & from))
 +            continue;
 +
-         Bitboard b1 = (  (pos.attacks_from(us, pt, from) & pos.pieces())
-                        | (pos.moves_from(us, pt, from) & ~pos.pieces())) & target;
++        Bitboard b1 = (  (pos.attacks_from(Us, pt, from) & pos.pieces())
++                       | (pos.moves_from(Us, pt, from) & ~pos.pieces())) & target;
 +        PieceType prom_pt = pos.promoted_piece_type(pt);
-         Bitboard b2 = prom_pt && (!pos.promotion_limit(prom_pt) || pos.promotion_limit(prom_pt) > pos.count(us, prom_pt)) ? b1 : Bitboard(0);
++        Bitboard b2 = prom_pt && (!pos.promotion_limit(prom_pt) || pos.promotion_limit(prom_pt) > pos.count(Us, prom_pt)) ? b1 : Bitboard(0);
 +        Bitboard b3 = pos.piece_demotion() && pos.is_promoted(from) ? b1 : Bitboard(0);
 +
          if (Checks)
          {
 -            if (    (Pt == BISHOP || Pt == ROOK || Pt == QUEEN)
 -                && !(attacks_bb<Pt>(from) & target & pos.check_squares(Pt)))
 -                continue;
 +            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)));
 +        }
  
 -            if (pos.blockers_for_king(~Us) & from)
 -                continue;
 +        // Restrict target squares considering promotion zone
 +        if (b2 | b3)
 +        {
-             Bitboard promotion_zone = promotion_zone_bb(us, pos.promotion_rank(), pos.max_rank());
++            Bitboard promotion_zone = promotion_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;
 +            }
          }
  
 -        Bitboard b = attacks_bb<Pt>(from, pos.pieces()) & target;
 +        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));
  
 -        if (Checks)
 -            b &= pos.check_squares(Pt);
 +        // Shogi-style piece promotions
 +        while (b2)
 +            *moveList++ = make<PIECE_PROMOTION>(from, pop_lsb(&b2));
  
 -        while (b)
 -            *moveList++ = make_move(from, pop_lsb(&b));
 +        // Piece demotions
 +        while (b3)
 +            *moveList++ = make<PIECE_DEMOTION>(from, pop_lsb(&b3));
      }
  
      return moveList;
          default:
              static_assert(true, "Unsupported type in generate_all()");
      }
 +    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);
 -
 -    if (Type != QUIET_CHECKS && Type != EVASIONS)
 +    for (PieceType pt : pos.piece_types())
 +        if (pt != PAWN && pt != KING)
-             moveList = generate_moves<Checks>(pos, moveList, Us, pt, 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))
 +        for (PieceType pt : pos.piece_types())
 +            moveList = generate_drops<Us, Checks>(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 = attacks_bb<KING>(ksq) & target;
 +        Bitboard b = (  (pos.attacks_from(Us, KING, ksq) & pos.pieces())
 +                      | (pos.moves_from(Us, KING, ksq) & ~pos.pieces())) & 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 != CAPTURES) && pos.can_castle(Us & ANY_CASTLING))
              for(CastlingRights cr : { Us & KING_SIDE, Us & QUEEN_SIDE } )
@@@ -110,11 -106,11 +110,11 @@@ void MovePicker::score() 
  
        else if (Type == QUIETS)
            m.value =      (*mainHistory)[pos.side_to_move()][from_to(m)]
 -                   + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
 -                   + 2 * (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
 -                   + 2 * (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
 -                   +     (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
 +                   + 2 * (*continuationHistory[0])[history_slot(pos.moved_piece(m))][to_sq(m)]
 +                   + 2 * (*continuationHistory[1])[history_slot(pos.moved_piece(m))][to_sq(m)]
 +                   + 2 * (*continuationHistory[3])[history_slot(pos.moved_piece(m))][to_sq(m)]
 +                   +     (*continuationHistory[5])[history_slot(pos.moved_piece(m))][to_sq(m)]
-                    + (ply < MAX_LPH ?  4 * (*lowPlyHistory)[ply][from_to(m)] : 0);
+                    + (ply < MAX_LPH ? std::min(4, depth / 3) * (*lowPlyHistory)[ply][from_to(m)] : 0);
  
        else // Type == EVASIONS
        {
diff --cc src/pawns.cpp
@@@ -148,13 -145,13 +148,13 @@@ namespace 
  
          else if (!neighbours)
          {
-             score -=   Isolated * (1 + 2 * pos.must_capture())
-                      + WeakUnopposed * !opposed;
-             if (   (ourPawns & forward_file_bb(Them, s))
-                 && popcount(opposed) == 1
+             if (     opposed
+                 &&  (ourPawns & forward_file_bb(Them, s))
                  && !(theirPawns & adjacent_files_bb(s)))
 -                score -= Doubled;
 +                score -= Doubled * (1 + 2 * pos.must_capture());
+             else
 -                score -=   Isolated
++                score -=   Isolated * (1 + 2 * pos.must_capture())
+                          + WeakUnopposed * !opposed;
          }
  
          else if (backward)
diff --cc src/search.cpp
@@@ -586,37 -556,11 +586,39 @@@ void Thread::search() 
            }
            double bestMoveInstability = 1 + totBestMoveChanges / Threads.size();
  
+           double totalTime = rootMoves.size() == 1 ? 0 :
+                              Time.optimum() * fallingEval * reduction * bestMoveInstability;
 +          if (completedDepth >= 8 && rootPos.two_boards() && Options["Protocol"] == "xboard")
 +          {
 +              if (Limits.time[us])
 +                  Partner.ptell<FAIRY>("time " + std::to_string((Limits.time[us] - Time.elapsed()) / 10));
 +              if (Limits.time[~us])
 +                  Partner.ptell<FAIRY>("otim " + std::to_string(Limits.time[~us] / 10));
 +              if (!Partner.weDead && bestValue <= VALUE_MATED_IN_MAX_PLY)
 +              {
 +                  Partner.ptell("dead");
 +                  Partner.weDead = true;
 +              }
 +              else if (Partner.weDead && bestValue > VALUE_MATED_IN_MAX_PLY)
 +              {
 +                  Partner.ptell("x");
 +                  Partner.weDead = false;
 +              }
 +              else if (!Partner.weWin && bestValue >= VALUE_MATE_IN_MAX_PLY && Limits.time[~us] < Partner.time * 10)
 +              {
 +                  Partner.ptell("sit");
 +                  Partner.weWin = true;
 +              }
 +              else if (Partner.weWin && (bestValue < VALUE_MATE_IN_MAX_PLY || Limits.time[~us] > Partner.time * 10))
 +              {
 +                  Partner.ptell("x");
 +                  Partner.weWin = false;
 +              }
 +          }
 +
-           // Stop the search if we have only one legal move, or if available time elapsed
-           if (   rootMoves.size() == 1
-               || Time.elapsed() > Time.optimum() * fallingEval * reduction * bestMoveInstability)
+           // Stop the search if we have exceeded the totalTime, at least 1ms search.
+           if (Time.elapsed() > totalTime)
            {
                // If we are allowed to ponder do not stop the search now but
                // keep pondering until the GUI sends "ponderhit" or "stop".