Subversion Repositories Kolibri OS

Rev

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