]> git.sesse.net Git - stockfish/commitdiff
In movepicker increase priority for moves that evade a capture
authorMichael Chaly <Vizvezdenec@gmail.com>
Mon, 28 Mar 2022 11:15:56 +0000 (14:15 +0300)
committerJoost VandeVondele <Joost.VandeVondele@gmail.com>
Mon, 28 Mar 2022 20:37:09 +0000 (22:37 +0200)
This idea is a mix of koivisto idea of threat history and heuristic that
was simplified some time ago in LMR - decreasing reduction for moves that evade a capture.
Instead of doing so in LMR this patch does it in movepicker - to do this it
calculates squares that are attacked by different piece types and pieces that are located
on this squares and boosts up weight of moves that make this pieces land on a square that is not under threat.
Boost is greater for pieces with bigger material values.
Special thanks to koivisto and seer authors for explaining me ideas behind threat history.

Passed STC:
https://tests.stockfishchess.org/tests/view/62406e473b32264b9aa1478b
LLR: 2.94 (-2.94,2.94) <0.00,2.50>
Total: 19816 W: 5320 L: 5072 D: 9424
Ptnml(0-2): 86, 2165, 5172, 2385, 100

Passed LTC:
https://tests.stockfishchess.org/tests/view/62407f2e3b32264b9aa149c8
LLR: 2.94 (-2.94,2.94) <0.50,3.00>
Total: 51200 W: 13805 L: 13500 D: 23895
Ptnml(0-2): 44, 5023, 15164, 5322, 47

closes https://github.com/official-stockfish/Stockfish/pull/3970

bench 7736491

src/movepick.cpp

index 77453a45aedc26ea172cd3ff1bab52497388af3f..ce82a59ba3dd14441f431cf42c0692d0824bcefa 100644 (file)
@@ -97,6 +97,44 @@ MovePicker::MovePicker(const Position& p, Move ttm, Value th, Depth d, const Cap
                              && pos.see_ge(ttm, threshold));
 }
 
+//squares threatened by pawn attacks
+template <Color Us>
+Bitboard threatsByPawn (const Position& pos)
+{
+    return pawn_attacks_bb<Us>(pos.pieces(Us, PAWN));
+}
+
+//squares threatened by minor attacks
+template <Color Us>
+Bitboard threatsByMinor (const Position& pos)
+{
+    Bitboard our = pos.pieces(Us, KNIGHT, BISHOP);
+    Bitboard threats = 0;
+    while (our)
+    {
+        Square s = pop_lsb(our);
+        if (type_of(pos.piece_on(s)) == KNIGHT)
+            threats |= attacks_bb<KNIGHT>(s, pos.pieces());
+        else
+            threats |= attacks_bb<BISHOP>(s, pos.pieces());
+    }
+    return threats;
+}
+
+//squares threatened by rook attacks
+template <Color Us>
+Bitboard threatsByRook (const Position& pos)
+{
+    Bitboard our = pos.pieces(Us, ROOK);
+    Bitboard threats = 0;
+    while (our)
+    {
+        Square s = pop_lsb(our);
+        threats |= attacks_bb<ROOK>(s, pos.pieces());
+    }
+    return threats;
+}
+
 /// MovePicker::score() assigns a numerical value to each move in a list, used
 /// for sorting. Captures are ordered by Most Valuable Victim (MVV), preferring
 /// captures with a good history. Quiets moves are ordered using the histories.
@@ -105,6 +143,35 @@ void MovePicker::score() {
 
   static_assert(Type == CAPTURES || Type == QUIETS || Type == EVASIONS, "Wrong type");
 
+  Bitboard threatened, threatenedByPawn, threatenedByMinor, threatenedByRook;
+  if constexpr (Type == QUIETS)
+  {
+      // squares threatened by pawns
+      threatenedByPawn   = pos.side_to_move() == WHITE ? threatsByPawn<BLACK>(pos)  : threatsByPawn<WHITE>(pos);
+      // squares threatened by minors or pawns
+      threatenedByMinor  = pos.side_to_move() == WHITE ? threatsByMinor<BLACK>(pos) : threatsByMinor<WHITE>(pos);
+      threatenedByMinor |= threatenedByPawn;
+      // squares threatened by rooks, minors or pawns
+      threatenedByRook   = pos.side_to_move() == WHITE ? threatsByRook<BLACK>(pos)  : threatsByRook<WHITE>(pos);
+      threatenedByRook  |= threatenedByMinor;
+
+      // pieces threatened by pieces of lesser material value
+      threatened = pos.side_to_move() == WHITE ? ((pos.pieces(WHITE, QUEEN) & threatenedByRook) |
+                                                  (pos.pieces(WHITE, ROOK) & threatenedByMinor) |
+                                                  (pos.pieces(WHITE, KNIGHT, BISHOP) & threatenedByPawn))
+                                               : ((pos.pieces(BLACK, QUEEN) & threatenedByRook) |
+                                                  (pos.pieces(BLACK, ROOK) & threatenedByMinor) |
+                                                  (pos.pieces(BLACK, KNIGHT, BISHOP) & threatenedByPawn));
+  }
+  else
+  {
+      // Silence unused variable warning
+      (void) threatened;
+      (void) threatenedByPawn;
+      (void) threatenedByMinor;
+      (void) threatenedByRook;
+  }
+
   for (auto& m : *this)
       if constexpr (Type == CAPTURES)
           m.value =  6 * int(PieceValue[MG][pos.piece_on(to_sq(m))])
@@ -115,7 +182,13 @@ void MovePicker::score() {
                    + 2 * (*continuationHistory[0])[pos.moved_piece(m)][to_sq(m)]
                    +     (*continuationHistory[1])[pos.moved_piece(m)][to_sq(m)]
                    +     (*continuationHistory[3])[pos.moved_piece(m)][to_sq(m)]
-                   +     (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)];
+                   +     (*continuationHistory[5])[pos.moved_piece(m)][to_sq(m)]
+                   +     (threatened & from_sq(m) ?
+                           (type_of(pos.piece_on(from_sq(m))) == QUEEN && !(to_sq(m) & threatenedByRook)  ? 50000
+                          : type_of(pos.piece_on(from_sq(m))) == ROOK  && !(to_sq(m) & threatenedByMinor) ? 25000
+                          :                                               !(to_sq(m) & threatenedByPawn)  ? 15000
+                          :                                                                                 0)
+                          :                                                                                 0);
 
       else // Type == EVASIONS
       {