From e50fdba64846de01539a8283888ddfcef93fb22a Mon Sep 17 00:00:00 2001 From: Xawotihs Date: Sun, 6 Nov 2011 17:31:44 +0000 Subject: [PATCH] - Replaced static parts by per-instance parts of of several classes when they were not threadsafe (AIMomirPlayer, SimpleMenu, Trash, AIAction, MTGCardInstance, ATutorialMessage, MTGRules). The direct consequence is that we could consumme more memory. So, tell me if you have problems with low memory devices (PSP), there are some threadsafe optimizations that could be implemented if needed. - Reworked the testsuite to be able to work multithreaded. This is deactivated by default everywhere except in QT_CONFIG as one testcase still refuses to pass in multithreaded mode. On my 4 cores linux desktop, the 650 tests passes now in 4 seconds (1 fails). - Replaced usage of CardSelectorSingleton by a card selector per game observer. - Modified the resource manager to be optionnal and per game observer instance instead of being a singleton. Two reasons here : threading AND Open Gl access. I only updated the crashing parts called from the game observer, so most of the code is still using the single instance. Beware of copy-paste concerning resources ... - Cleaned up the game observer constructors - Fixed several problems in action logging code while testing proliferate decks - Cleaned up Threading implementation based on QThread --- JGE/include/Threading.h | 8 +- projects/mtg/include/AIMomirPlayer.h | 2 +- projects/mtg/include/AIPlayer.h | 5 - projects/mtg/include/ActionStack.h | 7 +- projects/mtg/include/AllAbilities.h | 3 - projects/mtg/include/DuelLayers.h | 1 + projects/mtg/include/GameObserver.h | 17 +- projects/mtg/include/MTGCardInstance.h | 2 - projects/mtg/include/MTGRules.h | 8 +- projects/mtg/include/SimpleMenu.h | 3 +- projects/mtg/include/TestSuiteAI.h | 79 ++++-- projects/mtg/include/Trash.h | 29 ++- projects/mtg/src/AIMomirPlayer.cpp | 2 - projects/mtg/src/AIPlayer.cpp | 12 +- projects/mtg/src/AIStats.cpp | 2 +- projects/mtg/src/ActionStack.cpp | 38 +-- projects/mtg/src/AllAbilities.cpp | 39 ++- projects/mtg/src/CardDisplay.cpp | 2 +- projects/mtg/src/CardGui.cpp | 26 +- projects/mtg/src/DuelLayers.cpp | 14 +- projects/mtg/src/GameObserver.cpp | 49 ++-- projects/mtg/src/GameStateDuel.cpp | 9 +- projects/mtg/src/GuiAvatars.cpp | 14 +- projects/mtg/src/GuiCombat.cpp | 18 +- projects/mtg/src/GuiFrame.cpp | 34 +-- projects/mtg/src/GuiHand.cpp | 27 +- projects/mtg/src/GuiPhaseBar.cpp | 2 +- projects/mtg/src/GuiPlay.cpp | 6 +- projects/mtg/src/GuiStatic.cpp | 6 +- projects/mtg/src/MTGCardInstance.cpp | 2 - projects/mtg/src/MTGGameZones.cpp | 13 +- projects/mtg/src/MTGRules.cpp | 20 +- projects/mtg/src/Player.cpp | 12 +- projects/mtg/src/Rules.cpp | 8 +- projects/mtg/src/SimpleMenu.cpp | 7 +- projects/mtg/src/StoryFlow.cpp | 9 +- projects/mtg/src/TestSuiteAI.cpp | 344 ++++++++++++++++--------- projects/mtg/src/Trash.cpp | 12 +- 38 files changed, 509 insertions(+), 382 deletions(-) diff --git a/JGE/include/Threading.h b/JGE/include/Threading.h index 532467515..fe3c79068 100644 --- a/JGE/include/Threading.h +++ b/JGE/include/Threading.h @@ -449,15 +449,15 @@ namespace boost { detail::thread_data_ptr mThreadInfo; public: - static threadImpl* spThreadImpl; threadImpl(detail::thread_data_ptr threadInfo) : mThreadInfo(threadInfo) { setTerminationEnabled(); - spThreadImpl = this; }; static void mymsleep(unsigned long msecs) { - spThreadImpl->msleep(msecs); + QThread* currentThread = QThread::currentThread(); + if(currentThread) + currentThread->msleep(msecs); } protected: void run() @@ -467,8 +467,6 @@ namespace boost } }; - threadImpl* threadImpl::spThreadImpl = 0; - /** ** A simplistic implementation of boost::thread, using QThread. ** diff --git a/projects/mtg/include/AIMomirPlayer.h b/projects/mtg/include/AIMomirPlayer.h index 39ca3fc95..07526778f 100644 --- a/projects/mtg/include/AIMomirPlayer.h +++ b/projects/mtg/include/AIMomirPlayer.h @@ -10,7 +10,7 @@ public: int getEfficiency(OrderedAIAction * action); int momir(); int computeActions(); - static MTGAbility * momirAbility; + MTGAbility * momirAbility; MTGAbility * getMomirAbility(); }; diff --git a/projects/mtg/include/AIPlayer.h b/projects/mtg/include/AIPlayer.h index d09802f3f..6042dd9fa 100644 --- a/projects/mtg/include/AIPlayer.h +++ b/projects/mtg/include/AIPlayer.h @@ -26,8 +26,6 @@ class AIPlayer; class AIAction { -protected: - static int currentId; public: AIPlayer * owner; MTGAbility * ability; @@ -43,7 +41,6 @@ public: AIAction(AIPlayer * owner, MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL) : owner(owner), ability(a), player(NULL), click(c), target(t),playerAbilityTarget(NULL) { - id = currentId++; }; AIAction(AIPlayer * owner, MTGCardInstance * c, MTGCardInstance * t = NULL); @@ -56,13 +53,11 @@ public: AIAction(AIPlayer * owner, MTGAbility * a, MTGCardInstance * c, vectortargetCards) : owner(owner), ability(a), player(NULL), click(c), mAbilityTargets(targetCards),playerAbilityTarget(NULL) { - id = currentId++; }; AIAction(AIPlayer * owner, MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities. : owner(owner), ability(a), click(c),target(NULL), playerAbilityTarget(p) { - id = currentId++; }; int Act(); int clickMultiAct(vector&actionTargets); diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index a8c5f5917..03c9ec1a2 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -176,6 +176,7 @@ public: DrawAction(GameObserver* observer, int id, Player * _player, int _nbcards); }; +class ATutorialMessage; class LifeAction: public Interruptible { public: @@ -196,6 +197,7 @@ protected: int currentState; int mode; int checked; + ATutorialMessage* currentTutorial; public: @@ -216,7 +218,7 @@ public: int getNextIndex(Interruptible * previous, int type = 0, int state = 0 , int display = -1); void Fizzle(Interruptible * action); Interruptible * getAt(int id); - void cancelInterruptOffer(int cancelMode = 1); + void cancelInterruptOffer(int cancelMode = 1, bool log = true); void endOfInterruption(bool log = true); Interruptible * getLatest(int state); Player * askIfWishesToInterrupt; @@ -241,7 +243,8 @@ public: #if defined (WIN32) || defined (LINUX) || defined (IOS) void Dump(); #endif - + void setCurrentTutorial(ATutorialMessage* message) {currentTutorial = message;}; + ATutorialMessage* getCurrentTutorial() {return currentTutorial;}; }; #endif diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 3fb3898e0..2adb79277 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -781,9 +781,6 @@ public: //JGuiListener Implementation void ButtonPressed(int controllerId, int controlId); - - static ATutorialMessage * Current; - }; diff --git a/projects/mtg/include/DuelLayers.h b/projects/mtg/include/DuelLayers.h index 931df1446..52986e645 100644 --- a/projects/mtg/include/DuelLayers.h +++ b/projects/mtg/include/DuelLayers.h @@ -26,6 +26,7 @@ protected: ActionStack* stack; GuiHandSelf *hand; GuiAvatars * avatars; + GameObserver* observer; public: DuelLayers(); diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 25b969eb6..91d421fcd 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -13,6 +13,7 @@ #include #include + class MTGGamePhase; class MTGAbility; class MTGCardInstance; @@ -20,7 +21,8 @@ struct CardGui; class Player; class TargetChooser; class Rules; -class TestSuite; +class TestSuiteGame; +class Trash; using namespace std; class GameObserver{ @@ -46,6 +48,7 @@ class GameObserver{ void nextGamePhase(); void shuffleLibrary(Player* p); RandomGenerator randomGenerator; + WResourceManager* mResourceManager; public: int currentPlayerId; @@ -66,6 +69,8 @@ class GameObserver{ time_t startedAt; Rules * mRules; GameType mGameType; + MTGCardInstance* ExtraRules; + Trash* mTrash; TargetChooser * getCurrentTargetChooser(); void stackObjectClicked(Interruptible * action); @@ -80,19 +85,19 @@ class GameObserver{ void userRequestNextGamePhase(bool allowInterrupt = true, bool log = true); void cleanupPhase(); void nextPlayer(); - void setPlayers(vector _players); #ifdef TESTSUITE - void loadTestSuitePlayer(int playerId, TestSuite* testSuite); + void loadTestSuitePlayer(int playerId, TestSuiteGame* testSuite); #endif //TESTSUITE void loadPlayer(int playerId, PlayerType playerType = PLAYER_TYPE_HUMAN, int decknb=0, bool premadeDeck=false); + void loadPlayer(int playerId, Player* player); + Player * currentPlayer; Player * currentActionPlayer; Player * isInterrupting; Player * opponent(); Player * currentlyActing(); - GameObserver(); - GameObserver(vector _players); + GameObserver(WResourceManager* resourceManager = NULL); ~GameObserver(); void gameStateBasedEffects(); void enchantmentStatus(); @@ -125,6 +130,8 @@ class GameObserver{ Player* getPlayer(size_t index) { return players[index];}; bool isStarted() { return (mLayers!=NULL);}; RandomGenerator* getRandomGenerator() { return &randomGenerator; }; + WResourceManager* getResourceManager() { if(this) return mResourceManager;else return 0;}; + CardSelectorBase* getCardSelector() { return mLayers->mCardSelector;}; }; #endif diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 613c1c90b..c5e40899a 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -208,8 +208,6 @@ public: static MTGCardInstance AnyCard; static MTGCardInstance NoCard; - static MTGCardInstance ExtraRules[2]; - bool parseLine(const string& ss); }; diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index c677d2a69..9016f4fe6 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -306,8 +306,8 @@ class MTGMomirRule: public PermanentAbility { private: int genRandomCreatureId(int convertedCost); - static vector pool[20]; - static int initialized; + vector pool[20]; + int initialized; int textAlpha; string text; @@ -335,8 +335,8 @@ class MTGStoneHewerRule: public PermanentAbility { private: int genRandomEquipId(int convertedCost); - static vector pool[20]; - static int initialized; + vector pool[20]; + int initialized; public: MTGAllCards * collection; MTGCardInstance * genEquip(int id); diff --git a/projects/mtg/include/SimpleMenu.h b/projects/mtg/include/SimpleMenu.h index 9593eaa90..c9e1786f7 100644 --- a/projects/mtg/include/SimpleMenu.h +++ b/projects/mtg/include/SimpleMenu.h @@ -28,8 +28,7 @@ private: static JQuadPtr spadeR, spadeL, jewel, side; static JTexture *spadeRTex, *spadeLTex, *jewelTex, *sideTex; - static WFont* titleFont; - static hgeParticleSystem* stars; + hgeParticleSystem* stars; inline void MogrifyJewel(); void drawHorzPole(float x, float y, float width); diff --git a/projects/mtg/include/TestSuiteAI.h b/projects/mtg/include/TestSuiteAI.h index f82567571..ccaf9b3ab 100644 --- a/projects/mtg/include/TestSuiteAI.h +++ b/projects/mtg/include/TestSuiteAI.h @@ -6,6 +6,7 @@ #define MAX_TESTSUITE_ACTIONS 100 #define MAX_TESTUITE_CARDS 100 +#include "Threading.h" #include "AIPlayerBaka.h" class TestSuiteActions @@ -19,6 +20,7 @@ public: }; +class TestSuiteGame; class TestSuite; class TestSuiteAI; class TestSuiteState @@ -30,64 +32,87 @@ public: ~TestSuiteState(); vector players; - void cleanup(TestSuite*); + void cleanup(TestSuiteGame* tsGame); }; -class TestSuitePregame +class TestSuiteGame { + friend class TestSuiteAI; + friend class TestSuite; +protected: + string filename; + int summoningSickness; + bool forceAbility; + GameType gameType; + unsigned int seed; + int aiMaxCalls; + TestSuiteState endState; + TestSuiteState initState; + TestSuiteActions actions; + float timerLimit; + bool isOK; + int currentAction; + GameObserver* observer; + + static boost::mutex mMutex; + virtual void handleResults(bool wasAI, int error); + TestSuite* testsuite; + bool load(); + public: - virtual void performTest() = 0; + ~TestSuiteGame(); + TestSuiteGame(TestSuite* testsuite); + TestSuiteGame(TestSuite* testsuite, string _filename); + void initGame(); + void assertGame(); + MTGPlayerCards * buildDeck(Player* player, int playerId); + GameType getGameType() { return gameType; }; + string getNextAction(); + Interruptible * getActionByMTGId(int mtgid); + static int Log(const char * text); + void setObserver(GameObserver* anObserver) {observer = anObserver; }; }; -class TestSuite +class TestSuite : public TestSuiteGame { private: int currentfile; int nbfiles; string files[1024]; - TestSuiteState endState; - TestSuiteActions actions; - bool forceAbility; - int load(const char * filename); void cleanup(); - -public: - /* but only used by the testsuite classes */ - float timerLimit; - int aiMaxCalls; - int currentAction; - int summoningSickness; - - TestSuiteState initState; - string getNextAction(); - MTGPlayerCards * buildDeck(Player*, int playerId); - Interruptible * getActionByMTGId(GameObserver* observer, int mtgid); - int assertGame(GameObserver*); + vector mWorkerThread; + Rules* mRules; + bool mProcessing; public: int startTime, endTime; - GameType gameType; unsigned int seed; int nbFailed, nbTests, nbAIFailed, nbAITests; TestSuite(const char * filename); void initGame(GameObserver* g); void pregameTests(); int loadNext(); - static int Log(const char * text); - + string getNextFile() { + boost::mutex::scoped_lock lock(mMutex); + if (currentfile >= nbfiles) return ""; + currentfile++; + return files[currentfile - 1]; + }; + static void ThreadProc(void* inParam); + void setRules(Rules* rules) {mRules = rules;}; + void handleResults(bool wasAI, int error); }; -// TODO This should inherit from AIPlayer instead! class TestSuiteAI:public AIPlayerBaka { private: MTGCardInstance * getCard(string action); float timer; - TestSuite * suite; + TestSuiteGame * suite; public: - TestSuiteAI(GameObserver *observer, TestSuite * suite, int playerId); + TestSuiteAI(TestSuiteGame *tsGame, int playerId); virtual int Act(float dt); virtual int displayStack(); bool summoningSickness() {return (suite->summoningSickness == 1); } diff --git a/projects/mtg/include/Trash.h b/projects/mtg/include/Trash.h index 830d5a112..14c781b53 100644 --- a/projects/mtg/include/Trash.h +++ b/projects/mtg/include/Trash.h @@ -4,22 +4,39 @@ #include #include "Pos.h" #include "WEvent.h" +#include "DamagerDamaged.h" + +class CardView; +class AttackerDamaged; +class DamagerDamaged; +typedef DamagerDamaged DefenserDamaged; template void trash(T*); -class Trash -{ -public: - static void cleanup(); -}; template class TrashBin { - std::vector bin; + std::vector bin; void put_out(); int receiveEvent(WEvent* e); template friend void trash(Q*); friend class Trash; }; + +class Trash +{ +private: + TrashBin CardViewTrash; + TrashBin DefenserDamagedTrash; + TrashBin AttackerDamagedTrash; + +public: + Trash(){}; + void cleanup(); + void trash(CardView* garbage); + void trash(DefenserDamaged* garbage); + void trash(AttackerDamaged* garbage); +}; + #endif // _TRASH_H_ diff --git a/projects/mtg/src/AIMomirPlayer.cpp b/projects/mtg/src/AIMomirPlayer.cpp index 8b3d89be9..461c1aa25 100644 --- a/projects/mtg/src/AIMomirPlayer.cpp +++ b/projects/mtg/src/AIMomirPlayer.cpp @@ -6,8 +6,6 @@ #include "AIStats.h" #include "AllAbilities.h" -MTGAbility * AIMomirPlayer::momirAbility = NULL; - AIMomirPlayer::AIMomirPlayer(GameObserver *observer, string file, string fileSmall, string avatarFile, MTGDeck * deck) : AIPlayerBaka(observer, file, fileSmall, avatarFile, deck) { diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index fd27e54b6..78de54ecd 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -17,28 +17,24 @@ const char * const MTG_LAND_TEXTS[] = { "artifact", "forest", "island", "mountain", "swamp", "plains", "other lands" }; -int AIAction::currentId = 0; - AIAction::AIAction(AIPlayer * owner, MTGCardInstance * c, MTGCardInstance * t) : owner(owner), ability(NULL), player(NULL), click(c), target(t) { - id = currentId++; - // useability tweak - assume that the user is probably going to want to see the full res card, // so prefetch it. The idea is that we do it here as we want to start the prefetch before it's time to render, // and waiting for it to actually go into play is too late, as we start drawing the card during the interrupt window. // This is a good intercept point, as the AI has committed to using this card. // if we're not in text mode, always get the thumb - if (CardSelectorSingleton::Instance()->GetDrawMode() != DrawMode::kText) + if (owner->getObserver()->getCardSelector()->GetDrawMode() != DrawMode::kText) { //DebugTrace("Prefetching AI card going into play: " << c->getImageName()); - WResourceManager::Instance()->RetrieveCard(c, RETRIEVE_THUMB); + owner->getObserver()->getResourceManager()->RetrieveCard(c, RETRIEVE_THUMB); // also cache the large image if we're using kNormal mode - if (CardSelectorSingleton::Instance()->GetDrawMode() == DrawMode::kNormal) + if (owner->getObserver()->getCardSelector()->GetDrawMode() == DrawMode::kNormal) { - WResourceManager::Instance()->RetrieveCard(c); + owner->getObserver()->getResourceManager()->RetrieveCard(c); } } } diff --git a/projects/mtg/src/AIStats.cpp b/projects/mtg/src/AIStats.cpp index 28e05dc93..970572a8e 100644 --- a/projects/mtg/src/AIStats.cpp +++ b/projects/mtg/src/AIStats.cpp @@ -196,7 +196,7 @@ void AIStats::Render() x0 = 280; JRenderer::GetInstance()->FillRoundRect(x0, 10, 200, 180, 5, ARGB(50,0,0,0)); - WFont * f = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * f = g->getResourceManager()->GetWFont(Fonts::MAIN_FONT); int i = 0; char buffer[512]; list::iterator it; diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 9e1995aac..ed61ee94d 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -48,7 +48,7 @@ const string NextGamePhase::getDisplayName() const void NextGamePhase::Render() { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); char buffer[200]; @@ -81,20 +81,20 @@ const string Interruptible::getDisplayName() const float Interruptible::GetVerticalTextOffset() const { - static const float kTextVerticalOffset = (mHeight - WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT)->GetHeight()) / 2; + static const float kTextVerticalOffset = (mHeight - observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT)->GetHeight()) / 2; return kTextVerticalOffset; } void Interruptible::Render(MTGCardInstance * source, JQuad * targetQuad, string alt1, string alt2, string action, bool bigQuad) { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetColor(ARGB(255,255,255,255)); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); mFont->DrawString(_(action).c_str(), x + 35, y + GetVerticalTextOffset(), JGETEXT_LEFT); JRenderer * renderer = JRenderer::GetInstance(); - JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(source, CACHE_THUMB); + JQuadPtr quad = observer->getResourceManager()->RetrieveCard(source, CACHE_THUMB); if (!quad.get()) quad = CardGui::AlternateThumbQuad(source); if (quad.get()) @@ -111,7 +111,7 @@ void Interruptible::Render(MTGCardInstance * source, JQuad * targetQuad, string if (bigQuad) { Pos pos = Pos(CardGui::BigWidth / 2, CardGui::BigHeight / 2 - 10, 1.0, 0.0, 220); - CardGui::DrawCard(source, pos, CardSelectorSingleton::Instance()->GetDrawMode()); + CardGui::DrawCard(source, pos, observer->getCardSelector()->GetDrawMode()); } if (targetQuad) @@ -409,7 +409,7 @@ int PutInGraveyard::resolve() void PutInGraveyard::Render() { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); if (!removeFromGame) @@ -421,7 +421,7 @@ void PutInGraveyard::Render() mFont->DrawString(_("is exiled").c_str(), x + 30, y, JGETEXT_LEFT); } JRenderer * renderer = JRenderer::GetInstance(); - JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(card, CACHE_THUMB); + JQuadPtr quad = observer->getResourceManager()->RetrieveCard(card, CACHE_THUMB); if (quad.get()) { quad->SetColor(ARGB(255,255,255,255)); @@ -457,7 +457,7 @@ int DrawAction::resolve() void DrawAction::Render() { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); char buffer[200]; @@ -487,7 +487,7 @@ target->life += amount; void LifeAction::Render() { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); char buffer[200]; @@ -574,7 +574,7 @@ int ActionStack::setIsInterrupting(Player * player, bool log) if (!gModRules.game.canInterrupt()) { - cancelInterruptOffer(); + cancelInterruptOffer(1, log); return 0; } @@ -632,7 +632,7 @@ Interruptible * ActionStack::getAt(int id) } ActionStack::ActionStack(GameObserver* game) - : GuiLayer(game) + : GuiLayer(game), currentTutorial(0) { for (int i = 0; i < 2; i++) interruptDecision[i] = 0; @@ -642,11 +642,12 @@ ActionStack::ActionStack(GameObserver* game) mode = ACTIONSTACK_STANDARD; checked = 0; + if(!observer->getResourceManager()) return; for (int i = 0; i < 8; ++i) { std::ostringstream stream; stream << "iconspsp" << i; - pspIcons[i] = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, stream.str(), RETRIEVE_MANAGE); + pspIcons[i] = observer->getResourceManager()->RetrieveQuad("iconspsp.png", (float) i * 32, 0, 32, 32, stream.str(), RETRIEVE_MANAGE); pspIcons[i]->SetHotSpot(16, 16); } } @@ -829,7 +830,7 @@ void ActionStack::Update(float dt) { //This is a hack to avoid updating the stack while tuto messages are being shown //Ideally, the tuto messages should be moved to a layer above this one - if (ATutorialMessage::Current) + if (getCurrentTutorial()) return; askIfWishesToInterrupt = NULL; @@ -955,14 +956,15 @@ void ActionStack::Update(float dt) } } -void ActionStack::cancelInterruptOffer(int cancelMode) +void ActionStack::cancelInterruptOffer(int cancelMode, bool log) { int playerId = (observer->isInterrupting == observer->players[1]) ? 1 : 0; interruptDecision[playerId] = cancelMode; askIfWishesToInterrupt = NULL; observer->isInterrupting = NULL; timer = -1; - observer->logAction(playerId, "no"); + if(log) + observer->logAction(playerId, "no"); } void ActionStack::endOfInterruption(bool log) @@ -1101,7 +1103,7 @@ void ActionStack::Render() { //This is a hack to avoid rendering the stack above the tuto messages //Ideally, the tuto messages should be moved to a layer above this one - if (ATutorialMessage::Current) + if (getCurrentTutorial()) return; static const float kSpacer = 8; @@ -1123,7 +1125,7 @@ void ActionStack::Render() height += current->mHeight; } - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetBase(0); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); mFont->SetColor(ARGB(255,255,255,255)); @@ -1201,7 +1203,7 @@ void ActionStack::Render() height += current->mHeight; } - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = observer->getResourceManager()->GetWFont(Fonts::MAIN_FONT); mFont->SetScale(DEFAULT_MAIN_FONT_SCALE); mFont->SetColor(ARGB(255,255,255,255)); diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 3da1a7287..5f67f7a90 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -2241,7 +2241,7 @@ int MayAbility::testDestroy() if(game->currentPlayer == source->controller() && game->isInterrupting == source->controller() && dynamic_cast(AbilityFactory::getCoreAbility(ability))) //if its my turn, and im interrupting myself(why?) then set interrupting to previous interrupter if the ability was a manaability //special case since they don't use the stack. - game->mLayers->stackLayer()->setIsInterrupting(previousInterrupter); + game->mLayers->stackLayer()->setIsInterrupting(previousInterrupter, false); return 1; } @@ -2305,7 +2305,7 @@ void MenuAbility::Update(float dt) { game->mLayers->actionLayer()->setCustomMenuObject(source, must,abilities); previousInterrupter = game->isInterrupting; - game->mLayers->stackLayer()->setIsInterrupting(source->controller()); + game->mLayers->stackLayer()->setIsInterrupting(source->controller(), false); } } @@ -2359,10 +2359,9 @@ int MenuAbility::reactToChoiceClick(Targetable * object,int choice,int control) mClone->resolve(); SAFE_DELETE(mClone); if (source->controller() == game->isInterrupting) - game->mLayers->stackLayer()->cancelInterruptOffer(); + game->mLayers->stackLayer()->cancelInterruptOffer(1, false); this->forceDestroy = 1; removeMenu = true; - game->logAction(source->controller(), "choice " + choice); return reactToTargetClick(object); } @@ -3913,8 +3912,6 @@ AAConnect * AAConnect::clone() const //Tutorial Messaging -ATutorialMessage * ATutorialMessage::Current = NULL; - ATutorialMessage::ATutorialMessage(GameObserver* observer, MTGCardInstance * source, string message, int limit) : MTGAbility(observer, 0, source), IconButtonsController(0, 0), mLimit(limit) { @@ -3926,7 +3923,7 @@ ATutorialMessage::ATutorialMessage(GameObserver* observer, MTGCardInstance * sou for (int i = 0; i < 9; i++) mBg[i] = NULL; - string gfx = WResourceManager::Instance()->graphicsFile(message); + string gfx = game->getResourceManager()->graphicsFile(message); if (fileExists(gfx.c_str())) { mIsImage = true; @@ -3987,10 +3984,10 @@ bool ATutorialMessage::CheckUserInput(JButton key) void ATutorialMessage::Update(float dt) { - if (!Current && !mDontShow) - Current = this; + if (!game->mLayers->stackLayer()->getCurrentTutorial() && !mDontShow) + game->mLayers->stackLayer()->setCurrentTutorial(this); - if (Current != this) + if (game->mLayers->stackLayer()->getCurrentTutorial() != this) return; if (mUserCloseRequest && mY < -SCREEN_HEIGHT) @@ -3998,7 +3995,7 @@ void ATutorialMessage::Update(float dt) if (mDontShow) { - Current = NULL; + game->mLayers->stackLayer()->setCurrentTutorial(0); forceDestroy = 1; return; } @@ -4048,14 +4045,14 @@ void ATutorialMessage::Render() { if (mIsImage) { - mBgTex = WResourceManager::Instance()->RetrieveTexture(mMessage, RETRIEVE_LOCK); + mBgTex = game->getResourceManager()->RetrieveTexture(mMessage, RETRIEVE_LOCK); if (mBgTex) { mBg[0] = NEW JQuad(mBgTex, 0, 0, (float) mBgTex->mWidth, (float) mBgTex->mHeight); mBg[0]->SetHotSpot(mBg[0]->mWidth / 2, mBg[0]->mHeight / 2); //Continue Button - JQuadPtr quad = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE); + JQuadPtr quad = game->getResourceManager()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE); quad->SetHotSpot(16, 16); IconButton * iconButton = NEW IconButton(1, this, quad.get(), 0, mBg[0]->mHeight / 2, 0.7f, Fonts::MAGIC_FONT, _("continue"), 0, 16, true); Add(iconButton); @@ -4063,14 +4060,14 @@ void ATutorialMessage::Render() if (options[Options::SFXVOLUME].number > 0) { - JSample * sample = WResourceManager::Instance()->RetrieveSample("tutorial.wav"); + JSample * sample = game->getResourceManager()->RetrieveSample("tutorial.wav"); if (sample) JSoundSystem::GetInstance()->PlaySample(sample); } } else { - mBgTex = WResourceManager::Instance()->RetrieveTexture("taskboard.png", RETRIEVE_LOCK); + mBgTex = game->getResourceManager()->RetrieveTexture("taskboard.png", RETRIEVE_LOCK); float unitH = static_cast (mBgTex->mHeight / 4); float unitW = static_cast (mBgTex->mWidth / 4); @@ -4090,7 +4087,7 @@ void ATutorialMessage::Render() } //Continue Button - JQuadPtr quad = WResourceManager::Instance()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE); + JQuadPtr quad = game->getResourceManager()->RetrieveQuad("iconspsp.png", 4 * 32, 0, 32, 32, "iconpsp4", RETRIEVE_MANAGE); quad->SetHotSpot(16, 16); IconButton * iconButton = NEW IconButton(1, this, quad.get(), SCREEN_WIDTH_F / 2, SCREEN_HEIGHT_F - 60, 0.7f, Fonts::MAGIC_FONT, _("continue"), 0, 16, true); Add(iconButton); @@ -4100,7 +4097,7 @@ void ATutorialMessage::Render() if (options[Options::SFXVOLUME].number > 0) { - JSample * sample = WResourceManager::Instance()->RetrieveSample("chain.wav"); + JSample * sample = game->getResourceManager()->RetrieveSample("chain.wav"); if (sample) JSoundSystem::GetInstance()->PlaySample(sample); } @@ -4126,7 +4123,7 @@ void ATutorialMessage::Render() else { //Setup fonts. - WFont * f2 = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT); + WFont * f2 = game->getResourceManager()->GetWFont(Fonts::MAGIC_FONT); f2->SetColor(ARGB(255, 205, 237, 240)); r->FillRect(0, mY, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(128,0,0,0)); @@ -4159,8 +4156,8 @@ void ATutorialMessage::Render() float posX = 40, posY = mY + 20; string title = _("Help"); - WFont * f = WResourceManager::Instance()->GetWFont(Fonts::MAGIC_FONT); - WFont * f3 = WResourceManager::Instance()->GetWFont(Fonts::MENU_FONT); //OPTION_FONT + WFont * f = game->getResourceManager()->GetWFont(Fonts::MAGIC_FONT); + WFont * f3 = game->getResourceManager()->GetWFont(Fonts::MENU_FONT); //OPTION_FONT f->SetColor(ARGB(255, 55, 46, 34)); f3->SetColor(ARGB(255, 219, 206, 151)); @@ -4187,7 +4184,7 @@ ATutorialMessage::~ATutorialMessage() { if (mBgTex) { - WResourceManager::Instance()->Release(mBgTex); + game->getResourceManager()->Release(mBgTex); for (int i = 0; i < 9; i++) SAFE_DELETE(mBg[i]); } diff --git a/projects/mtg/src/CardDisplay.cpp b/projects/mtg/src/CardDisplay.cpp index 4377961b7..d444597f9 100644 --- a/projects/mtg/src/CardDisplay.cpp +++ b/projects/mtg/src/CardDisplay.cpp @@ -265,7 +265,7 @@ void CardDisplay::Render() { pos.actY = 150; if (x < (CardGui::BigWidth / 2)) pos.actX = SCREEN_WIDTH - 10 - CardGui::BigWidth / 2; - drawMode = CardSelectorSingleton::Instance()->GetDrawMode(); + drawMode = observer->getCardSelector()->GetDrawMode(); } cardg->DrawCard(pos, drawMode); diff --git a/projects/mtg/src/CardGui.cpp b/projects/mtg/src/CardGui.cpp index 07a97ae52..1e030c4dc 100644 --- a/projects/mtg/src/CardGui.cpp +++ b/projects/mtg/src/CardGui.cpp @@ -130,7 +130,7 @@ void CardGui::DrawCard(MTGCard* inCard, const Pos& inPosition, int inMode) void CardGui::Render() { - WFont * mFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); + WFont * mFont = card->getObserver()->getResourceManager()->GetWFont(Fonts::MAIN_FONT); JRenderer * renderer = JRenderer::GetInstance(); GameObserver * game = card->getObserver(); @@ -140,7 +140,7 @@ void CardGui::Render() tc = game->getCurrentTargetChooser(); bool alternate = true; - JQuadPtr quad = WResourceManager::Instance()->RetrieveCard(card, CACHE_THUMB); + JQuadPtr quad = card->getObserver()->getResourceManager()->RetrieveCard(card, CACHE_THUMB); if (quad.get()) alternate = false; @@ -153,7 +153,7 @@ void CardGui::Render() JQuadPtr shadow; if (actZ > 1) { - shadow = WResourceManager::Instance()->GetQuad("shadow"); + shadow = card->getObserver()->getResourceManager()->GetQuad("shadow"); shadow->SetColor(ARGB(static_cast(actA)/2,255,255,255)); renderer->RenderQuad(shadow.get(), actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16); } @@ -161,7 +161,7 @@ void CardGui::Render() JQuadPtr extracostshadow; if (card->isExtraCostTarget) { - extracostshadow = WResourceManager::Instance()->GetQuad("extracostshadow"); + extracostshadow = card->getObserver()->getResourceManager()->GetQuad("extracostshadow"); extracostshadow->SetColor(ARGB(static_cast(actA)/2,100,0,0)); renderer->RenderQuad(extracostshadow.get(), actX + (actZ - 1) * 15, actY + (actZ - 1) * 15, actT, 28 * actZ / 16, 40 * actZ / 16); } @@ -185,7 +185,7 @@ void CardGui::Render() } if (isActiveConnectedParent) { - JQuadPtr white = WResourceManager::Instance()->GetQuad("white"); + JQuadPtr white = card->getObserver()->getResourceManager()->GetQuad("white"); if(white) { white->SetColor(ARGB(255,230,50,50)); @@ -212,7 +212,7 @@ void CardGui::Render() } if (isActiveConnectedChild) { - JQuadPtr white = WResourceManager::Instance()->GetQuad("white"); + JQuadPtr white = card->getObserver()->getResourceManager()->GetQuad("white"); if(white) { white->SetColor(ARGB(255,0,0,255)); @@ -235,15 +235,15 @@ void CardGui::Render() JQuadPtr icon; if (card->hasSubtype("plains")) - icon = WResourceManager::Instance()->GetQuad("c_white"); + icon = card->getObserver()->getResourceManager()->GetQuad("c_white"); else if (card->hasSubtype("swamp")) - icon = WResourceManager::Instance()->GetQuad("c_black"); + icon = card->getObserver()->getResourceManager()->GetQuad("c_black"); else if (card->hasSubtype("forest")) - icon = WResourceManager::Instance()->GetQuad("c_green"); + icon = card->getObserver()->getResourceManager()->GetQuad("c_green"); else if (card->hasSubtype("mountain")) - icon = WResourceManager::Instance()->GetQuad("c_red"); + icon = card->getObserver()->getResourceManager()->GetQuad("c_red"); else if (card->hasSubtype("island")) - icon = WResourceManager::Instance()->GetQuad("c_blue"); + icon = card->getObserver()->getResourceManager()->GetQuad("c_blue"); if (icon.get()) { @@ -256,7 +256,7 @@ void CardGui::Render() JQuadPtr mor; if(card->isMorphed && !alternate) { - mor = WResourceManager::Instance()->GetQuad("morph"); + mor = card->getObserver()->getResourceManager()->GetQuad("morph"); mor->SetColor(ARGB(255,255,255,255)); renderer->RenderQuad(mor.get(), actX, actY, actT,scale, scale); } @@ -299,7 +299,7 @@ void CardGui::Render() if (tc && !tc->canTarget(card)) { if (!shadow) - shadow = WResourceManager::Instance()->GetQuad("shadow"); + shadow = card->getObserver()->getResourceManager()->GetQuad("shadow"); shadow->SetColor(ARGB(200,255,255,255)); renderer->RenderQuad(shadow.get(), actX, actY, actT, (28 * actZ + 1) / 16, 40 * actZ / 16); } diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index a37eafaa5..450a99847 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -1,7 +1,7 @@ #include "PrecompiledHeader.h" #include "MTGRules.h" -#include "CardSelectorSingleton.h" +#include "CardSelector.h" #include "GuiCombat.h" #include "GuiBackground.h" #include "GuiFrame.h" @@ -15,7 +15,8 @@ void DuelLayers::init(GameObserver* go) { - mCardSelector = CardSelectorSingleton::Create(go, this); + observer = go; + mCardSelector = NEW CardSelector(go, this); //1 Action Layer action = NEW ActionLayer(go); action->Add(NEW MTGGamePhase(go, action->getMaxId())); @@ -65,7 +66,7 @@ void DuelLayers::CheckUserInput(int isAI) JGE::GetInstance()->LeftClickedProcessed(); break; } - if (CardSelectorSingleton::Instance()->CheckUserInput(key)) { + if (mCardSelector->CheckUserInput(key)) { JGE::GetInstance()->LeftClickedProcessed(); break; } @@ -126,10 +127,9 @@ DuelLayers::~DuelLayers() for (size_t i = 0; i < waiters.size(); ++i) delete (waiters[i]); - Trash::cleanup(); + observer->mTrash->cleanup(); - CardSelectorSingleton::Terminate(); - mCardSelector = NULL; + SAFE_DELETE(mCardSelector); } void DuelLayers::Add(GuiLayer * layer) @@ -203,7 +203,7 @@ int DuelLayers::receiveEvent(WEvent * e) if (WEventPhaseChange *event = dynamic_cast(e)) if (Constants::MTG_PHASE_BEFORE_BEGIN == event->to->id) - Trash::cleanup(); + observer->mTrash->cleanup(); return 1; } diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index ac2bbae0b..10c98362c 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -12,6 +12,7 @@ #include "GuiPhaseBar.h" #include "AIPlayerBaka.h" #include "MTGRules.h" +#include "Trash.h" #ifdef TESTSUITE #include "TestSuiteAI.h" #endif @@ -35,6 +36,7 @@ void GameObserver::initialize() connectRule = false; mLoading = false; mLayers = NULL; + mTrash = new Trash(); } void GameObserver::cleanup() @@ -63,7 +65,6 @@ void GameObserver::cleanup() combatStep = BLOCKERS; connectRule = false; actionsList.clear(); - } GameObserver::~GameObserver() @@ -82,31 +83,21 @@ GameObserver::~GameObserver() SAFE_DELETE(players[i]); } players.clear(); + delete[] ExtraRules; + ExtraRules = 0; LOG("==GameObserver Destroyed=="); + SAFE_DELETE(mTrash); } -GameObserver::GameObserver() - : randomGenerator(true) +GameObserver::GameObserver(WResourceManager *resourceManager) + : randomGenerator(true), mResourceManager(resourceManager) + { + ExtraRules = new MTGCardInstance[2](); + initialize(); } -GameObserver::GameObserver(vector _players) - : randomGenerator(true) -{ - initialize(); - setPlayers(_players); -} - -void GameObserver::setPlayers(vector _players) -{ - for (size_t i = 0; i < _players.size(); i++) - { - players.push_back(_players[i]); - players[i]->setObserver(this); - } -} - int GameObserver::getCurrentGamePhase() { return currentGamePhase; @@ -1009,7 +1000,10 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) } else { backup = card; zone = card->currentZone; - index = zone->getIndex(card); + if(zone) + { + index = zone->getIndex(card); + } } do { @@ -1136,7 +1130,7 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) if (clickedPlayer) { logAction(clickedPlayer); - } else { + } else if(zone) { logAction(backup, zone, index, toReturn); } @@ -1451,7 +1445,7 @@ bool GameObserver::processActions(bool undo) if (s.find("p1") != string::npos) p = players[0]; - for (int i = 0; i<5; i++) + for (int i = 0; i<1; i++) { // let's fake an update Update(counter); @@ -1500,7 +1494,7 @@ bool GameObserver::processActions(bool undo) size_t nb = actionsList.size(); - for (int i = 0; i<5; i++) + for (int i = 0; i<3; i++) { // let's fake an update Update(counter); @@ -1563,12 +1557,17 @@ void GameObserver::Mulligan(Player* player) } #ifdef TESTSUITE -void GameObserver::loadTestSuitePlayer(int playerId, TestSuite* testSuite) +void GameObserver::loadTestSuitePlayer(int playerId, TestSuiteGame* testSuite) { - players.push_back(new TestSuiteAI(this, testSuite, playerId)); + players.push_back(new TestSuiteAI(testSuite, playerId)); } #endif //TESTSUITE +void GameObserver::loadPlayer(int playerId, Player* player) +{ + players.push_back(player); +} + void GameObserver::loadPlayer(int playerId, PlayerType playerType, int decknb, bool premadeDeck) { if (decknb) diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index c093a61fd..eb3e853c5 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -119,7 +119,7 @@ void GameStateDuel::Start() renderer->EnableVSync(true); OpponentsDeckid = 0; - game = NEW GameObserver(); + game = NEW GameObserver(WResourceManager::Instance()); #ifdef TESTSUITE SAFE_DELETE(testSuite); @@ -200,12 +200,13 @@ void GameStateDuel::loadTestSuitePlayers() if (!testSuite) return; initRand(testSuite->seed); SAFE_DELETE(game); - game = new GameObserver(); + game = new GameObserver(WResourceManager::Instance()); + testSuite->setObserver(game); for (int i = 0; i < 2; i++) { game->loadTestSuitePlayer(i, testSuite); } - mParent->gameType = testSuite->gameType; + mParent->gameType = testSuite->getGameType(); game->startGame(mParent->gameType, mParent->rules); } @@ -294,6 +295,8 @@ void GameStateDuel::Update(float dt) #ifdef TESTSUITE else if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) { + testSuite->setRules(mParent->rules); + if (testSuite && testSuite->loadNext()) { loadTestSuitePlayers(); diff --git a/projects/mtg/src/GuiAvatars.cpp b/projects/mtg/src/GuiAvatars.cpp index 23bdac5f4..ebef50122 100644 --- a/projects/mtg/src/GuiAvatars.cpp +++ b/projects/mtg/src/GuiAvatars.cpp @@ -26,13 +26,13 @@ GuiAvatars::GuiAvatars(GameObserver* observer) : Add(opponentLibrary = NEW GuiLibrary(5 + GuiAvatar::Width * 1.4 - GuiGameZone::Width / 2, 5 + GuiGameZone::Height + 5, false, observer->players[1], this)); - CardSelectorSingleton::Instance()->Add(self); - CardSelectorSingleton::Instance()->Add(selfGraveyard); - CardSelectorSingleton::Instance()->Add(selfLibrary); - CardSelectorSingleton::Instance()->Add(opponent); - CardSelectorSingleton::Instance()->Add(opponentGraveyard); - CardSelectorSingleton::Instance()->Add(opponentLibrary); - CardSelectorSingleton::Instance()->Add(opponentHand); + observer->getCardSelector()->Add(self); + observer->getCardSelector()->Add(selfGraveyard); + observer->getCardSelector()->Add(selfLibrary); + observer->getCardSelector()->Add(opponent); + observer->getCardSelector()->Add(opponentGraveyard); + observer->getCardSelector()->Add(opponentLibrary); + observer->getCardSelector()->Add(opponentHand); selfGraveyard->alpha = selfLibrary->alpha = opponentGraveyard->alpha = opponentLibrary->alpha = opponentHand->alpha = 0; } diff --git a/projects/mtg/src/GuiCombat.cpp b/projects/mtg/src/GuiCombat.cpp index 8b0b17c5f..1550253b9 100644 --- a/projects/mtg/src/GuiCombat.cpp +++ b/projects/mtg/src/GuiCombat.cpp @@ -44,17 +44,17 @@ GuiCombat::GuiCombat(GameObserver* go) : GuiLayer(go), active(false), activeAtk(NULL), ok(SCREEN_WIDTH - MARGIN, 210, 1, 0, 255), enemy_avatar(SCREEN_WIDTH - MARGIN, TOP_LINE, 2, 0, 255), cursor_pos(NONE), step(DAMAGE) { - if (NULL == ok_tex) + if (NULL == ok_tex && go->getResourceManager()) { - ok_tex = WResourceManager::Instance()->RetrieveTexture("Ok.png", RETRIEVE_LOCK); + ok_tex = go->getResourceManager()->RetrieveTexture("Ok.png", RETRIEVE_LOCK); } } GuiCombat::~GuiCombat() { - if (ok_tex) + if (ok_tex && observer->getResourceManager()) { - WResourceManager::Instance()->Release(ok_tex); + observer->getResourceManager()->Release(ok_tex); ok_tex = NULL; } @@ -199,7 +199,7 @@ bool GuiCombat::CheckUserInput(JButton key) if (NONE == cursor_pos) return false; DamagerDamaged* oldActive = active; -/* This is untested +/* int x,y; if(JGE::GetInstance()->GetLeftClickCoordinates(x, y)) { @@ -537,7 +537,7 @@ int GuiCombat::receiveEventMinus(WEvent* e) if (activeAtk == *it) activeAtk = NULL; attackers.erase(it); - trash(d); + observer->mTrash->trash(d); return 1; } else @@ -546,7 +546,7 @@ int GuiCombat::receiveEventMinus(WEvent* e) { DefenserDamaged* d = *q; (*it)->blockers.erase(q); - trash(d); + observer->mTrash->trash(d); return 1; } return 0; @@ -560,7 +560,7 @@ int GuiCombat::receiveEventMinus(WEvent* e) { AttackerDamaged* d = *it; attackers.erase(it); - trash(d); + observer->mTrash->trash(d); return 1; } return 0; @@ -574,7 +574,7 @@ int GuiCombat::receiveEventMinus(WEvent* e) { DefenserDamaged* d = *q; (*it)->blockers.erase(q); - trash(d); + observer->mTrash->trash(d); return 1; } return 0; diff --git a/projects/mtg/src/GuiFrame.cpp b/projects/mtg/src/GuiFrame.cpp index a61eecfa6..e4f764fe9 100644 --- a/projects/mtg/src/GuiFrame.cpp +++ b/projects/mtg/src/GuiFrame.cpp @@ -6,26 +6,28 @@ GuiFrame::GuiFrame(GameObserver* observer) : GuiLayer(observer) { - if (WResourceManager::Instance()->GetTexture("wood.png")) - wood = WResourceManager::Instance()->RetrieveQuad("wood.png", 0, 0, SCREEN_WIDTH, 28); - else + if (observer->getResourceManager()) { - GameApp::systemError += "Can't load wood texture : " __FILE__ "\n"; - } - - if (WResourceManager::Instance()->GetTexture("gold.png")) - { - gold1 = WResourceManager::Instance()->RetrieveQuad("gold.png", 0, 0, SCREEN_WIDTH, 6, "gold1"); - gold2 = WResourceManager::Instance()->RetrieveQuad("gold.png", 0, 6, SCREEN_WIDTH, 6, "gold2"); - if (WResourceManager::Instance()->GetTexture("goldglow.png")) - goldGlow = WResourceManager::Instance()->RetrieveQuad("goldglow.png", 1, 1, SCREEN_WIDTH - 2, 18); - if (gold2) + if (observer->getResourceManager()->GetTexture("wood.png")) + wood = observer->getResourceManager()->RetrieveQuad("wood.png", 0, 0, SCREEN_WIDTH, 28); + else { - gold2->SetColor(ARGB(127, 255, 255, 255)); - gold2->SetHFlip(true); + GameApp::systemError += "Can't load wood texture : " __FILE__ "\n"; + } + + if (observer->getResourceManager()->GetTexture("gold.png")) + { + gold1 = observer->getResourceManager()->RetrieveQuad("gold.png", 0, 0, SCREEN_WIDTH, 6, "gold1"); + gold2 = observer->getResourceManager()->RetrieveQuad("gold.png", 0, 6, SCREEN_WIDTH, 6, "gold2"); + if (observer->getResourceManager()->GetTexture("goldglow.png")) + goldGlow = observer->getResourceManager()->RetrieveQuad("goldglow.png", 1, 1, SCREEN_WIDTH - 2, 18); + if (gold2) + { + gold2->SetColor(ARGB(127, 255, 255, 255)); + gold2->SetHFlip(true); + } } } - step = 0.0; } diff --git a/projects/mtg/src/GuiHand.cpp b/projects/mtg/src/GuiHand.cpp index 5129cb43a..037660503 100644 --- a/projects/mtg/src/GuiHand.cpp +++ b/projects/mtg/src/GuiHand.cpp @@ -35,11 +35,14 @@ HandLimitor::HandLimitor(GuiHand* hand) : GuiHand::GuiHand(GameObserver* observer, MTGHand* hand) : GuiLayer(observer), hand(hand) { - back = WResourceManager::Instance()->RetrieveTempQuad("handback.png"); - if (back.get()) - back->SetTextureRect(1, 0, 100, 250); - else - GameApp::systemError = "Error loading hand texture : " __FILE__; + if(observer->getResourceManager()) + { + back = observer->getResourceManager()->RetrieveTempQuad("handback.png"); + if (back.get()) + back->SetTextureRect(1, 0, 100, 250); + else + GameApp::systemError = "Error loading hand texture : " __FILE__; + } } GuiHand::~GuiHand() @@ -175,10 +178,10 @@ bool GuiHandSelf::CheckUserInput(JButton key) { state = (Open == state ? Closed : Open); if (Open == state) - CardSelectorSingleton::Instance()->Push(); - CardSelectorSingleton::Instance()->Limit(Open == state ? limitor : NULL, CardView::handZone); + observer->getCardSelector()->Push(); + observer->getCardSelector()->Limit(Open == state ? limitor : NULL, CardView::handZone); if (Closed == state) - CardSelectorSingleton::Instance()->Pop(); + observer->getCardSelector()->Pop(); if (OptionHandDirection::HORIZONTAL == options[Options::HANDDIRECTION].number) backpos.y = Open == state ? OpenY : ClosedY; else @@ -264,7 +267,7 @@ int GuiHandSelf::receiveEventPlus(WEvent* e) card = NEW CardView(CardView::handZone, ev->card, ClosedRowX, 0); card->t = 6 * M_PI; cards.push_back(card); - CardSelectorSingleton::Instance()->Add(card); + observer->getCardSelector()->Add(card); Repos(); return 1; } @@ -279,10 +282,10 @@ int GuiHandSelf::receiveEventMinus(WEvent* e) if (event->card->previous == (*it)->card) { CardView* cv = *it; - CardSelectorSingleton::Instance()->Remove(cv); + observer->getCardSelector()->Remove(cv); cards.erase(it); Repos(); - trash(cv); + observer->mTrash->trash(cv); return 1; } return 1; @@ -317,7 +320,7 @@ int GuiHandOpponent::receiveEventMinus(WEvent* e) { CardView* cv = *it; cards.erase(it); - trash(cv); + observer->mTrash->trash(cv); return 1; } return 0; diff --git a/projects/mtg/src/GuiPhaseBar.cpp b/projects/mtg/src/GuiPhaseBar.cpp index c9afda40c..3ded79fcc 100644 --- a/projects/mtg/src/GuiPhaseBar.cpp +++ b/projects/mtg/src/GuiPhaseBar.cpp @@ -55,7 +55,7 @@ GuiPhaseBar::GuiPhaseBar(GameObserver* observer) : GameApp::systemError = "Error loading phasebar texture : " __FILE__; zoom = ICONSCALE; - CardSelectorSingleton::Instance()->Add(this); + observer->getCardSelector()->Add(this); } diff --git a/projects/mtg/src/GuiPlay.cpp b/projects/mtg/src/GuiPlay.cpp index 38286dca1..c4dd5f168 100644 --- a/projects/mtg/src/GuiPlay.cpp +++ b/projects/mtg/src/GuiPlay.cpp @@ -356,7 +356,7 @@ int GuiPlay::receiveEventPlus(WEvent * e) // Make sure that the card is repositioned before adding it to the CardSelector, as // the card's position is a cue for certain CardSelector variants as to what zone the card is placed in Replace(); - CardSelectorSingleton::Instance()->Add(card); + observer->getCardSelector()->Add(card); return 1; } } @@ -420,9 +420,9 @@ int GuiPlay::receiveEventMinus(WEvent * e) else if (event->card->attacker) battleField.removeAttacker(event->card); CardView* cv = *it; - CardSelectorSingleton::Instance()->Remove(cv); + observer->getCardSelector()->Remove(cv); cards.erase(it); - trash(cv); + observer->mTrash->trash(cv); Replace(); return 1; } diff --git a/projects/mtg/src/GuiStatic.cpp b/projects/mtg/src/GuiStatic.cpp index f448abc83..6ac04ef60 100644 --- a/projects/mtg/src/GuiStatic.cpp +++ b/projects/mtg/src/GuiStatic.cpp @@ -213,7 +213,7 @@ void GuiGameZone::Update(float dt) if (fabs(c->actX - c->x) < 0.01 && fabs(c->actY - c->y) < 0.01) { cards.erase(it); - trash(c); + zone->owner->getObserver()->mTrash->trash(c); return; } } @@ -275,7 +275,7 @@ int GuiGraveyard::receiveEventMinus(WEvent* e) { CardView* cv = *it; cards.erase(it); - trash(cv); + zone->owner->getObserver()->mTrash->trash(cv); return 1; } return 0; @@ -322,7 +322,7 @@ int GuiOpponentHand::receiveEventMinus(WEvent* e) { CardView* cv = *it; cards.erase(it); - trash(cv); + zone->owner->getObserver()->mTrash->trash(cv); return 1; } return 0; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 875df8237..0d8087d69 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -19,8 +19,6 @@ SUPPORT_OBJECT_ANALYTICS(MTGCardInstance) MTGCardInstance MTGCardInstance::AnyCard = MTGCardInstance(); MTGCardInstance MTGCardInstance::NoCard = MTGCardInstance(); -MTGCardInstance MTGCardInstance::ExtraRules[] = { MTGCardInstance(), MTGCardInstance() }; - MTGCardInstance::MTGCardInstance() : CardPrimitive(), MTGCard(), Damageable(0, 0), view(NULL) { diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index b7d99c156..7192adef1 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -247,15 +247,16 @@ void MTGPlayerCards::drawFromLibrary() // so prefetch it. // if we're not in text mode, always get the thumb - if (CardSelectorSingleton::Instance()->GetDrawMode() != DrawMode::kText) + if (library->owner->getObserver()->getCardSelector()->GetDrawMode() != DrawMode::kText + && library->owner->getObserver()->getResourceManager()) { DebugTrace("Prefetching AI card going into play: " << toMove->getImageName()); - WResourceManager::Instance()->RetrieveCard(toMove, RETRIEVE_THUMB); + library->owner->getObserver()->getResourceManager()->RetrieveCard(toMove, RETRIEVE_THUMB); // also cache the large image if we're using kNormal mode - if (CardSelectorSingleton::Instance()->GetDrawMode() == DrawMode::kNormal) + if (library->owner->getObserver()->getCardSelector()->GetDrawMode() == DrawMode::kNormal) { - WResourceManager::Instance()->RetrieveCard(toMove); + library->owner->getObserver()->getResourceManager()->RetrieveCard(toMove); } } @@ -339,9 +340,9 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone { if (to == g->players[0]->game->graveyard || to == g->players[1]->game->graveyard) { - if (card->isCreature()) + if (card->isCreature() && g->getResourceManager()) { - JSample * sample = WResourceManager::Instance()->RetrieveSample("graveyard.wav"); + JSample * sample = g->getResourceManager()->RetrieveSample("graveyard.wav"); if (sample) JSoundSystem::GetInstance()->PlaySample(sample); } diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 7ef3ae98b..63514424e 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -1197,11 +1197,11 @@ int MTGAttackRule::reactToClick(MTGCardInstance * card) //Graphically select the next card that can attack if (!card->isAttacker()) { - CardSelectorSingleton::Instance()->PushLimitor(); - CardSelectorSingleton::Instance()->Limit(this, CardView::playZone); - CardSelectorSingleton::Instance()->CheckUserInput(JGE_BTN_RIGHT); - CardSelectorSingleton::Instance()->Limit(NULL, CardView::playZone); - CardSelectorSingleton::Instance()->PopLimitor(); + game->getCardSelector()->PushLimitor(); + game->getCardSelector()->Limit(this, CardView::playZone); + game->getCardSelector()->CheckUserInput(JGE_BTN_RIGHT); + game->getCardSelector()->Limit(NULL, CardView::playZone); + game->getCardSelector()->PopLimitor(); } card->toggleAttacker(); return 1; @@ -1416,11 +1416,8 @@ MTGBlockRule * MTGBlockRule::clone() const // * Momir // -int MTGMomirRule::initialized = 0; -vector MTGMomirRule::pool[20]; - MTGMomirRule::MTGMomirRule(GameObserver* observer, int _id, MTGAllCards * _collection) : -PermanentAbility(observer, _id) + PermanentAbility(observer, _id), initialized(false) { collection = _collection; if (!initialized) @@ -1565,11 +1562,8 @@ MTGMomirRule * MTGMomirRule::clone() const //less than or equal to the creature. //note this can kill your creature if the equipment contains negitive toughness -int MTGStoneHewerRule::initialized = 0; -vector MTGStoneHewerRule::pool[20]; - MTGStoneHewerRule::MTGStoneHewerRule(GameObserver* observer, int _id, MTGAllCards * _collection) : -PermanentAbility(observer, _id) + PermanentAbility(observer, _id), initialized(false) { collection = _collection; if (!initialized) diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index c611a1187..53edd2ada 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -60,21 +60,25 @@ Player::~Player() { SAFE_DELETE(manaPool); SAFE_DELETE(game); - WResourceManager::Instance()->Release(mAvatarTex); + if(mAvatarTex && observer->getResourceManager()) + observer->getResourceManager()->Release(mAvatarTex); mAvatarTex = NULL; SAFE_DELETE(mDeck); } bool Player::loadAvatar(string file, string resName) { + WResourceManager * rm = observer->getResourceManager(); + if(!rm) return false; + if (mAvatarTex) { - WResourceManager::Instance()->Release(mAvatarTex); + rm->Release(mAvatarTex); mAvatarTex = NULL; } - mAvatarTex = WResourceManager::Instance()->RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR); + mAvatarTex = rm->RetrieveTexture(file, RETRIEVE_LOCK, TEXTURE_SUB_AVATAR); if (mAvatarTex) { - mAvatar = WResourceManager::Instance()->RetrieveQuad(file, 0, 0, 35, 50, resName, RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR); + mAvatar = rm->RetrieveQuad(file, 0, 0, 35, 50, resName, RETRIEVE_NORMAL, TEXTURE_SUB_AVATAR); return true; } diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index 5d50ef047..0f458a77c 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -144,8 +144,8 @@ void Rules::addExtraRules(GameObserver* g) { Player * p = g->players[i]; //Trick so that the abilities don't die; - MTGCardInstance::ExtraRules[i].currentZone = p->game->inPlay; - MTGCardInstance::ExtraRules[i].lastController = p; + g->ExtraRules[i].currentZone = p->game->inPlay; + g->ExtraRules[i].lastController = p; for (size_t j = 0; j < initState.playerData[i].extraRules.size(); ++j) { AbilityFactory af(g); @@ -153,7 +153,7 @@ void Rules::addExtraRules(GameObserver* g) int handsize = 7; int difficultyRating = 0; int Optimizedhandcheat = options[Options::OPTIMIZE_HAND].number; - MTGAbility * a = af.parseMagicLine(initState.playerData[i].extraRules[j], id++, NULL, &MTGCardInstance::ExtraRules[i]); + MTGAbility * a = af.parseMagicLine(initState.playerData[i].extraRules[j], id++, NULL, &(g->ExtraRules[i])); if (p->playMode != Player::MODE_TEST_SUITE && g->mRules->gamemode != GAME_TYPE_MOMIR && g->mRules->gamemode != GAME_TYPE_RANDOM1 && g->mRules->gamemode != GAME_TYPE_RANDOM2 && g->mRules->gamemode != GAME_TYPE_STORY && @@ -214,7 +214,7 @@ void Rules::addExtraRules(GameObserver* g) for (size_t j = 0; j < extraRules.size(); ++j) { AbilityFactory af(g); - MTGAbility * a = af.parseMagicLine(extraRules[j], id++, NULL, &MTGCardInstance::ExtraRules[0]); + MTGAbility * a = af.parseMagicLine(extraRules[j], id++, NULL, &(g->ExtraRules[0])); if (a) { if (a->oneShot) diff --git a/projects/mtg/src/SimpleMenu.cpp b/projects/mtg/src/SimpleMenu.cpp index 536de4da0..3d9cddb77 100644 --- a/projects/mtg/src/SimpleMenu.cpp +++ b/projects/mtg/src/SimpleMenu.cpp @@ -27,8 +27,6 @@ JTexture* SimpleMenu::spadeRTex = NULL; JTexture* SimpleMenu::spadeLTex = NULL; JTexture* SimpleMenu::jewelTex = NULL; JTexture* SimpleMenu::sideTex = NULL; -WFont* SimpleMenu::titleFont = NULL; -hgeParticleSystem* SimpleMenu::stars = NULL; SimpleMenu::SimpleMenu(int id, JGuiListener* listener, int fontId, float x, float y, const char * _title, int _maxItems, bool centerHorizontal, bool centerVertical) : JGuiController(id, listener), fontId(fontId), mCenterHorizontal(centerHorizontal), mCenterVertical(centerVertical) @@ -58,14 +56,14 @@ SimpleMenu::SimpleMenu(int id, JGuiListener* listener, int fontId, float x, floa jewel.reset(NEW JQuad(jewelTex, 1, 1, 3, 3)); side = WResourceManager::Instance()->RetrieveQuad("menuside.png", 1, 1, 1, kPoleWidth, "menuside", RETRIEVE_MANAGE); - if (NULL == stars) - stars = NEW hgeParticleSystem(WResourceManager::Instance()->RetrievePSI("stars.psi", WResourceManager::Instance()->GetQuad("stars").get())); + stars = NEW hgeParticleSystem(WResourceManager::Instance()->RetrievePSI("stars.psi", WResourceManager::Instance()->GetQuad("stars").get())); stars->FireAt(mX, mY); } SimpleMenu::~SimpleMenu() { + SAFE_DELETE(stars); } void SimpleMenu::drawHorzPole(float x, float y, float width) @@ -247,6 +245,5 @@ void SimpleMenu::Close() void SimpleMenu::destroy() { SimpleMenu::jewel.reset(); - SAFE_DELETE(SimpleMenu::stars); SAFE_DELETE(SimpleMenu::jewelTex); } diff --git a/projects/mtg/src/StoryFlow.cpp b/projects/mtg/src/StoryFlow.cpp index b96ee9ef4..3194a7c74 100644 --- a/projects/mtg/src/StoryFlow.cpp +++ b/projects/mtg/src/StoryFlow.cpp @@ -303,27 +303,24 @@ StoryChoice::StoryChoice(string pageId, string text, int JGOid, float mX, float //Actually loads a duel void StoryDuel::init() { - vector players; + game = new GameObserver(); char folder[255], deckFile[255], deckFileSmall[255]; sprintf(folder, CAMPAIGNS_FOLDER"%s/%s", mParent->folder.c_str(), pageId.c_str()); sprintf(deckFile, "%s/deck.txt", folder); sprintf(deckFileSmall, "campaign_%s", mParent->folder.c_str()); - players.push_back(NEW HumanPlayer(0, deckFile, deckFileSmall, true)); - + game->loadPlayer(0, NEW HumanPlayer(game, deckFile, deckFileSmall, true)); sprintf(deckFile, "%s/opponent_deck.txt", folder); sprintf(deckFileSmall, "campaign_ennemy_%s_%s", mParent->folder.c_str(), pageId.c_str()); - players.push_back(NEW AIPlayerBaka(0, deckFile, deckFileSmall, "baka.jpg")); + game->loadPlayer(1, NEW AIPlayerBaka(game, deckFile, deckFileSmall, "baka.jpg")); string rulesFile = folder; rulesFile.append("/rules.txt"); rules = NEW Rules(bg); rules->load(rulesFile); - game = new GameObserver(players); - rules->gamemode = GAME_TYPE_STORY; game->startGame(GAME_TYPE_STORY, rules); } diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index c60b7abb4..bf3a059c3 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -15,14 +15,14 @@ using std::string; // NULL is sent in place of a MTGDeck since there is no way to create a MTGDeck without a proper deck file. // TestSuiteAI will be responsible for managing its own deck state. -TestSuiteAI::TestSuiteAI(GameObserver *observer, TestSuite * _suite, int playerId) : - AIPlayerBaka(observer, "testsuite", "testsuite", "baka.jpg", NULL) +TestSuiteAI::TestSuiteAI(TestSuiteGame *tsGame, int playerId) : + AIPlayerBaka(tsGame->observer, "testsuite", "testsuite", "baka.jpg", NULL) { SAFE_DELETE(game); //game might have been set in the parent with default values - game = _suite->buildDeck(this, playerId); + game = tsGame->buildDeck(this, playerId); game->setOwner(this); - suite = _suite; + suite = tsGame; timer = 0; playMode = MODE_TEST_SUITE; this->deckName = "Test Suite AI"; @@ -55,7 +55,7 @@ MTGCardInstance * TestSuiteAI::getCard(string action) return NULL; } -Interruptible * TestSuite::getActionByMTGId(GameObserver* observer, int mtgid) +Interruptible * TestSuiteGame::getActionByMTGId(int mtgid) { ActionStack * as = observer->mLayers->stackLayer(); Interruptible * action = NULL; @@ -121,7 +121,7 @@ int TestSuiteAI::Act(float dt) if (action == "") { //end of game - suite->assertGame(observer); + suite->assertGame(); observer->gameOver = observer->players[0]; DebugTrace("================================ END OF TEST =======================\n"); return 1; @@ -221,7 +221,7 @@ int TestSuiteAI::Act(float dt) if (mtgid) { DebugTrace("TESTSUITE CARD ID:" << mtgid); - toInterrupt = suite->getActionByMTGId(observer, mtgid); + toInterrupt = suite->getActionByMTGId(mtgid); } if (toInterrupt) @@ -277,7 +277,7 @@ void TestSuiteState::parsePlayerState(int playerId, string s) } -string TestSuite::getNextAction() +string TestSuiteGame::getNextAction() { currentAction++; if (actions.nbitems && currentAction <= actions.nbitems) @@ -287,40 +287,15 @@ string TestSuite::getNextAction() return ""; } -MTGPlayerCards * TestSuite::buildDeck(Player* player, int playerId) +void TestSuiteGame::handleResults(bool wasAI, int error) { - int list[100]; - int nbcards = 0; - MTGPlayerCards * deck = NULL; + testsuite->handleResults(wasAI, error); +}; - if(initState.players.size() > (size_t)playerId) - { - MTGGameZone * loadedPlayerZones[] = { initState.players[playerId]->game->graveyard, - initState.players[playerId]->game->library, - initState.players[playerId]->game->hand, - initState.players[playerId]->game->inPlay }; - - for (int j = 0; j < 4; j++) - { - for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++) - { - int cardid = loadedPlayerZones[j]->cards[k]->getId(); - list[nbcards] = cardid; - nbcards++; - } - } - deck = NEW MTGPlayerCards(player, list, nbcards); - } - else - { - deck = NEW MTGPlayerCards(); - } - - return deck; -} void TestSuite::initGame(GameObserver* g) { + observer = g; //The first test runs slowly, the other ones run faster. //This way a human can see what happens when testing a specific file, // or go faster when it comes to the whole test suite. @@ -334,64 +309,10 @@ void TestSuite::initGame(GameObserver* g) timerLimit = 3; } - DebugTrace("TESTSUITE Init Game"); - g->phaseRing->goToPhase(initState.phase, g->players[0]); - g->currentGamePhase = initState.phase; - for (int i = 0; i < 2; i++) - { - AIPlayerBaka * p = (AIPlayerBaka *) (g->players[i]); - p->forceBestAbilityUse = forceAbility; - p->life = initState.players[i]->life; - p->poisonCount = initState.players[i]->poisonCount; - stringstream stream; - stream << initState.players[i]->getRandomGenerator()->saveLoadedRandValues(stream); - p->getRandomGenerator()->loadRandValues(stream.str()); - MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; - MTGGameZone * loadedPlayerZones[] = { initState.players[i]->game->graveyard, - initState.players[i]->game->library, - initState.players[i]->game->hand, - initState.players[i]->game->inPlay }; - for (int j = 0; j < 4; j++) - { - MTGGameZone * zone = playerZones[j]; - for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++) - { - MTGCardInstance * card = Rules::getCardByMTGId(g, loadedPlayerZones[j]->cards[k]->getId()); - if (card && zone != p->game->library) - { - if (zone == p->game->inPlay) - { - MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); - Spell * spell = NEW Spell(g, copy); - spell->resolve(); - if (!summoningSickness && (size_t)p->game->inPlay->nb_cards > k) p->game->inPlay->cards[k]->summoningSickness = 0; - delete spell; - } - else - { - if (!p->game->library->hasCard(card)) - { - LOG ("TESTUITE ERROR, CARD NOT FOUND IN LIBRARY\n"); - } - p->game->putInZone(card, p->game->library, zone); - } - } - else - { - if (!card) - { - LOG ("TESTUITE ERROR, card is NULL\n"); - } - } - } - zone->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn - } - p->game->stack->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn - - } - DebugTrace("TESTUITE Init Game Done !"); + TestSuiteGame::initGame(); } -int TestSuite::Log(const char * text) + +int TestSuiteGame::Log(const char * text) { ofstream file; if (JFileSystem::GetInstance()->openForWrite(file, "test/results.html", ios_base::app)) @@ -405,27 +326,29 @@ int TestSuite::Log(const char * text) return 1; } -int TestSuite::assertGame(GameObserver* g) + +void TestSuiteGame::assertGame() { + mMutex.lock(); //compare the game state with the results char result[4096]; - sprintf(result, "

%s

", files[currentfile - 1].c_str()); + sprintf(result, "

%s

", filename.c_str()); Log(result); int error = 0; bool wasAI = false; - if (g->currentGamePhase != endState.phase) + if (observer->currentGamePhase != endState.phase) { sprintf(result, "==phase problem. Expected [ %s ](%i), got [ %s ](%i)==
", Constants::MTGPhaseNames[endState.phase],endState.phase, - Constants::MTGPhaseNames[g->currentGamePhase], g->currentGamePhase); + Constants::MTGPhaseNames[observer->currentGamePhase], observer->currentGamePhase); Log(result); error++; } for (int i = 0; i < 2; i++) { - TestSuiteAI * p = (TestSuiteAI *) (g->players[i]); + TestSuiteAI * p = (TestSuiteAI *) (observer->players[i]); if (p->playMode == Player::MODE_AI) wasAI = true; if (p->life != endState.players[i]->life) @@ -484,7 +407,7 @@ int TestSuite::assertGame(GameObserver* g) MTGCardInstance* cardToCheck = (kcards.size())?endstateZones[j]->cards[k]:0; if(cardToCheck) { // Can be NULL if used "*" in the testcase. - MTGCardInstance* card = Rules::getCardByMTGId(g, cardToCheck->getId()); + MTGCardInstance* card = Rules::getCardByMTGId(observer, cardToCheck->getId()); if (card != 0 && !zone->hasCard(card)) { sprintf(result, "==Card ID not the same. Didn't find %i
", card->getId()); @@ -495,13 +418,23 @@ int TestSuite::assertGame(GameObserver* g) } } } + handleResults(wasAI, error); + + if(!error) + Log("==Test Succesful !=="); + else + Log("==Test Failed !=="); + mMutex.unlock(); +} + +void TestSuite::handleResults(bool wasAI, int error) +{ if (wasAI) { nbAITests++; if (error) { nbAIFailed++; - return 0; } } else @@ -510,14 +443,13 @@ int TestSuite::assertGame(GameObserver* g) if (error) { nbFailed++; - return 0; } } - Log("==Test Succesful !=="); - return 1; } + TestSuite::TestSuite(const char * filename) + : TestSuiteGame(this), mRules(0), mProcessing(false) { timerLimit = 0; @@ -572,26 +504,46 @@ TestSuite::TestSuite(const char * filename) file2.close(); } + SAFE_DELETE(observer); } int TestSuite::loadNext() { + endTime = JGEGetTime(); summoningSickness = 0; seed = 0; aiMaxCalls = -1; if (!nbfiles) return 0; - if (currentfile >= nbfiles) return 0; - currentfile++; - string currFilename = files[currentfile - 1]; - if (currFilename == "+pregametests") + filename = getNextFile(); + if (filename == "") { + // we let GameStateDuel delete the latest gameObserver. + mProcessing = false; + observer = 0; + return 0; + } + + if (filename == "+pregametests") { pregameTests(); return loadNext(); } - if (!load(currFilename.c_str())) + if(!mProcessing) + { // "I don't like to wait" mode + mProcessing = true; + mWorkerThread.clear(); + size_t thread_count = 1; +#ifdef QT_CONFIG + thread_count = QThread::idealThreadCount(); +#endif + for(size_t i = 0; i < (thread_count-1); i++) + mWorkerThread.push_back(boost::thread(ThreadProc, this)); + } + + cleanup(); + if (!load()) return loadNext(); else cout << "Starting test : " << files[currentfile - 1] << endl; @@ -603,8 +555,7 @@ void TestSuiteActions::cleanup() nbitems = 0; } - -void TestSuiteState::cleanup(TestSuite* suite) +void TestSuiteState::cleanup(TestSuiteGame* tsGame) { for (size_t i = 0; i < players.size(); i++) { @@ -612,36 +563,34 @@ void TestSuiteState::cleanup(TestSuite* suite) } players.clear(); - players.push_back(new TestSuiteAI(0, suite, 0)); - players.push_back(new TestSuiteAI(0, suite, 1)); + players.push_back(new TestSuiteAI(tsGame, 0)); + players.push_back(new TestSuiteAI(tsGame, 1)); } void TestSuite::cleanup() { currentAction = 0; + observer = 0; initState.cleanup(this); endState.cleanup(this); actions.cleanup(); } -int TestSuite::load(const char * _filename) + +bool TestSuiteGame::load() { summoningSickness = 0; forceAbility = false; gameType = GAME_TYPE_CLASSIC; - char filename[4096]; - sprintf(filename, "test/%s", _filename); - + std::string s; int state = -1; std::string contents; - if (JFileSystem::GetInstance()->readIntoString(filename, contents)) + if (JFileSystem::GetInstance()->readIntoString("test/"+filename, contents)) { std::stringstream stream(contents); - - cleanup(); while (std::getline(stream, s)) { if (!s.size()) continue; @@ -754,9 +703,9 @@ int TestSuite::load(const char * _filename) } else { - return 0; + return false; } - return 1; + return true; } void TestSuite::pregameTests() @@ -773,4 +722,155 @@ void TestSuite::pregameTests() if (!sb.unitTest()) nbFailed++; } } + +void TestSuite::ThreadProc(void* inParam) +{ + LOG("Entering TestSuite::ThreadProc"); + TestSuite* instance = reinterpret_cast(inParam); + if (instance) + { + string filename; + float counter = 1.0f; +// while(instance->mProcessing) + { + while((filename = instance->getNextFile()) != "") + { + TestSuiteGame theGame(instance, filename); + if(theGame.isOK) + { + theGame.observer->loadTestSuitePlayer(0, &theGame); + theGame.observer->loadTestSuitePlayer(1, &theGame); + + theGame.observer->startGame(theGame.gameType, instance->mRules); + theGame.initGame(); + + while(!theGame.observer->gameOver) + theGame.observer->Update(counter++); + } + } + + boost::this_thread::sleep(100); + } + } + LOG("Leaving TestSuite::ThreadProc"); +} + +boost::mutex TestSuiteGame::mMutex; + +TestSuiteGame::~TestSuiteGame() +{ + SAFE_DELETE(observer); +} + +TestSuiteGame::TestSuiteGame(TestSuite* testsuite) + : summoningSickness(0), forceAbility(false), gameType(GAME_TYPE_CLASSIC), timerLimit(0), + currentAction(0), observer(0), testsuite(testsuite) +{ +} + +TestSuiteGame::TestSuiteGame(TestSuite* testsuite, string _filename) + : summoningSickness(0), forceAbility(false), gameType(GAME_TYPE_CLASSIC), timerLimit(3), + currentAction(0), observer(0), testsuite(testsuite) +{ + filename = _filename; + observer = new GameObserver(); + + initState.cleanup(this); + endState.cleanup(this); + + isOK = load(); +} + +void TestSuiteGame::initGame() +{ + DebugTrace("TESTSUITE Init Game"); + observer->phaseRing->goToPhase(initState.phase, observer->players[0]); + observer->currentGamePhase = initState.phase; + for (int i = 0; i < 2; i++) + { + AIPlayerBaka * p = (AIPlayerBaka *) (observer->players[i]); + p->forceBestAbilityUse = forceAbility; + p->life = initState.players[i]->life; + p->poisonCount = initState.players[i]->poisonCount; + stringstream stream; + stream << initState.players[i]->getRandomGenerator()->saveLoadedRandValues(stream); + p->getRandomGenerator()->loadRandValues(stream.str()); + MTGGameZone * playerZones[] = { p->game->graveyard, p->game->library, p->game->hand, p->game->inPlay }; + MTGGameZone * loadedPlayerZones[] = { initState.players[i]->game->graveyard, + initState.players[i]->game->library, + initState.players[i]->game->hand, + initState.players[i]->game->inPlay }; + for (int j = 0; j < 4; j++) + { + MTGGameZone * zone = playerZones[j]; + for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++) + { + MTGCardInstance * card = Rules::getCardByMTGId(observer, loadedPlayerZones[j]->cards[k]->getId()); + if (card && zone != p->game->library) + { + if (zone == p->game->inPlay) + { + MTGCardInstance * copy = p->game->putInZone(card, p->game->library, p->game->stack); + Spell * spell = NEW Spell(observer, copy); + spell->resolve(); + if (!summoningSickness && (size_t)p->game->inPlay->nb_cards > k) p->game->inPlay->cards[k]->summoningSickness = 0; + delete spell; + } + else + { + if (!p->game->library->hasCard(card)) + { + LOG ("TESTUITE ERROR, CARD NOT FOUND IN LIBRARY\n"); + } + p->game->putInZone(card, p->game->library, zone); + } + } + else + { + if (!card) + { + LOG ("TESTUITE ERROR, card is NULL\n"); + } + } + } + zone->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn + } + p->game->stack->cardsSeenThisTurn.clear(); //don't consider those cards as having moved in this area during this turn + + } + DebugTrace("TESTUITE Init Game Done !"); +} + +MTGPlayerCards * TestSuiteGame::buildDeck(Player* player, int playerId) +{ + int list[100]; + int nbcards = 0; + MTGPlayerCards * deck = NULL; + + if(initState.players.size() > (size_t)playerId) + { + MTGGameZone * loadedPlayerZones[] = { initState.players[playerId]->game->graveyard, + initState.players[playerId]->game->library, + initState.players[playerId]->game->hand, + initState.players[playerId]->game->inPlay }; + + for (int j = 0; j < 4; j++) + { + for (size_t k = 0; k < loadedPlayerZones[j]->cards.size(); k++) + { + int cardid = loadedPlayerZones[j]->cards[k]->getId(); + list[nbcards] = cardid; + nbcards++; + } + } + deck = NEW MTGPlayerCards(player, list, nbcards); + } + else + { + deck = NEW MTGPlayerCards(); + } + + return deck; +} + #endif diff --git a/projects/mtg/src/Trash.cpp b/projects/mtg/src/Trash.cpp index 515c2e3b2..c32095833 100644 --- a/projects/mtg/src/Trash.cpp +++ b/projects/mtg/src/Trash.cpp @@ -9,15 +9,11 @@ template void TrashBin::put_out() { - for (typename std::vector::iterator it = bin.begin(); it != bin.end(); ++it) + for (typename std::vector::iterator it = bin.begin(); it != bin.end(); ++it) SAFE_DELETE(*it); bin.clear(); } -static TrashBin CardViewTrash; -static TrashBin DefenserDamagedTrash; -static TrashBin AttackerDamagedTrash; - void Trash::cleanup() { CardViewTrash.put_out(); @@ -25,15 +21,15 @@ void Trash::cleanup() AttackerDamagedTrash.put_out(); } -template<> void trash(CardView* garbage) +void Trash::trash(CardView* garbage) { CardViewTrash.bin.push_back(garbage); } -template<> void trash(DefenserDamaged* garbage) +void Trash::trash(DefenserDamaged* garbage) { DefenserDamagedTrash.bin.push_back(garbage); } -template<> void trash(AttackerDamaged* garbage) +void Trash::trash(AttackerDamaged* garbage) { AttackerDamagedTrash.bin.push_back(garbage); }