Subversion Repositories Kolibri OS

Rev

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