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 |
||
59 | |||
60 | template |
||
61 | const tvalue TBaseCompPlayer |
||
62 | |||
63 | template |
||
64 | void TBaseCompPlayer |
||
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 |
||
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 |
||
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 |
||
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 |
||
283 | { |
||
284 | qsort(array + n0, n1 - n0, sizeof(PMvv), ComparePMv); |
||
285 | } |
||
286 | |||
287 | |||
288 | template |
||
289 | tvalue TBaseCompPlayer |
||
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 |
||
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 |
||
778 | { |
||
779 | if (!pos.AllCanMove() && !pos.AllCanEat()) return GetLossValue(pos); |
||
780 | else return GetValue(pos, num); |
||
781 | } |
||
782 | |||
783 | template |
||
784 | tvalue TBaseCompPlayer |
||
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 |
||
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 |
||
887 | |||
888 | #endif //_HEADER_PLAYER_H>>>>>>>>>=>>>>>>>>>>>>=>=>>>>>>>>>>>>>=>>>>=>>=>>=>>>>=>>>>>>> |