Subversion Repositories Games.Chess Giants

Rev

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

  1. /*
  2.     Texel - A UCI chess engine.
  3.     Copyright (C) 2012-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.  * parameters.cpp
  21.  *
  22.  *  Created on: Feb 25, 2012
  23.  *      Author: petero
  24.  */
  25.  
  26. #include "parameters.hpp"
  27. #include "computerPlayer.hpp"
  28.  
  29. namespace UciParams {
  30.     std::shared_ptr<Parameters::SpinParam> hash(std::make_shared<Parameters::SpinParam>("Hash", 1, 524288, 16));
  31.     std::shared_ptr<Parameters::CheckParam> ownBook(std::make_shared<Parameters::CheckParam>("OwnBook", false));
  32.     std::shared_ptr<Parameters::CheckParam> ponder(std::make_shared<Parameters::CheckParam>("Ponder", true));
  33.     std::shared_ptr<Parameters::CheckParam> analyseMode(std::make_shared<Parameters::CheckParam>("UCI_AnalyseMode", false));
  34.     std::shared_ptr<Parameters::SpinParam> strength(std::make_shared<Parameters::SpinParam>("Strength", 0, 1000, 1000));
  35.     std::shared_ptr<Parameters::SpinParam> threads(std::make_shared<Parameters::SpinParam>("Threads", 1, 64, 1));
  36.     std::shared_ptr<Parameters::SpinParam> multiPV(std::make_shared<Parameters::SpinParam>("MultiPV", 1, 256, 1));
  37.  
  38.     std::shared_ptr<Parameters::StringParam> gtbPath(std::make_shared<Parameters::StringParam>("GaviotaTbPath", ""));
  39.     std::shared_ptr<Parameters::SpinParam> gtbCache(std::make_shared<Parameters::SpinParam>("GaviotaTbCache", 1, 2047, 1));
  40.     std::shared_ptr<Parameters::StringParam> rtbPath(std::make_shared<Parameters::StringParam>("SyzygyPath", ""));
  41.     std::shared_ptr<Parameters::SpinParam> minProbeDepth(std::make_shared<Parameters::SpinParam>("MinProbeDepth", 0, 100, 1));
  42.  
  43.     std::shared_ptr<Parameters::ButtonParam> clearHash(std::make_shared<Parameters::ButtonParam>("Clear Hash"));
  44. }
  45.  
  46. int pieceValue[Piece::nPieceTypes];
  47.  
  48. DEFINE_PARAM(pV);
  49. DEFINE_PARAM(nV);
  50. DEFINE_PARAM(bV);
  51. DEFINE_PARAM(rV);
  52. DEFINE_PARAM(qV);
  53. DEFINE_PARAM(kV);
  54.  
  55. DEFINE_PARAM(pawnIslandPenalty);
  56. DEFINE_PARAM(pawnBackwardPenalty);
  57. DEFINE_PARAM(pawnSemiBackwardPenalty1);
  58. DEFINE_PARAM(pawnSemiBackwardPenalty2);
  59. DEFINE_PARAM(pawnRaceBonus);
  60. DEFINE_PARAM(passedPawnEGFactor);
  61. DEFINE_PARAM(RBehindPP1);
  62. DEFINE_PARAM(RBehindPP2);
  63.  
  64. DEFINE_PARAM(QvsRMBonus1);
  65. DEFINE_PARAM(QvsRMBonus2);
  66. DEFINE_PARAM(knightVsQueenBonus1);
  67. DEFINE_PARAM(knightVsQueenBonus2);
  68. DEFINE_PARAM(knightVsQueenBonus3);
  69. DEFINE_PARAM(krkpBonus);
  70. DEFINE_PARAM(krpkbBonus);
  71. DEFINE_PARAM(krpkbPenalty);
  72. DEFINE_PARAM(krpknBonus);
  73. DEFINE_PARAM(RvsBPBonus);
  74.  
  75. DEFINE_PARAM(pawnTradePenalty);
  76. DEFINE_PARAM(pieceTradeBonus);
  77. DEFINE_PARAM(pawnTradeThreshold);
  78. DEFINE_PARAM(pieceTradeThreshold);
  79.  
  80. DEFINE_PARAM(threatBonus1);
  81. DEFINE_PARAM(threatBonus2);
  82.  
  83. DEFINE_PARAM(rookHalfOpenBonus);
  84. DEFINE_PARAM(rookOpenBonus);
  85. DEFINE_PARAM(rookDouble7thRowBonus);
  86. DEFINE_PARAM(trappedRookPenalty1);
  87. DEFINE_PARAM(trappedRookPenalty2);
  88.  
  89. DEFINE_PARAM(bishopPairPawnPenalty);
  90. DEFINE_PARAM(trappedBishopPenalty);
  91. DEFINE_PARAM(oppoBishopPenalty);
  92.  
  93. DEFINE_PARAM(kingSafetyHalfOpenBCDEFG1);
  94. DEFINE_PARAM(kingSafetyHalfOpenBCDEFG2);
  95. DEFINE_PARAM(kingSafetyHalfOpenAH1);
  96. DEFINE_PARAM(kingSafetyHalfOpenAH2);
  97. DEFINE_PARAM(kingSafetyWeight1);
  98. DEFINE_PARAM(kingSafetyWeight2);
  99. DEFINE_PARAM(kingSafetyWeight3);
  100. DEFINE_PARAM(kingSafetyWeight4);
  101. DEFINE_PARAM(kingSafetyThreshold);
  102. DEFINE_PARAM(knightKingProtectBonus);
  103. DEFINE_PARAM(bishopKingProtectBonus);
  104. DEFINE_PARAM(pawnStormBonus);
  105.  
  106. DEFINE_PARAM(pawnLoMtrl);
  107. DEFINE_PARAM(pawnHiMtrl);
  108. DEFINE_PARAM(minorLoMtrl);
  109. DEFINE_PARAM(minorHiMtrl);
  110. DEFINE_PARAM(castleLoMtrl);
  111. DEFINE_PARAM(castleHiMtrl);
  112. DEFINE_PARAM(queenLoMtrl);
  113. DEFINE_PARAM(queenHiMtrl);
  114. DEFINE_PARAM(passedPawnLoMtrl);
  115. DEFINE_PARAM(passedPawnHiMtrl);
  116. DEFINE_PARAM(kingSafetyLoMtrl);
  117. DEFINE_PARAM(kingSafetyHiMtrl);
  118. DEFINE_PARAM(oppoBishopLoMtrl);
  119. DEFINE_PARAM(oppoBishopHiMtrl);
  120. DEFINE_PARAM(knightOutpostLoMtrl);
  121. DEFINE_PARAM(knightOutpostHiMtrl);
  122.  
  123.  
  124. DEFINE_PARAM(aspirationWindow);
  125. DEFINE_PARAM(rootLMRMoveCount);
  126.  
  127. DEFINE_PARAM(razorMargin1);
  128. DEFINE_PARAM(razorMargin2);
  129.  
  130. DEFINE_PARAM(reverseFutilityMargin1);
  131. DEFINE_PARAM(reverseFutilityMargin2);
  132. DEFINE_PARAM(reverseFutilityMargin3);
  133. DEFINE_PARAM(reverseFutilityMargin4);
  134.  
  135. DEFINE_PARAM(futilityMargin1);
  136. DEFINE_PARAM(futilityMargin2);
  137. DEFINE_PARAM(futilityMargin3);
  138. DEFINE_PARAM(futilityMargin4);
  139.  
  140. DEFINE_PARAM(lmpMoveCountLimit1);
  141. DEFINE_PARAM(lmpMoveCountLimit2);
  142. DEFINE_PARAM(lmpMoveCountLimit3);
  143. DEFINE_PARAM(lmpMoveCountLimit4);
  144.  
  145. DEFINE_PARAM(lmrMoveCountLimit1);
  146. DEFINE_PARAM(lmrMoveCountLimit2);
  147.  
  148. DEFINE_PARAM(quiesceMaxSortMoves);
  149. DEFINE_PARAM(deltaPruningMargin);
  150.  
  151. DEFINE_PARAM(timeMaxRemainingMoves);
  152. DEFINE_PARAM(bufferTime);
  153. DEFINE_PARAM(minTimeUsage);
  154. DEFINE_PARAM(maxTimeUsage);
  155. DEFINE_PARAM(timePonderHitRate);
  156.  
  157. /** Piece/square table for king during middle game. */
  158. ParamTable<64> kt1b { -200, 200, useUciParam,
  159.     {  71, 118, 113,  98,  88, 112, 129,  44,
  160.       117,   3,  36,  37,  64,  37,   3,  99,
  161.       -28,  -4,  13,  12,  18,  28,  25, -41,
  162.       -11, -11, -15, -20, -12,   4,  -9, -19,
  163.       -36, -14, -29, -31, -33, -33, -19, -76,
  164.       -12,   1, -25, -49, -23, -11,   7, -17,
  165.        24,  23,   3,  -7,   2,  -1,  39,  36,
  166.        -2,  34,  24, -27,  14, -15,  31,  10 },
  167.     {   1,   2,   3,   4,   5,   6,   7,   8,
  168.         9,  10,  11,  12,  13,  14,  15,  16,
  169.        17,  18,  19,  20,  21,  22,  23,  24,
  170.        25,  26,  27,  28,  29,  30,  31,  32,
  171.        33,  34,  35,  36,  37,  38,  39,  40,
  172.        41,  42,  43,  44,  45,  46,  47,  48,
  173.        49,  50,  51,  52,  53,  54,  55,  56,
  174.        57,  58,  59,  60,  61,  62,  63,  64 }
  175. };
  176. ParamTableMirrored<64> kt1w(kt1b);
  177.  
  178. /** Piece/square table for king during end game. */
  179. ParamTable<64> kt2b { -200, 200, useUciParam,
  180.     { -18,  48,  73,  82,  82,  73,  48, -18,
  181.        33,  93, 108, 100, 100, 108,  93,  33,
  182.        78, 104, 110, 109, 109, 110, 104,  78,
  183.        68,  97, 105, 108, 108, 105,  97,  68,
  184.        54,  79,  92,  97,  97,  92,  79,  54,
  185.        43,  61,  75,  82,  82,  75,  61,  43,
  186.        28,  47,  63,  62,  62,  63,  47,  28,
  187.         0,  20,  33,  20,  20,  33,  20,   0 },
  188.     {   1,   2,   3,   4,   4,   3,   2,   1,
  189.         5,   6,   7,   8,   8,   7,   6,   5,
  190.         9,  10,  11,  12,  12,  11,  10,   9,
  191.        13,  14,  15,  16,  16,  15,  14,  13,
  192.        17,  18,  19,  20,  20,  19,  18,  17,
  193.        21,  22,  23,  24,  24,  23,  22,  21,
  194.        25,  26,  27,  28,  28,  27,  26,  25,
  195.         0,  29,  30,  31,  31,  30,  29,   0 }
  196. };
  197. ParamTableMirrored<64> kt2w(kt2b);
  198.  
  199. /** Piece/square table for pawns during middle game. */
  200. ParamTable<64> pt1b { -200, 300, useUciParam,
  201.     {   0,   0,   0,   0,   0,   0,   0,   0,
  202.       137, 103, 117, 123,  74,  97, -12, 148,
  203.        19,  31,  28,  26,  22,  41,  32,   8,
  204.        -7,  -5, -11,  -1,   4, -12,  -9,  -7,
  205.        -9,  -2,  -7,   0,  -1,   2,  -2, -17,
  206.       -12,  -9, -27, -15,  -5, -12,  -5,  -6,
  207.       -10, -14, -24, -20, -13,   0,   5,  -5,
  208.         0,   0,   0,   0,   0,   0,   0,   0 },
  209.     {   0,   0,   0,   0,   0,   0,   0,   0,
  210.         1,   2,   3,   4,   5,   6,   7,   8,
  211.         9,  10,  11,  12,  13,  14,  15,  16,
  212.        17,  18,  19,  20,  21,  22,  23,  24,
  213.        25,  26,  27,  28,  29,  30,  31,  32,
  214.        33,  34,  35,  36,  37,  38,  39,  40,
  215.        41,  42,  43,  44,  45,  46,  47,  48,
  216.         0,   0,   0,   0,   0,   0,   0,   0 }
  217. };
  218. ParamTableMirrored<64> pt1w(pt1b);
  219.  
  220. /** Piece/square table for pawns during end game. */
  221. ParamTable<64> pt2b { -200, 200, useUciParam,
  222.     {   0,   0,   0,   0,   0,   0,   0,   0,
  223.       -10,   9,   4,  -9,  -9,   4,   9, -10,
  224.        33,  35,  22,   7,   7,  22,  35,  33,
  225.        22,  26,  15,   6,   6,  15,  26,  22,
  226.        12,  23,  13,  13,  13,  13,  23,  12,
  227.         4,  17,  17,  21,  21,  17,  17,   4,
  228.         3,  17,  27,  32,  32,  27,  17,   3,
  229.         0,   0,   0,   0,   0,   0,   0,   0 },
  230.     {   0,   0,   0,   0,   0,   0,   0,   0,
  231.         1,   2,   3,   4,   4,   3,   2,   1,
  232.         5,   6,   7,   8,   8,   7,   6,   5,
  233.         9,  10,  11,  12,  12,  11,  10,   9,
  234.        13,  14,  15,  16,  16,  15,  14,  13,
  235.        17,  18,  19,  20,  20,  19,  18,  17,
  236.        21,  22,  23,  24,  24,  23,  22,  21,
  237.         0,   0,   0,   0,   0,   0,   0,   0 }
  238. };
  239. ParamTableMirrored<64> pt2w(pt2b);
  240.  
  241. /** Piece/square table for knights during middle game. */
  242. ParamTable<64> nt1b { -300, 200, useUciParam,
  243.     {-258, -21, -42,  -4,  22, -65, -22,-239,
  244.       -57, -52,  13,  40,  35,  98,  -2,  20,
  245.       -41,  -5,  22,  39,  95, 102,  47, -13,
  246.       -15,   1,   9,  38,  16,  45,  22,  23,
  247.       -18,   6,  11,   9,  27,  25,  27, -12,
  248.       -49, -10,  -1,  11,  19,   0,  -5, -35,
  249.       -55, -39, -23,   2,  -2,  -7, -30, -27,
  250.       -78, -38, -42, -34, -24, -31, -39, -94 },
  251.     {   1,   2,   3,   4,   5,   6,   7,   8,
  252.         9,  10,  11,  12,  13,  14,  15,  16,
  253.        17,  18,  19,  20,  21,  22,  23,  24,
  254.        25,  26,  27,  28,  29,  30,  31,  32,
  255.        33,  34,  35,  36,  37,  38,  39,  40,
  256.        41,  42,  43,  44,  45,  46,  47,  48,
  257.        49,  50,  51,  52,  53,  54,  55,  56,
  258.        57,  58,  59,  60,  61,  62,  63,  64 }
  259. };
  260. ParamTableMirrored<64> nt1w(nt1b);
  261.  
  262. /** Piece/square table for knights during end game. */
  263. ParamTable<64> nt2b { -200, 200, useUciParam,
  264.     { -87,   7,  11,  -2,  -2,  11,   7, -87,
  265.       -10,   8,  20,  37,  37,  20,   8, -10,
  266.        -6,  20,  36,  41,  41,  36,  20,  -6,
  267.        -1,  29,  46,  47,  47,  46,  29,  -1,
  268.         2,  30,  43,  44,  44,  43,  30,   2,
  269.       -24,   6,  23,  34,  34,  23,   6, -24,
  270.       -35,  -3,   4,   9,   9,   4,  -3, -35,
  271.       -42, -57, -15, -12, -12, -15, -57, -42 },
  272.     {   1,   2,   3,   4,   4,   3,   2,   1,
  273.         5,   6,   7,   8,   8,   7,   6,   5,
  274.         9,  10,  11,  12,  12,  11,  10,   9,
  275.        13,  14,  15,  16,  16,  15,  14,  13,
  276.        17,  18,  19,  20,  20,  19,  18,  17,
  277.        21,  22,  23,  24,  24,  23,  22,  21,
  278.        25,  26,  27,  28,  28,  27,  26,  25,
  279.        29,  30,  31,  32,  32,  31,  30,  29 }
  280. };
  281. ParamTableMirrored<64> nt2w(nt2b);
  282.  
  283. /** Piece/square table for bishops during middle game. */
  284. ParamTable<64> bt1b { -200, 200, useUciParam,
  285.     { -56,  -6,  28, -46,  16, -71,  18, -41,
  286.       -35, -29, -29,  19, -24, -11, -52, -54,
  287.       -19,  11, -10,   2,  41,  56,  42,   3,
  288.       -25, -10,  -5,  30,  -6,   4, -17,  -4,
  289.        -5, -17,  -8,   9,  14, -20, -13,  -1,
  290.       -17,   0,  -2,  -4,  -5,  -5,  -5,   0,
  291.        10,  -5,   5,  -7,  -1,  -5,  11,   9,
  292.       -31,   6, -16, -15, -20, -11, -26, -12 },
  293.     {   1,   2,   3,   4,   5,   6,   7,   8,
  294.         9,  10,  11,  12,  13,  14,  15,  16,
  295.        17,  18,  19,  20,  21,  22,  23,  24,
  296.        25,  26,  27,  28,  29,  30,  31,  32,
  297.        33,  34,  35,  36,  37,  38,  39,  40,
  298.        41,  42,  43,  44,  45,  46,  47,  48,
  299.        49,  50,  51,  52,  53,  54,  55,  56,
  300.        57,  58,  59,  60,  61,  62,  63,  64 }
  301. };
  302. ParamTableMirrored<64> bt1w(bt1b);
  303.  
  304. /** Piece/square table for bishops during end game. */
  305. ParamTable<64> bt2b { -200, 200, useUciParam,
  306.     {  20,  20,  17,  22,  22,  17,  20,  20,
  307.        20,  20,  25,  30,  30,  25,  20,  20,
  308.        17,  25,  36,  38,  38,  36,  25,  17,
  309.        22,  30,  38,  43,  43,  38,  30,  22,
  310.        22,  30,  38,  43,  43,  38,  30,  22,
  311.        17,  25,  36,  38,  38,  36,  25,  17,
  312.        20,  20,  25,  30,  30,  25,  20,  20,
  313.        20,  20,  17,  22,  22,  17,  20,  20 },
  314.     {  10,   1,   2,   3,   3,   2,   1,  10,
  315.         1,   4,   5,   6,   6,   5,   4,   1,
  316.         2,   5,   7,   8,   8,   7,   5,   2,
  317.         3,   6,   8,   9,   9,   8,   6,   3,
  318.         3,   6,   8,   9,   9,   8,   6,   3,
  319.         2,   5,   7,   8,   8,   7,   5,   2,
  320.         1,   4,   5,   6,   6,   5,   4,   1,
  321.        10,   1,   2,   3,   3,   2,   1,  10 }
  322. };
  323. ParamTableMirrored<64> bt2w(bt2b);
  324.  
  325. /** Piece/square table for queens during middle game. */
  326. ParamTable<64> qt1b { -200, 200, useUciParam,
  327.     { -32, -23, -22, -26,  29, -11,  87,  32,
  328.       -66,-100, -54, -79,-113, -32, -66,  49,
  329.       -49, -41, -74, -68, -32, -22, -33, -48,
  330.       -37, -38, -44, -66, -60, -54, -40, -45,
  331.       -27, -32, -19, -38, -30, -32,  -3, -36,
  332.       -27, -17, -14, -21, -11, -14,   3, -20,
  333.       -30, -22, -13,  -4,  -5,   3,  -8, -30,
  334.       -15, -19,  -7,  -8,  -2, -18, -48, -19 },
  335.     {   1,   2,   3,   4,   5,   6,   7,   8,
  336.         9,  10,  11,  12,  13,  14,  15,  16,
  337.        17,  18,  19,  20,  21,  22,  23,  24,
  338.        25,  26,  27,  28,  29,  30,  31,  32,
  339.        33,  34,  35,  36,  37,  38,  39,  40,
  340.        41,  42,  43,  44,  45,  46,  47,  48,
  341.        49,  50,  51,  52,  53,  54,  55,  56,
  342.        57,  58,  59,  60,  61,  62,  63,  64 }
  343. };
  344. ParamTableMirrored<64> qt1w(qt1b);
  345.  
  346. ParamTable<64> qt2b { -200, 200, useUciParam,
  347.     { -17, -20, -19, -16, -16, -19, -20, -17,
  348.       -20, -23, -14,  -8,  -8, -14, -23, -20,
  349.       -19, -14,  -3,  -5,  -5,  -3, -14, -19,
  350.       -16,  -8,  -5,   7,   7,  -5,  -8, -16,
  351.       -16,  -8,  -5,   7,   7,  -5,  -8, -16,
  352.       -19, -14,  -3,  -5,  -5,  -3, -14, -19,
  353.       -20, -23, -14,  -8,  -8, -14, -23, -20,
  354.       -17, -20, -19, -16, -16, -19, -20, -17 },
  355.      { 10,   1,   2,   3,   3,   2,   1,  10,
  356.         1,   4,   5,   6,   6,   5,   4,   1,
  357.         2,   5,   7,   8,   8,   7,   5,   2,
  358.         3,   6,   8,   9,   9,   8,   6,   3,
  359.         3,   6,   8,   9,   9,   8,   6,   3,
  360.         2,   5,   7,   8,   8,   7,   5,   2,
  361.         1,   4,   5,   6,   6,   5,   4,   1,
  362.        10,   1,   2,   3,   3,   2,   1,  10 }
  363. };
  364. ParamTableMirrored<64> qt2w(qt2b);
  365.  
  366. /** Piece/square table for rooks during end game. */
  367. ParamTable<64> rt1b { -200, 200, useUciParam,
  368.     {  39,  45,  36,  36,  39,  58,  54,  63,
  369.        34,  36,  47,  53,  47,  53,  57,  47,
  370.        27,  36,  40,  36,  53,  71,  65,  53,
  371.        15,  18,  24,  27,  26,  33,  38,  19,
  372.        -1,  -1,  12,   6,   9,  12,  21,   3,
  373.       -17, -10,  -4,  -3,   0,   3,  15,  -5,
  374.       -24, -18,  -6,   1,   2,  -3,   1, -35,
  375.        -3,  -1,   6,   9,   9,   9,   3,   4 },
  376.     {   1,   2,   3,   4,   5,   6,   7,   8,
  377.         9,  10,  11,  12,  13,  14,  15,  16,
  378.        17,  18,  19,  20,  21,  22,  23,  24,
  379.        25,  26,  27,  28,  29,  30,  31,  32,
  380.        33,  34,  35,  36,  37,  38,  39,  40,
  381.        41,  42,  43,  44,  45,  46,  47,  48,
  382.        49,  50,  51,  52,  53,  54,  55,  56,
  383.        57,  58,  59,  60,  61,  62,  63,  64 }
  384. };
  385. ParamTableMirrored<64> rt1w(rt1b);
  386.  
  387. ParamTable<64> knightOutpostBonus { 0, 150, useUciParam,
  388.     {   0,   0,   0,   0,   0,   0,   0,   0,
  389.         0,   0,   0,   0,   0,   0,   0,   0,
  390.         0,  29,  49,  46,  46,  49,  29,   0,
  391.         0,  19,  38,  43,  43,  38,  19,   0,
  392.         0,   0,  23,  43,  43,  23,   0,   0,
  393.         0,   0,   0,   0,   0,   0,   0,   0,
  394.         0,   0,   0,   0,   0,   0,   0,   0,
  395.         0,   0,   0,   0,   0,   0,   0,   0 },
  396.     {   0,   0,   0,   0,   0,   0,   0,   0,
  397.         0,   0,   0,   0,   0,   0,   0,   0,
  398.         0,   1,   2,   3,   3,   2,   1,   0,
  399.         0,   4,   5,   6,   6,   5,   4,   0,
  400.         0,   0,   7,   8,   8,   7,   0,   0,
  401.         0,   0,   0,   0,   0,   0,   0,   0,
  402.         0,   0,   0,   0,   0,   0,   0,   0,
  403.         0,   0,   0,   0,   0,   0,   0,   0 }
  404. };
  405.  
  406. ParamTable<64> protectedPawnBonus { -50, 150, useUciParam,
  407.     {   0,   0,   0,   0,   0,   0,   0,   0,
  408.       104, 109,  69, 136, 136,  69, 109, 104,
  409.        28,  53,  51,  63,  63,  51,  53,  28,
  410.         4,  11,  16,  17,  17,  16,  11,   4,
  411.         4,   6,   5,   8,   8,   5,   6,   4,
  412.         8,  11,  17,  11,  11,  17,  11,   8,
  413.         0,   0,   0,   0,   0,   0,   0,   0,
  414.         0,   0,   0,   0,   0,   0,   0,   0 },
  415.     {   0,   0,   0,   0,   0,   0,   0,   0,
  416.         1,   2,   3,   4,   4,   3,   2,   1,
  417.         5,   6,   7,   8,   8,   7,   6,   5,
  418.         9,  10,  11,  12,  12,  11,  10,   9,
  419.        13,  14,  15,  16,  16,  15,  14,  13,
  420.        17,  18,  19,  20,  20,  19,  18,  17,
  421.         0,   0,   0,   0,   0,   0,   0,   0,
  422.         0,   0,   0,   0,   0,   0,   0,   0 }
  423. };
  424.  
  425. ParamTable<64> attackedPawnBonus { -150, 100, useUciParam,
  426.     {   0,   0,   0,   0,   0,   0,   0,   0,
  427.       -35, -55,  17, -16, -16,  17, -55, -35,
  428.        10,   0,  20,  18,  18,  20,   0,  10,
  429.       -10,  -5,  -6,   9,   9,  -6,  -5, -10,
  430.       -35,  11, -12,  13,  13, -12,  11, -35,
  431.      -101, -24, -59, -43, -43, -59, -24,-101,
  432.         0,   0,   0,   0,   0,   0,   0,   0,
  433.         0,   0,   0,   0,   0,   0,   0,   0 },
  434.     {   0,   0,   0,   0,   0,   0,   0,   0,
  435.         1,   2,   3,   4,   4,   3,   2,   1,
  436.         5,   6,   7,   8,   8,   7,   6,   5,
  437.         9,  10,  11,  12,  12,  11,  10,   9,
  438.        13,  14,  15,  16,  16,  15,  14,  13,
  439.        17,  18,  19,  20,  20,  19,  18,  17,
  440.         0,   0,   0,   0,   0,   0,   0,   0,
  441.         0,   0,   0,   0,   0,   0,   0,   0 }
  442. };
  443.  
  444. ParamTable<4> protectBonus { -50, 50, useUciParam,
  445.     {  1, 11,  7,  2 },
  446.     {  1,  2,  3,  4 }
  447. };
  448.  
  449. ParamTable<15> rookMobScore { -50, 50, useUciParam,
  450.     {-17,-11, -6, -2,  0,  5,  9, 12, 17, 20, 22, 26, 28, 25, 30 },
  451.     {   1, 2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 }
  452. };
  453. ParamTable<14> bishMobScore = { -50, 50, useUciParam,
  454.     {-14,-10, -1,  5, 12, 18, 24, 28, 31, 35, 34, 38, 39, 31 },
  455.     {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14 }
  456. };
  457. ParamTable<28> knightMobScore { -200, 200, useUciParam,
  458.     {-96,-25, 16,-36,-12,  4, 10,-49,-18, -3, 11, 15,-20,-20,-12, -7,  1,  6,  8,-22,-22,-19,-10, -3,  2,  7,  9,  6 },
  459.     {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26 }
  460. };
  461. ParamTable<28> queenMobScore { -100, 100, useUciParam,
  462.     {  7, -1, -4, -3, -1,  1,  4,  5,  9, 10, 14, 17, 20, 24, 28, 30, 35, 36, 41, 43, 44, 46, 45, 45, 39, 39, 43, 30 },
  463.     {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28 }
  464. };
  465.  
  466. ParamTable<36> connectedPPBonus { -200, 400, useUciParam,
  467.     {  -4,  -3,   3,  11,   5, -13,
  468.        -3,   1,   0,   7,   6,   8,
  469.         3,   0,  16,  12,  22,  17,
  470.        11,   7,  12,  40,  -2,  38,
  471.         5,   6,  22,  -2, 102, -27,
  472.       -13,   8,  17,  38, -27, 337 },
  473.     {   1,   2,   4,   7,  11,  16,
  474.         2,   3,   5,   8,  12,  17,
  475.         4,   5,   6,   9,  13,  18,
  476.         7,   8,   9,  10,  14,  19,
  477.        11,  12,  13,  14,  15,  20,
  478.        16,  17,  18,  19,  20,  21 }
  479. };
  480.  
  481. ParamTable<8> passedPawnBonusX { -200, 200, useUciParam,
  482.     {  0,  2, -2, -5, -5, -2,  2,  0 },
  483.     {  0,  1,  2,  3,  3,  2,  1,  0 }
  484. };
  485.  
  486. ParamTable<8> passedPawnBonusY { -200, 200, useUciParam,
  487.     {  0,  3,  5, 14, 33, 63,103,  0 },
  488.     {  0,  1,  2,  3,  4,  5,  6,  0 }
  489. };
  490.  
  491. ParamTable<10> ppBlockerBonus { -50, 50, useUciParam,
  492.     { 23, 26, 11,-11, 47, -1,  3,  1, -2,  8 },
  493.     {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10 }
  494. };
  495.  
  496. ParamTable<8> candidatePassedBonus { -200, 200, useUciParam,
  497.     { -1, -1,  5, 14, 36, 15, -1, -1 },
  498.     {  0,  1,  2,  3,  4,  5,  0,  0 }
  499. };
  500.  
  501. ParamTable<16> majorPieceRedundancy { -200, 200, useUciParam,
  502.     {   0, -85,   0,   0,
  503.        85,   0,   0,   0,
  504.         0,   0,   0,  88,
  505.         0,   0, -88,   0 },
  506.     {   0,  -1,   0,   0,
  507.         1,   0,   0,   0,
  508.         0,   0,   0,   2,
  509.         0,   0,  -2,   0 }
  510. };
  511.  
  512. ParamTable<5> QvsRRBonus { -200, 200, useUciParam,
  513.     {-10, 31, 55,113, 68 },
  514.     {  1,  2,  3,  4,  5 }
  515. };
  516.  
  517. ParamTable<7> RvsMBonus { -200, 200, useUciParam,
  518.     { 13, 37, 45, 35, 26, -2,-60 },
  519.     {  1,  2,  3,  4,  5,  6,  7 }
  520. };
  521.  
  522. ParamTable<7> RvsMMBonus { -200, 200, useUciParam,
  523.     {-92,-92,-12,  7, 12, 19, 54 },
  524.     {   1,   1,  2,  3,  4,  5,  6 }
  525. };
  526.  
  527. ParamTable<4> bishopPairValue { 0, 200, useUciParam,
  528.     {100, 79, 63, 57 },
  529.     {  1,  2,  3,  4 }
  530. };
  531.  
  532. ParamTable<7> rookEGDrawFactor { 0, 255, useUciParam,
  533.     { 65, 70,109,137,133,156,156 },
  534.     {  1,  2,  3,  4,  5,  6,  7 }
  535. };
  536.  
  537. ParamTable<7> RvsBPDrawFactor { 0, 255, useUciParam,
  538.     {128, 93,108,123,127,249,162 },
  539.     {  0,  1,  2,  3,  4,  5,  6 }
  540. };
  541. ParamTable<4> castleFactor { 0, 128, useUciParam,
  542.     { 64, 42, 30, 23 },
  543.     {  1,  2,  3,  4 }
  544. };
  545.  
  546. ParamTable<9> pawnShelterTable { -100, 100, useUciParam,
  547.     { 13, 31,-20,  6, 23,-12,  1,  9,  2 },
  548.     {  1,  2,  3,  4,  5,  6,  7,  8,  9 }
  549. };
  550.  
  551. ParamTable<9> pawnStormTable { -400, 100, useUciParam,
  552.     {-166,-93,-273, 37, 32,  4, 14,  4,-12 },
  553.     {  1,   2,   3,  4,  5,  6,  7,  8,  9 }
  554. };
  555.  
  556. ParamTable<14> kingAttackWeight { 0, 400, useUciParam,
  557.     {  0,  3,  0,  6,  7, 14, 29, 57, 64,103,112,152,211,353 },
  558.     {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13 }
  559. };
  560.  
  561. ParamTable<5> kingPPSupportK { 0, 200, useUciParam,
  562.     { 47, 71, 65, 56, 98 },
  563.     {  1,  2,  3,  4,  5 }
  564. };
  565.  
  566. ParamTable<8> kingPPSupportP { 1, 64, useUciParam,
  567.     {  0,  4,  4, 10, 16, 22, 32,  0 },
  568.     {  0,  1,  2,  3,  4,  5,  0,  0 }
  569. };
  570.  
  571. ParamTable<8> pawnDoubledPenalty { 0, 50, useUciParam,
  572.     { 42, 22, 17, 11, 11, 17, 22, 42 },
  573.     {  1,  2,  3,  4,  4,  3,  2,  1 }
  574. };
  575.  
  576. ParamTable<8> pawnIsolatedPenalty { 0, 50, useUciParam,
  577.     {  2, 12, 10, 14, 14, 10, 12,  2 },
  578.     {  1,  2,  3,  4,  4,  3,  2,  1 }
  579. };
  580.  
  581. ParamTable<10> halfMoveFactor { 0, 192, useUciParam,
  582.     {128,128,128,128, 43, 27, 19, 13,  9,  5 },
  583.     {  0,  0,  0,  0,  1,  2,  3,  4,  5,  6 }
  584. };
  585.  
  586. ParamTable<9> stalePawnFactor { 0, 192, useUciParam,
  587.     {119,127,131,133,137,129,104, 65, 28 },
  588.     {  1,  2,  3,  4,  5,  6,  7,  8,  9 }
  589. };
  590.  
  591. Parameters::Parameters() {
  592.     std::string about = ComputerPlayer::engineName +
  593.                         " by Peter Osterlund, see http://web.comhem.se/petero2home/javachess/index.html#texel";
  594.     addPar(std::make_shared<StringParam>("UCI_EngineAbout", about));
  595.  
  596.     addPar(UciParams::hash);
  597.     addPar(UciParams::ownBook);
  598.     addPar(UciParams::ponder);
  599.     addPar(UciParams::analyseMode);
  600.     addPar(UciParams::strength);
  601.     addPar(UciParams::threads);
  602.     addPar(UciParams::multiPV);
  603.  
  604.     addPar(UciParams::gtbPath);
  605.     addPar(UciParams::gtbCache);
  606.     addPar(UciParams::rtbPath);
  607.     addPar(UciParams::minProbeDepth);
  608.     addPar(UciParams::clearHash);
  609.  
  610.     // Evaluation parameters
  611.     REGISTER_PARAM(pV, "PawnValue");
  612.     REGISTER_PARAM(nV, "KnightValue");
  613.     REGISTER_PARAM(bV, "BishopValue");
  614.     REGISTER_PARAM(rV, "RookValue");
  615.     REGISTER_PARAM(qV, "QueenValue");
  616.     REGISTER_PARAM(kV, "KingValue");
  617.  
  618.     REGISTER_PARAM(pawnIslandPenalty, "PawnIslandPenalty");
  619.     REGISTER_PARAM(pawnBackwardPenalty, "PawnBackwardPenalty");
  620.     REGISTER_PARAM(pawnSemiBackwardPenalty1, "PawnSemiBackwardPenalty1");
  621.     REGISTER_PARAM(pawnSemiBackwardPenalty2, "PawnSemiBackwardPenalty2");
  622.     REGISTER_PARAM(pawnRaceBonus, "PawnRaceBonus");
  623.     REGISTER_PARAM(passedPawnEGFactor, "PassedPawnEGFactor");
  624.     REGISTER_PARAM(RBehindPP1, "RookBehindPassedPawn1");
  625.     REGISTER_PARAM(RBehindPP2, "RookBehindPassedPawn2");
  626.  
  627.     REGISTER_PARAM(QvsRMBonus1, "QueenVsRookMinorBonus1");
  628.     REGISTER_PARAM(QvsRMBonus2, "QueenVsRookMinorBonus2");
  629.     REGISTER_PARAM(knightVsQueenBonus1, "KnightVsQueenBonus1");
  630.     REGISTER_PARAM(knightVsQueenBonus2, "KnightVsQueenBonus2");
  631.     REGISTER_PARAM(knightVsQueenBonus3, "KnightVsQueenBonus3");
  632.     REGISTER_PARAM(krkpBonus, "RookVsPawnBonus");
  633.     REGISTER_PARAM(krpkbBonus, "RookPawnVsBishopBonus");
  634.     REGISTER_PARAM(krpkbPenalty, "RookPawnVsBishopPenalty");
  635.     REGISTER_PARAM(krpknBonus, "RookPawnVsKnightBonus");
  636.     REGISTER_PARAM(RvsBPBonus, "RookVsBishopPawnBonus");
  637.  
  638.     REGISTER_PARAM(pawnTradePenalty, "PawnTradePenalty");
  639.     REGISTER_PARAM(pieceTradeBonus, "PieceTradeBonus");
  640.     REGISTER_PARAM(pawnTradeThreshold, "PawnTradeThreshold");
  641.     REGISTER_PARAM(pieceTradeThreshold, "PieceTradeThreshold");
  642.  
  643.     REGISTER_PARAM(threatBonus1, "ThreatBonus1");
  644.     REGISTER_PARAM(threatBonus2, "ThreatBonus2");
  645.  
  646.     REGISTER_PARAM(rookHalfOpenBonus, "RookHalfOpenBonus");
  647.     REGISTER_PARAM(rookOpenBonus, "RookOpenBonus");
  648.     REGISTER_PARAM(rookDouble7thRowBonus, "RookDouble7thRowBonus");
  649.     REGISTER_PARAM(trappedRookPenalty1, "TrappedRookPenalty1");
  650.     REGISTER_PARAM(trappedRookPenalty2, "TrappedRookPenalty2");
  651.  
  652.     REGISTER_PARAM(bishopPairPawnPenalty, "BishopPairPawnPenalty");
  653.     REGISTER_PARAM(trappedBishopPenalty, "TrappedBishopPenalty");
  654.     REGISTER_PARAM(oppoBishopPenalty, "OppositeBishopPenalty");
  655.  
  656.     REGISTER_PARAM(kingSafetyHalfOpenBCDEFG1, "KingSafetyHalfOpenBCDEFG1");
  657.     REGISTER_PARAM(kingSafetyHalfOpenBCDEFG2, "KingSafetyHalfOpenBCDEFG2");
  658.     REGISTER_PARAM(kingSafetyHalfOpenAH1, "KingSafetyHalfOpenAH1");
  659.     REGISTER_PARAM(kingSafetyHalfOpenAH2, "KingSafetyHalfOpenAH2");
  660.     REGISTER_PARAM(kingSafetyWeight1, "KingSafetyWeight1");
  661.     REGISTER_PARAM(kingSafetyWeight2, "KingSafetyWeight2");
  662.     REGISTER_PARAM(kingSafetyWeight3, "KingSafetyWeight3");
  663.     REGISTER_PARAM(kingSafetyWeight4, "KingSafetyWeight4");
  664.     REGISTER_PARAM(kingSafetyThreshold, "KingSafetyThreshold");
  665.     REGISTER_PARAM(knightKingProtectBonus, "KnightKingProtectBonus");
  666.     REGISTER_PARAM(bishopKingProtectBonus, "BishopKingProtectBonus");
  667.     REGISTER_PARAM(pawnStormBonus, "PawnStormBonus");
  668.  
  669.     REGISTER_PARAM(pawnLoMtrl, "PawnLoMtrl");
  670.     REGISTER_PARAM(pawnHiMtrl, "PawnHiMtrl");
  671.     REGISTER_PARAM(minorLoMtrl, "MinorLoMtrl");
  672.     REGISTER_PARAM(minorHiMtrl, "MinorHiMtrl");
  673.     REGISTER_PARAM(castleLoMtrl, "CastleLoMtrl");
  674.     REGISTER_PARAM(castleHiMtrl, "CastleHiMtrl");
  675.     REGISTER_PARAM(queenLoMtrl, "QueenLoMtrl");
  676.     REGISTER_PARAM(queenHiMtrl, "QueenHiMtrl");
  677.     REGISTER_PARAM(passedPawnLoMtrl, "PassedPawnLoMtrl");
  678.     REGISTER_PARAM(passedPawnHiMtrl, "PassedPawnHiMtrl");
  679.     REGISTER_PARAM(kingSafetyLoMtrl, "KingSafetyLoMtrl");
  680.     REGISTER_PARAM(kingSafetyHiMtrl, "KingSafetyHiMtrl");
  681.     REGISTER_PARAM(oppoBishopLoMtrl, "OppositeBishopLoMtrl");
  682.     REGISTER_PARAM(oppoBishopHiMtrl, "OppositeBishopHiMtrl");
  683.     REGISTER_PARAM(knightOutpostLoMtrl, "KnightOutpostLoMtrl");
  684.     REGISTER_PARAM(knightOutpostHiMtrl, "KnightOutpostHiMtrl");
  685.  
  686.     // Evaluation tables
  687.     kt1b.registerParams("KingTableMG", *this);
  688.     kt2b.registerParams("KingTableEG", *this);
  689.     pt1b.registerParams("PawnTableMG", *this);
  690.     pt2b.registerParams("PawnTableEG", *this);
  691.     nt1b.registerParams("KnightTableMG", *this);
  692.     nt2b.registerParams("KnightTableEG", *this);
  693.     bt1b.registerParams("BishopTableMG", *this);
  694.     bt2b.registerParams("BishopTableEG", *this);
  695.     qt1b.registerParams("QueenTableMG", *this);
  696.     qt2b.registerParams("QueenTableEG", *this);
  697.     rt1b.registerParams("RookTable", *this);
  698.  
  699.     knightOutpostBonus.registerParams("KnightOutpostBonus", *this);
  700.     protectedPawnBonus.registerParams("ProtectedPawnBonus", *this);
  701.     attackedPawnBonus.registerParams("AttackedPawnBonus", *this);
  702.     protectBonus.registerParams("ProtectBonus", *this);
  703.     rookMobScore.registerParams("RookMobility", *this);
  704.     bishMobScore.registerParams("BishopMobility", *this);
  705.     knightMobScore.registerParams("KnightMobility", *this);
  706.     queenMobScore.registerParams("QueenMobility", *this);
  707.     majorPieceRedundancy.registerParams("MajorPieceRedundancy", *this);
  708.     connectedPPBonus.registerParams("ConnectedPPBonus", *this);
  709.     passedPawnBonusX.registerParams("PassedPawnBonusX", *this);
  710.     passedPawnBonusY.registerParams("PassedPawnBonusY", *this);
  711.     ppBlockerBonus.registerParams("PassedPawnBlockerBonus", *this);
  712.     candidatePassedBonus.registerParams("CandidatePassedPawnBonus", *this);
  713.     QvsRRBonus.registerParams("QueenVs2RookBonus", *this);
  714.     RvsMBonus.registerParams("RookVsMinorBonus", *this);
  715.     RvsMMBonus.registerParams("RookVs2MinorBonus", *this);
  716.     bishopPairValue.registerParams("BishopPairValue", *this);
  717.     rookEGDrawFactor.registerParams("RookEndGameDrawFactor", *this);
  718.     RvsBPDrawFactor.registerParams("RookVsBishopPawnDrawFactor", *this);
  719.     castleFactor.registerParams("CastleFactor", *this);
  720.     pawnShelterTable.registerParams("PawnShelterTable", *this);
  721.     pawnStormTable.registerParams("PawnStormTable", *this);
  722.     kingAttackWeight.registerParams("KingAttackWeight", *this);
  723.     kingPPSupportK.registerParams("KingPassedPawnSupportK", *this);
  724.     kingPPSupportP.registerParams("KingPassedPawnSupportP", *this);
  725.     pawnDoubledPenalty.registerParams("PawnDoubledPenalty", *this);
  726.     pawnIsolatedPenalty.registerParams("PawnIsolatedPenalty", *this);
  727.     halfMoveFactor.registerParams("HalfMoveFactor", *this);
  728.     stalePawnFactor.registerParams("StalePawnFactor", *this);
  729.  
  730.     // Search parameters
  731.     REGISTER_PARAM(aspirationWindow, "AspirationWindow");
  732.     REGISTER_PARAM(rootLMRMoveCount, "RootLMRMoveCount");
  733.  
  734.     REGISTER_PARAM(razorMargin1, "RazorMargin1");
  735.     REGISTER_PARAM(razorMargin2, "RazorMargin2");
  736.  
  737.     REGISTER_PARAM(reverseFutilityMargin1, "ReverseFutilityMargin1");
  738.     REGISTER_PARAM(reverseFutilityMargin2, "ReverseFutilityMargin2");
  739.     REGISTER_PARAM(reverseFutilityMargin3, "ReverseFutilityMargin3");
  740.     REGISTER_PARAM(reverseFutilityMargin4, "ReverseFutilityMargin4");
  741.  
  742.     REGISTER_PARAM(futilityMargin1, "FutilityMargin1");
  743.     REGISTER_PARAM(futilityMargin2, "FutilityMargin2");
  744.     REGISTER_PARAM(futilityMargin3, "FutilityMargin3");
  745.     REGISTER_PARAM(futilityMargin4, "FutilityMargin4");
  746.  
  747.     REGISTER_PARAM(lmpMoveCountLimit1, "LMPMoveCountLimit1");
  748.     REGISTER_PARAM(lmpMoveCountLimit2, "LMPMoveCountLimit2");
  749.     REGISTER_PARAM(lmpMoveCountLimit3, "LMPMoveCountLimit3");
  750.     REGISTER_PARAM(lmpMoveCountLimit4, "LMPMoveCountLimit4");
  751.  
  752.     REGISTER_PARAM(lmrMoveCountLimit1, "LMRMoveCountLimit1");
  753.     REGISTER_PARAM(lmrMoveCountLimit2, "LMRMoveCountLimit2");
  754.  
  755.     REGISTER_PARAM(quiesceMaxSortMoves, "QuiesceMaxSortMoves");
  756.     REGISTER_PARAM(deltaPruningMargin, "DeltaPruningMargin");
  757.  
  758.     // Time management parameters
  759.     REGISTER_PARAM(timeMaxRemainingMoves, "TimeMaxRemainingMoves");
  760.     REGISTER_PARAM(bufferTime, "BufferTime");
  761.     REGISTER_PARAM(minTimeUsage, "MinTimeUsage");
  762.     REGISTER_PARAM(maxTimeUsage, "MaxTimeUsage");
  763.     REGISTER_PARAM(timePonderHitRate, "TimePonderHitRate");
  764. }
  765.  
  766. Parameters&
  767. Parameters::instance() {
  768.     static Parameters inst;
  769.     return inst;
  770. }
  771.  
  772. void
  773. Parameters::getParamNames(std::vector<std::string>& parNames) {
  774.     parNames = paramNames;
  775. }
  776.  
  777. std::shared_ptr<Parameters::ParamBase>
  778. Parameters::getParam(const std::string& name) const {
  779.     auto it = params.find(toLowerCase(name));
  780.     if (it == params.end())
  781.         return nullptr;
  782.     return it->second;
  783. }
  784.  
  785. void
  786. Parameters::addPar(const std::shared_ptr<ParamBase>& p) {
  787.     std::string name = toLowerCase(p->name);
  788.     assert(params.find(name) == params.end());
  789.     params[name] = p;
  790.     paramNames.push_back(name);
  791. }
  792.  
  793. int
  794. Parameters::Listener::addListener(Func f, bool callNow) {
  795.     int id = ++nextId;
  796.     listeners[id] = f;
  797.     if (callNow)
  798.         f();
  799.     return id;
  800. }
  801.  
  802. void
  803. Parameters::Listener::removeListener(int id) {
  804.     listeners.erase(id);
  805. }
  806.  
  807. void
  808. Parameters::Listener::notify() {
  809.     for (auto& e : listeners)
  810.         (e.second)();
  811. }
  812.  
  813. void
  814. ParamTableBase::registerParamsN(const std::string& name, Parameters& pars,
  815.                                 int* table, int* parNo, int N) {
  816.     // Check that each parameter has a single value
  817.     std::map<int,int> parNoToVal;
  818.     int maxParIdx = -1;
  819.     for (int i = 0; i < N; i++) {
  820.         if (parNo[i] == 0)
  821.             continue;
  822.         const int pn = std::abs(parNo[i]);
  823.         const int sign = parNo[i] > 0 ? 1 : -1;
  824.         maxParIdx = std::max(maxParIdx, pn);
  825.         auto it = parNoToVal.find(pn);
  826.         if (it == parNoToVal.end())
  827.             parNoToVal.insert(std::make_pair(pn, sign*table[i]));
  828.         else
  829.             assert(it->second == sign*table[i]);
  830.     }
  831.     if (!uci)
  832.         return;
  833.     params.resize(maxParIdx+1);
  834.     for (const auto& p : parNoToVal) {
  835.         std::string pName = name + num2Str(p.first);
  836.         params[p.first] = std::make_shared<Parameters::SpinParam>(pName, minValue, maxValue, p.second);
  837.         pars.addPar(params[p.first]);
  838.         params[p.first]->addListener([=]() { modifiedN(table, parNo, N); }, false);
  839.     }
  840.     modifiedN(table, parNo, N);
  841. }
  842.  
  843. void
  844. ParamTableBase::modifiedN(int* table, int* parNo, int N) {
  845.     for (int i = 0; i < N; i++)
  846.         if (parNo[i] > 0)
  847.             table[i] = params[parNo[i]]->getIntPar();
  848.         else if (parNo[i] < 0)
  849.             table[i] = -params[-parNo[i]]->getIntPar();
  850.     notify();
  851. }
  852.