X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fendgame.cpp;h=a44d3a1c5e66f3c10a1f40853c41794f80dc81dc;hb=673841301b0cc6ed78c4db3e6ec2a0b9a010c8cb;hp=cf38009fa2a0f16baf69d017581c38d339085bcd;hpb=4a8c1b24702ddf577853d72962cee6735a0235da;p=stockfish
diff --git a/src/endgame.cpp b/src/endgame.cpp
index cf38009f..a44d3a1c 100644
--- a/src/endgame.cpp
+++ b/src/endgame.cpp
@@ -1,7 +1,6 @@
/*
Stockfish, a UCI chess playing engine derived from Glaurung 2.1
- Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
- Copyright (C) 2008-2010 Marco Costalba, Joona Kiiski, Tord Romstad
+ Copyright (C) 2004-2021 The Stockfish developers (see AUTHORS file)
Stockfish is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,229 +16,158 @@
along with this program. If not, see .
*/
-#include
#include
-#include "bitcount.h"
+#include "bitboard.h"
#include "endgame.h"
-#include "pawns.h"
+#include "movegen.h"
-using std::string;
-
-extern uint32_t probe_kpk_bitbase(Square wksq, Square wpsq, Square bksq, Color stm);
+namespace Stockfish {
namespace {
- // Table used to drive the defending king towards the edge of the board
+ // Used to drive the king towards the edge of the board
// in KX vs K and KQ vs KR endgames.
- const int MateTable[64] = {
- 100, 90, 80, 70, 70, 80, 90, 100,
- 90, 70, 60, 50, 50, 60, 70, 90,
- 80, 60, 40, 30, 30, 40, 60, 80,
- 70, 50, 30, 20, 20, 30, 50, 70,
- 70, 50, 30, 20, 20, 30, 50, 70,
- 80, 60, 40, 30, 30, 40, 60, 80,
- 90, 70, 60, 50, 50, 60, 70, 90,
- 100, 90, 80, 70, 70, 80, 90, 100,
- };
-
- // Table used to drive the defending king towards a corner square of the
- // right color in KBN vs K endgames.
- const int KBNKMateTable[64] = {
- 200, 190, 180, 170, 160, 150, 140, 130,
- 190, 180, 170, 160, 150, 140, 130, 140,
- 180, 170, 155, 140, 140, 125, 140, 150,
- 170, 160, 140, 120, 110, 140, 150, 160,
- 160, 150, 140, 110, 120, 140, 160, 170,
- 150, 140, 125, 140, 140, 155, 170, 180,
- 140, 130, 140, 150, 160, 170, 180, 190,
- 130, 140, 150, 160, 170, 180, 190, 200
- };
-
- // The attacking side is given a descending bonus based on distance between
- // the two kings in basic endgames.
- const int DistanceBonus[8] = { 0, 0, 100, 80, 60, 40, 20, 10 };
-
- // Build corresponding key code for the opposite color: "KBPKN" -> "KNKBP"
- const string swap_colors(const string& keyCode) {
-
- size_t idx = keyCode.find('K', 1);
- return keyCode.substr(idx) + keyCode.substr(0, idx);
+ // Values range from 27 (center squares) to 90 (in the corners)
+ inline int push_to_edge(Square s) {
+ int rd = edge_distance(rank_of(s)), fd = edge_distance(file_of(s));
+ return 90 - (7 * fd * fd / 2 + 7 * rd * rd / 2);
}
- // Get the material key of a position out of the given endgame key code
- // like "KBPKN". The trick here is to first build up a FEN string and then
- // let a Position object to do the work for us. Note that the FEN string
- // could correspond to an illegal position.
- Key mat_key(const string& keyCode) {
-
- assert(keyCode.length() > 0 && keyCode.length() < 8);
- assert(keyCode[0] == 'K');
-
- string fen;
- size_t i = 0;
-
- // First add white and then black pieces
- do fen += keyCode[i]; while (keyCode[++i] != 'K');
- do fen += char(tolower(keyCode[i])); while (++i < keyCode.length());
-
- // Add file padding and remaining empty ranks
- fen += string(1, '0' + int(8 - keyCode.length())) + "/8/8/8/8/8/8/8 w - - 0 10";
-
- // Build a Position out of the fen string and get its material key
- return Position(fen, false, 0).material_key();
+ // Used to drive the king towards A1H8 corners in KBN vs K endgames.
+ // Values range from 0 on A8H1 diagonal to 7 in A1H8 corners
+ inline int push_to_corner(Square s) {
+ return abs(7 - rank_of(s) - file_of(s));
}
- template
- void delete_endgame(const typename M::value_type& p) { delete p.second; }
+ // Drive a piece close to or away from another piece
+ inline int push_close(Square s1, Square s2) { return 140 - 20 * distance(s1, s2); }
+ inline int push_away(Square s1, Square s2) { return 120 - push_close(s1, s2); }
-} // namespace
+#ifndef NDEBUG
+ bool verify_material(const Position& pos, Color c, Value npm, int pawnsCnt) {
+ return pos.non_pawn_material(c) == npm && pos.count(c) == pawnsCnt;
+ }
+#endif
+ // Map the square as if strongSide is white and strongSide's only pawn
+ // is on the left half of the board.
+ Square normalize(const Position& pos, Color strongSide, Square sq) {
-/// Endgames member definitions
+ assert(pos.count(strongSide) == 1);
-template<> const Endgames::M1& Endgames::map() const { return m1; }
-template<> const Endgames::M2& Endgames::map() const { return m2; }
+ if (file_of(pos.square(strongSide)) >= FILE_E)
+ sq = flip_file(sq);
-Endgames::Endgames() {
+ return strongSide == WHITE ? sq : flip_rank(sq);
+ }
- add("KPK");
- add("KNNK");
- add("KBNK");
- add("KRKP");
- add("KRKB");
- add("KRKN");
- add("KQKR");
- add("KBBKN");
+} // namespace
- add("KNPK");
- add("KRPKR");
- add("KBPKB");
- add("KBPKN");
- add("KBPPKB");
- add("KRPPKRP");
-}
-Endgames::~Endgames() {
+namespace Endgames {
- for_each(m1.begin(), m1.end(), delete_endgame);
- for_each(m2.begin(), m2.end(), delete_endgame);
-}
+ std::pair