]> git.sesse.net Git - stockfish/blobdiff - src/pawns.cpp
Introduce penalty for weak (=unsupported) pawns.
[stockfish] / src / pawns.cpp
index 1e88652e154be205ee9a9008450f1ebc4bd53641..1e62557784199b1a4a135ef796d93bd053233762 100644 (file)
@@ -60,6 +60,9 @@ namespace {
   // Bonus for file distance of the two outermost pawns
   const Score PawnsFileSpan = S(0, 15);
 
+  // Unsupported pawn penalty
+  const Score UnsupportedPawnPenalty = S(20, 10);
+
   // Weakness of our pawn shelter in front of the king indexed by [rank]
   const Value ShelterWeakness[RANK_NB] =
   { V(100), V(0), V(27), V(73), V(92), V(101), V(101) };
@@ -86,10 +89,10 @@ namespace {
     const Square Right = (Us == WHITE ? DELTA_NE : DELTA_SW);
     const Square Left  = (Us == WHITE ? DELTA_NW : DELTA_SE);
 
-    Bitboard b;
+    Bitboard b, p;
     Square s;
     File f;
-    bool passed, isolated, doubled, opposed, connected, backward, candidate;
+    bool passed, isolated, doubled, opposed, connected, backward, candidate, unsupported;
     Score value = SCORE_ZERO;
     const Square* pl = pos.list<PAWN>(Us);
 
@@ -113,16 +116,20 @@ namespace {
         // This file cannot be semi-open
         e->semiopenFiles[Us] &= ~(1 << f);
 
+        // Previous rank
+        p = rank_bb(s - pawn_push(Us));
+
         // Our rank plus previous one
-        b = rank_bb(s) | rank_bb(s - pawn_push(Us));
+        b = rank_bb(s) | p;
 
-        // Flag the pawn as passed, isolated, doubled or
-        // connected (but not the backward one).
-        connected =   ourPawns   & adjacent_files_bb(f) & b;
-        isolated  = !(ourPawns   & adjacent_files_bb(f));
-        doubled   =   ourPawns   & forward_bb(Us, s);
-        opposed   =   theirPawns & forward_bb(Us, s);
-        passed    = !(theirPawns & passed_pawn_mask(Us, s));
+        // Flag the pawn as passed, isolated, doubled,
+        // unsupported or connected (but not the backward one).
+        connected   =   ourPawns   & adjacent_files_bb(f) & b;
+        unsupported = !(ourPawns   & adjacent_files_bb(f) & p);
+        isolated    = !(ourPawns   & adjacent_files_bb(f));
+        doubled     =   ourPawns   & forward_bb(Us, s);
+        opposed     =   theirPawns & forward_bb(Us, s);
+        passed      = !(theirPawns & passed_pawn_mask(Us, s));
 
         // Test for backward pawn.
         // If the pawn is passed, isolated, or connected it cannot be
@@ -166,6 +173,9 @@ namespace {
         if (isolated)
             value -= Isolated[opposed][f];
 
+        if (unsupported && !isolated)
+            value -= UnsupportedPawnPenalty;
+
         if (doubled)
             value -= Doubled[f];
 
@@ -240,6 +250,7 @@ template<Color Us>
 Value Entry::shelter_storm(const Position& pos, Square ksq) {
 
   const Color Them = (Us == WHITE ? BLACK : WHITE);
+  static const Bitboard MiddleEdges = (FileABB | FileHBB) & (Rank2BB | Rank3BB);
 
   Value safety = MaxSafetyBonus;
   Bitboard b = pos.pieces(PAWN) & (in_front_bb(Us, rank_of(ksq)) | rank_bb(ksq));
@@ -252,11 +263,17 @@ Value Entry::shelter_storm(const Position& pos, Square ksq) {
   {
       b = ourPawns & file_bb(f);
       rkUs = b ? relative_rank(Us, backmost_sq(Us, b)) : RANK_1;
-      safety -= ShelterWeakness[rkUs];
 
       b  = theirPawns & file_bb(f);
       rkThem = b ? relative_rank(Us, frontmost_sq(Them, b)) : RANK_1;
-      safety -= StormDanger[rkUs == RANK_1 ? 0 : rkThem == rkUs + 1 ? 2 : 1][rkThem];
+
+      if (   (MiddleEdges & make_square(f, rkThem))
+          && file_of(ksq) == f
+          && relative_rank(Us, ksq) == rkThem - 1)
+          safety += Value(200);
+      else
+          safety -= ShelterWeakness[rkUs]
+                  + StormDanger[rkUs == RANK_1 ? 0 : rkThem == rkUs + 1 ? 2 : 1][rkThem];
   }
 
   return safety;
@@ -271,7 +288,7 @@ template<Color Us>
 Score Entry::update_safety(const Position& pos, Square ksq) {
 
   kingSquares[Us] = ksq;
-  castlingFlags[Us] = pos.can_castle(Us);
+  castlingRights[Us] = pos.can_castle(Us);
   minKPdistance[Us] = 0;
 
   Bitboard pawns = pos.pieces(Us, PAWN);
@@ -284,10 +301,10 @@ Score Entry::update_safety(const Position& pos, Square ksq) {
   Value bonus = shelter_storm<Us>(pos, ksq);
 
   // If we can castle use the bonus after the castling if it is bigger
-  if (pos.can_castle(make_castling_flag(Us, KING_SIDE)))
+  if (pos.can_castle(MakeCastling<Us, KING_SIDE>::right))
       bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_G1)));
 
-  if (pos.can_castle(make_castling_flag(Us, QUEEN_SIDE)))
+  if (pos.can_castle(MakeCastling<Us, QUEEN_SIDE>::right))
       bonus = std::max(bonus, shelter_storm<Us>(pos, relative_square(Us, SQ_C1)));
 
   return kingSafety[Us] = make_score(bonus, -16 * minKPdistance[Us]);