Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1805 yogev_ezra 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
{
5123 clevermous 10
#ifndef NO_FILES
1805 yogev_ezra 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
 
5123 clevermous 24
#ifndef NO_FILES
1805 yogev_ezra 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
 
5123 clevermous 116
#ifndef NO_FILES
1805 yogev_ezra 117
char THistory::FileName[1024] = "history.che";
118
#endif
119
int THistory::NHid = 0;
120
 
5123 clevermous 121
#ifndef NO_FILES
1805 yogev_ezra 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
{
5123 clevermous 147
#ifndef NO_FILES
1805 yogev_ezra 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
{
5123 clevermous 157
#ifndef NO_FILES
1805 yogev_ezra 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;}
5123 clevermous 163
  delete[] str;
1805 yogev_ezra 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
 
5123 clevermous 185
#ifndef NO_FILES
1805 yogev_ezra 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
 
5123 clevermous 259
#ifndef NO_FILES
1805 yogev_ezra 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 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