Subversion Repositories Kolibri OS

Rev

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

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