- const Value BishopPairMidgameBonus = Value(100);
- const Value BishopPairEndgameBonus = Value(100);
-
- Key KPKMaterialKey, KKPMaterialKey;
- Key KBNKMaterialKey, KKBNMaterialKey;
- Key KRKPMaterialKey, KPKRMaterialKey;
- Key KRKBMaterialKey, KBKRMaterialKey;
- Key KRKNMaterialKey, KNKRMaterialKey;
- Key KQKRMaterialKey, KRKQMaterialKey;
- Key KRPKRMaterialKey, KRKRPMaterialKey;
- Key KRPPKRPMaterialKey, KRPKRPPMaterialKey;
- Key KNNKMaterialKey, KKNNMaterialKey;
- Key KBPKBMaterialKey, KBKBPMaterialKey;
- Key KBPKNMaterialKey, KNKBPMaterialKey;
- Key KNPKMaterialKey, KKNPMaterialKey;
- Key KPKPMaterialKey;
+ // Polynomial material imbalance parameters
+
+ constexpr int QuadraticOurs[][PIECE_TYPE_NB] = {
+ // OUR PIECES
+ // pair pawn knight bishop rook queen
+ {1438 }, // Bishop pair
+ { 40, 38 }, // Pawn
+ { 32, 255, -62 }, // Knight OUR PIECES
+ { 0, 104, 4, 0 }, // Bishop
+ { -26, -2, 47, 105, -208 }, // Rook
+ {-189, 24, 117, 133, -134, -6 } // Queen
+ };
+
+ constexpr 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
+ { 97, 100, -42, 137, 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_KBPsK(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]) {
+
+ constexpr 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;
+ }