Subversion Repositories Kolibri OS

Rev

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

  1. #define BUILD_RUS
  2. #ifndef __MENUET__
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <math.h>
  8. #else
  9. #include <menuet.h>
  10. #include <me_heap.h>
  11. using namespace Menuet;
  12. #define strlen StrLen
  13. #define strcpy StrCopy
  14. #define memcpy MemCopy
  15. #include <stdarg.h>
  16. const unsigned dectab[] = { 1000000000, 100000000, 10000000, 1000000, 100000,
  17.                    10000, 1000, 100, 10, 0 };
  18. int sprintf( char *Str, char* Format, ... )
  19. {
  20.         int i, fmtlinesize, j, k, flag;
  21.         unsigned head, tail;
  22.         char c;
  23.         va_list arglist;
  24.         //
  25.         va_start(arglist, Format);
  26.  
  27.         //
  28.         fmtlinesize = strlen( Format );
  29.         //
  30.         if( fmtlinesize == 0 ) return 0;
  31.  
  32.         //
  33.         for( i = 0, j = 0; i < fmtlinesize; i++ )
  34.         {
  35.                 //
  36.                 c = Format[i];
  37.                 //
  38.                 if( c != '%' )
  39.                 {
  40.                         Str[j++] = c;
  41.                         continue;
  42.                 }
  43.                 //
  44.                 i++;
  45.                 //
  46.                 if( i >= fmtlinesize ) break;
  47.  
  48.                 //
  49.                 flag = 0;
  50.                 //
  51.                 c = Format[i];
  52.                 if (c == 'l') c = Format[++i];
  53.                 //
  54.                 switch( c )
  55.                 {
  56.                 //
  57.                 case '%':
  58.                         Str[j++] = c;
  59.                         break;
  60.                 // БШБНД ЯРПНЙХ
  61.                 case 's':
  62.                         char* str;
  63.                         str = va_arg(arglist, char*);
  64.                         for( k = 0; ( c = str[k] ) != 0; k++ )
  65.                         {
  66.                                 Str[j++] = c;
  67.                         }
  68.                         break;
  69.                 // БШБНД ЯХЛБНКЮ
  70.                 case 'c':
  71.                         Str[j++] = va_arg(arglist, int) & 0xFF;
  72.                         break;
  73.                 // БШБНД ДБНИМНЦН ЯКНБЮ Б ДЕЯЪРХВМНЛ БХДЕ
  74.                 case 'u':
  75.                 case 'd':
  76.                         head = va_arg(arglist, unsigned);
  77.                         for( k = 0; dectab[k] != 0; k++ )
  78.                         {
  79.                                 tail = head % dectab[k];
  80.                                 head /= dectab[k];
  81.                                 c = head + '0';
  82.                                 if( c == '0' )
  83.                                 {
  84.                                         if( flag ) Str[j++] = c;
  85.                                 }
  86.                                 else
  87.                                 {
  88.                                         flag++;
  89.                                         Str[j++] = c;
  90.                                 }
  91.                                 //
  92.                                 head = tail;
  93.                         }
  94.                         //
  95.                         c = head + '0';
  96.                         Str[j++] = c;
  97.                         break;
  98.                 default:
  99.                         break;
  100.                 }
  101.         }
  102.         //
  103.         Str[j] = 0;
  104.         return j;
  105. }
  106. int isdigit(int c)
  107. {
  108.         return (c>='0' && c<='9');
  109. }
  110. int atoi(const char* string)
  111. {
  112.         int res=0;
  113.         int sign=0;
  114.         const char* ptr;
  115.         for (ptr=string; *ptr && *ptr<=' ';ptr++);
  116.         if (*ptr=='-') {sign=1;++ptr;}
  117.         while (*ptr >= '0' && *ptr <= '9')
  118.         {
  119.                 res = res*10 + *ptr++ - '0';
  120.         }
  121.         if (sign) res = -res;
  122.         return res;
  123. }
  124. int islower(int c)
  125. {
  126.         return (c>='a' && c<='z');
  127. }
  128. int abs(int n)
  129. {
  130.         return (n<0)?-n:n;
  131. }
  132. int memcmp(const void* buf1, const void* buf2, unsigned count)
  133. {
  134.         const char* ptr1 = (const char*)buf1;
  135.         const char* ptr2 = (const char*)buf2;
  136.         unsigned i=0;
  137.         while (i<count && *ptr1==*ptr2) {++i;++ptr1;++ptr2;}
  138.         if (i==count)
  139.                 return 0;
  140.         else if (*ptr1<*ptr2)
  141.                 return -1;
  142.         else
  143.                 return 1;
  144. }
  145. void strncpy(char* dest, const char* source, unsigned len)
  146. {
  147.         char* ptr1 = dest;
  148.         const char *ptr2 = source;
  149.         for (;len-- && *ptr2; *ptr1++=*ptr2++) ;
  150. }
  151. unsigned int rand_data[4];
  152.  
  153. void randomize()
  154. {
  155.         rand_data[0] = (unsigned int)Clock();
  156.         rand_data[1] = (unsigned int)GetPackedTime();
  157.         rand_data[2] = (unsigned int)GetPackedDate();
  158.         rand_data[3] = (unsigned int)0xA3901BD2 ^ GetPid();
  159. }
  160.  
  161. unsigned int rand()
  162. {
  163.         rand_data[0] ^= _HashDword(rand_data[3] + 0x2835C013U);
  164.         rand_data[1] += _HashDword(rand_data[0]);
  165.         rand_data[2] -= _HashDword(rand_data[1]);
  166.         rand_data[3] ^= _HashDword(rand_data[2]);
  167.         return rand_data[3];
  168. }
  169.  
  170. #define random(k)  (rand() % (k))
  171. #define floor Floor
  172. double fabs(double x)
  173. {
  174.         __asm   fld     x
  175.         __asm   fabs
  176. }
  177. #define M_PI       3.14159265358979323846
  178. double cos(double x)
  179. {
  180.         __asm   fld     x
  181.         __asm   fcos
  182. }
  183. double sin(double x)
  184. {
  185.         __asm   fld     x
  186.         __asm   fsin
  187. }
  188. /*inline void printf(const char* format, ...)
  189. {}*/
  190. #define printf /* nothing */
  191. inline void strcat(char* str1, const char* str2)
  192. {strcpy(str1+strlen(str1),str2);}
  193. int strncmp(const char* str1, const char* str2, unsigned len)
  194. {
  195.         for (;len--;)
  196.         {
  197.                 if (*str1 != *str2) break;
  198.                 if (*str1 == 0)
  199.                         return 0;
  200.                 ++str1;++str2;
  201.         }
  202.         if (len==(unsigned)-1)
  203.                 return 0;
  204.         if (*str1 < *str2)
  205.                 return -1;
  206.         return 1;
  207. }
  208. #define clock Clock
  209. typedef unsigned int clock_t;
  210. #define CLOCKS_PER_SEC 100
  211. #define XK_Left         0xB0
  212. #define XK_Right        0xB3
  213. #define XK_Up           0xB2
  214. #define XK_Down         0xB1
  215. #define XK_Return       0x0D
  216. #define XK_space        0x20
  217. #define XK_Escape       0x1B
  218. #define XK_less         '<'
  219. #define XK_comma        ','
  220. #define XK_period       '.'
  221. #define XK_greater      '>'
  222. #define XK_minus        '-'
  223. #define XK_equal        '='
  224. #define XK_underscore   '_'
  225. #define XK_plus         '+'
  226. #define XK_Delete       0xB6
  227. #define XK_F8           0x39
  228. #define XK_l            'l'
  229. #define XK_L            'L'
  230. #define XK_F2           0x33
  231. #define XK_s            's'
  232. #define XK_S            'S'
  233. #define XK_slash        '/'
  234. #define XK_question     '?'
  235. #define XK_n            'n'
  236. #define XK_N            'N'
  237. #define XK_t            't'
  238. #define XK_T            'T'
  239. #define XK_r            'r'
  240. #define XK_R            'R'
  241. #define XK_b            'b'
  242. #define XK_B            'B'
  243. #define XK_f            'f'
  244. #define XK_F            'F'
  245. #define assert(a) /* nothing */
  246. #include "qsort.c"
  247. #endif
  248. #include "gr-draw.h"
  249. #include "board.h"
  250. #include "player.h"
  251. #include "buttons.h"
  252. #include "sysproc.h"
  253.  
  254. char *strskipref(char *s1, char *s2)
  255. {
  256.   int L = strlen(s2);
  257.   if (strncmp(s1, s2, L) == 0) return s1 + L;
  258.   else return 0;
  259. }
  260.  
  261. class TPlayArray
  262. {
  263. public:
  264.   TPlayArray(int d = 10) : play(0), nplay(0), mplay(0) {}
  265.   ~TPlayArray() {Clear();}
  266.  
  267.   void Clear();
  268.   void Add(const PlayWrite &pl);
  269.   PlayWrite &operator[](int i) {return play[i];}
  270.   int GetNPlay() const {return nplay;}
  271. #ifndef __MENUET__
  272.   int OpenFile(const char *name, int kind);
  273.   int MsgOpenFile(const char *name, int kind);
  274.   int SaveFile(const char *name, int num, int kind);
  275.   int MsgSaveFile(const char *name, int num, int kind);
  276. #endif
  277.   void Del(int n);
  278. protected:
  279.   void Extend(int n = -1);
  280.  
  281.   PlayWrite *play;
  282.   int nplay, mplay;
  283. protected:
  284. #ifndef __MENUET__
  285.   static const char *const search[];
  286.   static int AnalizeKind(FILE *f, const int w[], const char *smb = 0);
  287.   static int ReadFileTo(FILE *f, char c);
  288.   static int ReadFileTo(FILE *f, const char *c);
  289.   static int ReadTheText(FILE *f, const char *s);
  290. #endif
  291. };
  292.  
  293. #ifndef __MENUET__
  294. const char *const TPlayArray::search[] =
  295.      {"checkers-", "play:", "text", "bin_1.0\n", "history_", "1.0", "1.1"};
  296. #endif
  297.  
  298. void TPlayArray::Clear()
  299. {
  300.   if (play) delete[] play;
  301.   play = 0; nplay = 0; mplay = 0;
  302. }
  303.  
  304. void TPlayArray::Extend(int n)
  305. {
  306.   if (n < 0) n = nplay + 1;
  307.   if (mplay < n)
  308.   {
  309.     PlayWrite *p_old = play;
  310.     int m_old = mplay;
  311.     mplay = n * 2;
  312.     play = new PlayWrite[mplay];
  313.     if (p_old)
  314.     {
  315.       for (int i = 0; i < m_old; i++) play[i] = p_old[i];
  316.       delete[] p_old;
  317.     }
  318.   }
  319. }
  320.  
  321. void TPlayArray::Add(const PlayWrite &pl)
  322. {
  323.   Extend();
  324.   play[nplay] = pl;
  325.   nplay++;
  326. }
  327.  
  328. #ifndef __MENUET__
  329. int TPlayArray::AnalizeKind(FILE *f, const int w[], const char *smb)
  330. {
  331.   int i, L, was1 = 1;
  332.   unsigned char ch;
  333.   int fnd[NELEM(search)];
  334.   for (i = 0; i < NELEM(search); i++) fnd[i] = 1;
  335.   for (L = 0; was1; L++)
  336.   {
  337.     was1 = 0;
  338.     if (fread(&ch, 1, 1, f) != 1) return (L == 0) ? -2 : -1;
  339.     for (i = 0; w[i] >= 0; i++) if (fnd[i])
  340.     {
  341.       if (tolower(ch) != tolower(search[w[i]][L])) fnd[i] = 0;
  342.       else
  343.       {
  344.         was1 = 1;
  345.         if (search[w[i]][L+1] == 0)
  346.         {
  347.           if (smb && smb[0] && fread(&ch, 1, 1, f) == 1)
  348.           {
  349.             ungetc(ch, f);
  350.             if (strchr(smb, tolower(ch)) || isalpha(ch) && strchr(smb, toupper(ch)))
  351.             {
  352.               break;
  353.             }
  354.           }
  355.           return i;
  356.         }
  357.       }
  358.     }
  359.   }
  360.   return -10 - L;
  361. }
  362.  
  363. int TPlayArray::ReadFileTo(FILE *f, char c)
  364. {
  365.   char ch;
  366.   do
  367.   {
  368.     if (fread(&ch, 1, 1, f) != 1) return 0;
  369.   }
  370.   while(ch != c);
  371.   return 1;
  372. }
  373.  
  374. int TPlayArray::ReadFileTo(FILE *f, const char *c)
  375. {
  376.   char ch;
  377.   do
  378.   {
  379.     if (fread(&ch, 1, 1, f) != 1) return 0;
  380.   }
  381.   while(!strchr(c, ch));
  382.   return 1;
  383. }
  384.  
  385. int TPlayArray::ReadTheText(FILE *f, const char *s)
  386. {
  387.   char ch;
  388.   while (*s)
  389.   {
  390.     if (fread(&ch, 1, 1, f) != 1 || ch != *s) return 0;
  391.     s++;
  392.   }
  393.   return 1;
  394. }
  395.  
  396. int TPlayArray::OpenFile(const char *name, int kind)
  397. {
  398.   int k_fnd = 0;
  399.   FILE *f = fopen(name, "rb");
  400.   if (!f) return -1;
  401.   if (kind == -1)
  402.   {
  403.     const int w[] = {0, -1};
  404.     int r = AnalizeKind(f, w);
  405.     if (r >= 0) {kind = w[r]; k_fnd = 1;}
  406.     else if (r == -11) {kind = 3; k_fnd = 3;}
  407.     else {fclose(f); return (kind == -2) ? -2 : -10;}
  408.   }
  409.   if (kind == 0)
  410.   {
  411.     if (k_fnd < 1 && !ReadFileTo(f, '-')) {fclose(f); return -10;}
  412.     k_fnd = 1;
  413.     const int w[] = {1, 4, -1};
  414.     int r = AnalizeKind(f, w);
  415.     if (r >= 0) {kind = w[r]; k_fnd = 2;}
  416.     else {fclose(f); return -10;}
  417.   }
  418.   if (kind == 1)
  419.   {
  420.     if (k_fnd < 2 && !ReadFileTo(f, ':')) {fclose(f); return -10;}
  421.     k_fnd = 2;
  422.     const int w[] = {2, 3, -1};
  423.     int r = AnalizeKind(f, w);
  424.     if (r >= 0) {kind = w[r]; k_fnd = 3;}
  425.     else {fclose(f); return -10;}
  426.   }
  427.   if (kind == 4)
  428.   {
  429.     if (k_fnd < 2 && !ReadFileTo(f, '_')) {fclose(f); return -10;}
  430.     k_fnd = 2;
  431.     const int w[] = {5, 6, -1};
  432.     int r = AnalizeKind(f, w, ".1234567890");
  433.     if (r >= 0) {kind = w[r]; k_fnd = 3;}
  434.     else {fclose(f); return -10;}
  435.   }
  436.   if (kind == 5) {kind = 3; k_fnd = 0;}
  437.   if (kind == 6)
  438.   {
  439.     if (!ReadFileTo(f, "\n\r")) {fclose(f); return -4;}
  440.     k_fnd = 3;
  441.     PlayWrite *pl = 0;
  442.     int np = THistory::HRead(f, pl);
  443.     if (np > 0 && pl)
  444.     {
  445.       int i;
  446.       Extend(nplay + np);
  447.       for (i = 0; i < np; i++)
  448.       {
  449.         if (pl[i].GetN() >= 3) play[nplay++] = pl[i];
  450.       }
  451.     }
  452.     if (pl) delete[] pl;
  453.     fclose(f);
  454.     return 1;
  455.   }
  456.   if (kind == 2)
  457.   {
  458.     printf("kind = 2\n");
  459.     unsigned char ch;
  460.     do
  461.     {
  462.       if (fread(&ch, 1, 1, f) != 1) {fclose(f); return -10;}
  463.     }
  464.     while(!isspace(ch));
  465.     PlayWrite pl;
  466.     char word[101];
  467.     int i, kind = 0;
  468.     for (;;)
  469.     {
  470.       do
  471.       {
  472.         if (fread(&ch, 1, 1, f) != 1) break;
  473.       }
  474.       while(ch == 0 || isspace(ch));
  475.       if (feof(f)) strcpy(word, "[end]");
  476.       else
  477.       {
  478.         i = 0;
  479.         while(ch != 0 && !isspace(ch))
  480.         {
  481.           if (i < 100) word[i++] = ch;
  482.           if (fread(&ch, 1, 1, f) != 1) break;
  483.         }
  484.         word[i] = 0;
  485.       }
  486.       if (word[0] != '[')
  487.       {
  488.         if (kind == 1)
  489.         {
  490.           if (word[0] != '#' && word[0] != '$' && word[0] != '%')
  491.           {
  492.             Position pos;
  493.             pos.Read(word, 1);
  494.             pl.Clear();
  495.             pl.Add(0, pos);
  496.             kind = 2;
  497.           }
  498.         }
  499.         else if (kind == 2)
  500.         {
  501.           if (word[0] != '#' && word[0] != '$' && word[0] != '%')
  502.           {
  503.             for (i = 0; word[i] && word[i] != '.' && word[i] != ','; i++)
  504.             {
  505.               if (!isdigit((unsigned char)word[i])) {i = -1; break;}
  506.             }
  507.             if (i == -1)
  508.             {
  509.               PlayWrite::PMv pmv;
  510.               if (pl.GetPosL(pmv.pos) < 0) kind = 3;
  511.               else if (!pmv.pos.ReadMv(pmv.mv, word, 1)) kind = 3;
  512.               else if (pl.Add(pmv.mv) != 0) kind = 3;
  513.             }
  514.           }
  515.         }
  516.       }
  517.       else
  518.       {
  519.         if (kind == 2 || kind == 3)
  520.         {
  521.           if (pl.GetN() > 0) Add(pl);
  522.           pl.Clear();
  523.         }
  524.         kind = 0;
  525.         for (i = 0; word[i]; i++)
  526.         {
  527.           word[i] = (char)tolower((unsigned char)word[i]);
  528.         }
  529.         if (strskipref(word, "[end]")) break;
  530.         else if (strskipref(word, "[play_v1.1]")) kind = 1;
  531.       }
  532.     }
  533.     fclose(f);
  534.     return 1;
  535.   }
  536.   if (kind == 3)
  537.   {
  538.     char ch[LEN_WPOS];
  539.     if (k_fnd < 3 && !ReadFileTo(f, '\n')) {fclose(f); return -10;}
  540.     k_fnd = 3;
  541.     do
  542.     {
  543.       PlayWrite pl;
  544.       for (;;)
  545.       {
  546.         int i;
  547.         for (i = 0; i < LEN_WPOS; i++)
  548.         {
  549.           if (fread(ch + i, 1, 1, f) != 1 || ch[i] < 0) break;
  550.         }
  551.         if (i < LEN_WPOS) break;
  552.         PlayWrite::PMv pmv0, pmv1;
  553.         pmv1.pos.Read(ch);
  554.         pmv1.pos.Reverse();
  555.         if (pl.GetPMvL(pmv0) >= 0)
  556.         {
  557.           TComputerPlayer::Z z;
  558.           z.FindAllMoves(pmv0);
  559.           int r;
  560.           for (r = 0; r < z.narr; r++)
  561.           {
  562.             if (memcmp(z.array[r].pos.SH, pmv1.pos.SH, sizeof(pmv1.pos.SH)) == 0)
  563.             {
  564.               pmv1 = z.array[r];
  565.               break;
  566.             }
  567.           }
  568.           if (r < z.narr) pl.Add(pmv1);
  569.           else {fclose(f); return -3;}
  570.         }
  571.         else pl.Add(0, pmv1.pos);
  572.       }
  573.       if (pl.GetN() > 0) Add(pl);
  574.     }
  575.     while(!feof(f));
  576.     fclose(f);
  577.     return 1;
  578.   }
  579.   fclose(f);
  580.   return -10;
  581. }
  582.  
  583. int TPlayArray::MsgOpenFile(const char *name, int kind)
  584. {
  585.   int n0 = nplay, no_games = 0;
  586.   int r = OpenFile(name, kind);
  587.   if (r <= 0)
  588.   {
  589.     if (r == -1)
  590.     {
  591. #ifdef BUILD_RUS
  592.       printf("\nШашки: Не могу открыть файл \"%s\".\n", name);
  593. #else
  594.       printf("\nCheckers: Can't open the file \"%s\".\n", name);
  595. #endif
  596.       return 0;
  597.     }
  598.     else if (r == -2)
  599.     {
  600. #ifdef BUILD_RUS
  601.       printf("\nШашки: Файл \"%s\" пуст.\n", name);
  602. #else
  603.       printf("\nCheckers: The file \"%s\" is empty.\n", name);
  604. #endif
  605.       return 0;
  606.     }
  607.     else if (r == -3)
  608.     {
  609. #ifdef BUILD_RUS
  610.       printf("\nШашки: Файл \"%s\" ошибочный.\n", name);
  611. #else
  612.       printf("\nCheckers: Invalid file \"%s\".\n", name);
  613. #endif
  614.       return 0;
  615.     }
  616.     else if (r == -4) no_games = 1;
  617.     else if (r == -10)
  618.     {
  619. #ifdef BUILD_RUS
  620.       printf("\nШашки: Файл \"%s\" имеет неверный тип.\n", name);
  621. #else
  622.       printf("\nCheckers: The file \"%s\" has wrong type.\n", name);
  623. #endif
  624.       return 0;
  625.     }
  626.     else
  627.     {
  628. #ifdef BUILD_RUS
  629.       printf("\nШашки: Ошибка открытия файла \"%s\".\n", name);
  630. #else
  631.       printf("\nCheckers: Error openning the file \"%s\".\n", name);
  632. #endif
  633.       return 0;
  634.     }
  635.   }
  636.   if (!no_games && nplay > n0) return 1;
  637.   else
  638.   {
  639. #ifdef BUILD_RUS
  640.     printf("\nШашки: Файл \"%s\" не содержит игр.\n", name);
  641. #else
  642.     printf("\nCheckers: File \"%s\" don't contains games.\n", name);
  643. #endif
  644.     return 0;
  645.   }
  646. }
  647.  
  648. int TPlayArray::SaveFile(const char *name, int num, int kind)
  649. {
  650.   FILE *f = 0;
  651.   if (kind == 0 || kind == 1 || kind == 2)
  652.   {
  653.     f = fopen(name, "wt");
  654.     if (!f) return -1;
  655.     fprintf(f, "checkers-play:text\n");
  656.     int i0 = num, i;
  657.     if (num < 0) {i0 = 0; num = nplay-1;}
  658.     for (i = i0; i <= num; i++) if (play[i].GetN() > 0)
  659.     {
  660.       PlayWrite::PMv pmv;
  661.       if (play[i].GetPos(pmv.pos, 0) < 0) return -9;
  662.       char *str = new char[10 + NUM_CELL];
  663.       if (!str) return -5;
  664.       pmv.pos.Write(str, 1);
  665.       fprintf(f, "\n[Play_v1.1]#%d  %s\n", i - i0 + 1, str);
  666.       delete[] str;
  667.       int j;
  668.       for (j = 1; j < play[i].GetN(); j++)
  669.       {
  670.         if (play[i].GetPos(pmv.pos, j - 1) < 0) return -9;
  671.         if (play[i].GetMove(pmv.mv, j) < 0) return -9;
  672.         str = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)];
  673.         if (!str) return -5;
  674.         pmv.pos.WriteMvEx(pmv.mv, str, 11);
  675.         if (j % 2 == 1)
  676.         {
  677.           int nbytes = fprintf(f, "%d. ", (j + 1) / 2);
  678.           while(nbytes++ < 5) fprintf(f, " ");
  679.         }
  680.         fprintf(f, "%s", str);
  681.         if (j % 2 == 0 || j == play[i].GetN() - 1) fprintf(f, "\n");
  682.         else fprintf(f, " ,\t");
  683.         delete[] str;
  684.       }
  685.     }
  686.     fclose(f);
  687.     return 1;
  688.   }
  689.   else if (kind == -1 || kind == 3)
  690.   {
  691.     f = fopen(name, "wb");
  692.     if (!f) return -1;
  693.     if (kind == 3) fprintf(f, "checkers-play:bin_1.0\n");
  694.     int i = num;
  695.     if (num < 0) {i = 0; num = nplay-1;}
  696.     for (; i <= num; i++)
  697.     {
  698.       char ch[LEN_WPOS];
  699.       Position pos;
  700.       play[i].GetPosL(pos);
  701.       if (!pos.AllCanEat() && !pos.AllCanMove())
  702.       {
  703.         ch[0] = (pos.wmove == 0) ? char(-3) : char(-1);
  704.       }
  705.       else ch[0] = char(-2);
  706.       fwrite(ch, 1, 1, f);
  707.       int j;
  708.       for (j = 0; j < play[i].GetN(); j++)
  709.       {
  710.         Position pos;
  711.         play[i].GetPos(pos, j);
  712.         pos.Reverse();
  713.         pos.Write(ch);
  714.         fwrite(ch, LEN_WPOS, 1, f);
  715.       }
  716.     }
  717.     fclose(f);
  718.     return 1;
  719.   }
  720.   if (f) fclose(f);
  721.   return -10;
  722. }
  723.  
  724. int TPlayArray::MsgSaveFile(const char *name, int num, int kind)
  725. {
  726.   int r = SaveFile(name, num, kind);
  727.   if (r <= 0)
  728.   {
  729.     if (r == -1)
  730.     {
  731. #ifdef BUILD_RUS
  732.       printf("\nШашки: Не могу открыть файл \"%s\" на запись.\n", name);
  733. #else
  734.       printf("\nCheckers: Can't open the file \"%s\" to write.\n", name);
  735. #endif
  736.     }
  737.     else if (r == -5)
  738.     {
  739. #ifdef BUILD_RUS
  740.       printf("\nШашки: Не достаточно памяти для сохранения файла \"%s\".\n", name);
  741. #else
  742.       printf("\nCheckers: Not enough memory to save the file \"%s\".\n", name);
  743. #endif
  744.     }
  745.     else if (r == -10)
  746.     {
  747. #ifdef BUILD_RUS
  748.       printf("\nШашки: Файл \"%s\" имеет неверный тип.\n", name);
  749. #else
  750.       printf("\nCheckers: The file \"%s\" has wrong type.\n", name);
  751. #endif
  752.     }
  753.     else
  754.     {
  755. #ifdef BUILD_RUS
  756.       printf("\nШашки: Ошибка сохранения файла \"%s\".\n", name);
  757. #else
  758.       printf("\nCheckers: Error saving the file \"%s\".\n", name);
  759. #endif
  760.     }
  761.     return 0;
  762.   }
  763.   else
  764.   {
  765. #ifdef BUILD_RUS
  766.     printf("\nШашки: Файл \"%s\" сохранён.\n", name);
  767. #else
  768.     printf("\nCheckers: File \"%s\" saved.\n", name);
  769. #endif
  770.     return 1;
  771.   }
  772. }
  773. #endif
  774.  
  775. void TPlayArray::Del(int n)
  776. {
  777.   if (!play || n < 0 || n >= nplay) return;
  778.   else if (nplay <= 1) {Clear(); return;}
  779.   int i;
  780.   for (i = n; i < nplay - 1; i++) play[i] = play[i+1];
  781.   play[nplay - 1].Clear();
  782.   nplay--;
  783. }
  784.  
  785.  
  786. void SetPlayerString(char *str, int c, TChPlayer *p)
  787. {
  788.   strcpy(str, c ? "blue: " : "red: ");
  789.   if (!p) strcat(str, "input");
  790.   else strcat(str, "computer");
  791. }
  792.  
  793. class TMainDraw : public TSomeDraw
  794. {
  795. public:
  796.   TMainDraw() : undo_redo(0), ur_type(-1), cur_play(0),
  797.                 def_savefile("save.che"), def_savekind(2) {InitButton();}
  798.  
  799.   virtual void Draw(TGraphDraw *drw, int w, int h)
  800.   {
  801.     int d = button.GetDelt();
  802.     int hh = button.GetHeight(w - 2*d);
  803.     if (hh != 0) hh += d;
  804.     drw->SetColor(drw->GetBlackColor());
  805.     button.Draw(drw, d, h - hh, w - 2*d);
  806.   }
  807.  
  808.   virtual void DrawB(TGraphDraw *drw, TChBoard &board)
  809.   {
  810.     int urt = (board.GetCurMoveN() <= 0) +
  811.             2*(board.GetCurMoveN() >= board.GetNumMove());
  812.     if (ur_type != urt) SetButtonKind(board);
  813.     Draw(drw, board.GetW(), board.GetH());
  814.   }
  815.  
  816.   virtual TIntPoint GetDSize(int w, int h)
  817.   {
  818.     int d = button.GetDelt();
  819.     int hh = button.GetHeight(w - 2*d);
  820.     if (hh != 0) hh += d;
  821.     return TIntPoint(0, hh);
  822.   }
  823.  
  824.   virtual int ButtonPnt(int xp, int yp, int w, int h, int &n, int k = 0)
  825.   {
  826.     int d = button.GetDelt();
  827.     int hh = button.GetHeight(w - 2*d);
  828.     if (hh != 0) hh += d;
  829.     return button.ButtonPnt(xp - d, yp - (h - hh), w - 2*d, n, k);
  830.   }
  831.  
  832.   void InitButton();
  833.   void SetButtonKind(const TChBoard &board);
  834.   void PressUR(int n, TChBoard &board, TGraphDraw *drw);
  835.   void PressLS(int n, TChBoard &board, TGraphDraw *drw);
  836.   void CurPlayNorm()
  837.   {
  838.     if (cur_play < 0 || cur_play >= play.GetNPlay()) cur_play = 0;
  839.   }
  840.  
  841.   TXButtonArray button;
  842.   TMultiButton *undo_redo, *play_list;
  843.   char player_str[2][50], play_num[2][10];
  844.   TPlayArray play;
  845.   int cur_play;
  846.   char *def_savefile;
  847.   int def_savekind;
  848. protected:
  849.   int ur_type;
  850. };
  851.  
  852. void TMainDraw::InitButton()
  853. {
  854.   button.Add(1, 80, 22, "new game");
  855.   button.Add(6, 60, 22, "list");
  856.   button.Add(7, 60, 22, "delete");
  857.   play_list = new TMultiButton(20);
  858.   play_list->a.Add(26, 20, 22, "1");
  859.   play_list->a.Add(21, 20, 22, "-");
  860.   play_list->a.Add(23, 37, 22, play_num[0], -2);
  861.   play_list->a.Add(22, 20, 22, "+");
  862.   play_list->a.Add(27, 37, 22, play_num[1]);
  863.   play_list->SetDefW();
  864.   button.Add(play_list);
  865.   button.Add(24, 50, 22, "clear");
  866. #ifndef __MENUET__
  867.   button.Add(25, 50, 22, "save");
  868. #endif
  869.   button.Add(2, 120, 22, player_str[0]);
  870.   button.Add(3, 120, 22, player_str[1]);
  871.   button.Add(4, 110, 22, "rotate board");
  872.   undo_redo = new TMultiButton(10);
  873.   undo_redo->a.Add(11, 27, 22, "<<");
  874.   undo_redo->a.Add(12, 20, 22, "<");
  875.   undo_redo->a.Add(15, 20, 22, "^");
  876.   undo_redo->a.Add(13, 20, 22, ">");
  877.   undo_redo->a.Add(14, 27, 22, ">>");
  878.   undo_redo->SetDefW();
  879.   button.Add(undo_redo);
  880.   button.Add(5, 60, 22, "exit");
  881. }
  882.  
  883. void TMainDraw::SetButtonKind(const TChBoard &board)
  884. {
  885.   int thick;
  886.   TextButton *txb;
  887.   TXButton *bt1;
  888.   ur_type = 0;
  889.   SetPlayerString(player_str[0], 0, board.GetPlayer(0));
  890.   SetPlayerString(player_str[1], 1, board.GetPlayer(1));
  891.   int is_drw = !board.GetPViewStatus();
  892.   bt1 = button.GetButton(2);
  893.   if (bt1) bt1->drw = is_drw;
  894.   bt1 = button.GetButton(3);
  895.   if (bt1) bt1->drw = is_drw;
  896.   if (board.GetCurMoveN() <= 0) {ur_type++; thick = 0;}
  897.   else thick =  3;
  898. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(11));
  899. //  if (txb) txb->thick = thick;
  900. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(12));
  901. //  if (txb) txb->thick = thick;
  902. // we can use simple static cast
  903.         ((TextButton*)(undo_redo->a.GetButton(11)))->thick = thick;
  904.         ((TextButton*)(undo_redo->a.GetButton(12)))->thick = thick;
  905.   if (board.GetCurMoveN() >= board.GetNumMove()) {ur_type += 2; thick = 0;}
  906.   else thick = 3;
  907. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(13));
  908. //  if (txb) txb->thick = thick;
  909. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(14));
  910. //  if (txb) txb->thick = thick;
  911.         ((TextButton*)(undo_redo->a.GetButton(13)))->thick = thick;
  912.         ((TextButton*)(undo_redo->a.GetButton(14)))->thick = thick;
  913.   if (board.GetCurMoveN() < board.GetNumMove() ||
  914.      (board.GetPViewStatus() && board.GetGameEnd() <= 0))
  915.   {
  916.     thick = 3;
  917.   }
  918.   else thick = 0;
  919. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(15));
  920. //  if (txb) txb->thick = thick;
  921.         ((TextButton*)(undo_redo->a.GetButton(15)))->thick = thick;
  922.   if (play.GetNPlay() == 0) is_drw = 1;
  923.   bt1 = button.GetButton(6);
  924.   if (bt1) bt1->drw = is_drw;
  925.   bt1 = button.GetButton(7);
  926.   if (bt1) bt1->drw = !is_drw;
  927. #ifndef __MENUET__
  928.   bt1 = button.GetButton(25);
  929.   if (bt1) bt1->drw = !is_drw;
  930. #endif
  931.   is_drw = board.GetPViewStatus() && play.GetNPlay() > 1;
  932.   bt1 = button.GetButton(20);
  933.   if (bt1) bt1->drw = is_drw;
  934.   bt1 = button.GetButton(24);
  935.   if (bt1) bt1->drw = is_drw;
  936.   if (is_drw)
  937.   {
  938.     play_num[0][0] = 0; play_num[1][0] = 0;
  939.     if (cur_play >= 0) sprintf(play_num[0], "%d", cur_play + 1);
  940.     sprintf(play_num[1], "%d", play.GetNPlay());
  941.     thick = (cur_play <= 0) ? 0 : 3;
  942. #define dynamic_cast static_cast
  943.     txb = dynamic_cast<TextButton*>(play_list->a.GetButton(21));
  944.     if (txb) txb->thick = thick;
  945.     txb = dynamic_cast<TextButton*>(play_list->a.GetButton(26));
  946.     if (txb) txb->thick = thick;
  947.     thick = (cur_play >= play.GetNPlay() - 1) ? 0 : 3;
  948.     txb = dynamic_cast<TextButton*>(play_list->a.GetButton(22));
  949.     if (txb) txb->thick = thick;
  950.     txb = dynamic_cast<TextButton*>(play_list->a.GetButton(27));
  951.     if (txb) txb->thick = thick;
  952. #undef dynamic_cast
  953.   }
  954. }
  955.  
  956. void TMainDraw::PressUR(int n, TChBoard &board, TGraphDraw *drw)
  957. {
  958.   int mv;
  959.   if (n == 11) mv = 0;
  960.   else if (n == 12) mv = board.GetCurMoveN() - 1;
  961.   else if (n == 13) mv = board.GetCurMoveN() + 1;
  962.   else mv = board.GetNumMove();
  963.   if (board.SetCurMoveN(mv))
  964.   {
  965.     SetButtonKind(board);
  966.     if (drw && drw->IsDraw())
  967.     {
  968.       drw->DrawClear();
  969.       board.Draw(drw);
  970.     }
  971.   }
  972.   else Draw(drw, board.GetW(), board.GetH());
  973. }
  974.  
  975. void TMainDraw::PressLS(int n, TChBoard &board, TGraphDraw *drw)
  976. {
  977.   int need_redraw = 0;
  978.   if (n == 6)
  979.   {
  980.     if (!board.GetPViewStatus() || play.GetNPlay() == 0)
  981.     {
  982.       PlayWrite cur_pw = board.GetPlay();
  983.       if (cur_pw.GetN() > 2 || play.GetNPlay() == 0) play.Add(board.GetPlay());
  984.       cur_play = play.GetNPlay() - 1;
  985.       board.SetPlay(play[cur_play]);
  986.       need_redraw = 1;
  987.     }
  988.   }
  989.   else if (n == 7)
  990.   {
  991.     if (board.GetPViewStatus() && play.GetNPlay() != 0)
  992.     {
  993.       play.Del(cur_play);
  994.       if (play.GetNPlay() >= 1)
  995.       {
  996.         if (cur_play >= play.GetNPlay()) cur_play--;
  997.         board.SetPlay(play[cur_play]);
  998.       }
  999.       need_redraw = 1;
  1000.     }
  1001.   }
  1002.   else if (n == 21)
  1003.   {
  1004.     if (cur_play > 0) {board.SetPlay(play[--cur_play]); need_redraw = 1;}
  1005.   }
  1006.   else if (n == 22)
  1007.   {
  1008.     if (cur_play < play.GetNPlay() - 1)
  1009.     {
  1010.       board.SetPlay(play[++cur_play]); need_redraw = 1;
  1011.     }
  1012.   }
  1013.   else if (n == 26)
  1014.   {
  1015.     if (cur_play > 0)
  1016.     {
  1017.       cur_play = 0;
  1018.       board.SetPlay(play[cur_play]); need_redraw = 1;
  1019.     }
  1020.   }
  1021.   else if (n == 27)
  1022.   {
  1023.     if (cur_play < play.GetNPlay() - 1)
  1024.     {
  1025.       cur_play = play.GetNPlay() - 1;
  1026.       board.SetPlay(play[cur_play]); need_redraw = 1;
  1027.     }
  1028.   }
  1029.   else if (n == 24) {play.Clear(); cur_play = 0; need_redraw = 1;}
  1030. #ifndef __MENUET__
  1031.   else if (n == 25)
  1032.   {
  1033.     if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, -1, def_savekind);
  1034.   }
  1035.   else if (n == 28)
  1036.   {
  1037.     if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, cur_play, def_savekind);
  1038.   }
  1039. #endif
  1040.   if (need_redraw)
  1041.   {
  1042.     SetButtonKind(board);
  1043.     if (drw && drw->IsDraw())
  1044.     {
  1045.       drw->DrawClear();
  1046.       board.Draw(drw);
  1047.     }
  1048.   }
  1049.   else Draw(drw, board.GetW(), board.GetH());
  1050. }
  1051.  
  1052. struct TTimerDraw
  1053. {
  1054.   TTimerDraw(TChBoard *brd, TGraphDraw *drw) : brd(brd), drw(drw) {}
  1055.  
  1056.   TChBoard *brd;
  1057.   clock_t st, ut, dt;
  1058.   double x0;
  1059.   TGraphDraw *drw;
  1060.  
  1061.   static void draw(void *v, int k = 0);
  1062. };
  1063.  
  1064. void TTimerDraw::draw(void *v, int k)
  1065. {
  1066.   TTimerDraw &d = *(TTimerDraw*)v;
  1067.   clock_t t = clock();
  1068.   if (k == 0 && t - d.ut < CLOCKS_PER_SEC * 0.01) return;
  1069.   if (k > 0)
  1070.   {
  1071.     d.st = t;
  1072.     if (!d.drw || !d.drw->IsDraw()) return;
  1073.     d.drw->DrawClear();
  1074.     d.brd->Draw(d.drw);
  1075.     d.dt = t;
  1076.   }
  1077.   else if (!d.drw || !d.drw->IsDraw()) return;
  1078.   double xold = d.x0;
  1079.   if (k >= 0)
  1080.   {
  1081.     d.x0 = (1 - cos(2.0 * (t - d.st) / CLOCKS_PER_SEC)) / 2;
  1082.     d.brd->DrawTimer(d.drw, d.x0, 0);
  1083.     d.ut = t;
  1084.     if (k == 0 && t - d.dt > CLOCKS_PER_SEC * 0.5)
  1085.     {
  1086.       d.brd->Draw(d.drw);
  1087.       d.dt = t;
  1088.     }
  1089.   }
  1090.   if (k <= 0) d.brd->DrawTimer(d.drw, xold, 1);
  1091. }
  1092.  
  1093.  
  1094. struct TMainData
  1095. {
  1096.   TChBoard board;
  1097.   TComputerPlayer player;
  1098.   TMainDraw main_draw;
  1099.  
  1100.   TMainData(int id = 0);
  1101.   void InitDef();
  1102.   static int EventFunction(const TGraphDraw::event &ev);
  1103.   void NewGame(TGraphDraw *drw);
  1104.   void RotateBoard(TGraphDraw *drw);
  1105.   void PlayerPress(int np, TGraphDraw *drw);
  1106.   void GoToCurMove(TGraphDraw *drw);
  1107. };
  1108.  
  1109. TMainData::TMainData(int id) : board(id)
  1110. {
  1111.   board.SetCheckResize(1);
  1112.   board.SetPlayer(1, &player);
  1113.   board.SetBottomColor(0);
  1114.   board.SetSomeDraw(&main_draw);
  1115.   board.SetMinWSize(90, 140);
  1116. }
  1117.  
  1118. void TMainData::InitDef()
  1119. {
  1120.   if (main_draw.play.GetNPlay() > 0)
  1121.   {
  1122.     main_draw.CurPlayNorm();
  1123.     board.SetPlay(main_draw.play[main_draw.cur_play]);
  1124.   }
  1125.   main_draw.SetButtonKind(board);
  1126. }
  1127.  
  1128. void TMainData::NewGame(TGraphDraw *drw)
  1129. {
  1130.   board.NewGame();
  1131.   main_draw.SetButtonKind(board);
  1132.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  1133. }
  1134.  
  1135. void TMainData::RotateBoard(TGraphDraw *drw)
  1136. {
  1137.   board.SetBottomColor(3 - board.GetBottomColor());
  1138.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  1139. }
  1140.  
  1141. void TMainData::PlayerPress(int np, TGraphDraw *drw)
  1142. {
  1143.   if (np != 0 && np != 1) return;
  1144.   if (board.GetPlayer(np)) board.SetPlayer(np, 0);
  1145.   else board.SetPlayer(np, &player);
  1146.   if (board.GetPlayer(0) && !board.GetPlayer(1))
  1147.   {
  1148.     board.SetBottomColor(1);
  1149.   }
  1150.   if (board.GetPlayer(1) && !board.GetPlayer(0))
  1151.   {
  1152.     board.SetBottomColor(0);
  1153.   }
  1154.   main_draw.SetButtonKind(board);
  1155.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  1156. }
  1157.  
  1158. void TMainData::GoToCurMove(TGraphDraw *drw)
  1159. {
  1160.   board.GoToCurMove();
  1161.   main_draw.SetButtonKind(board);
  1162.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  1163. }
  1164.  
  1165. int TMainData::EventFunction(const TGraphDraw::event &ev)
  1166. {
  1167.   if (!ev.any.drw->data) return -100;
  1168.   TMainData &data = *(TMainData*)ev.any.drw->data;
  1169.   int nbutton, ret = 0;
  1170.   switch(ev.type)
  1171.   {
  1172.   case TGraphDraw::event::button_down:
  1173.     if (ev.button.n != 1) break;
  1174.     ev.button.drw->OpenDraw();
  1175.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1176.              data.board.GetW(), data.board.GetH(), nbutton, 1) > 0)
  1177.     {
  1178.       data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1179.       ret |= TGraphDraw::ret_setcapture;
  1180.     }
  1181.     else data.board.MouseClick(ev.button.drw, ev.button.x, ev.button.y);
  1182.     ev.button.drw->CloseDraw();
  1183.     break;
  1184.   case TGraphDraw::event::mouse_move:
  1185.     if (ev.button.n >= 0 && ev.button.n != 1) break;
  1186.     ev.button.drw->OpenDraw();
  1187.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1188.              data.board.GetW(), data.board.GetH(), nbutton, 2) >= 1000)
  1189.     {
  1190.       data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1191.     }
  1192.     ev.button.drw->CloseDraw();
  1193.     break;
  1194.   case TGraphDraw::event::button_up:
  1195.     if (ev.button.n != 1) break;
  1196.     ev.button.drw->OpenDraw();
  1197.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1198.              data.board.GetW(), data.board.GetH(), nbutton, 3) > 0)
  1199.     {
  1200.       switch(nbutton)
  1201.       {
  1202.       case 1:
  1203.         data.NewGame(ev.button.drw);
  1204.         break;
  1205.       case 2:
  1206.       case 3:
  1207.         data.PlayerPress(nbutton - 2, ev.button.drw);
  1208.         break;
  1209.       case 4:
  1210.         data.RotateBoard(ev.button.drw);
  1211.         break;
  1212.       case 5:
  1213.         data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1214.         ev.button.drw->Quit();
  1215.         break;
  1216.       case 11:
  1217.       case 12:
  1218.       case 13:
  1219.       case 14:
  1220.         data.main_draw.PressUR(nbutton, data.board, ev.button.drw);
  1221.         break;
  1222.       case 15:
  1223.         data.GoToCurMove(ev.button.drw);
  1224.         break;
  1225.       case 6:
  1226.       case 7:
  1227.       case 21:
  1228.       case 22:
  1229.       case 23:
  1230.       case 24:
  1231.       case 25:
  1232.       case 26:
  1233.       case 27:
  1234.         data.main_draw.PressLS(nbutton, data.board, ev.button.drw);
  1235.         break;
  1236.       default:
  1237.         data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1238.         break;
  1239.       }
  1240.     }
  1241.     ev.button.drw->CloseDraw();
  1242.     break;
  1243.   case TGraphDraw::event::draw:
  1244.     ev.button.drw->OpenDraw();
  1245.     data.board.Draw(ev.button.drw);
  1246.     ev.button.drw->CloseDraw();
  1247.     break;
  1248.   case TGraphDraw::event::key_down:
  1249.     ev.button.drw->OpenDraw();
  1250.     if (ev.key.k == XK_Left) data.board.PKeyEvent(ev.button.drw, TChBoard::PLeft);
  1251.     else if (ev.key.k == XK_Right) data.board.PKeyEvent(ev.button.drw, TChBoard::PRight);
  1252.     else if (ev.key.k == XK_Up) data.board.PKeyEvent(ev.button.drw, TChBoard::PUp);
  1253.     else if (ev.key.k == XK_Down) data.board.PKeyEvent(ev.button.drw, TChBoard::PDown);
  1254.     else if (ev.key.k == XK_Return || ev.key.k == XK_space)
  1255.     {
  1256.       data.board.PKeyEvent(ev.button.drw, TChBoard::PEnter);
  1257.     }
  1258.     else if (ev.key.k == XK_Escape) ev.button.drw->Quit();
  1259.     else if (ev.key.k == XK_less) data.main_draw.PressUR(11, data.board, ev.button.drw);
  1260.     else if (ev.key.k == XK_comma) data.main_draw.PressUR(12, data.board, ev.button.drw);
  1261.     else if (ev.key.k == XK_period) data.main_draw.PressUR(13, data.board, ev.button.drw);
  1262.     else if (ev.key.k == XK_greater) data.main_draw.PressUR(14, data.board, ev.button.drw);
  1263.     else if (ev.key.k == XK_minus) data.main_draw.PressLS(21, data.board, ev.button.drw);
  1264.     else if (ev.key.k == XK_equal) data.main_draw.PressLS(22, data.board, ev.button.drw);
  1265.     else if (ev.key.k == XK_underscore) data.main_draw.PressLS(26, data.board, ev.button.drw);
  1266.     else if (ev.key.k == XK_plus) data.main_draw.PressLS(27, data.board, ev.button.drw);
  1267.     else if (ev.key.k == XK_Delete) data.main_draw.PressLS(7, data.board, ev.button.drw);
  1268.     else if (ev.key.k == XK_F8) data.main_draw.PressLS(24, data.board, ev.button.drw);
  1269.     else if (ev.key.k == XK_l || ev.key.k == XK_L) data.main_draw.PressLS(6, data.board, ev.button.drw);
  1270. #ifndef __MENUET__
  1271.     else if (ev.key.k == XK_F2) data.main_draw.PressLS(25, data.board, ev.button.drw);
  1272. #endif
  1273.     else if (ev.key.k == XK_s || ev.key.k == XK_S) data.main_draw.PressLS(28, data.board, ev.button.drw);
  1274.     else if (ev.key.k == XK_slash || ev.key.k == XK_question) data.GoToCurMove(ev.button.drw);
  1275.     else if (ev.key.k == XK_n || ev.key.k == XK_N) data.NewGame(ev.button.drw);
  1276.     else if (ev.key.k == XK_t || ev.key.k == XK_T) data.RotateBoard(ev.button.drw);
  1277.     else if (ev.key.k == XK_r || ev.key.k == XK_R) data.PlayerPress(0, ev.button.drw);
  1278.     else if (ev.key.k == XK_b || ev.key.k == XK_B) data.PlayerPress(1, ev.button.drw);
  1279.     else if (ev.key.k == XK_f || ev.key.k == XK_F)
  1280.     {
  1281.       int w, h;
  1282.       ev.button.drw->GetSize(w, h);
  1283.       ev.button.drw->CloseDraw();
  1284.       if (DuplicateProcess() == 0)
  1285.       {
  1286.         ev.button.drw->ResReinit(w, h);
  1287.         data.board.EraseHistory();
  1288.       }
  1289.     }
  1290.     ev.button.drw->CloseDraw();
  1291.     break;
  1292.   case TGraphDraw::event::close:
  1293.     ret = 1;
  1294.     break;
  1295.   }
  1296.   return ret;
  1297. }
  1298.  
  1299. #ifndef __MENUET__
  1300. int main(int argc, char **argv)
  1301. {
  1302.   randomize();
  1303.   THistory::InitHFile(argv[0]);
  1304.   TMainData data(-1);
  1305.   if (argv && argc >= 2)
  1306.   {
  1307.     int i, kx = 1;
  1308.     for (i = 1; i < argc; i++)
  1309.     {
  1310.       if (kx == 1 && argv[i][0] == '-')
  1311.       {
  1312.         if (strcmp(argv[i], "--") == 0) kx = 0;
  1313.         else if (strcmp(argv[i], "-ssf") == 0) ssf = 1;
  1314.         else if (strncmp(argv[i], "-save", 5) == 0)
  1315.         {
  1316.           int j = 5;
  1317.           if (argv[i][j])
  1318.           {
  1319.             if (argv[i][j] != '=' || !argv[i][j+1])
  1320.             {
  1321.               data.main_draw.def_savekind = atoi(argv[i] + j);
  1322.               while (argv[i][j] && argv[i][j] != '=') j++;
  1323.               if (argv[i][j] != '=' || !argv[i][j+1]) continue;
  1324.             }
  1325.             data.main_draw.def_savefile = argv[i] + j + 1;
  1326.           }
  1327.         }
  1328.         else printf("Checkers: Invalid key %s\n", argv[i]);
  1329.       }
  1330.       else if (kx == 0 || kx == 1)
  1331.       {
  1332.         data.main_draw.play.MsgOpenFile(argv[i], -1);
  1333.       }
  1334.     }
  1335.   }
  1336.   data.InitDef();
  1337.   TMainGraphDraw graph(
  1338. #ifdef BUILD_RUS
  1339.   "Шашки"
  1340. #else
  1341.   "Checkers"
  1342. #endif
  1343.   );
  1344.   TTimerDraw timer_draw(&data.board, &graph);
  1345.   data.player.draw = TTimerDraw::draw; data.player.data = &timer_draw;
  1346.   graph.evfunc = TMainData::EventFunction; graph.data = &data;
  1347.   graph.SetAboutInfo(1);
  1348.   graph.Run(TGraphDraw::button_down_mask | TGraphDraw::button_up_mask |
  1349.             TGraphDraw::key_down_mask | TGraphDraw::mouse_drag_mask,
  1350.             450 + 100 * ssf, 528);
  1351.   return 0;
  1352. }
  1353. #else
  1354.  
  1355. TMainData* mdata;
  1356. TMainGraphDraw* graph;
  1357.  
  1358. bool MenuetOnStart(TStartData &me_start, TThreadData)
  1359. {
  1360.         mdata = new TMainData(-1);
  1361.         graph = new TMainGraphDraw;
  1362.         randomize();
  1363.         mdata->InitDef();
  1364.         static TTimerDraw timer_draw(&mdata->board, graph);
  1365.         mdata->player.draw = TTimerDraw::draw; mdata->player.data = &timer_draw;
  1366.         graph->data = mdata;
  1367.         me_start.WinData.Title =
  1368. #ifdef BUILD_RUS
  1369.         "Шашки"
  1370. #else
  1371.         "Checkers"
  1372. #endif
  1373.         ;
  1374.         me_start.Width = 450 + 100*ssf;
  1375.         me_start.Height = 528;
  1376.         return true;
  1377. }
  1378. bool MenuetOnClose(TThreadData)
  1379. {
  1380.         delete mdata;
  1381.         delete graph;
  1382.         return true;
  1383. }
  1384. int MenuetOnIdle(TThreadData)
  1385. {return -1;}
  1386. void MenuetOnSize(int window_rect[], TThreadData)
  1387. {mdata->board.Resize(window_rect[2]-window_rect[0], window_rect[3]-window_rect[1]);}
  1388. void MenuetOnKeyPress(TThreadData)
  1389. {
  1390.         TGraphDraw::event ev;
  1391.         ev.type = TGraphDraw::event::key_down;
  1392.         ev.any.drw = graph;
  1393.         ev.key.k = GetKey();
  1394.         mdata->EventFunction(ev);
  1395. }
  1396. void MenuetOnDraw(void)
  1397. {
  1398.         TGraphDraw::event ev;
  1399.         ev.type = TGraphDraw::event::draw;
  1400.         ev.any.drw = graph;
  1401.         mdata->EventFunction(ev);
  1402. }
  1403. void MenuetOnMouse(TThreadData)
  1404. {
  1405.         short x,y;
  1406.         GetMousePosition(x,y);
  1407.         int m = GetMouseButton() & 1;
  1408.         static int mprev = 0;
  1409.         if (m == mprev)
  1410.                 return;
  1411.         mprev = m;
  1412.         TGraphDraw::event ev;
  1413.         ev.type = m ? TGraphDraw::event::button_down : TGraphDraw::event::button_up;
  1414.         ev.any.drw = graph;
  1415.         ev.button.n = 1;
  1416.         ev.button.x = x;
  1417.         ev.button.y = y;
  1418.         mdata->EventFunction(ev);
  1419. }
  1420. #endif
  1421.