Merge pull request #9 from glinscott/pawnspan
authorGary Linscott <glinscott@gmail.com>
Thu, 26 Jun 2014 19:21:06 +0000 (12:21 -0700)
committerGary Linscott <glinscott@gmail.com>
Thu, 26 Jun 2014 19:21:06 +0000 (12:21 -0700)
Scale down endgames with pawns on one or two adjacent files

Passed STC
LLR: 2.95 (-2.94,2.94) [-1.50,4.50]
Total: 16081 W: 2745 L: 2604 D: 10732

Passed LTC
LLR: 2.95 (-2.94,2.94) [1.00,6.00]
Total: 123832 W: 17292 L: 16584 D: 89956

128k games to measure ELO at 15+0.05:
ELO: 2.07 +-1.1 (95%) LOS: 100.0%
Total: 128000 W: 21632 L: 20869 D: 85499

New bench: 8028792

src/evaluate.cpp
src/pawns.cpp
src/pawns.h

index 1099a6e40b57a58e85f608d79e2857dba834faa1..7fb3a8cb141d4294c969b8292b4e4ca3c288813b 100644 (file)
@@ -197,6 +197,7 @@ namespace {
   // scores, indexed by a calculated integer number.
   Score KingDanger[128];
 
+  const int ScalePawnSpan[2] = { 38, 56 };
 
   // apply_weight() weighs score 'v' by weight 'w' trying to prevent overflow
   Score apply_weight(Score v, const Weight& w) {
@@ -726,29 +727,35 @@ namespace {
     }
 
     // Scale winning side if position is more drawish than it appears
-    ScaleFactor sf = eg_value(score) > VALUE_DRAW ? ei.mi->scale_factor(pos, WHITE)
-                                                  : ei.mi->scale_factor(pos, BLACK);
+    Color strongSide = eg_value(score) > VALUE_DRAW ? WHITE : BLACK;
+    ScaleFactor sf = ei.mi->scale_factor(pos, strongSide);
 
-    // If we don't already have an unusual scale factor, check for opposite
-    // colored bishop endgames, and use a lower scale for those.
+    // If we don't already have an unusual scale factor, check for certain
+    // types of endgames, and use a lower scale for those.
     if (    ei.mi->game_phase() < PHASE_MIDGAME
-        &&  pos.opposite_bishops()
         && (sf == SCALE_FACTOR_NORMAL || sf == SCALE_FACTOR_ONEPAWN))
     {
-        // Ignoring any pawns, do both sides only have a single bishop and no
-        // other pieces?
-        if (   pos.non_pawn_material(WHITE) == BishopValueMg
-            && pos.non_pawn_material(BLACK) == BishopValueMg)
-        {
-            // Check for KBP vs KB with only a single pawn that is almost
-            // certainly a draw or at least two pawns.
-            bool one_pawn = (pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK) == 1);
-            sf = one_pawn ? ScaleFactor(8) : ScaleFactor(32);
+        if (pos.opposite_bishops()) {
+            // Ignoring any pawns, do both sides only have a single bishop and no
+            // other pieces?
+            if (   pos.non_pawn_material(WHITE) == BishopValueMg
+                && pos.non_pawn_material(BLACK) == BishopValueMg)
+            {
+                // Check for KBP vs KB with only a single pawn that is almost
+                // certainly a draw or at least two pawns.
+                bool one_pawn = (pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK) == 1);
+                sf = one_pawn ? ScaleFactor(8) : ScaleFactor(32);
+            }
+            else
+                // Endgame with opposite-colored bishops, but also other pieces. Still
+                // a bit drawish, but not as drawish as with only the two bishops.
+                 sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
+        } else if (    abs(eg_value(score)) <= BishopValueEg
+                   &&  ei.pi->pawn_span(strongSide) <= 1
+                   && !pos.pawn_passed(~strongSide, pos.king_square(~strongSide))) {
+            // Endings where weaker side can be place his king in front of the opponent's pawns are drawish.
+            sf = ScaleFactor(ScalePawnSpan[ei.pi->pawn_span(strongSide)]);
         }
-        else
-            // Endgame with opposite-colored bishops, but also other pieces. Still
-            // a bit drawish, but not as drawish as with only the two bishops.
-             sf = ScaleFactor(50 * sf / SCALE_FACTOR_NORMAL);
     }
 
     // Interpolate between a middlegame and a (scaled by 'sf') endgame score
index 4d878e2063419a590e3a18a3633c1b75444820fa..2f7bb5a6c20ab1904681c15dd31a809c769935f7 100644 (file)
@@ -204,13 +204,12 @@ namespace {
         }
     }
 
+    b = e->semiopenFiles[Us] ^ 0xFF;
+    e->pawnSpan[Us] = b ? int(msb(b) - lsb(b)) : 0;
+
     // In endgame it's better to have pawns on both wings. So give a bonus according
     // to file distance between left and right outermost pawns.
-    if (pos.count<PAWN>(Us) > 1)
-    {
-        b = e->semiopenFiles[Us] ^ 0xFF;
-        value += PawnsFileSpan * int(msb(b) - lsb(b));
-    }
+    value += PawnsFileSpan * e->pawnSpan[Us];
 
     return value;
   }
index 28fe1c075ed9ae344dbfc052058ff7ba80a2ac15..6124246229696291b3cfa162ba7cc1f87e83c374 100644 (file)
@@ -45,6 +45,10 @@ struct Entry {
     return semiopenFiles[c] & (leftSide ? (1 << f) - 1 : ~((1 << (f + 1)) - 1));
   }
 
+  int pawn_span(Color c) const {
+    return pawnSpan[c];
+  }
+
   int pawns_on_same_color_squares(Color c, Square s) const {
     return pawnsOnSquares[c][!!(DarkSquares & s)];
   }
@@ -71,6 +75,7 @@ struct Entry {
   int minKPdistance[COLOR_NB];
   int castlingRights[COLOR_NB];
   int semiopenFiles[COLOR_NB];
+  int pawnSpan[COLOR_NB];
   int pawnsOnSquares[COLOR_NB][COLOR_NB]; // [color][light/dark squares]
 };