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).

This commit is contained in:
Vittorio Alfieri
2021-01-22 14:15:43 +01:00
parent 3a38e7f4ab
commit 5184132e8b
11 changed files with 63 additions and 34 deletions

View File

@@ -43015,8 +43015,9 @@ type=Enchantment
[/card]
[card]
name=Shared Summons
aicode=activate target(<upto:2>creature[-share!name!]|mylibrary) moveto(myhand)
auto=name(search card) Reveal:type:*:mylibrary revealzone(mylibrary) optionone name(choose card) target(<upto:2>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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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<DeckMetaData *> 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<DeckMetaData *> 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<DeckMetaData *> 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<DeckMetaData *> BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0);
static vector<DeckMetaData *> 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<DeckMetaData *>
static void renderDeckMenu(SimpleMenu * _menu, const vector<DeckMetaData *>& deckMetaDataList);

View File

@@ -217,6 +217,7 @@ public:
map<int, int> cards;
string meta_desc;
string meta_name;
bool meta_commander;
vector<string> meta_AIHints;
vector<string> Sideboard;
vector<string> CommandZone;

View File

@@ -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;

View File

@@ -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<string> 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);

View File

@@ -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<DeckMetaData *> GameState::fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix,
Player * statsPlayer)
{
vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer);
renderDeckMenu(_menu, deckMetaDataVector);
return deckMetaDataVector;
}
vector<DeckMetaData *> GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix,
Player * statsPlayer, int maxDecks)
Player * statsPlayer, int maxDecks, GameType type)
{
vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks);
vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks, type);
renderDeckMenu(_menu, deckMetaDataVector);
return deckMetaDataVector;
}
vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks)
vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks, GameType type)
{
vector<DeckMetaData*> retList;
@@ -52,6 +42,11 @@ vector<DeckMetaData *> 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<int> unlockRequirements = meta->getUnlockRequirements();

View File

@@ -240,7 +240,7 @@ void GameStateDuel::Start()
GameStateDuel::selectedPlayerDeckId, true);
deckmenu->enableDisplayDetailsOverride();
DeckManager *deckManager = DeckManager::GetInstance();
vector<DeckMetaData *> playerDeckList = BuildDeckList(options.profileFile());
vector<DeckMetaData *> 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<DeckMetaData*> 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());

View File

@@ -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)

View File

@@ -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)