Subversion Repositories Kolibri OS

Rev

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