- 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
This commit is contained in:
Xawotihs@gmail.com
2012-03-20 23:10:05 +00:00
parent 865bc7e494
commit cb8af6d6c0
14 changed files with 80 additions and 58 deletions
+20 -6
View File
@@ -41,11 +41,7 @@ class GameObserver{
WResourceManager* mResourceManager; WResourceManager* mResourceManager;
JGE* mJGE; JGE* mJGE;
DeckManager* mDeckManager; DeckManager* mDeckManager;
Player * gameOver;
size_t updateCtr;
#ifdef ACTION_LOGGING_TESTING
GameObserver* oldGame;
#endif //ACTION_LOGGING_TESTING
int untap(MTGCardInstance * card); int untap(MTGCardInstance * card);
bool WaitForExtraPayment(MTGCardInstance* card); bool WaitForExtraPayment(MTGCardInstance* card);
@@ -83,7 +79,6 @@ class GameObserver{
TargetChooser * targetChooser; TargetChooser * targetChooser;
DuelLayers * mLayers; DuelLayers * mLayers;
ReplacementEffects *replacementEffects; ReplacementEffects *replacementEffects;
Player * gameOver;
vector<Player *> players; //created outside vector<Player *> players; //created outside
time_t startedAt; time_t startedAt;
Rules * mRules; Rules * mRules;
@@ -165,6 +160,25 @@ class GameObserver{
DeckManager* getDeckManager(){ return mDeckManager; }; DeckManager* getDeckManager(){ return mDeckManager; };
void dumpAssert(bool val); void dumpAssert(bool val);
void resetStartupGame(); 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 #endif
+1 -1
View File
@@ -67,7 +67,7 @@ public:
void handleResults(GameObserver* aGame){ void handleResults(GameObserver* aGame){
mMutex.lock(); mMutex.lock();
totalTestGames++; totalTestGames++;
if (aGame->gameOver == aGame->players[0]) if (aGame->didWin(aGame->players[1]))
testPlayer2Victories++; testPlayer2Victories++;
mMutex.unlock(); mMutex.unlock();
}; };
+2 -1
View File
@@ -164,7 +164,8 @@ public:
static void sortSubtypeList() static void sortSubtypeList()
{ {
return instance->subtypesList.sortSubTypes(); boost::mutex::scoped_lock lock(instance->mMutex);
instance->subtypesList.sortSubTypes();
} }
static int findSubtypeId(string value){ static int findSubtypeId(string value){
+2
View File
@@ -102,6 +102,8 @@ public:
std::string GetCurrentDeckStatsFile(); std::string GetCurrentDeckStatsFile();
virtual bool parseLine(const string& s); virtual bool parseLine(const string& s);
friend ostream& operator<<(ostream&, const Player&); friend ostream& operator<<(ostream&, const Player&);
bool operator<(Player& aPlayer);
bool isDead();
}; };
class HumanPlayer: public Player class HumanPlayer: public Player
+1 -1
View File
@@ -2930,7 +2930,7 @@ int AAWinGame::resolve()
if (canwin) if (canwin)
{ {
game->gameOver = p->opponent(); game->setLoser(p->opponent());
} }
return 1; return 1;
+4 -4
View File
@@ -173,7 +173,7 @@ void Credits::compute(GameObserver* g, GameApp * _app)
return; return;
PlayerData * playerdata = NEW PlayerData(MTGCollection()); PlayerData * playerdata = NEW PlayerData(MTGCollection());
if (p2->isAI() && p1 != g->gameOver) if (p2->isAI() && g->didWin(p1))
{ {
gameLength = time(0) - g->startedAt; gameLength = time(0) - g->startedAt;
value = 400; value = 400;
@@ -367,7 +367,7 @@ void Credits::Render()
{ {
if (!p1->isAI() && p2->isAI()) if (!p1->isAI() && p2->isAI())
{ {
if (observer->gameOver != p1) if (observer->didWin(p1))
{ {
sprintf(buffer, _("Congratulations! You earn %i credits").c_str(), value); sprintf(buffer, _("Congratulations! You earn %i credits").c_str(), value);
JQuadPtr unlockedQuad = GetUnlockedQuad(unlockedTextureName); JQuadPtr unlockedQuad = GetUnlockedQuad(unlockedTextureName);
@@ -389,7 +389,7 @@ void Credits::Render()
else else
{ {
int winner = 2; int winner = 2;
if (observer->gameOver != p1) if (observer->didWin(p1))
{ {
winner = 1; winner = 1;
} }
@@ -412,7 +412,7 @@ void Credits::Render()
y += 15; 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); sprintf(buffer, _("Game length: %i turns (%i seconds)").c_str(), observer->turn, this->gameLength);
f->DrawString(buffer, 10, y); f->DrawString(buffer, 10, y);
+2 -2
View File
@@ -206,12 +206,12 @@ void DeckStats::save(const std::string& filename)
void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game) void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game)
{ {
int victory = 1; int victory = 1;
if (!game->gameOver) if (!game->didWin())
{ {
if (player->life == opponent->life) return; if (player->life == opponent->life) return;
if (player->life < opponent->life) victory = 0; if (player->life < opponent->life) victory = 0;
} }
else if (game->gameOver == player) else if (!game->didWin(player))
{ {
victory = 0; victory = 0;
} }
+2 -26
View File
@@ -45,14 +45,11 @@ void GameObserver::cleanup()
combatStep = BLOCKERS; combatStep = BLOCKERS;
connectRule = false; connectRule = false;
actionsList.clear(); actionsList.clear();
gameTurn.clear();
} }
GameObserver::~GameObserver() GameObserver::~GameObserver()
{ {
#ifdef ACTION_LOGGING_TESTING
if(oldGame) SAFE_DELETE(oldGame);
#endif //ACTION_LOGGING_TESTING
LOG("==Destroying GameObserver=="); LOG("==Destroying GameObserver==");
for (size_t i = 0; i < players.size(); ++i) 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) : randomGenerator(true), mResourceManager(output), mJGE(input)
{ {
updateCtr = 0;
#ifdef ACTION_LOGGING_TESTING
oldGame = 0;
#endif //ACTION_LOGGING_TESTING
ExtraRules = new MTGCardInstance[2](); ExtraRules = new MTGCardInstance[2]();
mGameType = GAME_TYPE_CLASSIC; mGameType = GAME_TYPE_CLASSIC;
@@ -549,23 +542,6 @@ void GameObserver::dumpAssert(bool val)
void GameObserver::Update(float dt) 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; Player * player = currentPlayer;
if (MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) if (MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep)
{ {
@@ -757,7 +733,7 @@ void GameObserver::gameStateBasedEffects()
} }
if (cantlosers < 1) if (cantlosers < 1)
{ {
gameOver = players[i]; setLoser(players[i]);
} }
} }
} }
+6 -6
View File
@@ -294,11 +294,11 @@ void GameStateDuel::ThreadProc(void* inParam)
int oldPhase = -1; int oldPhase = -1;
int stagnationCounter = -1; int stagnationCounter = -1;
observer.loadPlayer(0, PLAYER_TYPE_TESTSUITE); observer.loadPlayer(0, PLAYER_TYPE_CPU_TEST);
observer.loadPlayer(1, PLAYER_TYPE_TESTSUITE); observer.loadPlayer(1, PLAYER_TYPE_CPU_TEST);
observer.startGame(instance->mParent->gameType, instance->mParent->rules); observer.startGame(instance->mParent->gameType, instance->mParent->rules);
while(!observer.gameOver) { while(!observer.didWin()) {
if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase) { if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase) {
stagnationCounter++; stagnationCounter++;
} else { } 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) // 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); mParent->rules->postUpdateInit(game);
if (game->gameOver) if (game->didWin())
{ {
if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game, mParent); if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game, mParent);
setGamePhase(DUEL_STATE_END); setGamePhase(DUEL_STATE_END);
@@ -486,7 +486,7 @@ void GameStateDuel::Update(float dt)
#ifdef QT_CONFIG #ifdef QT_CONFIG
thread_count = QThread::idealThreadCount(); thread_count = QThread::idealThreadCount();
#endif #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)); mWorkerThread.push_back(boost::thread(ThreadProc, this));
} }
} }
@@ -515,7 +515,7 @@ void GameStateDuel::Update(float dt)
} }
//END almosthumane - mulligan //END almosthumane - mulligan
menu->Add(MENUITEM_MAIN_MENU, "Back to main menu"); menu->Add(MENUITEM_MAIN_MENU, "Back to main menu");
//menu->Add(MENUITEM_UNDO, "Undo"); menu->Add(MENUITEM_UNDO, "Undo");
#ifdef TESTSUITE #ifdef TESTSUITE
menu->Add(MENUITEM_LOAD, "Load"); menu->Add(MENUITEM_LOAD, "Load");
#endif #endif
+1 -1
View File
@@ -221,7 +221,7 @@ void MTGPlayerCards::drawFromLibrary()
return; return;
} }
library->owner->getObserver()->gameOver = library->owner; library->owner->getObserver()->setLoser(library->owner);
return; return;
} }
MTGCardInstance * toMove = library->cards[library->nb_cards - 1]; MTGCardInstance * toMove = library->cards[library->nb_cards - 1];
+28
View File
@@ -348,4 +348,32 @@ ostream& operator<<(ostream& out, const Player& p)
return out; 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;
};
+2 -2
View File
@@ -365,9 +365,9 @@ void StoryDuel::Update(float dt)
{ {
if (!game) init(); if (!game) init();
game->Update(dt); game->Update(dt);
if (game->gameOver) if (game->didWin())
{ {
if (game->gameOver == game->players[1]) if (game->didWin(game->players[0]))
mParent->gotoPage(onWin); mParent->gotoPage(onWin);
else else
mParent->gotoPage(onLose); mParent->gotoPage(onLose);
+4 -4
View File
@@ -617,7 +617,7 @@ string TaskWinAgainst::getShortDesc()
bool TaskWinAgainst::isDone(GameObserver* observer, GameApp * _app) bool TaskWinAgainst::isDone(GameObserver* observer, GameApp * _app)
{ {
AIPlayerBaka * baka = (AIPlayerBaka*) observer->players[1]; 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)); && (baka->deckId == opponent));
} }
@@ -823,7 +823,7 @@ string TaskImmortal::getShortDesc()
bool TaskImmortal::isDone(GameObserver *observer, GameApp * _app) 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); && (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); && (countColor >= cardCount);
} }
@@ -1092,7 +1092,7 @@ string TaskPacifism::getShortDesc()
bool TaskPacifism::isDone(GameObserver* observer, GameApp * _app) 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); && (observer->players[1]->life >= lifeSlashCardMin) && ((int) observer->players[1]->game->library->cards.size() >= lifeSlashCardMin);
} }
+5 -4
View File
@@ -77,7 +77,7 @@ int TestSuiteAI::displayStack()
int TestSuiteAI::Act(float dt) 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 //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 //end of game
suite->assertGame(); suite->assertGame();
observer->gameOver = observer->players[0]; observer->setLoser(observer->players[0]);
DebugTrace("================================ END OF TEST =======================\n"); DebugTrace("================================ END OF TEST =======================\n");
return 1; return 1;
} }
@@ -764,9 +764,9 @@ void TestSuite::ThreadProc(void* inParam)
theGame.observer->startGame(theGame.gameType, instance->mRules); theGame.observer->startGame(theGame.gameType, instance->mRules);
theGame.initGame(); theGame.initGame();
while(!theGame.observer->gameOver) while(!theGame.observer->didWin())
theGame.observer->Update(counter++); theGame.observer->Update(counter++);
/*
if(theGame.observer->gameType() != GAME_TYPE_MOMIR) if(theGame.observer->gameType() != GAME_TYPE_MOMIR)
{ {
stringstream stream; stringstream stream;
@@ -774,6 +774,7 @@ void TestSuite::ThreadProc(void* inParam)
theGame.observer->load(stream.str(), false, &theGame); theGame.observer->load(stream.str(), false, &theGame);
theGame.assertGame(); theGame.assertGame();
} }
*/
} }
} }
} }