From: Fabian Fichter Date: Sun, 20 Sep 2020 11:17:16 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=db1112840a6d6928147dddae494e09b766bb3d48;p=fairystockfish.git Merge official-stockfish/master bench: 4629236 --- db1112840a6d6928147dddae494e09b766bb3d48 diff --cc src/pawns.cpp index 232dd14,7f8d451..663f81e --- a/src/pawns.cpp +++ b/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) }; @@@ -144,12 -146,10 +147,12 @@@ 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(Us) > popcount(pos.board_bb()) / 4) + v = popcount(support | phalanx) * 50 / (opposed ? 2 : 1); score += make_score(v, v * (r - 2) / 4); } @@@ -172,28 -172,11 +175,31 @@@ 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(Us) == pos.count(Us)) + score = score * 2; + + const Square* pl_shogi = pos.squares(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; } diff --cc src/position.cpp index d7e694b,396bff5..d742d33 --- a/src/position.cpp +++ b/src/position.cpp @@@ -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(c) ? square(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);