Initial commit
This commit is contained in:
800
engines/groovie/logic/cell.cpp
Normal file
800
engines/groovie/logic/cell.cpp
Normal file
@@ -0,0 +1,800 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
* This file is dual-licensed.
|
||||
* In addition to the GPLv3 license mentioned above, MojoTouch has exclusively licensed
|
||||
* this code on November 10th, 2021, to be use in closed-source products.
|
||||
* Therefore, any contributions (commits) to it will also be dual-licensed.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "groovie/logic/cell.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
namespace Groovie {
|
||||
|
||||
CellGame::CellGame(bool easierAi) {
|
||||
_startX = _startY = _endX = _endY = 255;
|
||||
|
||||
_stack_index = _boardStackPtr = 0;
|
||||
_flag4 = false;
|
||||
_flag2 = false;
|
||||
_flag1 = false;
|
||||
_coeff3 = 0;
|
||||
|
||||
_moveCount = 0;
|
||||
_easierAi = easierAi;
|
||||
}
|
||||
|
||||
byte CellGame::getStartX() {
|
||||
if (_startX > BOARDSIZE) {
|
||||
warning ("CellGame::getStartX: not calculated yet (%d)!", _startX);
|
||||
return 0;
|
||||
} else {
|
||||
return _startX;
|
||||
}
|
||||
}
|
||||
|
||||
byte CellGame::getStartY() {
|
||||
if (_startY > BOARDSIZE) {
|
||||
warning ("CellGame::getStartY: not calculated yet (%d)!", _startY);
|
||||
return 6;
|
||||
} else {
|
||||
return _startY;
|
||||
}
|
||||
}
|
||||
|
||||
byte CellGame::getEndX() {
|
||||
if (_endX > BOARDSIZE) {
|
||||
warning ("CellGame::getEndX: not calculated yet (%d)!", _endX);
|
||||
return 1;
|
||||
} else {
|
||||
return _endX;
|
||||
}
|
||||
}
|
||||
|
||||
byte CellGame::getEndY() {
|
||||
if (_endY > BOARDSIZE) {
|
||||
warning ("CellGame::getEndY: not calculated yet (%d)!", _endY);
|
||||
return 6;
|
||||
} else {
|
||||
return _endY;
|
||||
}
|
||||
}
|
||||
|
||||
CellGame::~CellGame() {
|
||||
}
|
||||
|
||||
const int8 possibleMoves[][9] = {
|
||||
{ 1, 7, 8, -1 },
|
||||
{ 0, 2, 7, 8, 9, -1 },
|
||||
{ 1, 3, 8, 9, 10, -1 },
|
||||
{ 2, 4, 9, 10, 11, -1 },
|
||||
{ 3, 5, 10, 11, 12, -1 },
|
||||
{ 4, 6, 11, 12, 13, -1 }, // 5
|
||||
{ 5, 12, 13, -1 },
|
||||
{ 0, 1, 8, 14, 15, -1 },
|
||||
{ 0, 1, 2, 7, 9, 14, 15, 16, -1 },
|
||||
{ 1, 2, 3, 8, 10, 15, 16, 17, -1 },
|
||||
{ 2, 3, 4, 9, 11, 16, 17, 18, -1 }, // 10
|
||||
{ 3, 4, 5, 10, 12, 17, 18, 19, -1 },
|
||||
{ 4, 5, 6, 11, 13, 18, 19, 20, -1 },
|
||||
{ 5, 6, 12, 19, 20, -1 },
|
||||
{ 7, 8, 15, 21, 22, -1 },
|
||||
{ 7, 8, 9, 14, 16, 21, 22, 23, -1 }, // 15
|
||||
{ 8, 9, 10, 15, 17, 22, 23, 24, -1 },
|
||||
{ 9, 10, 11, 16, 18, 23, 24, 25, -1 },
|
||||
{ 10, 11, 12, 17, 19, 24, 25, 26, -1 },
|
||||
{ 11, 12, 13, 18, 20, 25, 26, 27, -1 },
|
||||
{ 12, 13, 19, 26, 27, -1 }, // 20
|
||||
{ 14, 15, 22, 28, 29, -1 },
|
||||
{ 14, 15, 16, 21, 23, 28, 29, 30, -1 },
|
||||
{ 15, 16, 17, 22, 24, 29, 30, 31, -1 },
|
||||
{ 16, 17, 18, 23, 25, 30, 31, 32, -1 },
|
||||
{ 17, 18, 19, 24, 26, 31, 32, 33, -1 }, // 25
|
||||
{ 18, 19, 20, 25, 27, 32, 33, 34, -1 },
|
||||
{ 19, 20, 26, 33, 34, -1 },
|
||||
{ 21, 22, 29, 35, 36, -1 },
|
||||
{ 21, 22, 23, 28, 30, 35, 36, 37, -1 },
|
||||
{ 22, 23, 24, 29, 31, 36, 37, 38, -1 }, // 30
|
||||
{ 23, 24, 25, 30, 32, 37, 38, 39, -1 },
|
||||
{ 24, 25, 26, 31, 33, 38, 39, 40, -1 },
|
||||
{ 25, 26, 27, 32, 34, 39, 40, 41, -1 },
|
||||
{ 26, 27, 33, 40, 41, -1 },
|
||||
{ 28, 29, 36, 42, 43, -1 }, // 35
|
||||
{ 28, 29, 30, 35, 37, 42, 43, 44, -1 },
|
||||
{ 29, 30, 31, 36, 38, 43, 44, 45, -1 },
|
||||
{ 30, 31, 32, 37, 39, 44, 45, 46, -1 },
|
||||
{ 31, 32, 33, 38, 40, 45, 46, 47, -1 },
|
||||
{ 32, 33, 34, 39, 41, 46, 47, 48, -1 }, // 40
|
||||
{ 33, 34, 40, 47, 48, -1 },
|
||||
{ 35, 36, 43, -1 },
|
||||
{ 35, 36, 37, 42, 44, -1 },
|
||||
{ 36, 37, 38, 43, 45, -1 },
|
||||
{ 37, 38, 39, 44, 46, -1 }, // 45
|
||||
{ 38, 39, 40, 45, 47, -1 },
|
||||
{ 39, 40, 41, 46, 48, -1 },
|
||||
{ 40, 41, 47, -1 }
|
||||
};
|
||||
|
||||
|
||||
const int8 strategy2[][17] = {
|
||||
{ 2, 9, 14, 15, 16, -1 },
|
||||
{ 3, 10, 14, 15, 16, 17, -1 },
|
||||
{ 0, 4, 7, 11, 14, 15, 16, 17, 18, -1 },
|
||||
{ 1, 5, 8, 12, 15, 16, 17, 18, 19, -1 },
|
||||
{ 2, 6, 9, 13, 16, 17, 18, 19, 20, -1 },
|
||||
{ 3, 10, 17, 18, 19, 20, -1 }, // 5
|
||||
{ 4, 11, 18, 19, 20, -1 },
|
||||
{ 2, 9, 16, 21, 22, 23, -1 },
|
||||
{ 3, 10, 17, 21, 22, 23, 24, -1 },
|
||||
{ 0, 4, 7, 11, 14, 18, 21, 22, 23, 24, 25, -1 },
|
||||
{ 1, 5, 8, 12, 15, 19, 22, 23, 24, 25, 26, -1 }, // 10
|
||||
{ 2, 6, 9, 13, 16, 20, 23, 24, 25, 26, 27, -1 },
|
||||
{ 3, 10, 17, 24, 25, 26, 27, -1 },
|
||||
{ 4, 11, 18, 25, 26, 27, -1 },
|
||||
{ 0, 1, 2, 9, 16, 23, 28, 29, 30, -1 },
|
||||
{ 0, 1, 2, 3, 10, 17, 24, 28, 29, 30, 31, -1 }, // 15
|
||||
{ 0, 1, 2, 3, 4, 7, 11, 14, 18, 21, 25, 28, 29, 30, 31, 32, -1 },
|
||||
{ 1, 2, 3, 4, 5, 8, 12, 15, 19, 22, 26, 29, 30, 31, 32, 33, -1 },
|
||||
{ 2, 3, 4, 5, 6, 9, 13, 16, 20, 23, 27, 30, 31, 32, 33, 34, -1 },
|
||||
{ 3, 4, 5, 6, 10, 17, 24, 31, 32, 33, 34, -1 },
|
||||
{ 4, 5, 6, 11, 18, 25, 32, 33, 34, -1 }, // 20
|
||||
{ 7, 8, 9, 16, 23, 30, 35, 36, 37, -1 },
|
||||
{ 7, 8, 9, 10, 17, 24, 31, 35, 36, 37, 38, -1 },
|
||||
{ 7, 8, 9, 10, 11, 14, 18, 21, 25, 28, 32, 35, 36, 37, 38, 39, -1 },
|
||||
{ 8, 9, 10, 11, 12, 15, 19, 22, 26, 29, 33, 36, 37, 38, 39, 40, -1 },
|
||||
{ 9, 10, 11, 12, 13, 16, 20, 23, 27, 30, 34, 37, 38, 39, 40, 41, -1 }, // 25
|
||||
{ 10, 11, 12, 13, 17, 24, 31, 38, 39, 40, 41, -1 },
|
||||
{ 11, 12, 13, 18, 25, 32, 39, 40, 41, -1 },
|
||||
{ 14, 15, 16, 23, 30, 37, 42, 43, 44, -1 },
|
||||
{ 14, 15, 16, 17, 24, 31, 38, 42, 43, 44, 45, -1 },
|
||||
{ 14, 15, 16, 17, 18, 21, 25, 28, 32, 35, 39, 42, 43, 44, 45, 46, -1 }, // 30
|
||||
{ 15, 16, 17, 18, 19, 22, 26, 29, 33, 36, 40, 43, 44, 45, 46, 47, -1 },
|
||||
{ 16, 17, 18, 19, 20, 23, 27, 30, 34, 37, 41, 44, 45, 46, 47, 48, -1 },
|
||||
{ 17, 18, 19, 20, 24, 31, 38, 45, 46, 47, 48, -1 },
|
||||
{ 18, 19, 20, 25, 32, 39, 46, 47, 48, -1 },
|
||||
{ 21, 22, 23, 30, 37, 44, -1 }, // 35
|
||||
{ 21, 22, 23, 24, 31, 38, 45, -1 },
|
||||
{ 21, 22, 23, 24, 25, 28, 32, 35, 39, 42, 46, -1 },
|
||||
{ 22, 23, 24, 25, 26, 29, 33, 36, 40, 43, 47, -1 },
|
||||
{ 23, 24, 25, 26, 27, 30, 34, 37, 41, 44, 48, -1 },
|
||||
{ 24, 25, 26, 27, 31, 38, 45, -1 }, // 40
|
||||
{ 25, 26, 27, 32, 39, 46, -1 },
|
||||
{ 28, 29, 30, 37, 44, -1 },
|
||||
{ 28, 29, 30, 31, 38, 45, -1 },
|
||||
{ 28, 29, 30, 31, 32, 35, 39, 42, 46, -1 },
|
||||
{ 29, 30, 31, 32, 33, 36, 40, 43, 47, -1 }, // 45
|
||||
{ 30, 31, 32, 33, 34, 37, 41, 44, 48, -1 },
|
||||
{ 31, 32, 33, 34, 38, 45, -1 },
|
||||
{ 32, 33, 34, 39, 46, -1 }
|
||||
};
|
||||
|
||||
void CellGame::copyToTempBoard() {
|
||||
for (int i = 0; i < 53; ++i) {
|
||||
_tempBoard[i] = _board[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::copyFromTempBoard() {
|
||||
for (int i = 0; i < 53; ++i) {
|
||||
_board[i] = _tempBoard[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::copyToShadowBoard() {
|
||||
_board[53] = 0;
|
||||
_board[55] = 1;
|
||||
_board[56] = 0;
|
||||
|
||||
for (int i = 0; i < 49; ++i) {
|
||||
_shadowBoard[i] = _board[i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::pushBoard() {
|
||||
assert(_boardStackPtr < 57 * 9);
|
||||
|
||||
for (int i = 0; i < 57; ++i)
|
||||
_boardStack[_boardStackPtr + i] = _board[i];
|
||||
_boardStackPtr += 57;
|
||||
}
|
||||
|
||||
void CellGame::popBoard() {
|
||||
assert(_boardStackPtr > 0);
|
||||
|
||||
_boardStackPtr -= 57;
|
||||
for (int i = 0; i < 57; ++i) {
|
||||
_board[i] = _boardStack[_boardStackPtr + i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::pushShadowBoard() {
|
||||
assert(_boardStackPtr < 57 * 9);
|
||||
|
||||
for (int i = 0; i < 57; ++i)
|
||||
_boardStack[_boardStackPtr + i] = _shadowBoard[i];
|
||||
|
||||
_boardStackPtr += 57;
|
||||
}
|
||||
|
||||
void CellGame::popShadowBoard() {
|
||||
assert(_boardStackPtr > 0);
|
||||
|
||||
_boardStackPtr -= 57;
|
||||
|
||||
for (int i = 0; i < 57; ++i) {
|
||||
_shadowBoard[i] = _boardStack[_boardStackPtr + i];
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::clearMoves() {
|
||||
_stack_startXY[0] = _board[53];
|
||||
_stack_endXY[0] = _board[54];
|
||||
_stack_pass[0] = _board[55];
|
||||
|
||||
_stack_index = 1;
|
||||
}
|
||||
|
||||
void CellGame::pushMove() {
|
||||
_stack_startXY[_stack_index] = _board[53];
|
||||
_stack_endXY[_stack_index] = _board[54];
|
||||
_stack_pass[_stack_index] = _board[55];
|
||||
|
||||
_stack_index++;
|
||||
}
|
||||
|
||||
void CellGame::resetMove() {
|
||||
_board[53] = 0;
|
||||
_board[54] = 0;
|
||||
_board[55] = 0;
|
||||
}
|
||||
|
||||
void CellGame::takeCells(uint16 whereTo, int8 color) {
|
||||
int cellN;
|
||||
const int8 *str;
|
||||
|
||||
str = possibleMoves[whereTo];
|
||||
while (1) {
|
||||
cellN = *str++;
|
||||
if (cellN < 0)
|
||||
break;
|
||||
if (_tempBoard[cellN] > 0) {
|
||||
--_tempBoard[_tempBoard[cellN] + 48];
|
||||
_tempBoard[cellN] = color;
|
||||
++_tempBoard[color + 48];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::countAllCells() {
|
||||
_board[49] = 0;
|
||||
_board[50] = 0;
|
||||
_board[51] = 0;
|
||||
_board[52] = 0;
|
||||
|
||||
for (int i = 0; i < 49; i++) {
|
||||
switch (_board[i]) {
|
||||
case 1: // CELL_BLUE
|
||||
_board[49]++;
|
||||
break;
|
||||
case 2: // CELL_GREEN
|
||||
_board[50]++;
|
||||
break;
|
||||
case 3:
|
||||
_board[51]++;
|
||||
break;
|
||||
case 4:
|
||||
_board[52]++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CellGame::countCellsOnTempBoard(int8 color) {
|
||||
const int8 *str;
|
||||
int res = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 49; i++)
|
||||
_boardSum[i] = 0;
|
||||
|
||||
for (i = 0; i < 49; i++) {
|
||||
if (_tempBoard[i] == color) {
|
||||
for (str = possibleMoves[i]; *str > 0; str++) {
|
||||
if (!_tempBoard[*str])
|
||||
++_boardSum[*str];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 49; i++)
|
||||
res += _boardSum[i];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool CellGame::canMoveFunc1(int8 color) {
|
||||
const int8 *str;
|
||||
|
||||
if (_board[55] == 1) {
|
||||
for (; _board[53] < 49; _board[53]++) {
|
||||
if (_shadowBoard[_board[53]] == color) {
|
||||
str = &possibleMoves[_board[53]][_board[56]];
|
||||
for (;_board[56] < 8; _board[56]++) {
|
||||
_board[54] = *str++;
|
||||
if (_board[54] < 0)
|
||||
break;
|
||||
if (!_shadowBoard[_board[54]]) {
|
||||
_shadowBoard[_board[54]] = -1;
|
||||
++_board[56];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_board[56] = 0;
|
||||
}
|
||||
}
|
||||
_board[53] = 0;
|
||||
_board[55] = 2;
|
||||
_board[56] = 0;
|
||||
}
|
||||
if (_board[55] == 2) {
|
||||
for (; _board[53] < 49; _board[53]++) {
|
||||
if (_shadowBoard[_board[53]] == color) {
|
||||
str = &strategy2[_board[53]][_board[56]];
|
||||
for (;_board[56] < 16; _board[56]++) {
|
||||
_board[54] = *str++;
|
||||
if (_board[54] < 0)
|
||||
break;
|
||||
if (!_board[_board[54]]) {
|
||||
++_board[56];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_board[56] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CellGame::canMoveFunc3(int8 color) {
|
||||
const int8 *str;
|
||||
|
||||
if (_board[55] == 1) {
|
||||
for (; _board[53] < 49; _board[53]++) {
|
||||
if (_shadowBoard[_board[53]] == color) {
|
||||
str = &possibleMoves[_board[53]][_board[56]];
|
||||
for (;_board[56] < 8; _board[56]++) {
|
||||
_board[54] = *str++;
|
||||
if (_board[54] < 0)
|
||||
break;
|
||||
if (!_shadowBoard[_board[54]]) {
|
||||
_shadowBoard[_board[54]] = -1;
|
||||
++_board[56];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_board[56] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_board[53] = 0;
|
||||
_board[55] = 2;
|
||||
_board[56] = 0;
|
||||
for (int i = 0; i < 49; ++i)
|
||||
_shadowBoard[i] = _board[i];
|
||||
}
|
||||
if (_board[55] == 2) {
|
||||
for (; _board[53] < 49; _board[53]++) {
|
||||
if (_shadowBoard[_board[53]] == color) {
|
||||
str = &strategy2[_board[53]][_board[56]];
|
||||
for (;_board[56] < 16; _board[56]++) {
|
||||
_board[54] = *str++;
|
||||
if (_board[54] < 0)
|
||||
break;
|
||||
if (!_shadowBoard[_board[54]]) {
|
||||
_shadowBoard[_board[54]] = -1;
|
||||
++_board[56];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_board[56] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CellGame::canMoveFunc2(int8 color) {
|
||||
const int8 *str;
|
||||
|
||||
while (1) {
|
||||
while (_board[_board[54]]) {
|
||||
++_board[54];
|
||||
if (_board[54] >= 49)
|
||||
return false;
|
||||
}
|
||||
if (!_board[55]) {
|
||||
str = possibleMoves[_board[54]];
|
||||
while (1) {
|
||||
_board[53] = *str++;
|
||||
if (_board[53] < 0)
|
||||
break;
|
||||
if (_board[_board[53]] == color) {
|
||||
_board[55] = 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_board[55] = 1;
|
||||
}
|
||||
if (_board[55] == 1) {
|
||||
_board[55] = 2;
|
||||
_board[56] = 0;
|
||||
}
|
||||
if (_board[55] == 2) {
|
||||
str = &strategy2[_board[54]][_board[56]];
|
||||
for (; _board[56] < 16; _board[56]++) {
|
||||
_board[53] = *str++;
|
||||
if (_board[53] < 0)
|
||||
break;
|
||||
if (_board[_board[53]] == color) {
|
||||
++_board[56];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++_board[54];
|
||||
_board[55] = 0;
|
||||
if (_board[54] >= 49)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CellGame::makeMove(int8 color) {
|
||||
copyToTempBoard();
|
||||
_tempBoard[_board[54]] = color;
|
||||
++_tempBoard[color + 48];
|
||||
if (_board[55] == 2) {
|
||||
_tempBoard[_board[53]] = 0;
|
||||
--_tempBoard[color + 48];
|
||||
}
|
||||
takeCells(_board[54], color);
|
||||
}
|
||||
|
||||
int CellGame::getBoardWeight(int8 color1, int8 color2) {
|
||||
int8 celln;
|
||||
const int8 *str;
|
||||
byte cellCnt[8];
|
||||
|
||||
str = possibleMoves[_board[54]];
|
||||
cellCnt[1] = _board[49];
|
||||
cellCnt[2] = _board[50];
|
||||
cellCnt[3] = _board[51];
|
||||
cellCnt[4] = _board[52];
|
||||
if (_board[55] != 2)
|
||||
++cellCnt[color2];
|
||||
celln = *str++;
|
||||
|
||||
celln = _board[celln];
|
||||
if (celln > 0) {
|
||||
--cellCnt[celln];
|
||||
++cellCnt[color2];
|
||||
}
|
||||
celln = *str++;
|
||||
|
||||
celln = _board[celln];
|
||||
if (celln > 0) {
|
||||
--cellCnt[celln];
|
||||
++cellCnt[color2];
|
||||
}
|
||||
celln = *str++;
|
||||
|
||||
celln = _board[celln];
|
||||
if (celln > 0) {
|
||||
--cellCnt[celln];
|
||||
++cellCnt[color2];
|
||||
}
|
||||
while (1) {
|
||||
celln = *str++;
|
||||
if (celln < 0)
|
||||
break;
|
||||
celln = _board[celln];
|
||||
if (celln > 0) {
|
||||
--cellCnt[celln];
|
||||
++cellCnt[color2];
|
||||
}
|
||||
}
|
||||
return _coeff3 + 2 * (2 * cellCnt[color1] - cellCnt[1] - cellCnt[2] - cellCnt[3] - cellCnt[4]);
|
||||
}
|
||||
|
||||
void CellGame::chooseBestMove(int8 color) {
|
||||
int moveIndex = 0;
|
||||
|
||||
if (_flag2) {
|
||||
int bestWeight = 32767;
|
||||
for (int i = 0; i < _stack_index; ++i) {
|
||||
_board[53] = _stack_startXY[i];
|
||||
_board[54] = _stack_endXY[i];
|
||||
_board[55] = _stack_pass[i];
|
||||
makeMove(color);
|
||||
int curWeight = countCellsOnTempBoard(color);
|
||||
if (curWeight <= bestWeight) {
|
||||
if (curWeight < bestWeight)
|
||||
moveIndex = 0;
|
||||
bestWeight = curWeight;
|
||||
_stack_startXY[moveIndex] = _board[53];
|
||||
_stack_endXY[moveIndex] = _board[54];
|
||||
_stack_pass[moveIndex++] = _board[55];
|
||||
}
|
||||
}
|
||||
_stack_index = moveIndex;
|
||||
}
|
||||
|
||||
_startX = _stack_startXY[0] % 7;
|
||||
_startY = _stack_startXY[0] / 7;
|
||||
_endX = _stack_endXY[0] % 7;
|
||||
_endY = _stack_endXY[0] / 7;
|
||||
}
|
||||
|
||||
int8 CellGame::calcBestWeight(int8 color1, int8 color2, uint16 depth, int bestWeight) {
|
||||
int8 res;
|
||||
int8 curColor;
|
||||
bool canMove;
|
||||
int type;
|
||||
uint16 i;
|
||||
int8 currBoardWeight;
|
||||
int8 weight;
|
||||
|
||||
pushBoard();
|
||||
copyFromTempBoard();
|
||||
curColor = color2;
|
||||
for (i = 0;; ++i) {
|
||||
if (i >= 4) {
|
||||
res = _coeff3 + 2 * (2 * _board[color1 + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
|
||||
popBoard();
|
||||
return res;
|
||||
}
|
||||
++curColor;
|
||||
if (curColor > 4)
|
||||
curColor = 1;
|
||||
|
||||
if (_board[curColor + 48]) {
|
||||
if (_board[curColor + 48] >= 49 - _board[49] - _board[50] - _board[51] - _board[52]) {
|
||||
resetMove();
|
||||
canMove = canMoveFunc2(curColor);
|
||||
type = 1;
|
||||
} else {
|
||||
copyToShadowBoard();
|
||||
if (depth == 1) {
|
||||
canMove = canMoveFunc3(curColor);
|
||||
type = 3;
|
||||
} else {
|
||||
canMove = canMoveFunc1(curColor);
|
||||
type = 2;
|
||||
}
|
||||
}
|
||||
if (canMove)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (_flag1) {
|
||||
popBoard();
|
||||
return bestWeight + 1;
|
||||
}
|
||||
|
||||
depth -= 1;
|
||||
if (depth) {
|
||||
makeMove(curColor);
|
||||
if (type == 1) {
|
||||
res = calcBestWeight(color1, curColor, depth, bestWeight);
|
||||
} else {
|
||||
pushShadowBoard();
|
||||
res = calcBestWeight(color1, curColor, depth, bestWeight);
|
||||
popShadowBoard();
|
||||
}
|
||||
} else {
|
||||
res = getBoardWeight(color1, curColor);
|
||||
}
|
||||
|
||||
if ((res < bestWeight && color1 != curColor) || _flag4) {
|
||||
popBoard();
|
||||
return res;
|
||||
}
|
||||
|
||||
currBoardWeight = _coeff3 + 2 * (2 * _board[color1 + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
|
||||
while (1) {
|
||||
if (type == 1) {
|
||||
canMove = canMoveFunc2(curColor);
|
||||
} else if (type == 2) {
|
||||
canMove = canMoveFunc1(curColor);
|
||||
} else {
|
||||
canMove = canMoveFunc3(curColor);
|
||||
}
|
||||
|
||||
if (!canMove)
|
||||
break;
|
||||
if (_flag1) {
|
||||
popBoard();
|
||||
return bestWeight + 1;
|
||||
}
|
||||
if (_board[55] == 2) {
|
||||
if (getBoardWeight(color1, curColor) == currBoardWeight)
|
||||
continue;
|
||||
}
|
||||
if (!depth) {
|
||||
weight = getBoardWeight(color1, curColor);
|
||||
if (type == 1) {
|
||||
if (_board[55] == 2)
|
||||
_board[56] = 16;
|
||||
}
|
||||
} else {
|
||||
makeMove(curColor);
|
||||
if (type != 1) {
|
||||
pushShadowBoard();
|
||||
weight = calcBestWeight(color1, curColor, depth, bestWeight);
|
||||
popShadowBoard();
|
||||
} else {
|
||||
weight = calcBestWeight(color1, curColor, depth, bestWeight);
|
||||
}
|
||||
}
|
||||
if ((weight < res && color1 != curColor) || (weight > res && color1 == curColor))
|
||||
res = weight;
|
||||
|
||||
if ((res < bestWeight && color1 != curColor) || _flag4)
|
||||
break;
|
||||
}
|
||||
popBoard();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void CellGame::doGame(int8 color, int depth) {
|
||||
bool canMove;
|
||||
int type;
|
||||
|
||||
countAllCells();
|
||||
if (_board[color + 48] >= 49 - _board[49] - _board[50] - _board[51] - _board[52]) {
|
||||
resetMove();
|
||||
canMove = canMoveFunc2(color);
|
||||
type = true;
|
||||
} else {
|
||||
copyToShadowBoard();
|
||||
canMove = canMoveFunc1(color);
|
||||
type = false;
|
||||
}
|
||||
|
||||
if (canMove) {
|
||||
int8 w1, w2;
|
||||
if (_board[color + 48] - _board[49] - _board[50] - _board[51] - _board[52] == 0)
|
||||
depth = 0;
|
||||
_coeff3 = 0;
|
||||
if (_board[55] == 1)
|
||||
_coeff3 = 1;
|
||||
clearMoves();
|
||||
if (depth) {
|
||||
makeMove(color);
|
||||
_flag4 = false;
|
||||
if (type) {
|
||||
w2 = calcBestWeight(color, color, depth, -127);
|
||||
} else {
|
||||
pushShadowBoard();
|
||||
w2 = calcBestWeight(color, color, depth, -127);
|
||||
popShadowBoard();
|
||||
}
|
||||
} else {
|
||||
w2 = getBoardWeight(color, color);
|
||||
}
|
||||
int8 currBoardWeight = 2 * (2 * _board[color + 48] - _board[49] - _board[50] - _board[51] - _board[52]);
|
||||
while (1) {
|
||||
if (type)
|
||||
canMove = canMoveFunc2(color);
|
||||
else
|
||||
canMove = canMoveFunc1(color);
|
||||
|
||||
if (!canMove)
|
||||
break;
|
||||
if (_flag1)
|
||||
break;
|
||||
_coeff3 = 0;
|
||||
if (_board[55] == 2) {
|
||||
if (getBoardWeight(color, color) == currBoardWeight)
|
||||
continue;
|
||||
}
|
||||
if (_board[55] == 1)
|
||||
_coeff3 = 1;
|
||||
if (depth) {
|
||||
makeMove(color);
|
||||
_flag4 = false;
|
||||
if (type) {
|
||||
w1 = calcBestWeight(color, color, depth, w2);
|
||||
} else {
|
||||
pushShadowBoard();
|
||||
w1 = calcBestWeight(color, color, depth, w2);
|
||||
popShadowBoard();
|
||||
}
|
||||
} else {
|
||||
w1 = getBoardWeight(color, color);
|
||||
}
|
||||
if (w1 == w2)
|
||||
pushMove();
|
||||
|
||||
if (w1 > w2) {
|
||||
clearMoves();
|
||||
w2 = w1;
|
||||
}
|
||||
}
|
||||
chooseBestMove(color);
|
||||
}
|
||||
}
|
||||
|
||||
const int8 depths[] = { 1, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2, 3, 2, 2, 3, 3, 2, 3, 3, 3 };
|
||||
|
||||
void CellGame::calcMove(int8 color, uint16 depth) {
|
||||
_flag1 = false;
|
||||
++_moveCount;
|
||||
if (depth) {
|
||||
if (depth == 1) {
|
||||
_flag2 = true;
|
||||
doGame(color, 0);
|
||||
} else {
|
||||
int newDepth;
|
||||
|
||||
newDepth = depths[3 * (depth - 2) + _moveCount % 3];
|
||||
if (_easierAi && _moveCount > 7)
|
||||
newDepth = 1;
|
||||
|
||||
_flag2 = true;
|
||||
if (newDepth >= 20) {
|
||||
assert(0); // This branch is not implemented
|
||||
} else {
|
||||
doGame(color, newDepth);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_flag2 = false;
|
||||
doGame(color, depth);
|
||||
}
|
||||
}
|
||||
|
||||
void CellGame::run(uint16 depth, byte *scriptBoard) {
|
||||
const byte color = 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 49; i++, scriptBoard++) {
|
||||
_board[i] = 0;
|
||||
if (*scriptBoard == 50)
|
||||
_board[i] = 1;
|
||||
if (*scriptBoard == 66)
|
||||
_board[i] = 2;
|
||||
}
|
||||
for (i = 49; i < 57; i++)
|
||||
_board[i] = 0;
|
||||
|
||||
calcMove(color, depth);
|
||||
}
|
||||
|
||||
|
||||
} // End of Groovie namespace
|
||||
Reference in New Issue
Block a user