GROOVIE: Easier AI options

This commit is contained in:
Die4Ever 2021-12-04 08:04:35 -06:00
parent dff981f90b
commit 92c59956cc
No known key found for this signature in database
GPG Key ID: 7B8AAD15B16CE289
16 changed files with 96 additions and 33 deletions

View File

@ -31,6 +31,7 @@ namespace Groovie {
#define GAMEOPTION_T7G_FAST_MOVIE_SPEED GUIO_GAMEOPTIONS1
#define GAMEOPTION_ORIGINAL_SAVELOAD GUIO_GAMEOPTIONS2
#define GAMEOPTION_EASIER_AI GUIO_GAMEOPTIONS3
static const DebugChannelDef debugFlagList[] = {
{Groovie::kDebugVideo, "Video", "Debug video and audio playback"},
@ -57,6 +58,7 @@ static const PlainGameDescriptor groovieGames[] = {
{nullptr, nullptr}
};
// clang-format off
static const GroovieGameDescription gameDescriptions[] = {
// groovie.cpp requires the first file to be the main .grv file for v2 games, might as well stick to that convention for v1 games from now on too
@ -66,7 +68,7 @@ static const GroovieGameDescription gameDescriptions[] = {
"t7g", "",
AD_ENTRY1s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659),
Common::EN_ANY, Common::kPlatformDOS, ADGF_NO_FLAGS,
GUIO7(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO8(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT7G
},
@ -78,7 +80,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", nullptr, -1, // FIXMEMD5
"T7GMac", "acdc4a58dd3f007f65e99b99d78e0bce", 1814029),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_MACRESFORK,
GUIO7(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO8(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT7G
},
@ -90,7 +92,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659,
"intro.gjd", nullptr, 31711554),
Common::RU_RUS, Common::kPlatformDOS, ADGF_NO_FLAGS,
GUIO7(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO8(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT7G
},
@ -102,7 +104,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", "d1b8033b40aa67c076039881eccce90d", 16659,
"SeventhGuest", nullptr, -1),
Common::EN_ANY, Common::kPlatformIOS, ADGF_NO_FLAGS,
GUIO5(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO6(GUIO_NOMIDI, GUIO_NOASPECT, GUIO_NOSFX, GAMEOPTION_T7G_FAST_MOVIE_SPEED, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT7G
},
@ -125,7 +127,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
"introd1.gjd", nullptr, -1),
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT11H
},
@ -137,7 +139,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
"The 11th Hour Installer", "bcdb4040b27f15b18f39fb9e496d384a", 1002987),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT11H
},
@ -149,7 +151,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("script.grv", "bdb9a783d4debe477ac3856adc454c17", 62447,
"el01.mov", "70f42dfc25b1488a08011dc45bb5145d", 6039),
Common::EN_ANY, Common::kPlatformMacintosh, ADGF_UNSTABLE,
GUIO5(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD)
GUIO6(GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_MIDIGM, GUIO_NOASPECT, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_EASIER_AI)
},
kGroovieT11H
},
@ -281,7 +283,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("clanmain.grv", "dd424120fa1daa9d6b576d0ba22a4936", 54253,
"ACT01MUS.MPG", nullptr, -1),
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_EASIER_AI)
},
kGroovieCDY
},
@ -293,7 +295,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("CLANMAIN.GRV", "dd424120fa1daa9d6b576d0ba22a4936", 54253,
"ACT01MUS.m4a", nullptr, -1),
Common::EN_ANY, Common::kPlatformUnknown, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_EASIER_AI)
},
kGroovieCDY
},
@ -305,7 +307,7 @@ static const GroovieGameDescription gameDescriptions[] = {
AD_ENTRY2s("tpot.grv", "849dc7e5309e1b9acf72d8abc9e145df", 11693,
"trt7g.gjd", nullptr, -1),
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE,
GUIO2(GUIO_NOMIDI, GUIO_NOASPECT)
GUIO3(GUIO_NOMIDI, GUIO_NOASPECT, GAMEOPTION_EASIER_AI)
},
kGroovieUHP
},
@ -389,8 +391,19 @@ static const ADExtraGuiOptionsMap optionsList[] = {
}
},
{
GAMEOPTION_EASIER_AI,
{
_s("Easier AI"),
_s("Decrease the difficulty of AI puzzles"),
"easier_ai",
false
}
},
AD_EXTRA_GUI_OPTIONS_TERMINATOR
};
// clang-format on
class GroovieMetaEngineDetection : public AdvancedMetaEngineDetection {
public:

View File

@ -309,8 +309,12 @@ void BeehiveGame::sub07(int8 *a1, int8 *a2, int8 *a3, int8 *a4, int8 *a5, int8 *
int8 params[4];
*a4 = 0;
if (calcMove(_beehiveState, -125, -1, 4, 0, params) == 125
&& (*a4 = 1, calcMove(_beehiveState, -125, -1, 4, 1, params) == 125)) {
int8 depth = 4;
if (_easierAi)
depth = 1;
if (calcMove(_beehiveState, -125, -1, depth, 0, params) == 125
&& (*a4 = 1, calcMove(_beehiveState, -125, -1, depth, 1, params) == 125)) {
*a1 = -1;
*a2 = -1;
for (int i = 0; i < HEXCOUNT; ++i) {
@ -329,8 +333,12 @@ void BeehiveGame::sub08(int8 *a1, int8 *a2, int8 *a3, int8 *a4, int8 *a5, int8 *
int8 params[4];
*a4 = 0;
if (calcMove(_beehiveState, 125, 1, 4, 0, params) == -125
&& (*a4 = 1, calcMove(_beehiveState, 125, 1, 4, 1, params) == -125)) {
int8 depth = 4;
if (_easierAi)
depth = 1;
if (calcMove(_beehiveState, 125, 1, depth, 0, params) == -125
&& (*a4 = 1, calcMove(_beehiveState, 125, 1, depth, 1, params) == -125)) {
*a1 = -1;
*a2 = -1;
for (int i = 0; i < HEXCOUNT; ++i) {

View File

@ -44,10 +44,12 @@ namespace Groovie {
*/
class BeehiveGame {
public:
BeehiveGame() {
BeehiveGame(bool easierAi) {
#if 0
_easierAi = false;
tests();
#endif
_easierAi = easierAi;
}
~BeehiveGame() {}
@ -80,6 +82,7 @@ private:
Common::Array<int> overrideMoves;
uint overrideIndex;
bool _easierAi;
};
} // End of Groovie namespace

View File

@ -42,7 +42,7 @@ namespace Groovie {
* .
* @see UpdateScores()
*/
CakeGame::CakeGame() : _random("CakeGame") {
CakeGame::CakeGame(bool easierAi) : _random("CakeGame") {
restart();
_map = {};
@ -89,8 +89,11 @@ CakeGame::CakeGame() : _random("CakeGame") {
}
#if 0
_easierAi = false;
testCake();
#endif
_easierAi = easierAi;
}
void CakeGame::run(byte *scriptVariables) {
@ -123,7 +126,11 @@ void CakeGame::run(byte *scriptVariables) {
return;
}
lastMove = aiGetBestMove(4 + (_hasCheated == false));
int depth = 4 + (_hasCheated == false);
if (_easierAi)
depth = 0;
lastMove = aiGetBestMove(depth);
placeBonBon(lastMove);
if (gameEnded()) {
winner = STAUF;

View File

@ -39,7 +39,7 @@ namespace Groovie {
*/
class CakeGame {
public:
CakeGame();
CakeGame(bool easierAi);
void run(byte *scriptVariables);
private:
@ -75,6 +75,7 @@ private:
bool _hasCheated;
LinesMappings _map;//!< ID numbers for all of the potential victory lines for each spot on the board
bool _easierAi;
void restart();
void setLineNum(uint x, uint y, uint index);

View File

@ -21,10 +21,11 @@
*/
#include "groovie/logic/cell.h"
#include "common/config-manager.h"
namespace Groovie {
CellGame::CellGame() {
CellGame::CellGame(bool easierAi) {
_startX = _startY = _endX = _endY = 255;
_stack_index = _boardStackPtr = 0;
@ -34,6 +35,7 @@ CellGame::CellGame() {
_coeff3 = 0;
_moveCount = 0;
_easierAi = easierAi;
}
byte CellGame::getStartX() {
@ -756,6 +758,9 @@ void CellGame::calcMove(int8 color, uint16 depth) {
int newDepth;
newDepth = depths[3 * (depth - 2) + _moveCount % 3];
if (_easierAi)
newDepth = 1;
_flag2 = true;
if (newDepth >= 20) {
assert(0); // This branch is not implemented

View File

@ -34,7 +34,7 @@ namespace Groovie {
class CellGame {
public:
CellGame();
CellGame(bool easierAi);
~CellGame();
void run(uint16 depth, byte *scriptBoard);
@ -88,6 +88,7 @@ private:
int _coeff3;
bool _flag1, _flag2, _flag4;
int _moveCount;
bool _easierAi;
};
} // End of Groovie namespace

View File

@ -183,7 +183,9 @@ byte GalleryGame::galleryAI(byte *pieceStatus, int depth) {
}
}
if (v9 == v10)
return 1;// I believe 1 means this is an optimal move
return 1; // I believe 1 means this is an optimal move
else if (_easierAi && v9 * 3 >= v10 * 2)
return 1; // close enough to an optimal move?
else
return (v8 + 102 * v9) / v10;// otherwise, higher numbers are better
}

View File

@ -79,10 +79,12 @@ namespace Groovie {
class GalleryGame {
public:
GalleryGame() {
GalleryGame(bool easierAi) {
#if 0
_easierAi = false;
test();
#endif
_easierAi = easierAi;
}
void run(byte *scriptVariables);
@ -90,6 +92,7 @@ private:
byte galleryAI(byte *pieceStatus, int depth);
static const byte kGalleryLinks[21][10];
bool _easierAi;
void test();
void ensureSamanthaWins(int seed);

View File

@ -31,7 +31,7 @@
namespace Groovie {
MouseTrapGame::MouseTrapGame() : _random("MouseTrapGame") {
MouseTrapGame::MouseTrapGame(bool easierAi) : _random("MouseTrapGame") {
_mouseTrapCounter = _mouseTrapCounter1 = 0;
_mouseTrapX = _mouseTrapY = 0;
memset(_mouseTrapRoute, 0, 75);
@ -39,6 +39,7 @@ MouseTrapGame::MouseTrapGame() : _random("MouseTrapGame") {
_mouseTrapPosX = _mouseTrapPosY = 0;
memset(_mouseTrapCells, 0, 31);
_mouseTrapNumSteps = 0;
_easierAi = easierAi;
}
void MouseTrapGame::run(byte *scriptVariables) {
@ -556,6 +557,9 @@ void MouseTrapGame::goFarthest(int8 *x, int8 *y) {
int8 dist = calcDistanceToExit();
if (_easierAi)
dist += _random.getRandomNumber(2);
if (_mouseTrapNumSteps && _random.getRandomNumber(1) != 0)
dist += 3;

View File

@ -54,7 +54,7 @@ namespace Groovie {
*/
class MouseTrapGame {
public:
MouseTrapGame();
MouseTrapGame(bool easierAi);
void run(byte *scriptVariables);
private:
@ -94,6 +94,7 @@ private:
int8 _mouseTrapCells[31];
int8 _mouseTrapPosX, _mouseTrapPosY;
int8 _mouseTrapNumSteps;
bool _easierAi;
};
} // End of Groovie namespace

View File

@ -176,7 +176,7 @@ int OthelloGame::scoreLateGame(Freeboard *freeboard) {
}
int OthelloGame::scoreBoard(Freeboard *board) {
if (_isLateGame)
if (_isLateGame || _easierAi)
return scoreLateGame(board);
else
return scoreEarlyGame(board);
@ -370,7 +370,10 @@ byte OthelloGame::aiDoBestMove(Freeboard *pBoard) {
for (int move = 0; move < numPossibleMoves; move++) {
_isAiTurn = !_isAiTurn; // flip before recursing
int score = aiRecurse(&possibleMoves[move], _depths[_counter], parentScore, 100);
int depth = _depths[_counter];
if (_easierAi)
depth = 0;
int score = aiRecurse(&possibleMoves[move], depth, parentScore, 100);
if (bestScore < score) {
parentScore = score;
bestMove = move;
@ -554,7 +557,7 @@ void OthelloGame::op5(byte *vars) {
vars[4] = 1;
}
OthelloGame::OthelloGame()
OthelloGame::OthelloGame(bool easierAi)
: _random("OthelloGame"),
_depths {
1, 4, 3, 3, 3, 3, 3, 3, 3, 3,
@ -619,8 +622,10 @@ OthelloGame::OthelloGame()
initLines();
#if 0
_easierAi = false;
test();
#endif
_easierAi = easierAi;
}
void OthelloGame::run(byte *vars) {

View File

@ -49,7 +49,7 @@ struct Freeboard {
class OthelloGame {
public:
OthelloGame();
OthelloGame(bool easierAi);
void run(byte *scriptVariables);
private:
@ -94,6 +94,7 @@ private:
int8 *_linesStorage[484];
int8 _lineStorage[2016];
Freeboard _board;
bool _easierAi;
};
} // End of Groovie namespace

View File

@ -679,8 +679,11 @@ void PenteGame::run(byte *vars) {
aiDepth = 5;
}
if (aiDepth != 2)
if (aiDepth != 2) {
if (_easierAi && aiDepth > 2)
aiDepth = 2;
_previousMove = aiGetBestMove(aiDepth);
}
else
warning("pente unknown else");
@ -693,14 +696,16 @@ void PenteGame::run(byte *vars) {
moveXYToVars(x, y, vars[0], vars[1], vars[2]);
}
PenteGame::PenteGame() : _random("PenteGame") {
PenteGame::PenteGame(bool easierAi) : _random("PenteGame") {
_table = nullptr;
_nextCapturedSpot = -1;
_animateCapturesBitMask = 0;
_previousMove = 0;
#if 0
_easierAi = false;
test();
#endif
_easierAi = easierAi;
}
void PenteGame::test() {

View File

@ -43,7 +43,7 @@ struct penteTable;
class PenteGame {
public:
PenteGame();
PenteGame(bool easierAi);
void run(byte *vars);
private:
@ -77,6 +77,7 @@ private:
short _previousMove;
short _nextCapturedSpot;
penteTable *_table;
bool _easierAi;
};
} // End of Groovie namespace

View File

@ -78,7 +78,10 @@ enum kSpecialVariableTypes {
Script::Script(GroovieEngine *vm, EngineVersion version) :
_code(nullptr), _savedCode(nullptr), _stacktop(0), _debugger(nullptr), _vm(vm),
_videoFile(nullptr), _videoRef(UINT_MAX), _cellGame(nullptr), _lastCursor(0xff),
_version(version), _random("GroovieScripts"), _tlcGame(nullptr) {
_version(version), _random("GroovieScripts"), _tlcGame(nullptr),
_beehive(ConfMan.getBool("easier_ai")), _cake(ConfMan.getBool("easier_ai")), _gallery(ConfMan.getBool("easier_ai")),
_mouseTrap(ConfMan.getBool("easier_ai")), _othello(ConfMan.getBool("easier_ai")), _pente(ConfMan.getBool("easier_ai"))
{
// Initialize the opcode set depending on the engine version
if (version == kGroovieT7G) {
@ -2126,7 +2129,7 @@ void Script::o_gamelogic() {
switch (_version) {
case kGroovieT7G:
if (!_cellGame)
_cellGame = new CellGame;
_cellGame = new CellGame(ConfMan.getBool("easier_ai"));
_cellGame->run(param, &_variables[0x19]);