- const Value BishopPairMidgameBonus = Value(100);
- const Value BishopPairEndgameBonus = Value(100);
-
- Key KRPKRMaterialKey, KRKRPMaterialKey;
- Key KNNKMaterialKey, KKNNMaterialKey;
- Key KBPKBMaterialKey, KBKBPMaterialKey;
- Key KBPKNMaterialKey, KNKBPMaterialKey;
- Key KNPKMaterialKey, KKNPMaterialKey;
- Key KPKPMaterialKey;
- Key KRPPKRPMaterialKey, KRPKRPPMaterialKey;
-
- std::map<Key, EndgameEvaluationFunction*> EEFmap;
-
- void EEFAdd(Key k, EndgameEvaluationFunction* f) {
-
- EEFmap.insert(std::pair<Key, EndgameEvaluationFunction*>(k, f));
- }
-}
-
-
-////
-//// Functions
-////
-
-/// MaterialInfo::init() is called during program initialization. It
-/// precomputes material hash keys for a few basic endgames, in order
-/// to make it easy to recognize such endgames when they occur.
-
-void MaterialInfo::init() {
-
- typedef Key ZM[2][8][16];
- const ZM& z = Position::zobMaterial;
-
- static const Color W = WHITE;
- static const Color B = BLACK;
-
- EEFAdd(z[W][PAWN][1], &EvaluateKPK);
- EEFAdd(z[B][PAWN][1], &EvaluateKKP);
-
- EEFAdd(z[W][BISHOP][1] ^ z[W][KNIGHT][1], &EvaluateKBNK);
- EEFAdd(z[B][BISHOP][1] ^ z[B][KNIGHT][1], &EvaluateKKBN);
- EEFAdd(z[W][ROOK][1] ^ z[B][PAWN][1], &EvaluateKRKP);
- EEFAdd(z[W][PAWN][1] ^ z[B][ROOK][1], &EvaluateKPKR);
- EEFAdd(z[W][ROOK][1] ^ z[B][BISHOP][1], &EvaluateKRKB);
- EEFAdd(z[W][BISHOP][1] ^ z[B][ROOK][1], &EvaluateKBKR);
- EEFAdd(z[W][ROOK][1] ^ z[B][KNIGHT][1], &EvaluateKRKN);
- EEFAdd(z[W][KNIGHT][1] ^ z[B][ROOK][1], &EvaluateKNKR);
- EEFAdd(z[W][QUEEN][1] ^ z[B][ROOK][1], &EvaluateKQKR);
- EEFAdd(z[W][ROOK][1] ^ z[B][QUEEN][1], &EvaluateKRKQ);
-
- KRPKRMaterialKey = z[W][ROOK][1]
- ^ z[W][PAWN][1]
- ^ z[B][ROOK][1];
-
- KRKRPMaterialKey = z[W][ROOK][1]
- ^ z[B][ROOK][1]
- ^ z[B][PAWN][1];
-
- KRPPKRPMaterialKey =
- z[W][ROOK][1] ^
- z[W][PAWN][1] ^
- z[W][PAWN][2] ^
- z[B][ROOK][1] ^
- z[B][PAWN][1];
- KRPKRPPMaterialKey =
- z[W][ROOK][1] ^
- z[W][PAWN][1] ^
- z[B][ROOK][1] ^
- z[B][PAWN][1] ^
- z[B][PAWN][2];
- KNNKMaterialKey =
- z[W][KNIGHT][1] ^
- z[W][KNIGHT][2];
- KKNNMaterialKey =
- z[B][KNIGHT][1] ^
- z[B][KNIGHT][2];
- KBPKBMaterialKey =
- z[W][BISHOP][1] ^
- z[W][PAWN][1] ^
- z[B][BISHOP][1];
- KBKBPMaterialKey =
- z[W][BISHOP][1] ^
- z[B][BISHOP][1] ^
- z[B][PAWN][1];
- KBPKNMaterialKey =
- z[W][BISHOP][1] ^
- z[W][PAWN][1] ^
- z[B][KNIGHT][1];
- KNKBPMaterialKey =
- z[W][KNIGHT][1] ^
- z[B][BISHOP][1] ^
- z[B][PAWN][1];
- KNPKMaterialKey =
- z[W][KNIGHT][1] ^
- z[W][PAWN][1];
- KKNPMaterialKey =
- z[B][KNIGHT][1] ^
- z[B][PAWN][1];
- KPKPMaterialKey =
- z[W][PAWN][1] ^
- z[B][PAWN][1];
-
-
-}
-
-
-/// Constructor for the MaterialInfoTable class.
-
-MaterialInfoTable::MaterialInfoTable(unsigned numOfEntries) {
+ // Polynomial material imbalance parameters
+
+ const int QuadraticOurs[][PIECE_TYPE_NB] = {
+ // OUR PIECES
+ // pair pawn knight bishop rook queen
+ {1667 }, // Bishop pair
+ { 40, 2 }, // Pawn
+ { 32, 255, -3 }, // Knight OUR PIECES
+ { 0, 104, 4, 0 }, // Bishop
+ { -26, -2, 47, 105, -149 }, // Rook
+ {-185, 24, 122, 137, -134, 0 } // Queen
+ };
+
+ const int QuadraticTheirs[][PIECE_TYPE_NB] = {
+ // THEIR PIECES
+ // pair pawn knight bishop rook queen
+ { 0 }, // Bishop pair
+ { 36, 0 }, // Pawn
+ { 9, 63, 0 }, // Knight OUR PIECES
+ { 59, 65, 42, 0 }, // Bishop
+ { 46, 39, 24, -24, 0 }, // Rook
+ { 101, 100, -37, 141, 268, 0 } // Queen
+ };
+
+ // Endgame evaluation and scaling functions are accessed directly and not through
+ // the function maps because they correspond to more than one material hash key.
+ Endgame<KXK> EvaluateKXK[] = { Endgame<KXK>(WHITE), Endgame<KXK>(BLACK) };
+
+ Endgame<KBPsK> ScaleKBPsK[] = { Endgame<KBPsK>(WHITE), Endgame<KBPsK>(BLACK) };
+ Endgame<KQKRPs> ScaleKQKRPs[] = { Endgame<KQKRPs>(WHITE), Endgame<KQKRPs>(BLACK) };
+ Endgame<KPsK> ScaleKPsK[] = { Endgame<KPsK>(WHITE), Endgame<KPsK>(BLACK) };
+ Endgame<KPKP> ScaleKPKP[] = { Endgame<KPKP>(WHITE), Endgame<KPKP>(BLACK) };
+
+ // Helper used to detect a given material distribution
+ bool is_KXK(const Position& pos, Color us) {
+ return !more_than_one(pos.pieces(~us))
+ && pos.non_pawn_material(us) >= RookValueMg;
+ }
+
+ bool is_KBPsKs(const Position& pos, Color us) {
+ return pos.non_pawn_material(us) == BishopValueMg
+ && pos.count<BISHOP>(us) == 1
+ && pos.count<PAWN >(us) >= 1;
+ }
+
+ bool is_KQKRPs(const Position& pos, Color us) {
+ return !pos.count<PAWN>(us)
+ && pos.non_pawn_material(us) == QueenValueMg
+ && pos.count<QUEEN>(us) == 1
+ && pos.count<ROOK>(~us) == 1
+ && pos.count<PAWN>(~us) >= 1;
+ }
+
+ /// imbalance() calculates the imbalance by comparing the piece count of each
+ /// piece type for both colors.
+ template<Color Us>
+ int imbalance(const int pieceCount[][PIECE_TYPE_NB]) {
+
+ const Color Them = (Us == WHITE ? BLACK : WHITE);
+
+ int bonus = 0;
+
+ // Second-degree polynomial material imbalance by Tord Romstad
+ for (int pt1 = NO_PIECE_TYPE; pt1 <= QUEEN; ++pt1)
+ {
+ if (!pieceCount[Us][pt1])
+ continue;
+
+ int v = 0;
+
+ for (int pt2 = NO_PIECE_TYPE; pt2 <= pt1; ++pt2)
+ v += QuadraticOurs[pt1][pt2] * pieceCount[Us][pt2]
+ + QuadraticTheirs[pt1][pt2] * pieceCount[Them][pt2];
+
+ bonus += pieceCount[Us][pt1] * v;
+ }