namespace {
// Threshold for lazy and space evaluation
- constexpr Value LazyThreshold1 = Value(1400);
- constexpr Value LazyThreshold2 = Value(1300);
- constexpr Value SpaceThreshold = Value(12222);
- constexpr Value NNUEThreshold1 = Value(550);
- constexpr Value NNUEThreshold2 = Value(150);
+ constexpr Value LazyThreshold1 = Value(1565);
+ constexpr Value LazyThreshold2 = Value(1102);
+ constexpr Value SpaceThreshold = Value(11551);
+ constexpr Value NNUEThreshold1 = Value(682);
+ constexpr Value NNUEThreshold2 = Value(176);
// KingAttackWeights[PieceType] contains king attack weights by piece type
- constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10 };
+ constexpr int KingAttackWeights[PIECE_TYPE_NB] = { 0, 0, 81, 52, 44, 10, 40 };
// SafeCheck[PieceType][single/multiple] contains safe check bonus by piece type,
// higher if multiple safe checks are possible for that piece type.
// If there is PSQ imbalance use classical eval, with small probability if it is small
Value psq = Value(abs(eg_value(pos.psq_score())));
int r50 = 16 + pos.rule50_count();
- bool largePsq = psq * 16 > (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50;
- bool classical = largePsq || (psq > PawnValueMg / 4 && !(pos.this_thread()->nodes & 0xB));
+ bool pure = pos.capture_the_flag_piece() && pos.checking_permitted();
+ bool largePsq = psq * 16 > (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50 && !pure;
+ bool classical = largePsq || (psq > PawnValueMg / 4 && !(pos.this_thread()->nodes & 0xB) && !pure);
- v = classical ? Evaluation<NO_TRACE>(pos).value() : adjusted_NNUE();
+ bool strongClassical = pos.non_pawn_material() < 2 * RookValueMg && pos.count<PAWN>() < 2;
+
+ v = classical || strongClassical ? Evaluation<NO_TRACE>(pos).value() : adjusted_NNUE();
// If the classical eval is small and imbalance large, use NNUE nevertheless.
// For the case of opposite colored bishops, switch to NNUE eval with
score -= Doubled * doubled
+ WeakLever * more_than_one(lever);
- if (blocked && r > RANK_4)
- score += BlockedPawn[r-4];
+ if (blocked && r >= RANK_5)
+ score += BlockedPawn[r - RANK_5];
}
+ // 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;
}
&& (ss-1)->statScore < 22977
&& eval >= beta
&& eval >= ss->staticEval
- && ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 182 + 200 * (!pos.double_step_enabled() && pos.piece_to_char()[PAWN] != ' ')
- && ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 168
++ && ss->staticEval >= beta - 30 * depth - 28 * improving + 84 * ss->ttPv + 168 + 200 * (!pos.double_step_enabled() && pos.piece_to_char()[PAWN] != ' ')
&& !excludedMove
&& pos.non_pawn_material(us)
+ && pos.count<ALL_PIECES>(~us) != pos.count<PAWN>(~us)
+ && !pos.flip_enclosed_pieces()
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
{
assert(eval - beta >= 0);
// Null move dynamic reduction based on depth and value
- Depth R = (982 - 200 * pos.must_capture() - 150 * !pos.checking_permitted() + 85 * depth) / 256 + std::min(int(eval - beta) / 192, 3);
- Depth R = (1015 + 85 * depth) / 256 + std::min(int(eval - beta) / 191, 3);
++ Depth R = (1015 - 200 * pos.must_capture() - 150 * !pos.checking_permitted() + 85 * depth) / 256 + std::min(int(eval - beta) / 191, 3);
ss->currentMove = MOVE_NULL;
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
}
}
- probCutBeta = beta + (176 + 20 * !!pos.capture_the_flag_piece()) * (1 + pos.check_counting() + (pos.extinction_value() != VALUE_NONE)) - 49 * improving;
- probCutBeta = beta + 183 - 49 * improving;
++ probCutBeta = beta + (183 + 20 * !!pos.capture_the_flag_piece()) * (1 + pos.check_counting() + (pos.extinction_value() != VALUE_NONE)) - 49 * improving;
// Step 10. ProbCut (~10 Elo)
// If we have a good enough capture and a reduced search returns a value
// Futility pruning: parent node (~5 Elo)
if ( lmrDepth < 7
&& !ss->inCheck
- && ss->staticEval + 266 + 170 * lmrDepth <= alpha
- && (*contHist[0])[movedPiece][to_sq(move)]
- + (*contHist[1])[movedPiece][to_sq(move)]
- + (*contHist[3])[movedPiece][to_sq(move)]
- + (*contHist[5])[movedPiece][to_sq(move)] / 2 < 27376)
+ && !( pos.extinction_value() == -VALUE_MATE
+ && pos.extinction_piece_types().find(ALL_PIECES) == pos.extinction_piece_types().end())
- && ss->staticEval + (283 + 170 * lmrDepth) * (1 + pos.check_counting()) <= alpha
++ && ss->staticEval + (266 + 170 * 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)]
+ + (*contHist[5])[history_slot(movedPiece)][to_sq(move)] / 2 < 27376)
continue;
// Prune moves with negative SEE (~20 Elo)
- if (!pos.see_ge(move, Value(-(29 - std::min(lmrDepth, 18) + 10 * !!pos.capture_the_flag_piece()) * lmrDepth * lmrDepth)))
- if (!pos.see_ge(move, Value(-(30 - std::min(lmrDepth, 18)) * lmrDepth * lmrDepth)))
++ if (!pos.see_ge(move, Value(-(30 - std::min(lmrDepth, 18) + 10 * !!pos.capture_the_flag_piece()) * lmrDepth * lmrDepth)))
continue;
}
- else
+ else if (!pos.must_capture())
{
// Capture history based pruning when the move doesn't give check
if ( !givesCheck
&& captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] < 0)
continue;
- // See based pruning
- if (!pos.see_ge(move, Value(-221 - 120 * pos.captures_to_hand()) * depth)) // (~25 Elo)
+ // SEE based pruning
- if (!pos.see_ge(move, Value(-213) * depth)) // (~25 Elo)
++ if (!pos.see_ge(move, Value(-213 - 120 * pos.captures_to_hand()) * depth)) // (~25 Elo)
continue;
}
}
|| moveCountPruning
|| ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha
|| cutNode
- || thisThread->ttHitAverage < 427 * TtHitAverageResolution * TtHitAverageWindow / 1024)
- || thisThread->ttHitAverage < 432 * TtHitAverageResolution * TtHitAverageWindow / 1024))
++ || thisThread->ttHitAverage < 432 * TtHitAverageResolution * TtHitAverageWindow / 1024)
+ && !(pos.must_capture() && (givesCheck || pos.has_capture())))
{
Depth r = reduction(improving, depth, moveCount);