diff --git a/projects/mtg/include/Damage.h b/projects/mtg/include/Damage.h index 13a9bdd24..e2118ceaa 100644 --- a/projects/mtg/include/Damage.h +++ b/projects/mtg/include/Damage.h @@ -39,6 +39,8 @@ public: virtual int poisoned(){return 0;} virtual int prevented(){return 0;} virtual JQuadPtr getIcon(){return JQuadPtr();} + + bool parseLine(const string& s); }; class Damage: public Interruptible diff --git a/projects/mtg/include/MTGGameZones.h b/projects/mtg/include/MTGGameZones.h index 55ea571c0..ab066c921 100644 --- a/projects/mtg/include/MTGGameZones.h +++ b/projects/mtg/include/MTGGameZones.h @@ -115,6 +115,7 @@ class MTGGameZone { bool needShuffle; virtual const char * getName(){return "zone";}; virtual ostream& toString(ostream&) const; + bool parseLine(const string& s); }; class MTGLibrary: public MTGGameZone { @@ -197,6 +198,7 @@ public: int isInPlay(MTGCardInstance * card); int isInGrave(MTGCardInstance * card); int isInZone(MTGCardInstance * card,MTGGameZone * zone); + bool parseLine(const string& s); }; ostream& operator<<(ostream&, const MTGGameZone&); diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index fc52150aa..239b90838 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -35,7 +35,7 @@ public: string deckFileSmall; string deckName; string phaseRing; - int offerInterruptOnPhase; + int offerInterruptOnPhase; Player(GameObserver *observer, string deckFile, string deckFileSmall, MTGDeck * deck = NULL); virtual ~Player(); virtual void setObserver(GameObserver*g); @@ -97,6 +97,7 @@ public: std::string GetCurrentDeckStatsFile(); friend istream& operator>>(istream& in, Player& p); + bool parseLine(const string& s); }; class HumanPlayer: public Player diff --git a/projects/mtg/src/Damage.cpp b/projects/mtg/src/Damage.cpp index debc9854c..5242824ca 100644 --- a/projects/mtg/src/Damage.cpp +++ b/projects/mtg/src/Damage.cpp @@ -308,6 +308,40 @@ ostream& operator<<(ostream& out, const Damageable& p) return out; } + +bool Damageable::parseLine(const string& s) +{ + size_t limiter = s.find("="); + if (limiter == string::npos) limiter = s.find(":"); + string areaS; + if (limiter != string::npos) + { + areaS = s.substr(0, limiter); + if (areaS.compare("life") == 0) + { + life = atoi((s.substr(limiter + 1)).c_str()); + } + else if (areaS.compare("poisoncount") == 0) + { + poisonCount = atoi((s.substr(limiter + 1)).c_str()); + } + else if (areaS.compare("damagecount") == 0) + { + damageCount = atoi((s.substr(limiter + 1)).c_str()); + } + else if (areaS.compare("preventable") == 0) + { + preventable = atoi((s.substr(limiter + 1)).c_str()); + } + else + { + return false; + } + } + + return true; +} + istream& operator>>(istream& in, Damageable& p) { string s; diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 82bec0b06..3354a8f63 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -1011,6 +1011,67 @@ ostream& operator<<(ostream& out, const MTGPlayerCards& z) return out; } +bool MTGGameZone::parseLine(const string& ss) +{ + bool result = false; + string s = ss; + + for (int i = 0; i < nb_cards; i++) + { + SAFE_DELETE( cards[i] ); + } + cards.clear(); + cardsMap.clear(); + + while(s.size()) + { + size_t limiter = s.find(","); + MTGCard * card = 0; + string toFind; + if (limiter != string::npos) + { + toFind = trim(s.substr(0, limiter)); + s = s.substr(limiter + 1); + } + else + { + toFind = trim(s); + s = ""; + } + + card = MTGCollection()->getCardByName(toFind); + int id = Rules::getMTGId(toFind); + + if (card) + { + /* For the moment we add the card directly in the final zone. + This is not the normal way and this prevents to resolve spells. + We'll need a fusion operation afterward to cast relevant spells */ + MTGCardInstance * newCard = NEW MTGCardInstance(card, owner->game); + addCard(newCard); + result = true; + } + else + { + if(toFind == "*") + nb_cards++; + else if ( id < 0 ) + { + // For the moment, we create a dummy Token to please the testsuite + Token* myToken = new Token(id); + addCard(myToken); + result = true; + } + else + { + DebugTrace("Card unfound " << toFind << " " << id); + } + } + } + + return result; +} + istream& operator>>(istream& in, MTGGameZone& z) { for (int i = 0; i < z.nb_cards; i++) @@ -1071,6 +1132,39 @@ istream& operator>>(istream& in, MTGGameZone& z) return in; } +bool MTGPlayerCards::parseLine(const string& s) +{ + size_t limiter = s.find("="); + if (limiter == string::npos) limiter = s.find(":"); + string areaS; + if (limiter != string::npos) + { + areaS = s.substr(0, limiter); + if (areaS.compare("graveyard") == 0) + { + graveyard->parseLine(s.substr(limiter+1)); + return true; + } + else if (areaS.compare("library") == 0) + { + library->parseLine(s.substr(limiter+1)); + return true; + } + else if (areaS.compare("hand") == 0) + { + hand->parseLine(s.substr(limiter+1)); + return true; + } + else if (areaS.compare("inplay") == 0 || areaS.compare("battlefield") == 0) + { + battlefield->parseLine(s.substr(limiter+1)); + return true; + } + } + + return false; +} + istream& operator>>(istream& in, MTGPlayerCards& z) { string s; diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index 2154dad3f..0e99f4db2 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -208,6 +208,60 @@ ostream& operator<<(ostream& out, const Player& p) return out << *(p.game); } +bool Player::parseLine(const string& s) +{ + if(((Damageable*)this)->parseLine(s)) + return true; + + size_t limiter = s.find("="); + if (limiter == string::npos) limiter = s.find(":"); + string areaS; + if (limiter != string::npos) + { + areaS = s.substr(0, limiter); + if (areaS.compare("manapool") == 0) + { + SAFE_DELETE(manaPool); + manaPool = new ManaPool(this); + ManaCost::parseManaCost(s.substr(limiter + 1), manaPool); + return true; + } + else if (areaS.compare("avatar") == 0) + { // We don't load directly for now + mAvatarName = s.substr(limiter + 1); + return true; + } + else if (areaS.compare("customphasering") == 0) + { + phaseRing = s.substr(limiter + 1); + return true; + } + else if (areaS.compare("offerinterruptonphase") == 0) + { + for (int i = 0; i < Constants::NB_MTG_PHASES; i++) + { + string phaseStr = Constants::MTGPhaseCodeNames[i]; + if (s.find(phaseStr) != string::npos) + { + offerInterruptOnPhase = PhaseRing::phaseStrToInt(phaseStr); + return true; + } + } + } + } + + if(!game) + { + game = new MTGPlayerCards(); + game->setOwner(this); + } + + if(game->parseLine(s)) + return true; + + return false; +} + istream& operator>>(istream& in, Player& p) { string s; @@ -215,6 +269,7 @@ istream& operator>>(istream& in, Player& p) in >> *((Damageable*)&p); + in.seekg(pos); while(std::getline(in, s)) { size_t limiter = s.find("="); diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index 72aedac26..e751b201a 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -111,9 +111,8 @@ RulesState::RulesState() void RulesState::parsePlayerState(int playerId, string s) { - stringstream stream(s); - streampos pos = stream.tellg(); - stream >> *(playerData[playerId].player); + if(playerData[playerId].player->parseLine(s)) + return; size_t limiter = s.find("="); if (limiter == string::npos) limiter = s.find(":"); diff --git a/projects/mtg/src/TestSuiteAI.cpp b/projects/mtg/src/TestSuiteAI.cpp index e6079b482..4076e137d 100644 --- a/projects/mtg/src/TestSuiteAI.cpp +++ b/projects/mtg/src/TestSuiteAI.cpp @@ -76,7 +76,7 @@ int TestSuiteAI::displayStack() int TestSuiteAI::Act(float dt) { - observer->gameOver = NULL; // Prevent draw rule from losing the game +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) @@ -261,8 +261,7 @@ TestSuiteState::TestSuiteState() void TestSuiteState::parsePlayerState(int playerId, string s) { - stringstream stream(s); - stream >> *players[playerId]; + players[playerId]->parseLine(s); }