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