- // Scale and shift NNUE for compatibility with search and classical evaluation
- auto adjusted_NNUE = [&]()
- {
-
- int scale = 903 + 28 * pos.count<PAWN>() + 28 * pos.non_pawn_material() / 1024;
-
- Value nnue = NNUE::evaluate(pos, true) * scale / 1024;
-
- if (pos.is_chess960())
- nnue += fix_FRC(pos);
-
- return nnue;
- };
-
- // If there is PSQ imbalance we use the classical eval. We also introduce
- // a small probability of using the classical eval when PSQ imbalance 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;
-
- // Use classical evaluation for really low piece endgames.
- // One critical case is the draw for bishop + A/H file pawn vs naked king.
- bool lowPieceEndgame = pos.non_pawn_material() == BishopValueMg
- || (pos.non_pawn_material() < 2 * RookValueMg && pos.count<PAWN>() < 2);
-
- v = classical || lowPieceEndgame ? 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 small
- // probability if the classical eval is less than the threshold.
- if ( largePsq
- && !lowPieceEndgame
- && ( abs(v) * 16 < NNUEThreshold2 * r50
- || ( pos.opposite_bishops()
- && abs(v) * 16 < (NNUEThreshold1 + pos.non_pawn_material() / 64) * r50)))
- v = adjusted_NNUE();
+ int nnueComplexity;
+ int npm = pos.non_pawn_material() / 64;
+
+ Color stm = pos.side_to_move();
+ Value optimism = pos.this_thread()->optimism[stm];
+
+ Value nnue = NNUE::evaluate(pos, true, &nnueComplexity);
+
+ // Blend nnue complexity with (semi)classical complexity
+ nnueComplexity = ( 397 * nnueComplexity
+ + 477 * abs(psq - nnue)
+ ) / 1024;
+
+ optimism += optimism * nnueComplexity / 256;
+ v = (nnue * (945 + npm) + optimism * (174 + npm)) / 1024;