Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endgame KBN v K #1877

Closed

Conversation

protonspring
Copy link

@protonspring protonspring commented Dec 17, 2018

I'm working on endgames and this particular ones needs some work.

This particular endgame should be a win 100% of the time assuming there are enough moves remaining to finish the game without hitting the 50 move rule.

PROBLEM: The issue here is that the PushClose difference per square is 20, however, the difference in squares for the PushToCorners array is usually less. Thus, the engine prefers to move the kings closer together rather than pushing the weak king to the correct corner.

What happens is if the weak king is in a safe corner, sf still prefers pushing the kings together. Occasionally, the strong king traps the weak king in the safe corner. It takes a while for sf to figure it out, but often draws the game by the 50 move rule (on shorter time controls).

SOLUTION: I'm having success by either reducing the PushClose and/or increasing PushToCorners.
Version1) Divide PushClose by 2, and multiply PushToCorners by 2.
Version2) This PR is better. A better scaled array also shows to be much better than master (wins 5+ games per 100), but we need more testing.

MORE TESTING:
This PR is much better than master, but I'm guessing we can come up with something better if others can help test. Just download the KBNvK fen file and use it as an opening book with cutechess. Set the depth to 1, and anyone can test other KBNvK endgame versions, or validate this particular patch.

https://groups.google.com/forum/?fromgroups=#!topic/fishcooking/ZXzi8K0CcxU

Please let me know how I should proceed.

bench 3646542

@protonspring
Copy link
Author

Also, results seem to vary quite a bit based on time controls. Which times are preferred for these kinds of tests?

@MichaelB7
Copy link
Contributor

FYI, There are no KBNK positions that should ever take more than 50 moves.

@protonspring
Copy link
Author

protonspring commented Dec 17, 2018 via email

@snicolet
Copy link
Member

Looks good to me

@joergoster
Copy link
Contributor

Nothing earthshaking, but a slight improvement indeed. :-)

500 games at 3"+0.03" from random KBNK start positions, finished in favor of this patch:

Finished game 500 (SF-Master vs SF-KBNK): 1-0 {White mates}
Score of SF-KBNK vs SF-Master: 224 - 218 - 58  [0.506] 500
Elo difference: 4.17 +/- 28.66
Finished match

Most draws are by insufficent material, because the weak side king was able to capture a minor at the 1st or the 2nd move.
One example game where master branch is not able to deliver the mate within 50 moves.

[Event "?"]
[Site "?"]
[Date "2018.12.18"]
[Round "56"]
[White "SF-Master"]
[Black "SF-KBNK"]
[Result "1/2-1/2"]
[FEN "4N3/1B6/K7/8/8/5k2/8/8 b - - 0 1"]
[PlyCount "100"]
[SetUp "1"]
[TimeControl "3+0.03"]

1... Ke3 {-49.09/23 0.20s} 2. Kb5 {+49.18/19 0.074s} Kd2 {-49.09/23 0.033s}
3. Kc4 {+49.23/17 0.032s} Ke3 {-49.09/20 0.035s} 4. Bh1 {+49.27/21 0.069s}
Kf4 {-49.12/19 0.038s} 5. Kd5 {+49.27/21 0.026s} Ke3 {-49.14/20 0.042s}
6. Be4 {+49.27/21 0.053s} Kf4 {-49.26/23 0.060s} 7. Kd4 {+49.27/19 0.034s}
Kg5 {-49.26/24 0.044s} 8. Nd6 {+49.32/21 0.057s} Kf6 {-49.16/15 0.031s}
9. Bd5 {+49.37/21 0.073s} Ke7 {-49.26/22 0.092s} 10. Ke5 {+49.37/20 0.027s}
Kf8 {-49.16/20 0.022s} 11. Kf5 {+49.37/23 0.091s} Kg7 {-49.48/27 0.17s}
12. Ke5 {+49.27/22 0.067s} Kh6 {-49.48/23 0.057s} 13. Kf5 {+49.27/22 0.046s}
Kh7 {-49.48/24 0.026s} 14. Kf6 {+49.42/24 0.067s} Kh8 {-49.48/26 0.042s}
15. Bb3 {+49.37/21 0.031s} Kh7 {-48.75/1 0s} 16. Be6 {+49.42/23 0.073s}
Kh8 {-49.36/27 0.17s} 17. Nb7 {+49.42/23 0.034s} Kh7 {-48.75/1 0s}
18. Nd6 {+49.42/24 0.041s} Kh8 {-49.48/29 0.083s} 19. Bd5 {+49.37/24 0.091s}
Kh7 {-48.75/1 0s} 20. Nf7 {+49.37/24 0.040s} Kg8 {-48.75/1 0s}
21. Kg6 {+49.37/24 0.038s} Kf8 {-48.92/1 0s} 22. Nd6 {+49.37/23 0.047s}
Ke7 {-49.12/1 0s} 23. Nc4 {+49.37/24 0.057s} Kf8 {-49.43/24 0.062s}
24. Kh7 {+49.42/25 0.10s} Ke8 {-49.60/26 0.077s} 25. Kg8 {+49.37/23 0.034s}
Ke7 {-M46/30 0.27s} 26. Kg7 {+49.37/24 0.061s} Ke8 {-M44/30 0.039s}
27. Bf3 {+49.42/27 0.13s} Ke7 {-M46/29 0.075s} 28. Bc6 {+49.42/24 0.029s}
Ke6 {-M48/26 0.031s} 29. Kg6 {+49.37/24 0.049s} Ke7 {-49.12/1 0s}
30. Bd5 {+49.47/24 0.048s} Kf8 {-M40/30 0.18s} 31. Kh7 {+49.51/26 0.048s}
Ke8 {-M52/26 0.033s} 32. Kg8 {+M51/26 0.042s} Ke7 {-M44/26 0.053s}
33. Kg7 {+298.97/28 0.13s} Ke8 {-M50/28 0.14s} 34. Kf6 {+M89/26 0.059s}
Kf8 {-M46/23 0.041s} 35. Ne5 {+M35/23 0.066s} Ke8 {-49.26/1 0s}
36. Bb3 {+49.37/24 0.20s} Kf8 {-49.50/25 0.15s} 37. Ng6+ {+49.37/21 0.069s}
Ke8 {-49.26/1 0s} 38. Ba4+ {+M79/24 0.47s} Kd8 {-49.26/1 0s}
39. Bc2 {+49.18/24 0.36s} Kd7 {-48.75/14 0.059s} 40. Ke5 {+49.18/18 0.019s}
Kc6 {-49.04/16 0.11s} 41. Bd3 {+49.18/17 0.053s} Kc5 {-48.49/17 0.057s}
42. Ne7 {+49.08/18 0.14s} Kb4 {-48.59/17 0.15s} 43. Kd4 {+49.13/16 0.087s}
Kb3 {-48.59/16 0.11s} 44. Kc5 {+48.89/16 0.23s} Kc3 {-48.39/15 0.080s}
45. Be4 {+48.99/14 0.17s} Kb3 {-48.12/14 0.055s} 46. Kd4 {0.00/17 0.11s}
Kb2 {0.00/16 0.079s} 47. Nd5 {0.00/15 0.018s} Ka3 {0.00/18 0.023s}
48. Kc3 {0.00/17 0.040s} Ka4 {0.00/25 0.063s} 49. Kb2 {0.00/19 0.019s}
Kb5 {0.00/31 0.046s} 50. Ka1 {0.00/31 0.015s} Kc6 {0.00/127 0.010s}
51. Nc3+ {0.00/127 0.004s, Draw by fifty moves rule} 1/2-1/2

@protonspring
Copy link
Author

It is even better (barely) to multiply PushToCorner * 2, and divide PushClose / 2.

I ran 5+0.1 games overnight against this patch and got: 9190 - 9130. Could someone else confirm?

@protonspring
Copy link
Author

The original array * 32 was 940 - 915 against the original patch.

@protonspring
Copy link
Author

I have done all I can here. . . if someone else could confirm my best version, we can consider merging.

@vdbergh
Copy link
Contributor

vdbergh commented Dec 19, 2018

Elo difference: 4.17 +/- 28.66

@joergoster

Just a small comment. This is one of the cases where the calculation of the error bars is probably incorrect. I assume you are playing each position twice with reversed colors? Since KBNK is extremely unbalanced each game pair should be treated as a unit and the outcome of a match should be described by a pentanomial distribution (indexed by (2, 3/2, 1, 1/2, 0)) instead of a trinomial one (indexed by (1, 1/2, 0)). This will then result in a much lower variance possibly leading to a significant result.

@joergoster
Copy link
Contributor

joergoster commented Dec 19, 2018

@vdbergh Sure you know, games were played with cutechess-cli. All openings are indeed being played twice with reversed colors. What you see is the reported result calculated by cutechess.

@vdbergh
Copy link
Contributor

vdbergh commented Dec 19, 2018

@vdbergh Sure you know, games were played with cutechess-cli.

I should probably submit a patch to cutechess-cli. It is never wrong to use the pentanomial model to calculate the error bars (although it is not necessary in the case of balanced positions).

@joergoster
Copy link
Contributor

@protonspring Sorry to say, but now this looks a bit off.

Let's say, someone wants to change VALUE_KNOWN_WIN to a greater value, he will eventually run into an overflow of 'Value'. (Not that this is currently not possible because some guards in KingDanger eval have been removed.)
Note that adding the non_pawn_material(strongSide) like in other endgames is also missing. I never cared to open a PR because of this, though.

@protonspring
Copy link
Author

I've simply modified values, playing 100,000 of games and adjusted the values until the win margin stopped increasing. I think there is room to decrease them a bit. What do your propose to fix the overflow of 'Value?'

@joergoster
Copy link
Contributor

@protonspring Something like we already do in KXK for the exact same reason.
result = std::min(result, VALUE_MATE_IN_MAX_PLY - 1);

@protonspring
Copy link
Author

I will try to minimize the Corners array as much as possible without losing elo, and include the std::min.

@snicolet
Copy link
Member

snicolet commented Dec 20, 2018

I think the best solution would be:

• to extend the array without the std::min() overhead
• a mathematical proof that the value of the new function never overshoots VALUE_MATE_IN_MAX_PLY
• and to include an assert on the return value

@protonspring
Copy link
Author

Proof that the returned value can never exceed VALUE_MATE_IN_MAX_PLY:

The returned value is VALUE_KNOWN_WIN + PushClose[x] + PushToCorners[x];
The maximum values for these are: 10,000 + 100 + 6400;
Thus, the maximum value that KBNvK can return is 16,500.

VALUE_MATE_IN_MAX_PLY = VALUE_MATE - 2 * MAX_PLY
= 32000 - 2 * 128
= 31,744

Thus, because we can never return a value greater than 16,500 and VALUE_MATE_IN_MAX_PLY is 31,744, the method can never return a value that exceeds VALUE_MATE_IN_MAX_PLY.

Please let me know if this is sufficient, or if anything else is needed.

@snicolet
Copy link
Member

The assert should use an absolute value

snicolet pushed a commit that referenced this pull request Dec 24, 2018
Even when playing without endgame table bases, this particular endgame should
be a win 100% of the time when Stockfish is given a KRBK position, assuming
there are enough moves remaining in the FEN to finish the game without hitting
the 50 move rule.

PROBLEM: The issue with master here is that the PushClose difference per square
is 20, however, the difference in squares for the PushToCorners array is usually
less. Thus, the engine prefers to move the kings closer together rather than pushing
the weak king to the correct corner.

What happens is if the weak king is in a safe corner, SF still prefers pushing the
kings together. Occasionally, the strong king traps the weak king in the safe corner.
It takes a while for SF to figure it out, but often draws the game by the 50 move rule
(on shorter time controls).

This patch increases the PushToCorners values to correct this problem. We also added
an assert to catch any overflow problem if anybody would want to increase the array
values again in the future.

It was tested in a couple of matches starting with random KRBK positions and showed
increased winning rates, see #1877

No functional change
@snicolet
Copy link
Member

Merged via 96ac85b, congrats!

@snicolet snicolet closed this Dec 24, 2018
@protonspring
Copy link
Author

protonspring commented Dec 25, 2018 via email

@Rocky640
Copy link

Ok, got it.

vondele pushed a commit to vondele/Stockfish that referenced this pull request Dec 27, 2018
Even when playing without endgame table bases, this particular endgame should
be a win 100% of the time when Stockfish is given a KRBK position, assuming
there are enough moves remaining in the FEN to finish the game without hitting
the 50 move rule.

PROBLEM: The issue with master here is that the PushClose difference per square
is 20, however, the difference in squares for the PushToCorners array is usually
less. Thus, the engine prefers to move the kings closer together rather than pushing
the weak king to the correct corner.

What happens is if the weak king is in a safe corner, SF still prefers pushing the
kings together. Occasionally, the strong king traps the weak king in the safe corner.
It takes a while for SF to figure it out, but often draws the game by the 50 move rule
(on shorter time controls).

This patch increases the PushToCorners values to correct this problem. We also added
an assert to catch any overflow problem if anybody would want to increase the array
values again in the future.

It was tested in a couple of matches starting with random KRBK positions and showed
increased winning rates, see official-stockfish#1877

No functional change
snicolet pushed a commit that referenced this pull request Dec 27, 2018
Even when playing without endgame table bases, this particular endgame should
be a win 100% of the time when Stockfish is given a KRBK position, assuming
there are enough moves remaining in the FEN to finish the game without hitting
the 50 move rule.

PROBLEM: The issue with master here is that the PushClose difference per square
is 20, however, the difference in squares for the PushToCorners array is usually
less. Thus, the engine prefers to move the kings closer together rather than pushing
the weak king to the correct corner.

What happens is if the weak king is in a safe corner, SF still prefers pushing the
kings together. Occasionally, the strong king traps the weak king in the safe corner.
It takes a while for SF to figure it out, but often draws the game by the 50 move rule
(on shorter time controls).

This patch increases the PushToCorners values to correct this problem. We also added
an assert to catch any overflow problem if anybody would want to increase the array
values again in the future.

It was tested in a couple of matches starting with random KRBK positions and showed
increased winning rates, see #1877

No functional change
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants