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