From: Fabian Fichter Date: Thu, 29 Oct 2020 10:42:31 +0000 (+0100) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=a7aadda0bdf8c31b63c553f2c2751efeee3f8c91;p=fairystockfish.git Merge official-stockfish/master bench: 4282417 --- a7aadda0bdf8c31b63c553f2c2751efeee3f8c91 diff --cc src/evaluate.cpp index f8c6030,030d101..3488c35 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -225,9 -221,13 +225,15 @@@ namespace S( 74,147), S( 76,149), S( 90,153), S(104,169), S(105,171), S(106,171), S(112,178), S(114,185), S(114,187), S(119,221) } }; + constexpr Score MaxMobility = S(150, 200); + constexpr Score DropMobility = S(10, 10); + // BishopPawns[distance from edge] contains a file-dependent penalty for pawns on + // squares of the same color as our bishop. + constexpr Score BishopPawns[int(FILE_NB) / 2] = { + S(3, 8), S(3, 9), S(1, 8), S(3, 7) + }; + // KingProtector[knight/bishop] contains penalty for each distance unit to own king constexpr Score KingProtector[] = { S(8, 9), S(6, 9) }; @@@ -1315,8 -910,8 +1320,8 @@@ sf = 37 + 3 * (pos.count(WHITE) == 1 ? pos.count(BLACK) + pos.count(BLACK) : pos.count(WHITE) + pos.count(WHITE)); else - sf = std::min(sf, 36 + 7 * pos.count(strongSide)) - 4 * !pawnsOnBothFlanks; + sf = std::min(sf, 36 + 7 * (pos.count(strongSide) + pos.count(strongSide))) - 4 * !pawnsOnBothFlanks; - + sf -= 4 * !pawnsOnBothFlanks; } diff --cc src/position.cpp index 7ae6617,b707293..08852b2 --- a/src/position.cpp +++ b/src/position.cpp @@@ -306,157 -218,69 +306,159 @@@ 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 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')); + + // 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); + } - chess960 = isChess960; + // counting rules + if (st->countingLimit && st->rule50) + { + st->countingPly = st->rule50; + st->rule50 = 0; + } + + chess960 = isChess960 || v->chess960; thisThread = th; set_state(st); + st->accumulator.state[WHITE] = Eval::NNUE::INIT; + st->accumulator.state[BLACK] = Eval::NNUE::INIT; assert(pos_is_ok()); @@@ -1205,11 -703,10 +1207,12 @@@ void Position::do_move(Move m, StateInf ++gamePly; ++st->rule50; ++st->pliesFromNull; + if (st->countingLimit) + ++st->countingPly; // Used by NNUE - st->accumulator.computed_accumulation = false; + st->accumulator.state[WHITE] = Eval::NNUE::EMPTY; + st->accumulator.state[BLACK] = Eval::NNUE::EMPTY; auto& dp = st->dirtyPiece; dp.dirty_num = 1;