Subversion Repositories Kolibri OS

Rev

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

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