-
-/// MaterialInfoTable::imbalance() calculates imbalance comparing piece count of each
-/// piece type for both colors.
-
-template<Color Us>
-int MaterialInfoTable::imbalance(const int pieceCount[][8]) {
-
- const Color Them = (Us == WHITE ? BLACK : WHITE);
-
- int pt1, pt2, pc, vv;
- int value = 0;
-
- // Redundancy of major pieces, formula based on Kaufman's paper
- // "The Evaluation of Material Imbalances in Chess"
- if (pieceCount[Us][ROOK] > 0)
- value -= RedundantRookPenalty * (pieceCount[Us][ROOK] - 1)
- + RedundantQueenPenalty * pieceCount[Us][QUEEN];
-
- // Second-degree polynomial material imbalance by Tord Romstad
- for (pt1 = PIECE_TYPE_NONE; pt1 <= QUEEN; pt1++)
- {
- pc = pieceCount[Us][pt1];
- if (!pc)
- continue;
-
- vv = LinearCoefficients[pt1];
-
- for (pt2 = PIECE_TYPE_NONE; pt2 <= pt1; pt2++)
- vv += QuadraticCoefficientsSameColor[pt1][pt2] * pieceCount[Us][pt2]
- + QuadraticCoefficientsOppositeColor[pt1][pt2] * pieceCount[Them][pt2];
-
- value += pc * vv;
- }
- return value;
-}
-
-
-/// MaterialInfoTable::game_phase() calculates the phase given the current
-/// position. Because the phase is strictly a function of the material, it
-/// is stored in MaterialInfo.
-
-Phase MaterialInfoTable::game_phase(const Position& pos) {
-
- Value npm = pos.non_pawn_material(WHITE) + pos.non_pawn_material(BLACK);
-
- if (npm >= MidgameLimit)
- return PHASE_MIDGAME;
-
- if (npm <= EndgameLimit)
- return PHASE_ENDGAME;
-
- return Phase(((npm - EndgameLimit) * 128) / (MidgameLimit - EndgameLimit));
-}
-
-
-/// EndgameFunctions member definitions
-
-EndgameFunctions::EndgameFunctions() {
-
- add<EvaluationFunction<KNNK> >("KNNK");
- add<EvaluationFunction<KPK> >("KPK");
- add<EvaluationFunction<KBNK> >("KBNK");
- add<EvaluationFunction<KRKP> >("KRKP");
- add<EvaluationFunction<KRKB> >("KRKB");
- add<EvaluationFunction<KRKN> >("KRKN");
- add<EvaluationFunction<KQKR> >("KQKR");
- add<EvaluationFunction<KBBKN> >("KBBKN");
-
- add<ScalingFunction<KNPK> >("KNPK");
- add<ScalingFunction<KRPKR> >("KRPKR");
- add<ScalingFunction<KBPKB> >("KBPKB");
- add<ScalingFunction<KBPPKB> >("KBPPKB");
- add<ScalingFunction<KBPKN> >("KBPKN");
- add<ScalingFunction<KRPPKRP> >("KRPPKRP");
-}
-
-EndgameFunctions::~EndgameFunctions() {
-
- for (EFMap::const_iterator it = maps.first.begin(); it != maps.first.end(); ++it)
- delete it->second;
-
- for (SFMap::const_iterator it = maps.second.begin(); it != maps.second.end(); ++it)
- delete it->second;
-}
-
-Key EndgameFunctions::buildKey(const string& keyCode) {
-
- assert(keyCode.length() > 0 && keyCode.length() < 8);
- assert(keyCode[0] == 'K');
-
- string fen;
- bool upcase = false;
-
- // Build up a fen string with the given pieces, note that
- // the fen string could be of an illegal position.
- for (size_t i = 0; i < keyCode.length(); i++)
- {
- if (keyCode[i] == 'K')
- upcase = !upcase;
-
- fen += char(upcase ? toupper(keyCode[i]) : tolower(keyCode[i]));
- }
- fen += char(8 - keyCode.length() + '0');
- fen += "/8/8/8/8/8/8/8 w - -";
- return Position(fen, false, 0).get_material_key();
-}
-
-const string EndgameFunctions::swapColors(const string& keyCode) {
-
- // Build corresponding key for the opposite color: "KBPKN" -> "KNKBP"
- size_t idx = keyCode.find('K', 1);
- return keyCode.substr(idx) + keyCode.substr(0, idx);
-}
-
-template<class T>
-void EndgameFunctions::add(const string& keyCode) {
-
- typedef typename T::Base F;
- typedef map<Key, F*> M;
-
- const_cast<M&>(get<F>()).insert(pair<Key, F*>(buildKey(keyCode), new T(WHITE)));
- const_cast<M&>(get<F>()).insert(pair<Key, F*>(buildKey(swapColors(keyCode)), new T(BLACK)));
-}
-
-template<class T>
-T* EndgameFunctions::get(Key key) const {
-
- typename map<Key, T*>::const_iterator it = get<T>().find(key);
- return it != get<T>().end() ? it->second : NULL;
-}