Subversion Repositories Kolibri OS

Rev

Rev 4652 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. //#define LANG_RUS
  2. #define NDEBUG
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <math.h>
  8.  
  9. // sprintf is too heavy
  10. int itoa(char* dst, int number)
  11. {
  12.         int result = 0;
  13.         if (number < 0) {
  14.                 result++;
  15.                 *dst++ = '-';
  16.                 number = -number;
  17.         }
  18.         char digits[16];
  19.         int ndigits = 0;
  20.         do {
  21.                 digits[ndigits++] = number % 10;
  22.                 number /= 10;
  23.         } while (number);
  24.         result += ndigits;
  25.         for (; ndigits--; )
  26.                 *dst++ = digits[ndigits] + '0';
  27.         return result;
  28. }
  29.  
  30. #include "gr-draw.h"
  31. #include "board.h"
  32. #include "player.h"
  33. #include "buttons.h"
  34. #include "sysproc.h"
  35.  
  36. char *strskipref(char *s1, char *s2)
  37. {
  38.   int L = strlen(s2);
  39.   if (strncmp(s1, s2, L) == 0) return s1 + L;
  40.   else return 0;
  41. }
  42.  
  43. class TPlayArray
  44. {
  45. public:
  46.   TPlayArray(int d = 10) : play(0), nplay(0), mplay(0) {}
  47.   ~TPlayArray() {Clear();}
  48.  
  49.   void Clear();
  50.   void Add(const PlayWrite &pl);
  51.   PlayWrite &operator[](int i) {return play[i];}
  52.   int GetNPlay() const {return nplay;}
  53. #ifndef NO_FILES
  54.   int OpenFile(const char *name, int kind);
  55.   int MsgOpenFile(const char *name, int kind);
  56.   int SaveFile(const char *name, int num, int kind);
  57.   int MsgSaveFile(const char *name, int num, int kind);
  58. #endif
  59.   void Del(int n);
  60. protected:
  61.   void Extend(int n = -1);
  62.  
  63.   PlayWrite *play;
  64.   int nplay, mplay;
  65. protected:
  66. #ifndef NO_FILES
  67.   static const char *const search[];
  68.   static int AnalizeKind(FILE *f, const int w[], const char *smb = 0);
  69.   static int ReadFileTo(FILE *f, char c);
  70.   static int ReadFileTo(FILE *f, const char *c);
  71.   static int ReadTheText(FILE *f, const char *s);
  72. #endif
  73. };
  74.  
  75. #ifdef LANG_RUS //Pending Russian Translations
  76.     #define CHECKERS_CANT_OPEN_STR "\n˜ èª¨: ¥ ¬®£ã ®âªàëâì ä ©« \"%s\".\n"
  77.     #define CHECKERS_FILE_EMPTY_STR "\n˜ èª¨: ” ©« \"%s\" ¯ãáâ.\n"
  78.     #define CHECKERS_INVALID_FILE_STR "\n˜ èª¨: ” ©« \"%s\" ®è¨¡®ç­ë©.\n"
  79.     #define FILE_WRONG_TYPE_STR "\n˜ èª¨: ” ©« \"%s\" ¨¬¥¥â ­¥¢¥à­ë© ⨯.\n"
  80.     #define ERROR_OPENING_FILE_STR "\n˜ èª¨: Žè¨¡ª  ®âªàëâ¨ï ä ©«  \"%s\".\n"
  81.     #define FILE_HAS_NO_GAMES_STR "\n˜ èª¨: ” ©« \"%s\" ­¥ ᮤ¥à¦¨â ¨£à.\n"
  82.     #define CANT_OPEN_FILE_STR "\n˜ èª¨: ¥ ¬®£ã ®âªàëâì ä ©« \"%s\" ­  § ¯¨áì.\n"
  83.     #define CHECKERS_STR "˜ èª¨"
  84.     #define FILE_SAVED_STR "\n˜ èª¨: ” ©« \"%s\" á®åà ­ñ­.\n"
  85.     #define ERROR_SAVING_FILE_STR "\n˜ èª¨: Žè¨¡ª  á®åà ­¥­¨ï ä ©«  \"%s\".\n"
  86.     #define NOT_ENOUGH_MEM_STR "\n˜ èª¨: ¥ ¤®áâ â®ç­® ¯ ¬ï⨠¤«ï á®åà ­¥­¨ï ä ©«  \"%s\".\n"
  87.     #define KIND_EQ2 "kind = 2\n"
  88.     #define END_STR "[end]"
  89.     #define PLAYV11_STR "[play_v1.1]"
  90.     #define CHECKERS_PLAY_STR "checkers-play:text\n"
  91.     #define CHECKERS_BIN_STR "checkers-play:bin_1.0\n"
  92.     #define BLUE_STR "blue: "
  93.     #define RED_STR "red: "
  94.     #define INPUT_STR "input"
  95.     #define COMPUTER_STR "computer"
  96.     #define NEW_GAME_STR "new game"
  97.     #define LIST_STR "list"
  98.     #define DELETE_STR "delete"
  99.     #define CLEAR_STR "clear"
  100.     #define SAVE_STR "save"
  101.     #define ROTATE_BOARD_STR "rotate board"
  102.     #define EXIT_STR "exit"
  103.     #define CHECKERS_INVALID_STR "Checkers: Invalid key %s\n"
  104.  
  105. #ifndef NO_FILES
  106. const char *const TPlayArray::search[] =
  107.   {"checkers-", "play:", "text", "bin_1.0\n", "history_", "1.0", "1.1"};
  108. #endif
  109.  
  110. #else /*For all other languages except RUS*/
  111.     #define CHECKERS_CANT_OPEN_STR "\nCheckers: Can't open the file \"%s\".\n"
  112.     #define CHECKERS_FILE_EMPTY_STR "\nCheckers: The file \"%s\" is empty.\n"
  113.     #define CHECKERS_INVALID_FILE_STR "\nCheckers: Invalid file \"%s\".\n"
  114.     #define FILE_WRONG_TYPE_STR "\nCheckers: The file \"%s\" has the wrong type.\n"
  115.     #define ERROR_OPENING_FILE_STR "\nCheckers: Error opening the file \"%s\".\n"
  116.     #define FILE_HAS_NO_GAMES_STR "\nCheckers: File \"%s\" doesn't contain games.\n"
  117.     #define CANT_OPEN_FILE_STR "\nCheckers: Can't open the file \"%s\" to write.\n"
  118.     #define NOT_ENOUGH_MEM_STR "\nCheckers: Not enough memory to save the file \"%s\".\n"
  119.     #define ERROR_SAVING_FILE_STR "\nCheckers: Error saving the file \"%s\".\n"
  120.     #define FILE_SAVED_STR "\nCheckers: File \"%s\" saved.\n"
  121.     #define CHECKERS_STR "Checkers"
  122.     #define KIND_EQ2 "kind = 2\n"
  123.     #define END_STR "[end]"
  124.     #define PLAYV11_STR "[Play_v1.1]"
  125.     #define CHECKERS_PLAY_STR "checkers-play:text\n"
  126.     #define CHECKERS_BIN_STR "checkers-play:bin_1.0\n"
  127.     #define BLUE_STR "blue: "
  128.     #define RED_STR "red: "
  129.     #define INPUT_STR "input"
  130.     #define COMPUTER_STR "computer"
  131.     #define NEW_GAME_STR "new game"
  132.     #define LIST_STR "list"
  133.     #define DELETE_STR "delete"
  134.     #define CLEAR_STR "clear"
  135.     #define SAVE_STR "save"
  136.     #define ROTATE_BOARD_STR "rotate board"
  137.     #define EXIT_STR "exit"
  138.     #define CHECKERS_INVALID_STR "Checkers: Invalid key %s\n"
  139.  
  140. #ifndef NO_FILES
  141. const char *const TPlayArray::search[] =
  142.      {"checkers-", "play:", "text", "bin_1.0\n", "history_", "1.0", "1.1"};
  143. #endif
  144.  
  145. #endif
  146. void TPlayArray::Clear()
  147. {
  148.   if (play) delete[] play;
  149.   play = 0; nplay = 0; mplay = 0;
  150. }
  151.  
  152. void TPlayArray::Extend(int n)
  153. {
  154.   if (n < 0) n = nplay + 1;
  155.   if (mplay < n)
  156.   {
  157.     PlayWrite *p_old = play;
  158.     int m_old = mplay;
  159.     mplay = n * 2;
  160.     play = new PlayWrite[mplay];
  161.     if (p_old)
  162.     {
  163.       for (int i = 0; i < m_old; i++) play[i] = p_old[i];
  164.       delete[] p_old;
  165.     }
  166.   }
  167. }
  168.  
  169. void TPlayArray::Add(const PlayWrite &pl)
  170. {
  171.   Extend();
  172.   play[nplay] = pl;
  173.   nplay++;
  174. }
  175.  
  176. #ifndef NO_FILES
  177. int TPlayArray::AnalizeKind(FILE *f, const int w[], const char *smb)
  178. {
  179.   int i, L, was1 = 1;
  180.   unsigned char ch;
  181.   int fnd[NELEM(search)];
  182.   for (i = 0; i < NELEM(search); i++) fnd[i] = 1;
  183.   for (L = 0; was1; L++)
  184.   {
  185.     was1 = 0;
  186.     if (fread(&ch, 1, 1, f) != 1) return (L == 0) ? -2 : -1;
  187.     for (i = 0; w[i] >= 0; i++) if (fnd[i])
  188.     {
  189.       if (tolower(ch) != tolower(search[w[i]][L])) fnd[i] = 0;
  190.       else
  191.       {
  192.         was1 = 1;
  193.         if (search[w[i]][L+1] == 0)
  194.         {
  195.           if (smb && smb[0] && fread(&ch, 1, 1, f) == 1)
  196.           {
  197.             ungetc(ch, f);
  198.             if (strchr(smb, tolower(ch)) || isalpha(ch) && strchr(smb, toupper(ch)))
  199.             {
  200.               break;
  201.             }
  202.           }
  203.           return i;
  204.         }
  205.       }
  206.     }
  207.   }
  208.   return -10 - L;
  209. }
  210.  
  211. int TPlayArray::ReadFileTo(FILE *f, char c)
  212. {
  213.   char ch;
  214.   do
  215.   {
  216.     if (fread(&ch, 1, 1, f) != 1) return 0;
  217.   }
  218.   while(ch != c);
  219.   return 1;
  220. }
  221.  
  222. int TPlayArray::ReadFileTo(FILE *f, const char *c)
  223. {
  224.   char ch;
  225.   do
  226.   {
  227.     if (fread(&ch, 1, 1, f) != 1) return 0;
  228.   }
  229.   while(!strchr(c, ch));
  230.   return 1;
  231. }
  232.  
  233. int TPlayArray::ReadTheText(FILE *f, const char *s)
  234. {
  235.   char ch;
  236.   while (*s)
  237.   {
  238.     if (fread(&ch, 1, 1, f) != 1 || ch != *s) return 0;
  239.     s++;
  240.   }
  241.   return 1;
  242. }
  243.  
  244. int TPlayArray::OpenFile(const char *name, int kind)
  245. {
  246.   int k_fnd = 0;
  247.   FILE *f = fopen(name, "rb");
  248.   if (!f) return -1;
  249.   if (kind == -1)
  250.   {
  251.     const int w[] = {0, -1};
  252.     int r = AnalizeKind(f, w);
  253.     if (r >= 0) {kind = w[r]; k_fnd = 1;}
  254.     else if (r == -11) {kind = 3; k_fnd = 3;}
  255.     else {fclose(f); return (kind == -2) ? -2 : -10;}
  256.   }
  257.   if (kind == 0)
  258.   {
  259.     if (k_fnd < 1 && !ReadFileTo(f, '-')) {fclose(f); return -10;}
  260.     k_fnd = 1;
  261.     const int w[] = {1, 4, -1};
  262.     int r = AnalizeKind(f, w);
  263.     if (r >= 0) {kind = w[r]; k_fnd = 2;}
  264.     else {fclose(f); return -10;}
  265.   }
  266.   if (kind == 1)
  267.   {
  268.     if (k_fnd < 2 && !ReadFileTo(f, ':')) {fclose(f); return -10;}
  269.     k_fnd = 2;
  270.     const int w[] = {2, 3, -1};
  271.     int r = AnalizeKind(f, w);
  272.     if (r >= 0) {kind = w[r]; k_fnd = 3;}
  273.     else {fclose(f); return -10;}
  274.   }
  275.   if (kind == 4)
  276.   {
  277.     if (k_fnd < 2 && !ReadFileTo(f, '_')) {fclose(f); return -10;}
  278.     k_fnd = 2;
  279.     const int w[] = {5, 6, -1};
  280.     int r = AnalizeKind(f, w, ".1234567890");
  281.     if (r >= 0) {kind = w[r]; k_fnd = 3;}
  282.     else {fclose(f); return -10;}
  283.   }
  284.   if (kind == 5) {kind = 3; k_fnd = 0;}
  285.   if (kind == 6)
  286.   {
  287.     if (!ReadFileTo(f, "\n\r")) {fclose(f); return -4;}
  288.     k_fnd = 3;
  289.     PlayWrite *pl = 0;
  290.     int np = THistory::HRead(f, pl);
  291.     if (np > 0 && pl)
  292.     {
  293.       int i;
  294.       Extend(nplay + np);
  295.       for (i = 0; i < np; i++)
  296.       {
  297.         if (pl[i].GetN() >= 3) play[nplay++] = pl[i];
  298.       }
  299.     }
  300.     if (pl) delete[] pl;
  301.     fclose(f);
  302.     return 1;
  303.   }
  304.   if (kind == 2)
  305.   {
  306.     printf(KIND_EQ2);
  307.     unsigned char ch;
  308.     do
  309.     {
  310.       if (fread(&ch, 1, 1, f) != 1) {fclose(f); return -10;}
  311.     }
  312.     while(!isspace(ch));
  313.     PlayWrite pl;
  314.     char word[101];
  315.     int i, kind = 0;
  316.     for (;;)
  317.     {
  318.       do
  319.       {
  320.         if (fread(&ch, 1, 1, f) != 1) break;
  321.       }
  322.       while(ch == 0 || isspace(ch));
  323.       if (feof(f)) strcpy(word, END_STR);
  324.       else
  325.       {
  326.         i = 0;
  327.         while(ch != 0 && !isspace(ch))
  328.         {
  329.           if (i < 100) word[i++] = ch;
  330.           if (fread(&ch, 1, 1, f) != 1) break;
  331.         }
  332.         word[i] = 0;
  333.       }
  334.       if (word[0] != '[')
  335.       {
  336.         if (kind == 1)
  337.         {
  338.           if (word[0] != '#' && word[0] != '$' && word[0] != '%')
  339.           {
  340.             Position pos;
  341.             pos.Read(word, 1);
  342.             pl.Clear();
  343.             pl.Add(0, pos);
  344.             kind = 2;
  345.           }
  346.         }
  347.         else if (kind == 2)
  348.         {
  349.           if (word[0] != '#' && word[0] != '$' && word[0] != '%')
  350.           {
  351.             for (i = 0; word[i] && word[i] != '.' && word[i] != ','; i++)
  352.             {
  353.               if (!isdigit((unsigned char)word[i])) {i = -1; break;}
  354.             }
  355.             if (i == -1)
  356.             {
  357.               PlayWrite::PMv pmv;
  358.               if (pl.GetPosL(pmv.pos) < 0) kind = 3;
  359.               else if (!pmv.pos.ReadMv(pmv.mv, word, 1)) kind = 3;
  360.               else if (pl.Add(pmv.mv) != 0) kind = 3;
  361.             }
  362.           }
  363.         }
  364.       }
  365.       else
  366.       {
  367.         char end_literal[] = END_STR;
  368.         char playv11_literal[] = PLAYV11_STR;
  369.  
  370.         if (kind == 2 || kind == 3)
  371.         {
  372.           if (pl.GetN() > 0) Add(pl);
  373.           pl.Clear();
  374.         }
  375.         kind = 0;
  376.         for (i = 0; word[i]; i++)
  377.         {
  378.           word[i] = (char)tolower((unsigned char)word[i]);
  379.         }
  380.         if (strskipref(word, end_literal)) break;
  381.         else if (strskipref(word, playv11_literal)) kind = 1;
  382.       }
  383.     }
  384.     fclose(f);
  385.     return 1;
  386.   }
  387.   if (kind == 3)
  388.   {
  389.     char ch[LEN_WPOS];
  390.     if (k_fnd < 3 && !ReadFileTo(f, '\n')) {fclose(f); return -10;}
  391.     k_fnd = 3;
  392.     do
  393.     {
  394.       PlayWrite pl;
  395.       for (;;)
  396.       {
  397.         int i;
  398.         for (i = 0; i < LEN_WPOS; i++)
  399.         {
  400.           if (fread(ch + i, 1, 1, f) != 1 || ch[i] < 0) break;
  401.         }
  402.         if (i < LEN_WPOS) break;
  403.         PlayWrite::PMv pmv0, pmv1;
  404.         pmv1.pos.Read(ch);
  405.         pmv1.pos.Reverse();
  406.         if (pl.GetPMvL(pmv0) >= 0)
  407.         {
  408.           TComputerPlayer::Z z;
  409.           z.FindAllMoves(pmv0);
  410.           int r;
  411.           for (r = 0; r < z.narr; r++)
  412.           {
  413.             if (memcmp(z.array[r].pos.SH, pmv1.pos.SH, sizeof(pmv1.pos.SH)) == 0)
  414.             {
  415.               pmv1 = z.array[r];
  416.               break;
  417.             }
  418.           }
  419.           if (r < z.narr) pl.Add(pmv1);
  420.           else {fclose(f); return -3;}
  421.         }
  422.         else pl.Add(0, pmv1.pos);
  423.       }
  424.       if (pl.GetN() > 0) Add(pl);
  425.     }
  426.     while(!feof(f));
  427.     fclose(f);
  428.     return 1;
  429.   }
  430.   fclose(f);
  431.   return -10;
  432. }
  433.  
  434. int TPlayArray::MsgOpenFile(const char *name, int kind)
  435. {
  436.   int n0 = nplay, no_games = 0;
  437.   int r = OpenFile(name, kind);
  438.   if (r <= 0)
  439.   {
  440.     if (r == -1)
  441.     {
  442.       printf(CHECKERS_CANT_OPEN_STR, name);
  443.       return 0;
  444.     }
  445.     else if (r == -2)
  446.     {
  447.       printf(CHECKERS_FILE_EMPTY_STR, name);
  448.       return 0;
  449.     }
  450.     else if (r == -3)
  451.     {
  452.       printf(CHECKERS_INVALID_FILE_STR, name);
  453.       return 0;
  454.     }
  455.     else if (r == -4) no_games = 1;
  456.     else if (r == -10)
  457.     {
  458.       printf(FILE_WRONG_TYPE_STR, name);
  459.       return 0;
  460.     }
  461.     else
  462.     {
  463.       printf(ERROR_OPENING_FILE_STR, name);
  464.       return 0;
  465.     }
  466.   }
  467.   if (!no_games && nplay > n0) return 1;
  468.   else
  469.   {
  470.     printf(FILE_HAS_NO_GAMES_STR, name);
  471.     return 0;
  472.   }
  473. }
  474.  
  475. int TPlayArray::SaveFile(const char *name, int num, int kind)
  476. {
  477.   FILE *f = 0;
  478.   if (kind == 0 || kind == 1 || kind == 2)
  479.   {
  480.     f = fopen(name, "wt");
  481.     if (!f) return -1;
  482.  
  483.     fprintf(f, CHECKERS_PLAY_STR);
  484.     int i0 = num, i;
  485.     if (num < 0) {i0 = 0; num = nplay-1;}
  486.     for (i = i0; i <= num; i++) if (play[i].GetN() > 0)
  487.     {
  488.       PlayWrite::PMv pmv;
  489.       if (play[i].GetPos(pmv.pos, 0) < 0) return -9;
  490.       char *str = new char[10 + NUM_CELL];
  491.       if (!str) return -5;
  492.       pmv.pos.Write(str, 1);
  493.       fprintf(f, "\n"PLAYV11_STR"#%d  %s\n", i - i0 + 1, str);
  494.       delete[] str;
  495.       int j;
  496.       for (j = 1; j < play[i].GetN(); j++)
  497.       {
  498.         if (play[i].GetPos(pmv.pos, j - 1) < 0) return -9;
  499.         if (play[i].GetMove(pmv.mv, j) < 0) return -9;
  500.         str = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)];
  501.         if (!str) return -5;
  502.         pmv.pos.WriteMvEx(pmv.mv, str, 11);
  503.         if (j % 2 == 1)
  504.         {
  505.           int nbytes = fprintf(f, "%d. ", (j + 1) / 2);
  506.           while(nbytes++ < 5) fprintf(f, " ");
  507.         }
  508.         fprintf(f, "%s", str);
  509.         if (j % 2 == 0 || j == play[i].GetN() - 1) fprintf(f, "\n");
  510.         else fprintf(f, " ,\t");
  511.         delete[] str;
  512.       }
  513.     }
  514.     fclose(f);
  515.     return 1;
  516.   }
  517.   else if (kind == -1 || kind == 3)
  518.   {
  519.     f = fopen(name, "wb");
  520.     if (!f) return -1;
  521.     if (kind == 3) fprintf(f, CHECKERS_BIN_STR);
  522.  
  523.     int i = num;
  524.     if (num < 0) {i = 0; num = nplay-1;}
  525.     for (; i <= num; i++)
  526.     {
  527.       char ch[LEN_WPOS];
  528.       Position pos;
  529.       play[i].GetPosL(pos);
  530.       if (!pos.AllCanEat() && !pos.AllCanMove())
  531.       {
  532.         ch[0] = (pos.wmove == 0) ? char(-3) : char(-1);
  533.       }
  534.       else ch[0] = char(-2);
  535.       fwrite(ch, 1, 1, f);
  536.       int j;
  537.       for (j = 0; j < play[i].GetN(); j++)
  538.       {
  539.         Position pos;
  540.         play[i].GetPos(pos, j);
  541.         pos.Reverse();
  542.         pos.Write(ch);
  543.         fwrite(ch, LEN_WPOS, 1, f);
  544.       }
  545.     }
  546.     fclose(f);
  547.     return 1;
  548.   }
  549.   if (f) fclose(f);
  550.   return -10;
  551. }
  552.  
  553. int TPlayArray::MsgSaveFile(const char *name, int num, int kind)
  554. {
  555.   int r = SaveFile(name, num, kind);
  556.   if (r <= 0)
  557.   {
  558.     if (r == -1)
  559.     {
  560.       printf(CANT_OPEN_FILE_STR, name);
  561.     }
  562.     else if (r == -5)
  563.     {
  564.       printf(NOT_ENOUGH_MEM_STR, name);
  565.     }
  566.     else if (r == -10)
  567.     {
  568.       printf(FILE_WRONG_TYPE_STR, name);
  569.     }
  570.     else
  571.     {
  572.       printf(ERROR_SAVING_FILE_STR, name);
  573.     }
  574.     return 0;
  575.   }
  576.   else
  577.   {
  578.     printf(FILE_SAVED_STR, name);
  579.     return 1;
  580.   }
  581. }
  582. #endif
  583.  
  584. void TPlayArray::Del(int n)
  585. {
  586.   if (!play || n < 0 || n >= nplay) return;
  587.   else if (nplay <= 1) {Clear(); return;}
  588.   int i;
  589.   for (i = n; i < nplay - 1; i++) play[i] = play[i+1];
  590.   play[nplay - 1].Clear();
  591.   nplay--;
  592. }
  593.  
  594.  
  595. void SetPlayerString(char *str, int c, TChPlayer *p)
  596. {
  597.   strcpy(str, c ? BLUE_STR : RED_STR);
  598.   if (!p) strcat(str, INPUT_STR);
  599.   else strcat(str, COMPUTER_STR);
  600. }
  601.  
  602. class TMainDraw : public TSomeDraw
  603. {
  604. public:
  605.  
  606.   TMainDraw() : undo_redo(0), ur_type(-1), cur_play(0),
  607.                 def_savefile("save.che"), def_savekind(2) {InitButton();}
  608.  
  609.   virtual void Draw(TGraphDraw *drw, int w, int h)
  610.   {
  611.     int d = button.GetDelt();
  612.     int hh = button.GetHeight(w - 2*d);
  613.     if (hh != 0) hh += d;
  614.     drw->SetColor(drw->GetBlackColor());
  615.     button.Draw(drw, d, h - hh, w - 2*d);
  616.   }
  617.  
  618.   virtual void DrawB(TGraphDraw *drw, TChBoard &board)
  619.   {
  620.     int urt = (board.GetCurMoveN() <= 0) +
  621.             2*(board.GetCurMoveN() >= board.GetNumMove());
  622.     if (ur_type != urt) SetButtonKind(board);
  623.     Draw(drw, board.GetW(), board.GetH());
  624.   }
  625.  
  626.   virtual TIntPoint GetDSize(int w, int h)
  627.   {
  628.     int d = button.GetDelt();
  629.     int hh = button.GetHeight(w - 2*d);
  630.     if (hh != 0) hh += d;
  631.     return TIntPoint(0, hh);
  632.   }
  633.  
  634.   virtual int ButtonPnt(int xp, int yp, int w, int h, int &n, int k = 0)
  635.   {
  636.     int d = button.GetDelt();
  637.     int hh = button.GetHeight(w - 2*d);
  638.     if (hh != 0) hh += d;
  639.     return button.ButtonPnt(xp - d, yp - (h - hh), w - 2*d, n, k);
  640.   }
  641.  
  642.   void InitButton();
  643.   void SetButtonKind(const TChBoard &board);
  644.   void PressUR(int n, TChBoard &board, TGraphDraw *drw);
  645.   void PressLS(int n, TChBoard &board, TGraphDraw *drw);
  646.   void CurPlayNorm()
  647.   {
  648.     if (cur_play < 0 || cur_play >= play.GetNPlay()) cur_play = 0;
  649.   }
  650.  
  651.   TXButtonArray button;
  652.   TMultiButton *undo_redo, *play_list;
  653.   char player_str[2][50], play_num[2][10];
  654.   TPlayArray play;
  655.   int cur_play;
  656.   char *def_savefile;
  657.   int def_savekind;
  658. protected:
  659.   int ur_type;
  660. };
  661.  
  662. void TMainDraw::InitButton()
  663. {
  664.   static char newgame_literal[] = NEW_GAME_STR;
  665.   static char list_literal[] = LIST_STR;
  666.   static char delete_literal[] = DELETE_STR;
  667.   static char clear_literal[] = CLEAR_STR;
  668.   static char save_literal[] = SAVE_STR;
  669.   static char rotateboard_literal[] = ROTATE_BOARD_STR;
  670.   static char exit_literal[] = EXIT_STR;
  671.  
  672.   static char one_literal[] = "1";
  673.   static char dash_literal[] = "-";
  674.   static char plus_literal[] = "+";
  675.   static char leftshift_literal[] = "<<";
  676.   static char rightshift_literal[] = ">>";
  677.   static char lessthan_literal[] = "<";
  678.   static char greaterthan_literal[] = ">";
  679.   static char xor_literal[] = "^";
  680.  
  681.   button.Add(1, 80, 22, newgame_literal);
  682.   button.Add(6, 60, 22, list_literal);
  683.   button.Add(7, 60, 22, delete_literal);
  684.   play_list = new TMultiButton(20);
  685.   play_list->a.Add(26, 20, 22, one_literal);
  686.   play_list->a.Add(21, 20, 22, dash_literal);
  687.   play_list->a.Add(23, 37, 22, play_num[0], -2);
  688.   play_list->a.Add(22, 20, 22, plus_literal);
  689.   play_list->a.Add(27, 37, 22, play_num[1]);
  690.   play_list->SetDefW();
  691.   button.Add(play_list);
  692.   button.Add(24, 50, 22, clear_literal);
  693. #ifndef NO_FILES
  694.   button.Add(25, 50, 22, save_literal);
  695. #endif
  696.   button.Add(2, 120, 22, player_str[0]);
  697.   button.Add(3, 120, 22, player_str[1]);
  698.   button.Add(4, 110, 22, rotateboard_literal);
  699.   undo_redo = new TMultiButton(10);
  700.   undo_redo->a.Add(11, 27, 22, leftshift_literal);
  701.   undo_redo->a.Add(12, 20, 22, lessthan_literal);
  702.   undo_redo->a.Add(15, 20, 22, xor_literal);
  703.   undo_redo->a.Add(13, 20, 22, greaterthan_literal);
  704.   undo_redo->a.Add(14, 27, 22, rightshift_literal);
  705.   undo_redo->SetDefW();
  706.   button.Add(undo_redo);
  707.   button.Add(5, 60, 22, exit_literal);
  708. }
  709.  
  710. void TMainDraw::SetButtonKind(const TChBoard &board)
  711. {
  712.   int thick;
  713.   TextButton *txb;
  714.   TXButton *bt1;
  715.   ur_type = 0;
  716.   SetPlayerString(player_str[0], 0, board.GetPlayer(0));
  717.   SetPlayerString(player_str[1], 1, board.GetPlayer(1));
  718.   int is_drw = !board.GetPViewStatus();
  719.   bt1 = button.GetButton(2);
  720.   if (bt1) bt1->drw = is_drw;
  721.   bt1 = button.GetButton(3);
  722.   if (bt1) bt1->drw = is_drw;
  723.   if (board.GetCurMoveN() <= 0) {ur_type++; thick = 0;}
  724.   else thick =  3;
  725. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(11));
  726. //  if (txb) txb->thick = thick;
  727. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(12));
  728. //  if (txb) txb->thick = thick;
  729. // we can use simple static cast
  730.         ((TextButton*)(undo_redo->a.GetButton(11)))->thick = thick;
  731.         ((TextButton*)(undo_redo->a.GetButton(12)))->thick = thick;
  732.   if (board.GetCurMoveN() >= board.GetNumMove()) {ur_type += 2; thick = 0;}
  733.   else thick = 3;
  734. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(13));
  735. //  if (txb) txb->thick = thick;
  736. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(14));
  737. //  if (txb) txb->thick = thick;
  738.         ((TextButton*)(undo_redo->a.GetButton(13)))->thick = thick;
  739.         ((TextButton*)(undo_redo->a.GetButton(14)))->thick = thick;
  740.   if (board.GetCurMoveN() < board.GetNumMove() ||
  741.      (board.GetPViewStatus() && board.GetGameEnd() <= 0))
  742.   {
  743.     thick = 3;
  744.   }
  745.   else thick = 0;
  746. //  txb = dynamic_cast<TextButton*>(undo_redo->a.GetButton(15));
  747. //  if (txb) txb->thick = thick;
  748.         ((TextButton*)(undo_redo->a.GetButton(15)))->thick = thick;
  749.   if (play.GetNPlay() == 0) is_drw = 1;
  750.   bt1 = button.GetButton(6);
  751.   if (bt1) bt1->drw = is_drw;
  752.   bt1 = button.GetButton(7);
  753.   if (bt1) bt1->drw = !is_drw;
  754. #ifndef NO_FILES
  755.   bt1 = button.GetButton(25);
  756.   if (bt1) bt1->drw = !is_drw;
  757. #endif
  758.   is_drw = board.GetPViewStatus() && play.GetNPlay() > 1;
  759.   bt1 = button.GetButton(20);
  760.   if (bt1) bt1->drw = is_drw;
  761.   bt1 = button.GetButton(24);
  762.   if (bt1) bt1->drw = is_drw;
  763.   if (is_drw)
  764.   {
  765.     play_num[0][0] = 0; play_num[1][0] = 0;
  766.     if (cur_play >= 0) itoa(play_num[0], cur_play + 1);
  767.     itoa(play_num[1], play.GetNPlay());
  768.     thick = (cur_play <= 0) ? 0 : 3;
  769.     txb = static_cast<TextButton*>(play_list->a.GetButton(21));
  770.     if (txb) txb->thick = thick;
  771.     txb = static_cast<TextButton*>(play_list->a.GetButton(26));
  772.     if (txb) txb->thick = thick;
  773.     thick = (cur_play >= play.GetNPlay() - 1) ? 0 : 3;
  774.     txb = static_cast<TextButton*>(play_list->a.GetButton(22));
  775.     if (txb) txb->thick = thick;
  776.     txb = static_cast<TextButton*>(play_list->a.GetButton(27));
  777.     if (txb) txb->thick = thick;
  778.   }
  779. }
  780.  
  781. void TMainDraw::PressUR(int n, TChBoard &board, TGraphDraw *drw)
  782. {
  783.   int mv;
  784.   if (n == 11) mv = 0;
  785.   else if (n == 12) mv = board.GetCurMoveN() - 1;
  786.   else if (n == 13) mv = board.GetCurMoveN() + 1;
  787.   else mv = board.GetNumMove();
  788.   if (board.SetCurMoveN(mv))
  789.   {
  790.     SetButtonKind(board);
  791.     if (drw && drw->IsDraw())
  792.     {
  793.       drw->DrawClear();
  794.       board.Draw(drw);
  795.     }
  796.   }
  797.   else Draw(drw, board.GetW(), board.GetH());
  798. }
  799.  
  800. void TMainDraw::PressLS(int n, TChBoard &board, TGraphDraw *drw)
  801. {
  802.   int need_redraw = 0;
  803.   if (n == 6)
  804.   {
  805.     if (!board.GetPViewStatus() || play.GetNPlay() == 0)
  806.     {
  807.       PlayWrite cur_pw = board.GetPlay();
  808.       if (cur_pw.GetN() > 2 || play.GetNPlay() == 0) play.Add(board.GetPlay());
  809.       cur_play = play.GetNPlay() - 1;
  810.       board.SetPlay(play[cur_play]);
  811.       need_redraw = 1;
  812.     }
  813.   }
  814.   else if (n == 7)
  815.   {
  816.     if (board.GetPViewStatus() && play.GetNPlay() != 0)
  817.     {
  818.       play.Del(cur_play);
  819.       if (play.GetNPlay() >= 1)
  820.       {
  821.         if (cur_play >= play.GetNPlay()) cur_play--;
  822.         board.SetPlay(play[cur_play]);
  823.       }
  824.       need_redraw = 1;
  825.     }
  826.   }
  827.   else if (n == 21)
  828.   {
  829.     if (cur_play > 0) {board.SetPlay(play[--cur_play]); need_redraw = 1;}
  830.   }
  831.   else if (n == 22)
  832.   {
  833.     if (cur_play < play.GetNPlay() - 1)
  834.     {
  835.       board.SetPlay(play[++cur_play]); need_redraw = 1;
  836.     }
  837.   }
  838.   else if (n == 26)
  839.   {
  840.     if (cur_play > 0)
  841.     {
  842.       cur_play = 0;
  843.       board.SetPlay(play[cur_play]); need_redraw = 1;
  844.     }
  845.   }
  846.   else if (n == 27)
  847.   {
  848.     if (cur_play < play.GetNPlay() - 1)
  849.     {
  850.       cur_play = play.GetNPlay() - 1;
  851.       board.SetPlay(play[cur_play]); need_redraw = 1;
  852.     }
  853.   }
  854.   else if (n == 24) {play.Clear(); cur_play = 0; need_redraw = 1;}
  855. #ifndef NO_FILES
  856.   else if (n == 25)
  857.   {
  858.     if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, -1, def_savekind);
  859.   }
  860.   else if (n == 28)
  861.   {
  862.     if (play.GetNPlay() > 0) play.MsgSaveFile(def_savefile, cur_play, def_savekind);
  863.   }
  864. #endif
  865.   if (need_redraw)
  866.   {
  867.     SetButtonKind(board);
  868.     if (drw && drw->IsDraw())
  869.     {
  870.       drw->DrawClear();
  871.       board.Draw(drw);
  872.     }
  873.   }
  874.   else Draw(drw, board.GetW(), board.GetH());
  875. }
  876.  
  877. struct TTimerDraw
  878. {
  879.   TTimerDraw(TChBoard *brd, TGraphDraw *drw) : brd(brd), drw(drw) {}
  880.  
  881.   TChBoard *brd;
  882.   clock_t st, ut, dt;
  883.   double x0;
  884.   TGraphDraw *drw;
  885.  
  886.   static void draw(void *v, int k = 0);
  887. };
  888.  
  889. void TTimerDraw::draw(void *v, int k)
  890. {
  891.   TTimerDraw &d = *(TTimerDraw*)v;
  892.   clock_t t = clock();
  893.   if (k == 0 && t - d.ut < CLOCKS_PER_SEC * 0.01) return;
  894.   if (k > 0)
  895.   {
  896.     d.st = t;
  897.     if (!d.drw || !d.drw->IsDraw()) return;
  898.     d.drw->DrawClear();
  899.     d.brd->Draw(d.drw);
  900.     d.dt = t;
  901.   }
  902.   else if (!d.drw || !d.drw->IsDraw()) return;
  903.   double xold = d.x0;
  904.   if (k >= 0)
  905.   {
  906.     d.x0 = (1 - cos(2.0 * (t - d.st) / CLOCKS_PER_SEC)) / 2;
  907.     d.brd->DrawTimer(d.drw, d.x0, 0);
  908.     d.ut = t;
  909.     if (k == 0 && t - d.dt > CLOCKS_PER_SEC * 0.5)
  910.     {
  911.       d.brd->Draw(d.drw);
  912.       d.dt = t;
  913.     }
  914.   }
  915.   if (k <= 0) d.brd->DrawTimer(d.drw, xold, 1);
  916. }
  917.  
  918.  
  919. struct TMainData
  920. {
  921.   TChBoard board;
  922.   TComputerPlayer player;
  923.   TMainDraw main_draw;
  924.  
  925.   TMainData(int id = 0);
  926.   void InitDef();
  927.   static int EventFunction(const TGraphDraw::event &ev);
  928.   void NewGame(TGraphDraw *drw);
  929.   void RotateBoard(TGraphDraw *drw);
  930.   void PlayerPress(int np, TGraphDraw *drw);
  931.   void GoToCurMove(TGraphDraw *drw);
  932. };
  933.  
  934. TMainData::TMainData(int id) : board(id)
  935. {
  936.   board.SetCheckResize(1);
  937.   board.SetPlayer(1, &player);
  938.   board.SetBottomColor(0);
  939.   board.SetSomeDraw(&main_draw);
  940.   board.SetMinWSize(90, 140);
  941. }
  942.  
  943. void TMainData::InitDef()
  944. {
  945.   if (main_draw.play.GetNPlay() > 0)
  946.   {
  947.     main_draw.CurPlayNorm();
  948.     board.SetPlay(main_draw.play[main_draw.cur_play]);
  949.   }
  950.   main_draw.SetButtonKind(board);
  951. }
  952.  
  953. void TMainData::NewGame(TGraphDraw *drw)
  954. {
  955.   board.NewGame();
  956.   main_draw.SetButtonKind(board);
  957.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  958. }
  959.  
  960. void TMainData::RotateBoard(TGraphDraw *drw)
  961. {
  962.   board.SetBottomColor(3 - board.GetBottomColor());
  963.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  964. }
  965.  
  966. void TMainData::PlayerPress(int np, TGraphDraw *drw)
  967. {
  968.   if (np != 0 && np != 1) return;
  969.   if (board.GetPlayer(np)) board.SetPlayer(np, 0);
  970.   else board.SetPlayer(np, &player);
  971.   if (board.GetPlayer(0) && !board.GetPlayer(1))
  972.   {
  973.     board.SetBottomColor(1);
  974.   }
  975.   if (board.GetPlayer(1) && !board.GetPlayer(0))
  976.   {
  977.     board.SetBottomColor(0);
  978.   }
  979.   main_draw.SetButtonKind(board);
  980.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  981. }
  982.  
  983. void TMainData::GoToCurMove(TGraphDraw *drw)
  984. {
  985.   board.GoToCurMove();
  986.   main_draw.SetButtonKind(board);
  987.   if (drw && drw->IsDraw()) {drw->DrawClear(); board.Draw(drw);}
  988. }
  989.  
  990. int TMainData::EventFunction(const TGraphDraw::event &ev)
  991. {
  992.   if (!ev.any.drw->data) return -100;
  993.   TMainData &data = *(TMainData*)ev.any.drw->data;
  994.   int nbutton, ret = 0;
  995.   switch(ev.type)
  996.   {
  997.   case TGraphDraw::event::button_down:
  998.     if (ev.button.n != 1) break;
  999.     ev.button.drw->OpenDraw();
  1000.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1001.              data.board.GetW(), data.board.GetH(), nbutton, 1) > 0)
  1002.     {
  1003.       data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1004.       ret |= TGraphDraw::ret_setcapture;
  1005.     }
  1006.     else data.board.MouseClick(ev.button.drw, ev.button.x, ev.button.y);
  1007.     ev.button.drw->CloseDraw();
  1008.     break;
  1009.   case TGraphDraw::event::mouse_move:
  1010.     if (ev.button.n >= 0 && ev.button.n != 1) break;
  1011.     ev.button.drw->OpenDraw();
  1012.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1013.              data.board.GetW(), data.board.GetH(), nbutton, 2) >= 1000)
  1014.     {
  1015.       data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1016.     }
  1017.     ev.button.drw->CloseDraw();
  1018.     break;
  1019.   case TGraphDraw::event::button_up:
  1020.     if (ev.button.n != 1) break;
  1021.     ev.button.drw->OpenDraw();
  1022.     if (data.main_draw.ButtonPnt(ev.button.x, ev.button.y,
  1023.              data.board.GetW(), data.board.GetH(), nbutton, 3) > 0)
  1024.     {
  1025.       switch(nbutton)
  1026.       {
  1027.       case 1:
  1028.         data.NewGame(ev.button.drw);
  1029.         break;
  1030.       case 2:
  1031.       case 3:
  1032.         data.PlayerPress(nbutton - 2, ev.button.drw);
  1033.         break;
  1034.       case 4:
  1035.         data.RotateBoard(ev.button.drw);
  1036.         break;
  1037.       case 5:
  1038.         data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1039.         ev.button.drw->Quit();
  1040.         break;
  1041.       case 11:
  1042.       case 12:
  1043.       case 13:
  1044.       case 14:
  1045.         data.main_draw.PressUR(nbutton, data.board, ev.button.drw);
  1046.         break;
  1047.       case 15:
  1048.         data.GoToCurMove(ev.button.drw);
  1049.         break;
  1050.       case 6:
  1051.       case 7:
  1052.       case 21:
  1053.       case 22:
  1054.       case 23:
  1055.       case 24:
  1056.       case 25:
  1057.       case 26:
  1058.       case 27:
  1059.         data.main_draw.PressLS(nbutton, data.board, ev.button.drw);
  1060.         break;
  1061.       default:
  1062.         data.main_draw.Draw(ev.button.drw, data.board.GetW(), data.board.GetH());
  1063.         break;
  1064.       }
  1065.     }
  1066.     ev.button.drw->CloseDraw();
  1067.     break;
  1068.   case TGraphDraw::event::draw:
  1069.     ev.button.drw->OpenDraw();
  1070.     data.board.Draw(ev.button.drw);
  1071.     ev.button.drw->CloseDraw();
  1072.     break;
  1073.   case TGraphDraw::event::key_down:
  1074.     ev.button.drw->OpenDraw();
  1075.     if (ev.key.k == XK_Left) data.board.PKeyEvent(ev.button.drw, TChBoard::PLeft);
  1076.     else if (ev.key.k == XK_Right) data.board.PKeyEvent(ev.button.drw, TChBoard::PRight);
  1077.     else if (ev.key.k == XK_Up) data.board.PKeyEvent(ev.button.drw, TChBoard::PUp);
  1078.     else if (ev.key.k == XK_Down) data.board.PKeyEvent(ev.button.drw, TChBoard::PDown);
  1079.     else if (ev.key.k == XK_Return || ev.key.k == XK_space)
  1080.     {
  1081.       data.board.PKeyEvent(ev.button.drw, TChBoard::PEnter);
  1082.     }
  1083.     else if (ev.key.k == XK_Escape) ev.button.drw->Quit();
  1084.     else if (ev.key.k == XK_less) data.main_draw.PressUR(11, data.board, ev.button.drw);
  1085.     else if (ev.key.k == XK_comma) data.main_draw.PressUR(12, data.board, ev.button.drw);
  1086.     else if (ev.key.k == XK_period) data.main_draw.PressUR(13, data.board, ev.button.drw);
  1087.     else if (ev.key.k == XK_greater) data.main_draw.PressUR(14, data.board, ev.button.drw);
  1088.     else if (ev.key.k == XK_minus) data.main_draw.PressLS(21, data.board, ev.button.drw);
  1089.     else if (ev.key.k == XK_equal) data.main_draw.PressLS(22, data.board, ev.button.drw);
  1090.     else if (ev.key.k == XK_underscore) data.main_draw.PressLS(26, data.board, ev.button.drw);
  1091.     else if (ev.key.k == XK_plus) data.main_draw.PressLS(27, data.board, ev.button.drw);
  1092.     else if (ev.key.k == XK_Delete) data.main_draw.PressLS(7, data.board, ev.button.drw);
  1093.     else if (ev.key.k == XK_F8) data.main_draw.PressLS(24, data.board, ev.button.drw);
  1094.     else if (ev.key.k == XK_l || ev.key.k == XK_L) data.main_draw.PressLS(6, data.board, ev.button.drw);
  1095. #ifndef NO_FILES
  1096.     else if (ev.key.k == XK_F2) data.main_draw.PressLS(25, data.board, ev.button.drw);
  1097. #endif
  1098.     else if (ev.key.k == XK_s || ev.key.k == XK_S) data.main_draw.PressLS(28, data.board, ev.button.drw);
  1099.     else if (ev.key.k == XK_slash || ev.key.k == XK_question) data.GoToCurMove(ev.button.drw);
  1100.     else if (ev.key.k == XK_n || ev.key.k == XK_N) data.NewGame(ev.button.drw);
  1101.     else if (ev.key.k == XK_t || ev.key.k == XK_T) data.RotateBoard(ev.button.drw);
  1102.     else if (ev.key.k == XK_r || ev.key.k == XK_R) data.PlayerPress(0, ev.button.drw);
  1103.     else if (ev.key.k == XK_b || ev.key.k == XK_B) data.PlayerPress(1, ev.button.drw);
  1104.     else if (ev.key.k == XK_f || ev.key.k == XK_F)
  1105.     {
  1106.       int w, h;
  1107.       ev.button.drw->GetSize(w, h);
  1108.       ev.button.drw->CloseDraw();
  1109.       if (DuplicateProcess() == 0)
  1110.       {
  1111.         ev.button.drw->ResReinit(w, h);
  1112.         data.board.EraseHistory();
  1113.       }
  1114.     }
  1115.     ev.button.drw->CloseDraw();
  1116.     break;
  1117.   case TGraphDraw::event::close:
  1118.     ret = 1;
  1119.     break;
  1120.   }
  1121.   return ret;
  1122. }
  1123.  
  1124. int main(int argc, char **argv)
  1125. {
  1126.   randomize();
  1127. #ifndef NO_FILES
  1128.   THistory::InitHFile(argv[0]);
  1129. #endif
  1130.   TMainData data(-1);
  1131.   if (argv && argc >= 2)
  1132.   {
  1133.     int i, kx = 1;
  1134.     for (i = 1; i < argc; i++)
  1135.     {
  1136.       if (kx == 1 && argv[i][0] == '-')
  1137.       {
  1138.         if (strcmp(argv[i], "--") == 0) kx = 0;
  1139.         else if (strcmp(argv[i], "-ssf") == 0) ssf = 1;
  1140.         else if (strncmp(argv[i], "-save", 5) == 0)
  1141.         {
  1142.           int j = 5;
  1143.           if (argv[i][j])
  1144.           {
  1145.             if (argv[i][j] != '=' || !argv[i][j+1])
  1146.             {
  1147.               data.main_draw.def_savekind = atoi(argv[i] + j);
  1148.               while (argv[i][j] && argv[i][j] != '=') j++;
  1149.               if (argv[i][j] != '=' || !argv[i][j+1]) continue;
  1150.             }
  1151.             data.main_draw.def_savefile = argv[i] + j + 1;
  1152.           }
  1153.         }
  1154.  
  1155.         else printf(CHECKERS_INVALID_STR, argv[i]);
  1156.       }
  1157.       else if (kx == 0 || kx == 1)
  1158.       {
  1159. #ifndef NO_FILES
  1160.         data.main_draw.play.MsgOpenFile(argv[i], -1);
  1161. #endif
  1162.       }
  1163.     }
  1164.   }
  1165.   data.InitDef();
  1166.   TMainGraphDraw graph(CHECKERS_STR);
  1167.   TTimerDraw timer_draw(&data.board, &graph);
  1168.   data.player.draw = TTimerDraw::draw; data.player.data = &timer_draw;
  1169.   graph.evfunc = TMainData::EventFunction; graph.data = &data;
  1170.   graph.SetAboutInfo(1);
  1171.   graph.Run(TGraphDraw::button_down_mask | TGraphDraw::button_up_mask |
  1172.             TGraphDraw::key_down_mask | TGraphDraw::mouse_drag_mask,
  1173.             450 + 100 * ssf, 528);
  1174.   return 0;
  1175. }
  1176.