1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "groovie/cell.h"
24
25 namespace Groovie {
26
CellGame()27 CellGame::CellGame() {
28 _startX = _startY = _endX = _endY = 255;
29
30 _stack_index = _boardStackPtr = 0;
31 _flag4 = false;
32 _flag2 = false;
33 _flag1 = false;
34 _coeff3 = 0;
35
36 _moveCount = 0;
37 }
38
getStartX()39 byte CellGame::getStartX() {
40 if (_startX > BOARDSIZE) {
41 warning ("CellGame::getStartX: not calculated yet (%d)!", _startX);
42 return 0;
43 } else {
44 return _startX;
45 }
46 }
47
getStartY()48 byte CellGame::getStartY() {
49 if (_startY > BOARDSIZE) {
50 warning ("CellGame::getStartY: not calculated yet (%d)!", _startY);
51 return 6;
52 } else {
53 return _startY;
54 }
55 }
56
getEndX()57 byte CellGame::getEndX() {
58 if (_endX > BOARDSIZE) {
59 warning ("CellGame::getEndX: not calculated yet (%d)!", _endX);
60 return 1;
61 } else {
62 return _endX;
63 }
64 }
65
getEndY()66 byte CellGame::getEndY() {
67 if (_endY > BOARDSIZE) {
68 warning ("CellGame::getEndY: not calculated yet (%d)!", _endY);
69 return 6;
70 } else {
71 return _endY;
72 }
73 }
74
~CellGame()75 CellGame::~CellGame() {
76 }
77
78 const int8 possibleMoves[][9] = {
79 { 1, 7, 8, -1 },
80 { 0, 2, 7, 8, 9, -1 },
81 { 1, 3, 8, 9, 10, -1 },
82 { 2, 4, 9, 10, 11, -1 },
83 { 3, 5, 10, 11, 12, -1 },
84 { 4, 6, 11, 12, 13, -1 }, // 5
85 { 5, 12, 13, -1 },
86 { 0, 1, 8, 14, 15, -1 },
87 { 0, 1, 2, 7, 9, 14, 15, 16, -1 },
88 { 1, 2, 3, 8, 10, 15, 16, 17, -1 },
89 { 2, 3, 4, 9, 11, 16, 17, 18, -1 }, // 10
90 { 3, 4, 5, 10, 12, 17, 18, 19, -1 },
91 { 4, 5, 6, 11, 13, 18, 19, 20, -1 },
92 { 5, 6, 12, 19, 20, -1 },
93 { 7, 8, 15, 21, 22, -1 },
94 { 7, 8, 9, 14, 16, 21, 22, 23, -1 }, // 15
95 { 8, 9, 10, 15, 17, 22, 23, 24, -1 },
96 { 9, 10, 11, 16, 18, 23, 24, 25, -1 },
97 { 10, 11, 12, 17, 19, 24, 25, 26, -1 },
98 { 11, 12, 13, 18, 20, 25, 26, 27, -1 },
99 { 12, 13, 19, 26, 27, -1 }, // 20
100 { 14, 15, 22, 28, 29, -1 },
101 { 14, 15, 16, 21, 23, 28, 29, 30, -1 },
102 { 15, 16, 17, 22, 24, 29, 30, 31, -1 },
103 { 16, 17, 18, 23, 25, 30, 31, 32, -1 },
104 { 17, 18, 19, 24, 26, 31, 32, 33, -1 }, // 25
105 { 18, 19, 20, 25, 27, 32, 33, 34, -1 },
106 { 19, 20, 26, 33, 34, -1 },
107 { 21, 22, 29, 35, 36, -1 },
108 { 21, 22, 23, 28, 30, 35, 36, 37, -1 },
109 { 22, 23, 24, 29, 31, 36, 37, 38, -1 }, // 30
110 { 23, 24, 25, 30, 32, 37, 38, 39, -1 },
111 { 24, 25, 26, 31, 33, 38, 39, 40, -1 },
112 { 25, 26, 27, 32, 34, 39, 40, 41, -1 },
113 { 26, 27, 33, 40, 41, -1 },
114 { 28, 29, 36, 42, 43, -1 }, // 35
115 { 28, 29, 30, 35, 37, 42, 43, 44, -1 },
116 { 29, 30, 31, 36, 38, 43, 44, 45, -1 },
117 { 30, 31, 32, 37, 39, 44, 45, 46, -1 },
118 { 31, 32, 33, 38, 40, 45, 46, 47, -1 },
119 { 32, 33, 34, 39, 41, 46, 47, 48, -1 }, // 40
120 { 33, 34, 40, 47, 48, -1 },
121 { 35, 36, 43, -1 },
122 { 35, 36, 37, 42, 44, -1 },
123 { 36, 37, 38, 43, 45, -1 },
124 { 37, 38, 39, 44, 46, -1 }, // 45
125 { 38, 39, 40, 45, 47, -1 },
126 { 39, 40, 41, 46, 48, -1 },
127 { 40, 41, 47, -1 }
128 };
129
130
131 const int8 strategy2[][17] = {
132 { 2, 9, 14, 15, 16, -1 },
133 { 3, 10, 14, 15, 16, 17, -1 },
134 { 0, 4, 7, 11, 14, 15, 16, 17, 18, -1 },
135 { 1, 5, 8, 12, 15, 16, 17, 18, 19, -1 },
136 { 2, 6, 9, 13, 16, 17, 18, 19, 20, -1 },
137 { 3, 10, 17, 18, 19, 20, -1 }, // 5
138 { 4, 11, 18, 19, 20, -1 },
139 { 2, 9, 16, 21, 22, 23, -1 },
140 { 3, 10, 17, 21, 22, 23, 24, -1 },
141 { 0, 4, 7, 11, 14, 18, 21, 22, 23, 24, 25, -1 },
142 { 1, 5, 8, 12, 15, 19, 22, 23, 24, 25, 26, -1 }, // 10
143 { 2, 6, 9, 13, 16, 20, 23, 24, 25, 26, 27, -1 },
144 { 3, 10, 17, 24, 25, 26, 27, -1 },
145 { 4, 11, 18, 25, 26, 27, -1 },
146 { 0, 1, 2, 9, 16, 23, 28, 29, 30, -1 },
147 { 0, 1, 2, 3, 10, 17, 24, 28, 29, 30, 31, -1 }, // 15
148 { 0, 1, 2, 3, 4, 7, 11, 14, 18, 21, 25, 28, 29, 30, 31, 32, -1 },
149 { 1, 2, 3, 4, 5, 8, 12, 15, 19, 22, 26, 29, 30, 31, 32, 33, -1 },
150 { 2, 3, 4, 5, 6, 9, 13, 16, 20, 23, 27, 30, 31, 32, 33, 34, -1 },
151 { 3, 4, 5, 6, 10, 17, 24, 31, 32, 33, 34, -1 },
152 { 4, 5, 6, 11, 18, 25, 32, 33, 34, -1 }, // 20
153 { 7, 8, 9, 16, 23, 30, 35, 36, 37, -1 },
154 { 7, 8, 9, 10, 17, 24, 31, 35, 36, 37, 38, -1 },
155 { 7, 8, 9, 10, 11, 14, 18, 21, 25, 28, 32, 35, 36, 37, 38, 39, -1 },
156 { 8, 9, 10, 11, 12, 15, 19, 22, 26, 29, 33, 36, 37, 38, 39, 40, -1 },
157 { 9, 10, 11, 12, 13, 16, 20, 23, 27, 30, 34, 37, 38, 39, 40, 41, -1 }, // 25
158 { 10, 11, 12, 13, 17, 24, 31, 38, 39, 40, 41, -1 },
159 { 11, 12, 13, 18, 25, 32, 39, 40, 41, -1 },
160 { 14, 15, 16, 23, 30, 37, 42, 43, 44, -1 },
161 { 14, 15, 16, 17, 24, 31, 38, 42, 43, 44, 45, -1 },
162 { 14, 15, 16, 17, 18, 21, 25, 28, 32, 35, 39, 42, 43, 44, 45, 46, -1 }, // 30
163 { 15, 16, 17, 18, 19, 22, 26, 29, 33, 36, 40, 43, 44, 45, 46, 47, -1 },
164 { 16, 17, 18, 19, 20, 23, 27, 30, 34, 37, 41, 44, 45, 46, 47, 48, -1 },
165 { 17, 18, 19, 20, 24, 31, 38, 45, 46, 47, 48, -1 },
166 { 18, 19, 20, 25, 32, 39, 46, 47, 48, -1 },
167 { 21, 22, 23, 30, 37, 44, -1 }, // 35
168 { 21, 22, 23, 24, 31, 38, 45, -1 },
169 { 21, 22, 23, 24, 25, 28, 32, 35, 39, 42, 46, -1 },
170 { 22, 23, 24, 25, 26, 29, 33, 36, 40, 43, 47, -1 },
171 { 23, 24, 25, 26, 27, 30, 34, 37, 41, 44, 48, -1 },
172 { 24, 25, 26, 27, 31, 38, 45, -1 }, // 40
173 { 25, 26, 27, 32, 39, 46, -1 },
174 { 28, 29, 30, 37, 44, -1 },
175 { 28, 29, 30, 31, 38, 45, -1 },
176 { 28, 29, 30, 31, 32, 35, 39, 42, 46, -1 },
177 { 29, 30, 31, 32, 33, 36, 40, 43, 47, -1 }, // 45
178 { 30, 31, 32, 33, 34, 37, 41, 44, 48, -1 },
179 { 31, 32, 33, 34, 38, 45, -1 },
180 { 32, 33, 34, 39, 46, -1 }
181 };
182
copyToTempBoard()183 void CellGame::copyToTempBoard() {
184 for (int i = 0; i < 53; ++i) {
185 _tempBoard[i] = _board[i];
186 }
187 }
188
copyFromTempBoard()189 void CellGame::copyFromTempBoard() {
190 for (int i = 0; i < 53; ++i) {
191 _board[i] = _tempBoard[i];
192 }
193 }
194
copyToShadowBoard()195 void CellGame::copyToShadowBoard() {
196 _board[53] = 0;
197 _board[55] = 1;
198 _board[56] = 0;
199
200 for (int i = 0; i < 49; ++i) {
201 _shadowBoard[i] = _board[i];
202 }
203 }
204
pushBoard()205 void CellGame::pushBoard() {
206 assert(_boardStackPtr < 57 * 9);
207
208 for (int i = 0; i < 57; ++i)
209 _boardStack[_boardStackPtr + i] = _board[i];
210 _boardStackPtr += 57;
211 }
212
popBoard()213 void CellGame::popBoard() {
214 assert(_boardStackPtr > 0);
215
216 _boardStackPtr -= 57;
217 for (int i = 0; i < 57; ++i) {
218 _board[i] = _boardStack[_boardStackPtr + i];
219 }
220 }
221
pushShadowBoard()222 void CellGame::pushShadowBoard() {
223 assert(_boardStackPtr < 57 * 9);
224
225 for (int i = 0; i < 57; ++i)
226 _boardStack[_boardStackPtr + i] = _shadowBoard[i];
227
228 _boardStackPtr += 57;
229 }
230
popShadowBoard()231 void CellGame::popShadowBoard() {
232 assert(_boardStackPtr > 0);
233
234 _boardStackPtr -= 57;
235
236 for (int i = 0; i < 57; ++i) {
237 _shadowBoard[i] = _boardStack[_boardStackPtr + i];
238 }
239 }
240
clearMoves()241 void CellGame::clearMoves() {
242 _stack_startXY[0] = _board[53];
243 _stack_endXY[0] = _board[54];
244 _stack_pass[0] = _board[55];
245
246 _stack_index = 1;
247 }
248
pushMove()249 void CellGame::pushMove() {
250 _stack_startXY[_stack_index] = _board[53];
251 _stack_endXY[_stack_index] = _board[54];
252 _stack_pass[_stack_index] = _board[55];
253
254 _stack_index++;
255 }
256
resetMove()257 void CellGame::resetMove() {
258 _board[53] = 0;
259 _board[54] = 0;
260 _board[55] = 0;
261 }
262
takeCells(uint16 whereTo,int8 color)263 void CellGame::takeCells(uint16 whereTo, int8 color) {
264 int cellN;
265 const int8 *str;
266
267 str = possibleMoves[whereTo];
268 while (1) {
269 cellN = *str++;
270 if (cellN < 0)
271 break;
272 if (_tempBoard[cellN] > 0) {
273 --_tempBoard[_tempBoard[cellN] + 48];
274 _tempBoard[cellN] = color;
275 ++_tempBoard[color + 48];
276 }
277 }
278 }
279
countAllCells()280 void CellGame::countAllCells() {
281 _board[49] = 0;
282 _board[50] = 0;
283 _board[51] = 0;
284 _board[52] = 0;
285
286 for (int i = 0; i < 49; i++) {
287 switch (_board[i]) {
288 case 1: // CELL_BLUE
289 _board[49]++;
290 break;
291 case 2: // CELL_GREEN
292 _board[50]++;
293 break;
294 case 3:
295 _board[51]++;
296 break;
297 case 4:
298 _board[52]++;
299 break;
300 default:
301 break;
302 }
303 }
304 }
305
countCellsOnTempBoard(int8 color)306 int CellGame::countCellsOnTempBoard(int8 color) {
307 const int8 *str;
308 int res = 0;
309 int i;
310
311 for (i = 0; i < 49; i++)
312 _boardSum[i] = 0;
313
314 for (i = 0; i < 49; i++) {
315 if (_tempBoard[i] == color) {
316 for (str = possibleMoves[i]; *str > 0; str++) {
317 if (!_tempBoard[*str])
318 ++_boardSum[*str];
319 }
320 }
321 }
322
323 for (i = 0; i < 49; i++)
324 res += _boardSum[i];
325
326 return res;
327 }
328
canMoveFunc1(int8 color)329 bool CellGame::canMoveFunc1(int8 color) {
330 const int8 *str;
331
332 if (_board[55] == 1) {
333 for (; _board[53] < 49; _board[53]++) {
334 if (_shadowBoard[_board[53]] == color) {
335 str = &possibleMoves[_board[53]][_board[56]];
336 for (;_board[56] < 8; _board[56]++) {
337 _board[54] = *str++;
338 if (_board[54] < 0)
339 break;
340 if (!_shadowBoard[_board[54]]) {
341 _shadowBoard[_board[54]] = -1;
342 ++_board[56];
343 return true;
344 }
345 }
346 _board[56] = 0;
347 }
348 }
349 _board[53] = 0;
350 _board[55] = 2;
351 _board[56] = 0;
352 }
353 if (_board[55] == 2) {
354 for (; _board[53] < 49; _board[53]++) {
355 if (_shadowBoard[_board[53]] == color) {
356 str = &strategy2[_board[53]][_board[56]];
357 for (;_board[56] < 16; _board[56]++) {
358 _board[54] = *str++;
359 if (_board[54] < 0)
360 break;
361 if (!_board[_board[54]]) {
362 ++_board[56];
363 return true;
364 }
365 }
366 _board[56] = 0;
367 }
368 }
369 }
370
371 return false;
372 }
373
canMoveFunc3(int8 color)374 bool CellGame::canMoveFunc3(int8 color) {
375 const int8 *str;
376
377 if (_board[55] == 1) {
378 for (; _board[53] < 49; _board[53]++) {
379 if (_shadowBoard[_board[53]] == color) {
380 str = &possibleMoves[_board[53]][_board[56]];
381 for (;_board[56] < 8; _board[56]++) {
382 _board[54] = *str++;
383 if (_board[54] < 0)
384 break;
385 if (!_shadowBoard[_board[54]]) {
386 _shadowBoard[_board[54]] = -1;
387 ++_board[56];
388 return true;
389 }
390 }
391 _board[56] = 0;
392 }
393 }
394
395 _board[53] = 0;
396 _board[55] = 2;
397 _board[56] = 0;
398 for (int i = 0; i < 49; ++i)
399 _shadowBoard[i] = _board[i];
400 }
401 if (_board[55] == 2) {
402 for (; _board[53] < 49; _board[53]++) {
403 if (_shadowBoard[_board[53]] == color) {
404 str = &strategy2[_board[53]][_board[56]];
405 for (;_board[56] < 16; _board[56]++) {
406 _board[54] = *str++;
407 if (_board[54] < 0)
408 break;
409 if (!_shadowBoard[_board[54]]) {
410 _shadowBoard[_board[54]] = -1;
411 ++_board[56];
412 return true;
413 }
414 }
415 _board[56] = 0;
416 }
417 }
418 }
419
420 return false;
421 }
422
canMoveFunc2(int8 color)423 bool CellGame::canMoveFunc2(int8 color) {
424 const int8 *str;
425
426 while (1) {
427 while (_board[_board[54]]) {
428 ++_board[54];
429 if (_board[54] >= 49)
430 return false;
431 }
432 if (!_board[55]) {
433 str = possibleMoves[_board[54]];
434 while (1) {
435 _board[53] = *str++;
436 if (_board[53] < 0)
437 break;
438 if (_board[_board[53]] == color) {
439 _board[55] = 1;
440 return true;
441 }
442 }
443 _board[55] = 1;
444 }
445 if (_board[55] == 1) {
446 _board[55] = 2;
447 _board[56] = 0;
448 }
449 if (_board[55] == 2) {
450 str = &strategy2[_board[54]][_board[56]];
451 for (; _board[56] < 16; _board[56]++) {
452 _board[53] = *str++;
453 if (_board[53] < 0)
454 break;
455 if (_board[_board[53]] == color) {
456 ++_board[56];
457 return true;
458 }
459 }
460 ++_board[54];
461 _board[55] = 0;
462 if (_board[54] >= 49)
463 break;
464 }
465 }
466 return false;
467 }
468
makeMove(int8 color)469 void CellGame::makeMove(int8 color) {
470 copyToTempBoard();
471 _tempBoard[_board[54]] = color;
472 ++_tempBoard[color + 48];
473 if (_board[55] == 2) {
474 _tempBoard[_board[53]] = 0;
475 --_tempBoard[color + 48];
476 }
477 takeCells(_board[54], color);
478 }
479
getBoardWeight(int8 color1,int8 color2)480 int CellGame::getBoardWeight(int8 color1, int8 color2) {
481 int8 celln;
482 const int8 *str;
483 byte cellCnt[8];
484
485 str = possibleMoves[_board[54]];
486 cellCnt[1] = _board[49];
487 cellCnt[2] = _board[50];
488 cellCnt[3] = _board[51];
489 cellCnt[4] = _board[52];
490 if (_board[55] != 2)
491 ++cellCnt[color2];
492 celln = *str++;
493
494 celln = _board[celln];
495 if (celln > 0) {
496 --cellCnt[celln];
497 ++cellCnt[color2];
498 }
499 celln = *str++;
500
501 celln = _board[celln];
502 if (celln > 0) {
503 --cellCnt[celln];
504 ++cellCnt[color2];
505 }
506 celln = *str++;
507
508 celln = _board[celln];
509 if (celln > 0) {
510 --cellCnt[celln];
511 ++cellCnt[color2];
512 }
513 while (1) {
514 celln = *str++;
515 if (celln < 0)
516 break;
517 celln = _board[celln];
518 if (celln > 0) {
519 --cellCnt[celln];
520 ++cellCnt[color2];
521 }
522 }
523 return _coeff3 + 2 * (2 * cellCnt[color1] - cellCnt[1] - cellCnt[2] - cellCnt[3] - cellCnt[4]);
524 }
525
chooseBestMove(int8 color)526 void CellGame::chooseBestMove(int8 color) {
527 int moveIndex = 0;
528
529 if (_flag2) {
530 int bestWeight = 32767;
531 for (int i = 0; i < _stack_index; ++i) {
532 _board[53] = _stack_startXY[i];
533 _board[54] = _stack_endXY[i];
534 _board[55] = _stack_pass[i];
535 makeMove(color);
536 int curWeight = countCellsOnTempBoard(color);
537 if (curWeight <= bestWeight) {
538 if (curWeight < bestWeight)
539 moveIndex = 0;
540 bestWeight = curWeight;
541 _stack_startXY[moveIndex] = _board[53];
542 _stack_endXY[moveIndex] = _board[54];
543 _stack_pass[moveIndex++] = _board[55];
544 }
545 }
546 _stack_index = moveIndex;
547 }
548
549 _startX = _stack_startXY[0] % 7;
550 _startY = _stack_startXY[0] / 7;
551 _endX = _stack_endXY[0] % 7;
552 _endY = _stack_endXY[0] / 7;
553 }
554
calcBestWeight(int8 color1,int8 color2,uint16 depth,int bestWeight)555 int8 CellGame::calcBestWeight(int8 color1, int8 color2, uint16 depth, int bestWeight) {
556 int8 res;
557 int8 curColor;
558 bool canMove;
559 int type;
560 uint16 i;
561 int8 currBoardWeight;
562 int8 weight;
563
564 pushBoard();
565 copyFromTempBoard();
566 curColor = color2;
567 for (i = 0;; ++i) {
568 if (i >= 4) {
569 res = _coeff3 + 2 * (2 * _board[color1 + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
570 popBoard();
571 return res;
572 }
573 ++curColor;
574 if (curColor > 4)
575 curColor = 1;
576
577 if (_board[curColor + 48]) {
578 if (_board[curColor + 48] >= 49 - _board[49] - _board[50] - _board[51] - _board[52]) {
579 resetMove();
580 canMove = canMoveFunc2(curColor);
581 type = 1;
582 } else {
583 copyToShadowBoard();
584 if (depth == 1) {
585 canMove = canMoveFunc3(curColor);
586 type = 3;
587 } else {
588 canMove = canMoveFunc1(curColor);
589 type = 2;
590 }
591 }
592 if (canMove)
593 break;
594 }
595 }
596 if (_flag1) {
597 popBoard();
598 return bestWeight + 1;
599 }
600
601 depth -= 1;
602 if (depth) {
603 makeMove(curColor);
604 if (type == 1) {
605 res = calcBestWeight(color1, curColor, depth, bestWeight);
606 } else {
607 pushShadowBoard();
608 res = calcBestWeight(color1, curColor, depth, bestWeight);
609 popShadowBoard();
610 }
611 } else {
612 res = getBoardWeight(color1, curColor);
613 }
614
615 if ((res < bestWeight && color1 != curColor) || _flag4) {
616 popBoard();
617 return res;
618 }
619
620 currBoardWeight = _coeff3 + 2 * (2 * _board[color1 + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
621 while (1) {
622 if (type == 1) {
623 canMove = canMoveFunc2(curColor);
624 } else if (type == 2) {
625 canMove = canMoveFunc1(curColor);
626 } else {
627 canMove = canMoveFunc3(curColor);
628 }
629
630 if (!canMove)
631 break;
632 if (_flag1) {
633 popBoard();
634 return bestWeight + 1;
635 }
636 if (_board[55] == 2) {
637 if (getBoardWeight(color1, curColor) == currBoardWeight)
638 continue;
639 }
640 if (!depth) {
641 weight = getBoardWeight(color1, curColor);
642 if (type == 1) {
643 if (_board[55] == 2)
644 _board[56] = 16;
645 }
646 } else {
647 makeMove(curColor);
648 if (type != 1) {
649 pushShadowBoard();
650 weight = calcBestWeight(color1, curColor, depth, bestWeight);
651 popShadowBoard();
652 } else {
653 weight = calcBestWeight(color1, curColor, depth, bestWeight);
654 }
655 }
656 if ((weight < res && color1 != curColor) || (weight > res && color1 == curColor))
657 res = weight;
658
659 if ((res < bestWeight && color1 != curColor) || _flag4)
660 break;
661 }
662 popBoard();
663
664 return res;
665 }
666
doGame(int8 color,int depth)667 int16 CellGame::doGame(int8 color, int depth) {
668 bool canMove;
669 int type;
670
671 countAllCells();
672 if (_board[color + 48] >= 49 - _board[49] - _board[50] - _board[51] - _board[52]) {
673 resetMove();
674 canMove = canMoveFunc2(color);
675 type = true;
676 } else {
677 copyToShadowBoard();
678 canMove = canMoveFunc1(color);
679 type = false;
680 }
681
682 if (canMove) {
683 int8 w1, w2;
684 if (_board[color + 48] - _board[49] - _board[50] - _board[51] - _board[52] == 0)
685 depth = 0;
686 _coeff3 = 0;
687 if (_board[55] == 1)
688 _coeff3 = 1;
689 clearMoves();
690 if (depth) {
691 makeMove(color);
692 _flag4 = false;
693 if (type) {
694 w2 = calcBestWeight(color, color, depth, -127);
695 } else {
696 pushShadowBoard();
697 w2 = calcBestWeight(color, color, depth, -127);
698 popShadowBoard();
699 }
700 } else {
701 w2 = getBoardWeight(color, color);
702 }
703 int8 currBoardWeight = 2 * (2 * _board[color + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
704 while (1) {
705 if (type)
706 canMove = canMoveFunc2(color);
707 else
708 canMove = canMoveFunc1(color);
709
710 if (!canMove)
711 break;
712 if (_flag1)
713 break;
714 _coeff3 = 0;
715 if (_board[55] == 2) {
716 if (getBoardWeight(color, color) == currBoardWeight)
717 continue;
718 }
719 if (_board[55] == 1)
720 _coeff3 = 1;
721 if (depth) {
722 makeMove(color);
723 _flag4 = false;
724 if (type) {
725 w1 = calcBestWeight(color, color, depth, w2);
726 } else {
727 pushShadowBoard();
728 w1 = calcBestWeight(color, color, depth, w2);
729 popShadowBoard();
730 }
731 } else {
732 w1 = getBoardWeight(color, color);
733 }
734 if (w1 == w2)
735 pushMove();
736
737 if (w1 > w2) {
738 clearMoves();
739 w2 = w1;
740 }
741 }
742 chooseBestMove(color);
743 return 1;
744 }
745
746 return 0;
747 }
748
749 const int8 depths[] = { 1, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 3, 2, 2, 3, 3, 2, 3, 3, 3 };
750
calcMove(int8 color,uint16 depth)751 int16 CellGame::calcMove(int8 color, uint16 depth) {
752 int result = 0;
753
754 _flag1 = false;
755 ++_moveCount;
756 if (depth) {
757 if (depth == 1) {
758 _flag2 = true;
759 result = doGame(color, 0);
760 } else {
761 int newDepth;
762
763 newDepth = depths[3 * (depth - 2) + _moveCount % 3];
764 _flag2 = true;
765 if (newDepth >= 20) {
766 assert(0); // This branch is not implemented
767 } else {
768 result = doGame(color, newDepth);
769 }
770 }
771 } else {
772 _flag2 = false;
773 result = doGame(color, depth);
774 }
775 return result;
776 }
777
playStauf(byte color,uint16 depth,byte * scriptBoard)778 int CellGame::playStauf(byte color, uint16 depth, byte *scriptBoard) {
779 int i;
780
781 for (i = 0; i < 49; i++, scriptBoard++) {
782 _board[i] = 0;
783 if (*scriptBoard == 50)
784 _board[i] = 1;
785 if (*scriptBoard == 66)
786 _board[i] = 2;
787 }
788 for (i = 49; i < 57; i++)
789 _board[i] = 0;
790
791 return calcMove(color, depth);
792 }
793
794
795 } // End of Groovie namespace
796