[Scummvm-git-logs] scummvm master -> 992fc12c6957008abe9590a78ec6a0eb9643f78d
Die4Ever
30947252+Die4Ever at users.noreply.github.com
Sat Oct 30 22:35:40 UTC 2021
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
992fc12c69 GROOVIE: pente refactor and cleanup
Commit: 992fc12c6957008abe9590a78ec6a0eb9643f78d
https://github.com/scummvm/scummvm/commit/992fc12c6957008abe9590a78ec6a0eb9643f78d
Author: Die4Ever (die4ever2005 at gmail.com)
Date: 2021-10-30T17:35:15-05:00
Commit Message:
GROOVIE: pente refactor and cleanup
Changed paths:
engines/groovie/logic/pente.cpp
engines/groovie/logic/pente.h
diff --git a/engines/groovie/logic/pente.cpp b/engines/groovie/logic/pente.cpp
index 7c9fa71dd9..c32bc2d1eb 100644
--- a/engines/groovie/logic/pente.cpp
+++ b/engines/groovie/logic/pente.cpp
@@ -22,11 +22,15 @@
#include "groovie/logic/pente.h"
#include "common/stack.h"
+#include "common/algorithm.h"
#include "groovie/groovie.h"
-#include <limits.h>
namespace Groovie {
+#ifdef UINT_MAX
+#undef UINT_MAX
+#endif
+const uint UINT_MAX = (uint)-1;
const uint WIN_SCORE = 100000000;
const uint CAPTURE_SCORE = 1000000;
@@ -53,165 +57,91 @@ struct penteTable {
byte calcTouchingPieces; // the deepest level of AI recursion sets this to 0, and then sets it back to 1 when returning
};
-void PenteGame::penteSub02Frees(penteTable *table) {
- delete table;
+void PenteGame::addLine(int x, int y, int linesCounter) {
+ int i = ++_table->linesTable[x][y][0];
+ _table->linesTable[x][y][i] = linesCounter;
}
-void PenteGame::penteSub05BuildLookupTable(penteTable *table) {
- uint16 *puVar1;
- uint _width;
- uint uVar4;
- uint uVar5;
- byte bVar6;
- byte local_14;
- byte local_13;
- uint16 lines_counter;
- byte height;
- byte line_length;
- byte width;
-
- width = table->width;
- height = table->height;
- bVar6 = 0;
- lines_counter = 0;
- line_length = table->lineLength;
- _width = (uint)width;
-
- auto &lines_table = table->linesTable;
- local_14 = 0;
- if (height != 0) {
- do {
- local_13 = 0;
- if (-1 < (int)(_width - line_length)) {
- do {
- bVar6 = 0;
- if (line_length != 0) {
- do {
- uVar4 = (uint)bVar6;
- bVar6 += 1;
- puVar1 = lines_table[uVar4 + local_13][local_14];
- *puVar1 = *puVar1 + 1;
- puVar1 = lines_table[uVar4 + local_13][local_14];
- puVar1[*puVar1] = lines_counter;
- } while (bVar6 < line_length);
- }
- lines_counter += 1;
- local_13 += 1;
- } while ((int)(uint)local_13 <= (int)(_width - line_length));
+void PenteGame::buildLookupTable() {
+ int width = _table->width;
+ int height = _table->height;
+ uint16 linesCounter = 0;
+ int lineLength = _table->lineLength;
+
+ // slope of (1,0)
+ for (int x = 0; x <= width - lineLength; x++) {
+ for (int y = 0; y < height; y++) {
+ for (int z = 0; z < lineLength; z++) {
+ addLine(x + z, y, linesCounter);
}
- local_14 += 1;
- } while (local_14 < height);
+ linesCounter++;
+ }
}
- local_13 = 0;
- if (width != 0) {
- do {
- local_14 = 0;
- if (-1 < (int)((uint)height - (uint)line_length)) {
- do {
- if (line_length != 0) {
- uVar4 = 0;
- do {
- bVar6 = (char)uVar4 + 1;
- puVar1 = lines_table[local_13][uVar4 + local_14];
- *puVar1 = *puVar1 + 1;
- puVar1 = lines_table[local_13][uVar4 + local_14];
- puVar1[*puVar1] = lines_counter;
- uVar4 = (uint)bVar6;
- } while (bVar6 < line_length);
- }
- lines_counter += 1;
- local_14 += 1;
- } while ((int)(uint)local_14 <= (int)((uint)height - (uint)line_length));
+
+ // slope of (0,1)
+ for (int x = 0; x < width; x++) {
+ for (int y = 0; y <= height - lineLength; y++) {
+ for (int z = 0; z < lineLength; z++) {
+ addLine(x, y + z, linesCounter);
}
- local_13 += 1;
- } while (local_13 < width);
+ linesCounter++;
+ }
}
- local_14 = 0;
- uVar4 = (uint)line_length;
- if (-1 < (int)(height - uVar4)) {
- do {
- local_13 = 0;
- if (-1 < (int)(_width - uVar4)) {
- do {
- if (line_length != 0) {
- uVar5 = 0;
- do {
- width = (char)uVar5 + 1;
- puVar1 = lines_table[local_13 + uVar5][uVar5 + local_14];
- *puVar1 = *puVar1 + 1;
- puVar1 = lines_table[local_13 + uVar5][uVar5 + local_14];
- puVar1[*puVar1] = lines_counter;
- uVar5 = (uint)width;
- } while (width < line_length);
- }
- lines_counter += 1;
- local_13 += 1;
- } while ((int)(uint)local_13 <= (int)(_width - uVar4));
+
+ // slope of (1,1)
+ for (int x = 0; x <= width - lineLength; x++) {
+ for (int y = 0; y <= height - lineLength; y++) {
+ for (int z = 0; z < lineLength; z++) {
+ addLine(x + z, y + z, linesCounter);
}
- local_14 += 1;
- } while ((int)(uint)local_14 <= (int)(height - uVar4));
+ linesCounter++;
+ }
}
- local_14 = line_length - 1;
- if (local_14 < height) {
- do {
- local_13 = 0;
- if (-1 < (int)(_width - uVar4)) {
- do {
- if (line_length != 0) {
- uVar5 = 0;
- do {
- width = (char)uVar5 + 1;
- puVar1 = lines_table[local_13 + uVar5][local_14 - uVar5];
- *puVar1 = *puVar1 + 1;
- puVar1 = lines_table[local_13 + uVar5][local_14 - uVar5];
- puVar1[*puVar1] = lines_counter;
- uVar5 = (uint)width;
- } while (width < line_length);
- }
- lines_counter += 1;
- local_13 += 1;
- } while ((int)(uint)local_13 <= (int)(_width - uVar4));
+
+ // slope of (1,-1)
+ for (int x = 0; x <= width - lineLength; x++) {
+ for (int y = lineLength - 1; y < height; y++) {
+ for (int z = 0; z < lineLength; z++) {
+ addLine(x + z, y - z, linesCounter);
}
- local_14 += 1;
- } while (local_14 < height);
+ linesCounter++;
+ }
}
- table->linesCounter = lines_counter;
+
+ _table->linesCounter = linesCounter;
}
-penteTable *PenteGame::penteSub01Init(byte width, byte height, byte length) {
- penteTable *table;
- //byte bVar5;
- uint16 _height;
-
- table = new penteTable();
- table->width = width;
- table->height = height;
- _height = (uint16)height;
- table->boardSize = _height * width;
- //bVar5 = 0;
- table->lineLength = length;
- memset(table->boardState, 0, sizeof(table->boardState));
-
- penteSub05BuildLookupTable(table);
- assert(table->linesCounter == 812);
-
- //bVar5 = 0;
- table->staufScore = (uint)table->linesCounter;
- table->playerScore = (uint)table->linesCounter;
- memset(table->numAdjacentPieces, 0, sizeof(table->numAdjacentPieces));
-
- table->calcTouchingPieces = 1;
- return table;
+void PenteGame::penteDeInit() {
+ delete _table;
+ _table = NULL;
}
-uint &getPlayerTable(penteTable *table, bool staufTurn, pentePlayerTable *&pt) {
- pt = staufTurn ? &table->stauf : &table->player;
- return staufTurn ? table->staufScore : table->playerScore;
+void PenteGame::penteInit(uint width, uint height, uint length) {
+ _table = new penteTable();
+ _table->width = width;
+ _table->height = height;
+ _table->boardSize = height * width;
+ _table->lineLength = length;
+ memset(_table->boardState, 0, sizeof(_table->boardState));
+
+ buildLookupTable();
+ assert(_table->linesCounter == 812);
+
+ _table->staufScore = (uint)_table->linesCounter;
+ _table->playerScore = (uint)_table->linesCounter;
+ memset(_table->numAdjacentPieces, 0, sizeof(_table->numAdjacentPieces));
+
+ _table->calcTouchingPieces = 1;
}
-void penteScoringLine(penteTable *table, uint16 lineIndex, bool stauf_turn, bool revert) {
+uint &PenteGame::getPlayerTable(bool staufTurn, pentePlayerTable *&pt) {
+ pt = staufTurn ? &_table->stauf : &_table->player;
+ return staufTurn ? _table->staufScore : _table->playerScore;
+}
+
+void PenteGame::scoreLine(uint16 lineIndex, bool stauf_turn, bool revert) {
pentePlayerTable *playerTable;
- uint &score = getPlayerTable(table, stauf_turn, playerTable);
+ uint &score = getPlayerTable(stauf_turn, playerTable);
int lineLength, mult;
if (revert) {
@@ -222,29 +152,29 @@ void penteScoringLine(penteTable *table, uint16 lineIndex, bool stauf_turn, bool
mult = 1;
}
- if (table->lineLength - lineLength == 1) {
+ if (_table->lineLength - lineLength == 1) {
score = (int)score + (int)WIN_SCORE * mult;
} else {
pentePlayerTable *opponentTable;
- uint &opponentScore = getPlayerTable(table, !stauf_turn, opponentTable);
+ uint &opponentScore = getPlayerTable(!stauf_turn, opponentTable);
int opponentLineLength = opponentTable->lines[lineIndex];
if (lineLength == 0) {
opponentScore += (-(1 << ((byte)opponentLineLength & 0x1f))) * mult;
- if (table->lineLength - opponentLineLength == 1) {
+ if (_table->lineLength - opponentLineLength == 1) {
if (stauf_turn)
- table->playerLines -= mult;
+ _table->playerLines -= mult;
else
- table->staufLines -= mult;
+ _table->staufLines -= mult;
}
}
if (opponentLineLength == 0) {
score += (1 << ((byte)lineLength & 0x1f)) * mult;
- if (table->lineLength - lineLength == 2) {
+ if (_table->lineLength - lineLength == 2) {
byte b;
if (stauf_turn)
- b = (table->staufLines += mult);
+ b = (_table->staufLines += mult);
else
- b = (table->playerLines += mult);
+ b = (_table->playerLines += mult);
if (revert)
b -= mult;
@@ -257,19 +187,19 @@ void penteScoringLine(penteTable *table, uint16 lineIndex, bool stauf_turn, bool
}
}
-void penteTouchingPieces(penteTable *table, byte moveX, byte moveY, bool revert) {
+void PenteGame::calcTouchingPieces(byte moveX, byte moveY, bool revert) {
byte endX, endY;
- if (moveX + 1 < table->width) {
+ if (moveX + 1 < _table->width) {
endX = moveX + 1;
} else {
- endX = table->width - 1;
+ endX = _table->width - 1;
}
- if (moveY + 1 < table->height) {
+ if (moveY + 1 < _table->height) {
endY = moveY + 1;
} else {
- endY = table->height - 1;
+ endY = _table->height - 1;
}
byte x = 0;
@@ -285,46 +215,46 @@ void penteTouchingPieces(penteTable *table, byte moveX, byte moveY, bool revert)
for (; y <= endY; y++) {
if (revert)
- table->numAdjacentPieces[x][y]--;
+ _table->numAdjacentPieces[x][y]--;
else
- table->numAdjacentPieces[x][y]++;
+ _table->numAdjacentPieces[x][y]++;
}
}
}
-void PenteGame::penteSub03Scoring(penteTable *table, byte move_y, byte move_x, bool stauf_turn) {
- table->boardState[move_x][move_y] = stauf_turn ? 88 : 79;
- uint16 lines = table->linesTable[move_x][move_y][0];
+void PenteGame::updateScore(byte move_y, byte move_x, bool stauf_turn) {
+ _table->boardState[move_x][move_y] = stauf_turn ? 88 : 79;
+ uint16 lines = _table->linesTable[move_x][move_y][0];
for (int i = 1; i <= lines; i++) {
- uint16 lineIndex = table->linesTable[move_x][move_y][i];
- penteScoringLine(table, lineIndex, stauf_turn, false);
+ uint16 lineIndex = _table->linesTable[move_x][move_y][i];
+ scoreLine(lineIndex, stauf_turn, false);
}
- if (table->calcTouchingPieces != 0) {
- penteTouchingPieces(table, move_x, move_y, false);
+ if (_table->calcTouchingPieces != 0) {
+ calcTouchingPieces(move_x, move_y, false);
}
- table->moveCounter++;
+ _table->moveCounter++;
}
-void PenteGame::penteSub07RevertScore(penteTable *table, byte y, byte x) {
- bool stauf_turn = table->boardState[x][y] == 88;
- table->boardState[x][y] = 0;
- table->moveCounter--;
- uint lines = table->linesTable[x][y][0];
+void PenteGame::revertScore(byte y, byte x) {
+ bool stauf_turn = _table->boardState[x][y] == 88;
+ _table->boardState[x][y] = 0;
+ _table->moveCounter--;
+ uint lines = _table->linesTable[x][y][0];
for (uint i = 1; i <= lines; i++) {
- uint16 lineIndex = table->linesTable[x][y][i];
- penteScoringLine(table, lineIndex, stauf_turn, true);
+ uint16 lineIndex = _table->linesTable[x][y][i];
+ scoreLine(lineIndex, stauf_turn, true);
}
- if (table->calcTouchingPieces != 0) {
- penteTouchingPieces(table, x, y, true);
+ if (_table->calcTouchingPieces != 0) {
+ calcTouchingPieces(x, y, true);
}
}
-byte PenteGame::penteScoreCaptureSingle(penteTable *table, byte x, byte y, int slopeX, int slopeY) {
+byte PenteGame::scoreCaptureSingle(byte x, byte y, int slopeX, int slopeY) {
byte x1 = x + slopeX;
byte y1 = y + slopeY;
byte x2 = x + slopeX * 2;
@@ -333,12 +263,12 @@ byte PenteGame::penteScoreCaptureSingle(penteTable *table, byte x, byte y, int s
byte endY = y + slopeY * 3;
// we don't need to check for below 0 when we have unsigned types
- if (x >= table->width || y >= table->height)
+ if (x >= _table->width || y >= _table->height)
return 0;
- if (endX >= table->width || endY >= table->height)
+ if (endX >= _table->width || endY >= _table->height)
return 0;
- auto &boardState = table->boardState;
+ auto &boardState = _table->boardState;
byte captor = boardState[x][y];
byte captive = captor == 88 ? 79 : 88;
@@ -350,8 +280,8 @@ byte PenteGame::penteScoreCaptureSingle(penteTable *table, byte x, byte y, int s
if (boardState[x1][y1] != captive || boardState[x2][y2] != captive)
return 0;
- penteSub07RevertScore(table, y1, x1);
- penteSub07RevertScore(table, y2, x2);
+ revertScore(y1, x1);
+ revertScore(y2, x2);
return 1;
}
@@ -368,23 +298,23 @@ Slope slopes[] = {{1, 0},
{0, -1},
{1, -1}};
-uint PenteGame::penteSub04ScoreCapture(penteTable *table, byte y, byte x) {
+uint PenteGame::scoreCapture(byte y, byte x) {
byte bitMask = 0;
- bool isStauf = table->boardState[x][y] == 88;
+ bool isStauf = _table->boardState[x][y] == 88;
for (const Slope &slope : slopes) {
bitMask <<= 1;
- bitMask |= penteScoreCaptureSingle(table, x, y, slope.x, slope.y);
+ bitMask |= scoreCaptureSingle(x, y, slope.x, slope.y);
}
for (int i = bitMask; i; i >>= 1) {
if ((i & 1) == 0)
continue;
pentePlayerTable *playerTable;
- uint &score = getPlayerTable(table, isStauf, playerTable);
+ uint &score = getPlayerTable(isStauf, playerTable);
- int lineLength = ++playerTable->lines[table->linesCounter];
- if (table->lineLength == lineLength) {
+ int lineLength = ++playerTable->lines[_table->linesCounter];
+ if (_table->lineLength == lineLength) {
score += WIN_SCORE;
} else {
score += 1 << ((lineLength - 1U) & 0x1f);
@@ -393,7 +323,7 @@ uint PenteGame::penteSub04ScoreCapture(penteTable *table, byte y, byte x) {
return bitMask;
}
-void PenteGame::penteSub08MaybeAnimateCapture(short move, byte *bitMaskG, short *param_3, short *param_4) {
+void PenteGame::animateCapture(short move, byte *bitMaskG, short *param_3, short *param_4) {
byte x;
byte y;
@@ -452,18 +382,18 @@ void PenteGame::penteSub08MaybeAnimateCapture(short move, byte *bitMaskG, short
return;
}
-void PenteGame::penteSub11RevertCapture(penteTable *table, byte y, byte x, byte bitMask) {
- bool isPlayer = table->boardState[x][y] == 79;
+void PenteGame::revertCapture(byte y, byte x, byte bitMask) {
+ bool isPlayer = _table->boardState[x][y] == 79;
for (int i = bitMask; i; i >>= 1) {
if ((i & 1) == 0)
continue;
pentePlayerTable *playerTable;
- uint &score = getPlayerTable(table, !isPlayer, playerTable);
+ uint &score = getPlayerTable(!isPlayer, playerTable);
- int linesCounter = --playerTable->lines[table->linesCounter];
+ int linesCounter = --playerTable->lines[_table->linesCounter];
- if (table->lineLength - linesCounter == 1) {
+ if (_table->lineLength - linesCounter == 1) {
score -= WIN_SCORE;
} else {
score -= (1 << ((char)linesCounter & 0x1f));
@@ -475,244 +405,159 @@ void PenteGame::penteSub11RevertCapture(penteTable *table, byte y, byte x, byte
continue;
Slope &slope = slopes[7 - i];
- penteSub03Scoring(table, y + slope.y * 2, x + slope.x * 2, isPlayer);
- penteSub03Scoring(table, y + slope.y, x + slope.x, isPlayer);
+ updateScore(y + slope.y * 2, x + slope.x * 2, isPlayer);
+ updateScore(y + slope.y, x + slope.x, isPlayer);
}
}
-int PenteGame::penteSub10AiRecurse(penteTable *table_1, char depth, int parent_score) {
- int iVar2;
- int iVar3;
- int iVar4;
- bool bVar5;
- uint uVar7;
- int iVar8;
- uint uVar9;
- short sVar10;
- int iVar12;
- uint16 local_970[2];
- int best_score;
- Common::FixedStack<int, 600> local_95c;
-
- best_score = 0x7fffffff;
- if (depth == 1) {
- table_1->calcTouchingPieces = 0;
- for (byte bVar1 = 0; bVar1 < table_1->width; bVar1++) {
- for (byte bVar11 = 0; bVar11 < table_1->height; bVar11++) {
- if ((table_1->boardState[bVar1][bVar11] != 0) ||
- (table_1->numAdjacentPieces[bVar1][bVar11] == 0)) {
- continue;
- }
+int PenteGame::scoreMoveAndRevert(byte x, byte y, char depth, int parentScore, bool &gameOver) {
+ updateScore(y, x, _table->moveCounter % 2);
+ uint score = scoreCapture(y, x);
- penteSub03Scoring(table_1, bVar11, bVar1, (bool)((byte)table_1->moveCounter & 1));
- uVar7 = penteSub04ScoreCapture(table_1, bVar11, bVar1);
- if ((*(byte *)&table_1->moveCounter & 1) == 0) {
- iVar12 = table_1->playerScore - table_1->staufScore;
- } else {
- iVar12 = table_1->staufScore - table_1->playerScore;
- }
- if ((byte)uVar7 != 0) {
- penteSub11RevertCapture(table_1, bVar11, bVar1, (byte)uVar7);
- }
- penteSub07RevertScore(table_1, bVar11, bVar1);
- if (iVar12 < best_score) {
- best_score = iVar12;
- }
- if (-parent_score != best_score && parent_score <= -best_score) {
- table_1->calcTouchingPieces = 1;
- return -best_score;
- }
- }
- }
- table_1->calcTouchingPieces = 1;
- } else {
- *(uint *)local_970 = 0;
- for (byte bVar1 = 0; bVar1 < table_1->width; bVar1++) {
- for (byte bVar11 = 0; bVar11 < table_1->height; bVar11++) {
- if ((table_1->boardState[bVar1][bVar11] != 0) ||
- (table_1->numAdjacentPieces[bVar1][bVar11] == 0)) {
- continue;
- }
+ if (_table->playerScore >= WIN_SCORE || _table->staufScore >= WIN_SCORE)
+ gameOver = true;
+ else
+ gameOver = false;
- penteSub03Scoring(table_1, bVar11, bVar1, (bool)((byte)table_1->moveCounter & 1));
- uVar7 = penteSub04ScoreCapture(table_1, bVar11, bVar1);
- if ((*(byte *)&table_1->moveCounter & 1) == 0) {
- iVar12 = table_1->playerScore - table_1->staufScore;
- } else {
- iVar12 = table_1->staufScore - table_1->playerScore;
- }
- if ((byte)uVar7 != 0) {
- penteSub11RevertCapture(table_1, bVar11, bVar1, (byte)uVar7);
- }
- penteSub07RevertScore(table_1, bVar11, bVar1);
- iVar8 = (int)(short)local_970[1];
- *(uint *)local_970 = (uint)(uint16)(local_970[1] + 1) << 0x10;
- local_95c[iVar8 * 2 + 1] = iVar12;
- *(byte *)&local_95c[iVar8 * 2] = bVar11;
- *((byte *)&local_95c[iVar8 * 2] + 1) = bVar1;
- }
+ int scoreDiff;
+ if (depth > 0 && gameOver==false && _table->boardSize != _table->moveCounter) {
+ scoreDiff = aiRecurse(depth, parentScore);
+ } else {
+ if (_table->moveCounter % 2 == 0) {
+ scoreDiff = _table->playerScore - _table->staufScore;
+ } else {
+ scoreDiff = _table->staufScore - _table->playerScore;
}
+ }
+ if (score != 0) {
+ revertCapture(y, x, score);
+ }
+ revertScore(y, x);
+ return scoreDiff;
+}
- uint16 uVar6;
- for (uVar6 = 1; uVar6 < local_970[1]; uVar6 = uVar6 * 3 + 1) {
- }
+int PenteGame::scoreMoveAndRevert(byte x, byte y, char depth, int parentScore) {
+ // same thing, but don't need to provide the reference to the gameOverBool
+ bool gameOver;
+ return scoreMoveAndRevert(x, y, depth, parentScore, gameOver);
+}
- while (2 < (short)uVar6) {
- uVar6 = (short)uVar6 / 3;
- uVar7 = *(uint *)local_970 & 0xffff0000;
- *(uint *)local_970 = uVar7 | uVar6;
- local_970[1] = (uint16)(uVar7 >> 0x10);
- if ((short)uVar6 < (short)local_970[1]) {
- do {
- bVar5 = false;
- sVar10 = local_970[0] - uVar6;
- while ((-1 < sVar10 && (!bVar5))) {
- iVar8 = (int)sVar10;
- iVar12 = (short)uVar6 + iVar8;
- if (local_95c[iVar12 * 2 + 1] < local_95c[iVar8 * 2 + 1]) {
- sVar10 -= uVar6;
- iVar2 = local_95c[iVar12 * 2 + 1];
- iVar3 = local_95c[iVar12 * 2];
- iVar4 = local_95c[iVar8 * 2 + 1];
- local_95c[iVar12 * 2] = local_95c[iVar8 * 2];
- local_95c[iVar12 * 2 + 1] = iVar4;
- local_95c[iVar8 * 2] = iVar3;
- local_95c[iVar8 * 2 + 1] = iVar2;
- } else {
- bVar5 = true;
- }
- }
- uVar7 = *(uint *)local_970 & 0xffff0000;
- *(uint *)local_970 = uVar7 | (uint16)(local_970[0] + 1);
- local_970[1] = (uint16)(uVar7 >> 0x10);
- } while ((short)(local_970[0] + 1) < (short)local_970[1]);
+int PenteGame::aiRecurseTail(int parentScore) {
+ int best_score = 0x7fffffff;
+
+ _table->calcTouchingPieces = 0;
+ for (byte x = 0; x < _table->width; x++) {
+ for (byte y = 0; y < _table->height; y++) {
+ if ((_table->boardState[x][y] != 0) ||
+ (_table->numAdjacentPieces[x][y] == 0)) {
+ continue;
}
- }
- local_970[1] = (uint16)(*(uint *)local_970 >> 0x10);
- for (sVar10 = 0; sVar10 < local_970[1]; sVar10++) {
- byte bVar1 = *(byte *)&local_95c[sVar10 * 2];
- byte bVar11 = *((byte *)&local_95c[sVar10 * 2] + 1);
- *(uint *)local_970 &= 0xffffff00;
- penteSub03Scoring(table_1, bVar1, bVar11, (bool)((byte)table_1->moveCounter & 1));
- uVar9 = penteSub04ScoreCapture(table_1, bVar1, bVar11);
- uVar7 = table_1->playerScore;
- if (((uVar7 < WIN_SCORE) && (table_1->staufScore < WIN_SCORE)) &&
- (table_1->boardSize != table_1->moveCounter)) {
- iVar12 = penteSub10AiRecurse(table_1, depth + -1, best_score);
- } else {
- if ((*(byte *)&table_1->moveCounter & 1) == 0) {
- iVar12 = uVar7 - table_1->staufScore;
- } else {
- iVar12 = table_1->staufScore - uVar7;
- }
+ int scoreDiff = scoreMoveAndRevert(x, y, 0, 0);
+ if (scoreDiff < best_score) {
+ best_score = scoreDiff;
}
- if ((byte)uVar9 != 0) {
- penteSub11RevertCapture(table_1, bVar1, bVar11, (byte)uVar9);
+ if (-parentScore != best_score && parentScore <= -best_score) {
+ _table->calcTouchingPieces = 1;
+ return -best_score;
}
- penteSub07RevertScore(table_1, bVar1, bVar11);
- if (iVar12 < best_score) {
- best_score = iVar12;
+ }
+ }
+ _table->calcTouchingPieces = 1;
+
+ return -best_score;
+}
+
+int PenteGame::aiRecurse(char depth, int parent_score) {
+ if (depth == 1) {
+ // don't do more recursion
+ return aiRecurseTail(parent_score);
+ }
+
+ // do more recursion after finding some good moves
+ struct GoodMove {
+ int scoreDiff;
+ byte x, y;
+
+ bool operator()(GoodMove a, GoodMove b) {
+ return a.scoreDiff < b.scoreDiff;
+ }
+ };
+ Common::FixedStack<GoodMove, 300> goodMoves; // 300 slots because the board is 20x15, but we rarely need many since the search excludes spots with no adjacenet pieces
+ int best_score = 0x7fffffff;
+
+ for (byte x = 0; x < _table->width; x++) {
+ for (byte y = 0; y < _table->height; y++) {
+ if ((_table->boardState[x][y] != 0) ||
+ (_table->numAdjacentPieces[x][y] == 0)) {
+ continue;
}
- if (-parent_score != best_score && parent_score <= -best_score)
- break;
- local_970[1] = (uint16)(*(uint *)local_970 >> 0x10);
+
+ int scoreDiff = scoreMoveAndRevert(x, y, 0, 0);
+ goodMoves.push({scoreDiff, x, y});
}
}
+
+ // sort ascending by scoreDiff, most of the time you'll see scores like -40 at the top and -34 at the end
+ Common::sort(&goodMoves[0], &goodMoves.top(), goodMoves[0]);
+
+ for (uint i = 0; i < goodMoves.size(); i++) {
+ byte x = goodMoves[i].x;
+ byte y = goodMoves[i].y;
+
+ int scoreDiff = scoreMoveAndRevert(x, y, depth - 1, best_score);
+ if (scoreDiff < best_score) {
+ best_score = scoreDiff;
+ }
+ if (-parent_score != best_score && parent_score <= -best_score)
+ break;
+ }
return -best_score;
}
-uint PenteGame::penteSub09Ai(uint y_1, int param_2, int param_3, penteTable *table_4, byte depth) {
- bool bVar1;
- uint uVar2;
- int iVar3;
- byte _y;
- int best_score;
- uint16 uVar5;
- byte bStack18;
- byte _x;
- uint16 local_c;
- short local_4;
- uint _y2;
-
- bStack18 = 1;
- _x = 0;
- uVar5 = 0xffff;
- best_score = 0x7fffffff;
- if (table_4->width != 0) {
- do {
- _y = 0;
- if (table_4->height != 0) {
- do {
- y_1 = (uint)_y;
- if ((table_4->boardState[_x][y_1] == 0) && (table_4->numAdjacentPieces[_x][y_1] != 0)) {
- penteSub03Scoring(table_4, _y, _x, (bool)((byte)table_4->moveCounter & 1));
- _y2 = penteSub04ScoreCapture(table_4, _y, _x);
- if ((table_4->playerScore < WIN_SCORE) &&
- (table_4->staufScore < WIN_SCORE)) {
- bVar1 = false;
- } else {
- bVar1 = true;
- }
- if ((byte)_y2 != 0) {
- penteSub11RevertCapture(table_4, _y, _x, (byte)_y2);
- }
- penteSub07RevertScore(table_4, _y, _x);
- if (bVar1) {
- return (y_1 & 0xffff0000) | (uint)(uint16)((uint16)_y + (uint16)_x * 100);
- }
- }
- _y += 1;
- } while (_y <= table_4->height && table_4->height != _y);
+uint16 PenteGame::aiGetBestMove(uint param_1, int param_2, int param_3, byte depth) {
+ for (int x = 0; x < _table->width; x++) {
+ for (int y = 0; y < _table->height; y++) {
+ if (_table->boardState[x][y] != 0 || _table->numAdjacentPieces[x][y] == 0)
+ continue;
+
+ bool gameOver;
+ scoreMoveAndRevert(x, y, 0, 0, gameOver);
+ if (gameOver) {
+ return y + x * 100;
}
- _x += 1;
- y_1 &= 0xffffff00;
- } while (_x <= table_4->width && table_4->width != _x);
+ }
}
- do {
- _x = 0;
- if (table_4->width != 0) {
- do {
- _y2 = 0;
- if (table_4->height != 0) {
- do {
- _y = (byte)_y2;
- y_1 = 0;
- if ((table_4->boardState[_x][_y2] == 0) && (table_4->numAdjacentPieces[_x][_y2] != 0)) {
- penteSub03Scoring(table_4, _y, _x, (bool)((byte)table_4->moveCounter & 1));
- uVar2 = penteSub04ScoreCapture(table_4, _y, _x);
- iVar3 = penteSub10AiRecurse(table_4, depth - 1, best_score);
- if ((byte)uVar2 != 0) {
- penteSub11RevertCapture(table_4, _y, _x, (byte)uVar2);
- }
- penteSub07RevertScore(table_4, _y, _x);
- local_c = (uint16)_x;
- local_4 = (short)_y2;
- if (iVar3 < best_score) {
- bStack18 = 1;
- uVar5 = local_c * 100 + local_4;
- best_score = iVar3;
- } else {
- if (iVar3 == best_score) {
- bStack18 += 1;
- _y2 = _random.getRandomNumber(UINT_MAX);
- y_1 = (uint)bStack18;
- if ((_y2 % CAPTURE_SCORE) * y_1 < CAPTURE_SCORE) {
- uVar5 = local_c * 100 + local_4;
- }
- }
- }
+
+ byte counter = 1;
+ int bestScore = 0x7fffffff;
+ uint16 bestMove = 0xffff;
+
+ for (; bestScore > 99999999 && depth > 1; depth--) {
+ for (int x = 0; x < _table->width; x++) {
+ for (int y = 0; y < _table->height; y++) {
+ if (_table->boardState[x][y] != 0 || _table->numAdjacentPieces[x][y] == 0)
+ continue;
+
+ int scoreRecurse = scoreMoveAndRevert(x, y, depth - 1, bestScore);
+
+ if (scoreRecurse < bestScore) {
+ counter = 1;
+ bestMove = x * 100 + y;
+ bestScore = scoreRecurse;
+ } else {
+ if (scoreRecurse == bestScore) {
+ counter += 1;
+ uint rng = _random.getRandomNumber(UINT_MAX);
+ if ((rng % CAPTURE_SCORE) * counter < CAPTURE_SCORE) {
+ bestMove = x * 100 + y;
}
- _y += 1;
- _y2 = (uint)_y;
- } while (_y <= table_4->height && table_4->height != _y);
+ }
}
- _x += 1;
- y_1 &= 0xffffff00;
- } while (_x <= table_4->width && table_4->width != _x);
+ }
}
- } while ((99999999 < best_score) && (depth -= 1, 1 < depth));
- return (y_1 & 0xffff0000) | (uint)uVar5;
+ }
+ return bestMove;
}
int varsMoveToXY(byte var0, byte var1, byte var2, byte &x, byte &y) {
@@ -738,64 +583,57 @@ void moveXYToVars(uint x, uint y, byte &var0, byte &var1, byte &var2) {
moveToVars(move, var0, var1, var2);
}
-void PenteGame::penteOp(byte *vars) {
+void PenteGame::run(byte *vars) {
uint16 uVar1;
int iVar2;
- uint uVar3;
byte ai_depth;
short local_2;
- if ((game_state_table == (penteTable *)0x0) && (vars[4] != 0)) {
- game_state_table = penteSub01Init(0x14, 0xf, 5);
+ byte op = vars[4];
+ if (_table == NULL && op != 0) {
+ penteInit(20, 15, 5);
}
- uVar3 = vars[4];
- debugC(kDebugLogic, "penteOp vars[4]: %d", (int)vars[4]);
+ debugC(kDebugLogic, "penteOp vars[4]: %d", (int)op);
- switch (uVar3) {
+ switch (op) {
case 0:
- if (game_state_table != (penteTable *)0x0) {
- penteSub02Frees(game_state_table);
- }
- game_state_table = (penteTable *)0x0;
+ penteDeInit();
return;
case 1:
- globalPlayerMove = varsMoveToXY(vars[0], vars[1], vars[2], globalX, globalY);
- debugC(kDebugLogic, "player moved to %d, %d", (int)globalX, (int)globalY);
- penteSub03Scoring(game_state_table, globalY, globalX,
- (bool)((byte)game_state_table->moveCounter & 1));
- uVar3 = penteSub04ScoreCapture(game_state_table, globalY, globalX);
- global2 = (char)uVar3;
+ _globalPlayerMove = varsMoveToXY(vars[0], vars[1], vars[2], _globalX, _globalY);
+ debugC(kDebugLogic, "player moved to %d, %d", (int)_globalX, (int)_globalY);
+ updateScore(_globalY, _globalX, _table->moveCounter % 2);
+ _global2 = scoreCapture(_globalY, _globalX);
return;
case 2:
case 4:
- if (global2 != '\0') {
- if (global1 < 0) {
- penteSub08MaybeAnimateCapture(globalPlayerMove, (byte *)&global2, &local_2, &global1);
+ if (_global2 != '\0') {
+ if (_global1 < 0) {
+ animateCapture(_globalPlayerMove, (byte *)&_global2, &local_2, &_global1);
vars[5] = 1;
moveToVars(local_2, vars[0], vars[1], vars[2]);
return;
}
LAB_00412da4:
- vars[0] = (byte)((int)global1 / 100);
- vars[1] = (byte)((int)(global1 % 100) / 10);
- iVar2 = (int)global1;
+ vars[0] = (byte)((int)_global1 / 100);
+ vars[1] = (byte)((int)(_global1 % 100) / 10);
+ iVar2 = (int)_global1;
vars[2] = (byte)(iVar2 % 10);
- global1 = -1;
+ _global1 = -1;
vars[5] = 1;
return;
}
- if (-1 < global1)
+ if (-1 < _global1)
goto LAB_00412da4;
- if (game_state_table->playerScore < WIN_SCORE) {
- if ((game_state_table->staufScore < WIN_SCORE) &&
- (uVar1 = game_state_table->moveCounter)) {
+ if (_table->playerScore < WIN_SCORE) {
+ if ((_table->staufScore < WIN_SCORE) &&
+ (uVar1 = _table->moveCounter)) {
vars[5] = 0;
return;
}
- if (game_state_table->playerScore < WIN_SCORE) {
- uVar3 = game_state_table->staufScore;
+ if (_table->playerScore < WIN_SCORE) {
vars[5] = 2; // Stauf wins
- if (uVar3 < WIN_SCORE) {
+ if (_table->staufScore < WIN_SCORE) {
vars[5] = 4; // player wins because the board is full?
}
goto DEALLOC;
@@ -803,8 +641,7 @@ void PenteGame::penteOp(byte *vars) {
}
vars[5] = 3; // player wins
DEALLOC:
- penteSub02Frees(game_state_table);
- game_state_table = (penteTable *)0x0;
+ penteDeInit();
return;
case 3:
break;
@@ -812,7 +649,7 @@ void PenteGame::penteOp(byte *vars) {
// asking Samantha to make a move? this does a bunch of queries to check if pieces belong to stauf or the player?
byte x, y;
varsMoveToXY(vars[0], vars[1], vars[2], x, y);
- ai_depth = game_state_table->boardState[x][y];
+ ai_depth = _table->boardState[x][y];
if (ai_depth == 0) {
vars[3] = 0;
return;
@@ -840,43 +677,28 @@ void PenteGame::penteOp(byte *vars) {
ai_depth = 5;
}
}
- globalPlayerMove = penteSub09Ai(0, 0, 0, game_state_table, ai_depth);
+ _globalPlayerMove = aiGetBestMove(0, 0, 0, ai_depth);
LAB_00412e85:
- aiMoveToXY(globalPlayerMove, globalX, globalY);
- debugC(kDebugLogic, "Stauf moved to %d, %d", (int)globalX, (int)globalY);
- penteSub03Scoring(game_state_table, globalY, globalX,
- (bool)((byte)game_state_table->moveCounter & 1));
- uVar3 = penteSub04ScoreCapture(game_state_table, globalY, globalX);
- global2 = (char)uVar3;
- globalPlayerMove = ((uint16)globalX * 0xf - (uint16)globalY) + 0xe;
- moveXYToVars(globalX, globalY, vars[0], vars[1], vars[2]);
+ aiMoveToXY(_globalPlayerMove, _globalX, _globalY);
+ debugC(kDebugLogic, "Stauf moved to %d, %d", (int)_globalX, (int)_globalY);
+ updateScore(_globalY, _globalX, _table->moveCounter % 2);
+ _global2 = scoreCapture(_globalY, _globalX);
+ _globalPlayerMove = ((uint16)_globalX * 0xf - (uint16)_globalY) + 0xe;
+ moveXYToVars(_globalX, _globalY, vars[0], vars[1], vars[2]);
}
PenteGame::PenteGame() : _random("PenteGame") {
- global1 = -1;
- game_state_table = NULL;
- globalY = 0;
- globalX = 0;
- global2 = 0;
- globalPlayerMove = 0;
+ _table = NULL;
+ _global1 = -1;
+ _globalY = 0;
+ _globalX = 0;
+ _global2 = 0;
+ _globalPlayerMove = 0;
#if 0
test();
#endif
}
-void PenteGame::run(byte *scriptVariables) {
- // TODO: don't need to copy these variables once this is cleaned up
- byte tvars[1024];
- memcpy(tvars, scriptVariables, sizeof(tvars));
- penteOp(tvars);
- for (size_t i = 0; i < sizeof(tvars); i++) {
- if (tvars[i] != scriptVariables[i]) {
- debugC(kDebugLogic, "PenteGame::run var %ld changed from %d to %d", i, (int)scriptVariables[i], (int)tvars[i]);
- }
- }
- memcpy(scriptVariables, tvars, sizeof(tvars));
-}
-
void PenteGame::test() {
warning("starting PenteGame::test()");
uint32 oldSeed = _random.getSeed();
@@ -946,7 +768,7 @@ void PenteGame::testGame(uint32 seed, Common::Array<int> moves, bool playerWin)
_random.setSeed(seed);
op = 0;
- penteOp(vars);
+ run(vars);
for (uint i = 0; i < moves.size(); i += 2) {
if (winner)
@@ -958,7 +780,7 @@ void PenteGame::testGame(uint32 seed, Common::Array<int> moves, bool playerWin)
if (i % 4) {
// check Stauf's move
op = 3;
- penteOp(vars);
+ run(vars);
byte sX, sY;
varsMoveToXY(vars[0], vars[1], vars[2], sX, sY);
@@ -968,18 +790,18 @@ void PenteGame::testGame(uint32 seed, Common::Array<int> moves, bool playerWin)
do {
op = 4;
- penteOp(vars);
+ run(vars);
} while (winner == 1);
continue;
}
moveXYToVars(x, y, vars[0], vars[1], vars[2]);
op = 1;
- penteOp(vars);
+ run(vars);
do {
op = 2;
- penteOp(vars);
+ run(vars);
} while (winner == 1);
}
diff --git a/engines/groovie/logic/pente.h b/engines/groovie/logic/pente.h
index 457794ab53..87eb1689c2 100644
--- a/engines/groovie/logic/pente.h
+++ b/engines/groovie/logic/pente.h
@@ -38,33 +38,38 @@ struct penteTable;
class PenteGame {
public:
PenteGame();
- void run(byte *scriptVariables);
+ void run(byte *vars);
private:
- int *allocs(int param_1, int param_2);
- void penteSub02Frees(penteTable *param_1);
- void penteSub05BuildLookupTable(penteTable *table);
- penteTable *penteSub01Init(byte width, byte height, byte length);
- void penteSub03Scoring(penteTable *table, byte move_y, byte move_x, bool whose_turn);
- void penteSub07RevertScore(penteTable *table_1, byte y, byte x);
- byte penteScoreCaptureSingle(penteTable *table, byte x, byte y, int slopeX, int slopeY);
- uint penteSub04ScoreCapture(penteTable *table, byte y, byte x);
- void penteSub08MaybeAnimateCapture(short param_1, byte *param_2, short *param_3, short *param_4);
- void penteSub11RevertCapture(penteTable *table, byte y, byte x, byte y2);
- int penteSub10AiRecurse(penteTable *table_1, char depth, int parent_score);
- uint penteSub09Ai(uint y_1, int param_2, int param_3, penteTable *table_4, byte depth);
- void penteOp(byte *vars);
+ void addLine(int x, int y, int linesCounter);
+ void buildLookupTable();
+ void penteDeInit();
+ void penteInit(uint width, uint height, uint length);
+ uint &getPlayerTable(bool staufTurn, pentePlayerTable *&pt);
+ void scoreLine(uint16 lineIndex, bool stauf_turn, bool revert);
+ void calcTouchingPieces(byte moveX, byte moveY, bool revert);
+ void updateScore(byte move_y, byte move_x, bool whose_turn);
+ void revertScore(byte y, byte x);
+ byte scoreCaptureSingle(byte x, byte y, int slopeX, int slopeY);
+ uint scoreCapture(byte y, byte x);
+ void animateCapture(short param_1, byte *param_2, short *param_3, short *param_4);
+ void revertCapture(byte y, byte x, byte y2);
+ int scoreMoveAndRevert(byte x, byte y, char depth, int parentScore, bool &gameOver);
+ int scoreMoveAndRevert(byte x, byte y, char depth, int parent_score);
+ int aiRecurseTail(int parent_score);
+ int aiRecurse(char depth, int parent_score);
+ uint16 aiGetBestMove(uint y_1, int param_2, int param_3, byte depth);
void test();
void testGame(uint32 seed, Common::Array<int> moves, bool playerWin);
Common::RandomSource _random;
- byte globalY;
- byte globalX;
- char global2;
- short globalPlayerMove;
- short global1;
- penteTable *game_state_table;
+ byte _globalY;
+ byte _globalX;
+ char _global2;
+ short _globalPlayerMove;
+ short _global1;
+ penteTable *_table;
};
} // End of Groovie namespace
More information about the Scummvm-git-logs
mailing list