From: Fabian Fichter Date: Sat, 19 Sep 2020 12:49:12 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=278727bdc2db61b322ad057df5818191124a1076;p=fairystockfish.git Merge official-stockfish/master bench: 4665603 --- 278727bdc2db61b322ad057df5818191124a1076 diff --cc src/evaluate.cpp index 9b1c26a,615df1b..0205361 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -1154,8 -781,18 +1153,18 @@@ namespace else sf = 22 + 3 * pos.count(strongSide); } + else if ( pos.non_pawn_material(WHITE) == RookValueMg + && pos.non_pawn_material(BLACK) == RookValueMg + && !pe->passed_pawns(strongSide) + && pos.count(strongSide) - pos.count(~strongSide) <= 1 + && bool(KingSide & pos.pieces(strongSide, PAWN)) != bool(QueenSide & pos.pieces(strongSide, PAWN)) + && (attacks_bb(pos.square(~strongSide)) & pos.pieces(~strongSide, PAWN))) + sf = 36; + else if (pos.count() == 1) + 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)); + sf = std::min(sf, 36 + 7 * (pos.count(strongSide) + pos.count(strongSide))); } // Interpolate between the middlegame and (scaled by 'sf') endgame score diff --cc src/position.cpp index dc58e08,6ef7aed..d7e694b --- a/src/position.cpp +++ b/src/position.cpp @@@ -1309,79 -770,15 +1301,79 @@@ void Position::do_move(Move m, StateInf } // Update castling rights if needed - if (st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to])) + if (type_of(m) != DROP && st->castlingRights && (castlingRightsMask[from] | castlingRightsMask[to])) { - int cr = castlingRightsMask[from] | castlingRightsMask[to]; - k ^= Zobrist::castling[st->castlingRights & cr]; - st->castlingRights &= ~cr; + k ^= Zobrist::castling[st->castlingRights]; + st->castlingRights &= ~(castlingRightsMask[from] | castlingRightsMask[to]); + k ^= Zobrist::castling[st->castlingRights]; } + // Flip enclosed pieces + st->flippedPieces = 0; + if (flip_enclosed_pieces() && !is_pass(m)) + { + // Find end of rows to be flipped + if (flip_enclosed_pieces() == REVERSI) + { + Bitboard b = attacks_bb(us, QUEEN, to, board_bb() & ~pieces(~us)) & ~PseudoAttacks[us][KING][to] & pieces(us); + while(b) + st->flippedPieces |= between_bb(to, pop_lsb(&b)); + } + else + { + assert(flip_enclosed_pieces() == ATAXX); + st->flippedPieces = PseudoAttacks[us][KING][to] & pieces(~us); + } + + // Flip pieces + Bitboard to_flip = st->flippedPieces; + while(to_flip) + { + Square s = pop_lsb(&to_flip); + Piece flipped = piece_on(s); + Piece resulting = ~flipped; + + // remove opponent's piece + remove_piece(s); + k ^= Zobrist::psq[flipped][s]; + st->materialKey ^= Zobrist::psq[flipped][pieceCount[flipped]]; + st->nonPawnMaterial[them] -= PieceValue[MG][flipped]; + + // add our piece + put_piece(resulting, s); + k ^= Zobrist::psq[resulting][s]; + st->materialKey ^= Zobrist::psq[resulting][pieceCount[resulting]-1]; + st->nonPawnMaterial[us] += PieceValue[MG][resulting]; + } + } + // Move the piece. The tricky Chess960 castling is handled earlier - if (type_of(m) != CASTLING) + if (type_of(m) == DROP) + { + drop_piece(make_piece(us, in_hand_piece_type(m)), pc, to); + st->materialKey ^= Zobrist::psq[pc][pieceCount[pc]-1]; + if (type_of(pc) != PAWN) + st->nonPawnMaterial[us] += PieceValue[MG][pc]; + // Set castling rights for dropped king or rook + if (castling_dropped_piece() && rank_of(to) == castling_rank(us)) + { + if (type_of(pc) == KING && file_of(to) == FILE_E) + { + Bitboard castling_rooks = pieces(us, castling_rook_piece()) + & rank_bb(castling_rank(us)) + & (file_bb(FILE_A) | file_bb(max_file())); + while (castling_rooks) + set_castling_right(us, pop_lsb(&castling_rooks)); + } + else if (type_of(pc) == castling_rook_piece()) + { + if ( (file_of(to) == FILE_A || file_of(to) == max_file()) + && piece_on(make_square(FILE_E, castling_rank(us))) == make_piece(us, KING)) + set_castling_right(us, to); + } + } + } + else if (type_of(m) != CASTLING) move_piece(from, to); // If the moving piece is a pawn do some special extra work diff --cc src/search.h index cd2c47f,3e855c8..a03ed60 --- a/src/search.h +++ b/src/search.h @@@ -91,10 -91,10 +91,10 @@@ struct LimitsType } bool use_time_management() const { - return !(mate | movetime | depth | nodes | perft | infinite); + return time[WHITE] || time[BLACK]; } - std::vector searchmoves; + std::vector searchmoves, banmoves; TimePoint time[COLOR_NB], inc[COLOR_NB], npmsec, movetime, startTime; int movestogo, depth, mate, perft, infinite; int64_t nodes; diff --cc src/types.h index 8d7c7d7,c159856..d127799 --- a/src/types.h +++ b/src/types.h @@@ -778,27 -447,19 +778,32 @@@ constexpr Move reverse_move(Move m) } template -constexpr Move make(Square from, Square to, PieceType pt = KNIGHT) { - return Move(T + ((pt - KNIGHT) << 12) + (from << 6) + to); +constexpr Move make_gating(Square from, Square to, PieceType pt, Square gate) { + return Move((gate << (2 * SQUARE_BITS + MOVE_TYPE_BITS + PIECE_TYPE_BITS)) + (pt << (2 * SQUARE_BITS + MOVE_TYPE_BITS)) + T + (from << SQUARE_BITS) + to); +} + +constexpr PieceType dropped_piece_type(Move m) { + return PieceType((m >> (2 * SQUARE_BITS + MOVE_TYPE_BITS)) & (PIECE_TYPE_NB - 1)); +} + +constexpr PieceType in_hand_piece_type(Move m) { + return PieceType((m >> (2 * SQUARE_BITS + MOVE_TYPE_BITS + PIECE_TYPE_BITS)) & (PIECE_TYPE_NB - 1)); +} + +inline bool is_ok(Move m) { + return from_sq(m) != to_sq(m) || type_of(m) == PROMOTION || type_of(m) == SPECIAL; // Catch MOVE_NULL and MOVE_NONE } -constexpr bool is_ok(Move m) { - return from_sq(m) != to_sq(m); // Catch MOVE_NULL and MOVE_NONE +inline int dist(Direction d) { + return std::abs(d % NORTH) < NORTH / 2 ? std::max(std::abs(d / NORTH), int(std::abs(d % NORTH))) + : std::max(std::abs(d / NORTH) + 1, int(NORTH - std::abs(d % NORTH))); } + /// Based on a congruential pseudo random number generator + constexpr Key make_key(uint64_t seed) { + return seed * 6364136223846793005ULL + 1442695040888963407ULL; + } + #endif // #ifndef TYPES_H_INCLUDED #include "tune.h" // Global visibility to tuning setup diff --cc src/uci.cpp index d3a891b,bb57c80..2232aa2 --- a/src/uci.cpp +++ b/src/uci.cpp @@@ -201,26 -183,28 +202,48 @@@ namespace << "\nNodes/second : " << 1000 * nodes / elapsed << endl; } + // The win rate model returns the probability (per mille) of winning given an eval + // and a game-ply. The model fits rather accurately the LTC fishtest statistics. + int win_rate_model(Value v, int ply) { + + // The model captures only up to 240 plies, so limit input (and rescale) + double m = std::min(240, ply) / 64.0; + + // Coefficients of a 3rd order polynomial fit based on fishtest data + // for two parameters needed to transform eval to the argument of a + // logistic function. + double as[] = {-8.24404295, 64.23892342, -95.73056462, 153.86478679}; + double bs[] = {-3.37154371, 28.44489198, -56.67657741, 72.05858751}; + double a = (((as[0] * m + as[1]) * m + as[2]) * m) + as[3]; + double b = (((bs[0] * m + bs[1]) * m + bs[2]) * m) + bs[3]; + + // Transform eval to centipawns with limited range + double x = Utility::clamp(double(100 * v) / PawnValueEg, -1000.0, 1000.0); + + // Return win rate in per mille (rounded to nearest) + return int(0.5 + 1000 / (1 + std::exp((a - x) / b))); + } + + // load() is called when engine receives the "load" command. + // The function reads variant configuration files. + + void load(istringstream& is) { + + string token; + while (is >> token) + Options["VariantPath"] = token; + } + + // check() is called when engine receives the "check" command. + // The function reads variant configuration files and validates them. + + void check(istringstream& is) { + + string token; + while (is >> token) + variants.parse(token); + } + } // namespace @@@ -342,36 -292,26 +365,52 @@@ string UCI::value(Value v) } + /// UCI::wdl() report WDL statistics given an evaluation and a game ply, based on + /// data gathered for fishtest LTC games. + + string UCI::wdl(Value v, int ply) { + + stringstream ss; + + int wdl_w = win_rate_model( v, ply); + int wdl_l = win_rate_model(-v, ply); + int wdl_d = 1000 - wdl_w - wdl_l; + ss << " wdl " << wdl_w << " " << wdl_d << " " << wdl_l; + + return ss.str(); + } + + /// UCI::square() converts a Square to a string in algebraic notation (g1, a7, etc.) -std::string UCI::square(Square s) { - return std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) }; +std::string UCI::square(const Position& pos, Square s) { +#ifdef LARGEBOARDS + if (Options["Protocol"] == "usi") + return rank_of(s) < RANK_10 ? std::string{ char('1' + pos.max_file() - file_of(s)), char('a' + pos.max_rank() - rank_of(s)) } + : std::string{ char('0' + (pos.max_file() - file_of(s) + 1) / 10), + char('0' + (pos.max_file() - file_of(s) + 1) % 10), + char('a' + pos.max_rank() - rank_of(s)) }; + else if ((Options["Protocol"] == "xboard" || Options["Protocol"] == "ucci") && pos.max_rank() == RANK_10) + return std::string{ char('a' + file_of(s)), char('0' + rank_of(s)) }; + else + return rank_of(s) < RANK_10 ? std::string{ char('a' + file_of(s)), char('1' + (rank_of(s) % 10)) } + : std::string{ char('a' + file_of(s)), char('0' + ((rank_of(s) + 1) / 10)), + char('0' + ((rank_of(s) + 1) % 10)) }; +#else + return Options["Protocol"] == "usi" ? std::string{ char('1' + pos.max_file() - file_of(s)), char('a' + pos.max_rank() - rank_of(s)) } + : std::string{ char('a' + file_of(s)), char('1' + rank_of(s)) }; +#endif +} + +/// UCI::dropped_piece() generates a piece label string from a Move. + +string UCI::dropped_piece(const Position& pos, Move m) { + assert(type_of(m) == DROP); + if (dropped_piece_type(m) == pos.promoted_piece_type(in_hand_piece_type(m))) + // Dropping as promoted piece + return std::string{'+', pos.piece_to_char()[in_hand_piece_type(m)]}; + else + return std::string{pos.piece_to_char()[dropped_piece_type(m)]}; } diff --cc src/uci.h index 73c672f,ad954d9..c95fa9f --- a/src/uci.h +++ b/src/uci.h @@@ -76,10 -70,10 +76,11 @@@ private void init(OptionsMap&); void loop(int argc, char* argv[]); std::string value(Value v); -std::string square(Square s); -std::string move(Move m, bool chess960); +std::string square(const Position& pos, Square s); +std::string dropped_piece(const Position& pos, Move m); +std::string move(const Position& pos, Move m); std::string pv(const Position& pos, Depth depth, Value alpha, Value beta); + std::string wdl(Value v, int ply); Move to_move(const Position& pos, std::string& str); } // namespace UCI