Merge official-stockfish/master
authorFabian Fichter <ianfab@users.noreply.github.com>
Sun, 20 Sep 2020 11:17:16 +0000 (13:17 +0200)
committerFabian Fichter <ianfab@users.noreply.github.com>
Sun, 20 Sep 2020 11:17:16 +0000 (13:17 +0200)
bench: 4629236

1  2 
src/endgame.cpp
src/evaluate.cpp
src/movegen.cpp
src/pawns.cpp
src/position.cpp
src/search.cpp
src/ucioption.cpp

diff --cc src/endgame.cpp
Simple merge
Simple merge
diff --cc src/movegen.cpp
Simple merge
diff --cc src/pawns.cpp
@@@ -38,6 -38,9 +38,9 @@@ namespace 
    constexpr Score WeakLever     = S( 0, 56);
    constexpr Score WeakUnopposed = S(13, 27);
  
+   // Bonus for blocked pawns at 5th or 6th rank
 -  constexpr Score BlockedPawn[2] = { S(-11, -4), S(-3, 4) };
++  constexpr Score BlockedPawn[RANK_NB - 5] = { S(-11, -4), S(-3, 4) };
    constexpr Score BlockedStorm[RANK_NB] = {
      S(0, 0), S(0, 0), S(76, 78), S(-10, 15), S(-7, 10), S(-4, 6), S(-1, 2)
    };
              e->passedPawns[Us] |= s;
  
          // Score this pawn
 -        if (support | phalanx)
 +        if ((support | phalanx) && (r < pos.promotion_rank() || !pos.mandatory_pawn_promotion()))
          {
-             int v =  Connected[r] * (4 + 2 * bool(phalanx) - 2 * bool(opposed) - bool(blocked)) / 2 * (r == RANK_2 && pos.captures_to_hand() ? 3 : 1)
 -            int v =  Connected[r] * (2 + bool(phalanx) - bool(opposed))
++            int v =  Connected[r] * (2 + bool(phalanx) - bool(opposed)) * (r == RANK_2 && pos.captures_to_hand() ? 3 : 1)
                     + 21 * popcount(support);
 +            if (r >= RANK_4 && pos.count<PAWN>(Us) > popcount(pos.board_bb()) / 4)
 +                v = popcount(support | phalanx) * 50 / (opposed ? 2 : 1);
  
              score += make_score(v, v * (r - 2) / 4);
          }
          if (!support)
              score -=  Doubled * doubled
                      + WeakLever * more_than_one(lever);
+         if (blocked && r > RANK_4)
+             score += BlockedPawn[r-4];
      }
  
 +    // Double pawn evaluation if there are no non-pawn pieces
 +    if (pos.count<ALL_PIECES>(Us) == pos.count<PAWN>(Us))
 +        score = score * 2;
 +
 +    const Square* pl_shogi = pos.squares<SHOGI_PAWN>(Us);
 +
 +    ourPawns   = pos.pieces(Us,   SHOGI_PAWN);
 +    theirPawns = pos.pieces(Them, SHOGI_PAWN);
 +
 +    // Loop through all shogi pawns of the current color and score each one
 +    while ((s = *pl_shogi++) != SQ_NONE)
 +    {
 +        assert(pos.piece_on(s) == make_piece(Us, SHOGI_PAWN));
 +
 +        neighbours = ourPawns & adjacent_files_bb(s);
 +
 +        if (!neighbours)
 +            score -= Isolated / 2;
 +    }
 +
      return score;
    }
  
@@@ -308,147 -221,65 +308,155 @@@ Position& Position::set(const Variant* 
    // 2. Active color
    ss >> token;
    sideToMove = (token == 'w' ? WHITE : BLACK);
 +  // Invert side to move for SFEN
 +  if (sfen)
 +      sideToMove = ~sideToMove;
    ss >> token;
  
 -  // 3. Castling availability. Compatible with 3 standards: Normal FEN standard,
 -  // Shredder-FEN that uses the letters of the columns on which the rooks began
 -  // the game instead of KQkq and also X-FEN standard that, in case of Chess960,
 -  // if an inner rook is associated with the castling right, the castling tag is
 -  // replaced by the file letter of the involved rook, as for the Shredder-FEN.
 -  while ((ss >> token) && !isspace(token))
 +  // 3-4. Skip parsing castling and en passant flags if not present
 +  st->epSquare = SQ_NONE;
 +  if (!isdigit(ss.peek()) && !sfen)
    {
 -      Square rsq;
 -      Color c = islower(token) ? BLACK : WHITE;
 -      Piece rook = make_piece(c, ROOK);
 +      // 3. Castling availability. Compatible with 3 standards: Normal FEN standard,
 +      // Shredder-FEN that uses the letters of the columns on which the rooks began
 +      // the game instead of KQkq and also X-FEN standard that, in case of Chess960,
 +      // if an inner rook is associated with the castling right, the castling tag is
 +      // replaced by the file letter of the involved rook, as for the Shredder-FEN.
 +      while ((ss >> token) && !isspace(token))
 +      {
 +          Square rsq;
 +          Color c = islower(token) ? BLACK : WHITE;
 +          Piece rook = make_piece(c, castling_rook_piece());
  
 -      token = char(toupper(token));
 +          token = char(toupper(token));
  
 -      if (token == 'K')
 -          for (rsq = relative_square(c, SQ_H1); piece_on(rsq) != rook; --rsq) {}
 +          if (token == 'K')
 +              for (rsq = make_square(FILE_MAX, castling_rank(c)); piece_on(rsq) != rook; --rsq) {}
  
 -      else if (token == 'Q')
 -          for (rsq = relative_square(c, SQ_A1); piece_on(rsq) != rook; ++rsq) {}
 +          else if (token == 'Q')
 +              for (rsq = make_square(FILE_A, castling_rank(c)); piece_on(rsq) != rook; ++rsq) {}
  
 -      else if (token >= 'A' && token <= 'H')
 -          rsq = make_square(File(token - 'A'), relative_rank(c, RANK_1));
 +          else if (token >= 'A' && token <= 'A' + max_file())
 +              rsq = make_square(File(token - 'A'), castling_rank(c));
  
 -      else
 -          continue;
 +          else
 +              continue;
  
 -      set_castling_right(c, rsq);
 +          // Set gates (and skip castling rights)
 +          if (gating())
 +          {
 +              st->gatesBB[c] |= rsq;
 +              if (token == 'K' || token == 'Q')
 +                  st->gatesBB[c] |= count<KING>(c) ? square<KING>(c) : make_square(FILE_E, castling_rank(c));
 +              // Do not set castling rights for gates unless there are no pieces in hand,
 +              // which means that the file is referring to a chess960 castling right.
 +              else if (!seirawan_gating() || count_in_hand(c, ALL_PIECES) || captures_to_hand())
 +                  continue;
 +          }
 +
 +          if (castling_enabled())
 +              set_castling_right(c, rsq);
 +      }
 +
 +      // Set castling rights for 960 gating variants
 +      if (gating() && castling_enabled())
 +          for (Color c : {WHITE, BLACK})
 +              if ((gates(c) & pieces(KING)) && !castling_rights(c) && (!seirawan_gating() || count_in_hand(c, ALL_PIECES) || captures_to_hand()))
 +              {
 +                  Bitboard castling_rooks = gates(c) & pieces(castling_rook_piece());
 +                  while (castling_rooks)
 +                      set_castling_right(c, pop_lsb(&castling_rooks));
 +              }
 +
 +      // counting limit
 +      if (counting_rule() && isdigit(ss.peek()))
 +          ss >> st->countingLimit;
 +
-       // 4. En passant square. Ignore if no pawn capture is possible
++      // 4. En passant square.
++      // Ignore if square is invalid or not on side to move relative rank 6.
 +      else if (   ((ss >> col) && (col >= 'a' && col <= 'a' + max_file()))
 +               && ((ss >> row) && (row >= '1' && row <= '1' + max_rank())))
 +      {
 +          st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
 +
-           if (   !(attackers_to(st->epSquare) & pieces(sideToMove, PAWN))
-               || !(pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove))))
++          // En passant square will be considered only if
++          // a) side to move have a pawn threatening epSquare
++          // b) there is an enemy pawn in front of epSquare
++          // c) there is no piece on epSquare or behind epSquare
++          bool enpassant;
++          enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
++                  && (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
++                  && !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))));
++          if (!enpassant)
 +              st->epSquare = SQ_NONE;
 +      }
    }
  
 -  // 4. En passant square.
 -  // Ignore if square is invalid or not on side to move relative rank 6.
 -  bool enpassant = false;
 +  // Check counter for nCheck
 +  ss >> std::skipws >> token >> std::noskipws;
  
 -  if (   ((ss >> col) && (col >= 'a' && col <= 'h'))
 -      && ((ss >> row) && (row == (sideToMove == WHITE ? '6' : '3'))))
 +  if (check_counting())
    {
 -      st->epSquare = make_square(File(col - 'a'), Rank(row - '1'));
 -
 -      // En passant square will be considered only if
 -      // a) side to move have a pawn threatening epSquare
 -      // b) there is an enemy pawn in front of epSquare
 -      // c) there is no piece on epSquare or behind epSquare
 -      enpassant = pawn_attacks_bb(~sideToMove, st->epSquare) & pieces(sideToMove, PAWN)
 -               && (pieces(~sideToMove, PAWN) & (st->epSquare + pawn_push(~sideToMove)))
 -               && !(pieces() & (st->epSquare | (st->epSquare + pawn_push(sideToMove))));
 +      if (ss.peek() == '+')
 +      {
 +          st->checksRemaining[WHITE] = CheckCount(std::max(token - '0', 0));
 +          ss >> token >> token;
 +          st->checksRemaining[BLACK] = CheckCount(std::max(token - '0', 0));
 +      }
 +      else
 +      {
 +          // If check count is not provided, assume that the next check wins
 +          st->checksRemaining[WHITE] = CheckCount(1);
 +          st->checksRemaining[BLACK] = CheckCount(1);
 +          ss.putback(token);
 +      }
    }
 -
 -  if (!enpassant)
 -      st->epSquare = SQ_NONE;
 +  else
 +      ss.putback(token);
  
    // 5-6. Halfmove clock and fullmove number
 -  ss >> std::skipws >> st->rule50 >> gamePly;
 +  if (sfen)
 +  {
 +      // Pieces in hand for SFEN
 +      int handCount = 1;
 +      while ((ss >> token) && !isspace(token))
 +      {
 +          if (token == '-')
 +              continue;
 +          else if (isdigit(token))
 +          {
 +              handCount = token - '0';
 +              while (isdigit(ss.peek()) && ss >> token)
 +                  handCount = 10 * handCount + (token - '0');
 +          }
 +          else if ((idx = piece_to_char().find(token)) != string::npos)
 +          {
 +              for (int i = 0; i < handCount; i++)
 +                  add_to_hand(Piece(idx));
 +              handCount = 1;
 +          }
 +      }
 +      // Move count is in ply for SFEN
 +      ss >> std::skipws >> gamePly;
 +      gamePly = std::max(gamePly - 1, 0);
 +  }
 +  else
 +  {
 +      ss >> std::skipws >> st->rule50 >> gamePly;
  
 -  // Convert from fullmove starting from 1 to gamePly starting from 0,
 -  // handle also common incorrect FEN with fullmove = 0.
 -  gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == BLACK);
 +      // Convert from fullmove starting from 1 to gamePly starting from 0,
 +      // handle also common incorrect FEN with fullmove = 0.
 +      gamePly = std::max(2 * (gamePly - 1), 0) + (sideToMove == BLACK);
 +  }
 +
 +  // counting rules
 +  if (st->countingLimit && st->rule50)
 +  {
 +      st->countingPly = st->rule50;
 +      st->rule50 = 0;
 +  }
  
 -  chess960 = isChess960;
 +  chess960 = isChess960 || v->chess960;
    thisThread = th;
    set_state(st);
  
diff --cc src/search.cpp
Simple merge
Simple merge