mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 05:38:56 +00:00
6561a7bf36
svn-id: r35651
183 lines
5.3 KiB
C++
183 lines
5.3 KiB
C++
/* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* $URL$
|
|
* $Id$
|
|
*
|
|
*/
|
|
|
|
#include "groovie/cell.h"
|
|
|
|
namespace Groovie {
|
|
|
|
CellGame::CellGame(byte *board) :
|
|
_board(board) {
|
|
_startX = _startY = _endX = _endY = 255;
|
|
}
|
|
|
|
int8 CellGame::calcMove(byte *origboard, uint8 color, uint8 depth) {
|
|
uint8 i, j;
|
|
int8 di, dj;
|
|
uint8 bestStartX, bestStartY, bestEndX, bestEndY;
|
|
int8 bestDiff = -100;
|
|
int8 origBoardCount = countBoard(origboard, color);
|
|
int8 currDiff = -100;
|
|
byte *newboard;
|
|
uint8 boardmemsize = sizeof(byte) * BOARDSIZE * BOARDSIZE;
|
|
uint8 oppColor = 3 - color;
|
|
|
|
bestStartX = bestStartY = bestEndX = bestEndY = 255;
|
|
newboard = (byte*) malloc(boardmemsize);
|
|
memcpy(newboard, origboard, boardmemsize);
|
|
|
|
if (0 == depth) {
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0; BOARDSIZE > i; i++) { // For every square on the board
|
|
for (j = 0; BOARDSIZE > j; j++) { //
|
|
if (color == *(origboard + i + (BOARDSIZE * j))) { // If the square is the desired colour
|
|
for (di = -2; 2 >= di; di++) { // Check every square two or less in every direction
|
|
for (dj = -2; 2 >= dj; dj++) { //
|
|
if (di != 0 || dj != 0) { // Don't allow a move onto itself
|
|
debugC(7, kGroovieDebugCell | kGroovieDebugAll, "Depth: %d: Testing move %d, %d-> %d, %d", depth, i, j, i+di, j+dj);
|
|
if (validMove(origboard, color, i+di, j+dj)) {
|
|
int8 nextlevel;
|
|
debugC(5, kGroovieDebugCell | kGroovieDebugAll, "Depth: %d: Valid move %d, %d-> %d, %d", depth, i, j, i+di, j+dj);
|
|
execMove (newboard, color, i, j, i+di, j+dj);
|
|
|
|
nextlevel = calcMove (newboard, oppColor, depth - 1);
|
|
debugC(5, kGroovieDebugCell | kGroovieDebugAll, "Depth: %d: Next level down returned %d", depth, nextlevel);
|
|
currDiff = countBoard(newboard, color) - origBoardCount - nextlevel;
|
|
if (currDiff > bestDiff) {
|
|
debugC(4, kGroovieDebugCell | kGroovieDebugAll, "Depth: %d: Found new best move (diff of %d): %d, %d-> %d, %d", depth, currDiff, i, j, i+di, j+dj);
|
|
bestDiff = currDiff;
|
|
bestStartX = i;
|
|
bestStartY = j;
|
|
bestEndX = i+di;
|
|
bestEndY = j+dj;
|
|
|
|
}
|
|
// TODO: ideal would be to revert the move, rather than copy the board again. I think.
|
|
memcpy(newboard, origboard, boardmemsize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
_startX = bestStartX;
|
|
_startY = bestStartY;
|
|
_endX = bestEndX;
|
|
_endY = bestEndY;
|
|
|
|
debugC(2, kGroovieDebugCell | kGroovieDebugAll, "Depth: %d: Best move is (diff of %d): %d, %d-> %d, %d", depth, bestDiff, _startX, _startY, _endX, _endY);
|
|
free(newboard);
|
|
debugC(5, kGroovieDebugCell | kGroovieDebugAll, "Freed newboard");
|
|
return bestDiff;
|
|
}
|
|
|
|
void CellGame::execMove(byte *board, uint8 color, int8 startX, int8 startY, int8 endX, int8 endY) {
|
|
int8 i, j;
|
|
uint8 colorToEat = 3 - color; // The opposite of the colour passed: 2 -> 1, 1 -> 2
|
|
|
|
if (abs(endX - startX) == 2 || abs(endY - startY) == 2) {
|
|
*(board + startX + BOARDSIZE * startY) = 0;
|
|
}
|
|
|
|
*(board + endX + BOARDSIZE * endY) = color;
|
|
|
|
for (i = (endX - 1); endX + 1 >= i; i++) {
|
|
for (j = (endY - 1); endY + 1 >= j; j++) {
|
|
if (BOARDSIZE > i && BOARDSIZE > j && 0 <= i && 0 <= j) { // Don't wrap around the board edges!
|
|
uint8 offset = i + BOARDSIZE * j;
|
|
if (colorToEat == *(board + offset)) {
|
|
*(board + offset) = color;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CellGame::validMove(byte *board, uint8 color, int8 endX, int8 endY) {
|
|
if (0 > endX || 0 > endY || BOARDSIZE <= endX || BOARDSIZE <= endY) { // Move is out of bounds
|
|
return false;
|
|
}
|
|
if (0 == *(board + endX + (BOARDSIZE * endY))) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint8 CellGame::countBoard(byte *board, uint8 color) {
|
|
uint8 total = 0;
|
|
for (uint8 i = 0; BOARDSIZE > i; i++) {
|
|
for (uint8 j = 0; BOARDSIZE > j; j++) {
|
|
if (color == *(board + i + (BOARDSIZE * j))) {
|
|
total++;
|
|
}
|
|
}
|
|
}
|
|
return total;
|
|
}
|
|
|
|
byte CellGame::getStartX() {
|
|
if (_startX > BOARDSIZE) {
|
|
warning ("CellGame::getStartX: not calculated yet!");
|
|
return 0;
|
|
} else {
|
|
return _startX;
|
|
}
|
|
}
|
|
|
|
byte CellGame::getStartY() {
|
|
if (_startY > BOARDSIZE) {
|
|
warning ("CellGame::getStartY: not calculated yet!");
|
|
return 6;
|
|
} else {
|
|
return _startY;
|
|
}
|
|
}
|
|
|
|
byte CellGame::getEndX() {
|
|
if (_endX > BOARDSIZE) {
|
|
warning ("CellGame::getEndX: not calculated yet!");
|
|
return 1;
|
|
} else {
|
|
return _endX;
|
|
}
|
|
}
|
|
|
|
byte CellGame::getEndY() {
|
|
if (_endY > BOARDSIZE) {
|
|
warning ("CellGame::getEndY: not calculated yet!");
|
|
return 6;
|
|
} else {
|
|
return _endY;
|
|
}
|
|
}
|
|
|
|
CellGame::~CellGame() {
|
|
}
|
|
|
|
} // End of Groovie namespace
|