- Modified gameObserver and related classes to be able to work with a precise JGE instance given at construction and not the static global one. That allows to run gameObserver without JGE instance (for example in a worker thread).

- Added an "ACTION_LOGGING_TESTING" mode in the gameObserver. When this is defined, the game reloads itself in every update. I want to use that to track undo problems. Be aware that it kills performances and crashes with the testsuite if you want to activate it.
- Various cleanup/refactor of the game observer.
- Added a gameObserver == operator to compare two games
- Added player mode to the player serialization
- Added a multi-threaded mode to AI_CHANGE_TESTING. For the moment it's only useable with Qt. If you want to use it without, just defined a thread_count higher than 1.
- Refactored random generator class to use list intead of queue
- Defined a specific type for interrupt decision instead of int
This commit is contained in:
Xawotihs
2011-11-13 22:36:34 +00:00
parent 2240c14f56
commit f68c106e7e
33 changed files with 320 additions and 141 deletions

View File

@@ -17,28 +17,6 @@
#include "TestSuiteAI.h"
#endif
void GameObserver::initialize()
{
mGameType = GAME_TYPE_CLASSIC;
currentPlayer = NULL;
currentActionPlayer = NULL;
isInterrupting = NULL;
currentPlayerId = 0;
currentGamePhase = -1;
targetChooser = NULL;
cardWaitingForTargets = NULL;
mExtraPayment = NULL;
gameOver = NULL;
phaseRing = NULL;
replacementEffects = NEW ReplacementEffects();
combatStep = BLOCKERS;
mRules = NULL;
connectRule = false;
mLoading = false;
mLayers = NULL;
mTrash = new Trash();
}
void GameObserver::cleanup()
{
SAFE_DELETE(targetChooser);
@@ -69,6 +47,10 @@ void GameObserver::cleanup()
GameObserver::~GameObserver()
{
#ifdef ACTION_LOGGING_TESTING
if(oldGame) SAFE_DELETE(oldGame);
#endif //ACTION_LOGGING_TESTING
LOG("==Destroying GameObserver==");
for (size_t i = 0; i < players.size(); ++i)
{
@@ -89,13 +71,34 @@ GameObserver::~GameObserver()
SAFE_DELETE(mTrash);
}
GameObserver::GameObserver(WResourceManager *resourceManager)
: randomGenerator(true), mResourceManager(resourceManager)
GameObserver::GameObserver(WResourceManager *output, JGE* input)
: randomGenerator(true), mResourceManager(output), mJGE(input)
{
updateCtr = 0;
#ifdef ACTION_LOGGING_TESTING
oldGame = 0;
#endif //ACTION_LOGGING_TESTING
ExtraRules = new MTGCardInstance[2]();
initialize();
mGameType = GAME_TYPE_CLASSIC;
currentPlayer = NULL;
currentActionPlayer = NULL;
isInterrupting = NULL;
currentPlayerId = 0;
currentGamePhase = -1;
targetChooser = NULL;
cardWaitingForTargets = NULL;
mExtraPayment = NULL;
gameOver = NULL;
phaseRing = NULL;
replacementEffects = NEW ReplacementEffects();
combatStep = BLOCKERS;
mRules = NULL;
connectRule = false;
mLoading = false;
mLayers = NULL;
mTrash = new Trash();
}
int GameObserver::getCurrentGamePhase()
@@ -417,9 +420,80 @@ bool GameObserver::removeObserver(ActionElement * observer)
}
bool GameObserver::operator==(const GameObserver& aGame)
{
int error = 0;
if (aGame.currentGamePhase != currentGamePhase)
{
error++;
}
for (int i = 0; i < 2; i++)
{
TestSuiteAI * p = (TestSuiteAI *) (aGame.players[i]);
if (p->life != players[i]->life)
{
error++;
}
if (p->poisonCount != players[i]->poisonCount)
{
error++;
}
if (!p->getManaPool()->canAfford(players[i]->getManaPool()))
{
error++;
}
if (!players[i]->getManaPool()->canAfford(p->getManaPool()))
{
error++;
}
MTGGameZone * aZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay };
MTGGameZone * thisZones[] = { players[i]->game->graveyard,
players[i]->game->library,
players[i]->game->hand,
players[i]->game->inPlay };
for (int j = 0; j < 4; j++)
{
MTGGameZone * zone = aZones[j];
if (zone->nb_cards != thisZones[j]->nb_cards)
{
error++;
}
for (size_t k = 0; k < (size_t)thisZones[j]->nb_cards; k++)
{
MTGCardInstance* cardToCheck = (k<thisZones[j]->cards.size())?thisZones[j]->cards[k]:0;
MTGCardInstance* card = (k<aZones[j]->cards.size())?aZones[j]->cards[k]:0;
if(!card || !cardToCheck || cardToCheck->getId() != card->getId())
{
error++;
}
}
}
}
return (error == 0);
}
void GameObserver::Update(float dt)
{
/*******************/
updateCtr++;
#ifdef ACTION_LOGGING_TESTING
if(!oldGame || (!(*oldGame == *this) &&
!mLoading && mLayers->stackLayer()->isCalm()))
{ // constant game check
stringstream stream;
stream << *this;
if(oldGame) SAFE_DELETE(oldGame);
oldGame = new GameObserver();
oldGame->mRules = mRules;
oldGame->load(stream.str());
assert(*this == *oldGame);
}
#endif // ACTION_LOGGING_TESTING
/*******************/
Player * player = currentPlayer;
if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep)
{
@@ -1368,7 +1442,12 @@ bool GameObserver::load(const string& ss, bool undo)
else
{
if(players.size() == 0 || !players[0])
players.push_back(new HumanPlayer(this, deckFile, deckFileSmall));
{
if (s.find("mode=") == 0)
{
createPlayer(s.substr(5));
}
}
players[0]->parseLine(s);
}
break;
@@ -1379,9 +1458,12 @@ bool GameObserver::load(const string& ss, bool undo)
}
else
{
if(players.size() == 1 || !players[1]) {
AIPlayerFactory playerCreator;
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), players[0]));
if(players.size() == 1 || !players[1])
{
if (s.find("mode=") == 0)
{
createPlayer(s.substr(5));
}
}
players[1]->parseLine(s);
}
@@ -1556,6 +1638,27 @@ void GameObserver::Mulligan(Player* player)
player->takeMulligan();
}
void GameObserver::createPlayer(const string& playerMode)
{
Player::Mode aMode = (Player::Mode)atoi(playerMode.c_str());
switch(aMode)
{
case Player::MODE_AI:
AIPlayerFactory playerCreator;
// FIXME: gonna break in AI vs AI mode
players.push_back(playerCreator.createAIPlayer(this, MTGCollection(), players[0]));
break;
case Player::MODE_HUMAN:
players.push_back(new HumanPlayer(this, "", ""));
break;
case Player::MODE_TEST_SUITE:
// FIXME, not real TestPlayer, but we don't care here.
players.push_back(new Player(this, "", ""));
players.back()->playMode = Player::MODE_TEST_SUITE;
break;
}
}
#ifdef TESTSUITE
void GameObserver::loadTestSuitePlayer(int playerId, TestSuiteGame* testSuite)
{