Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | 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
#ifndef __MENUET__
5
#include 
6
#include 
7
#include 
8
#include 
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 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