From cb8af6d6c02e8d5cee41eea70019430390dd1b9e Mon Sep 17 00:00:00 2001 From: "Xawotihs@gmail.com" Date: Tue, 20 Mar 2012 23:10:05 +0000 Subject: [PATCH] - modified gameOver to be protected and defined two new operations to do the same thing (didWin and setLoser) - removed ACTION_LOGGING_TESTING code - Fixed AIvsAI games multithreaded games - Activated undo when testsuite is enable - Defined an initial player comparison operator - Fixed multi-threaded modification to subtypes - Fixed gameTurn cleanup for gameObserver reuse --- projects/mtg/include/GameObserver.h | 26 ++++++++++++++++++++------ projects/mtg/include/GameStateDuel.h | 2 +- projects/mtg/include/MTGDeck.h | 3 ++- projects/mtg/include/Player.h | 2 ++ projects/mtg/src/AllAbilities.cpp | 2 +- projects/mtg/src/Credits.cpp | 8 ++++---- projects/mtg/src/DeckStats.cpp | 4 ++-- projects/mtg/src/GameObserver.cpp | 28 ++-------------------------- projects/mtg/src/GameStateDuel.cpp | 12 ++++++------ projects/mtg/src/MTGGameZones.cpp | 2 +- projects/mtg/src/Player.cpp | 28 ++++++++++++++++++++++++++++ projects/mtg/src/StoryFlow.cpp | 4 ++-- projects/mtg/src/Tasks.cpp | 8 ++++---- projects/mtg/src/TestSuiteAI.cpp | 9 +++++---- 14 files changed, 80 insertions(+), 58 deletions(-) diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 54f21fd33..cee0072f0 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -41,11 +41,7 @@ class GameObserver{ WResourceManager* mResourceManager; JGE* mJGE; DeckManager* mDeckManager; - - size_t updateCtr; -#ifdef ACTION_LOGGING_TESTING - GameObserver* oldGame; -#endif //ACTION_LOGGING_TESTING + Player * gameOver; int untap(MTGCardInstance * card); bool WaitForExtraPayment(MTGCardInstance* card); @@ -83,7 +79,6 @@ class GameObserver{ TargetChooser * targetChooser; DuelLayers * mLayers; ReplacementEffects *replacementEffects; - Player * gameOver; vector players; //created outside time_t startedAt; Rules * mRules; @@ -165,6 +160,25 @@ class GameObserver{ DeckManager* getDeckManager(){ return mDeckManager; }; void dumpAssert(bool val); void resetStartupGame(); + void setLoser(Player* aPlayer) { + gameOver = aPlayer; + }; + + bool didWin(Player* aPlayer = 0) const { + if(!gameOver) { + // nobody won + return false; + } else if(!aPlayer) { + // somebody won and we don't care who + return true; + } else if(gameOver == aPlayer) { + // aPlayer lost + return false; + } else { + // aPlayer won + return true; + } + }; }; #endif diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 5526ac39a..2fd971903 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -67,7 +67,7 @@ public: void handleResults(GameObserver* aGame){ mMutex.lock(); totalTestGames++; - if (aGame->gameOver == aGame->players[0]) + if (aGame->didWin(aGame->players[1])) testPlayer2Victories++; mMutex.unlock(); }; diff --git a/projects/mtg/include/MTGDeck.h b/projects/mtg/include/MTGDeck.h index a21e44795..247598948 100644 --- a/projects/mtg/include/MTGDeck.h +++ b/projects/mtg/include/MTGDeck.h @@ -164,7 +164,8 @@ public: static void sortSubtypeList() { - return instance->subtypesList.sortSubTypes(); + boost::mutex::scoped_lock lock(instance->mMutex); + instance->subtypesList.sortSubTypes(); } static int findSubtypeId(string value){ diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index a76f1add4..4bc516c6a 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -102,6 +102,8 @@ public: std::string GetCurrentDeckStatsFile(); virtual bool parseLine(const string& s); friend ostream& operator<<(ostream&, const Player&); + bool operator<(Player& aPlayer); + bool isDead(); }; class HumanPlayer: public Player diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 15b12f1d7..6d931541b 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -2930,7 +2930,7 @@ int AAWinGame::resolve() if (canwin) { - game->gameOver = p->opponent(); + game->setLoser(p->opponent()); } return 1; diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index 654ad600e..fffb57f36 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -173,7 +173,7 @@ void Credits::compute(GameObserver* g, GameApp * _app) return; PlayerData * playerdata = NEW PlayerData(MTGCollection()); - if (p2->isAI() && p1 != g->gameOver) + if (p2->isAI() && g->didWin(p1)) { gameLength = time(0) - g->startedAt; value = 400; @@ -367,7 +367,7 @@ void Credits::Render() { if (!p1->isAI() && p2->isAI()) { - if (observer->gameOver != p1) + if (observer->didWin(p1)) { sprintf(buffer, _("Congratulations! You earn %i credits").c_str(), value); JQuadPtr unlockedQuad = GetUnlockedQuad(unlockedTextureName); @@ -389,7 +389,7 @@ void Credits::Render() else { int winner = 2; - if (observer->gameOver != p1) + if (observer->didWin(p1)) { winner = 1; } @@ -412,7 +412,7 @@ void Credits::Render() y += 15; //!! - if (observer->gameOver != p1 && this->gameLength != 0) + if (observer->didWin(p1) && this->gameLength != 0) { sprintf(buffer, _("Game length: %i turns (%i seconds)").c_str(), observer->turn, this->gameLength); f->DrawString(buffer, 10, y); diff --git a/projects/mtg/src/DeckStats.cpp b/projects/mtg/src/DeckStats.cpp index d13355049..329ce3736 100644 --- a/projects/mtg/src/DeckStats.cpp +++ b/projects/mtg/src/DeckStats.cpp @@ -206,12 +206,12 @@ void DeckStats::save(const std::string& filename) void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game) { int victory = 1; - if (!game->gameOver) + if (!game->didWin()) { if (player->life == opponent->life) return; if (player->life < opponent->life) victory = 0; } - else if (game->gameOver == player) + else if (!game->didWin(player)) { victory = 0; } diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 75fd8e610..e3967a971 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -45,14 +45,11 @@ void GameObserver::cleanup() combatStep = BLOCKERS; connectRule = false; actionsList.clear(); + gameTurn.clear(); } 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) { @@ -79,10 +76,6 @@ 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](); mGameType = GAME_TYPE_CLASSIC; @@ -549,23 +542,6 @@ void GameObserver::dumpAssert(bool val) 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()); - DumpAssert(*this == *oldGame); - } -#endif // ACTION_LOGGING_TESTING - - /*******************/ Player * player = currentPlayer; if (MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) { @@ -757,7 +733,7 @@ void GameObserver::gameStateBasedEffects() } if (cantlosers < 1) { - gameOver = players[i]; + setLoser(players[i]); } } } diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 04c30e6a0..b3916da4a 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -294,11 +294,11 @@ void GameStateDuel::ThreadProc(void* inParam) int oldPhase = -1; int stagnationCounter = -1; - observer.loadPlayer(0, PLAYER_TYPE_TESTSUITE); - observer.loadPlayer(1, PLAYER_TYPE_TESTSUITE); + observer.loadPlayer(0, PLAYER_TYPE_CPU_TEST); + observer.loadPlayer(1, PLAYER_TYPE_CPU_TEST); observer.startGame(instance->mParent->gameType, instance->mParent->rules); - while(!observer.gameOver) { + while(!observer.didWin()) { if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase) { stagnationCounter++; } else { @@ -451,7 +451,7 @@ void GameStateDuel::Update(float dt) // That's mostly because of a legacy bug, where we use the update sequence for some things when we should use events (such as phase changes) mParent->rules->postUpdateInit(game); - if (game->gameOver) + if (game->didWin()) { if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game, mParent); setGamePhase(DUEL_STATE_END); @@ -486,7 +486,7 @@ void GameStateDuel::Update(float dt) #ifdef QT_CONFIG thread_count = QThread::idealThreadCount(); #endif - for(size_t i = 0; i < (thread_count-1); i++) + for(size_t i = 0; i < (thread_count); i++) mWorkerThread.push_back(boost::thread(ThreadProc, this)); } } @@ -515,7 +515,7 @@ void GameStateDuel::Update(float dt) } //END almosthumane - mulligan menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); - //menu->Add(MENUITEM_UNDO, "Undo"); + menu->Add(MENUITEM_UNDO, "Undo"); #ifdef TESTSUITE menu->Add(MENUITEM_LOAD, "Load"); #endif diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 5823d00c8..9e3c0ef48 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -221,7 +221,7 @@ void MTGPlayerCards::drawFromLibrary() return; } - library->owner->getObserver()->gameOver = library->owner; + library->owner->getObserver()->setLoser(library->owner); return; } MTGCardInstance * toMove = library->cards[library->nb_cards - 1]; diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 3cb40ae74..6d510bf06 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -348,4 +348,32 @@ ostream& operator<<(ostream& out, const Player& p) return out; } +// Method comparing "this" to "aPlayer", each in their own gameObserver +bool Player::operator<(Player& aPlayer) +{ + // if this is dead and aPlayer is not dead then this < aPlayer + if(isDead() && !aPlayer.isDead()) + return true; + // heuristics for min-max + + // if this is more poisoined than aPlayer then this < aPlayer + if(poisonCount > aPlayer.poisonCount) + return true; + + // if this has less life than aPlayer then this < aPlayer + if(life < aPlayer.life) + return true; + + // if this has less parmanents in game that aPlayer then this < aPlayer + if(game->battlefield->cards.size() < aPlayer.game->battlefield->cards.size()) + return true; + + return false; +} + +bool Player::isDead() { + if(observer) + return observer->didWin(opponent()); + return false; +}; diff --git a/projects/mtg/src/StoryFlow.cpp b/projects/mtg/src/StoryFlow.cpp index 06bb5ce17..5eac5828c 100644 --- a/projects/mtg/src/StoryFlow.cpp +++ b/projects/mtg/src/StoryFlow.cpp @@ -365,9 +365,9 @@ void StoryDuel::Update(float dt) { if (!game) init(); game->Update(dt); - if (game->gameOver) + if (game->didWin()) { - if (game->gameOver == game->players[1]) + if (game->didWin(game->players[0])) mParent->gotoPage(onWin); else mParent->gotoPage(onLose); diff --git a/projects/mtg/src/Tasks.cpp b/projects/mtg/src/Tasks.cpp index c6c623edf..aefe1ad86 100644 --- a/projects/mtg/src/Tasks.cpp +++ b/projects/mtg/src/Tasks.cpp @@ -617,7 +617,7 @@ string TaskWinAgainst::getShortDesc() bool TaskWinAgainst::isDone(GameObserver* observer, GameApp * _app) { AIPlayerBaka * baka = (AIPlayerBaka*) observer->players[1]; - return ((baka) && (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->gameOver != observer->players[0]) // Human player wins + return ((baka) && (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->didWin(observer->players[0])) // Human player wins && (baka->deckId == opponent)); } @@ -823,7 +823,7 @@ string TaskImmortal::getShortDesc() bool TaskImmortal::isDone(GameObserver *observer, GameApp * _app) { - return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->gameOver != observer->players[0]) // Human player wins + return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->didWin(observer->players[0])) // Human player wins && (observer->players[0]->life >= targetLife); } @@ -1022,7 +1022,7 @@ bool TaskWisdom::isDone(GameObserver* observer, GameApp * _app) } } - return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->gameOver != observer->players[0]) // Human player wins + return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->didWin(observer->players[0])) // Human player wins && (countColor >= cardCount); } @@ -1092,7 +1092,7 @@ string TaskPacifism::getShortDesc() bool TaskPacifism::isDone(GameObserver* observer, GameApp * _app) { - return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->gameOver != observer->players[0]) // Human player wins + return (!observer->players[0]->isAI()) && (observer->players[1]->isAI()) && (observer->didWin(observer->players[0])) // Human player wins && (observer->players[1]->life >= lifeSlashCardMin) && ((int) observer->players[1]->game->library->cards.size() >= lifeSlashCardMin); } diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index ef2492d9b..a945618fb 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -77,7 +77,7 @@ int TestSuiteAI::displayStack() int TestSuiteAI::Act(float dt) { - observer->gameOver = NULL; // Prevent draw rule from losing the game + observer->setLoser(NULL); // Prevent draw rule from losing the game //Last bits of initialization require to be done here, after the first "update" call of the game @@ -123,7 +123,7 @@ int TestSuiteAI::Act(float dt) { //end of game suite->assertGame(); - observer->gameOver = observer->players[0]; + observer->setLoser(observer->players[0]); DebugTrace("================================ END OF TEST =======================\n"); return 1; } @@ -764,9 +764,9 @@ void TestSuite::ThreadProc(void* inParam) theGame.observer->startGame(theGame.gameType, instance->mRules); theGame.initGame(); - while(!theGame.observer->gameOver) + while(!theGame.observer->didWin()) theGame.observer->Update(counter++); - +/* if(theGame.observer->gameType() != GAME_TYPE_MOMIR) { stringstream stream; @@ -774,6 +774,7 @@ void TestSuite::ThreadProc(void* inParam) theGame.observer->load(stream.str(), false, &theGame); theGame.assertGame(); } +*/ } } }