Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.     Texel - A UCI chess engine.
  3.     Copyright (C) 2014  Peter Ă–sterlund, peterosterlund2@gmail.com
  4.  
  5.     This program is free software: you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation, either version 3 of the License, or
  8.     (at your option) any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. */
  18.  
  19. /*
  20.  * tbprobe.cpp
  21.  *
  22.  *  Created on: Jun 2, 2014
  23.  *      Author: petero
  24.  */
  25.  
  26. #include "tbprobe.hpp"
  27. #include "gtb/gtb-probe.h"
  28. #include "syzygy/rtb-probe.hpp"
  29. #include "bitBoard.hpp"
  30. #include "position.hpp"
  31. #include "moveGen.hpp"
  32. #include "constants.hpp"
  33. #include <unordered_map>
  34. #include <cassert>
  35.  
  36. #include "util/timeUtil.hpp"
  37.  
  38. static std::string currentGtbPath;
  39. static int currentGtbCacheMB;
  40. static int currentGtbWdlFraction;
  41. static std::string currentRtbPath;
  42.  
  43. static const char** gtbPaths = nullptr;
  44. static int gtbMaxPieces = 0;
  45.  
  46. static std::unordered_map<int,int> maxDTM; // MatId -> Max DTM value in GTB TB
  47. static std::unordered_map<int,int> maxDTZ; // MatId -> Max DTZ value in RTB TB
  48. struct IIPairHash {
  49.     size_t operator()(const std::pair<int,int>& p) const {
  50.         return p.first * 0x714d3559 + p.second;
  51.     }
  52. };
  53. // (MatId,maxPawnMoves) -> Max DTM in sub TBs
  54. static std::unordered_map<std::pair<int,int>,int,IIPairHash> maxSubDTM;
  55.  
  56.  
  57. void
  58. TBProbe::initialize(const std::string& gtbPath, int cacheMB,
  59.                     const std::string& rtbPath) {
  60.     if (rtbPath != currentRtbPath) {
  61.         Syzygy::init(rtbPath);
  62.         currentRtbPath = rtbPath;
  63.     }
  64.  
  65.     int wdlFraction = (Syzygy::TBLargest >= 5) ? 8 : 96;
  66.     if ((gtbPath != currentGtbPath) ||
  67.         (cacheMB != currentGtbCacheMB) ||
  68.         (wdlFraction != currentGtbWdlFraction)) {
  69.         gtbInitialize(gtbPath, cacheMB, wdlFraction);
  70.         currentGtbPath = gtbPath;
  71.         currentGtbCacheMB = cacheMB;
  72.         currentGtbWdlFraction = wdlFraction;
  73.     }
  74.  
  75.     static bool initialized = false;
  76.     if (!initialized) {
  77.         initWDLBounds();
  78.         initialized = true;
  79.     }
  80. }
  81.  
  82. bool
  83. TBProbe::tbEnabled() {
  84.     return Syzygy::TBLargest > 0 || gtbMaxPieces > 0;
  85. }
  86.  
  87. bool
  88. TBProbe::tbProbe(Position& pos, int ply, int alpha, int beta,
  89.                  TranspositionTable::TTEntry& ent) {
  90.     const int nPieces = BitBoard::bitCount(pos.occupiedBB());
  91.     bool mateSearch = SearchConst::isLoseScore(alpha) || SearchConst::isWinScore(beta);
  92.  
  93.     if (mateSearch || pos.getHalfMoveClock() > 0) {
  94.         // Need DTM or DTZ probe
  95.         int dtmScore;
  96.         bool hasDtm = false;
  97.         if (nPieces <= gtbMaxPieces && gtbProbeDTM(pos, ply, dtmScore)) {
  98.             if (SearchConst::MATE0 - 1 - abs(dtmScore) - ply <= 100 - pos.getHalfMoveClock()) {
  99.                 ent.setScore(dtmScore, ply);
  100.                 ent.setType(TType::T_EXACT);
  101.                 return true;
  102.             }
  103.             hasDtm = true;
  104.         }
  105.         int dtzScore;
  106.         if (nPieces <= Syzygy::TBLargest && rtbProbeDTZ(pos, ply, dtzScore)) {
  107.             ent.setScore(dtzScore, ply);
  108.             if (dtzScore > 0)
  109.                 ent.setType(TType::T_GE);
  110.             else if (dtzScore < 0)
  111.                 ent.setType(TType::T_LE);
  112.             else
  113.                 ent.setType(TType::T_EXACT);
  114.             return true;
  115.         }
  116.         if (hasDtm) {
  117.             ent.setScore(dtmScore, ply);
  118.             ent.setType(TType::T_EXACT);
  119.             return true;
  120.         }
  121.     }
  122.  
  123.     if (pos.getHalfMoveClock() == 0) {
  124.         // Try WDL probe if DTM/DTZ not needed or not available
  125.         int wdlScore;
  126.         if ((nPieces <= Syzygy::TBLargest && rtbProbeWDL(pos, ply, wdlScore)) ||
  127.                 (nPieces <= gtbMaxPieces && gtbProbeWDL(pos, ply, wdlScore))) {
  128.             ent.setScore(wdlScore, ply);
  129.             if (wdlScore > 0)
  130.                 ent.setType(TType::T_GE);
  131.             else if (wdlScore < 0)
  132.                 ent.setType(TType::T_LE);
  133.             else
  134.                 ent.setType(TType::T_EXACT);
  135.             return true;
  136.         }
  137.     }
  138.     return false;
  139. }
  140.  
  141. bool
  142. TBProbe::getSearchMoves(Position& pos, const MoveList& legalMoves,
  143.                         std::vector<Move>& movesToSearch) {
  144.     const int mate0 = SearchConst::MATE0;
  145.     const int ply = 0;
  146.     TranspositionTable::TTEntry rootEnt;
  147.     if (!tbProbe(pos, ply, -mate0, mate0, rootEnt) || rootEnt.getType() == TType::T_LE)
  148.         return false;
  149.     const int rootScore = rootEnt.getScore(ply);
  150.     if (!SearchConst::isWinScore(rootScore))
  151.         return false;
  152.  
  153.     // Root position is TB win
  154.     bool hasProgress = false;
  155.     UndoInfo ui;
  156.     for (int mi = 0; mi < legalMoves.size; mi++) {
  157.         const Move& m = legalMoves[mi];
  158.         pos.makeMove(m, ui);
  159.         TranspositionTable::TTEntry ent;
  160.         ent.clear();
  161.         bool progressMove = false;
  162.         bool badMove = false;
  163.         if (tbProbe(pos, ply+1, -mate0, mate0, ent)) {
  164.             const int type = ent.getType();
  165.             const int score = -ent.getScore(ply+1);
  166.             if (score >= rootScore && (type == TType::T_EXACT || type == TType::T_LE))
  167.                 progressMove = true;
  168.             if ((score < rootScore)) //  && (type == TType::T_EXACT || type == TType::T_GE))
  169.                 badMove = true;
  170.         }
  171.         if (progressMove)
  172.             hasProgress = true;
  173.         if (!badMove)
  174.             movesToSearch.push_back(m);
  175.         pos.unMakeMove(m, ui);
  176.     }
  177.  
  178.     return !hasProgress && !movesToSearch.empty();
  179. }
  180.  
  181. void
  182. TBProbe::extendPV(const Position& rootPos, std::vector<Move>& pv) {
  183.     Position pos(rootPos);
  184.     UndoInfo ui;
  185.     int ply = 0;
  186.     int score;
  187.     for (int i = 0; i < (int)pv.size(); i++) {
  188.         const Move& m = pv[i];
  189.         pos.makeMove(m, ui);
  190.         if (TBProbe::gtbProbeDTM(pos, ply, score) && SearchConst::isWinScore(std::abs(score)) &&
  191.             (SearchConst::MATE0 - 1 - abs(score) - ply <= 100 - pos.getHalfMoveClock())) {
  192.             // TB win, replace rest of PV since it may be inaccurate
  193.             pv.erase(pv.begin()+i+1, pv.end());
  194.             break;
  195.         }
  196.     }
  197.     if (!TBProbe::gtbProbeDTM(pos, ply, score) || !SearchConst::isWinScore(std::abs(score)))
  198.         return; // No TB win
  199.     if (SearchConst::MATE0 - 1 - abs(score) - ply > 100 - pos.getHalfMoveClock())
  200.         return; // Mate too far away, perhaps 50-move draw
  201.     if (!pos.isWhiteMove())
  202.         score = -score;
  203.     while (true) {
  204.         MoveList moveList;
  205.         MoveGen::pseudoLegalMoves(pos, moveList);
  206.         MoveGen::removeIllegal(pos, moveList);
  207.         bool extended = false;
  208.         for (int mi = 0; mi < moveList.size; mi++) {
  209.             const Move& m = moveList[mi];
  210.             pos.makeMove(m, ui);
  211.             int newScore;
  212.             if (TBProbe::gtbProbeDTM(pos, ply+1, newScore)) {
  213.                 if (!pos.isWhiteMove())
  214.                     newScore = -newScore;
  215.                 if (newScore == score) {
  216.                     pv.push_back(m);
  217.                     ply++;
  218.                     extended = true;
  219.                     break;
  220.                 }
  221.             }
  222.             pos.unMakeMove(m, ui);
  223.         }
  224.         if (!extended)
  225.             break;
  226.     }
  227. }
  228.  
  229. template <typename ProbeFunc>
  230. static void handleEP(Position& pos, int ply, int& score, bool& ret, ProbeFunc probeFunc) {
  231.     const bool inCheck = MoveGen::inCheck(pos);
  232.     MoveList moveList;
  233.     if (inCheck) MoveGen::checkEvasions(pos, moveList);
  234.     else         MoveGen::pseudoLegalMoves(pos, moveList);
  235.     const int pawn = pos.isWhiteMove() ? Piece::WPAWN : Piece::BPAWN;
  236.     int bestEP = std::numeric_limits<int>::min();
  237.     UndoInfo ui;
  238.     for (int m = 0; m < moveList.size; m++) {
  239.         const Move& move = moveList[m];
  240.         if ((move.to() == pos.getEpSquare()) && (pos.getPiece(move.from()) == pawn)) {
  241.             if (MoveGen::isLegal(pos, move, inCheck)) {
  242.                 pos.makeMove(move, ui);
  243.                 int score2;
  244.                 bool ret2 = probeFunc(pos, ply+1, score2);
  245.                 pos.unMakeMove(move, ui);
  246.                 if (!ret2) {
  247.                     ret = false;
  248.                     return;
  249.                 }
  250.                 bestEP = std::max(bestEP, -score2);
  251.             }
  252.         } else if (MoveGen::isLegal(pos, move, inCheck))
  253.             return;
  254.     }
  255.     if (bestEP != std::numeric_limits<int>::min())
  256.         score = bestEP;
  257. }
  258.  
  259. bool
  260. TBProbe::gtbProbeDTM(Position& pos, int ply, int& score) {
  261.     if (BitBoard::bitCount(pos.occupiedBB()) > gtbMaxPieces)
  262.         return false;
  263.  
  264.     GtbProbeData gtbData;
  265.     getGTBProbeData(pos, gtbData);
  266.     bool ret = gtbProbeDTM(gtbData, ply, score);
  267.     if (ret && score == 0 && pos.getEpSquare() != -1)
  268.         handleEP(pos, ply, score, ret, [](Position& pos, int ply, int& score) -> bool {
  269.             return TBProbe::gtbProbeDTM(pos, ply, score);
  270.         });
  271.     return ret;
  272. }
  273.  
  274. bool
  275. TBProbe::gtbProbeWDL(Position& pos, int ply, int& score) {
  276.     if (BitBoard::bitCount(pos.occupiedBB()) > gtbMaxPieces)
  277.         return false;
  278.  
  279.     GtbProbeData gtbData;
  280.     getGTBProbeData(pos, gtbData);
  281.     bool ret = gtbProbeWDL(gtbData, ply, score);
  282.     if (ret && score == 0 && pos.getEpSquare() != -1)
  283.         handleEP(pos, ply, score, ret, [](Position& pos, int ply, int& score) -> bool {
  284.             return TBProbe::gtbProbeWDL(pos, ply, score);
  285.         });
  286.     return ret;
  287. }
  288.  
  289. bool
  290. TBProbe::rtbProbeDTZ(Position& pos, int ply, int& score) {
  291.     const int nPieces = BitBoard::bitCount(pos.occupiedBB());
  292.     if (nPieces > Syzygy::TBLargest)
  293.         return false;
  294.     if (pos.getCastleMask())
  295.         return false;
  296.  
  297.     int success;
  298.     const int dtz = Syzygy::probe_dtz(pos, &success);
  299.     if (!success)
  300.         return false;
  301.     if (dtz == 0) {
  302.         score = 0;
  303.         return true;
  304.     }
  305.     const int maxHalfMoveClock = std::abs(dtz) + pos.getHalfMoveClock();
  306.     if (abs(dtz) <= 2) {
  307.         if (maxHalfMoveClock > 101) {
  308.             score = 0;
  309.             return true;
  310.         } else if (maxHalfMoveClock == 101)
  311.             return false; // DTZ can be wrong when mate-in-1
  312.     } else {
  313.         if (maxHalfMoveClock > 100) {
  314.             score = 0;
  315.             return true;
  316.         }
  317.         // FIXME!! Are there positions where maxHalfMoveclock==101 needs special handling?
  318.     }
  319.     int plyToMate = getMaxSubMate(pos) + std::abs(dtz);
  320.     if (dtz > 0) {
  321.         score = SearchConst::MATE0 - ply - plyToMate - 2;
  322.     } else {
  323.         score = -(SearchConst::MATE0 - ply - plyToMate - 2);
  324.     }
  325.     return true;
  326. }
  327.  
  328. bool
  329. TBProbe::rtbProbeWDL(Position& pos, int ply, int& score) {
  330.     if (BitBoard::bitCount(pos.occupiedBB()) > Syzygy::TBLargest)
  331.         return false;
  332.     if (pos.getCastleMask())
  333.         return false;
  334.  
  335.     int success;
  336.     int wdl = Syzygy::probe_wdl(pos, &success);
  337.     if (!success)
  338.         return false;
  339.     int plyToMate;
  340.     switch (wdl) {
  341.     case 0: case 1: case -1:
  342.         score = 0;
  343.         break;
  344.     case 2:
  345.         plyToMate = getMaxSubMate(pos) + getMaxDTZ(pos.materialId());
  346.         score = SearchConst::MATE0 - ply - plyToMate - 2;
  347.         break;
  348.     case -2:
  349.         plyToMate = getMaxSubMate(pos) + getMaxDTZ(pos.materialId());
  350.         score = -(SearchConst::MATE0 - ply - plyToMate - 2);
  351.         break;
  352.     default:
  353.         return false;
  354.     }
  355.  
  356.     return true;
  357. }
  358.  
  359. void
  360. TBProbe::gtbInitialize(const std::string& path, int cacheMB, int wdlFraction) {
  361.     static_assert((int)tb_A1 == (int)A1, "Incompatible square numbering");
  362.     static_assert((int)tb_A8 == (int)A8, "Incompatible square numbering");
  363.     static_assert((int)tb_H1 == (int)H1, "Incompatible square numbering");
  364.     static_assert((int)tb_H8 == (int)H8, "Incompatible square numbering");
  365.  
  366.     tbpaths_done(gtbPaths);
  367.  
  368.     gtbMaxPieces = 0;
  369.     gtbPaths = tbpaths_init();
  370.     gtbPaths = tbpaths_add(gtbPaths, path.c_str());
  371.  
  372.     TB_compression_scheme scheme = tb_CP4;
  373.     int verbose = 0;
  374.     int cacheSize = 1024 * 1024 * cacheMB;
  375.     static bool isInitialized = false;
  376.     if (isInitialized) {
  377.         tb_restart(verbose, scheme, gtbPaths);
  378.         tbcache_restart(cacheSize, wdlFraction);
  379.     } else {
  380.         tb_init(verbose, scheme, gtbPaths);
  381.         tbcache_init(cacheSize, wdlFraction);
  382.     }
  383.     isInitialized = true;
  384.  
  385.     unsigned int av = tb_availability();
  386.     if (av & 3)
  387.         gtbMaxPieces = 3;
  388.     if (av & 12)
  389.         gtbMaxPieces = 4;
  390.     if (av & 48)
  391.         gtbMaxPieces = 5;
  392. }
  393.  
  394. void
  395. TBProbe::getGTBProbeData(const Position& pos, GtbProbeData& gtbData) {
  396.     gtbData.stm = pos.isWhiteMove() ? tb_WHITE_TO_MOVE : tb_BLACK_TO_MOVE;
  397.     gtbData.epsq = pos.getEpSquare() >= 0 ? pos.getEpSquare() : tb_NOSQUARE;
  398.  
  399.     gtbData.castles = 0;
  400.     if (pos.a1Castle()) gtbData.castles |= tb_WOOO;
  401.     if (pos.h1Castle()) gtbData.castles |= tb_WOO;
  402.     if (pos.a8Castle()) gtbData.castles |= tb_BOOO;
  403.     if (pos.h8Castle()) gtbData.castles |= tb_BOO;
  404.  
  405.     int cnt = 0;
  406.     U64 m = pos.whiteBB();
  407.     while (m != 0) {
  408.         int sq = BitBoard::extractSquare(m);
  409.         gtbData.wSq[cnt] = sq;
  410.         switch (pos.getPiece(sq)) {
  411.         case Piece::WKING:   gtbData.wP[cnt] = tb_KING;   break;
  412.         case Piece::WQUEEN:  gtbData.wP[cnt] = tb_QUEEN;  break;
  413.         case Piece::WROOK:   gtbData.wP[cnt] = tb_ROOK;   break;
  414.         case Piece::WBISHOP: gtbData.wP[cnt] = tb_BISHOP; break;
  415.         case Piece::WKNIGHT: gtbData.wP[cnt] = tb_KNIGHT; break;
  416.         case Piece::WPAWN:   gtbData.wP[cnt] = tb_PAWN;   break;
  417.         default:
  418.             assert(false);
  419.         }
  420.         cnt++;
  421.     }
  422.     gtbData.wSq[cnt] = tb_NOSQUARE;
  423.     gtbData.wP[cnt] = tb_NOPIECE;
  424.  
  425.     cnt = 0;
  426.     m = pos.blackBB();
  427.     while (m != 0) {
  428.         int sq = BitBoard::extractSquare(m);
  429.         gtbData.bSq[cnt] = sq;
  430.         switch (pos.getPiece(sq)) {
  431.         case Piece::BKING:   gtbData.bP[cnt] = tb_KING;   break;
  432.         case Piece::BQUEEN:  gtbData.bP[cnt] = tb_QUEEN;  break;
  433.         case Piece::BROOK:   gtbData.bP[cnt] = tb_ROOK;   break;
  434.         case Piece::BBISHOP: gtbData.bP[cnt] = tb_BISHOP; break;
  435.         case Piece::BKNIGHT: gtbData.bP[cnt] = tb_KNIGHT; break;
  436.         case Piece::BPAWN:   gtbData.bP[cnt] = tb_PAWN;   break;
  437.         default:
  438.             assert(false);
  439.         }
  440.         cnt++;
  441.     }
  442.     gtbData.bSq[cnt] = tb_NOSQUARE;
  443.     gtbData.bP[cnt] = tb_NOPIECE;
  444.     gtbData.materialId = pos.materialId();
  445. }
  446.  
  447. bool
  448. TBProbe::gtbProbeDTM(const GtbProbeData& gtbData, int ply, int& score) {
  449.     unsigned int tbInfo;
  450.     unsigned int plies;
  451.     if (!tb_probe_hard(gtbData.stm, gtbData.epsq, gtbData.castles,
  452.                        gtbData.wSq, gtbData.bSq,
  453.                        gtbData.wP, gtbData.bP,
  454.                        &tbInfo, &plies))
  455.         return false;
  456.  
  457.     switch (tbInfo) {
  458.     case tb_DRAW:
  459.         score = 0;
  460.         break;
  461.     case tb_WMATE:
  462.         score = SearchConst::MATE0 - ply - plies - 1;
  463.         break;
  464.     case tb_BMATE:
  465.         score = -(SearchConst::MATE0 - ply - (int)plies - 1); // Pierre-Marie Baty -- added type cast
  466.         break;
  467.     default:
  468.         return false;
  469.     };
  470.  
  471.     if (gtbData.stm == tb_BLACK_TO_MOVE)
  472.         score = -score;
  473.  
  474.     return true;
  475. }
  476.  
  477. bool
  478. TBProbe::gtbProbeWDL(const GtbProbeData& gtbData, int ply, int& score) {
  479.     unsigned int tbInfo;
  480.     if (!tb_probe_WDL_hard(gtbData.stm, gtbData.epsq, gtbData.castles,
  481.                            gtbData.wSq, gtbData.bSq,
  482.                            gtbData.wP, gtbData.bP,
  483.                            &tbInfo))
  484.         return false;
  485.  
  486.     switch (tbInfo) {
  487.     case tb_DRAW:
  488.         score = 0;
  489.         break;
  490.     case tb_WMATE:
  491.         score = maxDTM[gtbData.materialId] - ply;
  492.         break;
  493.     case tb_BMATE:
  494.         score = -(maxDTM[gtbData.materialId] - ply);
  495.         break;
  496.     default:
  497.         return false;
  498.     };
  499.  
  500.     if (gtbData.stm == tb_BLACK_TO_MOVE)
  501.         score = -score;
  502.     return true;
  503. }
  504.  
  505. void
  506. TBProbe::initWDLBounds() {
  507.     initMaxDTM();
  508.     initMaxDTZ();
  509.  
  510.     // Pre-calculate all interesting maxSubDTM values
  511.     for (int wp = 0; wp <= 4; wp++) {
  512.         std::vector<int> pieces(Piece::nPieceTypes);
  513.         pieces[Piece::WPAWN] = wp;
  514.         pieces[Piece::BPAWN] = 4 - wp;
  515.         getMaxSubMate(pieces, 4*5);
  516.     }
  517. }
  518.  
  519. /** Maximum DTZ value for a given material configuration. */
  520. int
  521. TBProbe::getMaxDTZ(int matId) {
  522.     auto it = maxDTZ.find(matId);
  523.     if (it == maxDTZ.end())
  524.         return 100;
  525.     int val = it->second;
  526.     if (val < 0)
  527.         return 0;
  528.     else
  529.         return std::min(val+2, 100); // RTB DTZ values are not exact
  530. }
  531.  
  532. static int
  533. getMaxPawnMoves(const Position& pos) {
  534.     int maxPawnMoves = 0;
  535.     U64 m = pos.pieceTypeBB(Piece::WPAWN);
  536.     while (m != 0) {
  537.         int sq = BitBoard::extractSquare(m);
  538.         maxPawnMoves += 6 - Position::getY(sq);
  539.     }
  540.     m = pos.pieceTypeBB(Piece::BPAWN);
  541.     while (m != 0) {
  542.         int sq = BitBoard::extractSquare(m);
  543.         maxPawnMoves += Position::getY(sq) - 1;
  544.     }
  545.     return maxPawnMoves;
  546. }
  547.  
  548. /** Get upper bound on longest mate in all possible material configurations
  549.  * after the next zeroing move. */
  550. int
  551. TBProbe::getMaxSubMate(const Position& pos) {
  552.     int maxPawnMoves = getMaxPawnMoves(pos);
  553.     int matId = pos.materialId();
  554.     matId = std::min(matId, MatId::mirror(matId));
  555.     auto it = maxSubDTM.find(std::make_pair(matId,maxPawnMoves));
  556.     if (it != maxSubDTM.end())
  557.         return it->second;
  558.  
  559.     std::vector<int> pieces(Piece::nPieceTypes);
  560.     for (int p = 0; p < Piece::nPieceTypes; p++)
  561.         pieces[p] = BitBoard::bitCount(pos.pieceTypeBB((Piece::Type)p));
  562.     pieces[Piece::EMPTY] = pieces[Piece::WKING] = pieces[Piece::BKING] = 0;
  563.     return getMaxSubMate(pieces, maxPawnMoves);
  564. }
  565.  
  566. int
  567. TBProbe::getMaxSubMate(std::vector<int>& pieces, int pawnMoves) {
  568.     assert(pawnMoves >= 0);
  569.     if (pawnMoves > (pieces[Piece::WPAWN] + pieces[Piece::BPAWN]) * 5)
  570.         return 0;
  571.  
  572.     MatId matId;
  573.     for (int p = 0; p < Piece::nPieceTypes; p++)
  574.         matId.addPieceCnt(p, pieces[p]);
  575.  
  576.     const int matIdMin = std::min(matId(), MatId::mirror(matId()));
  577.     auto it = maxSubDTM.find(std::make_pair(matIdMin, pawnMoves));
  578.     if (it != maxSubDTM.end())
  579.         return it->second;
  580.  
  581.     int maxSubMate = 0;
  582.     if (pawnMoves > 0) { // Pawn move
  583.         maxSubMate = getMaxSubMate(pieces, pawnMoves-1) + getMaxDTZ(matId());
  584.     }
  585.     for (int p = 0; p < Piece::nPieceTypes; p++) { // Capture
  586.         if (pieces[p] > 0) {
  587.             pieces[p]--;
  588.             matId.removePiece(p);
  589.             int maxRemovedPawnMoves = 0;
  590.             if (p == Piece::WPAWN || p == Piece::BPAWN)
  591.                 maxRemovedPawnMoves = 5;
  592.             for (int i = 0; i <= maxRemovedPawnMoves; i++) {
  593.                 int newPawnMoves = pawnMoves - i;
  594.                 if (newPawnMoves >= 0) {
  595.                     int tmp = getMaxSubMate(pieces, newPawnMoves) + getMaxDTZ(matId());
  596.                     maxSubMate = std::max(maxSubMate, tmp);
  597.                 }
  598.             }
  599.             pieces[p]++;
  600.             matId.addPiece(p);
  601.         }
  602.     }
  603.     for (int c = 0; c < 2; c++) { // Promotion
  604.         const int pawn = (c == 0) ? Piece::WPAWN : Piece::BPAWN;
  605.         if (pieces[pawn] > 0) {
  606.             const int p0 = (c == 0) ? Piece::WQUEEN : Piece::BQUEEN;
  607.             const int p1 = (c == 0) ? Piece::WKNIGHT : Piece::BKNIGHT;
  608.             for (int p = p0; p <= p1; p++) {
  609.                 pieces[pawn]--;
  610.                 pieces[p]++;
  611.                 matId.removePiece(pawn);
  612.                 matId.addPiece(p);
  613.                 int tmp = getMaxSubMate(pieces, pawnMoves) + getMaxDTZ(matId());
  614.                 maxSubMate = std::max(maxSubMate, tmp);
  615.                 pieces[pawn]++;
  616.                 pieces[p]--;
  617.                 matId.addPiece(pawn);
  618.                 matId.removePiece(p);
  619.             }
  620.         }
  621.     }
  622.  
  623. #if 0
  624.     std::cout << "wQ:" << pieces[Piece::WQUEEN]
  625.               << " wR:" << pieces[Piece::WROOK]
  626.               << " wB:" << pieces[Piece::WBISHOP]
  627.               << " wN:" << pieces[Piece::WKNIGHT]
  628.               << " wP:" << pieces[Piece::WPAWN]
  629.               << " bQ:" << pieces[Piece::BQUEEN]
  630.               << " bR:" << pieces[Piece::BROOK]
  631.               << " bB:" << pieces[Piece::BBISHOP]
  632.               << " bN:" << pieces[Piece::BKNIGHT]
  633.               << " bP:" << pieces[Piece::BPAWN]
  634.               << " pMoves:" << pawnMoves << " : " << maxSubMate << std::endl;
  635. #endif
  636.     maxSubDTM[std::make_pair(matIdMin, pawnMoves)] = maxSubMate;
  637.     return maxSubMate;
  638. }
  639.  
  640. void
  641. TBProbe::initMaxDTM() {
  642.     using MI = MatId;
  643.     auto add = [](int id, int value) {
  644.         maxDTM[id] = value;
  645.         maxDTM[MatId::mirror(id)] = value;
  646.     };
  647.  
  648.     add(MI::WQ, 31979);
  649.     add(MI::WR, 31967);
  650.     add(MI::WP, 31943);
  651.  
  652.     add(MI::WQ*2, 31979);
  653.     add(MI::WQ+MI::WR, 31967);
  654.     add(MI::WQ+MI::WB, 31979);
  655.     add(MI::WQ+MI::WN, 31979);
  656.     add(MI::WQ+MI::WP, 31943);
  657.     add(MI::WR*2, 31967);
  658.     add(MI::WR+MI::WB, 31967);
  659.     add(MI::WR+MI::WN, 31967);
  660.     add(MI::WR+MI::WP, 31943);
  661.     add(MI::WB*2, 31961);
  662.     add(MI::WB+MI::WN, 31933);
  663.     add(MI::WB+MI::WP, 31937);
  664.     add(MI::WN*2, 31998);
  665.     add(MI::WN+MI::WP, 31943);
  666.     add(MI::WP*2, 31935);
  667.     add(MI::WQ+MI::BQ, 31974);
  668.     add(MI::WR+MI::BQ, 31929);
  669.     add(MI::WR+MI::BR, 31961);
  670.     add(MI::WB+MI::BQ, 31965);
  671.     add(MI::WB+MI::BR, 31941);
  672.     add(MI::WB+MI::BB, 31998);
  673.     add(MI::WN+MI::BQ, 31957);
  674.     add(MI::WN+MI::BR, 31919);
  675.     add(MI::WN+MI::BB, 31998);
  676.     add(MI::WN+MI::BN, 31998);
  677.     add(MI::WP+MI::BQ, 31942);
  678.     add(MI::WP+MI::BR, 31914);
  679.     add(MI::WP+MI::BB, 31942);
  680.     add(MI::WP+MI::BN, 31942);
  681.     add(MI::WP+MI::BP, 31933);
  682.  
  683.     add(MI::WQ*3, 31991);
  684.     add(MI::WQ*2+MI::WR, 31987);
  685.     add(MI::WQ*2+MI::WB, 31983);
  686.     add(MI::WQ*2+MI::WN, 31981);
  687.     add(MI::WQ*2+MI::WP, 31979);
  688.     add(MI::WQ+MI::WR*2, 31985);
  689.     add(MI::WQ+MI::WR+MI::WB, 31967);
  690.     add(MI::WQ+MI::WR+MI::WN, 31967);
  691.     add(MI::WQ+MI::WR+MI::WP, 31967);
  692.     add(MI::WQ+MI::WB*2, 31961);
  693.     add(MI::WQ+MI::WB+MI::WN, 31933);
  694.     add(MI::WQ+MI::WB+MI::WP, 31937);
  695.     add(MI::WQ+MI::WN*2, 31981);
  696.     add(MI::WQ+MI::WN+MI::WP, 31945);
  697.     add(MI::WQ+MI::WP*2, 31935);
  698.     add(MI::WR*3, 31985);
  699.     add(MI::WR*2+MI::WB, 31967);
  700.     add(MI::WR*2+MI::WN, 31967);
  701.     add(MI::WR*2+MI::WP, 31967);
  702.     add(MI::WR+MI::WB*2, 31961);
  703.     add(MI::WR+MI::WB+MI::WN, 31933);
  704.     add(MI::WR+MI::WB+MI::WP, 31937);
  705.     add(MI::WR+MI::WN*2, 31967);
  706.     add(MI::WR+MI::WN+MI::WP, 31945);
  707.     add(MI::WR+MI::WP*2, 31935);
  708.     add(MI::WB*3, 31961);
  709.     add(MI::WB*2+MI::WN, 31933);
  710.     add(MI::WB*2+MI::WP, 31937);
  711.     add(MI::WB+MI::WN*2, 31931);
  712.     add(MI::WB+MI::WN+MI::WP, 31933);
  713.     add(MI::WB+MI::WP*2, 31935);
  714.     add(MI::WN*3, 31957);
  715.     add(MI::WN*2+MI::WP, 31943);
  716.     add(MI::WN+MI::WP*2, 31935);
  717.     add(MI::WP*3, 31933);
  718.     add(MI::WQ*2+MI::BQ, 31939);
  719.     add(MI::WQ*2+MI::BR, 31929);
  720.     add(MI::WQ*2+MI::BB, 31965);
  721.     add(MI::WQ*2+MI::BN, 31957);
  722.     add(MI::WQ*2+MI::BP, 31939);
  723.     add(MI::WQ+MI::WR+MI::BQ, 31865);
  724.     add(MI::WQ+MI::WR+MI::BR, 31929);
  725.     add(MI::WQ+MI::WR+MI::BB, 31941);
  726.     add(MI::WQ+MI::WR+MI::BN, 31919);
  727.     add(MI::WQ+MI::WR+MI::BP, 31865);
  728.     add(MI::WQ+MI::WB+MI::BQ, 31933);
  729.     add(MI::WQ+MI::WB+MI::BR, 31919);
  730.     add(MI::WQ+MI::WB+MI::BB, 31965);
  731.     add(MI::WQ+MI::WB+MI::BN, 31957);
  732.     add(MI::WQ+MI::WB+MI::BP, 31933);
  733.     add(MI::WQ+MI::WN+MI::BQ, 31917);
  734.     add(MI::WQ+MI::WN+MI::BR, 31918);
  735.     add(MI::WQ+MI::WN+MI::BB, 31965);
  736.     add(MI::WQ+MI::WN+MI::BN, 31957);
  737.     add(MI::WQ+MI::WN+MI::BP, 31917);
  738.     add(MI::WQ+MI::WP+MI::BQ, 31752);
  739.     add(MI::WQ+MI::WP+MI::BR, 31913);
  740.     add(MI::WQ+MI::WP+MI::BB, 31941);
  741.     add(MI::WQ+MI::WP+MI::BN, 31939);
  742.     add(MI::WQ+MI::WP+MI::BP, 31755);
  743.     add(MI::WR*2+MI::BQ, 31901);
  744.     add(MI::WR*2+MI::BR, 31937);
  745.     add(MI::WR*2+MI::BB, 31941);
  746.     add(MI::WR*2+MI::BN, 31919);
  747.     add(MI::WR*2+MI::BP, 31900);
  748.     add(MI::WR+MI::WB+MI::BQ, 31859);
  749.     add(MI::WR+MI::WB+MI::BR, 31870);
  750.     add(MI::WR+MI::WB+MI::BB, 31939);
  751.     add(MI::WR+MI::WB+MI::BN, 31919);
  752.     add(MI::WR+MI::WB+MI::BP, 31860);
  753.     add(MI::WR+MI::WN+MI::BQ, 31861);
  754.     add(MI::WR+MI::WN+MI::BR, 31918);
  755.     add(MI::WR+MI::WN+MI::BB, 31937);
  756.     add(MI::WR+MI::WN+MI::BN, 31919);
  757.     add(MI::WR+MI::WN+MI::BP, 31864);
  758.     add(MI::WR+MI::WP+MI::BQ, 31792);
  759.     add(MI::WR+MI::WP+MI::BR, 31851);
  760.     add(MI::WR+MI::WP+MI::BB, 31853);
  761.     add(MI::WR+MI::WP+MI::BN, 31891);
  762.     add(MI::WR+MI::WP+MI::BP, 31794);
  763.     add(MI::WB*2+MI::BQ, 31837);
  764.     add(MI::WB*2+MI::BR, 31938);
  765.     add(MI::WB*2+MI::BB, 31955);
  766.     add(MI::WB*2+MI::BN, 31843);
  767.     add(MI::WB*2+MI::BP, 31834);
  768.     add(MI::WB+MI::WN+MI::BQ, 31893);
  769.     add(MI::WB+MI::WN+MI::BR, 31918);
  770.     add(MI::WB+MI::WN+MI::BB, 31921);
  771.     add(MI::WB+MI::WN+MI::BN, 31786);
  772.     add(MI::WB+MI::WN+MI::BP, 31791);
  773.     add(MI::WB+MI::WP+MI::BQ, 31899);
  774.     add(MI::WB+MI::WP+MI::BR, 31910);
  775.     add(MI::WB+MI::WP+MI::BB, 31898);
  776.     add(MI::WB+MI::WP+MI::BN, 31800);
  777.     add(MI::WB+MI::WP+MI::BP, 31865);
  778.     add(MI::WN*2+MI::BQ, 31855);
  779.     add(MI::WN*2+MI::BR, 31918);
  780.     add(MI::WN*2+MI::BB, 31992);
  781.     add(MI::WN*2+MI::BN, 31986);
  782.     add(MI::WN*2+MI::BP, 31770);
  783.     add(MI::WN+MI::WP+MI::BQ, 31875);
  784.     add(MI::WN+MI::WP+MI::BR, 31866);
  785.     add(MI::WN+MI::WP+MI::BB, 31914);
  786.     add(MI::WN+MI::WP+MI::BN, 31805);
  787.     add(MI::WN+MI::WP+MI::BP, 31884);
  788.     add(MI::WP*2+MI::BQ, 31752);
  789.     add(MI::WP*2+MI::BR, 31892);
  790.     add(MI::WP*2+MI::BB, 31913);
  791.     add(MI::WP*2+MI::BN, 31899);
  792.     add(MI::WP*2+MI::BP, 31745);
  793. }
  794.  
  795. void
  796. TBProbe::initMaxDTZ() {
  797.     using MI = MatId;
  798.     auto add = [](int id, int value) {
  799.         maxDTZ[id] = value;
  800.         maxDTZ[MatId::mirror(id)] = value;
  801.     };
  802.  
  803.     // 2-men
  804.     add(0, -1);
  805.  
  806.     // 3-men
  807.     add(MI::WQ, 20);
  808.     add(MI::WR, 32);
  809.     add(MI::WB, -1);
  810.     add(MI::WN, -1);
  811.     add(MI::WP, 20);
  812.  
  813.     // 4-men
  814.     add(MI::WQ+MI::BQ, 19);
  815.     add(MI::WN*2, 1);
  816.     add(MI::WQ*2, 6);
  817.     add(MI::WP*2, 14);
  818.     add(MI::WR*2, 10);
  819.     add(MI::WR+MI::BR, 7);
  820.     add(MI::WQ+MI::WB, 12);
  821.     add(MI::WQ+MI::WR, 8);
  822.     add(MI::WQ+MI::WN, 14);
  823.     add(MI::WR+MI::BB, 35);
  824.     add(MI::WB+MI::BB, 1);
  825.     add(MI::WQ+MI::WP, 6);
  826.     add(MI::WB*2, 37);
  827.     add(MI::WB+MI::BN, 2);
  828.     add(MI::WR+MI::WP, 6);
  829.     add(MI::WN+MI::BN, 1);
  830.     add(MI::WR+MI::BN, 53);
  831.     add(MI::WP+MI::BP, 21);
  832.     add(MI::WB+MI::BP, 7);
  833.     add(MI::WR+MI::WB, 24);
  834.     add(MI::WQ+MI::BN, 38);
  835.     add(MI::WR+MI::WN, 24);
  836.     add(MI::WB+MI::WP, 26);
  837.     add(MI::WN+MI::BP, 16);
  838.     add(MI::WN+MI::WP, 26);
  839.     add(MI::WQ+MI::BR, 62);
  840.     add(MI::WQ+MI::BB, 24);
  841.     add(MI::WR+MI::BP, 25);
  842.     add(MI::WQ+MI::BP, 52);
  843.     add(MI::WB+MI::WN, 65);
  844.  
  845.     // 5-men
  846.     add(MI::WQ*3, 6);
  847.     add(MI::WQ*2+MI::WR, 6);
  848.     add(MI::WR*3, 8);
  849.     add(MI::WQ*2+MI::WB, 6);
  850.     add(MI::WQ*2+MI::WN, 8);
  851.     add(MI::WQ*2+MI::WP, 6);
  852.     add(MI::WQ+MI::WR+MI::WN, 8);
  853.     add(MI::WQ+MI::WR*2, 8);
  854.     add(MI::WQ+MI::WR+MI::WB, 8);
  855.     add(MI::WQ+MI::WP*2, 6);
  856.     add(MI::WQ+MI::WB+MI::WN, 8);
  857.     add(MI::WR*2+MI::WP, 6);
  858.     add(MI::WQ+MI::WB*2, 12);
  859.     add(MI::WB*3, 20);
  860.     add(MI::WR*2+MI::WN, 10);
  861.     add(MI::WR*2+MI::WB, 10);
  862.     add(MI::WQ+MI::WR+MI::WP, 6);
  863.     add(MI::WQ+MI::WN*2, 14);
  864.     add(MI::WQ+MI::WB+MI::WP, 6);
  865.     add(MI::WQ+MI::WN+MI::WP, 6);
  866.     add(MI::WR+MI::WP*2, 6);
  867.     add(MI::WR+MI::WB*2, 20);
  868.     add(MI::WP*3, 14);
  869.     add(MI::WR+MI::WN*2, 20);
  870.     add(MI::WQ*2+MI::BQ, 50);
  871.     add(MI::WQ*2+MI::BN, 8);
  872.     add(MI::WQ*2+MI::BB, 8);
  873.     add(MI::WR+MI::WB+MI::WN, 14);
  874.     add(MI::WB+MI::WP*2, 18);
  875.     add(MI::WB*2+MI::WP, 24);
  876.     add(MI::WQ*2+MI::BR, 28);
  877.     add(MI::WB*2+MI::WN, 26);
  878.     add(MI::WN+MI::WP*2, 12);
  879.     add(MI::WQ+MI::WB+MI::BQ, 59);
  880.     add(MI::WB+MI::WN*2, 26);
  881.     add(MI::WN*2+MI::WP, 16);
  882.     add(MI::WQ*2+MI::BP, 6);
  883.     add(MI::WN*3, 41);
  884.     add(MI::WQ+MI::WN+MI::BQ, 69);
  885.     add(MI::WQ+MI::WR+MI::BQ, 100);
  886.     add(MI::WQ+MI::WR+MI::BN, 10);
  887.     add(MI::WQ+MI::WR+MI::BB, 10);
  888.     add(MI::WQ+MI::WR+MI::BR, 30);
  889.     add(MI::WR+MI::WB+MI::WP, 8);
  890.     add(MI::WQ+MI::WB+MI::BN, 14);
  891.     add(MI::WQ+MI::WB+MI::BR, 38);
  892.     add(MI::WQ+MI::WB+MI::BB, 16);
  893.     add(MI::WB+MI::WN+MI::WP, 10);
  894.     add(MI::WR+MI::WN+MI::WP, 8);
  895.     add(MI::WR*2+MI::BQ, 40);
  896.     add(MI::WQ+MI::WN+MI::BN, 18);
  897.     add(MI::WR+MI::WB+MI::BR, 100);
  898.     add(MI::WQ+MI::WN+MI::BB, 18);
  899.     add(MI::WQ+MI::WR+MI::BP, 6);
  900.     add(MI::WR+MI::WB+MI::BQ, 82);
  901.     add(MI::WQ+MI::WP+MI::BQ, 100);
  902.     add(MI::WQ+MI::WP+MI::BP, 10);
  903.     add(MI::WQ+MI::WB+MI::BP, 22);
  904.     add(MI::WR+MI::WN+MI::BR, 64);
  905.     add(MI::WR*2+MI::BN, 14);
  906.     add(MI::WR*2+MI::BP, 18);
  907.     add(MI::WQ+MI::WN+MI::BR, 44);
  908.     add(MI::WR+MI::WN+MI::BQ, 92);
  909.     add(MI::WR*2+MI::BB, 20);
  910.     add(MI::WQ+MI::WN+MI::BP, 34);
  911.     add(MI::WR*2+MI::BR, 50);
  912.     add(MI::WB*2+MI::BR, 16);
  913.     add(MI::WB*2+MI::BB, 11);
  914.     add(MI::WQ+MI::WP+MI::BN, 12);
  915.     add(MI::WR+MI::WB+MI::BN, 42);
  916.     add(MI::WQ+MI::WP+MI::BB, 10);
  917.     add(MI::WB+MI::WN+MI::BR, 24);
  918.     add(MI::WB+MI::WN+MI::BB, 24);
  919.     add(MI::WB*2+MI::BN, 100);
  920.     add(MI::WB+MI::WN+MI::BN, 100);
  921.     add(MI::WQ+MI::WP+MI::BR, 34);
  922.     add(MI::WR+MI::WP+MI::BP, 19);
  923.     add(MI::WR+MI::WP+MI::BR, 70);
  924.     add(MI::WR+MI::WB+MI::BB, 50);
  925.     add(MI::WB*2+MI::BP, 42);
  926.     add(MI::WB*2+MI::BQ, 100);
  927.     add(MI::WR+MI::WB+MI::BP, 22);
  928.     add(MI::WN*2+MI::BR, 20);
  929.     add(MI::WN*2+MI::BB, 6);
  930.     add(MI::WB+MI::WP+MI::BR, 36);
  931.     add(MI::WN*2+MI::BN, 12);
  932.     add(MI::WB+MI::WP+MI::BB, 50);
  933.     add(MI::WR+MI::WN+MI::BN, 48);
  934.     add(MI::WN+MI::WP+MI::BR, 78);
  935.     add(MI::WN*2+MI::BQ, 100);
  936.     add(MI::WR+MI::WN+MI::BB, 50);
  937.     add(MI::WR+MI::WN+MI::BP, 29);
  938.     add(MI::WB+MI::WP+MI::BN, 60);
  939.     add(MI::WB+MI::WN+MI::BQ, 84);
  940.     add(MI::WB+MI::WP+MI::BP, 74);
  941.     add(MI::WN*2+MI::BP, 100);
  942.     add(MI::WN+MI::WP+MI::BB, 48);
  943.     add(MI::WP*2+MI::BB, 24);
  944.     add(MI::WP*2+MI::BQ, 58);
  945.     add(MI::WP*2+MI::BP, 42);
  946.     add(MI::WP*2+MI::BN, 27);
  947.     add(MI::WP*2+MI::BR, 30);
  948.     add(MI::WN+MI::WP+MI::BN, 59);
  949.     add(MI::WN+MI::WP+MI::BP, 46);
  950.     add(MI::WR+MI::WP+MI::BN, 62);
  951.     add(MI::WR+MI::WP+MI::BB, 100);
  952.     add(MI::WN+MI::WP+MI::BQ, 86);
  953.     add(MI::WB+MI::WN+MI::BP, 40);
  954.     add(MI::WR+MI::WP+MI::BQ, 100);
  955.     add(MI::WB+MI::WP+MI::BQ, 84);
  956.  
  957.     // 6-men
  958.     add(MI::WB*4, 20);
  959.     add(MI::WB*3+MI::BB, 40);
  960.     add(MI::WB*3+MI::BN, 28);
  961.     add(MI::WB*3+MI::BP, 24);
  962.     add(MI::WB*3+MI::BQ, 100);
  963.     add(MI::WB*3+MI::BR, 100);
  964.     add(MI::WB*3+MI::WN, 26);
  965.     add(MI::WB*3+MI::WP, 24);
  966.     add(MI::WB*2+MI::BB*2, 11);
  967.     add(MI::WB*2+MI::BB+MI::BN, 40);
  968.     add(MI::WB*2+MI::BB+MI::BP, 69);
  969.     add(MI::WB*2+MI::BN*2, 56);
  970.     add(MI::WB*2+MI::BN+MI::BP, 100);
  971.     add(MI::WB*2+MI::BP*2, 39);
  972.     add(MI::WB*2+MI::WN+MI::BB, 72);
  973.     add(MI::WB*2+MI::WN+MI::BN, 62);
  974.     add(MI::WB*2+MI::WN+MI::BP, 32);
  975.     add(MI::WB*2+MI::WN+MI::BQ, 100);
  976.     add(MI::WB*2+MI::WN+MI::BR, 100);
  977.     add(MI::WB*2+MI::WN*2, 20);
  978.     add(MI::WB*2+MI::WN+MI::WP, 10);
  979.     add(MI::WB*2+MI::WP+MI::BB, 56);
  980.     add(MI::WB*2+MI::WP+MI::BN, 100);
  981.     add(MI::WB*2+MI::WP+MI::BP, 29);
  982.     add(MI::WB*2+MI::WP+MI::BQ, 100);
  983.     add(MI::WB*2+MI::WP+MI::BR, 100);
  984.     add(MI::WB*2+MI::WP*2, 12);
  985.     add(MI::WB+MI::WN+MI::BB+MI::BN, 17);
  986.     add(MI::WB+MI::WN+MI::BB+MI::BP, 56);
  987.     add(MI::WB+MI::WN+MI::BN*2, 24);
  988.     add(MI::WB+MI::WN+MI::BN+MI::BP, 98);
  989.     add(MI::WB+MI::WN+MI::BP*2, 48);
  990.     add(MI::WB+MI::WN*2+MI::BB, 76);
  991.     add(MI::WB+MI::WN*2+MI::BN, 58);
  992.     add(MI::WB+MI::WN*2+MI::BP, 33);
  993.     add(MI::WB+MI::WN*2+MI::BQ, 98);
  994.     add(MI::WB+MI::WN*2+MI::BR, 96);
  995.     add(MI::WB+MI::WN*3, 20);
  996.     add(MI::WB+MI::WN*2+MI::WP, 10);
  997.     add(MI::WB+MI::WN+MI::WP+MI::BB, 86);
  998.     add(MI::WB+MI::WN+MI::WP+MI::BN, 77);
  999.     add(MI::WB+MI::WN+MI::WP+MI::BP, 21);
  1000.     add(MI::WB+MI::WN+MI::WP+MI::BQ, 100);
  1001.     add(MI::WB+MI::WN+MI::WP+MI::BR, 100);
  1002.     add(MI::WB+MI::WN+MI::WP*2, 10);
  1003.     add(MI::WB+MI::WP+MI::BB+MI::BP, 65);
  1004.     add(MI::WB+MI::WP+MI::BN*2, 48);
  1005.     add(MI::WB+MI::WP+MI::BN+MI::BP, 62);
  1006.     add(MI::WB+MI::WP+MI::BP*2, 75);
  1007.     add(MI::WB+MI::WP*2+MI::BB, 86);
  1008.     add(MI::WB+MI::WP*2+MI::BN, 100);
  1009.     add(MI::WB+MI::WP*2+MI::BP, 61);
  1010.     add(MI::WB+MI::WP*2+MI::BQ, 78);
  1011.     add(MI::WB+MI::WP*2+MI::BR, 66);
  1012.     add(MI::WB+MI::WP*3, 18);
  1013.     add(MI::WN*2+MI::BN*2, 13);
  1014.     add(MI::WN*2+MI::BN+MI::BP, 56);
  1015.     add(MI::WN*2+MI::BP*2, 100);
  1016.     add(MI::WN*3+MI::BB, 100);
  1017.     add(MI::WN*3+MI::BN, 100);
  1018.     add(MI::WN*3+MI::BP, 41);
  1019.     add(MI::WN*3+MI::BQ, 70);
  1020.     add(MI::WN*3+MI::BR, 22);
  1021.     add(MI::WN*4, 22);
  1022.     add(MI::WN*3+MI::WP, 12);
  1023.     add(MI::WN*2+MI::WP+MI::BB, 100);
  1024.     add(MI::WN*2+MI::WP+MI::BN, 100);
  1025.     add(MI::WN*2+MI::WP+MI::BP, 33);
  1026.     add(MI::WN*2+MI::WP+MI::BQ, 100);
  1027.     add(MI::WN*2+MI::WP+MI::BR, 91);
  1028.     add(MI::WN*2+MI::WP*2, 12);
  1029.     add(MI::WN+MI::WP+MI::BN+MI::BP, 57);
  1030.     add(MI::WN+MI::WP+MI::BP*2, 66);
  1031.     add(MI::WN+MI::WP*2+MI::BB, 97);
  1032.     add(MI::WN+MI::WP*2+MI::BN, 96);
  1033.     add(MI::WN+MI::WP*2+MI::BP, 40);
  1034.     add(MI::WN+MI::WP*2+MI::BQ, 78);
  1035.     add(MI::WN+MI::WP*2+MI::BR, 81);
  1036.     add(MI::WN+MI::WP*3, 10);
  1037.     add(MI::WP*2+MI::BP*2, 31);
  1038.     add(MI::WP*3+MI::BB, 36);
  1039.     add(MI::WP*3+MI::BN, 42);
  1040.     add(MI::WP*3+MI::BP, 40);
  1041.     add(MI::WP*3+MI::BQ, 65);
  1042.     add(MI::WP*3+MI::BR, 44);
  1043.     add(MI::WP*4, 14);
  1044.     add(MI::WQ+MI::WB*3, 12);
  1045.     add(MI::WQ+MI::WB*2+MI::BB, 16);
  1046.     add(MI::WQ+MI::WB*2+MI::BN, 14);
  1047.     add(MI::WQ+MI::WB*2+MI::BP, 10);
  1048.     add(MI::WQ+MI::WB*2+MI::BQ, 100);
  1049.     add(MI::WQ+MI::WB*2+MI::BR, 40);
  1050.     add(MI::WQ+MI::WB*2+MI::WN, 10);
  1051.     add(MI::WQ+MI::WB*2+MI::WP, 6);
  1052.     add(MI::WQ+MI::WB+MI::BB*2, 26);
  1053.     add(MI::WQ+MI::WB+MI::BB+MI::BN, 32);
  1054.     add(MI::WQ+MI::WB+MI::BB+MI::BP, 44);
  1055.     add(MI::WQ+MI::WB+MI::BN*2, 26);
  1056.     add(MI::WQ+MI::WB+MI::BN+MI::BP, 53);
  1057.     add(MI::WQ+MI::WB+MI::BP*2, 34);
  1058.     add(MI::WQ+MI::WB+MI::BQ+MI::BB, 91);
  1059.     add(MI::WQ+MI::WB+MI::BQ+MI::BN, 72);
  1060.     add(MI::WQ+MI::WB+MI::BQ+MI::BP, 100);
  1061.     add(MI::WQ+MI::WB+MI::BR+MI::BB, 83);
  1062.     add(MI::WQ+MI::WB+MI::BR+MI::BN, 54);
  1063.     add(MI::WQ+MI::WB+MI::BR+MI::BP, 77);
  1064.     add(MI::WQ+MI::WB+MI::BR*2, 100);
  1065.     add(MI::WQ+MI::WB+MI::WN+MI::BB, 14);
  1066.     add(MI::WQ+MI::WB+MI::WN+MI::BN, 12);
  1067.     add(MI::WQ+MI::WB+MI::WN+MI::BP, 8);
  1068.     add(MI::WQ+MI::WB+MI::WN+MI::BQ, 100);
  1069.     add(MI::WQ+MI::WB+MI::WN+MI::BR, 44);
  1070.     add(MI::WQ+MI::WB+MI::WN*2, 10);
  1071.     add(MI::WQ+MI::WB+MI::WN+MI::WP, 6);
  1072.     add(MI::WQ+MI::WB+MI::WP+MI::BB, 12);
  1073.     add(MI::WQ+MI::WB+MI::WP+MI::BN, 12);
  1074.     add(MI::WQ+MI::WB+MI::WP+MI::BP, 8);
  1075.     add(MI::WQ+MI::WB+MI::WP+MI::BQ, 100);
  1076.     add(MI::WQ+MI::WB+MI::WP+MI::BR, 62);
  1077.     add(MI::WQ+MI::WB+MI::WP*2, 8);
  1078.     add(MI::WQ+MI::WN+MI::BB*2, 30);
  1079.     add(MI::WQ+MI::WN+MI::BB+MI::BN, 34);
  1080.     add(MI::WQ+MI::WN+MI::BB+MI::BP, 67);
  1081.     add(MI::WQ+MI::WN+MI::BN*2, 32);
  1082.     add(MI::WQ+MI::WN+MI::BN+MI::BP, 62);
  1083.     add(MI::WQ+MI::WN+MI::BP*2, 44);
  1084.     add(MI::WQ+MI::WN+MI::BQ+MI::BN, 57);
  1085.     add(MI::WQ+MI::WN+MI::BQ+MI::BP, 100);
  1086.     add(MI::WQ+MI::WN+MI::BR+MI::BB, 52);
  1087.     add(MI::WQ+MI::WN+MI::BR+MI::BN, 80);
  1088.     add(MI::WQ+MI::WN+MI::BR+MI::BP, 83);
  1089.     add(MI::WQ+MI::WN+MI::BR*2, 100);
  1090.     add(MI::WQ+MI::WN*2+MI::BB, 22);
  1091.     add(MI::WQ+MI::WN*2+MI::BN, 18);
  1092.     add(MI::WQ+MI::WN*2+MI::BP, 20);
  1093.     add(MI::WQ+MI::WN*2+MI::BQ, 100);
  1094.     add(MI::WQ+MI::WN*2+MI::BR, 44);
  1095.     add(MI::WQ+MI::WN*3, 10);
  1096.     add(MI::WQ+MI::WN*2+MI::WP, 6);
  1097.     add(MI::WQ+MI::WN+MI::WP+MI::BB, 12);
  1098.     add(MI::WQ+MI::WN+MI::WP+MI::BN, 12);
  1099.     add(MI::WQ+MI::WN+MI::WP+MI::BP, 12);
  1100.     add(MI::WQ+MI::WN+MI::WP+MI::BQ, 100);
  1101.     add(MI::WQ+MI::WN+MI::WP+MI::BR, 42);
  1102.     add(MI::WQ+MI::WN+MI::WP*2, 10);
  1103.     add(MI::WQ+MI::WP+MI::BB*2, 44);
  1104.     add(MI::WQ+MI::WP+MI::BB+MI::BN, 36);
  1105.     add(MI::WQ+MI::WP+MI::BB+MI::BP, 99);
  1106.     add(MI::WQ+MI::WP+MI::BN*2, 92);
  1107.     add(MI::WQ+MI::WP+MI::BN+MI::BP, 54);
  1108.     add(MI::WQ+MI::WP+MI::BP*2, 35);
  1109.     add(MI::WQ+MI::WP+MI::BQ+MI::BP, 100);
  1110.     add(MI::WQ+MI::WP+MI::BR+MI::BB, 100);
  1111.     add(MI::WQ+MI::WP+MI::BR+MI::BN, 100);
  1112.     add(MI::WQ+MI::WP+MI::BR+MI::BP, 100);
  1113.     add(MI::WQ+MI::WP+MI::BR*2, 100);
  1114.     add(MI::WQ+MI::WP*2+MI::BB, 12);
  1115.     add(MI::WQ+MI::WP*2+MI::BN, 12);
  1116.     add(MI::WQ+MI::WP*2+MI::BP, 10);
  1117.     add(MI::WQ+MI::WP*2+MI::BQ, 100);
  1118.     add(MI::WQ+MI::WP*2+MI::BR, 42);
  1119.     add(MI::WQ+MI::WP*3, 6);
  1120.     add(MI::WQ*2+MI::WB*2, 6);
  1121.     add(MI::WQ*2+MI::WB+MI::BB, 10);
  1122.     add(MI::WQ*2+MI::WB+MI::BN, 10);
  1123.     add(MI::WQ*2+MI::WB+MI::BP, 6);
  1124.     add(MI::WQ*2+MI::WB+MI::BQ, 58);
  1125.     add(MI::WQ*2+MI::WB+MI::BR, 52);
  1126.     add(MI::WQ*2+MI::WB+MI::WN, 8);
  1127.     add(MI::WQ*2+MI::WB+MI::WP, 6);
  1128.     add(MI::WQ*2+MI::BB*2, 16);
  1129.     add(MI::WQ*2+MI::BB+MI::BN, 16);
  1130.     add(MI::WQ*2+MI::BB+MI::BP, 12);
  1131.     add(MI::WQ*2+MI::BN*2, 14);
  1132.     add(MI::WQ*2+MI::BN+MI::BP, 11);
  1133.     add(MI::WQ*2+MI::BP*2, 6);
  1134.     add(MI::WQ*2+MI::BQ+MI::BB, 100);
  1135.     add(MI::WQ*2+MI::BQ+MI::BN, 100);
  1136.     add(MI::WQ*2+MI::BQ+MI::BP, 79);
  1137.     add(MI::WQ*2+MI::BQ*2, 87);
  1138.     add(MI::WQ*2+MI::BQ+MI::BR, 100);
  1139.     add(MI::WQ*2+MI::BR+MI::BB, 27);
  1140.     add(MI::WQ*2+MI::BR+MI::BN, 28);
  1141.     add(MI::WQ*2+MI::BR+MI::BP, 38);
  1142.     add(MI::WQ*2+MI::BR*2, 36);
  1143.     add(MI::WQ*2+MI::WN+MI::BB, 8);
  1144.     add(MI::WQ*2+MI::WN+MI::BN, 10);
  1145.     add(MI::WQ*2+MI::WN+MI::BP, 6);
  1146.     add(MI::WQ*2+MI::WN+MI::BQ, 56);
  1147.     add(MI::WQ*2+MI::WN+MI::BR, 48);
  1148.     add(MI::WQ*2+MI::WN*2, 8);
  1149.     add(MI::WQ*2+MI::WN+MI::WP, 6);
  1150.     add(MI::WQ*2+MI::WP+MI::BB, 8);
  1151.     add(MI::WQ*2+MI::WP+MI::BN, 10);
  1152.     add(MI::WQ*2+MI::WP+MI::BP, 6);
  1153.     add(MI::WQ*2+MI::WP+MI::BQ, 70);
  1154.     add(MI::WQ*2+MI::WP+MI::BR, 48);
  1155.     add(MI::WQ*2+MI::WP*2, 6);
  1156.     add(MI::WQ*3+MI::WB, 6);
  1157.     add(MI::WQ*3+MI::BB, 6);
  1158.     add(MI::WQ*3+MI::BN, 8);
  1159.     add(MI::WQ*3+MI::BP, 6);
  1160.     add(MI::WQ*3+MI::BQ, 38);
  1161.     add(MI::WQ*3+MI::BR, 40);
  1162.     add(MI::WQ*3+MI::WN, 6);
  1163.     add(MI::WQ*3+MI::WP, 6);
  1164.     add(MI::WQ*4, 6);
  1165.     add(MI::WQ*3+MI::WR, 6);
  1166.     add(MI::WQ*2+MI::WR+MI::WB, 6);
  1167.     add(MI::WQ*2+MI::WR+MI::BB, 8);
  1168.     add(MI::WQ*2+MI::WR+MI::BN, 10);
  1169.     add(MI::WQ*2+MI::WR+MI::BP, 6);
  1170.     add(MI::WQ*2+MI::WR+MI::BQ, 56);
  1171.     add(MI::WQ*2+MI::WR+MI::BR, 48);
  1172.     add(MI::WQ*2+MI::WR+MI::WN, 8);
  1173.     add(MI::WQ*2+MI::WR+MI::WP, 6);
  1174.     add(MI::WQ*2+MI::WR*2, 6);
  1175.     add(MI::WQ+MI::WR+MI::WB*2, 8);
  1176.     add(MI::WQ+MI::WR+MI::WB+MI::BB, 10);
  1177.     add(MI::WQ+MI::WR+MI::WB+MI::BN, 10);
  1178.     add(MI::WQ+MI::WR+MI::WB+MI::BP, 6);
  1179.     add(MI::WQ+MI::WR+MI::WB+MI::BQ, 98);
  1180.     add(MI::WQ+MI::WR+MI::WB+MI::BR, 50);
  1181.     add(MI::WQ+MI::WR+MI::WB+MI::WN, 8);
  1182.     add(MI::WQ+MI::WR+MI::WB+MI::WP, 8);
  1183.     add(MI::WQ+MI::WR+MI::BB*2, 24);
  1184.     add(MI::WQ+MI::WR+MI::BB+MI::BN, 22);
  1185.     add(MI::WQ+MI::WR+MI::BB+MI::BP, 28);
  1186.     add(MI::WQ+MI::WR+MI::BN*2, 21);
  1187.     add(MI::WQ+MI::WR+MI::BN+MI::BP, 26);
  1188.     add(MI::WQ+MI::WR+MI::BP*2, 12);
  1189.     add(MI::WQ+MI::WR+MI::BQ+MI::BB, 100);
  1190.     add(MI::WQ+MI::WR+MI::BQ+MI::BN, 100);
  1191.     add(MI::WQ+MI::WR+MI::BQ+MI::BP, 100);
  1192.     add(MI::WQ+MI::WR+MI::BQ+MI::BR, 100);
  1193.     add(MI::WQ+MI::WR+MI::BR+MI::BB, 42);
  1194.     add(MI::WQ+MI::WR+MI::BR+MI::BN, 42);
  1195.     add(MI::WQ+MI::WR+MI::BR+MI::BP, 44);
  1196.     add(MI::WQ+MI::WR+MI::BR*2, 68);
  1197.     add(MI::WQ+MI::WR+MI::WN+MI::BB, 8);
  1198.     add(MI::WQ+MI::WR+MI::WN+MI::BN, 12);
  1199.     add(MI::WQ+MI::WR+MI::WN+MI::BP, 7);
  1200.     add(MI::WQ+MI::WR+MI::WN+MI::BQ, 100);
  1201.     add(MI::WQ+MI::WR+MI::WN+MI::BR, 48);
  1202.     add(MI::WQ+MI::WR+MI::WN*2, 8);
  1203.     add(MI::WQ+MI::WR+MI::WN+MI::WP, 8);
  1204.     add(MI::WQ+MI::WR+MI::WP+MI::BB, 8);
  1205.     add(MI::WQ+MI::WR+MI::WP+MI::BN, 10);
  1206.     add(MI::WQ+MI::WR+MI::WP+MI::BP, 7);
  1207.     add(MI::WQ+MI::WR+MI::WP+MI::BQ, 100);
  1208.     add(MI::WQ+MI::WR+MI::WP+MI::BR, 60);
  1209.     add(MI::WQ+MI::WR+MI::WP*2, 6);
  1210.     add(MI::WQ+MI::WR*2+MI::WB, 8);
  1211.     add(MI::WQ+MI::WR*2+MI::BB, 8);
  1212.     add(MI::WQ+MI::WR*2+MI::BN, 10);
  1213.     add(MI::WQ+MI::WR*2+MI::BP, 6);
  1214.     add(MI::WQ+MI::WR*2+MI::BQ, 82);
  1215.     add(MI::WQ+MI::WR*2+MI::BR, 46);
  1216.     add(MI::WQ+MI::WR*2+MI::WN, 8);
  1217.     add(MI::WQ+MI::WR*2+MI::WP, 6);
  1218.     add(MI::WQ+MI::WR*3, 8);
  1219.     add(MI::WR+MI::WB*3, 20);
  1220.     add(MI::WR+MI::WB*2+MI::BB, 36);
  1221.     add(MI::WR+MI::WB*2+MI::BN, 23);
  1222.     add(MI::WR+MI::WB*2+MI::BP, 24);
  1223.     add(MI::WR+MI::WB*2+MI::BQ, 88);
  1224.     add(MI::WR+MI::WB*2+MI::BR, 71);
  1225.     add(MI::WR+MI::WB*2+MI::WN, 14);
  1226.     add(MI::WR+MI::WB*2+MI::WP, 10);
  1227.     add(MI::WR+MI::WB+MI::BB*2, 100);
  1228.     add(MI::WR+MI::WB+MI::BB+MI::BN, 100);
  1229.     add(MI::WR+MI::WB+MI::BB+MI::BP, 76);
  1230.     add(MI::WR+MI::WB+MI::BN*2, 100);
  1231.     add(MI::WR+MI::WB+MI::BN+MI::BP, 90);
  1232.     add(MI::WR+MI::WB+MI::BP*2, 47);
  1233.     add(MI::WR+MI::WB+MI::BR+MI::BB, 33);
  1234.     add(MI::WR+MI::WB+MI::BR+MI::BN, 40);
  1235.     add(MI::WR+MI::WB+MI::BR+MI::BP, 94);
  1236.     add(MI::WR+MI::WB+MI::WN+MI::BB, 26);
  1237.     add(MI::WR+MI::WB+MI::WN+MI::BN, 24);
  1238.     add(MI::WR+MI::WB+MI::WN+MI::BP, 31);
  1239.     add(MI::WR+MI::WB+MI::WN+MI::BQ, 100);
  1240.     add(MI::WR+MI::WB+MI::WN+MI::BR, 72);
  1241.     add(MI::WR+MI::WB+MI::WN*2, 14);
  1242.     add(MI::WR+MI::WB+MI::WN+MI::WP, 10);
  1243.     add(MI::WR+MI::WB+MI::WP+MI::BB, 20);
  1244.     add(MI::WR+MI::WB+MI::WP+MI::BN, 20);
  1245.     add(MI::WR+MI::WB+MI::WP+MI::BP, 21);
  1246.     add(MI::WR+MI::WB+MI::WP+MI::BQ, 100);
  1247.     add(MI::WR+MI::WB+MI::WP+MI::BR, 100);
  1248.     add(MI::WR+MI::WB+MI::WP*2, 8);
  1249.     add(MI::WR+MI::WN+MI::BB*2, 100);
  1250.     add(MI::WR+MI::WN+MI::BB+MI::BN, 100);
  1251.     add(MI::WR+MI::WN+MI::BB+MI::BP, 100);
  1252.     add(MI::WR+MI::WN+MI::BN*2, 100);
  1253.     add(MI::WR+MI::WN+MI::BN+MI::BP, 100);
  1254.     add(MI::WR+MI::WN+MI::BP*2, 48);
  1255.     add(MI::WR+MI::WN+MI::BR+MI::BN, 41);
  1256.     add(MI::WR+MI::WN+MI::BR+MI::BP, 72);
  1257.     add(MI::WR+MI::WN*2+MI::BB, 24);
  1258.     add(MI::WR+MI::WN*2+MI::BN, 25);
  1259.     add(MI::WR+MI::WN*2+MI::BP, 30);
  1260.     add(MI::WR+MI::WN*2+MI::BQ, 81);
  1261.     add(MI::WR+MI::WN*2+MI::BR, 78);
  1262.     add(MI::WR+MI::WN*3, 14);
  1263.     add(MI::WR+MI::WN*2+MI::WP, 8);
  1264.     add(MI::WR+MI::WN+MI::WP+MI::BB, 26);
  1265.     add(MI::WR+MI::WN+MI::WP+MI::BN, 20);
  1266.     add(MI::WR+MI::WN+MI::WP+MI::BP, 27);
  1267.     add(MI::WR+MI::WN+MI::WP+MI::BQ, 100);
  1268.     add(MI::WR+MI::WN+MI::WP+MI::BR, 100);
  1269.     add(MI::WR+MI::WN+MI::WP*2, 10);
  1270.     add(MI::WR+MI::WP+MI::BB*2, 79);
  1271.     add(MI::WR+MI::WP+MI::BB+MI::BN, 100);
  1272.     add(MI::WR+MI::WP+MI::BB+MI::BP, 100);
  1273.     add(MI::WR+MI::WP+MI::BN*2, 84);
  1274.     add(MI::WR+MI::WP+MI::BN+MI::BP, 100);
  1275.     add(MI::WR+MI::WP+MI::BP*2, 31);
  1276.     add(MI::WR+MI::WP+MI::BR+MI::BP, 73);
  1277.     add(MI::WR+MI::WP*2+MI::BB, 36);
  1278.     add(MI::WR+MI::WP*2+MI::BN, 36);
  1279.     add(MI::WR+MI::WP*2+MI::BP, 26);
  1280.     add(MI::WR+MI::WP*2+MI::BQ, 100);
  1281.     add(MI::WR+MI::WP*2+MI::BR, 90);
  1282.     add(MI::WR+MI::WP*3, 6);
  1283.     add(MI::WR*2+MI::WB*2, 12);
  1284.     add(MI::WR*2+MI::WB+MI::BB, 14);
  1285.     add(MI::WR*2+MI::WB+MI::BN, 12);
  1286.     add(MI::WR*2+MI::WB+MI::BP, 8);
  1287.     add(MI::WR*2+MI::WB+MI::BQ, 100);
  1288.     add(MI::WR*2+MI::WB+MI::BR, 62);
  1289.     add(MI::WR*2+MI::WB+MI::WN, 12);
  1290.     add(MI::WR*2+MI::WB+MI::WP, 8);
  1291.     add(MI::WR*2+MI::BB*2, 74);
  1292.     add(MI::WR*2+MI::BB+MI::BN, 51);
  1293.     add(MI::WR*2+MI::BB+MI::BP, 52);
  1294.     add(MI::WR*2+MI::BN*2, 66);
  1295.     add(MI::WR*2+MI::BN+MI::BP, 50);
  1296.     add(MI::WR*2+MI::BP*2, 50);
  1297.     add(MI::WR*2+MI::BR+MI::BB, 100);
  1298.     add(MI::WR*2+MI::BR+MI::BN, 100);
  1299.     add(MI::WR*2+MI::BR+MI::BP, 100);
  1300.     add(MI::WR*2+MI::BR*2, 35);
  1301.     add(MI::WR*2+MI::WN+MI::BB, 14);
  1302.     add(MI::WR*2+MI::WN+MI::BN, 14);
  1303.     add(MI::WR*2+MI::WN+MI::BP, 18);
  1304.     add(MI::WR*2+MI::WN+MI::BQ, 100);
  1305.     add(MI::WR*2+MI::WN+MI::BR, 66);
  1306.     add(MI::WR*2+MI::WN*2, 12);
  1307.     add(MI::WR*2+MI::WN+MI::WP, 8);
  1308.     add(MI::WR*2+MI::WP+MI::BB, 14);
  1309.     add(MI::WR*2+MI::WP+MI::BN, 12);
  1310.     add(MI::WR*2+MI::WP+MI::BP, 22);
  1311.     add(MI::WR*2+MI::WP+MI::BQ, 100);
  1312.     add(MI::WR*2+MI::WP+MI::BR, 56);
  1313.     add(MI::WR*2+MI::WP*2, 6);
  1314.     add(MI::WR*3+MI::WB, 10);
  1315.     add(MI::WR*3+MI::BB, 10);
  1316.     add(MI::WR*3+MI::BN, 12);
  1317.     add(MI::WR*3+MI::BP, 6);
  1318.     add(MI::WR*3+MI::BQ, 100);
  1319.     add(MI::WR*3+MI::BR, 42);
  1320.     add(MI::WR*3+MI::WN, 10);
  1321.     add(MI::WR*3+MI::WP, 8);
  1322.     add(MI::WR*4, 8);
  1323. }
  1324.