LCOV - code coverage report
Current view: top level - Source - material.cpp (source / functions) Coverage Total Hit
Test: coverage Lines: 92.2 % 282 260
Test Date: 2026-03-02 16:42:41 Functions: 76.5 % 17 13

            Line data    Source code
       1              : #include "material.hpp"
       2              : 
       3              : #include "attack.hpp"
       4              : #include "dynamicConfig.hpp"
       5              : #include "evalConfig.hpp"
       6              : #include "kpk.hpp"
       7              : #include "logging.hpp"
       8              : #include "positionTools.hpp"
       9              : #include "tools.hpp"
      10              : 
      11              : namespace MaterialHash { // idea from Gull
      12              : 
      13              : // helper function function pointer table
      14              : ScoreType (*helperTable[TotalMat])(const Position &, Color, ScoreType, DepthType);
      15              : 
      16              : // the material cache
      17              : array1d<MaterialHashEntry,TotalMat> materialHashTable;
      18              : 
      19              : #ifndef WITH_MATERIAL_TABLE
      20              : [[nodiscard]] Hash getMaterialHash(const Position::Material &) {
      21              :     return nullHash;
      22              : }
      23              : [[nodiscard]] Hash getMaterialHash2(const Position::Material &mat) {
      24              : #else
      25      5013568 : [[nodiscard]] Hash getMaterialHash(const Position::Material &mat) {
      26              : #endif
      27      5013568 :    if (mat[Co_White][M_q] > 2  || mat[Co_Black][M_q] > 2
      28      5013568 :     || mat[Co_White][M_r] > 2  || mat[Co_Black][M_r] > 2
      29      5012604 :     || mat[Co_White][M_bl] > 2 || mat[Co_Black][M_bl] > 2
      30      5012604 :     || mat[Co_White][M_bd] > 2 || mat[Co_Black][M_bd] > 2
      31      5012604 :     || mat[Co_White][M_n] > 2  || mat[Co_Black][M_n] > 2
      32     10026172 :     || mat[Co_White][M_p] > 8  || mat[Co_Black][M_p] > 8) return nullHash;
      33              : 
      34      5012604 :    return mat[Co_White][M_p]  * MatWP + mat[Co_Black][M_p]  * MatBP
      35      5012604 :         + mat[Co_White][M_n]  * MatWN + mat[Co_Black][M_n]  * MatBN
      36      5012604 :         + mat[Co_White][M_bl] * MatWL + mat[Co_Black][M_bl] * MatBL
      37      5012604 :         + mat[Co_White][M_bd] * MatWD + mat[Co_Black][M_bd] * MatBD
      38      5012604 :         + mat[Co_White][M_r]  * MatWR + mat[Co_Black][M_r]  * MatBR
      39      5012604 :         + mat[Co_White][M_q]  * MatWQ + mat[Co_Black][M_q]  * MatBQ;
      40              : }
      41              : 
      42    105225318 : [[nodiscard]] Position::Material indexToMat(int index) {
      43    105225318 :    Position::Material m = {{{{0}}}};
      44              :    using MatType = Position::Material::value_type::value_type;
      45    105225318 :    m[Co_White][M_q] = static_cast<MatType>(index % 3); index /= 3;
      46    105225318 :    m[Co_Black][M_q] = static_cast<MatType>(index % 3); index /= 3;
      47    105225318 :    m[Co_White][M_r] = static_cast<MatType>(index % 3); index /= 3;
      48    105225318 :    m[Co_Black][M_r] = static_cast<MatType>(index % 3); index /= 3;
      49    105225318 :    m[Co_White][M_bl]= static_cast<MatType>(index % 3); index /= 3;
      50    105225318 :    m[Co_Black][M_bl]= static_cast<MatType>(index % 3); index /= 3;
      51    105225318 :    m[Co_White][M_bd]= static_cast<MatType>(index % 3); index /= 3;
      52    105225318 :    m[Co_Black][M_bd]= static_cast<MatType>(index % 3); index /= 3;
      53    105225318 :    m[Co_White][M_n] = static_cast<MatType>(index % 3); index /= 3;
      54    105225318 :    m[Co_Black][M_n] = static_cast<MatType>(index % 3); index /= 3;
      55    105225318 :    m[Co_White][M_p] = static_cast<MatType>(index % 9); index /= 9;
      56    105225318 :    m[Co_Black][M_p] = static_cast<MatType>(index);
      57    105225318 :    m[Co_White][M_b] = m[Co_White][M_bl] + m[Co_White][M_bd];
      58    105225318 :    m[Co_Black][M_b] = m[Co_Black][M_bl] + m[Co_Black][M_bd];
      59    105225318 :    m[Co_White][M_M] = m[Co_White][M_q] + m[Co_White][M_r];  m[Co_Black][M_M] = m[Co_Black][M_q] + m[Co_Black][M_r];
      60    105225318 :    m[Co_White][M_m] = m[Co_White][M_b] + m[Co_White][M_n];  m[Co_Black][M_m] = m[Co_Black][M_b] + m[Co_Black][M_n];
      61    105225318 :    m[Co_White][M_t] = m[Co_White][M_M] + m[Co_White][M_m];  m[Co_Black][M_t] = m[Co_Black][M_M] + m[Co_Black][M_m];
      62    105225318 :    return m;
      63              : }
      64              : 
      65         2090 : [[nodiscard]] Position::Material getMatReverseColor(const Position::Material &mat) {
      66         2090 :    Position::Material rev = {{{{0}}}};
      67         2090 :    rev[Co_White][M_k]  = mat[Co_Black][M_k];   rev[Co_Black][M_k]  = mat[Co_White][M_k];
      68         2090 :    rev[Co_White][M_q]  = mat[Co_Black][M_q];   rev[Co_Black][M_q]  = mat[Co_White][M_q];
      69         2090 :    rev[Co_White][M_r]  = mat[Co_Black][M_r];   rev[Co_Black][M_r]  = mat[Co_White][M_r];
      70         2090 :    rev[Co_White][M_b]  = mat[Co_Black][M_b];   rev[Co_Black][M_b]  = mat[Co_White][M_b];
      71         2090 :    rev[Co_White][M_bl] = mat[Co_Black][M_bl];  rev[Co_Black][M_bl] = mat[Co_White][M_bl];
      72         2090 :    rev[Co_White][M_bd] = mat[Co_Black][M_bd];  rev[Co_Black][M_bd] = mat[Co_White][M_bd];
      73         2090 :    rev[Co_White][M_n]  = mat[Co_Black][M_n];   rev[Co_Black][M_n]  = mat[Co_White][M_n];
      74         2090 :    rev[Co_White][M_p]  = mat[Co_Black][M_p];   rev[Co_Black][M_p]  = mat[Co_White][M_p];
      75         2090 :    rev[Co_White][M_M]  = mat[Co_Black][M_M];   rev[Co_Black][M_M]  = mat[Co_White][M_M];
      76         2090 :    rev[Co_White][M_m]  = mat[Co_Black][M_m];   rev[Co_Black][M_m]  = mat[Co_White][M_m];
      77         2090 :    rev[Co_White][M_t]  = mat[Co_Black][M_t];   rev[Co_Black][M_t]  = mat[Co_White][M_t];
      78         2090 :    return rev;
      79              : }
      80              : 
      81         2090 : [[nodiscard]] Position::Material materialFromString(const std::string &strMat) {
      82         2090 :    Position::Material mat = {{{{0}}}};
      83              :    Color c = Co_Black;
      84        11902 :    for (const auto & it : strMat) {
      85         9812 :       switch (it) {
      86         4180 :          case 'K':
      87              :             c = ~c;
      88         4180 :             mat[c][M_k] += 1;
      89         4180 :             break;
      90          946 :          case 'Q':
      91          946 :             mat[c][M_q] += 1;
      92          946 :             mat[c][M_M] += 1;
      93          946 :             mat[c][M_t] += 1;
      94          946 :             break;
      95         1144 :          case 'R':
      96         1144 :             mat[c][M_r] += 1;
      97         1144 :             mat[c][M_M] += 1;
      98         1144 :             mat[c][M_t] += 1;
      99         1144 :             break;
     100         1144 :          case 'L':
     101         1144 :             mat[c][M_bl] += 1;
     102         1144 :             mat[c][M_b] += 1;
     103         1144 :             mat[c][M_m] += 1;
     104         1144 :             mat[c][M_t] += 1;
     105         1144 :             break;
     106         1144 :          case 'D':
     107         1144 :             mat[c][M_bd] += 1;
     108         1144 :             mat[c][M_b] += 1;
     109         1144 :             mat[c][M_m] += 1;
     110         1144 :             mat[c][M_t] += 1;
     111         1144 :             break;
     112         1056 :          case 'N':
     113         1056 :             mat[c][M_n] += 1;
     114         1056 :             mat[c][M_m] += 1;
     115         1056 :             mat[c][M_t] += 1;
     116         1056 :             break;
     117          198 :          case 'P': mat[c][M_p] += 1; break;
     118            0 :          default: Logging::LogIt(Logging::logFatal) << "Bad char in material definition";
     119              :       }
     120              :    }
     121         2090 :    return mat;
     122              : }
     123              : 
     124            0 : [[nodiscard]] Terminaison reverseTerminaison(Terminaison t) {
     125            0 :    switch (t) {
     126              :    case Ter_Unknown: case Ter_Draw: case Ter_MaterialDraw: case Ter_LikelyDraw: case Ter_HardToWin: return t;
     127           66 :    case Ter_WhiteWin:             return Ter_BlackWin;
     128          264 :    case Ter_WhiteWinWithHelper:   return Ter_BlackWinWithHelper;
     129            0 :    case Ter_BlackWin:             return Ter_WhiteWin;
     130            0 :    case Ter_BlackWinWithHelper:   return Ter_WhiteWinWithHelper;
     131            0 :    default:                       return Ter_Unknown;
     132              :    }
     133              : }
     134              : 
     135              : const array1d<ScoreType,NbSquare> pushToEdges = {
     136              :    100, 90, 80, 70, 70, 80, 90, 100,
     137              :    90, 70, 60, 50, 50, 60, 70,  90,
     138              :    80, 60, 40, 30, 30, 40, 60,  80,
     139              :    70, 50, 30,  0,  0, 30, 50,  70,
     140              :    70, 50, 30,  0,  0, 30, 50,  70,
     141              :    80, 60, 40, 30, 30, 40, 60,  80,
     142              :    90, 70, 60, 50, 50, 60, 70,  90,
     143              :    100, 90, 80, 70, 70, 80, 90, 100
     144              : };
     145              : 
     146              : const array1d<ScoreType,NbSquare> pushToCorners = {
     147              :    200, 190, 180, 170, 160, 150, 140, 130,
     148              :    190, 180, 170, 160, 150, 140, 130, 140,
     149              :    180, 170, 155, 140, 140, 125, 140, 150,
     150              :    170, 160, 140, 120, 110, 140, 150, 160,
     151              :    160, 150, 140, 110, 120, 140, 160, 170,
     152              :    150, 140, 125, 140, 140, 155, 170, 180,
     153              :    140, 130, 140, 150, 160, 170, 180, 190,
     154              :    130, 140, 150, 160, 170, 180, 190, 200
     155              : };
     156              : 
     157              : const array1d<ScoreType,8> pushClose = {0, 0, 100, 80, 60, 40, 20, 10};
     158              : //const array1d<ScoreType,8> pushAway = { 0, 5, 20, 40, 60, 80, 90, 100 };
     159              : 
     160           20 : ScoreType helperKXK(const Position &p, Color winningSide, ScoreType s, DepthType height) {
     161              :    if (p.c != winningSide) {
     162              :      ///@todo stale mate detection for losing side
     163              :    }
     164           20 :    const Square    winningK = p.king[winningSide];
     165           20 :    const Square    losingK  = p.king[~winningSide];
     166           20 :    const ScoreType sc       = 12 * pushToEdges[losingK] + pushClose[chebyshevDistance(winningK, losingK)];
     167           20 :    return clampScore(s + ((winningSide == Co_White) ? (sc + WIN - height + 1) : (-sc - WIN + height)));
     168              : }
     169              : 
     170            0 : ScoreType helperKmmK(const Position &p, Color winningSide, ScoreType s, DepthType height) {
     171            0 :    Square winningK = p.king[winningSide];
     172            0 :    Square losingK  = p.king[~winningSide];
     173            0 :    if ((p.allBishop() & BB::whiteSquare) != 0) {
     174              :       winningK = VFlip(winningK);
     175              :       losingK  = VFlip(losingK);
     176              :    }
     177            0 :    const ScoreType sc = 12 * pushToCorners[losingK] + pushClose[chebyshevDistance(winningK, losingK)];
     178            0 :    return clampScore(s + ((winningSide == Co_White) ? (sc + WIN - height + 1) : (-sc - WIN + height)));
     179              : }
     180              : 
     181            0 : ScoreType helperDummy(const Position &, Color, ScoreType, DepthType) { return 0; } ///@todo not 0 for debug purpose ??
     182              : 
     183              : #if !defined(WITH_SMALL_MEMORY)
     184           11 : ScoreType helperKPK(const Position &p, Color winningSide, [[maybe_unused]] ScoreType s, DepthType height) {
     185           11 :    const Square psq  = KPK::normalizeSquare(p, winningSide, BBTools::SquareFromBitBoard(p.pieces_const<P_wp>(winningSide))); // we know there is at least one pawn
     186           11 :    const Square wksq = KPK::normalizeSquare(p, winningSide, p.king[winningSide]);
     187           11 :    const Square lksq = KPK::normalizeSquare(p, winningSide, p.king[~winningSide]);
     188           11 :    if (!KPK::probe(wksq, psq, lksq, winningSide == p.c ? Co_White : Co_Black)) {
     189            8 :       if (DynamicConfig::armageddon) {
     190            0 :          if (p.c == Co_White) return matedScore(height);
     191            0 :          else return matingScore(height-1);
     192              :       }
     193              :       return 0; // shall be drawScore but we don't care, this is not 3rep
     194              :    }
     195            6 :    return clampScore(((winningSide == Co_White) ? +1 : -1) * (WIN + valueEG(P_wp) + 10 * SQRANK(psq)));
     196              : }
     197              : #endif
     198              : 
     199            0 : ScoreType helperKBPK(const Position & p, Color winningSide, ScoreType s, DepthType height) {
     200            0 :    const Square winningPawn = BBTools::SquareFromBitBoard(p.allPawn()); // assume only one pawn
     201            0 :    const Square promSquare = winningSide == Co_White ? PromotionSquare<Co_White>(winningPawn) : PromotionSquare<Co_Black>(winningPawn);
     202            0 :    const Color bc = (p.allBishop() & BB::whiteSquare) ? Co_White : Co_Black;
     203            0 :    const Color pc = (SquareToBitboard(promSquare) & BB::whiteSquare) ? Co_White : Co_Black;
     204            0 :    if ( bc != pc ){
     205              :       // let's approximate score by the KPK one ...
     206            0 :       return helperKPK(p,winningSide,0,height);
     207              :    }
     208              :    else {
     209              :       return s;
     210              :    }
     211              : }
     212              : 
     213              : // Second-degree polynomial material imbalance, by Tord Romstad (old version, not the current Stockfish stuff)
     214    210450636 : EvalScore Imbalance(const Position::Material &mat, Color c) {
     215              :    EvalScore bonus = 0;
     216   1262703816 :    for (Mat m1 = M_p; m1 <= M_q; ++m1) {
     217   1052253180 :       if (!mat[c][m1]) continue;
     218   3086609328 :       for (Mat m2 = M_p; m2 <= m1; ++m2) {
     219   2291573592 :          bonus += EvalConfig::imbalance_mines[m1 - 1][m2 - 1] * mat[c][m1] * mat[c][m2] +
     220   4583147184 :                   EvalConfig::imbalance_theirs[m1 - 1][m2 - 1] * mat[c][m1] * mat[~c][m2];
     221              :       }
     222              :    }
     223    210450636 :    return bonus / 16;
     224              : }
     225              : 
     226              : #pragma GCC diagnostic push
     227              : #pragma GCC diagnostic ignored "-Wconversion"
     228              : 
     229           22 : void InitMaterialScore(bool display) {
     230           44 :    if (display) Logging::LogIt(Logging::logInfo) << "Material hash init";
     231    105225340 :    for (int k = 0; k < TotalMat; ++k) {
     232    105225318 :       const Position::Material mat = indexToMat(k);
     233              :       // MG
     234    105225318 :       const ScoreType matPieceScoreW = mat[Co_White][M_q] * absValue(P_wq) + mat[Co_White][M_r] * absValue(P_wr) +
     235    105225318 :                                        mat[Co_White][M_b] * absValue(P_wb) + mat[Co_White][M_n] * absValue(P_wn);
     236    105225318 :       const ScoreType matPieceScoreB = mat[Co_Black][M_q] * absValue(P_wq) + mat[Co_Black][M_r] * absValue(P_wr) +
     237    105225318 :                                        mat[Co_Black][M_b] * absValue(P_wb) + mat[Co_Black][M_n] * absValue(P_wn);
     238    105225318 :       const ScoreType matPawnScoreW = mat[Co_White][M_p] * absValue(P_wp);
     239    105225318 :       const ScoreType matPawnScoreB = mat[Co_Black][M_p] * absValue(P_wp);
     240    105225318 :       const ScoreType matScoreW     = matPieceScoreW + matPawnScoreW;
     241    105225318 :       const ScoreType matScoreB     = matPieceScoreB + matPawnScoreB;
     242              :       // EG
     243    105225318 :       const ScoreType matPieceScoreWEG = mat[Co_White][M_q] * absValueEG(P_wq) + mat[Co_White][M_r] * absValueEG(P_wr) +
     244    105225318 :                                          mat[Co_White][M_b] * absValueEG(P_wb) + mat[Co_White][M_n] * absValueEG(P_wn);
     245    105225318 :       const ScoreType matPieceScoreBEG = mat[Co_Black][M_q] * absValueEG(P_wq) + mat[Co_Black][M_r] * absValueEG(P_wr) +
     246    105225318 :                                          mat[Co_Black][M_b] * absValueEG(P_wb) + mat[Co_Black][M_n] * absValueEG(P_wn);
     247    105225318 :       const ScoreType matPawnScoreWEG = mat[Co_White][M_p] * absValueEG(P_wp);
     248    105225318 :       const ScoreType matPawnScoreBEG = mat[Co_Black][M_p] * absValueEG(P_wp);
     249    105225318 :       const ScoreType matScoreWEG     = matPieceScoreWEG + matPawnScoreWEG;
     250    105225318 :       const ScoreType matScoreBEG     = matPieceScoreBEG + matPawnScoreBEG;
     251              : #ifdef WITH_EVAL_TUNING
     252              :       const EvalScore imbalanceW = {0, 0};
     253              :       const EvalScore imbalanceB = {0, 0};
     254              : #else
     255    105225318 :       const EvalScore imbalanceW = Imbalance(mat, Co_White);
     256    105225318 :       const EvalScore imbalanceB = Imbalance(mat, Co_Black);
     257              : #endif
     258    105225318 :       ScoreType dummyW = 0;
     259    105225318 :       ScoreType dummyB = 0;
     260    105225318 :       materialHashTable[k].setGamePhase(gamePhase(mat, dummyW, dummyB));
     261              :       materialHashTable[k].score =
     262    210450636 :       EvalScore(imbalanceW[MG] + matScoreW - (imbalanceB[MG] + matScoreB), imbalanceW[EG] + matScoreWEG - (imbalanceB[EG] + matScoreBEG));
     263              :    }
     264           44 :    if (display) Logging::LogIt(Logging::logInfo) << "...Done";
     265           22 : }
     266              : 
     267              : #pragma GCC diagnostic pop
     268              : 
     269           22 : void MaterialHashInitializer::init() {
     270           22 :    Logging::LogIt(Logging::logInfo) << "Material hash total : " << TotalMat;
     271           22 :    Logging::LogIt(Logging::logInfo) << "Material hash size : " << TotalMat * sizeof(MaterialHashEntry) / 1024 / 1024 << "Mb";
     272              : 
     273              : #ifdef WITH_MATERIAL_TABLE
     274           22 :    InitMaterialScore();
     275    105225340 :    for (size_t k = 0; k < TotalMat; ++k) helperTable[k] = &helperDummy;
     276              : 
     277              : #define DEF_MAT(x,t)     const Position::Material MAT##x = materialFromString(TO_STR(x)); MaterialHashInitializer LINE_NAME(dummyMaterialInitializer,MAT##x)( MAT##x ,t   );
     278              : #define DEF_MAT_H(x,t,h) const Position::Material MAT##x = materialFromString(TO_STR(x)); MaterialHashInitializer LINE_NAME(dummyMaterialInitializer,MAT##x)( MAT##x ,t, h);
     279              : #define DEF_MAT_REV(rev,x)     const Position::Material MAT##rev = MaterialHash::getMatReverseColor(MAT##x); MaterialHashInitializer LINE_NAME(dummyMaterialInitializerRev,MAT##x)( MAT##rev,reverseTerminaison(materialHashTable[getMaterialHash(MAT##x)].t)   );
     280              : #define DEF_MAT_REV_H(rev,x,h) const Position::Material MAT##rev = MaterialHash::getMatReverseColor(MAT##x); MaterialHashInitializer LINE_NAME(dummyMaterialInitializerRev,MAT##x)( MAT##rev,reverseTerminaison(materialHashTable[getMaterialHash(MAT##x)].t), h);
     281              : 
     282              :    // WARNING : we assume STM has no capture
     283              : 
     284              :    ///@todo some Ter_MaterialDraw are Ter_Draw (FIDE)
     285              : 
     286              :    // other FIDE draw
     287              :    //DEF_MAT(KLKL,   Ter_MaterialDraw)  // useless
     288              :    //DEF_MAT(KDKD,   Ter_MaterialDraw)  // useless
     289              : 
     290              :    // sym (and pseudo sym) : all should be draw (or very nearly)
     291              :    //DEF_MAT(KK,     Ter_MaterialDraw)  // this is invalid hash
     292              :    //DEF_MAT(KQQKQQ, Ter_LikelyDraw)    // useless
     293              :    //DEF_MAT(KQKQ,   Ter_LikelyDraw)    // useless
     294              :    //DEF_MAT(KRRKRR, Ter_LikelyDraw)    // useless
     295              :    //DEF_MAT(KRKR,   Ter_LikelyDraw)    // useless
     296              :    //DEF_MAT(KLDKLD, Ter_MaterialDraw)  // useless
     297              :    //DEF_MAT(KLLKLL, Ter_MaterialDraw)  // useless
     298              :    //DEF_MAT(KDDKDD, Ter_MaterialDraw)  // useless
     299              :    //DEF_MAT(KNNKNN, Ter_MaterialDraw)  // useless
     300              :    //DEF_MAT(KNKN  , Ter_MaterialDraw)  // useless
     301              : 
     302              :    //DEF_MAT(KLDKLL, Ter_MaterialDraw)        DEF_MAT_REV(KLLKLD, KLDKLL)  // useless
     303              :    //DEF_MAT(KLDKDD, Ter_MaterialDraw)        DEF_MAT_REV(KDDKLD, KLDKDD)  // useless
     304              :    //DEF_MAT(KLKD,   Ter_MaterialDraw)        DEF_MAT_REV(KDKL,   KLKD)    // useless
     305              : 
     306              :    // 2M M
     307           44 :    DEF_MAT(KQQKQ, Ter_WhiteWin)             DEF_MAT_REV(KQKQQ, KQQKQ)
     308           44 :    DEF_MAT(KQQKR, Ter_WhiteWin)             DEF_MAT_REV(KRKQQ, KQQKR)
     309           44 :    DEF_MAT(KRRKQ, Ter_LikelyDraw)           DEF_MAT_REV(KQKRR, KRRKQ)
     310           44 :    DEF_MAT(KRRKR, Ter_WhiteWin)             DEF_MAT_REV(KRKRR, KRRKR)
     311           44 :    DEF_MAT(KQRKQ, Ter_WhiteWin)             DEF_MAT_REV(KQKQR, KQRKQ)
     312           44 :    DEF_MAT(KQRKR, Ter_WhiteWin)             DEF_MAT_REV(KRKQR, KQRKR)
     313              : 
     314              :    // 2M m (all easy wins)
     315           44 :    DEF_MAT(KQQKL, Ter_WhiteWin)             DEF_MAT_REV(KLKQQ, KQQKL)
     316           44 :    DEF_MAT(KRRKL, Ter_WhiteWin)             DEF_MAT_REV(KLKRR, KRRKL)
     317           44 :    DEF_MAT(KQRKL, Ter_WhiteWin)             DEF_MAT_REV(KLKQR, KQRKL)
     318           44 :    DEF_MAT(KQQKD, Ter_WhiteWin)             DEF_MAT_REV(KDKQQ, KQQKD)
     319           44 :    DEF_MAT(KRRKD, Ter_WhiteWin)             DEF_MAT_REV(KDKRR, KRRKD)
     320           44 :    DEF_MAT(KQRKD, Ter_WhiteWin)             DEF_MAT_REV(KDKQR, KQRKD)
     321           44 :    DEF_MAT(KQQKN, Ter_WhiteWin)             DEF_MAT_REV(KNKQQ, KQQKN)
     322           44 :    DEF_MAT(KRRKN, Ter_WhiteWin)             DEF_MAT_REV(KNKRR, KRRKN)
     323           44 :    DEF_MAT(KQRKN, Ter_WhiteWin)             DEF_MAT_REV(KNKQR, KQRKN)
     324              : 
     325              :    // 2m M
     326           44 :    DEF_MAT(KLDKQ, Ter_HardToWin)            DEF_MAT_REV(KQKLD,KLDKQ)
     327           44 :    DEF_MAT(KLDKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKLD,KLDKR)
     328           44 :    DEF_MAT(KLLKQ, Ter_HardToWin)            DEF_MAT_REV(KQKLL,KLLKQ)
     329           44 :    DEF_MAT(KLLKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKLL,KLLKR)
     330           44 :    DEF_MAT(KDDKQ, Ter_HardToWin)            DEF_MAT_REV(KQKDD,KDDKQ)
     331           44 :    DEF_MAT(KDDKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKDD,KDDKR)
     332           44 :    DEF_MAT(KNNKQ, Ter_HardToWin)            DEF_MAT_REV(KQKNN,KNNKQ)
     333           44 :    DEF_MAT(KNNKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKNN,KNNKR)
     334           44 :    DEF_MAT(KLNKQ, Ter_HardToWin)            DEF_MAT_REV(KQKLN,KLNKQ)
     335           44 :    DEF_MAT(KLNKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKLN,KLNKR)
     336           44 :    DEF_MAT(KDNKQ, Ter_HardToWin)            DEF_MAT_REV(KQKDN,KDNKQ)
     337           44 :    DEF_MAT(KDNKR, Ter_LikelyDraw)         DEF_MAT_REV(KRKDN,KDNKR)
     338              : 
     339              :    // 2m m : all draw
     340           44 :    DEF_MAT(KLDKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKLD,KLDKL)
     341           44 :    DEF_MAT(KLDKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKLD,KLDKD)
     342           44 :    DEF_MAT(KLDKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKLD,KLDKN)
     343           44 :    DEF_MAT(KLLKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKLL,KLLKL)
     344           44 :    DEF_MAT(KLLKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKLL,KLLKD)
     345           44 :    DEF_MAT(KLLKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKLL,KLLKN)
     346           44 :    DEF_MAT(KDDKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKDD,KDDKL)
     347           44 :    DEF_MAT(KDDKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKDD,KDDKD)
     348           44 :    DEF_MAT(KDDKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKDD,KDDKN)
     349           44 :    DEF_MAT(KNNKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKNN,KNNKL)
     350           44 :    DEF_MAT(KNNKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKNN,KNNKD)
     351           44 :    DEF_MAT(KNNKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKNN,KNNKN)
     352           44 :    DEF_MAT(KLNKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKLN,KLNKL)
     353           44 :    DEF_MAT(KLNKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKLN,KLNKD)
     354           44 :    DEF_MAT(KLNKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKLN,KLNKN)
     355           44 :    DEF_MAT(KDNKL, Ter_LikelyDraw)         DEF_MAT_REV(KLKDN,KDNKL)
     356           44 :    DEF_MAT(KDNKD, Ter_LikelyDraw)         DEF_MAT_REV(KDKDN,KDNKD)
     357           44 :    DEF_MAT(KDNKN, Ter_LikelyDraw)         DEF_MAT_REV(KNKDN,KDNKN)
     358              : 
     359              :    // Q x : all should be win (against rook with helper)
     360           66 :    DEF_MAT_H(KQKR, Ter_WhiteWinWithHelper,&helperKXK)      DEF_MAT_REV_H(KRKQ,KQKR,&helperKXK)
     361           66 :    DEF_MAT_H(KQKL, Ter_WhiteWinWithHelper,&helperKXK)      DEF_MAT_REV_H(KLKQ,KQKL,&helperKXK)
     362           66 :    DEF_MAT_H(KQKD, Ter_WhiteWinWithHelper,&helperKXK)      DEF_MAT_REV_H(KDKQ,KQKD,&helperKXK)
     363           66 :    DEF_MAT_H(KQKN, Ter_WhiteWinWithHelper,&helperKXK)      DEF_MAT_REV_H(KNKQ,KQKN,&helperKXK)
     364              : 
     365              :    // R x : all should be draw
     366           44 :    DEF_MAT(KRKL, Ter_LikelyDraw)            DEF_MAT_REV(KLKR,KRKL)
     367           44 :    DEF_MAT(KRKD, Ter_LikelyDraw)            DEF_MAT_REV(KDKR,KRKD)
     368           44 :    DEF_MAT(KRKN, Ter_LikelyDraw)            DEF_MAT_REV(KNKR,KRKN)
     369              : 
     370              :    // B x : all are draw
     371           44 :    DEF_MAT(KLKN, Ter_MaterialDraw)          DEF_MAT_REV(KNKL,KLKN)
     372           44 :    DEF_MAT(KDKN, Ter_MaterialDraw)          DEF_MAT_REV(KNKD,KDKN)
     373              : 
     374              :    // X 0 : QR win, BN draw
     375           66 :    DEF_MAT_H(KQK, Ter_WhiteWinWithHelper,&helperKXK)   DEF_MAT_REV_H(KKQ,KQK,&helperKXK)
     376           66 :    DEF_MAT_H(KRK, Ter_WhiteWinWithHelper,&helperKXK)   DEF_MAT_REV_H(KKR,KRK,&helperKXK)
     377           44 :    DEF_MAT(KLK, Ter_MaterialDraw)                      DEF_MAT_REV(KKL,KLK)
     378           44 :    DEF_MAT(KDK, Ter_MaterialDraw)                      DEF_MAT_REV(KKD,KDK)
     379           44 :    DEF_MAT(KNK, Ter_MaterialDraw)                      DEF_MAT_REV(KKN,KNK)
     380              : 
     381              :    // 2X 0 : all win except LL, DD, NN
     382           44 :    DEF_MAT(KQQK, Ter_WhiteWin)                         DEF_MAT_REV(KKQQ,KQQK)
     383           44 :    DEF_MAT(KRRK, Ter_WhiteWin)                         DEF_MAT_REV(KKRR,KRRK)
     384           66 :    DEF_MAT_H(KLDK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKLD,KLDK,&helperKmmK)
     385           44 :    DEF_MAT(KLLK, Ter_MaterialDraw)                     DEF_MAT_REV(KKLL,KLLK)
     386           44 :    DEF_MAT(KDDK, Ter_MaterialDraw)                     DEF_MAT_REV(KKDD,KDDK)
     387           44 :    DEF_MAT(KNNK, Ter_MaterialDraw)                     DEF_MAT_REV(KKNN,KNNK)
     388           66 :    DEF_MAT_H(KLNK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKLN,KLNK,&helperKmmK)
     389           66 :    DEF_MAT_H(KDNK, Ter_WhiteWinWithHelper,&helperKmmK) DEF_MAT_REV_H(KKDN,KDNK,&helperKmmK)
     390              : 
     391              :    // Rm R : draws
     392           44 :    DEF_MAT(KRNKR, Ter_LikelyDraw)            DEF_MAT_REV(KRKRN,KRNKR)
     393           44 :    DEF_MAT(KRLKR, Ter_LikelyDraw)            DEF_MAT_REV(KRKRL,KRLKR)
     394           44 :    DEF_MAT(KRDKR, Ter_LikelyDraw)            DEF_MAT_REV(KRKRD,KRDKR)
     395              : 
     396              :    // Rm m : draws
     397           44 :    DEF_MAT(KRNKN, Ter_HardToWin)             DEF_MAT_REV(KNKRN,KRNKN)
     398           44 :    DEF_MAT(KRNKL, Ter_HardToWin)             DEF_MAT_REV(KLKRN,KRNKL)
     399           44 :    DEF_MAT(KRNKD, Ter_HardToWin)             DEF_MAT_REV(KDKRN,KRNKD)
     400           44 :    DEF_MAT(KRLKN, Ter_HardToWin)             DEF_MAT_REV(KNKRL,KRLKN)
     401           44 :    DEF_MAT(KRLKL, Ter_HardToWin)             DEF_MAT_REV(KLKRL,KRLKL)
     402           44 :    DEF_MAT(KRLKD, Ter_HardToWin)             DEF_MAT_REV(KDKRL,KRLKD)
     403           44 :    DEF_MAT(KRDKN, Ter_HardToWin)             DEF_MAT_REV(KNKRD,KRDKN)
     404           44 :    DEF_MAT(KRDKL, Ter_HardToWin)             DEF_MAT_REV(KLKRD,KRDKL)
     405           44 :    DEF_MAT(KRDKD, Ter_HardToWin)             DEF_MAT_REV(KDKRD,KRDKD)
     406              : 
     407              :    // Qm Q : draws
     408           44 :    DEF_MAT(KQNKQ, Ter_LikelyDraw)             DEF_MAT_REV(KQKQN,KQNKQ)
     409           44 :    DEF_MAT(KQLKQ, Ter_LikelyDraw)             DEF_MAT_REV(KQKQL,KQLKQ)
     410           44 :    DEF_MAT(KQDKQ, Ter_LikelyDraw)             DEF_MAT_REV(KQKQD,KQDKQ)
     411              : 
     412              :    // Qm R : wins
     413           66 :    DEF_MAT_H(KQNKR, Ter_WhiteWin,&helperKXK)              DEF_MAT_REV_H(KRKQN,KQNKR,&helperKXK)
     414           66 :    DEF_MAT_H(KQLKR, Ter_WhiteWin,&helperKXK)              DEF_MAT_REV_H(KRKQL,KQLKR,&helperKXK)
     415           66 :    DEF_MAT_H(KQDKR, Ter_WhiteWin,&helperKXK)              DEF_MAT_REV_H(KRKQD,KQRKR,&helperKXK)
     416              : 
     417              :    // Q Rm : draws
     418           44 :    DEF_MAT(KQKRN, Ter_LikelyDraw)             DEF_MAT_REV(KRNKQ,KQKRN)
     419           44 :    DEF_MAT(KQKRL, Ter_LikelyDraw)             DEF_MAT_REV(KRLKQ,KQKRL)
     420           44 :    DEF_MAT(KQKRD, Ter_LikelyDraw)             DEF_MAT_REV(KRDKQ,KQKRD)
     421              : 
     422              :    // Opposite bishop with Ps
     423           44 :    DEF_MAT(KLPKD, Ter_LikelyDraw)            DEF_MAT_REV(KDKLP,KLPKD)
     424           44 :    DEF_MAT(KDPKL, Ter_LikelyDraw)            DEF_MAT_REV(KLKDP,KDPKL)
     425           44 :    DEF_MAT(KLPPKD, Ter_LikelyDraw)           DEF_MAT_REV(KDKLPP,KLPPKD)
     426           44 :    DEF_MAT(KDPPKL, Ter_LikelyDraw)           DEF_MAT_REV(KLKDPP,KDPPKL)
     427              : 
     428              :    // KPK
     429           66 :    DEF_MAT_H(KPK, Ter_WhiteWinWithHelper,&helperKPK)    DEF_MAT_REV_H(KKP,KPK,&helperKPK)
     430              : 
     431              :    // KBPK
     432           66 :    DEF_MAT_H(KLPK, Ter_WhiteWinWithHelper,&helperKBPK)    DEF_MAT_REV_H(KKLP,KLPK,&helperKBPK)
     433           66 :    DEF_MAT_H(KDPK, Ter_WhiteWinWithHelper,&helperKBPK)    DEF_MAT_REV_H(KKDP,KDPK,&helperKBPK)
     434              : 
     435              :    ///@todo other (with more pawn ...)
     436              : 
     437              : #endif
     438           22 : }
     439              : 
     440        22218 : Terminaison probeMaterialHashTable(const Position::Material &mat) {
     441        22218 :    const Hash h = getMaterialHash(mat);
     442        22218 :    if (h == nullHash) return Ter_Unknown;
     443        22218 :    return materialHashTable[h].t;
     444              : }
     445              : 
     446     10853906 : void updateMaterialOther(Position &p) {
     447     10853906 :    p.mat[Co_White][M_M]  = p.mat[Co_White][M_q] + p.mat[Co_White][M_r];
     448     10853906 :    p.mat[Co_White][M_m]  = p.mat[Co_White][M_b] + p.mat[Co_White][M_n];
     449     10853906 :    p.mat[Co_White][M_t]  = p.mat[Co_White][M_M] + p.mat[Co_White][M_m];
     450              :    const BitBoard wb     = p.whiteBishop();
     451     10853906 :    p.mat[Co_White][M_bl] = (uint8_t)BB::countBit(wb & BB::whiteSquare);
     452     10853906 :    p.mat[Co_White][M_bd] = (uint8_t)BB::countBit(wb & BB::blackSquare);
     453              : 
     454     10853906 :    p.mat[Co_Black][M_M]  = p.mat[Co_Black][M_q] + p.mat[Co_Black][M_r];
     455     10853906 :    p.mat[Co_Black][M_m]  = p.mat[Co_Black][M_b] + p.mat[Co_Black][M_n];
     456     10853906 :    p.mat[Co_Black][M_t]  = p.mat[Co_Black][M_M] + p.mat[Co_Black][M_m];
     457              :    const BitBoard bb     = p.blackBishop();
     458     10853906 :    p.mat[Co_Black][M_bl] = (uint8_t)BB::countBit(bb & BB::whiteSquare);
     459     10853906 :    p.mat[Co_Black][M_bd] = (uint8_t)BB::countBit(bb & BB::blackSquare);
     460     10853906 : }
     461              : 
     462          308 : void initMaterial(Position &p) { // M_p .. M_k is the same as P_wp .. P_wk
     463          924 :    for (Color c = Co_White; c < Co_End; ++c)
     464         4312 :       for (Piece pp = P_wp; pp <= P_wk; ++pp) 
     465         3696 :          p.mat[c][pp] = static_cast<uint8_t>(BB::countBit(p.pieces_const(c, pp)));
     466          308 :    updateMaterialOther(p);
     467          308 : }
     468              : 
     469       422894 : void updateMaterialProm(Position &p, const Square toBeCaptured, const MType mt) {
     470       422894 :    --p.mat[~p.c][PieceTools::getPieceType(p, toBeCaptured)]; // capture if to square is not empty
     471       422894 :    --p.mat[p.c][M_p];                                        // pawn
     472       422894 :    ++p.mat[p.c][promShift(mt)];                              // prom piece
     473       422894 : }
     474              : 
     475              : } // namespace MaterialHash
        

Generated by: LCOV version 2.0-1