Value npm = std::max(EndgameLimit, std::min(npm_w + npm_b, MidgameLimit));
// Map total non-pawn material into [PHASE_ENDGAME, PHASE_MIDGAME]
- e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
-
- // Let's look if we have a specialized evaluation function for this particular
- // material configuration. Firstly we look for a fixed configuration one, then
- // for a generic one if the previous search failed.
- if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
- return e;
-
- for (Color c = WHITE; c <= BLACK; ++c)
- if (is_KXK(pos, c))
- {
- e->evaluationFunction = &EvaluateKXK[c];
- return e;
- }
-
- // OK, we didn't find any special evaluation function for the current material
- // configuration. Is there a suitable specialized scaling function?
- const EndgameBase<ScaleFactor>* sf;
-
- if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
+ if (pos.captures_to_hand())
{
- e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
- return e;
+ npm = VALUE_ZERO;
+ for (PieceType pt : pos.piece_types())
+ npm += (pos.count_in_hand(WHITE, pt) + pos.count_in_hand(BLACK, pt)) * PieceValue[MG][make_piece(WHITE, pt)];
+ e->gamePhase = Phase(PHASE_MIDGAME * (MidgameLimit - std::min(npm, MidgameLimit)) / MidgameLimit);
}
-
- // We didn't find any specialized scaling function, so fall back on generic
- // ones that refer to more than one material distribution. Note that in this
- // case we don't return after setting the function.
- for (Color c = WHITE; c <= BLACK; ++c)
+ else
+ e->gamePhase = Phase(((npm - EndgameLimit) * PHASE_MIDGAME) / (MidgameLimit - EndgameLimit));
+
+#ifdef LARGEBOARDS
+ // Disable endgame evaluation until it works independent of board size
+ if (false)
+#else
+ if (pos.endgame_eval())
+#endif
{
- if (is_KBPsK(pos, c))
- e->scalingFunction[c] = &ScaleKBPsK[c];
-
- else if (is_KQKRPs(pos, c))
- e->scalingFunction[c] = &ScaleKQKRPs[c];
- }
+ // Let's look if we have a specialized evaluation function for this particular
+ // material configuration. Firstly we look for a fixed configuration one, then
+ // for a generic one if the previous search failed.
+ if ((e->evaluationFunction = pos.this_thread()->endgames.probe<Value>(key)) != nullptr)
+ return e;
- if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
- {
- if (!pos.count<PAWN>(BLACK))
+ for (Color c = WHITE; c <= BLACK; ++c)
+ if (is_KFsPsK(pos, c))
+ {
+ e->evaluationFunction = &EvaluateKFsPsK[c];
+ return e;
+ }
+
+ for (Color c = WHITE; c <= BLACK; ++c)
+ if (is_KXK(pos, c))
+ {
+ e->evaluationFunction = &EvaluateKXK[c];
+ return e;
+ }
+
+ // OK, we didn't find any special evaluation function for the current material
+ // configuration. Is there a suitable specialized scaling function?
- EndgameBase<ScaleFactor>* sf;
++ const EndgameBase<ScaleFactor>* sf;
+
+ if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
{
- assert(pos.count<PAWN>(WHITE) >= 2);
-
- e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
+ e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
+ return e;
}
- else if (!pos.count<PAWN>(WHITE))
+
+ // We didn't find any specialized scaling function, so fall back on generic
+ // ones that refer to more than one material distribution. Note that in this
+ // case we don't return after setting the function.
+ for (Color c = WHITE; c <= BLACK; ++c)
{
- assert(pos.count<PAWN>(BLACK) >= 2);
+ if (is_KBPsK(pos, c))
+ e->scalingFunction[c] = &ScaleKBPsK[c];
- e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
+ else if (is_KQKRPs(pos, c))
+ e->scalingFunction[c] = &ScaleKQKRPs[c];
}
- else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
+
+ if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
{
- // This is a special case because we set scaling functions
- // for both colors instead of only one.
- e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
- e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
+ if (!pos.count<PAWN>(BLACK))
+ {
+ assert(pos.count<PAWN>(WHITE) >= 2);
+
+ e->scalingFunction[WHITE] = &ScaleKPsK[WHITE];
+ }
+ else if (!pos.count<PAWN>(WHITE))
+ {
+ assert(pos.count<PAWN>(BLACK) >= 2);
+
+ e->scalingFunction[BLACK] = &ScaleKPsK[BLACK];
+ }
+ else if (pos.count<PAWN>(WHITE) == 1 && pos.count<PAWN>(BLACK) == 1)
+ {
+ // This is a special case because we set scaling functions
+ // for both colors instead of only one.
+ e->scalingFunction[WHITE] = &ScaleKPKP[WHITE];
+ e->scalingFunction[BLACK] = &ScaleKPKP[BLACK];
+ }
}
- }
- // Zero or just one pawn makes it difficult to win, even with a small material
- // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
- // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
- if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
- e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
- npm_b <= BishopValueMg ? 4 : 14);
+ // Zero or just one pawn makes it difficult to win, even with a small material
+ // advantage. This catches some trivial draws like KK, KBK and KNK and gives a
+ // drawish scale factor for cases such as KRKBP and KmmKm (except for KBBKN).
+ if (!pos.count<PAWN>(WHITE) && npm_w - npm_b <= BishopValueMg)
+ e->factor[WHITE] = uint8_t(npm_w < RookValueMg ? SCALE_FACTOR_DRAW :
+ npm_b <= BishopValueMg ? 4 : 14);
- if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
- e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
- npm_w <= BishopValueMg ? 4 : 14);
+ if (!pos.count<PAWN>(BLACK) && npm_b - npm_w <= BishopValueMg)
+ e->factor[BLACK] = uint8_t(npm_b < RookValueMg ? SCALE_FACTOR_DRAW :
+ npm_w <= BishopValueMg ? 4 : 14);
+ }
// Evaluate the material imbalance. We use PIECE_TYPE_NONE as a place holder
// for the bishop pair "extended piece", which allows us to be more flexible