- 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

View File

@@ -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

View File

@@ -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();
};

View File

@@ -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){

View File

@@ -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

View File

@@ -2930,7 +2930,7 @@ int AAWinGame::resolve()
if (canwin)
{
game->gameOver = p->opponent();
game->setLoser(p->opponent());
}
return 1;

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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]);
}
}
}

View File

@@ -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

View File

@@ -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];

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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();
}
*/
}
}
}