Subversion Repositories Kolibri OS

Rev

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

  1. #ifndef _HEADER_HISTORY_H
  2. #define _HEADER_HISTORY_H
  3.  
  4. #include "position.h"
  5. #include "hash.h"
  6. #include "sysproc.h"
  7.  
  8. class THistory
  9. {
  10. #ifndef NO_FILES
  11. public:
  12.   static char FileName[1024];
  13. #endif
  14. public:
  15.   THistory(int id = 0) {if (id >= 0) Hid = NHid++; else Hid = id;}
  16.  
  17.   int GetId() const {return Hid;}
  18.   static int GetNId() {return NHid;}
  19.  
  20.   int Start(const Position &pos) const;
  21.   int Move(const Position &pos, const unsigned char mv[], int nmove) const;
  22.   int Play(const PlayWrite &play) const;
  23.  
  24. #ifndef NO_FILES
  25.   static int InitHFile(char *dname = 0);
  26.   static int HRead(FILE *f, PlayWrite *&play);
  27. protected:
  28.   int Print(const char *str) const;
  29. #endif
  30.  
  31.   int Hid;
  32.  
  33.   static int NHid;
  34. protected:
  35.   struct TStr
  36.   {
  37.     TStr(const char *ss = 0) : s(0) {(*this) = ss;}
  38.     TStr(const TStr &ss) : s(0) {(*this) = ss.s;}
  39.     ~TStr() {(*this) = 0;}
  40.  
  41.     TStr &operator=(const char *ss);
  42.     TStr &operator=(const TStr &ss) {return (*this) = ss.s;}
  43.  
  44.     operator char*() {return s;}
  45.     operator const char*() const {return s;}
  46.     char &operator*() {return *s;}
  47.     const char &operator*() const {return *s;}
  48.     char &operator[](int i) {return s[i];}
  49.     const char &operator[](int i) const {return s[i];}
  50.     void Extend(int n);
  51.  
  52.     friend int operator==(const TStr &s1, const TStr &s2)
  53.         {return strcmp(s1, s2) == 0;}
  54.     friend int operator==(const char *s1, const TStr &s2)
  55.         {return strcmp(s1, s2) == 0;}
  56.     friend int operator==(const TStr &s1, const char *s2)
  57.         {return strcmp(s1, s2) == 0;}
  58.     friend int operator!=(const TStr &s1, const TStr &s2)
  59.         {return strcmp(s1, s2) != 0;}
  60.     friend int operator!=(const char *s1, const TStr &s2)
  61.         {return strcmp(s1, s2) != 0;}
  62.     friend int operator!=(const TStr &s1, const char *s2)
  63.         {return strcmp(s1, s2) != 0;}
  64.     friend int operator>=(const TStr &s1, const TStr &s2)
  65.         {return strcmp(s1, s2) >= 0;}
  66.     friend int operator>=(const char *s1, const TStr &s2)
  67.         {return strcmp(s1, s2) >= 0;}
  68.     friend int operator>=(const TStr &s1, const char *s2)
  69.         {return strcmp(s1, s2) >= 0;}
  70.     friend int operator<=(const TStr &s1, const TStr &s2)
  71.         {return strcmp(s1, s2) <= 0;}
  72.     friend int operator<=(const char *s1, const TStr &s2)
  73.         {return strcmp(s1, s2) <= 0;}
  74.     friend int operator<=(const TStr &s1, const char *s2)
  75.         {return strcmp(s1, s2) <= 0;}
  76.     friend int operator>(const TStr &s1, const TStr &s2)
  77.         {return strcmp(s1, s2) > 0;}
  78.     friend int operator>(const char *s1, const TStr &s2)
  79.         {return strcmp(s1, s2) > 0;}
  80.     friend int operator>(const TStr &s1, const char *s2)
  81.         {return strcmp(s1, s2) > 0;}
  82.     friend int operator<(const TStr &s1, const TStr &s2)
  83.         {return strcmp(s1, s2) < 0;}
  84.     friend int operator<(const char *s1, const TStr &s2)
  85.         {return strcmp(s1, s2) < 0;}
  86.     friend int operator<(const TStr &s1, const char *s2)
  87.         {return strcmp(s1, s2) < 0;}
  88.  
  89.     char *s;
  90.   };
  91.  
  92.   class THash
  93.   {
  94.   public:
  95.     void init(int _m);
  96.     int operator()(const TStr &str) const;
  97.   protected:
  98.     int m;
  99.     int K[16];
  100.   };
  101.  
  102.   struct TTableItem
  103.   {
  104.     TTableItem(const char *s = 0, int k = 0) : str(s), k(k) {}
  105.     TTableItem(const TStr &s, int k = 0) : str(s), k(k) {}
  106.     TTableItem(const TTableItem &t) : str(t.str), k(t.k) {}
  107.  
  108.     operator TStr&() {return str;}
  109.     operator const TStr&() const {return str;}
  110.  
  111.     TStr str;
  112.     int k;
  113.   };
  114. };
  115.  
  116. #ifndef NO_FILES
  117. char THistory::FileName[1024] = "history.che";
  118. #endif
  119. int THistory::NHid = 0;
  120.  
  121. #ifndef NO_FILES
  122. int THistory::Print(const char *str) const
  123. {
  124.   char *line = new char[30 + strlen(str)];
  125.   if (!line) return 0;
  126.   unsigned long pr_id = GetProcessId();
  127.   if (Hid == -1) sprintf(line, "%lu  %s\n", pr_id, str);
  128.   else if (Hid < 0) sprintf(line, "%lu%c  %s\n", pr_id, (char)Hid, str);
  129.   else sprintf(line, "%lu:%d  %s\n", pr_id, Hid, str);
  130.   FILE *f = fopen(FileName, "at");
  131.   if (!f)
  132.   {
  133.     clock_t cc = clock();
  134.     do {f = fopen(FileName, "at");}
  135.     while(!f && (clock() - cc) <= 0.05 * CLOCKS_PER_SEC);
  136.   }
  137.   if (!f) {delete[] line; return 0;}
  138.   fputs(line, f);
  139.   fclose(f);
  140.   delete[] line;
  141.   return 1;
  142. }
  143. #endif
  144.  
  145. int THistory::Start(const Position &pos) const
  146. {
  147. #ifndef NO_FILES
  148.   char str[20 + NUM_CELL] = "Start ";
  149.   if (!pos.Write(str + strlen(str), 1)) return 0;
  150.   if (!Print(str)) return 0;
  151. #endif
  152.   return 1;
  153. }
  154.  
  155. int THistory::Move(const Position &pos, const unsigned char mv[], int nmove) const
  156. {
  157. #ifndef NO_FILES
  158.   char *str = new char[15 + pos.GetLenMvEx(mv, 11)];
  159.   if (!str) return 0;
  160.   sprintf(str, "%d.%s ", (nmove + 1) / 2, (nmove % 2 == 0) ? ".." : "");
  161.   pos.WriteMvEx(mv, str + strlen(str), 11);
  162.   if (!Print(str)) {delete[] str; return 0;}
  163.   delete[] str;
  164. #endif
  165.   return 1;
  166. }
  167.  
  168. int THistory::Play(const PlayWrite &play) const
  169. {
  170.   if (play.GetN() <= 0) return 0;
  171.   Position pos;
  172.   if (play.GetPos(pos, 0) < 0) return 0;
  173.   if (!Start(pos)) return 0;
  174.   int i;
  175.   unsigned char mv[NUM_CELL];
  176.   for (i = 1; i < play.GetN(); i++)
  177.   {
  178.     if (play.GetPos(pos, i - 1) < 0) return 0;
  179.     if (play.GetMove(mv, i) < 0) return 0;
  180.     if (!Move(pos, mv, i)) return 0;
  181.   }
  182.   return 1;
  183. }
  184.  
  185. #ifndef NO_FILES
  186. int THistory::InitHFile(char *dname)
  187. {
  188.   if (dname && dname[0])
  189.   {
  190.     char fnm[1024];
  191.     strcpy(fnm, dname);
  192.     int i;
  193.     for (i = strlen(fnm) - 1; i >= 0; i--)
  194.     {
  195.       if (fnm[i] == DIR_SEPARATOR) break;
  196.     }
  197.     if (i >= 0)
  198.     {
  199.       strcpy(fnm + i + 1, FileName);
  200.       strcpy(FileName, fnm);
  201.     }
  202.   }
  203.   int e = 1;
  204.   FILE *f = fopen(FileName, "rt");
  205.   if (f) {e = feof(f); fclose(f);}
  206.   if (!e) return 0;
  207.   f = fopen(FileName, "wt");
  208.   if (!f) return -1;
  209.   fputs("checkers-history_1.1\n", f);
  210.   fclose(f);
  211.   return 1;
  212. }
  213. #endif
  214.  
  215. THistory::TStr &THistory::TStr::operator=(const char *ss)
  216. {
  217.   if (s) delete[] s;
  218.   if (ss)
  219.   {
  220.     s = new char[strlen(ss) + 1];
  221.     strcpy(s, ss);
  222.   }
  223.   else s = 0;
  224.   return *this;
  225. }
  226.  
  227. void THistory::TStr::Extend(int n)
  228. {
  229.   if (n <= 0) {(*this) = 0; return;}
  230.   char *ss = s;
  231.   s = new char[n+1];
  232.   if (ss)
  233.   {
  234.     strncpy(s, ss, n);
  235.     s[n] = 0;
  236.     delete[] ss;
  237.   }
  238.   else s[0] = 0;
  239. }
  240.  
  241. void THistory::THash::init(int _m)
  242. {
  243.   m = _m;
  244.   for (int i = 0; i < 16; i++)
  245.   {
  246.     K[i] = (2*random(32767) + 1) & ((1 << m) - 1);
  247.   }
  248. }
  249.  
  250. int THistory::THash::operator()(const TStr &str) const
  251. {
  252.   int i, r = 0;
  253.   const char *s = str;
  254.   for (i = 0; *s; i = (i+1) & 15) r += *(s++) * K[i];
  255.   r &= (1 << m) - 1;
  256.   return r;
  257. }
  258.  
  259. #ifndef NO_FILES
  260. int THistory::HRead(FILE *f, PlayWrite *&play)
  261. {
  262.   const int MAX_INP_WORD = 100;
  263.   int nplay = 0, mplay = 10;
  264.   play = new PlayWrite[mplay];
  265.   THashTable<TTableItem, TStr, THash> table;
  266.   TStr word;
  267.   char inp_word[MAX_INP_WORD + 1];
  268.   int r, maxword = 0;
  269.   unsigned char ch;
  270.   int i, k = 0, kind = 0, wasspace = 1, nmove = 0;
  271.   for (;;)
  272.   {
  273.     r = (fread(&ch, 1, 1, f) == 1);
  274.     if (!r || isspace(ch))
  275.     {
  276.       if (!wasspace)
  277.       {
  278.         if (kind == 0) kind = 1;
  279.         else if (kind == 2)
  280.         {
  281.           for (i = 0; inp_word[i]; i++)
  282.           {
  283.             inp_word[i] = (char)tolower((unsigned char)inp_word[i]);
  284.           }
  285.           if (strcmp(inp_word, "start") == 0) kind = 5;
  286.           else kind = -1;
  287.           inp_word[0] = 0; k = 0;
  288.         }
  289.         else if (kind == 3)
  290.         {
  291.           nmove *= 2;
  292.           if (k <= 1) nmove--;
  293.           inp_word[0] = 0;
  294.           k = 0; kind = 4;
  295.         }
  296.         else if (kind == 4)
  297.         {
  298.           TTableItem *n_pl = table.find(word);
  299.           if (!n_pl) kind = -1;
  300.           else if (nmove < 1 || nmove > play[n_pl->k].GetN()) kind = -1;
  301.           else
  302.           {
  303.             PlayWrite::PMv pmv;
  304.             if (play[n_pl->k].GetPos(pmv.pos, nmove - 1) < 0) kind = -1;
  305.             else if (!pmv.pos.ReadMv(pmv.mv, inp_word, 1)) kind = -1;
  306.             else
  307.             {
  308.               play[n_pl->k].ClearFrom(nmove);
  309.               if (play[n_pl->k].Add(pmv.mv) != 0) kind = -1;
  310.               else {k = n_pl->k; kind = 11;}
  311.             }
  312.           }
  313.         }
  314.         else if (kind == 5)
  315.         {
  316.           Position pos;
  317.           pos.Read(inp_word, 1);
  318.           if (pos.IsNull()) kind = -1;
  319.           else
  320.           {
  321.             TTableItem *n_pl = table.find(word);
  322.             if (!n_pl)
  323.             {
  324.               table.push(TTableItem(word, nplay));
  325.               n_pl = table.find(word);
  326.             }
  327.             if (!n_pl) kind = -1;
  328.             else
  329.             {
  330.               if (nplay >= mplay)
  331.               {
  332.                 PlayWrite *play0 = play;
  333.                 int mplay0 = mplay;
  334.                 mplay = 2*nplay + 3;
  335.                 play = new PlayWrite[mplay];
  336.                 if (play0)
  337.                 {
  338.                   for (i = 0; i < mplay0; i++) play[i] = play0[i];
  339.                   delete[] play0;
  340.                 }
  341.               }
  342.               n_pl->k = nplay++;
  343.               play[n_pl->k].Add(0, pos);
  344.               k = n_pl->k; kind = 12;
  345.             }
  346.           }
  347.         }
  348.       }
  349.       if (!r || ch == '\n' || ch == '\r')
  350.       {
  351.         k = 0;
  352.         kind = 0;
  353.         if (!r) break;
  354.       }
  355.       wasspace = 1;
  356.     }
  357.     else
  358.     {
  359.       if (kind == 0)
  360.       {
  361.         if (k >= maxword) word.Extend(2*k + 3);
  362.         word[k++] = ch;
  363.         word[k] = 0;
  364.       }
  365.       else if (kind == 1)
  366.       {
  367.         if (isdigit(ch)) {nmove = ch - '0'; k = 0; kind = 3;}
  368.         else
  369.         {
  370.           inp_word[0] = ch;
  371.           inp_word[1] = 0;
  372.           k = 1; kind = 2;
  373.         }
  374.       }
  375.       else if (kind == 2 || kind == 4 || kind == 5)
  376.       {
  377.         if (k < MAX_INP_WORD)
  378.         {
  379.           inp_word[k++] = ch;
  380.           inp_word[k] = 0;
  381.         }
  382.       }
  383.       else if (kind == 3)
  384.       {
  385.         if (k == 0 && isdigit(ch)) nmove = 10 * nmove + ch - '0';
  386.         else if (ch == '.') k++;
  387.         else kind = -1;
  388.       }
  389.       wasspace = 0;
  390.     }
  391.   }
  392.   return nplay;
  393. }
  394. #endif
  395.  
  396. #endif  //_HEADER_HISTORY_H
  397.