8/4n3/8/2n5/kp1N2P1/8/8/3K4 b - -
Only winning way is Nd5, but SF played here b3 (in depth 63) and game ended with draw. I think there is a problem on 2 Knights Endgame.
This is solved with 5, 6 and 7 men EGTB, who is playing a game that counts without EGTB?
This is why EGTB was created.
Chess engines haven't only made for Opening and Midgame. Chess Engines has made for chess and "chess" includes endgame. Isn't Stockfish the king of Endgame?
This is a KNNP KNP position (a 7 men position)
In this specific case, the win is to not go for a KNN KP final (win rate 14.6%) (with b3 ?)
but rather to keep everything on board (win rate 46.9%) or to go for KNP KP (win rate 64.0%)
Our current for KNN KP is rather optimistic (or stupid if you prefer) since it will always produce values higher than 6. It does not even verify if the opponent pawn is blocked by a Knight, which is quite important. So although the theoretical win rate is 14.6%, we always produce winning scores. So our evaluation is wrong 85.4 % of the time for this ending !!!
The code still have some value, as it will help win some of those winnable 14.6% positions, but a small improvement or two cannot hurt to detect draw positions.
Maybe the way to go would be to simply return a score below 5 instead of a score above 6.
See code below. We could replace 2 * KnightValueEg with KnightValueEg
But this will need extensive testing.
Some positions can still be won even if the pawn is beyond the Troitzky line, as long as it is blocked,
https://en.wikipedia.org/wiki/Two_knights_endgame#Troitsky_line
Meanwhile the strong side will corner the weak king, and the blocking knight can finally join the party and help deliver the mate.
In context of the 50 move rule, more interesting would be to implement the Second Troistsky line
https://en.wikipedia.org/wiki/Two_knights_endgame#Second_Troitsky_line
At least we can guarantee a theoretical win with that rule, but still SF might miss the narrow path to the win in some positions.
All this being said, I can only agree with @MichaelB7.
There are millions of position where SF is wrong without a tablebase.
If you want accuracy in endgame, install some syzygy tables.
With 3-4-5 men tables, it will find Nd5! instantly.
/// KNN vs KP. Simply push the opposing king to the corner
template<>
Value Endgame<KNNKP>::operator()(const Position& pos) const {
assert(verify_material(pos, strongSide, 2 * KnightValueMg, 0));
assert(verify_material(pos, weakSide, VALUE_ZERO, 1));
Value result = 2 * KnightValueEg
- PawnValueEg
+ PushToEdges[pos.square<KING>(weakSide)];
return strongSide == pos.side_to_move() ? result : -result;
}
I confirm that using the following in latest master will find Nd5 instantly,
Reducing the result value by half cannot be bad, (maybe even by 4 !) since it will be closer to the real value (which is a DRAW 86% of the time...) but this will need a proof.
Value result = KnightValueEg // don't use 2 * KnightValueEg to prefer other conversions
- PawnValueEg
+ PushToEdges[pos.square<KING>(weakSide)];
Another thing to consider is that cornering the weak king is great, but it has to be the right corner too ! to find the right corner one solution could be the following.
use a knight distance table (number of move required for a knight to go from s1 to s2)
find the corner which minimize the KnightDistance[s1][s2] where s1 is the corner, and s2 is the square of the blocking Knight (the Knight which blocks the opponent pawn).
EDIT: not always true. Often the blocking Knight will give a check to the Kh7, and the other knight will give the checkmate on h8.
I wonder if the idea in https://groups.google.com/forum/#!topic/fishcooking/7XPt3vJztxk could be used to tackle this more generally.
Most helpful comment
I confirm that using the following in latest master will find Nd5 instantly,
Reducing the result value by half cannot be bad, (maybe even by 4 !) since it will be closer to the real value (which is a DRAW 86% of the time...) but this will need a proof.
Another thing to consider is that cornering the weak king is great, but it has to be the right corner too ! to find the right corner one solution could be the following.
use a knight distance table (number of move required for a knight to go from s1 to s2)
find the corner which minimize the KnightDistance[s1][s2] where s1 is the corner, and s2 is the square of the blocking Knight (the Knight which blocks the opponent pawn).
EDIT: not always true. Often the blocking Knight will give a check to the Kh7, and the other knight will give the checkmate on h8.