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