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_POSITION_H
2
#define _HEADER_POSITION_H
3
 
4
#ifndef __MENUET__
5
#include 
6
#include 
7
#include 
8
#include 
9
#endif
10
 
11
#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
12
 
13
const int NW_CELL = 8;
14
 
15
const int NUM_CELL = NW_CELL * NW_CELL / 2;
16
const int LEN_WPOS = (NUM_CELL + 2) / 3;
17
 
18
inline int PoleCpos(int i, int j)
19
{
20
  return (i + j) % 2 != 0;
21
}
22
 
23
inline int PoleToNum(int i, int j)
24
{
25
  return j * (NW_CELL / 2) + i/2;
26
}
27
 
28
inline void NumToPole(int k, int &i, int &j)
29
{
30
  j = k / (NW_CELL / 2);
31
  i = k % (NW_CELL / 2);
32
  i *= 2;
33
  if (j % 2 == 0) i++;
34
}
35
 
36
class Position
37
{
38
public:
39
  char SH[NUM_CELL];
40
  char wmove;
41
 
42
  Position() {Init();}
43
  Position(const Position &p);
44
  Position& operator=(const Position &p);
45
 
46
  void Init();
47
  int IsNull() const;
48
  void Add(int np, char sh) {SH[np] = sh;}
49
  void Del(int np) {SH[np] = 0;}
50
  void Move(int np0, int np1) {if (np0 != np1) {SH[np1] = SH[np0]; SH[np0] = 0;}}
51
  static int BecameD(int np, char ch);
52
 
53
  enum {AWrong = -1, AWColor = -2, AfCell = -3, AnfCell = -4,
54
        AMustEatMore = -5, AMustEat = -6, ANoMove = -7, AChBack = -8,
55
        ANotDm = -9, AOnlyDiag = -10, AEatYour = -11, AMoreOne = -12,
56
        ANotDmE = -13, AMustEatMoreD = -14, ATurnBack = -15};
57
 
58
  int ScanSide(int x, int y, int sx, int sy, int sh_k = -1) const;
59
  int CanEat(int k, int psx = 0, int psy = 0, int sh_k = -1) const;
60
  int CanMove(int k) const;
61
  int AChCell(int k);
62
  int AMove(const unsigned char MV[], int k = -1, int &mkmove = *(int*)0);
63
  int AllCanEat(int w = -1) const;
64
  int AllCanMove(int w = -1) const;
65
 
66
  char *Write(char WP[], int how = 0) const;
67
  Position &Read(const char WP[], int how = 0);
68
  static char *WriteMv(const unsigned char mv[], char WP[], int how = 0);
69
  int WriteMvEx(const unsigned char mv[], char WP[], int how = 0) const;
70
  static unsigned char *ReadMv(unsigned char mv[], const char WP[], int how = 0);
71
  static int GetLenMv(const unsigned char mv[], int how = 0);
72
  int GetLenMvEx(const unsigned char mv[], int how = 0) const;
73
  static int GetLenMwr(const char WP[], int how = 0);
74
  static void SetNullMv(unsigned char mv[]) {mv[0] = 0;}
75
  void Reverse();
76
};
77
 
78
Position::Position(const Position &p) : wmove(p.wmove)
79
{
80
  for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i];
81
}
82
 
83
Position& Position::operator=(const Position &p)
84
{
85
  wmove = p.wmove;
86
  for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i];
87
  return *this;
88
}
89
 
90
void Position::Init()
91
{
92
  wmove = 0;
93
  for (int i = 0; i < NUM_CELL; i++) SH[i] = 0;
94
}
95
 
96
int Position::IsNull() const
97
{
98
  for (int i = 0; i < NUM_CELL; i++) if (SH[i] != 0) return 0;
99
  return 1;
100
}
101
 
102
inline int Position::BecameD(int np, char ch)
103
{
104
  int x, y;
105
  NumToPole(np, x, y);
106
  return ch == 1 && y == NW_CELL - 1 || ch == 2 && y == 0;
107
}
108
 
109
char *Position::Write(char WP[], int how) const
110
{
111
  if (how == 0)
112
  {
113
    int i = 0, j;
114
    for (j = 0; i < NUM_CELL; j++)
115
    {
116
      WP[j] = SH[i++];
117
      if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];}
118
      if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];}
119
      if (i >= NUM_CELL) {WP[j] *= (char)2; WP[j] += wmove;}
120
      WP[j]++;
121
    }
122
  }
123
  else if (how == 1)
124
  {
125
    int i;
126
    for (i = NUM_CELL - 1; i >= 0; i--)
127
    {
128
      if (SH[i] < 0 || SH[i] >= 5) return 0;
129
    }
130
    for (i = 0; i < NUM_CELL; i++)
131
    {
132
      const char SYMBOL[5] = {'0', 'R', 'B', 'X', 'Z'};
133
      WP[i] = SYMBOL[SH[NUM_CELL - 1 - i]];
134
    }
135
    WP[NUM_CELL] = ':';
136
    WP[NUM_CELL + 1] = (wmove == 0) ? 'r' : 'b';
137
    WP[NUM_CELL + 2] = 0;
138
  }
139
  return WP;
140
}
141
 
142
Position &Position::Read(const char WP[], int how)
143
{
144
  if (how == 0)
145
  {
146
    int i = 0, j, ii;
147
    for (j = 0; i < NUM_CELL; j++)
148
    {
149
      unsigned int cwp = WP[j] - 1;
150
      if (i >= NUM_CELL - 3)
151
      {
152
        wmove = char(cwp % 2);
153
        cwp /= 2;
154
        ii = NUM_CELL - 1;
155
      }
156
      else ii = i + 2;
157
      while(ii >= i) {SH[ii--] = char(cwp % 5); cwp /= 5;}
158
      i += 3;
159
    }
160
  }
161
  else if (how == 1)
162
  {
163
    int i;
164
    wmove = 0;
165
    for (i = 0; i < NUM_CELL; i++)
166
    {
167
      switch(WP[i])
168
      {
169
      case '0':
170
      case '-': case '.':
171
      case 'F': case 'f':
172
        SH[NUM_CELL - 1 - i] = 0;
173
        break;
174
      case '1':
175
      case 'A': case 'a':
176
      case 'R': case 'r':
177
        SH[NUM_CELL - 1 - i] = 1;
178
        break;
179
      case '2':
180
      case 'B': case 'b':
181
      case 'S': case 's':
182
        SH[NUM_CELL - 1 - i] = 2;
183
        break;
184
      case '3':
185
      case 'W': case 'w':
186
      case 'X': case 'x':
187
        SH[NUM_CELL - 1 - i] = 3;
188
        break;
189
      case '4':
190
      case 'Y': case 'y':
191
      case 'Z': case 'z':
192
        SH[NUM_CELL - 1 - i] = 4;
193
        break;
194
      default:
195
        Init();
196
        return *this;
197
      }
198
    }
199
    if (WP[NUM_CELL] == ':')
200
    {
201
      char c = WP[NUM_CELL + 1];
202
      if (c == 'B' || c == 'b' || c == 'S' || c == 's' ||
203
          c == 'Y' || c == 'y' || c == 'Z' || c == 'z')
204
      {
205
        wmove = 1;
206
      }
207
    }
208
  }
209
  return *this;
210
}
211
 
212
char *Position::WriteMv(const unsigned char mv[], char WP[], int how)
213
{
214
  int i, nmv = 0;
215
  if (mv) nmv = mv[0];
216
  if (how == 0)
217
  {
218
    WP[0] = char(nmv + 1);
219
    for (i = 1; i <= nmv; i++) WP[i] = char(mv[i] + 1);
220
  }
221
  else if (how == 1)
222
  {
223
    int j = 0;
224
    for (i = 1; i <= nmv; i++)
225
    {
226
      int x, y;
227
      NumToPole(mv[i], x, y);
228
      WP[j++] = char('a' + NW_CELL - 1 - x);
229
      int r = sprintf(WP + j, "%d", 1 + y);
230
      if (r > 0) j += r;
231
      if (i != nmv) WP[j++] = '-';
232
    }
233
    WP[j] = 0;
234
  }
235
  return WP;
236
}
237
 
238
unsigned char *Position::ReadMv(unsigned char mv[], const char WP[], int how)
239
{
240
  int i;
241
  if (how == 0)
242
  {
243
    mv[0] = char(WP[0] - 1);
244
    for (i = 1; i <= mv[0]; i++) mv[i] = char(WP[i] - 1);
245
  }
246
  else if (how == 1)
247
  {
248
    int j = 0, x = -1, y = -1;
249
    mv[0] = 0;
250
    for (;;)
251
    {
252
      if (isdigit(WP[j]))
253
      {
254
        y = atoi(WP + j) - 1;
255
        while (isdigit(WP[j])) j++;
256
      }
257
      else if (islower(WP[j])) x = NW_CELL - 1 - (WP[j++] - 'a');
258
      else
259
      {
260
        if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL)
261
        {
262
          mv[++mv[0]] = (char)PoleToNum(x, y);
263
        }
264
        else if (y >= 0 && y < NUM_CELL) mv[++mv[0]] = (char)(NUM_CELL - 1 - y);
265
        x = -1; y = -1;
266
        if (WP[j] == '-' || WP[j] == '*' || WP[j] == ':') j++;
267
        else break;
268
      }
269
      if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL)
270
      {
271
        mv[++mv[0]] = (char)PoleToNum(x, y);
272
        x = -1; y = -1;
273
      }
274
    }
275
  }
276
  return mv;
277
}
278
 
279
int Position::GetLenMv(const unsigned char mv[], int how)
280
{
281
  if (how == 0) return mv ? (1 + mv[0]) : 1;
282
  else if (how == 1)
283
  {
284
    int i, j = 0;
285
    if (!mv) return 1;
286
    for (i = 1; i <= mv[0]; i++)
287
    {
288
      int x, y;
289
      NumToPole(mv[i], x, y);
290
      j++; y++;
291
      while(y > 0) {j++; y /= 10;}
292
      if (i != mv[0]) j++;
293
    }
294
    return ++j;
295
  }
296
  else return 0;
297
}
298
 
299
int Position::GetLenMwr(const char WP[], int how)
300
{
301
  if (how == 0) return (unsigned char)WP[0];
302
  else if (how == 1)
303
  {
304
    int j;
305
    for (j = 0; WP[j] == '-' || WP[j] == '*' ||
306
                WP[j] == ':' || isdigit(j) || islower(j); j++);
307
    return j + 1;
308
  }
309
  else return 0;
310
}
311
 
312
inline int Position::GetLenMvEx(const unsigned char mv[], int how) const
313
{
314
  return WriteMvEx(mv, 0, how);
315
}
316
 
317
int Position::WriteMvEx(const unsigned char mv[], char WP[], int how) const
318
{
319
  if (how == 11)
320
  {
321
    Position pos = *this;
322
    int p, L = 0, was_d = 0;
323
    for (p = 1; p <= mv[0]; p++)
324
    {
325
      if (!was_d && pos.SH[mv[p]] > 2)
326
      {
327
        if (WP) WP[L] = '*';
328
        L++;
329
        was_d = 1;
330
      }
331
      int x0, y0, x1, y1;
332
      NumToPole(mv[p], x0, y0);
333
      if (WP)
334
      {
335
        WP[L++] = char('a' + NW_CELL - 1 - x0);
336
        int r = sprintf(WP + L, "%d", 1 + y0);
337
        if (r > 0) L += r;
338
      }
339
      else
340
      {
341
        L++;
342
        int g = y0 + 1;
343
        while(g > 0) {L++; g /= 10;}
344
      }
345
      if (p >= mv[0]) break;
346
      NumToPole(mv[p+1], x1, y1);
347
      int mi = abs(x1 - x0), i, eat = -1;
348
      if (mi > 0 && mi == abs(y1 - y0))
349
      {
350
        int sx = (x1 > x0) ? 1 : -1;
351
        int sy = (y1 > y0) ? 1 : -1;
352
        for (i = 1; i < mi; i++)
353
        {
354
          int r = PoleToNum(x0 + i * sx, y0 + i * sy);
355
          if (pos.SH[r] != 0)
356
          {
357
            eat = r;
358
            pos.Del(r);
359
          }
360
        }
361
      }
362
      if (WP) WP[L] = (eat >= 0) ? ':' : '-';
363
      L++;
364
      if (pos.SH[mv[p]] == 1 && y1 == NW_CELL - 1) pos.SH[mv[p]] = 3;
365
      else if (pos.SH[mv[p]] == 2 && y1 == 0) pos.SH[mv[p]] = 4;
366
      pos.Move(mv[p], mv[p+1]);
367
    }
368
    if (WP) WP[L] = 0;
369
    L++;
370
    return L;
371
  }
372
  else
373
  {
374
    if (WP) WriteMv(mv, WP, how);
375
    return GetLenMv(mv, how);
376
  }
377
}
378
 
379
int Position::ScanSide(int x, int y, int sx, int sy, int sh_k) const
380
{
381
  if (sh_k < 0) sh_k = SH[PoleToNum(x, y)];
382
  if (sh_k < 1 || sh_k > 4) return -2;
383
  if (sh_k >= 2) sh_k -= 2;
384
  int i, i0, i1, f = 0, g = 0;
385
  if (sx < 0) i0 = x;
386
  else i0 = NW_CELL - x - 1;
387
  if (sy < 0) i1 = y;
388
  else i1 = NW_CELL - y - 1;
389
  if (i0 > i1) i0 = i1;
390
  for (i = 1; i <= i0; i++)
391
  {
392
    char nk = SH[PoleToNum(x + i*sx, y + i*sy)];
393
    if (nk)
394
    {
395
      if (f || (nk != 3 - sh_k && nk != 5 - sh_k)) return g;
396
      else f = 1;
397
    }
398
    else if (f) return (i == 2) ? 4 : (2 + g);
399
    else if (i == 1) g = 1;
400
  }
401
  return g;
402
}
403
 
404
int Position::CanEat(int k, int psx, int psy, int sh_k) const
405
{
406
  int x, y, sx, sy;
407
  if (sh_k < 0) sh_k = SH[k];
408
  if (sh_k < 1 || sh_k > 6) return 0;
409
  NumToPole(k, x, y);
410
  if (sh_k > 4)
411
  {
412
    int i, i0, i1, f = 0;
413
    if (-psx < 0) i0 = x;
414
    else i0 = NW_CELL - x - 1;
415
    if (-psy < 0) i1 = y;
416
    else i1 = NW_CELL - y - 1;
417
    if (i0 > i1) i0 = i1;
418
    for (i = 1; i <= i0; i++)
419
    {
420
      int nk = SH[PoleToNum(x - i*psx, y - i*psy)];
421
      if (nk)
422
      {
423
        if (f || (nk != 7 - sh_k && nk != 9 - sh_k)) break;
424
        else f = 1;
425
      }
426
      else
427
      {
428
        if (f) return 1;
429
        if (ScanSide(x - i*psx, y - i*psy, psy, -psx, sh_k-2) >= 2) return 1;
430
        if (ScanSide(x - i*psx, y - i*psy, -psy, psx, sh_k-2) >= 2) return 1;
431
      }
432
    }
433
  }
434
  else for (sx = -1; sx <= 1; sx += 2) if (x + 2*sx >= 0 && x + 2*sx < NW_CELL)
435
  {
436
    for (sy = -1; sy <= 1; sy += 2)
437
    {
438
      if ((sx != psx || sy != psy) && y + 2*sy >= 0 && y + 2*sy < NW_CELL)
439
      {
440
        if (sh_k <= 2)
441
        {
442
          if (SH[PoleToNum(x + 2*sx, y + 2*sy)] == 0)
443
          {
444
            int nk = SH[PoleToNum(x + sx, y + sy)];
445
            if (nk == 3 - sh_k || nk == 5 - sh_k) return 1;
446
          }
447
        }
448
        else if (ScanSide(x, y, sx, sy, sh_k) >= 2) return 1;
449
      }
450
    }
451
  }
452
  return 0;
453
}
454
 
455
int Position::CanMove(int k) const
456
{
457
  int x, y, xx, yy, y1, y2;
458
  NumToPole(k, x, y);
459
  if (SH[k] == 1) y1 = y2 = y + 1;
460
  else if (SH[k] == 2) y1 = y2 = y - 1;
461
  else if (SH[k] != 3 && SH[k] != 4) return 0;
462
  else {y1 = y - 1; y2 = y + 1;}
463
  for (yy = y1; yy <= y2; yy += 2) if (yy >= 0 && yy < NW_CELL)
464
  {
465
    for (xx = x - 1; xx <= x + 1; xx += 2) if (xx >= 0 && xx < NW_CELL)
466
    {
467
      if (SH[PoleToNum(xx, yy)] == 0) return 1;
468
    }
469
  }
470
  return 0;
471
}
472
 
473
int Position::AChCell(int k)
474
{
475
  if (k < 0 || k >= NUM_CELL) return AWrong;
476
  if (SH[k] == 0) return AfCell;
477
  if (SH[k] != 1 + wmove && SH[k] != 3 + wmove) return AWColor;
478
  if (CanEat(k)) return 1;
479
  if (AllCanEat()) return AMustEat;
480
  if (CanMove(k)) return 1;
481
  return ANoMove;
482
}
483
 
484
int Position::AMove(const unsigned char MV[], int k, int &mkmove)
485
{
486
  if (k >= NUM_CELL) return AWrong;
487
  if (MV[0] <= 0)
488
  {
489
    if (k < 0) return NUM_CELL;
490
    int s = AChCell(k);
491
    if (s < 0) return s;
492
    else return NUM_CELL;
493
  }
494
  if (MV[0] == 1 && k < 0)
495
  {
496
    int s = AChCell(MV[1]);
497
    if (s < 0) return s;
498
    else return NUM_CELL;
499
  }
500
  if (SH[MV[1]] == 0) return AfCell;
501
  if (SH[MV[1]] != 1 + wmove && SH[MV[1]] != 3 + wmove) return AWColor;
502
  int i, mi, p, MV_L, MV_N = MV[0], eat = -1, r;
503
  int psx = 0, psy = 0;
504
  if (k >= 0) MV_N++;
505
  Position pos = *this;
506
  for (p = 1; p < MV_N; p++)
507
  {
508
    int x0, y0, x1, y1, i_eat;
509
    if (p < MV[0]) MV_L = MV[p+1];
510
    else if (k < 0) break;
511
    else MV_L = k;
512
    if (pos.SH[MV_L] != 0) return AnfCell;
513
    NumToPole(MV[p], x0, y0);
514
    NumToPole(MV_L, x1, y1);
515
    mi = abs(x1 - x0);
516
    if (mi <= 0 || mi != abs(y1 - y0)) return AOnlyDiag;
517
    int sx = (x1 > x0) ? 1 : -1;
518
    int sy = (y1 > y0) ? 1 : -1;
519
    if (sx == psx && sy == psy) return ATurnBack;
520
    psx = -sx; psy = -sy;
521
    eat = -1; i_eat = -1;
522
    for (i = 1; i < mi; i++)
523
    {
524
      r = PoleToNum(x0 + i * sx, y0 + i * sy);
525
      if (pos.SH[r] != 0)
526
      {
527
        if (eat >= 0) return AMoreOne;
528
        if (pos.SH[r] != 2 - wmove && pos.SH[r] != 4 - wmove) return AEatYour;
529
        eat = r; i_eat = i;
530
        pos.Del(r);
531
      }
532
    }
533
    if (eat >= 0)
534
    {
535
      if (pos.SH[MV[p]] <= 2 && mi != 2) return ANotDmE;
536
    }
537
    else
538
    {
539
      if (MV_N > 2) return AMustEatMore;
540
      if (pos.SH[MV[p]] <= 2)
541
      {
542
        if (mi != 1) return ANotDm;
543
        if (wmove == 0 && y1 < y0 || wmove == 1 && y1 > y0) return AChBack;
544
      }
545
      if (AllCanEat()) return AMustEat;
546
    }
547
    if (i_eat >= 0 && pos.SH[MV[p]] > 2)
548
    {
549
      if (!pos.CanEat(MV_L, psx, psy, pos.SH[MV[p]]))
550
      {
551
        if (pos.CanEat(PoleToNum(x0 + i_eat*sx, y0 + i_eat*sy),
552
                                 psx, psy, pos.SH[MV[p]] + 2))
553
        {
554
          return AMustEatMoreD;
555
        }
556
      }
557
    }
558
    if (wmove == 0 && y1 == NW_CELL - 1) pos.SH[MV[p]] = 3;
559
    else if (wmove == 1 && y1 == 0) pos.SH[MV[p]] = 4;
560
    pos.Move(MV[p], MV_L);
561
  }
562
  if (&mkmove)
563
  {
564
    int end = MV_N > 1 && (eat < 0 || !pos.CanEat(MV_L, psx, psy));
565
    if (mkmove == 1 && end)
566
    {
567
      *this = pos;
568
      wmove = !wmove;
569
    }
570
    if (end) mkmove = 0;
571
    else
572
    {
573
      if (MV_N > 1 && eat >= 0) mkmove = AMustEatMore;
574
      else mkmove = AWrong;
575
    }
576
  }
577
  if (k < 0 || eat < 0) eat = NUM_CELL;
578
  return eat;
579
}
580
 
581
int Position::AllCanEat(int w) const
582
{
583
  int k;
584
  if (w < 0) w = wmove;
585
  for (k = 0; k < NUM_CELL; k++)
586
  {
587
    if ((SH[k] == w+1 || SH[k] == w+3) && CanEat(k)) return 1;
588
  }
589
  return 0;
590
}
591
 
592
int Position::AllCanMove(int w) const
593
{
594
  int k;
595
  if (w < 0) w = wmove;
596
  for (k = 0; k < NUM_CELL; k++)
597
  {
598
    if ((SH[k] == w+1 || SH[k] == w+3) && CanMove(k)) return 1;
599
  }
600
  return 0;
601
}
602
 
603
void Position::Reverse()
604
{
605
  int i;
606
  for (i = 0; i <= (NUM_CELL-1) / 2; i++)
607
  {
608
    int sh1 = SH[i], sh2 = SH[NUM_CELL - 1 - i];
609
    if (sh1 == 1) sh1 = 2;
610
    else if (sh1 == 2) sh1 = 1;
611
    else if (sh1 == 3) sh1 = 4;
612
    else if (sh1 == 4) sh1 = 3;
613
    if (sh2 == 1) sh2 = 2;
614
    else if (sh2 == 2) sh2 = 1;
615
    else if (sh2 == 3) sh2 = 4;
616
    else if (sh2 == 4) sh2 = 3;
617
    SH[i] = (char)sh2; SH[NUM_CELL - 1 - i] = (char)sh1;
618
  }
619
  wmove = !wmove;
620
}
621
 
622
 
623
class PlayWrite
624
{
625
public:
626
  PlayWrite() : play(0), mplay(0), nplay(0), start(0), mstart(0), nstart(0) {}
627
  PlayWrite(const PlayWrite &pl) : play(0), mplay(0), nplay(0),
628
               start(0), mstart(0), nstart(0) {(*this) = pl;}
629
  ~PlayWrite() {Clear();}
630
 
631
  void Clear();
632
  PlayWrite &operator=(const PlayWrite &pl);
633
  int GetN() const {return nstart - 1;}
634
  int GetLen() const {return nplay - sizeof(int);}
635
 
636
  struct PMv
637
  {
638
    Position pos;
639
    unsigned char mv[NUM_CELL];
640
  };
641
 
642
  void Add(const unsigned char move[], const Position &pos);
643
  void Add(const PMv &pmv) {Add(pmv.mv, pmv.pos);}
644
  int Add(const unsigned char move[]);
645
  int GetMove(unsigned char move[], int k) const;
646
  int GetPos(Position &pos, int k) const;
647
  int GetPMv(PMv &pmv, int k) const;
648
  int GetMoveL(unsigned char move[], int k = 0) const
649
              {return GetMove(move, nstart - 2 - k);}
650
  int GetPosL(Position &pos, int k = 0) const {return GetPos(pos, nstart - 2 - k);}
651
  int GetPMvL(PMv &pmv, int k = 0) const {return GetPMv(pmv, nstart - 2 - k);}
652
  int ClearFrom(int k = 0);
653
  int IsDraw(int nmove = -1);
654
protected:
655
  void IncPlay(int k);
656
  void IncStart(int k);
657
  void IncStart() {IncStart(nstart + 1);}
658
  void AddStart() {IncStart(); start[nstart++] = nplay;}
659
  void Split();
660
  void SplitClear();
661
protected:
662
  char *play;
663
  int *start;
664
  int mplay, nplay, mstart, nstart;
665
};
666
 
667
void PlayWrite::Clear()
668
{
669
  if (play)
670
  {
671
    if ((*(int*)play) > 0) (*(int*)play)--;
672
    else delete[] play;
673
  }
674
  play = 0; mplay = 0; nplay = 0;
675
  if (start)
676
  {
677
    if (start[0] > 0) start[0]--;
678
    else delete[] start;
679
  }
680
  start = 0; mstart = 0; nstart = 0;
681
}
682
 
683
void PlayWrite::Split()
684
{
685
  if (play && (*(int*)play) > 0)
686
  {
687
    (*(int*)play)--;
688
    char *play0 = play;
689
    mplay = nplay;
690
    play = new char[mplay];
691
    memcpy(play, play0, nplay * sizeof(play[0]));
692
    (*(int*)play) = 0;
693
  }
694
  if (start && start[0] > 0)
695
  {
696
    start[0]--;
697
    int *start0 = start;
698
    mstart = nstart;
699
    start = new int[mstart];
700
    memcpy(start, start0, nstart * sizeof(start[0]));
701
    start[0] = 0;
702
  }
703
}
704
 
705
void PlayWrite::SplitClear()
706
{
707
  if (play && (*(int*)play) > 0)
708
  {
709
    (*(int*)play)--;
710
    play = 0;
711
    nplay = 0; mplay = 0;
712
  }
713
  if (start && start[0] > 0)
714
  {
715
    start[0]--;
716
    start = 0;
717
    nstart = 0; mstart = 0;
718
  }
719
}
720
 
721
PlayWrite &PlayWrite::operator=(const PlayWrite &pl)
722
{
723
  if (&pl != this)
724
  {
725
    play = pl.play;
726
    (*(int*)play)++;
727
    nplay = pl.nplay; mplay = pl.mplay;
728
    start = pl.start;
729
    start[0]++;
730
    nstart = pl.nstart; mstart = pl.mstart;
731
  }
732
  return *this;
733
}
734
 
735
void PlayWrite::IncPlay(int k)
736
{
737
  if (mplay < k)
738
  {
739
    int m0 = mplay;
740
    char *play0 = play;
741
    mplay = 2*k + 10;
742
    play = new char[mplay];
743
    memcpy(play, play0, m0 * sizeof(play[0]));
744
    (*(int*)play) = 0;
745
    if (play0)
746
    {
747
      if ((*(int*)play0) > 0) (*(int*)play0)--;
748
      else delete[] play0;
749
    }
750
  }
751
}
752
 
753
void PlayWrite::IncStart(int k)
754
{
755
  if (mstart < k)
756
  {
757
    int m0 = mstart;
758
    int *start0 = start;
759
    mstart = 2*k + 10;
760
    start = new int[mstart];
761
    memcpy(start, start0, m0 * sizeof(start[0]));
762
    start[0] = 0;
763
    if (start0)
764
    {
765
      if (start0[0] > 0) start0[0]--;
766
      else delete[] start0;
767
    }
768
  }
769
}
770
 
771
void PlayWrite::Add(const unsigned char move[], const Position &pos)
772
{
773
  Split();
774
  int k = Position::GetLenMv(move);
775
  if (nstart < 1) nstart = 1;
776
  if (nplay < sizeof(int)) nplay = sizeof(int);
777
  AddStart();
778
  IncPlay(nplay + k + LEN_WPOS);
779
  Position::WriteMv(move, play + nplay, 0);
780
  nplay += k;
781
  pos.Write(play + nplay, 0);
782
  nplay += LEN_WPOS;
783
}
784
 
785
int PlayWrite::Add(const unsigned char move[])
786
{
787
  if (nstart <= 1) return 1;
788
  Position pos;
789
  GetPosL(pos);
790
  int mkmove = 1;
791
  int res = pos.AMove(move, -1, mkmove);
792
  if (res < 0) return res;
793
  else if (mkmove != 0) return mkmove;
794
  Add(move, pos);
795
  return 0;
796
}
797
 
798
int PlayWrite::GetMove(unsigned char move[], int k) const
799
{
800
  if (!play || !start) return -1;
801
  k++;
802
  if (k <= 0 || k >= nstart) return -1;
803
  Position::ReadMv(move, play + start[k], 0);
804
  return Position::GetLenMv(move);
805
}
806
 
807
int PlayWrite::GetPos(Position &pos, int k) const
808
{
809
  if (!play || !start) return -1;
810
  k++;
811
  if (k <= 0 || k >= nstart) return -1;
812
  int mlen = Position::GetLenMwr(play + start[k], 0);
813
  pos.Read(play + start[k] + mlen, 0);
814
  return LEN_WPOS;
815
}
816
 
817
int PlayWrite::GetPMv(PMv &pmv, int k) const
818
{
819
  if (!play || !start) return -1;
820
  k++;
821
  if (k <= 0 || k >= nstart) return -1;
822
  Position::ReadMv(pmv.mv, play + start[k], 0);
823
  int mlen = Position::GetLenMv(pmv.mv);
824
  pmv.pos.Read(play + start[k] + mlen, 0);
825
  return mlen + LEN_WPOS;
826
}
827
 
828
int PlayWrite::ClearFrom(int k)
829
{
830
  if (!play || !start) return 0;
831
  k++;
832
  if (k >= nstart) return 0;
833
  if (k <= 1) {Clear(); return 2;}
834
  nplay = start[k];
835
  nstart = k;
836
  return 1;
837
}
838
 
839
int PlayWrite::IsDraw(int nmove)
840
{
841
  nmove++;
842
  if (nmove <= 0 || nmove > nstart) nmove = nstart;
843
  if (!start || nmove <= 3) return 0;
844
  int i, j, k, draw = 0;
845
  for (i = 1; i < nmove; i++)
846
  {
847
    k = 1;
848
    char *p1 = play + start[i] + Position::GetLenMwr(play + start[i], 0);
849
    for (j = 1; j < i; j++)
850
    {
851
      char *p2 = play + start[j] + Position::GetLenMwr(play + start[j], 0);
852
      if (memcmp(p1, p2, LEN_WPOS) == 0) k++;
853
    }
854
    if (k >= 3) {draw = 1; break;}
855
  }
856
  return draw;
857
}
858
 
859
 
860
class TChPlayer
861
{
862
public:
863
  TChPlayer() {}
864
 
865
  typedef struct PlayWrite::PMv PMv;
866
 
867
  virtual int PlayerID() {return 0;}
868
  virtual int Move(PMv &pmv) = 0;
869
 
870
  int Move(Position &pos, char mv[]);
871
};
872
 
873
int TChPlayer::Move(Position &pos, char mv[])
874
{
875
  PMv pmv;
876
  pmv.pos = pos; memcpy(pmv.mv, mv, sizeof(pmv.mv));
877
  int res = Move(pmv);
878
  pos = pmv.pos; memcpy(mv, pmv.mv, sizeof(pmv.mv));
879
  return res;
880
}
881
 
882
#endif  //_HEADER_POSITION_H