From 5184132e8bbbbfe9b0fc317b68be190b3315dc45 Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Fri, 22 Jan 2021 14:15:43 +0100 Subject: [PATCH] Fixed primitives, added "notshare!" keyword (e.g. to search cards with different names), improved decks selection according to chosen game mode (e.g. Game will show commander decks only in commander mode and it will hide them in other modes). --- .../bin/Res/sets/primitives/borderline.txt | 5 +++-- projects/mtg/include/CardDescriptor.h | 4 +++- projects/mtg/include/DeckMetaData.h | 4 ++-- projects/mtg/include/GameState.h | 9 +++----- projects/mtg/include/MTGDeck.h | 1 + projects/mtg/src/CardDescriptor.cpp | 21 +++++++++++++++++-- projects/mtg/src/DeckMetaData.cpp | 2 ++ projects/mtg/src/GameState.cpp | 21 +++++++------------ projects/mtg/src/GameStateDuel.cpp | 4 ++-- projects/mtg/src/MTGDeck.cpp | 8 +++++-- projects/mtg/src/TargetChooser.cpp | 18 ++++++++++++---- 11 files changed, 63 insertions(+), 34 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index d6f25cf56..8be760835 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -43015,8 +43015,9 @@ type=Enchantment [/card] [card] name=Shared Summons -aicode=activate target(creature[-share!name!]|mylibrary) moveto(myhand) -auto=name(search card) Reveal:type:*:mylibrary revealzone(mylibrary) optionone name(choose card) target(creature[-share!name!]|reveal) transforms((,newability[all(other *|reveal) moveto(mylibrary) and!(shuffle)!],newability[moveto(myhand)])) optiononeend optiontwo name(shuffle) bottomoflibrary target(<1>*|reveal) and!( all(*|reveal) bottomoflibrary and!(shuffle)! )! optiontwoend revealend +auto=if type(creature|mylibrary)~morethan~1 then choice name(Search 2 creatures) name(Search 2 creatures) target(creature|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( transforms((,newability[name(Search second creature) target(creature[notshare!name!]|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( ability$!name(Put in hand from library) name(Put in hand from library) target(<2>creature[fresh]|opponentlibrary) moveto(opponenthand) and!( shuffle opponent )! !$ opponent )! )!])) oneshot )! )! +auto=if type(creature|mylibrary)~morethan~0 then choice name(Search 1 creature) name(Search 1 creature) target(creature|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( transforms((,newability[ability$!name(Put in hand from library) name(Put in hand from library) target(creature[fresh]|opponentlibrary) moveto(opponenthand) and!( shuffle opponent )! !$ opponent])) oneshot )! )! +auto=if type(creature|mylibrary)~morethan~0 then choice name(Don't search) name(Don't search) donothing text=Search your library for up to two creature cards with different names, reveal them, put them into your hand, then shuffle your library. mana={3}{G}{G} type=Instant diff --git a/projects/mtg/include/CardDescriptor.h b/projects/mtg/include/CardDescriptor.h index cfa938204..020deaa72 100644 --- a/projects/mtg/include/CardDescriptor.h +++ b/projects/mtg/include/CardDescriptor.h @@ -30,7 +30,9 @@ class CardDescriptor: public MTGCardInstance public: enum Operator{ CD_OR = 1, - CD_AND = 2 + CD_AND = 2, + CD_NOR = 3, + CD_NAND = 4 }; Operator mode; diff --git a/projects/mtg/include/DeckMetaData.h b/projects/mtg/include/DeckMetaData.h index 22617648d..eaf3d2304 100644 --- a/projects/mtg/include/DeckMetaData.h +++ b/projects/mtg/include/DeckMetaData.h @@ -24,7 +24,7 @@ private: int mDeckId; string mAvatarFilename; string mColorIndex; - + // statistical information int mGamesPlayed, mVictories, mPercentVictories, mDifficulty; int getAvatarId(); @@ -33,7 +33,7 @@ private: public: - + bool isCommanderDeck; //Added to read the command tag in deck's metafile. DeckMetaData(const string& filename, bool isAI = false); void LoadDeck(); void LoadStats(); diff --git a/projects/mtg/include/GameState.h b/projects/mtg/include/GameState.h index aa21d870a..12fe48024 100644 --- a/projects/mtg/include/GameState.h +++ b/projects/mtg/include/GameState.h @@ -73,14 +73,11 @@ public: // it makes it easier to manipulate the deck information menus. // generate the Deck Meta Data and build the menu items of the menu given - static vector fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL); - - // generate the Deck Meta Data and build the menu items of the menu given - // Will display up to maxDecks if maxDecks is non 0,all decks in path otherwise - static vector fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0); + // Will display up to maxDecks if maxDecks is non 0,all decks in path otherwise and it will show or not commander decks according to the current game type + static vector fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0, GameType type = GAME_TYPE_CLASSIC); // build a vector of decks with the information passsed in. - static vector BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0); + static vector BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0, GameType type = GAME_TYPE_CLASSIC); // build menu items based on the vector static void renderDeckMenu(SimpleMenu * _menu, const vector& deckMetaDataList); diff --git a/projects/mtg/include/MTGDeck.h b/projects/mtg/include/MTGDeck.h index a49896207..609a72072 100644 --- a/projects/mtg/include/MTGDeck.h +++ b/projects/mtg/include/MTGDeck.h @@ -217,6 +217,7 @@ public: map cards; string meta_desc; string meta_name; + bool meta_commander; vector meta_AIHints; vector Sideboard; vector CommandZone; diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index e6e5f61b5..5b9ee2f17 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -172,8 +172,9 @@ MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card) return NULL; if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) return NULL; - if (nameComparisonMode && compareName != card->name) + if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name)) return NULL; + return card; } @@ -219,7 +220,7 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card) match = NULL; if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) match = NULL; - if(nameComparisonMode && compareName != card->name) + if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name)) match = NULL; return match; @@ -233,10 +234,26 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card) { match = match_and(card); } + else if (mode == CD_NAND) + { + match = match_and(card); + if(!match) + match = card; + else + match = NULL; + } else if (mode == CD_OR) { match = match_or(card); } + else if (mode == CD_NOR) + { + match = match_or(card); + if(!match) + match = card; + else + match = NULL; + } //Abilities BasicAbilitiesSet set = basicAbilities & card->basicAbilities; diff --git a/projects/mtg/src/DeckMetaData.cpp b/projects/mtg/src/DeckMetaData.cpp index b53b98008..eccf500c5 100644 --- a/projects/mtg/src/DeckMetaData.cpp +++ b/projects/mtg/src/DeckMetaData.cpp @@ -30,6 +30,7 @@ void DeckMetaData::LoadDeck() mName = trim(deck.meta_name); mDescription = trim(deck.meta_desc); mDeckId = atoi((mFilename.substr(mFilename.find("deck") + 4, mFilename.find(".txt"))).c_str()); + isCommanderDeck = deck.meta_commander; //Added to read the command tag in deck's metafile. vector requirements = split(deck.meta_unlockRequirements, ','); for(size_t i = 0; i < requirements.size(); ++i) @@ -64,6 +65,7 @@ void DeckMetaData::LoadStats() mGamesPlayed = 0; mColorIndex = ""; mDifficulty = 0; + isCommanderDeck = false; stats->load(mPlayerDeck); DeckStat * opponentDeckStats = stats->getDeckStat(mStatsFilename); diff --git a/projects/mtg/src/GameState.cpp b/projects/mtg/src/GameState.cpp index ff26683fc..1a82a18fc 100644 --- a/projects/mtg/src/GameState.cpp +++ b/projects/mtg/src/GameState.cpp @@ -14,27 +14,17 @@ // TODO: revise sorting strategy to allow other types of sorting. Currently, it is hardwired to use // sortByName to do the sorting. This was done since the menu item display is done in insertion order. -vector GameState::fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix, - Player * statsPlayer) -{ - - vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer); - renderDeckMenu(_menu, deckMetaDataVector); - - return deckMetaDataVector; -} - vector GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix, - Player * statsPlayer, int maxDecks) + Player * statsPlayer, int maxDecks, GameType type) { - vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks); + vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks, type); renderDeckMenu(_menu, deckMetaDataVector); return deckMetaDataVector; } -vector GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks) +vector GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks, GameType type) { vector retList; @@ -52,6 +42,11 @@ vector GameState::BuildDeckList(const string& path, const string if (meta) { found = 1; + if((meta->isCommanderDeck && type != GAME_TYPE_COMMANDER) || (!meta->isCommanderDeck && type == GAME_TYPE_COMMANDER)){ + meta = NULL; // It will show commander decks only in commander mode and it will hide them in other modes. + nbDecks++; + continue; + } //Check if the deck is unlocked based on sets etc... bool unlocked = true; vector unlockRequirements = meta->getUnlockRequirements(); diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 2acb98b5e..04415e9ac 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -240,7 +240,7 @@ void GameStateDuel::Start() GameStateDuel::selectedPlayerDeckId, true); deckmenu->enableDisplayDetailsOverride(); DeckManager *deckManager = DeckManager::GetInstance(); - vector playerDeckList = BuildDeckList(options.profileFile()); + vector playerDeckList = BuildDeckList(options.profileFile(), "", NULL, 0, mParent->gameType); int nbDecks = playerDeckList.size(); if (nbDecks) @@ -425,7 +425,7 @@ void GameStateDuel::ConstructOpponentMenu() DeckManager * deckManager = DeckManager::GetInstance(); vector opponentDeckList; - opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", game->getPlayer(0), nbUnlockedDecks); + opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", game->getPlayer(0), nbUnlockedDecks, mParent->gameType); deckManager->updateMetaDataList(&opponentDeckList, true); tournament->setAvailableDecks(opponentDeckList.size()); opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index f76abe87d..2c707e3a4 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -825,6 +825,7 @@ MTGDeck::MTGDeck(MTGAllCards * _allcards) database = _allcards; filename = ""; meta_name = ""; + meta_commander = false; } int MTGDeck::totalPrice() @@ -850,6 +851,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on size_t dot = filename.find("."); meta_name = filename.substr(slash + 1, dot - slash - 1); meta_id = atoi(meta_name.substr(4).c_str()); + meta_commander = false; std::string contents; if (JFileSystem::GetInstance()->readIntoString(config_file, contents)) { @@ -888,7 +890,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on continue; } found = s.find("SB:"); // Now it's possible to add cards to Sideboard even using their Name instead of ID such as normal deck cards. - if (found != string::npos) + if (found != string::npos && database) { s = s.substr(found + 3); s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); @@ -920,6 +922,8 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on found = s.find("CMD:"); // Now it's possible to add a card to Command Zone even using their Name instead of ID such as normal deck cards. if (found != string::npos) { + meta_commander = true; //Added to read the command tag in metafile. + if(!database) continue; s = s.substr(found + 4); s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); s.erase(0, s.find_first_not_of("\t\n\v\f\r ")); @@ -961,7 +965,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on } continue; } - if (meta_only) break; + if (meta_only) continue; //Changed from break in order to read the command tag in metafile. int numberOfCopies = 1; size_t found = s.find(" *"); if (found != string::npos) diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 02bfd61d8..e93f55de1 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -816,7 +816,10 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta else cd->compareName = card->name; - cd->nameComparisonMode = COMPARISON_EQUAL; + if (attribute.find("notshare!") != string::npos) + cd->nameComparisonMode = COMPARISON_UNEQUAL; + else + cd->nameComparisonMode = COMPARISON_EQUAL; } else if( CDtype.find("color") != string::npos ) { @@ -824,8 +827,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta cd->colors = card->target->colors; else cd->colors = card->colors; - - cd->mode = CardDescriptor::CD_OR; + + if (attribute.find("notshare!") != string::npos) + cd->mode = CardDescriptor::CD_NOR; + else + cd->mode = CardDescriptor::CD_OR; } else if( CDtype.find("types") != string::npos ) { @@ -853,7 +859,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta subt << card->getName() << "_DummyType_" << i; cd->setSubtype(subt.str()); // Fix to avoid type vector size is 0 causing the always true match issue. } - cd->mode = CardDescriptor::CD_OR; + + if (attribute.find("notshare!") != string::npos) + cd->mode = CardDescriptor::CD_NOR; + else + cd->mode = CardDescriptor::CD_OR; } } else if (attribute.find("counter") != string::npos)