23

I arrived at the following position in an online game after the opponent left a queen hanging.

[FEN "r1b2r2/pp1p1ppk/2n1p3/6B1/2P5/5N2/PQ3PPP/R4RK1 w - - 0 16"]

In the game, I played 16. Bf6 with the idea that in case he accepts the sacrifice, my queen can come to an exposed king with mating ideas and possibility of exchanging the rook for the knight and I should probably be able to arrive with the rooks by lifting them sooner than his minor pieces are able to help significantly. If the opponent refuses, my bishop is still up with a better aim and I have possibilities of blasting the kingside with a major advantage.

I looked at the game with lichess' Stockfish to check if this was a blunder and the main lines lichess' Stockfish suggests to me are 16. Be3, 16. Qc2+, 16. Nd2, 16. c5 and 16. Qa3, the first line having an evaluation of +12.8. Bf6 is not suggested, but it has an evaluation of +18.0 after it is played, so it left me wondering why it doesn't suggest Bf6 in the first place. My guess is that maybe Stockfish does not consider sacrificial moves without a forced advantage if the player has a large lead, which seems reasonable, but this is only a guess.

Running an analysis in chess.com with the Komodo engine suggests Bf6 as the best move, with +11.6 evaluation, so it left me even more curious as to why Stockfish doesn't even consider it.

3
  • 3
    I suspect the engines have had far less training in positions that are clearly winning for one side because there is less interest there. Jun 3, 2020 at 3:09
  • 2
    Engine evaluations above +10 are always fuzzy. Don't interpret too much into them (the common chess sites that offer game analysis don't do either - you won't get a move that drops from +20 to "just" +10 get marked as a "blunder").
    – Annatar
    Jun 3, 2020 at 7:16
  • Stockfish will find it at depth 35, u need to wait about 15 mins in android to get it. But yes komodo finds it at lower depth Jun 5, 2020 at 7:58

4 Answers 4

7

To expand on what heuristic pruning means for an alpha-beta negamax search, which many chess programs use, typically the evaluation function has some kind of depth parameter and the alpha-beta window. What it does is to test each possible move one by one, calling itself on the resulting position with the depth parameter reduced and with the appropriate alpha-beta window passed in. eval(d,α,β) searches to depth d and returns the value of the current position truncated to the interval [α,β]. At the start we call eval(D,−∞,∞) where D is the maximum depth. Note that the alpha-beta window depends on the evaluation results for previously tried moves as follows.

We first set m := α before testing any move. When testing each subsequent move we would call t := −eval(d',−β,−m) and then set m := max(m,t). If m≥β then we can immediately return β. At the end we return m. The reason for calling "eval(d',−β,−m)" is that if the resulting position has true value u outside [−β,−m] then it would have equivalent effect on the true value v of the current position as the truncated value. (If u<−β, then −eval(d',−β,−m) yields β so we return β, which is correct since v>β. If u>−m, then −eval(d',−β,−m) yields m so it does not affect m, which is correct since that move led to true value of −u<m.) Here d' is set by a heuristic (e.g. quiescence search may set d' := d−1 for normal moves but d' := d−1/2 for check and d' := d for captures).

To understand how heuristic pruning helps, one must first understand how alpha-beta helps. When the move-ordering is optimal (it always tests an optimal move first), then alpha-beta eliminates all the other moves at every alternate recursion level in most of the cases. To intuitively see why, consider the first move. To find an optimal first move X, we really have to check all possible first moves. But after we test an optimal one first, m would be set to that value, and we call eval(,−∞,−m) for every other tested first move X'. But since we first test an optimal opponent response Y to X', we will find that it results in a value at least −m (since X' is not better than X), and hence immediately return (discarding all other opponent responses because the first one already confirms that X' is not better than X). This happens throughout the search tree, and so the branching factor is more or less reduced to 1 at every alternate level in the search tree. This effectively doubles the search-depth possible with the same resources.

Mathematically, it is impossible to do better than alpha-beta search if we want to prove that a move is optimal. However, in many games such as chess we can perform better on average by using heuristic pruning. Instead of testing all the moves required by the alpha-beta search, we discard many of the moves! Heuristics inform this process. For example, if d>4 then we could for each possible move X, perform X then set t[X] := −eval(4,−β,−α) then undo X. After that, t[X] represents a depth-4 evaluation of those moves truncated to [α,β]. We might then choose to discard any move X if t[X]+3≤m; Informally, if move X causes a depth-4 evaluation that is at least a 'bishop' worse than the current best, we assume that it is poor enough that ignoring it will not affect the evaluation result.

Heuristic pruning (beyond alpha-beta) can hence reduce the effective branching factor (not just at every alternate level). That is why it is used in many modern chess programs today. The example heuristic I gave above is just for illustrative purposes; actual chess programs use a whole variety of complex heuristics to prune (e.g. null-move heuristic), as well as heuristics to not prune (e.g. the killer/history heuristic).

Now looking at the situation you have here, it is easy for many heuristics to prune off the best move Bf6 unless the depth-0 evaluation gives high enough weight to king danger, because Bf6 drops the bishop for a pawn and it takes quite a lot of quiet moves to see any benefits besides increased Black king danger. I am not sure, but the best line appears to be:

[Title ""]
[FEN "r1b2r2/pp1p1ppk/2n1p3/6B1/2P5/5N2/PQ3PPP/R4RK1 w Q - 0 1"]

1. Bf6 gxf6 2. Qxf6 Rg8 3. Ng5+ Rxg5 4. Qxg5

This line takes 2 quiet moves, 1 check and 4 captures. However, a pruning heuristic will very likely prune based on the first few moves of the following line:

[Title ""]
[FEN "r1b2r2/pp1p1ppk/2n1p3/6B1/2P5/5N2/PQ3PPP/R4RK1 w Q - 0 1"]

1. Bf6 gxf6 2. Qxf6 Kg8 3. Ng5 Nd8 4. Rad1 e5

Since it cannot see that this line ends in checkmate, it may believe that the bishop has been lost for a pawn. If the evaluation function had counted the position after 3. Ng5 as high king danger, it would not have pruned the Bf6 line away. As it is, it likely weighed the king danger against the bishop loss and thought it was worse than keeping the bishop. Furthermore, since there are many possible moves instead of Bf6 that keep the bishop, they would likely have pushed the Bf6 line far down in the move-ordering, hence it never got searched deep.

1
  • Well it turns out what I thought was the best line wasn't the fastest, but it does lead to checkmate via 1. Bf6 gxf6 2. Qxf6 Rg8 3. Ng5+ Rxg5 4. Qxg5 Nd4 5. Rae1 d5 6. Re3 e5 7. Qh5+ Kg8 8. Rg3+ Kf8 9. Qh8+ Ke7 10. Qxe5+ Be6 11. Qxd4 Rd8 12. Qh4+ Kd7 13. cxd5 Re8 14. dxe6+ Rxe6 15. Rd1+. A faster route is via 1. Bf6 gxf6 2. Qxf6 Rg8 3. Qxf7+ Kh8 4. Ng5 Rxg5 5. f4 Rf5 6. Qe8+ Kg7 7. Rf3 Rf7 8. Rh3 Kf6 9. Rh6+ Kf5 10. Re1 Ne5 11. Rxe5+.
    – user21820
    Jun 3, 2020 at 13:46
26

Good question. I let Stockfish 11 think on the position, and even by around depth 25-26 it didn't suggest Bf6. But like in your case, after making the move on the board, Stockfish suddenly realizes it is the best move. Although what's also odd is that after Bf6 gxf6 Qxf6, it takes Stockfish longer than at least depth 27 to realize it's a mate in 9 moves/18 ply (instead of some evaluation that's "only" over +20).

One possible explanation for all this is due to how engines prune. If an engine spends an equal amount of time examining every single move in its calculations, it will be very slow (there's an average of roughly 30 moves in a given position, so the complexity for searching everything is on the order of 30^depth). Therefore, they will spend more time thinking on moves that look more promising, and stop wasting as many resources on moves that look clearly worse.

In the position you posted, there are multiple moves that give at least a +12 evaluation. Meanwhile, Bf6 drops a bishop, and perhaps it is only multiple moves further that White's overwhelming compensation for it becomes apparent. There are already many +12 moves available from the starting position, so an engine could decide not to waste time going deep into the Bf6 branch, stopping at a point before it realizes how good it is.

But then when you actually play Bf6 on the board, there's nothing else for the engine to look at. It's "forced" to examine the Bf6 branch, and then it quickly realizes it's very good (although in Stockfish's case taking a while to realize it's a forced mate, likely due to this same pruning issue).

Note that all the above is just my own understanding of things, and there could be other factors at play. If I had to guess why Komodo suggested Bf6 to you but not Stockfish, it would be because Stockfish prunes more aggressively in order to be extremely fast in searching.

4
  • This makes a lot of sense. If you find a variation that gives you +12 in your favor, you can stop looking at other lines.
    – Issel
    Jun 3, 2020 at 5:51
  • 1
    @Issel I would assume it's relative though. It's not just certain lines being +12 (other lines could be better), it's certain lines being far better than the alternatives seem to be at first. Jun 3, 2020 at 6:44
  • Yes, Stockfish itself would get there eventually, but it would need a lot of time and the necessary depth to do so. I don't know whether Lichess supports that.
    – Mast
    Jun 3, 2020 at 6:56
  • Yeh this is indeed a problem with move ordering and searching the "most promising" moves first. Also finding lines like this is what chess players do for their opening prep. With the primary reason that the engine does not suggest it. Jun 3, 2020 at 9:21
8

It's all a matter of pruning. If you're not familiar with this concept, it's a key part of how engines search so deeply from a position. They are based on heuristics, e.g. the engine will search moves that give away a queen for no material compensation less. This allows it to focus its attention on the main moves in the position and search those deeper.

Good pruning contributes a huge amount to engine strength, but it's possible that pruning also cuts off the best move if the compensation is too deep (more technical term here is "beyond the search horizon"). That's what you're seeing. The heuristics for this position tell Stockfish to focus on other moves.*

In any case, if you let Stockfish analyze deeper, it'll spot that Bf6 is the best move. At depth 38, it's suggesting Bf6 (+37.0), Be3 (+14.5) and Rad1 (+14.3).

*I'm not sure if Stockfish has "if everything wins, search X less" code. It's possible. After all, Stockfish patches are tested against previous versions of the same program, and if everything wins then a patch that moves Bf6 up the move ordering isn't really an improvement - they yield the same result.

1
  • Good point about how finding the most optimal move in a clearly winning position won't matter much/at all in tests. Jun 3, 2020 at 6:53
0

it is Bf6 after you let it run higher depth

enter image description here

But good for you for being like wesley so in breaking stockfish

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.