1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 08:43:09 +00:00

Simplify endgame functions handling

We really don't need to have global endgame functions. We can
allocate them on the heap at initialization time and store the
corresponding pointer directly in the functions maps. To avoid
leaks we just need to remember to deallocate them in map d'tor.

These functions are always created in couple, one for each color,
so remove a lot of redundant hard coded info and just use the minimum
required: the type and the corresponding named string.

This greatly simplifies the code and also it is less error prone,
now is much simpler to add a new endgame specialized function: just
add the corresponding enum in endgame.h and the obvious add_xx()
call in EndgameFunctions c'tor, and of course, the most important part,
the EvaluationFunction<xxx>::apply() specialization in endgame.cpp

No functional change.

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
This commit is contained in:
Marco Costalba 2009-07-16 14:31:32 +02:00
parent 5c20f59788
commit 297c12e595
3 changed files with 66 additions and 102 deletions

View file

@ -29,41 +29,6 @@
#include "endgame.h"
////
//// Constants and variables
////
/// Evaluation functions
// Generic "mate lone king" eval
EvaluationFunction<KXK> EvaluateKXK(WHITE), EvaluateKKX(BLACK);
// K and two minors vs K and one or two minors
EvaluationFunction<KmmKm> EvaluateKmmKm(WHITE);
EvaluationFunction<KBNK> EvaluateKBNK(WHITE), EvaluateKKBN(BLACK); // KBN vs K
EvaluationFunction<KPK> EvaluateKPK(WHITE), EvaluateKKP(BLACK); // KP vs K
EvaluationFunction<KRKP> EvaluateKRKP(WHITE), EvaluateKPKR(BLACK); // KR vs KP
EvaluationFunction<KRKB> EvaluateKRKB(WHITE), EvaluateKBKR(BLACK); // KR vs KB
EvaluationFunction<KRKN> EvaluateKRKN(WHITE), EvaluateKNKR(BLACK); // KR vs KN
EvaluationFunction<KQKR> EvaluateKQKR(WHITE), EvaluateKRKQ(BLACK); // KQ vs KR
EvaluationFunction<KBBKN> EvaluateKBBKN(WHITE), EvaluateKNKBB(BLACK); // KBB vs KN
/// Scaling functions
ScalingFunction<KBPK> ScaleKBPK(WHITE), ScaleKKBP(BLACK); // KBP vs K
ScalingFunction<KQKRP> ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK); // KQ vs KRP
ScalingFunction<KRPKR> ScaleKRPKR(WHITE), ScaleKRKRP(BLACK); // KRP vs KR
ScalingFunction<KRPPKRP> ScaleKRPPKRP(WHITE), ScaleKRPKRPP(BLACK); // KRPP vs KRP
ScalingFunction<KPsK> ScaleKPsK(WHITE), ScaleKKPs(BLACK); // King and pawns vs king
ScalingFunction<KBPKB> ScaleKBPKB(WHITE), ScaleKBKBP(BLACK); // KBP vs KB
ScalingFunction<KBPPKB> ScaleKBPPKB(WHITE), ScaleKBKBPP(BLACK); // KBPP vs KB
ScalingFunction<KBPKN> ScaleKBPKN(WHITE), ScaleKNKBP(BLACK); // KBP vs KN
ScalingFunction<KNPK> ScaleKNPK(WHITE), ScaleKKNP(BLACK); // KNP vs K
ScalingFunction<KPKP> ScaleKPKPw(WHITE), ScaleKPKPb(BLACK); // KPKP
////
//// Local definitions
////

View file

@ -92,31 +92,6 @@ struct ScalingFunction : public EndgameScalingFunctionBase {
};
////
//// Constants and variables
////
extern EvaluationFunction<KXK> EvaluateKXK, EvaluateKKX; // Generic "mate lone king" eval
extern EvaluationFunction<KBNK> EvaluateKBNK, EvaluateKKBN; // KBN vs K
extern EvaluationFunction<KPK> EvaluateKPK, EvaluateKKP; // KP vs K
extern EvaluationFunction<KRKP> EvaluateKRKP, EvaluateKPKR; // KR vs KP
extern EvaluationFunction<KRKB> EvaluateKRKB, EvaluateKBKR; // KR vs KB
extern EvaluationFunction<KRKN> EvaluateKRKN, EvaluateKNKR; // KR vs KN
extern EvaluationFunction<KQKR> EvaluateKQKR, EvaluateKRKQ; // KQ vs KR
extern EvaluationFunction<KBBKN> EvaluateKBBKN, EvaluateKNKBB; // KBB vs KN
extern EvaluationFunction<KmmKm> EvaluateKmmKm; // K and two minors vs K and one or two minors:
extern ScalingFunction<KBPK> ScaleKBPK, ScaleKKBP; // KBP vs K
extern ScalingFunction<KQKRP> ScaleKQKRP, ScaleKRPKQ; // KQ vs KRP
extern ScalingFunction<KRPKR> ScaleKRPKR, ScaleKRKRP; // KRP vs KR
extern ScalingFunction<KRPPKRP> ScaleKRPPKRP, ScaleKRPKRPP; // KRPP vs KRP
extern ScalingFunction<KPsK> ScaleKPsK, ScaleKKPs; // King and pawns vs king
extern ScalingFunction<KBPKB> ScaleKBPKB, ScaleKBKBP; // KBP vs KB
extern ScalingFunction<KBPPKB> ScaleKBPPKB, ScaleKBKBPP; // KBPP vs KB
extern ScalingFunction<KBPKN> ScaleKBPKN, ScaleKNKBP; // KBP vs KN
extern ScalingFunction<KNPK> ScaleKNPK, ScaleKKNP; // KNP vs K
extern ScalingFunction<KPKP> ScaleKPKPw, ScaleKPKPb; // KP vs KP
////
//// Prototypes
////

View file

@ -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<KmmKm> EvaluateKmmKm(WHITE);
EvaluationFunction<KXK> EvaluateKXK(WHITE), EvaluateKKX(BLACK);
ScalingFunction<KBPK> ScaleKBPK(WHITE), ScaleKKBP(BLACK);
ScalingFunction<KQKRP> ScaleKQKRP(WHITE), ScaleKRPKQ(BLACK);
ScalingFunction<KPsK> ScaleKPsK(WHITE), ScaleKKPs(BLACK);
ScalingFunction<KPKP> 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<EndgameType> void add_ef(const string& keyCode);
template<EndgameType> void add_sf(const string& keyCode);
struct ScalingInfo
{
Color col;
EndgameScalingFunctionBase* fun;
SF* fun;
};
std::map<Key, EndgameEvaluationFunctionBase*> EEFmap;
std::map<Key, EF*> EEFmap;
std::map<Key, ScalingInfo> ESFmap;
};
@ -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>("KPK");
add_ef<KBNK>("KBNK");
add_ef<KRKP>("KRKP");
add_ef<KRKB>("KRKB");
add_ef<KRKN>("KRKN");
add_ef<KQKR>("KQKR");
add_ef<KBBKN>("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>("KNPK");
add_sf<KRPKR>("KRPKR");
add_sf<KBPKB>("KBPKB");
add_sf<KBPPKB>("KBPPKB");
add_sf<KBPKN>("KBPKN");
add_sf<KRPPKRP>("KRPPKRP");
add_sf<KRPPKRP>("KRPPKRP");
}
EndgameFunctions::~EndgameFunctions() {
for (std::map<Key, EF*>::iterator it = EEFmap.begin(); it != EEFmap.end(); ++it)
delete (*it).second;
for (std::map<Key, ScalingInfo>::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<Key, EndgameEvaluationFunctionBase*>(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<EndgameType et>
void EndgameFunctions::add_ef(const string& keyCode) {
ScalingInfo s = {c, f};
ESFmap.insert(std::pair<Key, ScalingInfo>(buildKey(keyCode), s));
EEFmap.insert(std::pair<Key, EF*>(buildKey(keyCode), new EvaluationFunction<et>(WHITE)));
EEFmap.insert(std::pair<Key, EF*>(buildKey(swapColors(keyCode)), new EvaluationFunction<et>(BLACK)));
}
template<EndgameType et>
void EndgameFunctions::add_sf(const string& keyCode) {
ScalingInfo s1 = {WHITE, new ScalingFunction<et>(WHITE)};
ScalingInfo s2 = {BLACK, new ScalingFunction<et>(BLACK)};
ESFmap.insert(std::pair<Key, ScalingInfo>(buildKey(keyCode), s1));
ESFmap.insert(std::pair<Key, ScalingInfo>(buildKey(swapColors(keyCode)), s2));
}
EndgameEvaluationFunctionBase* EndgameFunctions::getEEF(Key key) const {
std::map<Key, EndgameEvaluationFunctionBase*>::const_iterator it(EEFmap.find(key));
std::map<Key, EF*>::const_iterator it(EEFmap.find(key));
return (it != EEFmap.end() ? it->second : NULL);
}