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_PLAYER_H
2
#define _HEADER_PLAYER_H
3
 
4
#include "position.h"
5
#include "sysproc.h"
6
#ifndef __MENUET__
7
#include 
8
#include 
9
#include 
10
#endif
11
 
12
template 
13
class TBaseCompPlayer : public TChPlayer
14
{
15
public:
16
  static const int PKind;
17
  static const tvalue win_val;
18
public:
19
  TBaseCompPlayer() : draw(0), data(0) {}
20
 
21
  virtual int PlayerID() {return PKind;}
22
  virtual int Move(PMv &pmv);
23
 
24
  struct PMvv : public PMv
25
  {
26
    tvalue val;
27
  };
28
 
29
  struct Z
30
  {
31
    Z(int marr = 400) : narr(0), marr(marr) {array = new PMvv[marr];}
32
    ~Z() {Clear();}
33
 
34
    void Clear() {if (array) {delete[] array; array = 0;} marr = 0; narr = 0;}
35
    void AddPos(int n);
36
    void AddPos() {AddPos(narr + 1);}
37
    int FindAllMoves(PMv pmv, int onlyeat = 0);
38
    void FindSideEats(PMv &pmv, int k, int sx, int sy);
39
 
40
    static int ComparePMv(const void *v1, const void *v2);
41
    void Sort(int n0, int n1);
42
 
43
    int marr, narr;
44
    PMvv *array;
45
  };
46
 
47
  static tvalue GetLossValue(const Position &pos);
48
  virtual tvalue GetValue(const Position &pos, int num = 0);
49
  tvalue GetFullValue(const Position &pos, int num = 0);
50
  tvalue FindBMove(Z &z, int num, PMvv *pmv, int zn = -1,
51
                tvalue a = -2 * win_val, tvalue b = 2 * win_val);
52
public:
4652 ashmew2 53
  void (*draw)(void*, int ); //draw() wants int = 0 as a default argument
1805 yogev_ezra 54
  void *data;
55
};
56
 
57
template 
58
const int TBaseCompPlayer::PKind = 0x2000;
59
 
60
template 
61
const tvalue TBaseCompPlayer::win_val = (tvalue)10000000L;
62
 
63
template 
64
void TBaseCompPlayer::Z::AddPos(int n)
65
{
66
  if (marr < n)
67
  {
68
     int m0 = marr;
69
     PMvv *arr0 = array;
70
     marr = 2*n + 10;
71
     array = new PMvv[marr];
72
     if (arr0)
73
     {
74
       int i;
75
       for (i = 0; i < m0; i++) array[i] = arr0[i];
76
       delete[] arr0;
77
     }
78
  }
79
}
80
 
81
template 
82
void TBaseCompPlayer::Z::FindSideEats(PMv &pmv, int k, int sx, int sy)
83
{
84
  int x, y;
85
  NumToPole(k, x, y);
86
  if (pmv.pos.SH[k] == pmv.pos.wmove + 1)
87
  {
88
    int xx = x + 2*sx, yy = y + 2*sy;
89
    if (xx >= 0 && xx < NW_CELL && yy >= 0 && yy < NW_CELL)
90
    {
91
      int kk = PoleToNum(xx, yy);
92
      if (pmv.pos.SH[kk] == 0)
93
      {
94
        int k1 = PoleToNum(x + sx, y + sy);
95
        char nk1 = pmv.pos.SH[k1];
96
        if (nk1 == 2 - pmv.pos.wmove || nk1 == 4 - pmv.pos.wmove)
97
        {
98
          char SH_k1 = pmv.pos.SH[k1];
99
          pmv.pos.Del(k1); pmv.pos.Move(k, kk);
100
          if (pmv.pos.wmove == 0 && yy == NW_CELL - 1 ||
101
              pmv.pos.wmove == 1 && yy == 0) pmv.pos.SH[kk] += (char)2;
102
          pmv.mv[++pmv.mv[0]] = (char)kk;
103
          int nold = narr;
104
          FindSideEats(pmv, kk, sx, sy);
105
          FindSideEats(pmv, kk, sy, -sx);
106
          FindSideEats(pmv, kk, -sy, sx);
107
          if (narr == nold)
108
          {
109
            AddPos();
110
            (PMv&)array[narr] = pmv;
111
            array[narr].pos.wmove = !pmv.pos.wmove;
112
            narr++;
113
          }
114
          pmv.mv[0]--;
115
          pmv.pos.SH[k1] = SH_k1; pmv.pos.Del(kk);
116
          pmv.pos.SH[k] = char(pmv.pos.wmove + 1);
117
        }
118
      }
119
    }
120
  }
121
  else if (pmv.pos.SH[k] == pmv.pos.wmove + 3)
122
  {
123
    int i, i0, i1;
124
    if (sx < 0) i0 = x;
125
    else i0 = NW_CELL - x - 1;
126
    if (sy < 0) i1 = y;
127
    else i1 = NW_CELL - y - 1;
128
    if (i0 > i1) i0 = i1;
129
    if (i0 >= 2)
130
    {
131
      pmv.pos.Del(k);
132
      pmv.mv[0]++;
133
      i1 = -1;
134
      int kk, kk1;
135
      char SH_kk1;
136
      int nold = narr;
137
      for (i = 1; i <= i0; i++)
138
      {
139
        kk = PoleToNum(x + i*sx, y + i*sy);
140
        char chh = pmv.pos.SH[kk];
141
        if (chh)
142
        {
143
          if (i1 >= 0 || (chh != 2 - pmv.pos.wmove && chh != 4 - pmv.pos.wmove)) break;
144
          else
145
          {
146
            i1 = i; kk1 = kk;
147
            SH_kk1 = chh;
148
            pmv.pos.Del(kk1);
149
          }
150
        }
151
        else if (i1 >= 0)
152
        {
153
          pmv.pos.SH[kk] = char(pmv.pos.wmove + 3);
154
          pmv.mv[pmv.mv[0]] = (char)kk;
155
          if (i == i1+1) FindSideEats(pmv, kk, sx, sy);
156
          FindSideEats(pmv, kk, sy, -sx);
157
          FindSideEats(pmv, kk, -sy, sx);
158
          pmv.pos.Del(kk);
159
        }
160
      }
161
      if (narr == nold && i1 >= 0)
162
      {
163
        while (--i > i1)
164
        {
165
          kk = PoleToNum(x + i*sx, y + i*sy);
166
          AddPos();
167
          (PMv&)array[narr] = pmv;
168
          array[narr].pos.SH[kk] = char(pmv.pos.wmove + 3);
169
          array[narr].mv[pmv.mv[0]] = (char)kk;
170
          array[narr].pos.wmove = !pmv.pos.wmove;
171
          narr++;
172
        }
173
      }
174
      pmv.mv[0]--;
175
      pmv.pos.SH[k] = char(pmv.pos.wmove + 3);
176
      if (i1 >= 0) pmv.pos.SH[kk1] = SH_kk1;
177
    }
178
  }
179
}
180
 
181
template 
182
int TBaseCompPlayer::Z::FindAllMoves(PMv pmv, int onlyeat)
183
{
184
  int k, nold = narr, was_eat = 1;
185
  pmv.mv[0] = 1;
186
  for (k = 0; k < NUM_CELL; k++)
187
  {
188
    if (pmv.pos.SH[k] == pmv.pos.wmove + 1 || pmv.pos.SH[k] == pmv.pos.wmove + 3)
189
    {
190
      pmv.mv[1] = (char)k;
191
      FindSideEats(pmv, k, 1, 1);
192
      FindSideEats(pmv, k, 1, -1);
193
      FindSideEats(pmv, k, -1, 1);
194
      FindSideEats(pmv, k, -1, -1);
195
    }
196
  }
197
  if (narr == nold)
198
  {
199
    was_eat = 0;
200
    if (!onlyeat)
201
    {
202
      pmv.mv[0] = 2;
203
      for (k = 0; k < NUM_CELL; k++)
204
      {
205
        if (pmv.pos.SH[k] == pmv.pos.wmove + 1)
206
        {
207
          pmv.mv[1] = (char)k;
208
          int x, x0, x1, y;
209
          NumToPole(k, x0, y);
210
          if (pmv.pos.wmove == 1) y--; else y++;
211
          if (y >= 0 && y < NW_CELL)
212
          {
213
            int kk;
214
            x1 = (x0--) + 1;
215
            for (x = x0; x <= x1; x += 2) if (x >= 0 && x < NW_CELL)
216
            {
217
              kk = PoleToNum(x, y);
218
              if (pmv.pos.SH[kk] == 0)
219
              {
220
                AddPos();
221
                (PMv&)array[narr] = pmv;
222
                array[narr].pos.Del(k);
223
                if (pmv.pos.wmove == 0 && y == NW_CELL - 1 ||
224
                    pmv.pos.wmove == 1 && y == 0)
225
                {
226
                  array[narr].pos.Add(kk, char(pmv.pos.wmove + 3));
227
                }
228
                else array[narr].pos.Add(kk, char(pmv.pos.wmove + 1));
229
                array[narr].mv[2] = (char)kk;
230
                array[narr].pos.wmove = !pmv.pos.wmove;
231
                narr++;
232
              }
233
            }
234
          }
235
        }
236
        else if (pmv.pos.SH[k] == pmv.pos.wmove + 3)
237
        {
238
          pmv.mv[1] = (char)k;
239
          int x, y, sx, sy;
240
          NumToPole(k, x, y);
241
          for (sx = -1; sx <= 1; sx += 2) if (x + sx >= 0 && x + sx < NW_CELL)
242
          {
243
            for (sy = -1; sy <= 1; sy += 2) if (y + sy >= 0 && y + sy < NW_CELL)
244
            {
245
              int i, i0, i1;
246
              if (sx < 0) i0 = x;
247
              else i0 = NW_CELL - x - 1;
248
              if (sy < 0) i1 = y;
249
              else i1 = NW_CELL - y - 1;
250
              if (i0 > i1) i0 = i1;
251
              for (i = 1; i <= i0; i++)
252
              {
253
                int kk = PoleToNum(x + i*sx, y + i*sy);
254
                if (pmv.pos.SH[kk]) break;
255
                AddPos();
256
                (PMv&)array[narr] = pmv;
257
                array[narr].pos.Move(k, kk);
258
                array[narr].mv[2] = (char)kk;
259
                array[narr].pos.wmove = !pmv.pos.wmove;
260
                narr++;
261
              }
262
            }
263
          }
264
        }
265
      }
266
    }
267
  }
268
  pmv.mv[0] = 0;
269
  return was_eat;
270
}
271
 
272
template 
273
int TBaseCompPlayer::Z::ComparePMv(const void *v1, const void *v2)
274
{
275
  PMvv *pmv1 = (PMvv*)v1, *pmv2 = (PMvv*)v2;
276
  if (pmv1->val < pmv2->val) return -1;
277
  else if (pmv1->val > pmv2->val) return 1;
278
  else return 0;
279
}
280
 
281
template 
282
void TBaseCompPlayer::Z::Sort(int n0, int n1)
283
{
284
  qsort(array + n0, n1 - n0, sizeof(PMvv), ComparePMv);
285
}
286
 
287
 
288
template 
289
tvalue TBaseCompPlayer::GetLossValue(const Position &pos)
290
{
291
  tvalue val = -win_val - 1000021L;
292
  for (int i = 0; i < NUM_CELL; i++)
293
  {
294
    if (pos.SH[i] == 1 + pos.wmove) val -= 10000L;
295
    else if (pos.SH[i] == 2 - pos.wmove) val -= 100L;
296
    else if (pos.SH[i] == 3 + pos.wmove) val -= 80000L;
297
    else if (pos.SH[i] == 4 - pos.wmove) val -= 100L;
298
  }
299
  return val;
300
}
301
 
302
template 
303
tvalue TBaseCompPlayer::GetValue(const Position &pos, int num)
304
{
305
  tvalue val = 0;
306
  if (num == 0)
307
  {
308
    int NumDM0 = 0, NumDM1 = 0;
309
    for (int i = 0; i < NUM_CELL; i++)
310
    {
311
      short PreimSHPos[32] = {243, 243, 243, 245,
312
                              240, 240, 240, 240,
313
                              244, 244, 244, 244,
314
                              245, 248, 248, 245,
315
                              249, 250, 250, 248,
316
                              256, 260, 260, 256,
317
                              280, 280, 280, 260,
318
                              280, 280, 280, 280};
319
      if (pos.SH[i] == 1 + pos.wmove)
320
      {
321
        val += PreimSHPos[pos.wmove ? (NUM_CELL - 1 - i) : i];
322
      }
323
      else if (pos.SH[i] == 2 - pos.wmove)
324
      {
325
        val -= PreimSHPos[pos.wmove ? i : (NUM_CELL - 1 - i)];
326
      }
327
      else if (pos.SH[i] == 3 + pos.wmove) NumDM1++;
328
      else if (pos.SH[i] == 4 - pos.wmove) NumDM0++;
329
    }
330
    if (NumDM1 > 0)
331
    {
332
      val += 560; NumDM1--;
333
      if (NumDM1 > 0)
334
      {
335
        val += 432; NumDM1--;
336
        val += NumDM1 * 384;
337
      }
338
    }
339
    if (NumDM0 > 0)
340
    {
341
      val -= 560; NumDM0--;
342
      if (NumDM0 > 0)
343
      {
344
        val -= 432; NumDM0--;
345
        val -= NumDM0 * 384;
346
      }
347
    }
348
  }
349
  if (num == 1)
350
  {
351
    char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0;
352
    int i;
353
    for (i = 0; i < 32; i++)
354
    {
355
      if (pos.SH[i] == 1 + pos.wmove) NSH1++;
356
      else if (pos.SH[i] == 2 - pos.wmove) NSH0++;
357
      else if (pos.SH[i] == 3 + pos.wmove) NDM1++;
358
      else if (pos.SH[i] == 4 - pos.wmove) NDM0++;
359
    }
360
    if (NDM1 > 0 && NDM0 > 0 && NSH1 + NSH0 < 3)
361
    {
362
      unsigned char HwoBD = 0;
363
      char Sh0BD = 1, Sh1BD = 1;
364
      for (i = 0; i < 8; i++)
365
      {
366
        char ShBD = pos.SH[PoleToNum(i, 7 - i)];
367
        if (ShBD == 1 + pos.wmove) Sh1BD++;
368
        else if (ShBD == 2 - pos.wmove) Sh0BD++;
369
        else if (ShBD == 3 + pos.wmove) HwoBD |= 2;
370
        else if (ShBD == 4 - pos.wmove) HwoBD |= 1;
371
      }
372
      if (HwoBD == 2) val += 128 / Sh0BD;
373
      if (HwoBD == 1) val -= 128 / Sh1BD;
374
      if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1)
375
      {
376
        char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
377
        char Add = 0;
378
        for (i = 0; i < 4; i++)
379
        {
380
          Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 +
381
                      (pos.SH[Best4P[i][1]] == 3 + pos.wmove));
382
        }
383
        if (Add >= 4) val += 32;
384
        else if (Add == 3) val += 24;
385
        else if (Add >= 1) val += 16;
386
      }
387
      else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2)
388
      {
389
        char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
390
        char Add = 0;
391
        for (i = 0; i < 4; i++)
392
        {
393
          Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 +
394
                      (pos.SH[Best4P[i][1]] == 4 - pos.wmove));
395
        }
396
        if (Add >= 4) val -= 32;
397
        else if (Add == 3) val -= 24;
398
        else if (Add >= 1) val -= 16;
399
      }
400
    }
401
    else
402
    {
403
      for (i = 0; i < NUM_CELL; i++)
404
      {
405
        char Color = char(pos.SH[i] - 1);
406
        if (Color == 0 || Color == 1)
407
        {
408
          char qi = Color ? char(NUM_CELL - 1 - i) : char(i);
409
          char Zn = Color ? char(-1) : char(1);
410
          char PreZ = (Color == pos.wmove) ? char(1) : char(-1);
411
          if (pos.SH[i + Zn * 8] != 2 - Color)
412
          {
413
            if (qi / 4 == 2)
414
            {
415
              char IsFree = 0;
416
              if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)2;
417
              else if (qi != 8)
418
              {
419
                if (pos.SH[i - Zn    ] == 2 - Color ||
420
                    pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)2;
421
                else if (Color != pos.wmove)
422
                      if (pos.SH[i - Zn * 5] == 2 - Color) IsFree++;
423
              }
424
              if (qi == 11) IsFree += (char)2;
425
              else if (pos.SH[i + Zn    ] == 2 - Color ||
426
                        pos.SH[i - Zn * 3] == 2 - Color ||
427
                        pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)2;
428
              else if (Color != pos.wmove && qi != 10)
429
              {
430
                if (pos.SH[i - Zn * 2] == 2 - Color) IsFree++;
431
              }
432
              if (IsFree < 3) val += PreZ * 176 / (1 + NDM0 + NDM1);
433
              else if (qi == 9 || qi == 10)
434
              {
435
                val += PreZ * 128 / (1 + NDM0 + NDM1);
436
              }
437
            }
438
            else if (qi / 4 == 3)
439
            {
440
              char IsFree = 0;
441
              if (pos.SH[i - Zn * 12] == 2 - Color)
442
              {
443
                if (Color == pos.wmove) IsFree += (char)11;
444
                else IsFree += (char)12;
445
              }
446
              else if (pos.SH[i - Zn * 4] == 2 - Color) IsFree += (char)11;
447
              else if (qi == 15) IsFree += (char)5;
448
              else if (pos.SH[i - Zn * 7] == 2 - Color) IsFree += (char)9;
449
              else if (pos.SH[i + Zn] == 2 - Color) IsFree += (char)8;
450
              else if (pos.SH[i - Zn * 11] == 2 - Color)
451
              {
452
                if (Color == pos.wmove) IsFree += (char)5;
453
                else IsFree += (char)7;
454
              }
455
              else if (pos.SH[i - Zn * 3] == 2 - Color) IsFree += (char)5;
456
              else if (qi != 14)
457
              {
458
                if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)3;
459
                else if (Color != pos.wmove)
460
                {
461
                  if (pos.SH[i - Zn * 10] == 2 - Color) IsFree++;
462
                }
463
              }
464
              if (qi == 12) IsFree += (char)7;
465
              else if (pos.SH[i - Zn * 13] == 2 - Color)
466
              {
467
                if (Color == pos.wmove) IsFree += (char)11;
468
                else IsFree += (char)12;
469
              }
470
              else if (pos.SH[i - Zn * 5] == 2 - Color) IsFree += (char)11;
471
              else if (pos.SH[i - Zn * 9] == 2 - Color) IsFree += (char)9;
472
              else if (pos.SH[i - Zn] == 2 - Color) IsFree += (char)8;
473
              else if (qi != 13)
474
              {
475
                if (pos.SH[i - Zn * 14] == 2 - Color)
476
                {
477
                  if (Color == pos.wmove) IsFree += (char)5;
478
                  else IsFree += (char)7;
479
                }
480
                else if (pos.SH[i - Zn * 6] == 2 - Color) IsFree += (char)5;
481
                else if (pos.SH[i - Zn * 10] == 2 - Color) IsFree += (char)3;
482
                else if (Color != pos.wmove && qi != 14)
483
                {
484
                  if (pos.SH[i - Zn * 15] == 2 - Color) IsFree++;
485
                }
486
              }
487
              if (IsFree < ((Color == pos.wmove) ? 14 : 12))
488
              {
489
                val += PreZ * 160 / (1 + NDM0 + NDM1);
490
              }
491
            }
492
          }
493
        }
494
      }
495
    }
496
  }
497
  if (num == 2)
498
  {
499
    char NSH1 = 0, NSH0 = 0, NDM1 = 0, NDM0 = 0;
500
    for (int i = 0; i < NUM_CELL; i++)
501
    {
502
      if (pos.SH[i] == 1 + pos.wmove) NSH1++;
503
      else if (pos.SH[i] == 2 - pos.wmove) NSH0++;
504
      else if (pos.SH[i] == 3 + pos.wmove) NDM1++;
505
      else if (pos.SH[i] == 4 - pos.wmove) NDM0++;
506
    }
507
    if (NDM1 > 0 && NDM0 > 0 && NSH1 == 0 && NSH0 == 0)
508
    {
509
      short PrP = 0;
510
      char Cpos3 = -1;
511
      if (NDM1 == 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0) Cpos3 = 1;
512
      else if (NDM1 == 1 && NDM0 == 3 && NSH1 == 0 && NSH0 == 0) Cpos3 = 0;
513
      if (Cpos3 >= 0)
514
      {
515
        for (int Osm = 0; Osm <= 1; Osm++) for (int Csm = 0; Csm <= 1; Csm++)
516
        {
517
          char PosSH[7][3] = {{13, 17, 18}, {6, 17, 18}, {9, 21, 22},
518
                              {17, 18, 19}, {9, 10, 15}, {11, 14, 18}, {2, 14, 18}};
519
          for (char PosNi = 0; PosNi < 7; PosNi++)
520
          {
521
            bool IsPosR = 1;
522
            for (char ShNi = 0; ShNi < 3; ShNi++)
523
            {
524
              char DNomSh = (Csm == 1) ? char(31 - PosSH[PosNi][ShNi])
525
                                       : char(PosSH[PosNi][ShNi]);
526
              if (Osm == 1)
527
              {
528
                int x, y;
529
                NumToPole(DNomSh, x, y);
530
                DNomSh = (char)PoleToNum(y, x);
531
              }
532
              if (pos.SH[DNomSh] != 3 + (Cpos3 == pos.wmove)) IsPosR = 0;
533
            }
534
            if (IsPosR)
535
            {
536
              if (PosNi == 3)
537
              {
538
                if (Cpos3 == 1)
539
                {
540
                  if (pos.SH[(Csm == 1) ? 29 : 2] !=
541
                      4 - (Cpos3 == pos.wmove) && pos.SH[(Csm == 1) ? 11 : 20] !=
542
                      4 - (Cpos3 == pos.wmove)) PrP = 216;
543
                }
544
                else
545
                {
546
                  bool PrPZ = 1;
547
                  for (int i = 0; i < 6; i++)
548
                      if (pos.SH[PoleToNum((Csm == 1) ? (i + 2) : i,
549
                        (Csm == 1) ? (7 - i) : (5 - i))] ==
550
                          4 - (Cpos3 == pos.wmove)) PrPZ = 0;
551
                  if (PrPZ) PrP = -216;
552
                }
553
              }
554
              else if (PosNi == 4)
555
              {
556
                if (Cpos3 == 1)
557
                {
558
                  if (pos.SH[ 0] != 4 - (Cpos3 == pos.wmove) &&
559
                      pos.SH[ 4] != 4 - (Cpos3 == pos.wmove) &&
560
                      pos.SH[27] != 4 - (Cpos3 == pos.wmove) &&
561
                      pos.SH[31] != 4 - (Cpos3 == pos.wmove))
562
                  {
563
                    PrP = 216;
564
                  }
565
                }
566
                else
567
                {
568
                  if (pos.SH[(Csm == Osm) ?  4 :  0] != 4 - (Cpos3 == pos.wmove) &&
569
                      pos.SH[(Csm == Osm) ?  8 :  5] != 4 - (Cpos3 == pos.wmove) &&
570
                      pos.SH[(Csm == Osm) ? 26 : 23] != 4 - (Cpos3 == pos.wmove) &&
571
                      pos.SH[(Csm == Osm) ? 31 : 27] != 4 - (Cpos3 == pos.wmove))
572
                  {
573
                    PrP = -216;
574
                  }
575
                }
576
              }
577
              else if (PosNi == 5)
578
              {
579
                char DNomSh = (Cpos3 == 1) ? ((Osm == 1) ? (char)16 : (char)6)
580
                                           : ((Osm == 1) ? (char)20 : (char)2);
581
                if (Csm == 1) DNomSh = char(31 - DNomSh);
582
                if (pos.SH[DNomSh] == 4 - (Cpos3 == pos.wmove))
583
                {
584
                  PrP = (Cpos3 == 1) ? short(160) : short(-160);
585
                }
586
              }
587
              else if (PosNi == 6)
588
              {
589
                if (Cpos3 == 1)
590
                {
591
                  if (pos.SH[ 1] == 4 - (Cpos3 == pos.wmove) ||
592
                      pos.SH[12] == 4 - (Cpos3 == pos.wmove) ||
593
                      pos.SH[19] == 4 - (Cpos3 == pos.wmove) ||
594
                      pos.SH[30] == 4 - (Cpos3 == pos.wmove))
595
                  {
596
                    PrP = 168;
597
                  }
598
                }
599
                else
600
                {
601
                  if (pos.SH[(Csm == 1) ? 15 :  6] == 4 - (Cpos3 == pos.wmove) ||
602
                      pos.SH[(Csm == 1) ? 25 : 16] == 4 - (Cpos3 == pos.wmove))
603
                  {
604
                    PrP = -168;
605
                  }
606
                }
607
              }
608
              else PrP = short(((Cpos3 == 1) ? 1 : -1) * ((PosNi == 0) ? 200 : 208));
609
            }
610
          }
611
        }
612
      }
613
      if (PrP == 0)
614
      {
615
        unsigned char HwoBD = 0;
616
        char NShSBD = 0;
617
        for (int i = 0; i < 8; i++)
618
        {
619
          char ShBD = pos.SH[PoleToNum(i, 7 - i)];
620
          if (ShBD == 3 + pos.wmove) {HwoBD |= 2; NShSBD++;}
621
          else if (ShBD == 4 - pos.wmove) {HwoBD |= 1; NShSBD++;}
622
        }
623
        if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 2)
624
        {
625
          if (NShSBD >= 1) val -= NShSBD - 1;
626
          if (pos.SH[ 3] == 3 + pos.wmove) val--;
627
          if (pos.SH[28] == 3 + pos.wmove) val--;
628
          char Drg1 = 0, DrgPS = 0;
629
          bool Drg1p = 0;
630
          for (int i = 0; i < 7; i++)
631
          {
632
            char Sh7D = pos.SH[PoleToNum(i, i + 1)];
633
            if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;}
634
            else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
635
            Sh7D = pos.SH[PoleToNum(i + 1, i)];
636
            if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;}
637
            else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
638
          }
639
          if (pos.SH[0] == 3 + pos.wmove || pos.SH[4] == 3 + pos.wmove ||
640
              pos.SH[27] == 3 + pos.wmove || pos.SH[31] == 3 + pos.wmove)
641
                  {if (Drg1p) val += 4; else val -= 1;}
642
          if ((pos.SH[14] == 3 + pos.wmove) == (pos.SH[17] == 3 + pos.wmove))
643
              {if (Drg1 == 1) val += 2;}
644
          else
645
          {
646
            if (Drg1 >= 2)
647
            {
648
              if (Drg1 > 2) val -= 1;
649
              if (DrgPS == 3) val += 4;
650
              if (Drg1p) val += 4; else val += 16;
651
              if (!Drg1p && DrgPS)
652
              {
653
                Drg1 = 0; Drg1p = 0; DrgPS = 0;
654
                for (int i = 0; i < 6; i++)
655
                {
656
                  char Sh7D = pos.SH[PoleToNum(i, 5 - i)];
657
                  if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 1;}
658
                  else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
659
                  Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)];
660
                  if (Sh7D == 3 + pos.wmove) {Drg1++; DrgPS |= 2;}
661
                  else if (Sh7D == 4 - pos.wmove) Drg1p = 1;
662
                }
663
                if (pos.SH[2] == 3 + pos.wmove || pos.SH[11] == 3 + pos.wmove ||
664
                    pos.SH[20] == 3 + pos.wmove || pos.SH[29] == 3 + pos.wmove)
665
                        val += 4;
666
                if ((pos.SH[14] == 3 + pos.wmove)
667
                    ? (pos.SH[13] == 3 + pos.wmove || pos.SH[22] == 3 + pos.wmove)
668
                    : (pos.SH[ 9] == 3 + pos.wmove || pos.SH[18] == 3 + pos.wmove))
669
                {
670
                  if (Drg1 >= 2)
671
                  {
672
                    if (DrgPS == 3) val += 4;
673
                    if (Drg1p) val += 4; else val += 16;
674
                  }
675
                  else if (Drg1 == 1) val += 1;
676
                }
677
                else if (Drg1 == 1) val += 2;
678
              }
679
            }
680
          }
681
        }
682
        else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 1)
683
        {
684
          if (NShSBD >= 1) val += NShSBD - 1;
685
          if (pos.SH[ 3] == 4 - pos.wmove) val++;
686
          if (pos.SH[28] == 4 - pos.wmove) val++;
687
          char Drg1 = 0, DrgPS = 0;
688
          bool Drg1p = 0;
689
          for (int i = 0; i < 7; i++)
690
          {
691
            char Sh7D = pos.SH[PoleToNum(i, i + 1)];
692
            if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;}
693
            else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
694
            Sh7D = pos.SH[PoleToNum(i + 1, i)];
695
            if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;}
696
            else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
697
          }
698
          if (pos.SH[0] == 4 - pos.wmove || pos.SH[4] == 4 - pos.wmove ||
699
              pos.SH[27] == 4 - pos.wmove || pos.SH[31] == 4 - pos.wmove)
700
                  {if (Drg1p) val -= 4; else val += 1;}
701
          if ((pos.SH[14] == 4 - pos.wmove) == (pos.SH[17] == 4 - pos.wmove))
702
              {if (Drg1 == 1) val -= 2;}
703
          else
704
          {
705
            if (Drg1 >= 2)
706
            {
707
              if (Drg1 > 2) val += 1;
708
              if (DrgPS == 3) val -= 4;
709
              if (Drg1p) val -= 4; else val -= 16;
710
              if (!Drg1p && DrgPS)
711
              {
712
                Drg1 = 0; Drg1p = 0; DrgPS = 0;
713
                for (int i = 0; i < 6; i++)
714
                {
715
                  char Sh7D = pos.SH[PoleToNum(i, 5 - i)];
716
                  if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 1;}
717
                  else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
718
                  Sh7D = pos.SH[PoleToNum(i + 2, 7 - i)];
719
                  if (Sh7D == 4 - pos.wmove) {Drg1++; DrgPS |= 2;}
720
                  else if (Sh7D == 3 + pos.wmove) Drg1p = 1;
721
                }
722
                if (pos.SH[2] == 4 - pos.wmove || pos.SH[11] == 4 - pos.wmove ||
723
                    pos.SH[20] == 4 - pos.wmove || pos.SH[29] == 4 - pos.wmove)
724
                {
725
                  val -= 4;
726
                }
727
                if ((pos.SH[14] == 4 - pos.wmove)
728
                    ? (pos.SH[13] == 4 - pos.wmove || pos.SH[22] == 4 - pos.wmove)
729
                    : (pos.SH[ 9] == 4 - pos.wmove || pos.SH[18] == 4 - pos.wmove))
730
                {
731
                  if (Drg1 >= 2)
732
                  {
733
                    if (DrgPS == 3) val -= 4;
734
                    if (Drg1p) val -= 4; else val -= 16;
735
                  }
736
                  else if (Drg1 == 1) val -= 1;
737
                }
738
                else if (Drg1 == 1) val -= 2;
739
              }
740
            }
741
          }
742
        }
743
        else if (NDM1 >= 3 && NDM0 == 1 && NSH1 == 0 && NSH0 == 0 && HwoBD == 1)
744
        {
745
          char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
746
          char Add = 0;
747
          for (int i = 0; i < 4; i++)
748
          {
749
            Add |= char((pos.SH[Best4P[i][0]] == 3 + pos.wmove) * 3 +
750
                        (pos.SH[Best4P[i][1]] == 3 + pos.wmove));
751
          }
752
          if (Add >= 4) val += 3;
753
          else if (Add == 3) val += 2;
754
          else if (Add >= 1) val += 1;
755
        }
756
        else if (NDM0 >= 3 && NDM1 == 1 && NSH0 == 0 && NSH1 == 0 && HwoBD == 2)
757
        {
758
          char Best4P[4][2] = {{0,9}, {4,13}, {31,22}, {27,18}};
759
          char Add = 0;
760
          for (int i = 0; i < 4; i++)
761
          {
762
            Add |= char((pos.SH[Best4P[i][0]] == 4 - pos.wmove) * 3 +
763
                        (pos.SH[Best4P[i][1]] == 4 - pos.wmove));
764
          }
765
          if (Add >= 4) val -= 3;
766
          else if (Add == 3) val -= 2;
767
          else if (Add >= 1) val -= 1;
768
        }
769
      }
770
      else val += PrP;
771
    }
772
  }
773
  return val;
774
}
775
 
776
template 
777
tvalue TBaseCompPlayer::GetFullValue(const Position &pos, int num)
778
{
779
  if (!pos.AllCanMove() && !pos.AllCanEat()) return GetLossValue(pos);
780
  else return GetValue(pos, num);
781
}
782
 
783
template 
784
tvalue TBaseCompPlayer::FindBMove(Z &z, int num,
785
                           PMvv *pmv, int zn, tvalue a, tvalue b)
786
{
787
  assert(b > a);
788
  assert(num >= 0);
4652 ashmew2 789
  if (num >= 3 && draw) draw(data, 0);
1805 yogev_ezra 790
  int nlast = z.narr;
791
  if (zn < 0) {z.AddPos(); z.array[zn = z.narr++] = *pmv;}
792
  if (pmv) pmv->mv[0] = 0;
793
  int n0 = z.narr;
794
  int was_eat = z.FindAllMoves(z.array[zn], num <= 0);
795
  int n1 = z.narr;
796
  tvalue val;
797
  if (n1 == n0)
798
  {
799
    assert(!z.array[zn].pos.AllCanEat());
800
    assert(num == 0 || !z.array[zn].pos.AllCanMove());
801
    if (num > 0 || !z.array[zn].pos.AllCanMove()) val = GetLossValue(z.array[zn].pos);
802
    else val = GetValue(z.array[zn].pos, 0);
803
  }
804
  else if (pmv && n1 == n0 + 1 && nlast < n0)
805
  {
806
    *pmv = z.array[n0];
807
    if (!z.array[n0].pos.AllCanMove() && !z.array[n0].pos.AllCanMove())
808
    {
809
      val = -1 - GetLossValue(z.array[n0].pos);
810
    }
811
    else
812
    {
813
      val = -GetValue(z.array[n0].pos, 0);
814
      n1 = -1;
815
    }
816
  }
817
  else
818
  {
819
    int k, opt;
820
    if (num >= 2)
821
    {
822
      if (pmv && n1 > n0 + 1)
823
      {
824
        for (k = 0; k < 2*(n1 - n0); k++)
825
        {
826
          int i0 = n0 + random(n1 - n0), i1 = n0 + random(n1 - n0 - 1);
827
          if (i1 >= i0) i1++;
828
          PMvv t_pmv = z.array[i0];
829
          z.array[i0] = z.array[i1];
830
          z.array[i1] = t_pmv;
831
        }
832
      }
833
      for (k = n0; k < n1; k++) z.array[k].val = GetFullValue(z.array[k].pos);
834
      z.Sort(n0, n1);
835
    }
836
    tvalue cc = 2 * win_val;
837
    tvalue dval = was_eat ? 0 : GetValue(z.array[zn].pos, num);
838
    tvalue aa = -b, bb = -a;
839
    if (aa < -win_val) aa--;
840
    else if (aa > win_val) aa++;
841
    else aa += dval;
842
    if (bb < -win_val) bb--;
843
    else if (bb > win_val) bb++;
844
    else bb += dval;
845
    for (k = n0; k < n1 && bb > aa; k++)
846
    {
847
      tvalue vk;
848
      vk = FindBMove(z, num-1+was_eat, 0, k, aa, bb);
849
      if (vk < cc)
850
      {
851
        opt = k; cc = vk;
852
        if (bb > cc) bb = cc;
853
      }
854
    }
855
    if (cc < -win_val) cc++;
856
    else if (cc > win_val) cc--;
857
    else cc -= dval;
858
    val = -cc;
859
    assert(opt >= n0 && opt < n1);
860
    if (pmv) *pmv = z.array[opt];
861
  }
862
  z.array[zn].val = val;
863
  z.narr = nlast;
864
  if (pmv)
865
  {
866
    if (n1 >= 0) printf("Checkers: value = %ld\n", val);
867
    else printf("Checkers: value = ?\n");
868
  }
869
  return val;
870
}
871
 
872
template 
873
int TBaseCompPlayer::Move(PMv &pmv)
874
{
875
  Z z;
876
  PMvv zpmv;
877
  (PMv&)zpmv = pmv;
878
  if (draw) draw(data, 1);
879
  FindBMove(z, 6, &zpmv);
880
  if (draw) draw(data, -1);
881
  if (zpmv.mv[0] == 0) return 0;
882
  pmv = zpmv;
883
  return 1;
884
}
885
 
886
typedef TBaseCompPlayer TComputerPlayer;
887
 
888
#endif  //_HEADER_PLAYER_H