Use endgame evaluation only for moderate variants
authorianfab <ianfab@users.noreply.github.com>
Sun, 15 Jul 2018 10:20:42 +0000 (12:20 +0200)
committerianfab <ianfab@users.noreply.github.com>
Sun, 15 Jul 2018 10:20:42 +0000 (12:20 +0200)
Endgame evaluation functions and scaling factors are no longer applied
to games where they are not applicable, e.g., crazyhouse, giveaway, etc.

No functional change for standard chess.

src/material.cpp
src/position.h
src/variant.cpp
src/variant.h

index b18d29d..2585d47 100644 (file)
@@ -137,74 +137,77 @@ Entry* probe(const Position& pos) {
   // 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];
+  if (pos.endgame_eval())
+  {
+      // 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;
-      }
 
-  // OK, we didn't find any special evaluation function for the current material
-  // configuration. Is there a suitable specialized scaling function?
-  EndgameBase<ScaleFactor>* sf;
+      for (Color c = WHITE; c <= BLACK; ++c)
+          if (is_KXK(pos, c))
+          {
+              e->evaluationFunction = &EvaluateKXK[c];
+              return e;
+          }
 
-  if ((sf = pos.this_thread()->endgames.probe<ScaleFactor>(key)) != nullptr)
-  {
-      e->scalingFunction[sf->strongSide] = sf; // Only strong color assigned
-      return e;
-  }
-
-  // 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)
-  {
-    if (is_KBPsK(pos, c))
-        e->scalingFunction[c] = &ScaleKBPsK[c];
+      // OK, we didn't find any special evaluation function for the current material
+      // configuration. Is there a suitable specialized scaling function?
+      EndgameBase<ScaleFactor>* sf;
 
-    else if (is_KQKRPs(pos, c))
-        e->scalingFunction[c] = &ScaleKQKRPs[c];
-  }
-
-  if (npm_w + npm_b == VALUE_ZERO && pos.pieces(PAWN)) // Only pawns on the board
-  {
-      if (!pos.count<PAWN>(BLACK))
+      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
index 926c871..9adf7cd 100644 (file)
@@ -94,6 +94,7 @@ public:
   const std::string piece_to_char() const;
   Rank promotion_rank() const;
   const std::set<PieceType, std::greater<PieceType> >& promotion_piece_types() const;
+  bool endgame_eval() const;
   bool double_step_enabled() const;
   bool castling_enabled() const;
   bool checking_permitted() const;
@@ -279,6 +280,11 @@ inline const std::set<PieceType, std::greater<PieceType> >& Position::promotion_
   return var->promotionPieceTypes;
 }
 
+inline bool Position::endgame_eval() const {
+  assert(var != nullptr);
+  return var->endgameEval;
+}
+
 inline bool Position::double_step_enabled() const {
   assert(var != nullptr);
   return var->doubleStep;
index fb9e908..f1ade24 100644 (file)
@@ -30,6 +30,7 @@ void VariantMap::init() {
     // Define variant rules
     const Variant* chess = [&]{
         Variant* v = new Variant();
+        v->endgameEval = true;
         return v;
     } ();
     const Variant* makruk = [&]{
@@ -41,6 +42,7 @@ void VariantMap::init() {
         v->startFen = "rnsmksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKMSNR w - - 0 1";
         v->promotionRank = RANK_6;
         v->promotionPieceTypes = {MET};
+        v->endgameEval = true;
         v->doubleStep = false;
         v->castling = false;
         return v;
@@ -53,6 +55,7 @@ void VariantMap::init() {
         v->add_piece(MET, 'q');
         v->startFen = "rnbqkbnr/8/pppppppp/8/8/PPPPPPPP/8/RNBQKBNR w - - 0 1";
         v->promotionPieceTypes = {ROOK, KNIGHT, KHON, MET};
+        v->endgameEval = true;
         v->doubleStep = false;
         v->castling = false;
         return v;
@@ -66,6 +69,7 @@ void VariantMap::init() {
         v->startFen = "rnsaksnr/8/pppppppp/8/8/PPPPPPPP/8/RNSKASNR w - - 0 1";
         v->promotionRank = RANK_6;
         v->promotionPieceTypes = {AIWOK};
+        v->endgameEval = true;
         v->doubleStep = false;
         v->castling = false;
         return v;
@@ -78,6 +82,7 @@ void VariantMap::init() {
         v->add_piece(FERS, 'q');
         v->startFen = "rnbkqbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBKQBNR w - - 0 1";
         v->promotionPieceTypes = {FERS};
+        v->endgameEval = true;
         v->doubleStep = false;
         v->castling = false;
         v->bareKingValue = -VALUE_MATE;
@@ -91,6 +96,7 @@ void VariantMap::init() {
         v->add_piece(AMAZON, 'a');
         v->startFen = "rnbakbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBAKBNR w KQkq - 0 1";
         v->promotionPieceTypes = {AMAZON, ROOK, BISHOP, KNIGHT};
+        v->endgameEval = true;
         return v;
     } ();
     const Variant* hoppelpoppel = [&]{
@@ -100,6 +106,7 @@ void VariantMap::init() {
         v->add_piece(KNIBIS, 'n');
         v->add_piece(BISKNI, 'b');
         v->promotionPieceTypes = {QUEEN, ROOK, BISKNI, KNIBIS};
+        v->endgameEval = true;
         return v;
     } ();
     const Variant* kingofthehill = [&]{
@@ -274,6 +281,7 @@ void VariantMap::init() {
         v->add_piece(CHANCELLOR, 'c');
         v->startFen = "rnbckbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBCKBNR w KQkq - 0 1";
         v->promotionPieceTypes = {CHANCELLOR, ROOK, BISHOP, KNIGHT};
+        v->endgameEval = true;
         return v;
     } ();
     const Variant* chigorin = [&]{
@@ -281,6 +289,7 @@ void VariantMap::init() {
         v->add_piece(CHANCELLOR, 'c');
         v->startFen = "rbbqkbbr/pppppppp/8/8/8/8/PPPPPPPP/RNNCKNNR w KQkq - 0 1";
         v->promotionPieceTypes = {QUEEN, CHANCELLOR, ROOK, BISHOP, KNIGHT};
+        v->endgameEval = true;
         return v;
     } ();
     const Variant* shatar = [&]{
@@ -289,6 +298,7 @@ void VariantMap::init() {
         v->add_piece(BERS, 'j');
         v->startFen = "rnbjkbnr/ppp1pppp/8/3p4/3P4/8/PPP1PPPP/RNBJKBNR w - - 0 1";
         v->promotionPieceTypes = {BERS};
+        v->endgameEval = true;
         v->doubleStep = false;
         v->castling = false;
         v->bareKingValue = VALUE_DRAW;
index a79ffa7..8af0c54 100644 (file)
@@ -42,6 +42,7 @@ struct Variant {
   std::string startFen = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
   Rank promotionRank = RANK_8;
   std::set<PieceType, std::greater<PieceType> > promotionPieceTypes = { QUEEN, ROOK, BISHOP, KNIGHT };
+  bool endgameEval = false;
   bool doubleStep = true;
   bool castling = true;
   bool checking = true;