diff --git a/src/endgame.cpp b/src/endgame.cpp index 3258c6fc..a8c1e1d0 100644 --- a/src/endgame.cpp +++ b/src/endgame.cpp @@ -29,41 +29,6 @@ #include "endgame.h" -//// -//// Constants and variables -//// - -/// Evaluation functions - -// Generic "mate lone king" eval -EvaluationFunction EvaluateKXK(WHITE), EvaluateKKX(BLACK); - -// K and two minors vs K and one or two minors -EvaluationFunction EvaluateKmmKm(WHITE); - -EvaluationFunction EvaluateKBNK(WHITE), EvaluateKKBN(BLACK); // KBN vs K -EvaluationFunction EvaluateKPK(WHITE), EvaluateKKP(BLACK); // KP vs K -EvaluationFunction EvaluateKRKP(WHITE), EvaluateKPKR(BLACK); // KR vs KP -EvaluationFunction EvaluateKRKB(WHITE), EvaluateKBKR(BLACK); // KR vs KB -EvaluationFunction EvaluateKRKN(WHITE), EvaluateKNKR(BLACK); // KR vs KN -EvaluationFunction EvaluateKQKR(WHITE), EvaluateKRKQ(BLACK); // KQ vs KR -EvaluationFunction EvaluateKBBKN(WHITE), EvaluateKNKBB(BLACK); // KBB vs KN - - -/// Scaling functions - -ScalingFunction ScaleKBPK(WHITE), ScaleKKBP(BLACK); // KBP vs K -ScalingFunction ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); // KQ vs KRP -ScalingFunction ScaleKRPKR(WHITE), ScaleKRKRP(BLACK); // KRP vs KR -ScalingFunction ScaleKRPPKRP(WHITE), ScaleKRPKRPP(BLACK); // KRPP vs KRP -ScalingFunction ScaleKPsK(WHITE), ScaleKKPs(BLACK); // King and pawns vs king -ScalingFunction ScaleKBPKB(WHITE), ScaleKBKBP(BLACK); // KBP vs KB -ScalingFunction ScaleKBPPKB(WHITE), ScaleKBKBPP(BLACK); // KBPP vs KB -ScalingFunction ScaleKBPKN(WHITE), ScaleKNKBP(BLACK); // KBP vs KN -ScalingFunction ScaleKNPK(WHITE), ScaleKKNP(BLACK); // KNP vs K -ScalingFunction ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); // KPKP - - //// //// Local definitions //// diff --git a/src/endgame.h b/src/endgame.h index 011299ac..271490b1 100644 --- a/src/endgame.h +++ b/src/endgame.h @@ -92,31 +92,6 @@ struct ScalingFunction : public EndgameScalingFunctionBase { }; -//// -//// Constants and variables -//// - -extern EvaluationFunction EvaluateKXK, EvaluateKKX; // Generic "mate lone king" eval -extern EvaluationFunction EvaluateKBNK, EvaluateKKBN; // KBN vs K -extern EvaluationFunction EvaluateKPK, EvaluateKKP; // KP vs K -extern EvaluationFunction EvaluateKRKP, EvaluateKPKR; // KR vs KP -extern EvaluationFunction EvaluateKRKB, EvaluateKBKR; // KR vs KB -extern EvaluationFunction EvaluateKRKN, EvaluateKNKR; // KR vs KN -extern EvaluationFunction EvaluateKQKR, EvaluateKRKQ; // KQ vs KR -extern EvaluationFunction EvaluateKBBKN, EvaluateKNKBB; // KBB vs KN -extern EvaluationFunction EvaluateKmmKm; // K and two minors vs K and one or two minors: - -extern ScalingFunction ScaleKBPK, ScaleKKBP; // KBP vs K -extern ScalingFunction ScaleKQKRP, ScaleKRPKQ; // KQ vs KRP -extern ScalingFunction ScaleKRPKR, ScaleKRKRP; // KRP vs KR -extern ScalingFunction ScaleKRPPKRP, ScaleKRPKRPP; // KRPP vs KRP -extern ScalingFunction ScaleKPsK, ScaleKKPs; // King and pawns vs king -extern ScalingFunction ScaleKBPKB, ScaleKBKBP; // KBP vs KB -extern ScalingFunction ScaleKBPPKB, ScaleKBKBPP; // KBPP vs KB -extern ScalingFunction ScaleKBPKN, ScaleKNKBP; // KBP vs KN -extern ScalingFunction ScaleKNPK, ScaleKKNP; // KNP vs K -extern ScalingFunction ScaleKPKPw, ScaleKPKPb; // KP vs KP - //// //// Prototypes //// diff --git a/src/material.cpp b/src/material.cpp index 845519bc..c9dcaba1 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -42,8 +42,17 @@ namespace { Key KNNKMaterialKey, KKNNMaterialKey; + // Unmapped endgame evaluation and scaling functions, these + // are accessed direcly and not through the function maps. + EvaluationFunction EvaluateKmmKm(WHITE); + EvaluationFunction EvaluateKXK(WHITE), EvaluateKKX(BLACK); + ScalingFunction ScaleKBPK(WHITE), ScaleKKBP(BLACK); + ScalingFunction ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); + ScalingFunction ScaleKPsK(WHITE), ScaleKKPs(BLACK); + ScalingFunction ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); } + //// //// Classes //// @@ -54,23 +63,28 @@ namespace { class EndgameFunctions { + typedef EndgameEvaluationFunctionBase EF; + typedef EndgameScalingFunctionBase SF; + public: EndgameFunctions(); - EndgameEvaluationFunctionBase* getEEF(Key key) const; - EndgameScalingFunctionBase* getESF(Key key, Color* c) const; + ~EndgameFunctions(); + EF* getEEF(Key key) const; + SF* getESF(Key key, Color* c) const; private: - void add(const string& keyCode, EndgameEvaluationFunctionBase* f); - void add(const string& keyCode, Color c, EndgameScalingFunctionBase* f); Key buildKey(const string& keyCode); + const string swapColors(const string& keyCode); + template void add_ef(const string& keyCode); + template void add_sf(const string& keyCode); struct ScalingInfo { Color col; - EndgameScalingFunctionBase* fun; + SF* fun; }; - std::map EEFmap; + std::map EEFmap; std::map ESFmap; }; @@ -176,7 +190,7 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { // material configuration. Is there a suitable scaling function? // // The code below is rather messy, and it could easily get worse later, - // if we decide to add more special cases. We face problems when there + // if we decide to add more special cases. We face problems when there // are several conflicting applicable scaling functions and we need to // decide which one to use. Color c; @@ -305,42 +319,39 @@ MaterialInfo* MaterialInfoTable::get_material_info(const Position& pos) { /// EndgameFunctions member definitions. This class is used to store the maps /// of end game and scaling functions that MaterialInfoTable will query for /// each key. The maps are constant and are populated only at construction, -/// but are per-thread instead of globals to avoid expensive locks. +/// but are per-thread instead of globals to avoid expensive locks needed +/// because std::map is not guaranteed to be thread-safe even if accessed +/// only for a lookup. EndgameFunctions::EndgameFunctions() { KNNKMaterialKey = buildKey("KNNK"); KKNNMaterialKey = buildKey("KKNN"); - add("KPK", &EvaluateKPK); - add("KKP", &EvaluateKKP); - add("KBNK", &EvaluateKBNK); - add("KKBN", &EvaluateKKBN); - add("KRKP", &EvaluateKRKP); - add("KPKR", &EvaluateKPKR); - add("KRKB", &EvaluateKRKB); - add("KBKR", &EvaluateKBKR); - add("KRKN", &EvaluateKRKN); - add("KNKR", &EvaluateKNKR); - add("KQKR", &EvaluateKQKR); - add("KRKQ", &EvaluateKRKQ); - add("KBBKN", &EvaluateKBBKN); - add("KNKBB", &EvaluateKNKBB); + add_ef("KPK"); + add_ef("KBNK"); + add_ef("KRKP"); + add_ef("KRKB"); + add_ef("KRKN"); + add_ef("KQKR"); + add_ef("KBBKN"); - add("KNPK", WHITE, &ScaleKNPK); - add("KKNP", BLACK, &ScaleKKNP); - add("KRPKR", WHITE, &ScaleKRPKR); - add("KRKRP", BLACK, &ScaleKRKRP); - add("KBPKB", WHITE, &ScaleKBPKB); - add("KBKBP", BLACK, &ScaleKBKBP); - add("KBPPKB", WHITE, &ScaleKBPPKB); - add("KBKBPP", BLACK, &ScaleKBKBPP); - add("KBPKN", WHITE, &ScaleKBPKN); - add("KNKBP", BLACK, &ScaleKNKBP); - add("KRPPKRP", WHITE, &ScaleKRPPKRP); - add("KRPKRPP", BLACK, &ScaleKRPKRPP); - add("KRPPKRP", WHITE, &ScaleKRPPKRP); - add("KRPKRPP", BLACK, &ScaleKRPKRPP); + add_sf("KNPK"); + add_sf("KRPKR"); + add_sf("KBPKB"); + add_sf("KBPPKB"); + add_sf("KBPKN"); + add_sf("KRPPKRP"); + add_sf("KRPPKRP"); +} + +EndgameFunctions::~EndgameFunctions() { + + for (std::map::iterator it = EEFmap.begin(); it != EEFmap.end(); ++it) + delete (*it).second; + + for (std::map::iterator it = ESFmap.begin(); it != ESFmap.end(); ++it) + delete (*it).second.fun; } Key EndgameFunctions::buildKey(const string& keyCode) { @@ -364,20 +375,33 @@ Key EndgameFunctions::buildKey(const string& keyCode) { return Position(s.str()).get_material_key(); } -void EndgameFunctions::add(const string& keyCode, EndgameEvaluationFunctionBase* f) { +const string EndgameFunctions::swapColors(const string& keyCode) { - EEFmap.insert(std::pair(buildKey(keyCode), f)); + // Build corresponding key for the opposite color: "KBPKN" -> "KNKBP" + size_t idx = keyCode.find("K", 1); + return keyCode.substr(idx) + keyCode.substr(0, idx); } -void EndgameFunctions::add(const string& keyCode, Color c, EndgameScalingFunctionBase* f) { +template +void EndgameFunctions::add_ef(const string& keyCode) { - ScalingInfo s = {c, f}; - ESFmap.insert(std::pair(buildKey(keyCode), s)); + EEFmap.insert(std::pair(buildKey(keyCode), new EvaluationFunction(WHITE))); + EEFmap.insert(std::pair(buildKey(swapColors(keyCode)), new EvaluationFunction(BLACK))); +} + +template +void EndgameFunctions::add_sf(const string& keyCode) { + + ScalingInfo s1 = {WHITE, new ScalingFunction(WHITE)}; + ScalingInfo s2 = {BLACK, new ScalingFunction(BLACK)}; + + ESFmap.insert(std::pair(buildKey(keyCode), s1)); + ESFmap.insert(std::pair(buildKey(swapColors(keyCode)), s2)); } EndgameEvaluationFunctionBase* EndgameFunctions::getEEF(Key key) const { - std::map::const_iterator it(EEFmap.find(key)); + std::map::const_iterator it(EEFmap.find(key)); return (it != EEFmap.end() ? it->second : NULL); }