+ typedef map<Key, EF*> EFMap;
+ typedef map<Key, SF*> SFMap;
+
+ // Endgame evaluation and scaling functions accessed direcly and not through
+ // the function maps because correspond to more then one material hash key.
+ EvaluationFunction<KmmKm> EvaluateKmmKm[] = { EvaluationFunction<KmmKm>(WHITE), EvaluationFunction<KmmKm>(BLACK) };
+ EvaluationFunction<KXK> EvaluateKXK[] = { EvaluationFunction<KXK>(WHITE), EvaluationFunction<KXK>(BLACK) };
+ ScalingFunction<KBPsK> ScaleKBPsK[] = { ScalingFunction<KBPsK>(WHITE), ScalingFunction<KBPsK>(BLACK) };
+ ScalingFunction<KQKRPs> ScaleKQKRPs[] = { ScalingFunction<KQKRPs>(WHITE), ScalingFunction<KQKRPs>(BLACK) };
+ ScalingFunction<KPsK> ScaleKPsK[] = { ScalingFunction<KPsK>(WHITE), ScalingFunction<KPsK>(BLACK) };
+ ScalingFunction<KPKP> ScaleKPKP[] = { ScalingFunction<KPKP>(WHITE), ScalingFunction<KPKP>(BLACK) };
+
+ // Helper templates used to detect a given material distribution
+ template<Color Us> bool is_KXK(const Position& pos) {
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ return pos.non_pawn_material(Them) == VALUE_ZERO
+ && pos.piece_count(Them, PAWN) == 0
+ && pos.non_pawn_material(Us) >= RookValueMidgame;
+ }
+
+ template<Color Us> bool is_KBPsK(const Position& pos) {
+ return pos.non_pawn_material(Us) == BishopValueMidgame
+ && pos.piece_count(Us, BISHOP) == 1
+ && pos.piece_count(Us, PAWN) >= 1;
+ }
+
+ template<Color Us> bool is_KQKRPs(const Position& pos) {
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+ return pos.piece_count(Us, PAWN) == 0
+ && pos.non_pawn_material(Us) == QueenValueMidgame
+ && pos.piece_count(Us, QUEEN) == 1
+ && pos.piece_count(Them, ROOK) == 1
+ && pos.piece_count(Them, PAWN) >= 1;
+ }