From 3514476812d7e13c253a1a4e0f0d990cbc9a7f29 Mon Sep 17 00:00:00 2001 From: Xawotihs Date: Tue, 29 Nov 2011 21:50:16 +0000 Subject: [PATCH] - Created a GamePhase type to ease debug. - Modified the testsuite and gameobserver to be able to replay all the testcases based on the actions logged during the first pass. This allows to test the action logging and replay used during undo. It's only activated in multithreaded mode and it does not work on Momir tests. - Modified choice logging and replay to use menuId instead of ability index, as, for some obscur reasons related to Lord, those ability indexes may change. - Fixed bug in nextphase logging wrongly generating click actions - Added a "stack" zone to the click ability logging to be able to replay properly interrupt - Fixed a wonderful bug mixing card names with zone names in the actions execution engine - Added a "combatok" action logging/execution - Added a "clone" virtual method to MTGCardInstance and Token to be able to clone correctly the right object type. Used that in MTGGameZones::removeCard --- projects/mtg/include/ActionElement.h | 5 +- projects/mtg/include/AllAbilities.h | 68 ++++---- projects/mtg/include/GameObserver.h | 29 +++- projects/mtg/include/MTGAbility.h | 2 +- projects/mtg/include/MTGCardInstance.h | 1 + projects/mtg/include/MTGDefinitions.h | 38 +++-- projects/mtg/include/PhaseRing.h | 9 +- projects/mtg/include/Rules.h | 3 +- projects/mtg/include/TestSuiteAI.h | 3 +- projects/mtg/include/Token.h | 2 + projects/mtg/include/utils.h | 2 +- projects/mtg/src/AIMomirPlayer.cpp | 6 +- projects/mtg/src/AIPlayerBaka.cpp | 40 ++--- projects/mtg/src/ActionElement.cpp | 4 +- projects/mtg/src/ActionLayer.cpp | 20 ++- projects/mtg/src/AllAbilities.cpp | 14 +- projects/mtg/src/DuelLayers.cpp | 2 +- projects/mtg/src/ExtraCost.cpp | 2 +- projects/mtg/src/GameObserver.cpp | 219 ++++++++++++++++--------- projects/mtg/src/GameOptions.cpp | 28 ++-- projects/mtg/src/GameStateDuel.cpp | 2 +- projects/mtg/src/GuiCombat.cpp | 5 +- projects/mtg/src/GuiPlay.cpp | 2 +- projects/mtg/src/MTGAbility.cpp | 46 +++--- projects/mtg/src/MTGCardInstance.cpp | 7 +- projects/mtg/src/MTGGameZones.cpp | 2 +- projects/mtg/src/MTGRules.cpp | 42 ++--- projects/mtg/src/PhaseRing.cpp | 48 +++--- projects/mtg/src/Player.cpp | 4 +- projects/mtg/src/Rules.cpp | 3 +- projects/mtg/src/TestSuiteAI.cpp | 28 +++- projects/mtg/src/Token.cpp | 29 ++++ projects/mtg/src/utils.cpp | 4 +- 33 files changed, 433 insertions(+), 286 deletions(-) diff --git a/projects/mtg/include/ActionElement.h b/projects/mtg/include/ActionElement.h index 5d8cf566a..b027e2d8f 100644 --- a/projects/mtg/include/ActionElement.h +++ b/projects/mtg/include/ActionElement.h @@ -7,6 +7,7 @@ #ifndef _ACTIONELEMENT_H_ #define _ACTIONELEMENT_H_ #include +#include "MTGDefinitions.h" #define INACTIVE 0 #define ACTION_REQUESTED 1 @@ -24,8 +25,8 @@ protected: int activeState; TargetChooser * tc; public: - int currentPhase; - int newPhase; + GamePhase currentPhase; + GamePhase newPhase; int modal; int waitingForAnswer; int getActivity(); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index da3c7ebd9..36c291a71 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1769,7 +1769,7 @@ public: void Update(float dt) { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP) clear(); + if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) clear(); TargetAbility::Update(dt); } @@ -3259,7 +3259,7 @@ public: void Update(float dt) { - if (newPhase != currentPhase && (newPhase == Constants::MTG_PHASE_COMBATBEGIN || newPhase == Constants::MTG_PHASE_COMBATATTACKERS)) + if (newPhase != currentPhase && (newPhase == MTG_PHASE_COMBATBEGIN || newPhase == MTG_PHASE_COMBATATTACKERS)) { if (source->controller()->opponent()->game->inPlay->hasType(land)) { @@ -3461,12 +3461,12 @@ public: { if (WEventPhaseChange* pe = dynamic_cast(event)) { - if (luckyWinner && Constants::MTG_PHASE_AFTER_EOT == pe->from->id) + if (luckyWinner && MTG_PHASE_AFTER_EOT == pe->from->id) { luckyWinner = NULL; } - if (Constants::MTG_PHASE_COMBATATTACKERS == pe->from->id) + if (MTG_PHASE_COMBATATTACKERS == pe->from->id) { int nbattackers = 0; MTGGameZone * z = source->controller()->game->inPlay; @@ -3627,7 +3627,7 @@ public: ManaCost * backupMana; AUpkeep(GameObserver* observer, int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int restrictions = 0, int _phase = - Constants::MTG_PHASE_UPKEEP, int _once = 0,bool Cumulative = false); + MTG_PHASE_UPKEEP, int _once = 0,bool Cumulative = false); int receiveEvent(WEvent * event); void Update(float dt); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); @@ -3655,7 +3655,7 @@ public: Player * abilityOwner; APhaseAction(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase = - Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true,bool once = false); + MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true,bool once = false); void Update(float dt); int resolve(); const char * getMenuText(); @@ -3670,7 +3670,7 @@ public: string sAbility; APhaseAction * ability; APhaseActionGeneric(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase = - Constants::MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false,bool once = false); + MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false,bool once = false); int resolve(); const char * getMenuText(); APhaseActionGeneric * clone() const; @@ -3819,11 +3819,11 @@ public: { if (newPhase != currentPhase) { - if (newPhase == Constants::MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source)) + if (newPhase == MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source)) { counters++; } - else if (newPhase == Constants::MTG_PHASE_DRAW && counters > 0 && game->currentPlayer->game->inPlay->hasCard(source)) + else if (newPhase == MTG_PHASE_DRAW && counters > 0 && game->currentPlayer->game->inPlay->hasCard(source)) { //End of upkeep = beginning of draw game->mLayers->stackLayer()->addDamage(source, game->players[0], counters); @@ -3834,7 +3834,7 @@ public: } int isReactingToClick(MTGCardInstance * _card, ManaCost * mana = NULL) { - if (counters > 0 && _card == source && currentPhase == Constants::MTG_PHASE_UPKEEP) + if (counters > 0 && _card == source && currentPhase == MTG_PHASE_UPKEEP) { if (game->currentlyActing()->getManaPool()->canAfford(&cost)) { @@ -3979,7 +3979,7 @@ public: void Update(float dt) { - if (newPhase != currentPhase && newPhase != Constants::MTG_PHASE_UPKEEP) + if (newPhase != currentPhase && newPhase != MTG_PHASE_UPKEEP) { usedThisTurn = 0; } @@ -3989,7 +3989,7 @@ public: int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL) { if (!ActivatedAbility::isReactingToClick(card, mana)) return 0; - if (currentPhase != Constants::MTG_PHASE_UPKEEP) return 0; + if (currentPhase != MTG_PHASE_UPKEEP) return 0; if (usedThisTurn) return 0; return 1; } @@ -4028,7 +4028,7 @@ public: { if (newPhase != currentPhase) { - if (newPhase == Constants::MTG_PHASE_COMBATEND) + if (newPhase == MTG_PHASE_COMBATEND) { nbOpponents = 0; MTGCardInstance * opponent = source->getNextOpponent(); @@ -4051,7 +4051,7 @@ public: int testDestroy() { - if (!game->isInPlay(source) && currentPhase != Constants::MTG_PHASE_UNTAP) + if (!game->isInPlay(source) && currentPhase != MTG_PHASE_UNTAP) { return 0; } @@ -4129,12 +4129,12 @@ public: if (newPhase != currentPhase) { Player * controller = source->controller(); - if(newPhase == Constants::MTG_PHASE_ENDOFTURN) + if(newPhase == MTG_PHASE_ENDOFTURN) { if(!attackedThisTurn && game->currentPlayer == source->controller() && !source->fresh) game->mLayers->stackLayer()->addDamage(source, controller, 2); } - else if (newPhase == Constants::MTG_PHASE_UNTAP) + else if (newPhase == MTG_PHASE_UNTAP) { if (game->currentPlayer == controller) @@ -4184,7 +4184,7 @@ public: void Update(float dt) { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP) + if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) { landsPlayedThisTurn = 0; } @@ -4358,7 +4358,7 @@ public: void Update(float dt) { MTGCardInstance * _target = (MTGCardInstance *) target; - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UPKEEP && _target->controller() == game->currentPlayer) + if (newPhase != currentPhase && newPhase == MTG_PHASE_UPKEEP && _target->controller() == game->currentPlayer) { damagesToDealThisTurn = 2; } @@ -4368,7 +4368,7 @@ public: int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL) { MTGCardInstance * _target = (MTGCardInstance *) target; - if (damagesToDealThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && card == source && _target->controller() + if (damagesToDealThisTurn && currentPhase == MTG_PHASE_UPKEEP && card == source && _target->controller() == game->currentPlayer) { if (game->currentPlayer->getManaPool()->canAfford(&cost)) return 1; @@ -4386,7 +4386,7 @@ public: int trigger() { MTGCardInstance * _target = (MTGCardInstance *) target; - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_DRAW && _target->controller() == game->currentPlayer) + if (newPhase != currentPhase && newPhase == MTG_PHASE_DRAW && _target->controller() == game->currentPlayer) { if (damagesToDealThisTurn) return 1; } @@ -4513,14 +4513,14 @@ public: void Update(float dt) { - if (currentPhase == Constants::MTG_PHASE_UNTAP && game->currentPlayer == source->controller()) + if (currentPhase == MTG_PHASE_UNTAP && game->currentPlayer == source->controller()) { initThisTurn = 0; for(unsigned int i = 0; i < effectedCards.size(); i++) effectedCards.at(i)->basicAbilities[(int)Constants::CANTATTACK] = 0; effectedCards.clear(); } - if (initThisTurn && currentPhase == Constants::MTG_PHASE_COMBATBEGIN && game->currentPlayer != source->controller()) + if (initThisTurn && currentPhase == MTG_PHASE_COMBATBEGIN && game->currentPlayer != source->controller()) { MTGGameZone * zone = game->currentPlayer->game->inPlay; for (int i = 0; i < zone->nb_cards; i++) @@ -4584,11 +4584,11 @@ public: //Upkeep Cost if (newPhase != currentPhase) { - if (newPhase == Constants::MTG_PHASE_UPKEEP) + if (newPhase == MTG_PHASE_UPKEEP) { paidThisTurn = 0; } - else if (!paidThisTurn && newPhase > Constants::MTG_PHASE_UPKEEP && game->currentPlayer == source->controller()) + else if (!paidThisTurn && newPhase > MTG_PHASE_UPKEEP && game->currentPlayer == source->controller()) { game->currentPlayer->game->putInGraveyard(source); paidThisTurn = 1; @@ -4597,7 +4597,7 @@ public: //Stasis Effect for (int i = 0; i < 2; i++) { - game->phaseRing->removePhase(Constants::MTG_PHASE_UNTAP, game->players[i]); + game->phaseRing->removePhase(MTG_PHASE_UNTAP, game->players[i]); } //Parent Class Method Call @@ -4606,7 +4606,7 @@ public: int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL) { - return (!paidThisTurn && currentPhase == Constants::MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card, mana)); + return (!paidThisTurn && currentPhase == MTG_PHASE_UPKEEP && ActivatedAbility::isReactingToClick(card, mana)); } int resolve() @@ -4619,7 +4619,7 @@ public: { for (int i = 0; i < 2; i++) { - game->phaseRing->addPhaseBefore(Constants::MTG_PHASE_UNTAP, game->players[i], Constants::MTG_PHASE_UPKEEP, + game->phaseRing->addPhaseBefore(MTG_PHASE_UNTAP, game->players[i], MTG_PHASE_UPKEEP, game->players[i]); } return 1; @@ -4654,7 +4654,7 @@ public: { if (newPhase != currentPhase) { - if (newPhase == Constants::MTG_PHASE_COMBATDAMAGE) + if (newPhase == MTG_PHASE_COMBATDAMAGE) { nbOpponents = 0; MTGCardInstance * opponent = source->getNextOpponent(); @@ -4665,7 +4665,7 @@ public: opponent = source->getNextOpponent(opponent); } } - else if (newPhase == Constants::MTG_PHASE_COMBATEND) + else if (newPhase == MTG_PHASE_COMBATEND) { for (int i = 0; i < nbOpponents; i++) { @@ -4753,11 +4753,11 @@ public: { if (newPhase != currentPhase && source->controller() == game->currentPlayer) { - if (newPhase == Constants::MTG_PHASE_UNTAP) + if (newPhase == MTG_PHASE_UNTAP) { paidThisTurn = 0; } - else if (newPhase == Constants::MTG_PHASE_UPKEEP + 1 && !paidThisTurn) + else if (newPhase == MTG_PHASE_UPKEEP + 1 && !paidThisTurn) { game->mLayers->stackLayer()->addDamage(source, source->controller(), 5); source->tap(); @@ -4768,7 +4768,7 @@ public: int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL) { - if (currentPhase != Constants::MTG_PHASE_UPKEEP || paidThisTurn) return 0; + if (currentPhase != MTG_PHASE_UPKEEP || paidThisTurn) return 0; return TargetAbility::isReactingToClick(card, mana); } @@ -4824,7 +4824,7 @@ public: } else if (WEventPhaseChange* pe = dynamic_cast(event)) { - if (Constants::MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents > MaxOpponent) + if (MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents > MaxOpponent) { source->power -= PowerModifier * (nbOpponents - MaxOpponent); source->addToToughness(-ToughnessModifier * (nbOpponents - MaxOpponent)); @@ -4922,7 +4922,7 @@ public: } else if (WEventPhaseChange* pe = dynamic_cast(event)) { - if (Constants::MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents) + if (MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents) { source->power -= PowerModifier; source->addToToughness(-ToughnessModifier); diff --git a/projects/mtg/include/GameObserver.h b/projects/mtg/include/GameObserver.h index 7dd22be4f..af72f4361 100644 --- a/projects/mtg/include/GameObserver.h +++ b/projects/mtg/include/GameObserver.h @@ -51,12 +51,20 @@ class GameObserver{ string startupGameSerialized; bool parseLine(const string& s); void logAction(const string& s); - bool processActions(bool undo); - friend ostream& operator<<(ostream&, GameObserver&); + bool processActions(bool undo + #ifdef TESTSUITE + , TestSuiteGame* testgame + #endif + ); + friend ostream& operator<<(ostream&, const GameObserver&); bool mLoading; void nextGamePhase(); void shuffleLibrary(Player* p); - void createPlayer(const string& playerMode); + void createPlayer(const string& playerMode + #ifdef TESTSUITE + , TestSuiteGame* testgame + #endif //TESTSUITE + ); public: int currentPlayerId; @@ -66,7 +74,7 @@ class GameObserver{ int targetListIsSet(MTGCardInstance * card); PhaseRing * phaseRing; int cancelCurrentAction(); - int currentGamePhase; + GamePhase currentGamePhase; ExtraCosts * mExtraPayment; int oldGamePhase; TargetChooser * targetChooser; @@ -83,10 +91,11 @@ class GameObserver{ TargetChooser * getCurrentTargetChooser(); void stackObjectClicked(Interruptible * action); + int cardClickLog(bool log, Player* clickedPlayer, MTGGameZone* zone, MTGCardInstance*backup, size_t index, int toReturn); int cardClick(MTGCardInstance * card, MTGAbility *ability); int cardClick(MTGCardInstance * card, int abilityType); - int cardClick(MTGCardInstance * card,Targetable * _object = NULL ); - int getCurrentGamePhase(); + int cardClick(MTGCardInstance * card,Targetable * _object = NULL, bool log = true); + GamePhase getCurrentGamePhase(); const char * getCurrentGamePhaseName(); const char * getNextGamePhaseName(); void nextCombatStep(); @@ -131,7 +140,11 @@ class GameObserver{ logAction(players[playerId], s); }; void logAction(MTGCardInstance* card, MTGGameZone* zone, size_t index, int result); - bool load(const string& s, bool undo = false); + bool load(const string& s, bool undo = false +#ifdef TESTSUITE + , TestSuiteGame* testgame = 0 +#endif + ); bool undo(); bool isLoading(){ return mLoading; }; void Mulligan(Player* player = NULL); @@ -144,7 +157,7 @@ class GameObserver{ JGE* getInput(){return mJGE;}; DeckManager* getDeckManager(){ return mDeckManager; }; void dumpAssert(bool val); - + void resetStartupGame(); }; #endif diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index b11624862..b93e4bb6c 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -289,7 +289,7 @@ public: virtual void Update(float dt) { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) + if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT) { counters = 0; } diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 642d03fbb..d872daf9e 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -208,6 +208,7 @@ public: static MTGCardInstance NoCard; bool parseLine(const string& ss); + virtual MTGCardInstance* clone(); }; diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 65fc886e7..cce334dda 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -35,6 +35,27 @@ typedef enum #endif //NETWORK_SUPPORT } PlayerType; +typedef enum +{ + MTG_PHASE_INVALID = -1, + MTG_PHASE_BEFORE_BEGIN = 0, + MTG_PHASE_UNTAP = 1, + MTG_PHASE_UPKEEP = 2, + MTG_PHASE_DRAW = 3, + MTG_PHASE_FIRSTMAIN = 4, + MTG_PHASE_COMBATBEGIN = 5, + MTG_PHASE_COMBATATTACKERS = 6, + MTG_PHASE_COMBATBLOCKERS = 7, + MTG_PHASE_COMBATDAMAGE = 8, + MTG_PHASE_COMBATEND = 9, + MTG_PHASE_SECONDMAIN = 10, + MTG_PHASE_ENDOFTURN = 11, + MTG_PHASE_CLEANUP = 12, + MTG_PHASE_AFTER_EOT = 13, + NB_MTG_PHASES = 14 +} GamePhase; + + class Constants { public: @@ -95,23 +116,6 @@ class Constants MTG_TYPE_LAND = 14, MTG_TYPE_INSTANT = 15, - - MTG_PHASE_BEFORE_BEGIN = 0, - MTG_PHASE_UNTAP = 1, - MTG_PHASE_UPKEEP = 2, - MTG_PHASE_DRAW = 3, - MTG_PHASE_FIRSTMAIN = 4, - MTG_PHASE_COMBATBEGIN = 5, - MTG_PHASE_COMBATATTACKERS = 6, - MTG_PHASE_COMBATBLOCKERS = 7, - MTG_PHASE_COMBATDAMAGE = 8, - MTG_PHASE_COMBATEND = 9, - MTG_PHASE_SECONDMAIN = 10, - MTG_PHASE_ENDOFTURN = 11, - MTG_PHASE_CLEANUP = 12, - MTG_PHASE_AFTER_EOT = 13, - NB_MTG_PHASES = 14, - TRAMPLE = 0, FORESTWALK = 1, ISLANDWALK = 2, diff --git a/projects/mtg/include/PhaseRing.h b/projects/mtg/include/PhaseRing.h index 0a7a23b92..7ef9da7b5 100644 --- a/projects/mtg/include/PhaseRing.h +++ b/projects/mtg/include/PhaseRing.h @@ -3,6 +3,7 @@ #include #include +#include "MTGDefinitions.h" using namespace std; /* @@ -26,9 +27,9 @@ typedef enum class Phase { public: - int id; + GamePhase id; Player * player; - Phase(int id, Player *player) : + Phase(GamePhase id, Player *player) : id(id), player(player) { } @@ -49,10 +50,10 @@ public: PhaseRing(GameObserver* observer); ~PhaseRing(); int addPhase(Phase * phase); - int addPhaseBefore(int id, Player* player, int after_id, Player * after_player, int allOccurences = 1); + int addPhaseBefore(GamePhase id, Player* player, int after_id, Player * after_player, int allOccurences = 1); int removePhase(int id, Player * player, int allOccurences = 1); const char * phaseName(int id); - static int phaseStrToInt(string s); + static GamePhase phaseStrToInt(string s); }; diff --git a/projects/mtg/include/Rules.h b/projects/mtg/include/Rules.h index 7fd66ae83..5b2069bc9 100644 --- a/projects/mtg/include/Rules.h +++ b/projects/mtg/include/Rules.h @@ -3,6 +3,7 @@ #include #include +#include "MTGDefinitions.h" using namespace std; class ManaCost; @@ -28,7 +29,7 @@ public: class RulesState { public: - int phase; + GamePhase phase; int player; void parsePlayerState(int playerId, string s); RulesState(); diff --git a/projects/mtg/include/TestSuiteAI.h b/projects/mtg/include/TestSuiteAI.h index 5829cbc96..13a925d23 100644 --- a/projects/mtg/include/TestSuiteAI.h +++ b/projects/mtg/include/TestSuiteAI.h @@ -26,7 +26,7 @@ class TestSuiteAI; class TestSuiteState { public: - int phase; + GamePhase phase; void parsePlayerState(int playerId, string s); TestSuiteState(); ~TestSuiteState(); @@ -63,6 +63,7 @@ public: virtual ~TestSuiteGame(); TestSuiteGame(TestSuite* testsuite); TestSuiteGame(TestSuite* testsuite, string _filename); + void ResetManapools(); void initGame(); void assertGame(); MTGPlayerCards * buildDeck(Player* player, int playerId); diff --git a/projects/mtg/include/Token.h b/projects/mtg/include/Token.h index 8af818f03..4ea6b6c15 100644 --- a/projects/mtg/include/Token.h +++ b/projects/mtg/include/Token.h @@ -9,6 +9,8 @@ class Token: public MTGCardInstance public: Token(string _name, MTGCardInstance * source, int _power = 0, int _toughness = 0); Token(int id); + Token(const Token& source); + virtual MTGCardInstance* clone(); }; #endif diff --git a/projects/mtg/include/utils.h b/projects/mtg/include/utils.h index 9e77467bf..6a12a84b0 100644 --- a/projects/mtg/include/utils.h +++ b/projects/mtg/include/utils.h @@ -75,7 +75,7 @@ protected: public: RandomGenerator(bool doLog = false) : log(doLog) {}; void loadRandValues(string s); - ostream& saveUsedRandValues(ostream& out); + ostream& saveUsedRandValues(ostream& out) const; ostream& saveLoadedRandValues(ostream& out); int random(); template void random_shuffle(Iter first, Iter last) diff --git a/projects/mtg/src/AIMomirPlayer.cpp b/projects/mtg/src/AIMomirPlayer.cpp index 461c1aa25..11d4b6251 100644 --- a/projects/mtg/src/AIMomirPlayer.cpp +++ b/projects/mtg/src/AIMomirPlayer.cpp @@ -20,7 +20,7 @@ int AIMomirPlayer::getEfficiency(OrderedAIAction * action) if (cost && !(cost->isExtraPaymentSet())) return 0; //Does not handle abilities with sacrifice yet int efficiency = AIPlayerBaka::getEfficiency(action); - if (observer->getCurrentGamePhase() < Constants::MTG_PHASE_FIRSTMAIN) return 0; + if (observer->getCurrentGamePhase() < MTG_PHASE_FIRSTMAIN) return 0; return efficiency; } @@ -95,7 +95,7 @@ int AIMomirPlayer::computeActions() switch (currentGamePhase) { - case Constants::MTG_PHASE_FIRSTMAIN: + case MTG_PHASE_FIRSTMAIN: { ManaCost * potentialMana = getPotentialMana(); int converted = potentialMana->getConvertedCost(); @@ -120,7 +120,7 @@ int AIMomirPlayer::computeActions() return 1; break; } - case Constants::MTG_PHASE_SECONDMAIN: + case MTG_PHASE_SECONDMAIN: selectAbility(); return 1; break; diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index 6a9982e12..195212e8b 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -104,7 +104,7 @@ int OrderedAIAction::getEfficiency() if (!coreAbilityCardTarget) break; - if (!coreAbilityCardTarget->regenerateTokens && currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS + if (!coreAbilityCardTarget->regenerateTokens && currentPhase == MTG_PHASE_COMBATBLOCKERS && (coreAbilityCardTarget->defenser || coreAbilityCardTarget->blockers.size()) ) { @@ -122,7 +122,7 @@ int OrderedAIAction::getEfficiency() bool NeedPreventing; NeedPreventing = false; - if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS) + if (currentPhase == MTG_PHASE_COMBATBLOCKERS) { MTGCardInstance * nextOpponent = target->getNextOpponent(); if(!nextOpponent) @@ -210,7 +210,7 @@ int OrderedAIAction::getEfficiency() //it should always try playing more cards before deciding } - if (g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN) + if (g->getCurrentGamePhase() == MTG_PHASE_SECONDMAIN) { efficiency = 100; //in 2nd main, go all out and try to max stuff. @@ -272,7 +272,7 @@ int OrderedAIAction::getEfficiency() int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); //i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does. int currentPhase = g->getCurrentGamePhase(); - if ((currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS) || (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS)) + if ((currentPhase == MTG_PHASE_COMBATBLOCKERS) || (currentPhase == MTG_PHASE_COMBATATTACKERS)) { if (suggestion == BAKA_EFFECT_GOOD && target->controller() == p) { @@ -309,7 +309,7 @@ int OrderedAIAction::getEfficiency() break; //nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat. - if (coreAbilityCardTarget && !coreAbilityCardTarget->isCreature() && currentPhase == Constants::MTG_PHASE_FIRSTMAIN) + if (coreAbilityCardTarget && !coreAbilityCardTarget->isCreature() && currentPhase == MTG_PHASE_FIRSTMAIN) { efficiency = 100; } @@ -343,7 +343,7 @@ int OrderedAIAction::getEfficiency() efficiency += efficiencyModifier; } - if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN + if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == MTG_PHASE_COMBATBEGIN && p == target->controller() ) { @@ -518,7 +518,7 @@ int OrderedAIAction::getEfficiency() if(AUpkeep * auk = dynamic_cast(ability)) { //hello, Ai pay your upcost please :P, this entices Ai into paying upcost, the conditional isAi() is required strangely ai is able to pay upcost during YOUR upkeep. - if (auk && g->getCurrentGamePhase() == Constants::MTG_PHASE_UPKEEP && g->currentPlayer == p && p == a->source->controller()) + if (auk && g->getCurrentGamePhase() == MTG_PHASE_UPKEEP && g->currentPlayer == p && p == a->source->controller()) { efficiency = 100; } @@ -1832,11 +1832,11 @@ int AIPlayerBaka::computeActions() { //standard actions switch (observer->getCurrentGamePhase()) { - case Constants::MTG_PHASE_UPKEEP: + case MTG_PHASE_UPKEEP: selectAbility(); break; - case Constants::MTG_PHASE_FIRSTMAIN: - case Constants::MTG_PHASE_SECONDMAIN: + case MTG_PHASE_FIRSTMAIN: + case MTG_PHASE_SECONDMAIN: { ManaCost * currentMana = getPotentialMana(); currentMana->add(this->getManaPool()); @@ -1891,19 +1891,19 @@ int AIPlayerBaka::computeActions() } break; } - case Constants::MTG_PHASE_COMBATATTACKERS: + case MTG_PHASE_COMBATATTACKERS: { if(observer->currentPlayer == this)//only on my turns. chooseAttackers(); break; } - case Constants::MTG_PHASE_COMBATBLOCKERS: + case MTG_PHASE_COMBATBLOCKERS: { if(observer->currentPlayer != this)//only on my opponents turns. chooseBlockers(); break; } - case Constants::MTG_PHASE_ENDOFTURN: + case MTG_PHASE_ENDOFTURN: selectAbility(); break; default: @@ -1914,11 +1914,11 @@ int AIPlayerBaka::computeActions() { switch (observer->getCurrentGamePhase()) { - case Constants::MTG_PHASE_UPKEEP: - case Constants::MTG_PHASE_FIRSTMAIN: - case Constants::MTG_PHASE_COMBATATTACKERS: - case Constants::MTG_PHASE_COMBATBLOCKERS: - case Constants::MTG_PHASE_SECONDMAIN: + case MTG_PHASE_UPKEEP: + case MTG_PHASE_FIRSTMAIN: + case MTG_PHASE_COMBATATTACKERS: + case MTG_PHASE_COMBATBLOCKERS: + case MTG_PHASE_SECONDMAIN: { selectAbility(); break; @@ -2138,10 +2138,10 @@ int AIPlayerBaka::combatDamages() { int currentGamePhase = observer->getCurrentGamePhase(); - if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) + if (currentGamePhase == MTG_PHASE_COMBATBLOCKERS) return orderBlockers(); - if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) + if (currentGamePhase != MTG_PHASE_COMBATDAMAGE) return 0; return 0; diff --git a/projects/mtg/src/ActionElement.cpp b/projects/mtg/src/ActionElement.cpp index 2d6c33c1b..abf685513 100644 --- a/projects/mtg/src/ActionElement.cpp +++ b/projects/mtg/src/ActionElement.cpp @@ -11,8 +11,8 @@ ActionElement::ActionElement(int id) : activeState = INACTIVE; modal = 0; waitingForAnswer = 0; - currentPhase = -1; - newPhase = -1; + currentPhase = MTG_PHASE_INVALID; + newPhase = MTG_PHASE_INVALID; tc = NULL; } diff --git a/projects/mtg/src/ActionLayer.cpp b/projects/mtg/src/ActionLayer.cpp index 354bd8dee..122052744 100644 --- a/projects/mtg/src/ActionLayer.cpp +++ b/projects/mtg/src/ActionLayer.cpp @@ -140,7 +140,7 @@ void ActionLayer::Update(float dt) observer->removeObserver(currentAction); } } - int newPhase = observer->getCurrentGamePhase(); + GamePhase newPhase = observer->getCurrentGamePhase(); for (size_t i = 0; i < mObjects.size(); i++) { if (mObjects[i] != NULL) @@ -299,17 +299,18 @@ bool ActionLayer::getMenuIdFromCardAbility(MTGCardInstance *card, MTGAbility *ab if (currentAction->isReactingToClick(card)) { if(currentAction == ability) { + // code corresponding to that is in setMenuObject menuId = ctr; + ctr++; } - ctr++; } } - // ability not working with card or only one ability possible if(ctr == 0 || ctr == 1) + { return false; + } else - // several abilities working with card, menuId set return true; } @@ -433,8 +434,15 @@ void ActionLayer::doReactTo(int menuIndex) void ActionLayer::ButtonPressed(int controllerid, int controlid) { stringstream stream; - stream << "choice " << controlid; - observer->logAction(observer->currentActionPlayer, stream.str()); + for(size_t i = 0; i < abilitiesMenu->mObjects.size(); i++) + { // this computes the reverse from the doReactTo method + if(abilitiesMenu->mObjects[i]->GetId() == controlid) + { + stream << "choice " << i; + observer->logAction(observer->currentActionPlayer, stream.str()); + break; + } + } if(this->abilitiesMenu && this->abilitiesMenu->isMultipleChoice) { diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index e3408f11e..d7e80ceac 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -2542,7 +2542,7 @@ int GenericTargetAbility::isReactingToClick(MTGCardInstance * card, ManaCost * m void GenericTargetAbility::Update(float dt) { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) + if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT) { counters = 0; } @@ -3345,7 +3345,7 @@ void AVanishing::Update(float dt) { if (newPhase != currentPhase && source->controller() == game->currentPlayer) { - if(newPhase == Constants::MTG_PHASE_UPKEEP) + if(newPhase == MTG_PHASE_UPKEEP) { source->counters->removeCounter(counterName.c_str(),0,0); Counter * targetCounter = NULL; @@ -3367,7 +3367,7 @@ void AVanishing::Update(float dt) { next = 0; } - if (newPhase == Constants::MTG_PHASE_UPKEEP && timeLeft <= 0 && next == 0) + if (newPhase == MTG_PHASE_UPKEEP && timeLeft <= 0 && next == 0) { WEvent * e = NEW WEventCardSacrifice(source); game->receiveEvent(e); @@ -3415,7 +3415,7 @@ AUpkeep::AUpkeep(GameObserver* observer, int _id, MTGCardInstance * card, MTGAbi { if (WEventPhaseChange* pe = dynamic_cast(event)) { - if (Constants::MTG_PHASE_DRAW == pe->to->id) + if (MTG_PHASE_DRAW == pe->to->id) { if (source->controller() == game->currentPlayer && once < 2 && paidThisTurn < 1) { @@ -3431,11 +3431,11 @@ void AUpkeep::Update(float dt) // once: 0 means always go off, 1 means go off only once, 2 means go off only once and already has. if (newPhase != currentPhase && source->controller() == game->currentPlayer && once < 2) { - if (newPhase == Constants::MTG_PHASE_UNTAP) + if (newPhase == MTG_PHASE_UNTAP) { paidThisTurn = 0; } - else if(newPhase == Constants::MTG_PHASE_UPKEEP && Cumulative ) + else if(newPhase == MTG_PHASE_UPKEEP && Cumulative ) { source->counters->addCounter("age",0,0); Counter * targetCounter = NULL; @@ -3644,7 +3644,7 @@ void ABlink::Update(float dt) resolveBlink(); } - if ((blinkueot && currentPhase == Constants::MTG_PHASE_ENDOFTURN)||(blinkForSource && !source->isInPlay(game))) + if ((blinkueot && currentPhase == MTG_PHASE_ENDOFTURN)||(blinkForSource && !source->isInPlay(game))) { if(Blinked == NULL) MTGAbility::Update(dt); diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index da3cde38f..7c464320f 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -206,7 +206,7 @@ int DuelLayers::receiveEvent(WEvent * e) objects[i]->receiveEventMinus(e); if (WEventPhaseChange *event = dynamic_cast(e)) - if (Constants::MTG_PHASE_BEFORE_BEGIN == event->to->id) + if (MTG_PHASE_BEFORE_BEGIN == event->to->id) observer->mTrash->cleanup(); return 1; diff --git a/projects/mtg/src/ExtraCost.cpp b/projects/mtg/src/ExtraCost.cpp index 711fb8f79..d2c498d7e 100644 --- a/projects/mtg/src/ExtraCost.cpp +++ b/projects/mtg/src/ExtraCost.cpp @@ -537,7 +537,7 @@ int Ninja::isPaymentSet() { if (target && ((target->isAttacker() && target->isBlocked()) || target->isAttacker() < 1 || - target->getObserver()->getCurrentGamePhase() != Constants::MTG_PHASE_COMBATBLOCKERS)) + target->getObserver()->getCurrentGamePhase() != MTG_PHASE_COMBATBLOCKERS)) { tc->removeTarget(target); target = NULL; diff --git a/projects/mtg/src/GameObserver.cpp b/projects/mtg/src/GameObserver.cpp index 8f7554da5..017bb5c23 100644 --- a/projects/mtg/src/GameObserver.cpp +++ b/projects/mtg/src/GameObserver.cpp @@ -14,6 +14,7 @@ #include "MTGRules.h" #include "Trash.h" #include "DeckManager.h" +#include "GuiCombat.h" #ifdef TESTSUITE #include "TestSuiteAI.h" #endif @@ -34,7 +35,7 @@ void GameObserver::cleanup() currentActionPlayer = NULL; isInterrupting = NULL; currentPlayerId = 0; - currentGamePhase = -1; + currentGamePhase = MTG_PHASE_INVALID; targetChooser = NULL; cardWaitingForTargets = NULL; mExtraPayment = NULL; @@ -89,7 +90,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input) currentActionPlayer = NULL; isInterrupting = NULL; currentPlayerId = 0; - currentGamePhase = -1; + currentGamePhase = MTG_PHASE_INVALID; targetChooser = NULL; cardWaitingForTargets = NULL; mExtraPayment = NULL; @@ -105,7 +106,7 @@ GameObserver::GameObserver(WResourceManager *output, JGE* input) mDeckManager = new DeckManager(); } -int GameObserver::getCurrentGamePhase() +GamePhase GameObserver::getCurrentGamePhase() { return currentGamePhase; } @@ -117,7 +118,7 @@ const char* GameObserver::getCurrentGamePhaseName() const char* GameObserver::getNextGamePhaseName() { - return phaseRing->phaseName((currentGamePhase + 1) % Constants::MTG_PHASE_CLEANUP); + return phaseRing->phaseName((currentGamePhase + 1) % MTG_PHASE_CLEANUP); } Player * GameObserver::opponent() @@ -137,14 +138,14 @@ void GameObserver::nextPlayer() void GameObserver::nextGamePhase() { Phase * cPhaseOld = phaseRing->getCurrentPhase(); - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE) + if (cPhaseOld->id == MTG_PHASE_COMBATDAMAGE) if ((FIRST_STRIKE == combatStep) || (END_FIRST_STRIKE == combatStep) || (DAMAGE == combatStep)) { nextCombatStep(); return; } - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS) + if (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS) if (BLOCKERS == combatStep || TRIGGERS == combatStep) { nextCombatStep(); @@ -154,7 +155,7 @@ void GameObserver::nextGamePhase() phaseRing->forward(); //Go directly to end of combat if no attackers - if (cPhaseOld->id == Constants::MTG_PHASE_COMBATATTACKERS && !(currentPlayer->game->inPlay->getNextAttacker(NULL))) + if (cPhaseOld->id == MTG_PHASE_COMBATATTACKERS && !(currentPlayer->game->inPlay->getNextAttacker(NULL))) { phaseRing->forward(); phaseRing->forward(); @@ -163,14 +164,14 @@ void GameObserver::nextGamePhase() Phase * cPhase = phaseRing->getCurrentPhase(); currentGamePhase = cPhase->id; - if (Constants::MTG_PHASE_COMBATDAMAGE == currentGamePhase) + if (MTG_PHASE_COMBATDAMAGE == currentGamePhase) nextCombatStep(); if (currentPlayer != cPhase->player) nextPlayer(); //init begin of turn - if (currentGamePhase == Constants::MTG_PHASE_BEFORE_BEGIN) + if (currentGamePhase == MTG_PHASE_BEFORE_BEGIN) { cleanupPhase(); currentPlayer->damageCount = 0; @@ -187,7 +188,7 @@ void GameObserver::nextGamePhase() return nextGamePhase(); } - if (currentGamePhase == Constants::MTG_PHASE_AFTER_EOT) + if (currentGamePhase == MTG_PHASE_AFTER_EOT) { //Auto Hand cleaning, in case the player didn't do it himself while (currentPlayer->game->hand->nb_cards > currentPlayer->handsize && currentPlayer->nomaxhandsize == false) @@ -205,11 +206,11 @@ void GameObserver::nextGamePhase() //Phase Specific actions switch (currentGamePhase) { - case Constants::MTG_PHASE_UNTAP: + case MTG_PHASE_UNTAP: DebugTrace("Untap Phase ------------- Turn " << turn ); untapPhase(); break; - case Constants::MTG_PHASE_COMBATBLOCKERS: + case MTG_PHASE_COMBATBLOCKERS: receiveEvent(NEW WEventAttackersChosen()); break; default: @@ -264,7 +265,7 @@ void GameObserver::userRequestNextGamePhase(bool allowInterrupt, bool log) { getCurrentTargetChooser()->done = true; if(getCurrentTargetChooser()->source) - cardClick(getCurrentTargetChooser()->source); + cardClick(getCurrentTargetChooser()->source, 0, false); } if (allowInterrupt && mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED)) return; @@ -279,9 +280,9 @@ void GameObserver::userRequestNextGamePhase(bool allowInterrupt, bool log) return; Phase * cPhaseOld = phaseRing->getCurrentPhase(); - if (allowInterrupt && ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) - || (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) - || (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE) + if (allowInterrupt && ((cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) + || (cPhaseOld->id == MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) + || (cPhaseOld->id == MTG_PHASE_COMBATDAMAGE) || opponent()->isAI() || options[Options::optionInterrupt(currentGamePhase)].number || currentPlayer->offerInterruptOnPhase - 1 == currentGamePhase @@ -318,6 +319,17 @@ int GameObserver::forceShuffleLibraries() return result; } +void GameObserver::resetStartupGame() +{ + stringstream stream; + startupGameSerialized = ""; + stream << *this; + startupGameSerialized = stream.str(); + DebugTrace("startGame\n"); + DebugTrace(startupGameSerialized); +} + + void GameObserver::startGame(GameType gtype, Rules * rules) { mGameType = gtype; @@ -336,11 +348,7 @@ void GameObserver::startGame(GameType gtype, Rules * rules) currentActionPlayer = currentPlayer; phaseRing = NEW PhaseRing(this); - stringstream stream; - stream << *this; - startupGameSerialized = stream.str(); - DebugTrace("startGame\n"); - DebugTrace(startupGameSerialized); + resetStartupGame(); if (rules) rules->initGame(this); @@ -509,7 +517,7 @@ void GameObserver::Update(float dt) /*******************/ Player * player = currentPlayer; - if (Constants::MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) + if (MTG_PHASE_COMBATBLOCKERS == currentGamePhase && BLOCKERS == combatStep) { player = player->opponent(); } @@ -602,7 +610,7 @@ void GameObserver::gameStateBasedEffects() ////////////////////////// //handles phasing events// ////////////////////////// - if(card->has(Constants::PHASING)&& currentGamePhase == Constants::MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn && !card->isPhased) + if(card->has(Constants::PHASING)&& currentGamePhase == MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn && !card->isPhased) { card->isPhased = true; card->phasedTurn = turn; @@ -610,7 +618,7 @@ void GameObserver::gameStateBasedEffects() card->view->alpha = 50; card->initAttackersDefensers(); } - else if((card->has(Constants::PHASING) || card->isPhased)&& currentGamePhase == Constants::MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn) + else if((card->has(Constants::PHASING) || card->isPhased)&& currentGamePhase == MTG_PHASE_UNTAP && currentPlayer == card->controller() && card->phasedTurn != turn) { card->isPhased = false; card->phasedTurn = turn; @@ -714,7 +722,7 @@ void GameObserver::gameStateBasedEffects() ///////////////////////////////////////////////// //handle end of turn effects while we're at it.// ///////////////////////////////////////////////// - if (currentGamePhase == Constants::MTG_PHASE_ENDOFTURN+1) + if (currentGamePhase == MTG_PHASE_ENDOFTURN+1) { for (int j = 0; j < nbcards; ++j) { @@ -812,17 +820,17 @@ void GameObserver::gameStateBasedEffects() if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL) { - if ((opponent()->isAI() && !(isInterrupting)) && ((currentGamePhase == Constants::MTG_PHASE_UNTAP) - || (currentGamePhase == Constants::MTG_PHASE_DRAW) || (currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN) - || ((currentGamePhase == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0)) - || currentGamePhase == Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN - || ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8)))) + if ((opponent()->isAI() && !(isInterrupting)) && ((currentGamePhase == MTG_PHASE_UNTAP) + || (currentGamePhase == MTG_PHASE_DRAW) || (currentGamePhase == MTG_PHASE_COMBATBEGIN) + || ((currentGamePhase == MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0)) + || currentGamePhase == MTG_PHASE_COMBATEND || currentGamePhase == MTG_PHASE_ENDOFTURN + || ((currentGamePhase == MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8)))) userRequestNextGamePhase(); } if (skipLevel == Constants::ASKIP_FULL) { - if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UPKEEP - || currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE)) + if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == MTG_PHASE_UPKEEP + || currentGamePhase == MTG_PHASE_COMBATDAMAGE)) userRequestNextGamePhase(); } } @@ -1013,12 +1021,16 @@ void GameObserver::ButtonPressed(PlayGuiObject * target) void GameObserver::stackObjectClicked(Interruptible * action) { + stringstream stream; + stream << "stack[" << mLayers->stackLayer()->getIndexOf(action) << "]"; + logAction(currentlyActing(), stream.str()); + if (targetChooser != NULL) { int result = targetChooser->toggleTarget(action); if (result == TARGET_OK_FULL) { - cardClick(cardWaitingForTargets); + cardClick(cardWaitingForTargets, 0, false); } else { @@ -1086,7 +1098,20 @@ int GameObserver::cardClick(MTGCardInstance * card, int abilityType) return result; } -int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) +int GameObserver::cardClickLog(bool log, Player* clickedPlayer, MTGGameZone* zone, MTGCardInstance*backup, size_t index, int toReturn) +{ + if(log) + { + if (clickedPlayer) { + this->logAction(clickedPlayer); + } else if(zone) { + this->logAction(backup, zone, index, toReturn); + } + } + return toReturn; +} + +int GameObserver::cardClick(MTGCardInstance * card, Targetable * object, bool log) { Player * clickedPlayer = NULL; int toReturn = 0; @@ -1175,13 +1200,13 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) { MTGAbility * a = mLayers->actionLayer()->getAbility(card->paymenttype); toReturn = a->reactToClick(card); - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } reaction = mLayers->actionLayer()->isReactingToClick(card); if (reaction == -1) { toReturn = mLayers->actionLayer()->reactToClick(card); - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } } else @@ -1189,17 +1214,17 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) reaction = mLayers->actionLayer()->isReactingToTargetClick(object); if (reaction == -1) { toReturn = mLayers->actionLayer()->reactToTargetClick(object); - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } } if (!card) { toReturn = 0; - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } //Current player's hand - if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == Constants::MTG_PHASE_CLEANUP + if (currentPlayer->game->hand->hasCard(card) && currentGamePhase == MTG_PHASE_CLEANUP && currentPlayer->game->hand->nb_cards > currentPlayer->handsize && currentPlayer->nomaxhandsize == false) { WEvent * e = NEW WEventCardDiscard(currentPlayer->game->hand->cards[0]); @@ -1211,29 +1236,24 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object) if (reaction == 1) { toReturn = mLayers->actionLayer()->reactToClick(card); - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } else { mLayers->actionLayer()->setMenuObject(object); toReturn = 1; - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } } else if (card->isTapped() && card->controller() == currentPlayer) { toReturn = untap(card); - break; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } } while(0); - if (clickedPlayer) { - logAction(clickedPlayer); - } else if(zone) { - logAction(backup, zone, index, toReturn); - } - return toReturn; + return cardClickLog(log, clickedPlayer, zone, backup, index, toReturn); } int GameObserver::untap(MTGCardInstance * card) @@ -1357,7 +1377,7 @@ int GameObserver::targetListIsSet(MTGCardInstance * card) } -ostream& operator<<(ostream& out, GameObserver& g) +ostream& operator<<(ostream& out, const GameObserver& g) { if(g.startupGameSerialized == "") { @@ -1380,7 +1400,7 @@ ostream& operator<<(ostream& out, GameObserver& g) } out << "[do]" << endl; - list::iterator it; + list::const_iterator it; for(it = (g.actionsList.begin()); it != (g.actionsList.end()); it++) { @@ -1413,13 +1433,15 @@ bool GameObserver::parseLine(const string& s) return false; } -bool GameObserver::load(const string& ss, bool undo) +bool GameObserver::load(const string& ss, bool undo +#ifdef TESTSUITE + , TestSuiteGame* testgame +#endif + ) { int state = -1; string s; stringstream stream(ss); - string deckFile = "";//players[0]->deckFile; - string deckFileSmall = "";//players[0]->deckFileSmall; DebugTrace("Loading " + ss); randomGenerator.loadRandValues(""); @@ -1470,7 +1492,11 @@ bool GameObserver::load(const string& ss, bool undo) { if (s.find("mode=") == 0) { - createPlayer(s.substr(5)); + createPlayer(s.substr(5) + #ifdef TESTSUITE + , testgame + #endif //TESTSUITE + ); } } players[0]->parseLine(s); @@ -1487,7 +1513,11 @@ bool GameObserver::load(const string& ss, bool undo) { if (s.find("mode=") == 0) { - createPlayer(s.substr(5)); + createPlayer(s.substr(5) +#ifdef TESTSUITE + , testgame +#endif //TESTSUITE + ); } } players[1]->parseLine(s); @@ -1504,16 +1534,22 @@ bool GameObserver::load(const string& ss, bool undo) startedAt = time(0); // take a snapshot before processing the actions - startupGameSerialized = ""; - stringstream stream; - stream << *this; - startupGameSerialized = stream.str(); + resetStartupGame(); mRules->initGame(this); phaseRing->goToPhase(0, currentPlayer, false); phaseRing->goToPhase(currentGamePhase, currentPlayer); - processActions(undo); +#ifdef TESTSUITE + if(testgame) + testgame->initGame(); +#endif //TESTSUITE + + processActions(undo + #ifdef TESTSUITE + , testgame + #endif //TESTSUITE + ); } else { @@ -1526,7 +1562,11 @@ bool GameObserver::load(const string& ss, bool undo) return true; } -bool GameObserver::processActions(bool undo) +bool GameObserver::processActions(bool undo + #ifdef TESTSUITE + , TestSuiteGame* testgame + #endif + ) { bool result = false; size_t cmdIndex = 0; @@ -1545,6 +1585,19 @@ bool GameObserver::processActions(bool undo) if(loadingList.back().find("next") == string::npos) loadingList.pop_back(); } + + // We fake here cause the initialization before caused mana pool reset events to be triggered + // So, we need them flushed to be able to set the manapool to whatever we need + Update(counter); + counter += 1.000f; + +#ifdef TESTSUITE + if(testgame) + { + testgame->ResetManapools(); + } +#endif + for(loadingite = loadingList.begin(); loadingite != loadingList.end(); loadingite++, cmdIndex++) { string s = *loadingite; @@ -1552,21 +1605,14 @@ bool GameObserver::processActions(bool undo) if (s.find("p1") != string::npos) p = players[0]; - for (int i = 0; i<1; i++) - { - // let's fake an update - Update(counter); - counter += 1.000f; - } - MTGGameZone* zone = NULL; - if(s.find(p->game->hand->getName()) != string::npos) + if(s.find(string(p->game->hand->getName())+"[") != string::npos) zone = p->game->hand; - else if(s.find(p->game->battlefield->getName()) != string::npos) + else if(s.find(string(p->game->battlefield->getName())+"[") != string::npos) zone = p->game->battlefield; - else if(s.find(p->game->graveyard->getName()) != string::npos) + else if(s.find(string(p->game->graveyard->getName())+"[") != string::npos) zone = p->game->graveyard; - else if(s.find(p->game->library->getName()) != string::npos) + else if(s.find(string(p->game->library->getName())+"[") != string::npos) zone = p->game->library; if(zone) { @@ -1575,6 +1621,11 @@ bool GameObserver::processActions(bool undo) size_t index = atoi(s.substr(begin, size).c_str()); dumpAssert(index < zone->cards.size()); cardClick(zone->cards[index], zone->cards[index]); + } else if (s.find("stack") != string::npos) { + size_t begin = s.find("[")+1; + size_t size = s.find("]")-begin; + size_t index = atoi(s.substr(begin, size).c_str()); + stackObjectClicked((Interruptible*)mLayers->stackLayer()->getByIndex(index)); } else if (s.find("yes") != string::npos) { mLayers->stackLayer()->setIsInterrupting(p); } else if (s.find("no") != string::npos) { @@ -1583,10 +1634,13 @@ bool GameObserver::processActions(bool undo) mLayers->stackLayer()->endOfInterruption(); } else if (s.find("next") != string::npos) { userRequestNextGamePhase(); + } else if (s.find("combatok") != string::npos) { + mLayers->combatLayer()->clickOK(); + } else if (s == "p1" || s == "p2") { + cardClick(NULL, p); } else if (s.find("choice") != string::npos) { int choice = atoi(s.substr(s.find("choice ") + 7).c_str()); - //menuSelect(choice); - mLayers->actionLayer()->ButtonPressed(0, choice); + mLayers->actionLayer()->doReactTo(choice); } else if (s == "p1" || s == "p2") { cardClick(NULL, p); } else if(s.find("mulligan") != string::npos) { @@ -1601,7 +1655,7 @@ bool GameObserver::processActions(bool undo) size_t nb = actionsList.size(); - for (int i = 0; i<5; i++) + for (int i = 0; i<6; i++) { // let's fake an update Update(counter); @@ -1663,7 +1717,11 @@ void GameObserver::Mulligan(Player* player) player->takeMulligan(); } -void GameObserver::createPlayer(const string& playerMode) +void GameObserver::createPlayer(const string& playerMode + #ifdef TESTSUITE + , TestSuiteGame* testgame + #endif //TESTSUITE + ) { Player::Mode aMode = (Player::Mode)atoi(playerMode.c_str()); switch(aMode) @@ -1679,9 +1737,12 @@ void GameObserver::createPlayer(const string& playerMode) players.push_back(new HumanPlayer(this, "", "")); break; case Player::MODE_TEST_SUITE: - // FIXME, not real TestPlayer, but we don't care here. - players.push_back(new Player(this, "", "")); - players.back()->playMode = Player::MODE_TEST_SUITE; +#ifdef TESTSUITE + if(players.size()) + players.push_back(new TestSuiteAI(testgame, 1)); + else + players.push_back(new TestSuiteAI(testgame, 0)); +#endif //TESTSUITE break; } } diff --git a/projects/mtg/src/GameOptions.cpp b/projects/mtg/src/GameOptions.cpp index 2e5763f2f..e023835d9 100644 --- a/projects/mtg/src/GameOptions.cpp +++ b/projects/mtg/src/GameOptions.cpp @@ -141,46 +141,46 @@ int Options::optionInterrupt(int gamePhase) //Huge, nearly illegible switch block spread out to improve readability. switch (gamePhase) { - case Constants::MTG_PHASE_BEFORE_BEGIN: + case MTG_PHASE_BEFORE_BEGIN: return INTERRUPT_BEFOREBEGIN; - case Constants::MTG_PHASE_UNTAP: + case MTG_PHASE_UNTAP: return INTERRUPT_UNTAP; - case Constants::MTG_PHASE_UPKEEP: + case MTG_PHASE_UPKEEP: return INTERRUPT_UPKEEP; - case Constants::MTG_PHASE_DRAW: + case MTG_PHASE_DRAW: return INTERRUPT_DRAW; - case Constants::MTG_PHASE_FIRSTMAIN: + case MTG_PHASE_FIRSTMAIN: return INTERRUPT_FIRSTMAIN; - case Constants::MTG_PHASE_COMBATBEGIN: + case MTG_PHASE_COMBATBEGIN: return INTERRUPT_BEGINCOMBAT; - case Constants::MTG_PHASE_COMBATATTACKERS: + case MTG_PHASE_COMBATATTACKERS: return INTERRUPT_ATTACKERS; - case Constants::MTG_PHASE_COMBATBLOCKERS: + case MTG_PHASE_COMBATBLOCKERS: return INTERRUPT_BLOCKERS; - case Constants::MTG_PHASE_COMBATDAMAGE: + case MTG_PHASE_COMBATDAMAGE: return INTERRUPT_DAMAGE; - case Constants::MTG_PHASE_COMBATEND: + case MTG_PHASE_COMBATEND: return INTERRUPT_ENDCOMBAT; - case Constants::MTG_PHASE_SECONDMAIN: + case MTG_PHASE_SECONDMAIN: return INTERRUPT_SECONDMAIN; - case Constants::MTG_PHASE_ENDOFTURN: + case MTG_PHASE_ENDOFTURN: return INTERRUPT_ENDTURN; - case Constants::MTG_PHASE_CLEANUP: + case MTG_PHASE_CLEANUP: return INTERRUPT_CLEANUP; - case Constants::MTG_PHASE_AFTER_EOT: + case MTG_PHASE_AFTER_EOT: return INTERRUPT_AFTEREND; } diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 8aef5d085..bed9c2b69 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -492,7 +492,7 @@ void GameStateDuel::Update(float dt) int cardsinhand = game->currentPlayer->game->hand->nb_cards; //almosthumane - mulligan - if ((game->turn < 1) && (cardsinhand != 0) && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN + if ((game->turn < 1) && (cardsinhand != 0) && game->currentGamePhase == MTG_PHASE_FIRSTMAIN && game->currentPlayer->game->inPlay->nb_cards == 0 && game->currentPlayer->game->graveyard->nb_cards == 0 && game->currentPlayer->game->exile->nb_cards == 0 && game->currentlyActing() == (Player*)game->currentPlayer) //1st Play Check //IF there was no play at the moment automatically mulligan diff --git a/projects/mtg/src/GuiCombat.cpp b/projects/mtg/src/GuiCombat.cpp index 84a8e16e8..4ded97cf7 100644 --- a/projects/mtg/src/GuiCombat.cpp +++ b/projects/mtg/src/GuiCombat.cpp @@ -169,6 +169,7 @@ void GuiCombat::removeOne(DefenserDamaged* blocker, CombatStep step) bool GuiCombat::clickOK() { + observer->logAction(observer->currentlyActing(), "combatok"); active = activeAtk = NULL; cursor_pos = NONE; switch (step) @@ -179,7 +180,7 @@ bool GuiCombat::clickOK() return false; // that should not happen case ORDER: - observer->userRequestNextGamePhase(); + observer->userRequestNextGamePhase(true, false); return true; case FIRST_STRIKE: return false; @@ -581,7 +582,7 @@ int GuiCombat::receiveEventMinus(WEvent* e) } else if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATDAMAGE == event->to->id) + if (MTG_PHASE_COMBATDAMAGE == event->to->id) step = BLOCKERS; else cursor_pos = NONE; diff --git a/projects/mtg/src/GuiPlay.cpp b/projects/mtg/src/GuiPlay.cpp index 9e88603f3..208728cd4 100644 --- a/projects/mtg/src/GuiPlay.cpp +++ b/projects/mtg/src/GuiPlay.cpp @@ -399,7 +399,7 @@ int GuiPlay::receiveEventPlus(WEvent * e) } else if (WEventPhaseChange *event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATEND == event->to->id) + if (MTG_PHASE_COMBATEND == event->to->id) battleField.colorFlow = -1; } else if (dynamic_cast (e)) diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 950869da1..a0be2c69f 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -93,7 +93,7 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe case MTGAbility::AS_SORCERY: if (player != observer->currentPlayer) return 0; - if (cPhase != Constants::MTG_PHASE_FIRSTMAIN && cPhase != Constants::MTG_PHASE_SECONDMAIN) + if (cPhase != MTG_PHASE_FIRSTMAIN && cPhase != MTG_PHASE_SECONDMAIN) return 0; break; } @@ -101,19 +101,19 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe { if (player != observer->currentPlayer) return 0; - if (cPhase != checkPhaseBased - MTGAbility::MY_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != checkPhaseBased - MTGAbility::MY_BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } if (checkPhaseBased >= MTGAbility::OPPONENT_BEFORE_BEGIN && checkPhaseBased <= MTGAbility::OPPONENT_AFTER_EOT) { if (player == observer->currentPlayer) return 0; - if (cPhase != checkPhaseBased - MTGAbility::OPPONENT_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != checkPhaseBased - MTGAbility::OPPONENT_BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } if (checkPhaseBased >= MTGAbility::BEFORE_BEGIN && checkPhaseBased <= MTGAbility::AFTER_EOT) { - if (cPhase != checkPhaseBased - MTGAbility::BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != checkPhaseBased - MTGAbility::BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } @@ -251,19 +251,19 @@ int AbilityFactory::parseCastRestrictions(MTGCardInstance * card, Player * playe check = restriction[i].find("before battle damage"); if(check != string::npos) { - if(cPhase > Constants::MTG_PHASE_COMBATBLOCKERS) + if(cPhase > MTG_PHASE_COMBATBLOCKERS) return 0; } check = restriction[i].find("after battle"); if(check != string::npos) { - if(cPhase < Constants::MTG_PHASE_COMBATBLOCKERS) + if(cPhase < MTG_PHASE_COMBATBLOCKERS) return 0; } check = restriction[i].find("during battle"); if(check != string::npos) { - if(cPhase < Constants::MTG_PHASE_COMBATBEGIN ||cPhase > Constants::MTG_PHASE_COMBATEND ) + if(cPhase < MTG_PHASE_COMBATBEGIN ||cPhase > MTG_PHASE_COMBATEND ) return 0; } check = restriction[i].find("control snow land"); @@ -302,7 +302,7 @@ int AbilityFactory::parseRestriction(string s) size_t found = s.find(types[j]); if (found != string::npos) { - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { string toFind = types[j]; toFind.append(Constants::MTGPhaseCodeNames[i]).append("only"); @@ -679,7 +679,7 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int found = s.find("next"); if (found != string::npos) { - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { found = s.find(Constants::MTGPhaseCodeNames[i]); if (found != string::npos) @@ -693,7 +693,7 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int found = s.find("each"); if (found != string::npos) { - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { found = s.find(Constants::MTGPhaseCodeNames[i]); if (found != string::npos) @@ -2429,11 +2429,11 @@ MTGAbility * AbilityFactory::parseUpkeepAbility(string s,MTGCardInstance * card, size_t end = s.find("]", start); string s1 = s.substr(start + 1, end - start - 1); size_t seperator = s1.find(";"); - int phase = Constants::MTG_PHASE_UPKEEP; + int phase = MTG_PHASE_UPKEEP; int once = 0; if (seperator != string::npos) { - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { if (s1.find("next") != string::npos) once = 1; @@ -2477,8 +2477,8 @@ MTGAbility * AbilityFactory::parsePhaseActionAbility(string s,MTGCardInstance * return NULL; } string s1 = splitActions[1]; - int phase = Constants::MTG_PHASE_UPKEEP; - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + int phase = MTG_PHASE_UPKEEP; + for (int i = 0; i < NB_MTG_PHASES; i++) { string phaseStr = Constants::MTGPhaseCodeNames[i]; if (s1.find(phaseStr) != string::npos) @@ -3052,7 +3052,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) } case 1124: //Mana Vault (the rest is softcoded!) { - observer->addObserver(NEW ARegularLifeModifierAura(observer, _id + 2, card, card, Constants::MTG_PHASE_DRAW, -1, 1)); + observer->addObserver(NEW ARegularLifeModifierAura(observer, _id + 2, card, card, MTG_PHASE_DRAW, -1, 1)); break; } case 1215: //Power Leak @@ -3089,7 +3089,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) case 1139: //The Rack { - observer->addObserver(NEW ALifeZoneLink(observer, _id, card, Constants::MTG_PHASE_UPKEEP, -3)); + observer->addObserver(NEW ALifeZoneLink(observer, _id, card, MTG_PHASE_UPKEEP, -3)); break; } @@ -3678,7 +3678,7 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) case AS_SORCERY: if (player != game->currentPlayer) return 0; - if (cPhase != Constants::MTG_PHASE_FIRSTMAIN && cPhase != Constants::MTG_PHASE_SECONDMAIN) + if (cPhase != MTG_PHASE_FIRSTMAIN && cPhase != MTG_PHASE_SECONDMAIN) return 0; break; } @@ -3686,7 +3686,7 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { if (player != game->currentPlayer) return 0; - if (cPhase != restrictions - MY_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != restrictions - MY_BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } @@ -3694,13 +3694,13 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { if (player == game->currentPlayer) return 0; - if (cPhase != restrictions - OPPONENT_BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != restrictions - OPPONENT_BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } if (restrictions >= BEFORE_BEGIN && restrictions <= AFTER_EOT) { - if (cPhase != restrictions - BEFORE_BEGIN + Constants::MTG_PHASE_BEFORE_BEGIN) + if (cPhase != restrictions - BEFORE_BEGIN + MTG_PHASE_BEFORE_BEGIN) return 0; } limitPerTurn = 0; @@ -4126,8 +4126,8 @@ InstantAbility::InstantAbility(GameObserver* observer, int _id, MTGCardInstance //Instant abilities last generally until the end of the turn int InstantAbility::testDestroy() { - int newPhase = game->getCurrentGamePhase(); - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_AFTER_EOT) + GamePhase newPhase = game->getCurrentGamePhase(); + if (newPhase != currentPhase && newPhase == MTG_PHASE_AFTER_EOT) return 1; currentPhase = newPhase; return 0; @@ -4490,7 +4490,7 @@ void GenericTriggeredAbility::setTriggerTargets(Targetable * ta, MTGAbility * a) void GenericTriggeredAbility::Update(float dt) { - int newPhase = game->getCurrentGamePhase(); + GamePhase newPhase = game->getCurrentGamePhase(); t->newPhase = newPhase; TriggeredAbility::Update(dt); t->currentPhase = newPhase; diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 0d8087d69..839c5cbbb 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -794,7 +794,7 @@ int MTGCardInstance::removeBlocker(MTGCardInstance * blocker) // Blockers can be removed "manually" (by the blocking player) at the Blockers step, // Or "automatically" in the damage phase, when they die and regenerate (see http://code.google.com/p/wagic/issues/detail?id=563 ) // In the second case, we still want the card to be marked as "blocked" this turn - if (!blockers.size() && observer->currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) + if (!blockers.size() && observer->currentGamePhase == MTG_PHASE_COMBATBLOCKERS) { blocked = false; } @@ -1096,3 +1096,8 @@ std::ostream& operator<<(std::ostream& out, const MTGCardInstance& c) { return c.toString(out); } + +MTGCardInstance* MTGCardInstance::clone() +{ + return new MTGCardInstance(model, owner->game); +} diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 11b7790b8..5da7f3365 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -451,7 +451,7 @@ MTGCardInstance * MTGGameZone::removeCard(MTGCardInstance * card, int createCopy //card->lastController = card->controller(); if (createCopy) { - copy = NEW MTGCardInstance(card->model, card->owner->game); + copy = card->clone(); copy->previous = card; copy->view = card->view; copy->isToken = card->isToken; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index 3cbcaa36c..4f6490e61 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -290,7 +290,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if (!player->game->hand->hasCard(card)) return 0; if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[(int)Constants::LEYLINE]) - && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN + && game->currentGamePhase == MTG_PHASE_FIRSTMAIN && game->players[0]->game->graveyard->nb_cards == 0 && game->players[0]->game->exile->nb_cards == 0 ) @@ -313,7 +313,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->inPlay) == PlayRestriction::CANT_PLAY) return 0; if (player == currentPlayer - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN || game->currentGamePhase == MTG_PHASE_SECONDMAIN) ) { return 1; @@ -321,8 +321,8 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) } else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == MTG_PHASE_SECONDMAIN)) ) { @@ -644,15 +644,15 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->inPlay) == PlayRestriction::CANT_PLAY) return 0; if (player == currentPlayer - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == MTG_PHASE_SECONDMAIN) ) return 1; } else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == MTG_PHASE_SECONDMAIN)) ) { if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY) @@ -916,7 +916,7 @@ int MTGSuspendRule::receiveEvent(WEvent *e) { if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_UNTAP == event->from->id) + if (MTG_PHASE_UNTAP == event->from->id) { Player * p = game->currentPlayer; MTGGameZone * z = p->game->exile; @@ -1025,8 +1025,8 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) //note lands can morph too, this is different from other cost types. if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == MTG_PHASE_SECONDMAIN)) ) { if (game->currentActionPlayer->game->playRestrictions->canPutIntoZone(card, game->currentActionPlayer->game->stack) == PlayRestriction::CANT_PLAY) @@ -1152,7 +1152,7 @@ PermanentAbility(observer, _id) int MTGAttackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { - if (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && card->controller() == game->currentlyActing())//on my turn and when I am the acting player. + if (currentPhase == MTG_PHASE_COMBATATTACKERS && card->controller() == game->currentPlayer && card->controller() == game->currentlyActing())//on my turn and when I am the acting player. { if(card->isPhased) return 0; @@ -1168,7 +1168,7 @@ int MTGAttackRule::receiveEvent(WEvent *e) { if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) + if (MTG_PHASE_COMBATATTACKERS == event->from->id) { Player * p = game->currentPlayer; MTGGameZone * z = p->game->inPlay; @@ -1229,7 +1229,7 @@ int MTGCombatTriggersRule::receiveEvent(WEvent *e) { if (WEventPhaseChange* event = dynamic_cast(e)) { - if (Constants::MTG_PHASE_COMBATATTACKERS == event->from->id) + if (MTG_PHASE_COMBATATTACKERS == event->from->id) { Player * p = game->currentPlayer; MTGGameZone * z = p->game->inPlay; @@ -1242,7 +1242,7 @@ int MTGCombatTriggersRule::receiveEvent(WEvent *e) } } } - if (Constants::MTG_PHASE_COMBATEND == event->from->id) + if (MTG_PHASE_COMBATEND == event->from->id) { Player * p = game->currentPlayer->opponent(); MTGGameZone * z = p->game->inPlay; @@ -1368,7 +1368,7 @@ PermanentAbility(observer, _id) int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) { - if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting + if (currentPhase == MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() != game->currentPlayer ) { @@ -1451,8 +1451,8 @@ int MTGMomirRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) if (!player->game->hand->hasCard(card)) return 0; if (player == currentPlayer && !game->isInterrupting - && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN - || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN) + && (game->currentGamePhase == MTG_PHASE_FIRSTMAIN + || game->currentGamePhase == MTG_PHASE_SECONDMAIN) ) { return 1; @@ -1520,7 +1520,7 @@ int MTGMomirRule::genRandomCreatureId(int convertedCost) void MTGMomirRule::Update(float dt) { - if (newPhase != currentPhase && newPhase == Constants::MTG_PHASE_UNTAP) + if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) { alreadyplayed = 0; } @@ -1664,7 +1664,7 @@ PermanentAbility(observer, _id) int MTGHermitRule::receiveEvent(WEvent * event) { WEventPhaseChange * e = dynamic_cast(event); - if (e && e->from->id == Constants::MTG_PHASE_UNTAP) + if (e && e->from->id == MTG_PHASE_UNTAP) { MTGCardInstance * lcard = NULL; vectorlands = vector(); @@ -1921,7 +1921,7 @@ int MTGVampireRule::receiveEvent(WEvent * event) } else if (WEventPhaseChange * pe = dynamic_cast(event)) { - if( pe->from->id == Constants::MTG_PHASE_ENDOFTURN) + if( pe->from->id == MTG_PHASE_ENDOFTURN) { victims.clear(); } diff --git a/projects/mtg/src/PhaseRing.cpp b/projects/mtg/src/PhaseRing.cpp index 969981a31..f09bf858f 100644 --- a/projects/mtg/src/PhaseRing.cpp +++ b/projects/mtg/src/PhaseRing.cpp @@ -5,26 +5,26 @@ #include "Player.h" #include "WEvent.h" //Parses a string and gives phase numer -int PhaseRing::phaseStrToInt(string s) +GamePhase PhaseRing::phaseStrToInt(string s) { - if (s.compare("untap") == 0) return Constants::MTG_PHASE_UNTAP; - if (s.compare("upkeep") == 0) return Constants::MTG_PHASE_UPKEEP; - if (s.compare("draw") == 0) return Constants::MTG_PHASE_DRAW; - if (s.compare("firstmain") == 0) return Constants::MTG_PHASE_FIRSTMAIN; - if (s.compare("combatbegin") == 0) return Constants::MTG_PHASE_COMBATBEGIN; - if (s.compare("combatbegins") == 0) return Constants::MTG_PHASE_COMBATBEGIN; - if (s.compare("combatattackers") == 0) return Constants::MTG_PHASE_COMBATATTACKERS; - if (s.compare("combatblockers") == 0) return Constants::MTG_PHASE_COMBATBLOCKERS; - if (s.compare("combatdamage") == 0) return Constants::MTG_PHASE_COMBATDAMAGE; - if (s.compare("combatend") == 0) return Constants::MTG_PHASE_COMBATEND; - if (s.compare("combatends") == 0) return Constants::MTG_PHASE_COMBATEND; - if (s.compare("secondmain") == 0) return Constants::MTG_PHASE_SECONDMAIN; - if (s.compare("endofturn") == 0) return Constants::MTG_PHASE_ENDOFTURN; - if (s.compare("end") == 0) return Constants::MTG_PHASE_ENDOFTURN; - if (s.compare("cleanup") == 0) return Constants::MTG_PHASE_CLEANUP; + if (s.compare("untap") == 0) return MTG_PHASE_UNTAP; + if (s.compare("upkeep") == 0) return MTG_PHASE_UPKEEP; + if (s.compare("draw") == 0) return MTG_PHASE_DRAW; + if (s.compare("firstmain") == 0) return MTG_PHASE_FIRSTMAIN; + if (s.compare("combatbegin") == 0) return MTG_PHASE_COMBATBEGIN; + if (s.compare("combatbegins") == 0) return MTG_PHASE_COMBATBEGIN; + if (s.compare("combatattackers") == 0) return MTG_PHASE_COMBATATTACKERS; + if (s.compare("combatblockers") == 0) return MTG_PHASE_COMBATBLOCKERS; + if (s.compare("combatdamage") == 0) return MTG_PHASE_COMBATDAMAGE; + if (s.compare("combatend") == 0) return MTG_PHASE_COMBATEND; + if (s.compare("combatends") == 0) return MTG_PHASE_COMBATEND; + if (s.compare("secondmain") == 0) return MTG_PHASE_SECONDMAIN; + if (s.compare("endofturn") == 0) return MTG_PHASE_ENDOFTURN; + if (s.compare("end") == 0) return MTG_PHASE_ENDOFTURN; + if (s.compare("cleanup") == 0) return MTG_PHASE_CLEANUP; DebugTrace("PHASERING: Unknown Phase name: " << s); - return Constants::MTG_PHASE_FIRSTMAIN; + return MTG_PHASE_FIRSTMAIN; } /* Creates a New phase ring with the default rules */ @@ -35,21 +35,21 @@ PhaseRing::PhaseRing(GameObserver* observer) { if(observer->players[i]->phaseRing.size()) { - addPhase(NEW Phase(Constants::MTG_PHASE_BEFORE_BEGIN, observer->players[i])); + addPhase(NEW Phase(MTG_PHASE_BEFORE_BEGIN, observer->players[i])); vectorcustomRing = split(observer->players[i]->phaseRing,','); for (unsigned int k = 0;k < customRing.size(); k++) { - int customOrder = phaseStrToInt(customRing[k]); + GamePhase customOrder = phaseStrToInt(customRing[k]); Phase * phase = NEW Phase(customOrder, observer->players[i]); addPhase(phase); } - addPhase( NEW Phase(Constants::MTG_PHASE_AFTER_EOT, observer->players[i])); + addPhase( NEW Phase(MTG_PHASE_AFTER_EOT, observer->players[i])); } else { - for (int j = 0; j < Constants::NB_MTG_PHASES; j++) + for (int j = 0; j < NB_MTG_PHASES; j++) { - Phase * phase = NEW Phase(j, observer->players[i]); + Phase * phase = NEW Phase((GamePhase)j, observer->players[i]); addPhase(phase); } } @@ -70,7 +70,7 @@ PhaseRing::~PhaseRing() //Tells if next phase will be another Damage phase rather than combat ends bool PhaseRing::extraDamagePhase(int id) { - if (id != Constants::MTG_PHASE_COMBATEND) return false; + if (id != MTG_PHASE_COMBATEND) return false; if (observer->combatStep != END_FIRST_STRIKE) return false; for (int j = 0; j < 2; ++j) { @@ -135,7 +135,7 @@ int PhaseRing::addPhase(Phase * phase) return 1; } -int PhaseRing::addPhaseBefore(int id, Player* player, int after_id, Player * after_player, int allOccurences) +int PhaseRing::addPhaseBefore(GamePhase id, Player* player, int after_id, Player * after_player, int allOccurences) { int result = 0; list::iterator it; diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index d8555f495..e498e707c 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -12,7 +12,7 @@ #endif Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * deck) : - Damageable(observer, 20), mAvatarName(""), offerInterruptOnPhase(Constants::MTG_PHASE_DRAW) + Damageable(observer, 20), mAvatarName(""), offerInterruptOnPhase(MTG_PHASE_DRAW) { if(deck == NULL && file != "testsuite" && file != "remote" && file != "") deck = NEW MTGDeck(file.c_str(), MTGCollection()); @@ -290,7 +290,7 @@ bool Player::parseLine(const string& s) } else if (areaS.compare("offerinterruptonphase") == 0) { - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { string phaseStr = Constants::MTGPhaseCodeNames[i]; if (s.find(phaseStr) != string::npos) diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index f8ab9fa39..11e479114 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -105,7 +105,7 @@ RulesPlayerData::~RulesPlayerData() RulesState::RulesState() { - phase = Constants::MTG_PHASE_FIRSTMAIN; + phase = MTG_PHASE_FIRSTMAIN; player = 0; } @@ -228,7 +228,6 @@ void Rules::addExtraRules(GameObserver* g) } } } - } Player * Rules::loadPlayerMomir(GameObserver* observer, int isAI) diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index 62fb21f78..b5372df5d 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -80,6 +80,7 @@ int TestSuiteAI::Act(float dt) observer->gameOver = 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 + if (suite->currentAction == 0) { for (int i = 0; i < 2; ++ i) @@ -129,7 +130,7 @@ int TestSuiteAI::Act(float dt) if (action.compare("eot") == 0) { - if (observer->getCurrentGamePhase() != Constants::MTG_PHASE_CLEANUP) suite->currentAction--; + if (observer->getCurrentGamePhase() != MTG_PHASE_CLEANUP) suite->currentAction--; observer->userRequestNextGamePhase(); } else if (action.compare("human") == 0) @@ -151,7 +152,7 @@ int TestSuiteAI::Act(float dt) size_t found = action.find("goto "); string phase = action.substr(found + 5); int phaseToGo = 0; - for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + for (int i = 0; i < NB_MTG_PHASES; i++) { if (phase.find(Constants::MTGPhaseCodeNames[i]) != string::npos) { @@ -552,6 +553,7 @@ int TestSuite::loadNext() SAFE_DELETE(mWorkerThread.back()); mWorkerThread.pop_back(); } + size_t thread_count = 1; #ifdef QT_CONFIG thread_count = QThread::idealThreadCount(); @@ -762,6 +764,14 @@ void TestSuite::ThreadProc(void* inParam) while(!theGame.observer->gameOver) theGame.observer->Update(counter++); + + if(theGame.observer->mGameType != GAME_TYPE_MOMIR) + { + stringstream stream; + stream << *(theGame.observer); + theGame.observer->load(stream.str(), false, &theGame); + theGame.assertGame(); + } } } } @@ -794,13 +804,23 @@ TestSuiteGame::TestSuiteGame(TestSuite* testsuite, string _filename) isOK = load(); } +void TestSuiteGame::ResetManapools() +{ + for (int i = 0; i < 2; ++ i) + observer->players[i]->getManaPool()->copy(initState.players[i]->getManaPool()); +} + + void TestSuiteGame::initGame() { DebugTrace("TESTSUITE Init Game"); - observer->phaseRing->goToPhase(initState.phase, observer->players[0]); + observer->phaseRing->goToPhase(initState.phase, observer->players[0], false); observer->currentGamePhase = initState.phase; + + observer->resetStartupGame(); + for (int i = 0; i < 2; i++) - { + { AIPlayerBaka * p = (AIPlayerBaka *) (observer->players[i]); p->forceBestAbilityUse = forceAbility; p->life = initState.players[i]->life; diff --git a/projects/mtg/src/Token.cpp b/projects/mtg/src/Token.cpp index 9ce93fa85..1e9eeae50 100644 --- a/projects/mtg/src/Token.cpp +++ b/projects/mtg/src/Token.cpp @@ -34,3 +34,32 @@ Token::Token(int id) : name = "dummyToken"; setMTGId(id); } + +Token::Token(const Token& source) : + MTGCardInstance(source.model, source.owner->game) +{ + isToken = source.isToken; + tokenSource = source.tokenSource; + power = source.power; + toughness = source.toughness; + life = source.life; + lifeOrig = source.life; + origpower = source.origpower; + origtoughness = source.origpower; + rarity = source.rarity; + name = source.name; + setId = source.setId; + model = source.model; + data = source.data; + owner = source.owner; + belongs_to = source.belongs_to; + attacker = source.attacker; + defenser = source.defenser; + banding = source.banding; +} + + +MTGCardInstance* Token::clone() +{ + return new Token(*this); +} diff --git a/projects/mtg/src/utils.cpp b/projects/mtg/src/utils.cpp index 6bb96961c..49867087b 100644 --- a/projects/mtg/src/utils.cpp +++ b/projects/mtg/src/utils.cpp @@ -38,9 +38,9 @@ int RandomGenerator::random() return result; } -ostream& RandomGenerator::saveUsedRandValues(ostream& out) +ostream& RandomGenerator::saveUsedRandValues(ostream& out) const { - list::iterator ite; + list::const_iterator ite; for(ite=usedRandomValues.begin(); ite != usedRandomValues.end(); ite++) { out << *ite << ",";