- 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:
@@ -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<Player *> 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
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2930,7 +2930,7 @@ int AAWinGame::resolve()
|
||||
|
||||
if (canwin)
|
||||
{
|
||||
game->gameOver = p->opponent();
|
||||
game->setLoser(p->opponent());
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user