Subversion Repositories Kolibri OS

Rev

Rev 1805 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef _HEADER_PLAYER_H
  2. #define _HEADER_PLAYER_H
  3.  
  4. #include "position.h"
  5. #include "sysproc.h"
  6. #ifndef __MENUET__
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <assert.h>
  10. #endif
  11.  
  12. template <class tvalue>
  13. class TBaseCompPlayer : public TChPlayer
  14. {
  15. public:
  16.   static const int PKind;
  17.   static const tvalue win_val;
  18. public:
  19.   TBaseCompPlayer() : draw(0), data(0) {}
  20.  
  21.   virtual int PlayerID() {return PKind;}
  22.   virtual int Move(PMv &pmv);
  23.  
  24.   struct PMvv : public PMv
  25.   {
  26.     tvalue val;
  27.   };
  28.  
  29.   struct Z
  30.   {
  31.     Z(int marr = 400) : narr(0), marr(marr) {array = new PMvv[marr];}
  32.     ~Z() {Clear();}
  33.  
  34.     void Clear() {if (array) {delete[] array; array = 0;} marr = 0; narr = 0;}
  35.     void AddPos(int n);
  36.     void AddPos() {AddPos(narr + 1);}
  37.     int FindAllMoves(PMv pmv, int onlyeat = 0);
  38.     void FindSideEats(PMv &pmv, int k, int sx, int sy);
  39.  
  40.     static int ComparePMv(const void *v1, const void *v2);
  41.     void Sort(int n0, int n1);
  42.  
  43.     int marr, narr;
  44.     PMvv *array;
  45.   };
  46.  
  47.   static tvalue GetLossValue(const Position &pos);
  48.   virtual tvalue GetValue(const Position &pos, int num = 0);
  49.   tvalue GetFullValue(const Position &pos, int num = 0);
  50.   tvalue FindBMove(Z &z, int num, PMvv *pmv, int zn = -1,
  51.                 tvalue a = -2 * win_val, tvalue b = 2 * win_val);
  52. public:
  53.   void (*draw)(void*, int ); //draw() wants int = 0 as a default argument
  54.   void *data;
  55. };
  56.  
  57. template <class tvalue>
  58. const int TBaseCompPlayer<tvalue>::PKind = 0x2000;
  59.  
  60. template <class tvalue>
  61. const tvalue TBaseCompPlayer<tvalue>::win_val = (tvalue)10000000L;
  62.  
  63. template <class tvalue>
  64. void TBaseCompPlayer<tvalue>::Z::AddPos(int n)
  65. {
  66.   if (marr < n)
  67.   {
  68.      int m0 = marr;
  69.      PMvv *arr0 = array;
  70.      marr = 2*n + 10;
  71.      array = new PMvv[marr];
  72.      if (arr0)
  73.      {
  74.        int i;
  75.        for (i = 0; i < m0; i++) array[i] = arr0[i];
  76.        delete[] arr0;
  77.      }
  78.   }
  79. }
  80.  
  81. template <class tvalue>
  82. void TBaseCompPlayer<tvalue>::Z::FindSideEats(PMv &pmv, int k, int sx, int sy)
  83. {
  84.   int x, y;
  85.   NumToPole(k, x, y);
  86.   if (pmv.pos.SH[k] == pmv.pos.wmove + 1)
  87.   {
  88.     int xx = x + 2*sx, yy = y + 2*sy;
  89.     if (xx >= 0 && xx < NW_CELL && yy >= 0 && yy < NW_CELL)
  90.     {
  91.       int kk = PoleToNum(xx, yy);
  92.       if (pmv.pos.SH[kk] == 0)
  93.       {
  94.         int k1 = PoleToNum(x + sx, y + sy);
  95.         char nk1 = pmv.pos.SH[k1];
  96.         if (nk1 == 2 - pmv.pos.wmove || nk1 == 4 - pmv.pos.wmove)
  97.         {
  98.           char SH_k1 = pmv.pos.SH[k1];
  99.           pmv.pos.Del(k1); pmv.pos.Move(k, kk);
  100.           if (pmv.pos.wmove == 0 && yy == NW_CELL - 1 ||
  101.               pmv.pos.wmove == 1 && yy == 0) pmv.pos.SH[kk] += (char)2;
  102.           pmv.mv[++pmv.mv[0]] = (char)kk;
  103.           int nold = narr;
  104.           FindSideEats(pmv, kk, sx, sy);
  105.           FindSideEats(pmv, kk, sy, -sx);
  106.           FindSideEats(pmv, kk, -sy, sx);
  107.           if (narr == nold)
  108.           {
  109.             AddPos();
  110.             (PMv&)array[narr] = pmv;
  111.             array[narr].pos.wmove = !pmv.pos.wmove;
  112.             narr++;
  113.           }
  114.           pmv.mv[0]--;
  115.           pmv.pos.SH[k1] = SH_k1; pmv.pos.Del(kk);
  116.           pmv.pos.SH[k] = char(pmv.pos.wmove + 1);
  117.         }
  118.       }
  119.     }
  120.   }
  121.   else if (pmv.pos.SH[k] == pmv.pos.wmove + 3)
  122.   {
  123.     int i, i0, i1;
  124.     if (sx < 0) i0 = x;
  125.     else i0 = NW_CELL - x - 1;
  126.     if (sy < 0) i1 = y;
  127.     else i1 = NW_CELL - y - 1;
  128.     if (i0 > i1) i0 = i1;
  129.     if (i0 >= 2)
  130.     {
  131.       pmv.pos.Del(k);
  132.       pmv.mv[0]++;
  133.       i1 = -1;
  134.       int kk, kk1;
  135.       char SH_kk1;
  136.       int nold = narr;
  137.       for (i = 1; i <= i0; i++)
  138.       {
  139.         kk = PoleToNum(x + i*sx, y + i*sy);
  140.         char chh = pmv.pos.SH[kk];
  141.         if (chh)
  142.         {
  143.           if (i1 >= 0 || (chh != 2 - pmv.pos.wmove && chh != 4 - pmv.pos.wmove)) break;
  144.           else
  145.           {
  146.             i1 = i; kk1 = kk;
  147.             SH_kk1 = chh;
  148.             pmv.pos.Del(kk1);
  149.           }
  150.         }
  151.         else if (i1 >= 0)
  152.         {
  153.           pmv.pos.SH[kk] = char(pmv.pos.wmove + 3);
  154.           pmv.mv[pmv.mv[0]] = (char)kk;
  155.           if (i == i1+1) FindSideEats(pmv, kk, sx, sy);
  156.           FindSideEats(pmv, kk, sy, -sx);
  157.           FindSideEats(pmv, kk, -sy, sx);
  158.           pmv.pos.Del(kk);
  159.         }
  160.       }
  161.       if (narr == nold && i1 >= 0)
  162.       {
  163.         while (--i > i1)
  164.         {
  165.           kk = PoleToNum(x + i*sx, y + i*sy);
  166.           AddPos();
  167.           (PMv&)array[narr] = pmv;
  168.           array[narr].pos.SH[kk] = char(pmv.pos.wmove + 3);
  169.           array[narr].mv[pmv.mv[0]] = (char)kk;
  170.           array[narr].pos.wmove = !pmv.pos.wmove;
  171.           narr++;
  172.         }
  173.       }
  174.       pmv.mv[0]--;
  175.       pmv.pos.SH[k] = char(pmv.pos.wmove + 3);
  176.       if (i1 >= 0) pmv.pos.SH[kk1] = SH_kk1;
  177.     }
  178.   }
  179. }
  180.  
  181. template <class tvalue>
  182. int TBaseCompPlayer<tvalue>::Z::FindAllMoves(PMv pmv, int onlyeat)
  183. {
  184.   int k, nold = narr, was_eat = 1;
  185.   pmv.mv[0] = 1;
  186.   for (k = 0; k < NUM_CELL; k++)
  187.   {
  188.     if (pmv.pos.SH[k] == pmv.pos.wmove + 1 || pmv.pos.SH[k] == pmv.pos.wmove + 3)
  189.     {
  190.       pmv.mv[1] = (char)k;
  191.       FindSideEats(pmv, k, 1, 1);
  192.       FindSideEats(pmv, k, 1, -1);
  193.       FindSideEats(pmv, k, -1, 1);
  194.       FindSideEats(pmv, k, -1, -1);
  195.     }
  196.   }
  197.   if (narr == nold)
  198.   {
  199.     was_eat = 0;
  200.     if (!onlyeat)
  201.     {
  202.       pmv.mv[0] = 2;
  203.       for (k = 0; k < NUM_CELL; k++)
  204.       {
  205.         if (pmv.pos.SH[k] == pmv.pos.wmove + 1)
  206.         {
  207.           pmv.mv[1] = (char)k;
  208.           int x, x0, x1, y;
  209.           NumToPole(k, x0, y);
  210.           if (pmv.pos.wmove == 1) y--; else y++;
  211.           if (y >= 0 && y < NW_CELL)
  212.           {
  213.             int kk;
  214.             x1 = (x0--) + 1;
  215.             for (x = x0; x <= x1; x += 2) if (x >= 0 && x < NW_CELL)
  216.             {
  217.               kk = PoleToNum(x, y);
  218.               if (pmv.pos.SH[kk] == 0)
  219.               {
  220.                 AddPos();
  221.                 (PMv&)array[narr] = pmv;
  222.                 array[narr].pos.Del(k);
  223.                 if (pmv.pos.wmove == 0 && y == NW_CELL - 1 ||
  224.                     pmv.pos.wmove == 1 && y == 0)
  225.                 {
  226.                   array[narr].pos.Add(kk, char(pmv.pos.wmove + 3));
  227.                 }
  228.                 else array[narr].pos.Add(kk, char(pmv.pos.wmove + 1));
  229.                 array[narr].mv[2] = (char)kk;
  230.                 array[narr].pos.wmove = !pmv.pos.wmove;
  231.                 narr++;
  232.               }
  233.             }
  234.           }
  235.         }
  236.         else if (pmv.pos.SH[k] == pmv.pos.wmove + 3)
  237.         {
  238.           pmv.mv[1] = (char)k;
  239.           int x, y, sx, sy;
  240.           NumToPole(k, x, y);
  241.           for (sx = -1; sx <= 1; sx += 2) if (x + sx >= 0 && x + sx < NW_CELL)
  242.           {
  243.             for (sy = -1; sy <= 1; sy += 2) if (y + sy >= 0 && y + sy < NW_CELL)
  244.             {
  245.               int i, i0, i1;
  246.               if (sx < 0) i0 = x;
  247.               else i0 = NW_CELL - x - 1;
  248.               if (sy < 0) i1 = y;
  249.               else i1 = NW_CELL - y - 1;
  250.               if (i0 > i1) i0 = i1;
  251.               for (i = 1; i <= i0; i++)
  252.               {
  253.                 int kk = PoleToNum(x + i*sx, y + i*sy);
  254.                 if (pmv.pos.SH[kk]) break;
  255.                 AddPos();
  256.                 (PMv&)array[narr] = pmv;
  257.                 array[narr].pos.Move(k, kk);
  258.                 array[narr].mv[2] = (char)kk;
  259.                 array[narr].pos.wmove = !pmv.pos.wmove;
  260.                 narr++;
  261.               }
  262.             }
  263.           }
  264.         }
  265.       }
  266.     }
  267.   }
  268.   pmv.mv[0] = 0;
  269.   return was_eat;
  270. }
  271.  
  272. template <class tvalue>
  273. int TBaseCompPlayer<tvalue>::Z::ComparePMv(const void *v1, const void *v2)
  274. {
  275.   PMvv *pmv1 = (PMvv*)v1, *pmv2 = (PMvv*)v2;
  276.   if (pmv1->val < pmv2->val) return -1;
  277.   else if (pmv1->val > pmv2->val) return 1;
  278.   else return 0;
  279. }
  280.  
  281. template <class tvalue>
  282. void TBaseCompPlayer<tvalue>::Z::Sort(int n0, int n1)
  283. {
  284.   qsort(array + n0, n1 - n0, sizeof(PMvv), ComparePMv);
  285. }
  286.  
  287.  
  288. template <class tvalue>
  289. tvalue TBaseCompPlayer<tvalue>::GetLossValue(const Position &pos)
  290. {
  291.   tvalue val = -win_val - 1000021L;
  292.   for (int i = 0; i < NUM_CELL; i++)
  293.   {
  294.     if (pos.SH[i] == 1 + pos.wmove) val -= 10000L;
  295.     else if (pos.SH[i] == 2 - pos.wmove) val -= 100L;
  296.     else if (pos.SH[i] == 3 + pos.wmove) val -= 80000L;
  297.     else if (pos.SH[i] == 4 - pos.wmove) val -= 100L;
  298.   }
  299.   return val;
  300. }
  301.  
  302. template <class tvalue>
  303. tvalue TBaseCompPlayer<tvalue>::GetValue(const Position &pos, int num)
  304. {
  305.   tvalue val = 0;
  306.   if (num == 0)
  307.   {
  308.     int NumDM0 = 0, NumDM1 = 0;
  309.     for (int i = 0; i < NUM_CELL; i++)
  310.     {
  311.       short PreimSHPos[32] = {243, 243, 243, 245,
  312.                               240, 240, 240, 240,
  313.                               244, 244, 244, 244,
  314.                               245, 248, 248, 245,
  315.                               249, 250, 250, 248,
  316.                               256, 260, 260, 256,
  317.                               280, 280, 280, 260,
  318.                               280, 280, 280, 280};
  319.       if (pos.SH[i] == 1 + pos.wmove)
  320.       {
  321.         val += PreimSHPos[pos.wmove ? (NUM_CELL - 1 - i) : i];
  322.       }
  323.       else if (pos.SH[i] == 2 - pos.wmove)
  324.       {
  325.         val -= PreimSHPos[pos.wmove ? i : (NUM_CELL - 1 - i)];
  326.       }
  327.       else if (pos.SH[i] == 3 + pos.wmove) NumDM1++;
  328.       else if (pos.SH[i] == 4 - pos.wmove) NumDM0++;
  329.     }
  330.     if (NumDM1 > 0)
  331.     {
  332.       val += 560; NumDM1--;
  333.       if (NumDM1 > 0)
  334.       {
  335.         val += 432; NumDM1--;
  336.         val += NumDM1 * 384;
  337.       }
  338.     }
  339.     if (NumDM0 > 0)
  340.     {
  341.       val -= 560; NumDM0--;
  342.       if (NumDM0 > 0)
  343.       {
  344.         val -= 432; NumDM0--;
  345.         val -= NumDM0 * 384;
  346.       }
  347.     }
  348.   }
  349.   if (num == 1)
  350.   {
  351.     char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0;
  352.     int i;
  353.     for (i = 0; i < 32; i++)
  354.     {
  355.       if (pos.SH[i] == 1 + pos.wmove) NSH1++;
  356.       else if (pos.SH[i] == 2 - pos.wmove) NSH0++;
  357.       else if (pos.SH[i] == 3 + pos.wmove) NDM1++;
  358.       else if (pos.SH[i] == 4 - pos.wmove) NDM0++;
  359.     }
  360.     if (NDM1 > 0 && NDM0 > 0 && NSH1 + NSH0 < 3)
  361.     {
  362.       unsigned char HwoBD = 0;
  363.       char Sh0BD = 1, Sh1BD = 1;
  364.       for (i = 0; i < 8; i++)
  365.       {
  366.         char ShBD = pos.SH[PoleToNum(i, 7 - i)];
  367.         if (ShBD == 1 + pos.wmove) Sh1BD++;
  368.         else if (ShBD == 2 - pos.wmove) Sh0BD++;
  369.         else if (ShBD == 3 + pos.wmove) HwoBD |= 2;
  370.         else if (ShBD == 4 - pos.wmove) HwoBD |= 1;
  371.       }
  372.       if (HwoBD == 2) val += 128 / Sh0BD;
  373.       if (HwoBD == 1) val -= 128 / Sh1BD;
  374.       if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1)
  375.       {
  376.         char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
  377.         char Add = 0;
  378.         for (i = 0; i < 4; i++)
  379.         {
  380.           Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 +
  381.                       (pos.SH[Best4P[i][1]] == 3 + pos.wmove));
  382.         }
  383.         if (Add >= 4) val += 32;
  384.         else if (Add == 3) val += 24;
  385.         else if (Add >= 1) val += 16;
  386.       }
  387.       else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2)
  388.       {
  389.         char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
  390.         char Add = 0;
  391.         for (i = 0; i < 4; i++)
  392.         {
  393.           Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 +
  394.                       (pos.SH[Best4P[i][1]] == 4 - pos.wmove));
  395.         }
  396.         if (Add >= 4) val -= 32;
  397.         else if (Add == 3) val -= 24;
  398.         else if (Add >= 1) val -= 16;
  399.       }
  400.     }
  401.     else
  402.     {
  403.       for (i = 0; i < NUM_CELL; i++)
  404.       {
  405.         char Color = char(pos.SH[i] - 1);
  406.         if (Color == 0 || Color == 1)
  407.         {
  408.           char qi = Color ? char(NUM_CELL - 1 - i) : char(i);
  409.           char Zn = Color ? char(-1) : char(1);
  410.           char PreZ = (Color == pos.wmove) ? char(1) : char(-1);
  411.           if (pos.SH[i + Zn * 8] != 2 - Color)
  412.           {
  413.             if (qi / 4 == 2)
  414.             {
  415.               char IsFree = 0;
  416.               if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)2;
  417.               else if (qi != 8)
  418.               {
  419.                 if (pos.SH[i - Zn    ] == 2 - Color ||
  420.                     pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)2;
  421.                 else if (Color != pos.wmove)
  422.                       if (pos.SH[i - Zn * 5] == 2 - Color) IsFree++;
  423.               }
  424.               if (qi == 11) IsFree += (char)2;
  425.               else if (pos.SH[i + Zn    ] == 2 - Color ||
  426.                         pos.SH[i - Zn * 3] == 2 - Color ||
  427.                         pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)2;
  428.               else if (Color != pos.wmove && qi != 10)
  429.               {
  430.                 if (pos.SH[i - Zn * 2] == 2 - Color) IsFree++;
  431.               }
  432.               if (IsFree < 3) val += PreZ * 176 / (1 + NDM0 + NDM1);
  433.               else if (qi == 9 || qi == 10)
  434.               {
  435.                 val += PreZ * 128 / (1 + NDM0 + NDM1);
  436.               }
  437.             }
  438.             else if (qi / 4 == 3)
  439.             {
  440.               char IsFree = 0;
  441.               if (pos.SH[i - Zn * 12] == 2 - Color)
  442.               {
  443.                 if (Color == pos.wmove) IsFree += (char)11;
  444.                 else IsFree += (char)12;
  445.               }
  446.               else if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)11;
  447.               else if (qi == 15) IsFree += (char)5;
  448.               else if (pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)9;
  449.               else if (pos.SH[i + Zn] == 2 - Color) IsFree += (char)8;
  450.               else if (pos.SH[i - Zn * 11] == 2 - Color)
  451.               {
  452.                 if (Color == pos.wmove) IsFree += (char)5;
  453.                 else IsFree += (char)7;
  454.               }
  455.               else if (pos.SH[i - Zn * 3] == 2 - Color) IsFree += (char)5;
  456.               else if (qi != 14)
  457.               {
  458.                 if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)3;
  459.                 else if (Color != pos.wmove)
  460.                 {
  461.                   if (pos.SH[i - Zn * 10] == 2 - Color) IsFree++;
  462.                 }
  463.               }
  464.               if (qi == 12) IsFree += (char)7;
  465.               else if (pos.SH[i - Zn * 13] == 2 - Color)
  466.               {
  467.                 if (Color == pos.wmove) IsFree += (char)11;
  468.                 else IsFree += (char)12;
  469.               }
  470.               else if (pos.SH[i - Zn * 5] == 2 - Color) IsFree += (char)11;
  471.               else if (pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)9;
  472.               else if (pos.SH[i - Zn] == 2 - Color) IsFree += (char)8;
  473.               else if (qi != 13)
  474.               {
  475.                 if (pos.SH[i - Zn * 14] == 2 - Color)
  476.                 {
  477.                   if (Color == pos.wmove) IsFree += (char)5;
  478.                   else IsFree += (char)7;
  479.                 }
  480.                 else if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)5;
  481.                 else if (pos.SH[i - Zn * 10] == 2 - Color) IsFree += (char)3;
  482.                 else if (Color != pos.wmove && qi != 14)
  483.                 {
  484.                   if (pos.SH[i - Zn * 15] == 2 - Color) IsFree++;
  485.                 }
  486.               }
  487.               if (IsFree < ((Color == pos.wmove) ? 14 : 12))
  488.               {
  489.                 val += PreZ * 160 / (1 + NDM0 + NDM1);
  490.               }
  491.             }
  492.           }
  493.         }
  494.       }
  495.     }
  496.   }
  497.   if (num == 2)
  498.   {
  499.     char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0;
  500.     for (int i = 0; i < NUM_CELL; i++)
  501.     {
  502.       if (pos.SH[i] == 1 + pos.wmove) NSH1++;
  503.       else if (pos.SH[i] == 2 - pos.wmove) NSH0++;
  504.       else if (pos.SH[i] == 3 + pos.wmove) NDM1++;
  505.       else if (pos.SH[i] == 4 - pos.wmove) NDM0++;
  506.     }
  507.     if (NDM1 > 0 && NDM0 > 0 && NSH1 == 0 && NSH0 == 0)
  508.     {
  509.       short PrP = 0;
  510.       char Cpos3 = -1;
  511.       if (NDM1 == 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0) Cpos3 = 1;
  512.       else if (NDM1 == 1 && NDM0 == 3 && NSH1 == 0 && NSH0 == 0) Cpos3 = 0;
  513.       if (Cpos3 >= 0)
  514.       {
  515.         for (int Osm = 0; Osm <= 1; Osm++) for (int Csm = 0; Csm <= 1; Csm++)
  516.         {
  517.           char PosSH[7][3] = {{13, 17, 18}, {6, 17, 18}, {9, 21, 22},
  518.                               {17, 18, 19}, {9, 10, 15}, {11, 14, 18}, {2, 14, 18}};
  519.           for (char PosNi = 0; PosNi < 7; PosNi++)
  520.           {
  521.             bool IsPosR = 1;
  522.             for (char ShNi = 0; ShNi < 3; ShNi++)
  523.             {
  524.               char DNomSh = (Csm == 1) ? char(31 - PosSH[PosNi][ShNi])
  525.                                        : char(PosSH[PosNi][ShNi]);
  526.               if (Osm == 1)
  527.               {
  528.                 int x, y;
  529.                 NumToPole(DNomSh, x, y);
  530.                 DNomSh = (char)PoleToNum(y, x);
  531.               }
  532.               if (pos.SH[DNomSh] != 3 + (Cpos3 == pos.wmove)) IsPosR = 0;
  533.             }
  534.             if (IsPosR)
  535.             {
  536.               if (PosNi == 3)
  537.               {
  538.                 if (Cpos3 == 1)
  539.                 {
  540.                   if (pos.SH[(Csm == 1) ? 29 : 2] !=
  541.                       4 - (Cpos3 == pos.wmove) && pos.SH[(Csm == 1) ? 11 : 20] !=
  542.                       4 - (Cpos3 == pos.wmove)) PrP = 216;
  543.                 }
  544.                 else
  545.                 {
  546.                   bool PrPZ = 1;
  547.                   for (int i = 0; i < 6; i++)
  548.                       if (pos.SH[PoleToNum((Csm == 1) ? (i + 2) : i,
  549.                         (Csm == 1) ? (7 - i) : (5 - i))] ==
  550.                           4 - (Cpos3 == pos.wmove)) PrPZ = 0;
  551.                   if (PrPZ) PrP = -216;
  552.                 }
  553.               }
  554.               else if (PosNi == 4)
  555.               {
  556.                 if (Cpos3 == 1)
  557.                 {
  558.                   if (pos.SH[ 0] != 4 - (Cpos3 == pos.wmove) &&
  559.                       pos.SH[ 4] != 4 - (Cpos3 == pos.wmove) &&
  560.                       pos.SH[27] != 4 - (Cpos3 == pos.wmove) &&
  561.                       pos.SH[31] != 4 - (Cpos3 == pos.wmove))
  562.                   {
  563.                     PrP = 216;
  564.                   }
  565.                 }
  566.                 else
  567.                 {
  568.                   if (pos.SH[(Csm == Osm) ?  4 :  0] != 4 - (Cpos3 == pos.wmove) &&
  569.                       pos.SH[(Csm == Osm) ?  8 :  5] != 4 - (Cpos3 == pos.wmove) &&
  570.                       pos.SH[(Csm == Osm) ? 26 : 23] != 4 - (Cpos3 == pos.wmove) &&
  571.                       pos.SH[(Csm == Osm) ? 31 : 27] != 4 - (Cpos3 == pos.wmove))
  572.                   {
  573.                     PrP = -216;
  574.                   }
  575.                 }
  576.               }
  577.               else if (PosNi == 5)
  578.               {
  579.                 char DNomSh = (Cpos3 == 1) ? ((Osm == 1) ? (char)16 : (char)6)
  580.                                            : ((Osm == 1) ? (char)20 : (char)2);
  581.                 if (Csm == 1) DNomSh = char(31 - DNomSh);
  582.                 if (pos.SH[DNomSh] == 4 - (Cpos3 == pos.wmove))
  583.                 {
  584.                   PrP = (Cpos3 == 1) ? short(160) : short(-160);
  585.                 }
  586.               }
  587.               else if (PosNi == 6)
  588.               {
  589.                 if (Cpos3 == 1)
  590.                 {
  591.                   if (pos.SH[ 1] == 4 - (Cpos3 == pos.wmove) ||
  592.                       pos.SH[12] == 4 - (Cpos3 == pos.wmove) ||
  593.                       pos.SH[19] == 4 - (Cpos3 == pos.wmove) ||
  594.                       pos.SH[30] == 4 - (Cpos3 == pos.wmove))
  595.                   {
  596.                     PrP = 168;
  597.                   }
  598.                 }
  599.                 else
  600.                 {
  601.                   if (pos.SH[(Csm == 1) ? 15 :  6] == 4 - (Cpos3 == pos.wmove) ||
  602.                       pos.SH[(Csm == 1) ? 25 : 16] == 4 - (Cpos3 == pos.wmove))
  603.                   {
  604.                     PrP = -168;
  605.                   }
  606.                 }
  607.               }
  608.               else PrP = short(((Cpos3 == 1) ? 1 : -1) * ((PosNi == 0) ? 200 : 208));
  609.             }
  610.           }
  611.         }
  612.       }
  613.       if (PrP == 0)
  614.       {
  615.         unsigned char HwoBD = 0;
  616.         char NShSBD = 0;
  617.         for (int i = 0; i < 8; i++)
  618.         {
  619.           char ShBD = pos.SH[PoleToNum(i, 7 - i)];
  620.           if (ShBD == 3 + pos.wmove) {HwoBD |= 2; NShSBD++;}
  621.           else if (ShBD == 4 - pos.wmove) {HwoBD |= 1; NShSBD++;}
  622.         }
  623.         if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 2)
  624.         {
  625.           if (NShSBD >= 1) val -= NShSBD - 1;
  626.           if (pos.SH[ 3] == 3 + pos.wmove) val--;
  627.           if (pos.SH[28] == 3 + pos.wmove) val--;
  628.           char Drg1 = 0, DrgPS = 0;
  629.           bool Drg1p = 0;
  630.           for (int i = 0; i < 7; i++)
  631.           {
  632.             char Sh7D = pos.SH[PoleToNum(i, i + 1)];
  633.             if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;}
  634.             else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
  635.             Sh7D = pos.SH[PoleToNum(i + 1, i)];
  636.             if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;}
  637.             else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
  638.           }
  639.           if (pos.SH[0] == 3 + pos.wmove || pos.SH[4] == 3 + pos.wmove ||
  640.               pos.SH[27] == 3 + pos.wmove || pos.SH[31] == 3 + pos.wmove)
  641.                   {if (Drg1p) val += 4; else val -= 1;}
  642.           if ((pos.SH[14] == 3 + pos.wmove) == (pos.SH[17] == 3 + pos.wmove))
  643.               {if (Drg1 == 1) val += 2;}
  644.           else
  645.           {
  646.             if (Drg1 >= 2)
  647.             {
  648.               if (Drg1 > 2) val -= 1;
  649.               if (DrgPS == 3) val += 4;
  650.               if (Drg1p) val += 4; else val += 16;
  651.               if (!Drg1p && DrgPS)
  652.               {
  653.                 Drg1 = 0; Drg1p = 0; DrgPS = 0;
  654.                 for (int i = 0; i < 6; i++)
  655.                 {
  656.                   char Sh7D = pos.SH[PoleToNum(i, 5 - i)];
  657.                   if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;}
  658.                   else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
  659.                   Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)];
  660.                   if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;}
  661.                   else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
  662.                 }
  663.                 if (pos.SH[2] == 3 + pos.wmove || pos.SH[11] == 3 + pos.wmove ||
  664.                     pos.SH[20] == 3 + pos.wmove || pos.SH[29] == 3 + pos.wmove)
  665.                         val += 4;
  666.                 if ((pos.SH[14] == 3 + pos.wmove)
  667.                     ? (pos.SH[13] == 3 + pos.wmove || pos.SH[22] == 3 + pos.wmove)
  668.                     : (pos.SH[ 9] == 3 + pos.wmove || pos.SH[18] == 3 + pos.wmove))
  669.                 {
  670.                   if (Drg1 >= 2)
  671.                   {
  672.                     if (DrgPS == 3) val += 4;
  673.                     if (Drg1p) val += 4; else val += 16;
  674.                   }
  675.                   else if (Drg1 == 1) val += 1;
  676.                 }
  677.                 else if (Drg1 == 1) val += 2;
  678.               }
  679.             }
  680.           }
  681.         }
  682.         else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 1)
  683.         {
  684.           if (NShSBD >= 1) val += NShSBD - 1;
  685.           if (pos.SH[ 3] == 4 - pos.wmove) val++;
  686.           if (pos.SH[28] == 4 - pos.wmove) val++;
  687.           char Drg1 = 0, DrgPS = 0;
  688.           bool Drg1p = 0;
  689.           for (int i = 0; i < 7; i++)
  690.           {
  691.             char Sh7D = pos.SH[PoleToNum(i, i + 1)];
  692.             if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;}
  693.             else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
  694.             Sh7D = pos.SH[PoleToNum(i + 1, i)];
  695.             if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;}
  696.             else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
  697.           }
  698.           if (pos.SH[0] == 4 - pos.wmove || pos.SH[4] == 4 - pos.wmove ||
  699.               pos.SH[27] == 4 - pos.wmove || pos.SH[31] == 4 - pos.wmove)
  700.                   {if (Drg1p) val -= 4; else val += 1;}
  701.           if ((pos.SH[14] == 4 - pos.wmove) == (pos.SH[17] == 4 - pos.wmove))
  702.               {if (Drg1 == 1) val -= 2;}
  703.           else
  704.           {
  705.             if (Drg1 >= 2)
  706.             {
  707.               if (Drg1 > 2) val += 1;
  708.               if (DrgPS == 3) val -= 4;
  709.               if (Drg1p) val -= 4; else val -= 16;
  710.               if (!Drg1p && DrgPS)
  711.               {
  712.                 Drg1 = 0; Drg1p = 0; DrgPS = 0;
  713.                 for (int i = 0; i < 6; i++)
  714.                 {
  715.                   char Sh7D = pos.SH[PoleToNum(i, 5 - i)];
  716.                   if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;}
  717.                   else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
  718.                   Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)];
  719.                   if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;}
  720.                   else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
  721.                 }
  722.                 if (pos.SH[2] == 4 - pos.wmove || pos.SH[11] == 4 - pos.wmove ||
  723.                     pos.SH[20] == 4 - pos.wmove || pos.SH[29] == 4 - pos.wmove)
  724.                 {
  725.                   val -= 4;
  726.                 }
  727.                 if ((pos.SH[14] == 4 - pos.wmove)
  728.                     ? (pos.SH[13] == 4 - pos.wmove || pos.SH[22] == 4 - pos.wmove)
  729.                     : (pos.SH[ 9] == 4 - pos.wmove || pos.SH[18] == 4 - pos.wmove))
  730.                 {
  731.                   if (Drg1 >= 2)
  732.                   {
  733.                     if (DrgPS == 3) val -= 4;
  734.                     if (Drg1p) val -= 4; else val -= 16;
  735.                   }
  736.                   else if (Drg1 == 1) val -= 1;
  737.                 }
  738.                 else if (Drg1 == 1) val -= 2;
  739.               }
  740.             }
  741.           }
  742.         }
  743.         else if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1)
  744.         {
  745.           char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
  746.           char Add = 0;
  747.           for (int i = 0; i < 4; i++)
  748.           {
  749.             Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 +
  750.                         (pos.SH[Best4P[i][1]] == 3 + pos.wmove));
  751.           }
  752.           if (Add >= 4) val += 3;
  753.           else if (Add == 3) val += 2;
  754.           else if (Add >= 1) val += 1;
  755.         }
  756.         else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2)
  757.         {
  758.           char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
  759.           char Add = 0;
  760.           for (int i = 0; i < 4; i++)
  761.           {
  762.             Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 +
  763.                         (pos.SH[Best4P[i][1]] == 4 - pos.wmove));
  764.           }
  765.           if (Add >= 4) val -= 3;
  766.           else if (Add == 3) val -= 2;
  767.           else if (Add >= 1) val -= 1;
  768.         }
  769.       }
  770.       else val += PrP;
  771.     }
  772.   }
  773.   return val;
  774. }
  775.  
  776. template <class tvalue>
  777. tvalue TBaseCompPlayer<tvalue>::GetFullValue(const Position &pos, int num)
  778. {
  779.   if (!pos.AllCanMove() && !pos.AllCanEat()) return GetLossValue(pos);
  780.   else return GetValue(pos, num);
  781. }
  782.  
  783. template <class tvalue>
  784. tvalue TBaseCompPlayer<tvalue>::FindBMove(Z &z, int num,
  785.                            PMvv *pmv, int zn, tvalue a, tvalue b)
  786. {
  787.   assert(b > a);
  788.   assert(num >= 0);
  789.   if (num >= 3 && draw) draw(data, 0);
  790.   int nlast = z.narr;
  791.   if (zn < 0) {z.AddPos(); z.array[zn = z.narr++] = *pmv;}
  792.   if (pmv) pmv->mv[0] = 0;
  793.   int n0 = z.narr;
  794.   int was_eat = z.FindAllMoves(z.array[zn], num <= 0);
  795.   int n1 = z.narr;
  796.   tvalue val;
  797.   if (n1 == n0)
  798.   {
  799.     assert(!z.array[zn].pos.AllCanEat());
  800.     assert(num == 0 || !z.array[zn].pos.AllCanMove());
  801.     if (num > 0 || !z.array[zn].pos.AllCanMove()) val = GetLossValue(z.array[zn].pos);
  802.     else val = GetValue(z.array[zn].pos, 0);
  803.   }
  804.   else if (pmv && n1 == n0 + 1 && nlast < n0)
  805.   {
  806.     *pmv = z.array[n0];
  807.     if (!z.array[n0].pos.AllCanMove() && !z.array[n0].pos.AllCanMove())
  808.     {
  809.       val = -1 - GetLossValue(z.array[n0].pos);
  810.     }
  811.     else
  812.     {
  813.       val = -GetValue(z.array[n0].pos, 0);
  814.       n1 = -1;
  815.     }
  816.   }
  817.   else
  818.   {
  819.     int k, opt;
  820.     if (num >= 2)
  821.     {
  822.       if (pmv && n1 > n0 + 1)
  823.       {
  824.         for (k = 0; k < 2*(n1 - n0); k++)
  825.         {
  826.           int i0 = n0 + random(n1 - n0), i1 = n0 + random(n1 - n0 - 1);
  827.           if (i1 >= i0) i1++;
  828.           PMvv t_pmv = z.array[i0];
  829.           z.array[i0] = z.array[i1];
  830.           z.array[i1] = t_pmv;
  831.         }
  832.       }
  833.       for (k = n0; k < n1; k++) z.array[k].val = GetFullValue(z.array[k].pos);
  834.       z.Sort(n0, n1);
  835.     }
  836.     tvalue cc = 2 * win_val;
  837.     tvalue dval = was_eat ? 0 : GetValue(z.array[zn].pos, num);
  838.     tvalue aa = -b, bb = -a;
  839.     if (aa < -win_val) aa--;
  840.     else if (aa > win_val) aa++;
  841.     else aa += dval;
  842.     if (bb < -win_val) bb--;
  843.     else if (bb > win_val) bb++;
  844.     else bb += dval;
  845.     for (k = n0; k < n1 && bb > aa; k++)
  846.     {
  847.       tvalue vk;
  848.       vk = FindBMove(z, num-1+was_eat, 0, k, aa, bb);
  849.       if (vk < cc)
  850.       {
  851.         opt = k; cc = vk;
  852.         if (bb > cc) bb = cc;
  853.       }
  854.     }
  855.     if (cc < -win_val) cc++;
  856.     else if (cc > win_val) cc--;
  857.     else cc -= dval;
  858.     val = -cc;
  859.     assert(opt >= n0 && opt < n1);
  860.     if (pmv) *pmv = z.array[opt];
  861.   }
  862.   z.array[zn].val = val;
  863.   z.narr = nlast;
  864.   if (pmv)
  865.   {
  866.     if (n1 >= 0) printf("Checkers: value = %ld\n", val);
  867.     else printf("Checkers: value = ?\n");
  868.   }
  869.   return val;
  870. }
  871.  
  872. template <class tvalue>
  873. int TBaseCompPlayer<tvalue>::Move(PMv &pmv)
  874. {
  875.   Z z;
  876.   PMvv zpmv;
  877.   (PMv&)zpmv = pmv;
  878.   if (draw) draw(data, 1);
  879.   FindBMove(z, 6, &zpmv);
  880.   if (draw) draw(data, -1);
  881.   if (zpmv.mv[0] == 0) return 0;
  882.   pmv = zpmv;
  883.   return 1;
  884. }
  885.  
  886. typedef TBaseCompPlayer<long> TComputerPlayer;
  887.  
  888. #endif  //_HEADER_PLAYER_H
  889.