Bonus for reachable outpost
authorStefan Geschwentner <stgeschwentner@gmail.com>
Sat, 14 Nov 2015 14:30:50 +0000 (06:30 -0800)
committerJoona Kiiski <joona@zoox.com>
Sat, 14 Nov 2015 14:31:45 +0000 (06:31 -0800)
Give a bonus for outpost squares which in reach of a bishop or knight.

STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 22725 W: 4570 L: 4339 D: 13816

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 15019 W: 2333 L: 2157 D: 10529

Bench: 8503181

Resolves #495

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

index 03d537d..2e1465f 100644 (file)
@@ -141,6 +141,11 @@ namespace {
       S(112,125), S(113,127), S(117,137), S(122,143) }
   };
 
+  // Mask of allowed outpost squares indexed by color
+  const Bitboard OutpostMask[COLOR_NB] = {
+    Rank4BB | Rank5BB | Rank6BB, Rank5BB | Rank4BB | Rank3BB
+  };
+
   // Outpost[knight/bishop][supported by pawn] contains bonuses for knights and
   // bishops outposts, bigger if outpost piece is supported by a pawn.
   const Score Outpost[][2] = {
@@ -148,6 +153,13 @@ namespace {
     { S(18, 5), S(27, 8) }  // Bishops
   };
 
+  // ReachableOutpost[knight/bishop][supported by pawn] contains bonuses for knights and
+  // bishops which can reach a outpost square in one move, bigger if outpost square is supported by a pawn.
+  const Score ReachableOutpost[][2] = {
+    { S(21, 5), S(31, 8) }, // Knights
+    { S( 8, 2), S(13, 4) }  // Bishops
+  };
+
   // Threat[minor/rook][attacked PieceType] contains
   // bonuses according to which piece type attacks which one.
   // Attacks on lesser pieces which are pawn defended are not considered.
@@ -257,7 +269,7 @@ namespace {
   template<PieceType Pt, Color Us, bool DoTrace>
   Score evaluate_pieces(const Position& pos, EvalInfo& ei, Score* mobility, const Bitboard* mobilityArea) {
 
-    Bitboard b;
+    Bitboard b, bb;
     Square s;
     Score score = SCORE_ZERO;
 
@@ -283,7 +295,7 @@ namespace {
         {
             ei.kingAttackersCount[Us]++;
             ei.kingAttackersWeight[Us] += KingAttackWeights[Pt];
-            Bitboard bb = b & ei.attackedBy[Them][KING];
+            bb = b & ei.attackedBy[Them][KING];
             if (bb)
                 ei.kingAdjacentZoneAttacksCount[Us] += popcount<Max15>(bb);
         }
@@ -299,11 +311,16 @@ namespace {
 
         if (Pt == BISHOP || Pt == KNIGHT)
         {
-            // Bonus for outpost square
-            if (   relative_rank(Us, s) >= RANK_4
-                && relative_rank(Us, s) <= RANK_6
-                && !(pos.pieces(Them, PAWN) & pawn_attack_span(Us, s)))
+            // Bonus for outpost squares
+            bb = OutpostMask[Us] & ~ei.pi->pawn_attacks_span(Them);
+            if (bb & s)
                 score += Outpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & s)];
+            else
+            {
+                bb &= b & ~pos.pieces(Us);
+                if (bb)
+                   score += ReachableOutpost[Pt == BISHOP][!!(ei.attackedBy[Us][PAWN] & bb)];
+            }
 
             // Bonus when behind a pawn
             if (    relative_rank(Us, s) < RANK_5
index 40037bb..8b44587 100644 (file)
@@ -116,7 +116,7 @@ namespace {
     Bitboard ourPawns   = pos.pieces(Us  , PAWN);
     Bitboard theirPawns = pos.pieces(Them, PAWN);
 
-    e->passedPawns[Us] = 0;
+    e->passedPawns[Us] = e->pawnAttacksSpan[Us] = 0;
     e->kingSquares[Us] = SQ_NONE;
     e->semiopenFiles[Us] = 0xFF;
     e->pawnAttacks[Us] = shift_bb<Right>(ourPawns) | shift_bb<Left>(ourPawns);
@@ -133,6 +133,8 @@ namespace {
         // This file cannot be semi-open
         e->semiopenFiles[Us] &= ~(1 << f);
 
+        e->pawnAttacksSpan[Us] |= pawn_attack_span(Us, s);
+
         // Flag the pawn
         neighbours  =   ourPawns   & adjacent_files_bb(f);
         doubled     =   ourPawns   & forward_bb(Us, s);
index 2b978ba..353cb6a 100644 (file)
@@ -35,6 +35,7 @@ struct Entry {
   Score pawns_score() const { return score; }
   Bitboard pawn_attacks(Color c) const { return pawnAttacks[c]; }
   Bitboard passed_pawns(Color c) const { return passedPawns[c]; }
+  Bitboard pawn_attacks_span(Color c) const { return pawnAttacksSpan[c]; }
   int pawn_span(Color c) const { return pawnSpan[c]; }
   int pawn_asymmetry() const { return asymmetry; }
 
@@ -66,6 +67,7 @@ struct Entry {
   Score score;
   Bitboard passedPawns[COLOR_NB];
   Bitboard pawnAttacks[COLOR_NB];
+  Bitboard pawnAttacksSpan[COLOR_NB];
   Square kingSquares[COLOR_NB];
   Score kingSafety[COLOR_NB];
   int castlingRights[COLOR_NB];