From: Fabian Fichter Date: Sun, 9 Aug 2020 10:35:44 +0000 (+0200) Subject: Merge official-stockfish/master X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=fa6adbaf7b68e50bb9c113d3f73dc4fddfcb4aa5;p=fairystockfish.git Merge official-stockfish/master bench: 4542650 --- fa6adbaf7b68e50bb9c113d3f73dc4fddfcb4aa5 diff --cc src/evaluate.cpp index d0b7c2b,cbcebd0..ccb8de7 --- a/src/evaluate.cpp +++ b/src/evaluate.cpp @@@ -489,77 -396,44 +489,78 @@@ namespace b1 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); b2 = attacks_bb(ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)); - // Enemy rooks checks - rookChecks = b1 & safe & attackedBy[Them][ROOK]; - if (rookChecks) - kingDanger += more_than_one(rookChecks) ? RookSafeCheck * 3/2 - : RookSafeCheck; - else - unsafeChecks |= b1 & attackedBy[Them][ROOK]; - - // Enemy queen safe checks: we count them only if they are from squares from - // which we can't give a rook check, because rook checks are more valuable. - queenChecks = (b1 | b2) - & attackedBy[Them][QUEEN] - & safe - & ~attackedBy[Us][QUEEN] - & ~rookChecks; - if (queenChecks) - kingDanger += more_than_one(queenChecks) ? QueenSafeCheck * 3/2 - : QueenSafeCheck; - - // Enemy bishops checks: we count them only if they are from squares from - // which we can't give a queen check, because queen checks are more valuable. - bishopChecks = b2 - & attackedBy[Them][BISHOP] - & safe - & ~queenChecks; - if (bishopChecks) - kingDanger += more_than_one(bishopChecks) ? BishopSafeCheck * 3/2 - : BishopSafeCheck; - else - unsafeChecks |= b2 & attackedBy[Them][BISHOP]; + std::function get_attacks = [this](Color c, PieceType pt) { + return attackedBy[c][pt] | (pos.piece_drops() && pos.count_in_hand(c, pt) ? pos.drop_region(c, pt) & ~pos.pieces() : Bitboard(0)); + }; + for (PieceType pt : pos.piece_types()) + { + switch (pt) + { + case QUEEN: + // Enemy queen safe checks: we count them only if they are from squares from + // which we can't give a rook check, because rook checks are more valuable. + queenChecks = (b1 | b2) + & get_attacks(Them, QUEEN) + & pos.board_bb() + & safe + & ~attackedBy[Us][QUEEN] + & ~(b1 & attackedBy[Them][ROOK]); + + if (queenChecks) - kingDanger += QueenSafeCheck; ++ kingDanger += more_than_one(queenChecks) ? QueenSafeCheck * 3/2 ++ : QueenSafeCheck; + break; + case ROOK: + case BISHOP: + case KNIGHT: + knightChecks = attacks_bb(Us, pt, ksq, pos.pieces() ^ pos.pieces(Us, QUEEN)) & get_attacks(Them, pt) & pos.board_bb(); + if (knightChecks & safe) - kingDanger += pt == ROOK ? RookSafeCheck ++ kingDanger += (pt == ROOK ? RookSafeCheck + : pt == BISHOP ? BishopSafeCheck - : KnightSafeCheck; ++ : KnightSafeCheck) * (more_than_one(knightChecks & safe) ? 3 : 2) / 2; + else + unsafeChecks |= knightChecks; + break; + case PAWN: + if (pos.piece_drops() && pos.count_in_hand(Them, pt)) + { + pawnChecks = attacks_bb(Us, pt, ksq, pos.pieces()) & ~pos.pieces() & pos.board_bb(); + if (pawnChecks & safe) + kingDanger += OtherSafeCheck; + else + unsafeChecks |= pawnChecks; + } + break; + case SHOGI_PAWN: + case KING: + break; + default: + otherChecks = attacks_bb(Us, pt, ksq, pos.pieces()) & get_attacks(Them, pt) & pos.board_bb(); + if (otherChecks & safe) - kingDanger += OtherSafeCheck; ++ kingDanger += OtherSafeCheck * (more_than_one(otherChecks & safe) ? 3 : 2) / 2; + else + unsafeChecks |= otherChecks; + } + } - // Enemy knights checks - knightChecks = pos.attacks_from(ksq) & attackedBy[Them][KNIGHT]; - if (knightChecks & safe) - kingDanger += more_than_one(knightChecks & safe) ? KnightSafeCheck * 3/2 - : KnightSafeCheck; - else - unsafeChecks |= knightChecks; + // Virtual piece drops + if (pos.two_boards() && pos.piece_drops()) + { + for (PieceType pt : pos.piece_types()) + if (!pos.count_in_hand(Them, pt) && (attacks_bb(Us, pt, ksq, pos.pieces()) & safe & pos.drop_region(Them, pt) & ~pos.pieces())) + { + kingDanger += OtherSafeCheck * 500 / (500 + PieceValue[MG][pt]); + // Presumably a mate threat + if (!(attackedBy[Us][KING] & ~(attackedBy[Them][ALL_PIECES] | pos.pieces(Us)))) + kingDanger += 2000; + } + } + + if (pos.check_counting()) + kingDanger += kingDanger * 7 / (3 + pos.checks_remaining(Them)); + + Square s = file_of(ksq) == FILE_A ? ksq + EAST : file_of(ksq) == pos.max_file() ? ksq + WEST : ksq; + Bitboard kingFlank = pos.max_file() == FILE_H ? KingFlank[file_of(ksq)] : file_bb(s) | adjacent_files_bb(s); // Find the squares that opponent attacks in our king flank, the squares // which they attack twice in that flank, and the squares that we defend. @@@ -1117,13 -759,18 +1118,18 @@@ int sf = me->scale_factor(pos, strongSide); // If scale is not already specific, scale down the endgame via general heuristics - if (sf == SCALE_FACTOR_NORMAL) + if (sf == SCALE_FACTOR_NORMAL && !pos.captures_to_hand()) { - if ( pos.opposite_bishops() - && pos.non_pawn_material() == 2 * BishopValueMg) - sf = 22; + if (pos.opposite_bishops()) + { + if ( pos.non_pawn_material(WHITE) == BishopValueMg + && pos.non_pawn_material(BLACK) == BishopValueMg) + sf = 22; + else + sf = 22 + 3 * pos.count(strongSide); + } else - sf = std::min(sf, 36 + (pos.opposite_bishops() ? 2 : 7) * (pos.count(strongSide) + pos.count(strongSide))); - sf = std::min(sf, 36 + 7 * pos.count(strongSide)); ++ sf = std::min(sf, 36 + 7 * (pos.count(strongSide) + pos.count(strongSide))); sf = std::max(0, sf - (pos.rule50_count() - 12) / 4); } diff --cc src/pawns.cpp index 607a6eb,066146e..95c1681 --- a/src/pawns.cpp +++ b/src/pawns.cpp @@@ -268,9 -244,9 +268,9 @@@ Score Entry::do_king_safety(const Posit // In endgame we like to bring our king near our closest pawn Bitboard pawns = pos.pieces(Us, PAWN); - int minPawnDist = pawns ? 8 : 0; + int minPawnDist = 6; - if (pawns & PseudoAttacks[KING][ksq]) + if (pawns & PseudoAttacks[Us][KING][ksq]) minPawnDist = 1; else while (pawns) minPawnDist = std::min(minPawnDist, distance(ksq, pop_lsb(&pawns))); diff --cc src/search.cpp index 3c0d185,55c520a..81ac978 --- a/src/search.cpp +++ b/src/search.cpp @@@ -708,14 -650,11 +708,14 @@@ namespace if (!rootNode) { + Value variantResult; + if (pos.is_game_end(variantResult, ss->ply)) + return variantResult; + // Step 2. Check for aborted search and immediate draw if ( Threads.stop.load(std::memory_order_relaxed) - || pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !inCheck) ? evaluate(pos) + return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : value_draw(pos.this_thread()); // Step 3. Mate distance pruning. Even if we mate at the next move our score @@@ -995,9 -920,9 +994,9 @@@ probCutCount++; ss->currentMove = move; - ss->continuationHistory = &thisThread->continuationHistory[inCheck] + ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] [captureOrPromotion] - [pos.moved_piece(move)] + [history_slot(pos.moved_piece(move))] [to_sq(move)]; pos.do_move(move, st); @@@ -1107,13 -1030,11 +1106,13 @@@ moves_loop: // When in check, search st // Futility pruning: parent node (~5 Elo) if ( lmrDepth < 6 - && !inCheck + && !ss->inCheck - && ss->staticEval + 235 + 172 * lmrDepth <= alpha - && (*contHist[0])[movedPiece][to_sq(move)] - + (*contHist[1])[movedPiece][to_sq(move)] - + (*contHist[3])[movedPiece][to_sq(move)] < 27400) + && !( pos.extinction_value() == -VALUE_MATE + && pos.extinction_piece_types().find(ALL_PIECES) == pos.extinction_piece_types().end()) + && ss->staticEval + (235 + 172 * lmrDepth) * (1 + pos.check_counting()) <= alpha + && (*contHist[0])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[1])[history_slot(movedPiece)][to_sq(move)] + + (*contHist[3])[history_slot(movedPiece)][to_sq(move)] < 27400) continue; // Prune moves with negative SEE (~20 Elo) @@@ -1128,8 -1049,15 +1127,15 @@@ && captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0) continue; + // Futility pruning for captures + if ( !givesCheck + && lmrDepth < 6 + && !ss->inCheck + && ss->staticEval + 270 + 384 * lmrDepth + PieceValue[MG][type_of(pos.piece_on(to_sq(move)))] <= alpha) + continue; + // See based pruning - if (!pos.see_ge(move, Value(-194) * depth)) // (~25 Elo) + if (!pos.see_ge(move, Value(-194 - 120 * pos.captures_to_hand()) * depth)) // (~25 Elo) continue; } } @@@ -1219,9 -1153,9 +1237,9 @@@ // Update the current move (this must be done after singular extension search) ss->currentMove = move; - ss->continuationHistory = &thisThread->continuationHistory[inCheck] + ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] [captureOrPromotion] - [movedPiece] + [history_slot(movedPiece)] [to_sq(move)]; // Step 15. Make the move @@@ -1443,7 -1376,7 +1461,7 @@@ if (!moveCount) bestValue = excludedMove ? alpha - : inCheck ? pos.checkmate_value(ss->ply) : pos.stalemate_value(ss->ply); - : ss->inCheck ? mated_in(ss->ply) : VALUE_DRAW; ++ : ss->inCheck ? pos.checkmate_value(ss->ply) : pos.stalemate_value(ss->ply); else if (bestMove) update_all_stats(pos, ss, bestMove, bestValue, beta, prevSq, @@@ -1500,16 -1433,13 +1518,16 @@@ Thread* thisThread = pos.this_thread(); (ss+1)->ply = ss->ply + 1; bestMove = MOVE_NONE; - inCheck = pos.checkers(); + ss->inCheck = pos.checkers(); moveCount = 0; - // Check for an immediate draw or maximum ply reached - if ( pos.is_draw(ss->ply) - || ss->ply >= MAX_PLY) - return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : VALUE_DRAW; + Value gameResult; + if (pos.is_game_end(gameResult, ss->ply)) + return gameResult; + + // Check for maximum ply reached + if (ss->ply >= MAX_PLY) - return !inCheck ? evaluate(pos) : VALUE_DRAW; ++ return !ss->inCheck ? evaluate(pos) : VALUE_DRAW; assert(0 <= ss->ply && ss->ply < MAX_PLY); @@@ -1597,11 -1527,8 +1615,11 @@@ moveCount++; // Futility pruning - if ( !inCheck + if ( !ss->inCheck && !givesCheck + && !( pos.extinction_value() == -VALUE_MATE + && pos.piece_on(to_sq(move)) + && pos.extinction_piece_types().find(type_of(pos.piece_on(to_sq(move)))) != pos.extinction_piece_types().end()) && futilityBase > -VALUE_KNOWN_WIN && !pos.advanced_pawn_push(move)) { @@@ -1637,9 -1564,9 +1655,9 @@@ } ss->currentMove = move; - ss->continuationHistory = &thisThread->continuationHistory[inCheck] + ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck] [captureOrPromotion] - [pos.moved_piece(move)] + [history_slot(pos.moved_piece(move))] [to_sq(move)]; // Make and search the move @@@ -1671,8 -1598,8 +1689,8 @@@ // All legal moves have been searched. A special case: If we're in check // and no legal moves were found, it is checkmate. - if (inCheck && bestValue == -VALUE_INFINITE) + if (ss->inCheck && bestValue == -VALUE_INFINITE) - return mated_in(ss->ply); // Plies to mate from the root + return pos.checkmate_value(ss->ply); // Plies to mate from the root tte->save(posKey, value_to_tt(bestValue, ss->ply), pvHit, bestValue >= beta ? BOUND_LOWER : @@@ -1790,8 -1717,12 +1808,12 @@@ void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) { for (int i : {1, 2, 4, 6}) + { + if (ss->inCheck && i > 2) + break; if (is_ok((ss-i)->currentMove)) - (*(ss-i)->continuationHistory)[pc][to] << bonus; + (*(ss-i)->continuationHistory)[history_slot(pc)][to] << bonus; + } }