diff --git a/projects/mtg/bin/Res/sets/mtg_todo.dat b/projects/mtg/bin/Res/sets/mtg_todo.dat index db365755f..2a37be3cb 100644 --- a/projects/mtg/bin/Res/sets/mtg_todo.dat +++ b/projects/mtg/bin/Res/sets/mtg_todo.dat @@ -16556,15 +16556,6 @@ power=1 toughness=1 [/card] [card] -name=Gwafa Hazid, Profiteer -text={W}{U}, {T}: Put a bribery counter on target creature you don't control. Its controller draws a card. -- Creatures with bribery counters on them can't attack or block. -mana={1}{W}{U} -type=Legendary Creature -subtype=Human Rogue -power=2 -toughness=2 -[/card] -[card] name=Gwyllion Hedge-Mage text=When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Plains, you may put a 1/1 white Kithkin Soldier creature token onto the battlefield. -- When Gwyllion Hedge-Mage enters the battlefield, if you control two or more Swamps, you may put a -1/-1 counter on target creature. mana={2}{WB} @@ -20960,15 +20951,6 @@ power=4 toughness=3 [/card] [card] -name=Kulrath Knight -text=Flying -- Wither (This deals damage to creatures in the form of -1/-1 counters.) -- Creatures your opponents control with counters on them can't attack or block. -mana={3}{BR}{BR} -type=Creature -subtype=Elemental Knight -power=3 -toughness=3 -[/card] -[card] name=Kumano's Blessing text=Flash -- Enchant creature -- If a creature dealt damage by enchanted creature this turn would be put into a graveyard, exile it instead. mana={2}{R} diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 91d586166..a6d7b2539 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -2281,6 +2281,21 @@ power=2 toughness=1 [/card] [card] +name=Aven Riftwatcher +abilities=flying +auto=counter(0/0,3,Time) +auto=life:2 +auto=@movedTo(this|exile,graveyard,hand,library) from(myBattlefield):life:2 +auto=@each my upkeep:counter(0/0,-1,Time) +auto=lord(aven riftwatcher[-counter{0/0.1.Time}]|myBattlefield) -99/-99 +text=Flying -- Vanishing 3 (This permanent enters the battlefield with three time counters on it. At the beginning of your upkeep, remove a time counter from it. When the last is removed, sacrifice it.) -- When Aven Riftwatcher enters the battlefield or leaves the battlefield, you gain 2 life. +mana={G} +type=Creature +subtype=Bird rebel Soldier +power=2 +toughness=3 +[/card] +[card] name=Aven Smokeweaver abilities=flying,protection from red text=Flying, protection from red @@ -16905,6 +16920,18 @@ mana={RG} type=Instant [/card] [card] +name=Gwafa Hazid, Profiteer +mana={1}{W}{U} +type=Creature +subtpe=Legendary Human Rogue +text={W}{U}, {T}: Put a bribery counter on target creature you don't control. Its controller draws a card. -- Creatures with bribery counters on them can't attack or block. +power=2 +toughness=2 +auto={W}{U}{T}:counter(0/0,1,Bribe) target(creature|opponentbattlefield) && draw:1 +auto=lord(creature[counter{0/0.1.Bribe}]) cantattack +auto=lord(creature[counter{0/0.1.Bribe}]) cantblock +[/card] +[card] name=Gwendlyn Di Corci auto={T}:discard:1 target(player) myTurnOnly text={T}: Target player discards a card at random. Activate this ability only during your turn. @@ -21548,6 +21575,18 @@ type=Enchantment subtype=Aura [/card] [card] +name=Kulrath Knight +mana={3}{BR}{BR} +power=3 +toughness=3 +type=Creature +subtype=Elemental Knight +abilities=flying,wither +text=Flying -- Wither (This deals damage to creatures in the form of -1/-1 counters.) -- Creatures your opponents control with counters on them can't attack or block. +auto=lord(creature[counter{any}]|opponentbattlefield) cantattack +auto=lord(creature[counter{any}]|opponentbattlefield) cantblock +[/card] +[card] name=Kurgadon auto=@movedTo(creature[manacost>=6]|mystack):counter(1/1,3) text=Whenever you cast a creature spell with converted mana cost 6 or more, put three +1/+1 counters on Kurgadon. diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 046788002..6279ab559 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -31,6 +31,8 @@ generic/kicker.txt generic/kicker2.txt generic/landwalk.txt generic/legendary.txt +generic/lord_counter.txt +generic/lord_counter_any.txt generic/lifelink.txt generic/m10_blockers.txt generic/m10_blockers2.txt @@ -101,6 +103,8 @@ ashen_firebeast.txt ashen_firebeast2.txt aura_mutation.txt avarice_totem.txt +aven_riftwatcher.txt +aven_riftwatcher2.txt aysen_bureaucrats.txt balduvian_conjurer.txt baneslayer_angel.txt diff --git a/projects/mtg/bin/Res/test/aven_riftwatcher.txt b/projects/mtg/bin/Res/test/aven_riftwatcher.txt new file mode 100644 index 000000000..537e31133 --- /dev/null +++ b/projects/mtg/bin/Res/test/aven_riftwatcher.txt @@ -0,0 +1,22 @@ +[INIT] +FIRSTMAIN +[PLAYER1] +hand:Aven Riftwatcher +manapool:{2}{W} +[PLAYER2] +[DO] +aven riftwatcher +eot +eot +eot +eot +eot +eot +eot +[ASSERT] +untap +[PLAYER1] +graveyard:Aven Riftwatcher +life:24 +[PLAYER2] +[END] diff --git a/projects/mtg/bin/Res/test/aven_riftwatcher2.txt b/projects/mtg/bin/Res/test/aven_riftwatcher2.txt new file mode 100644 index 000000000..9fd8d9d7e --- /dev/null +++ b/projects/mtg/bin/Res/test/aven_riftwatcher2.txt @@ -0,0 +1,16 @@ +[INIT] +FIRSTMAIN +[PLAYER1] +hand:Aven Riftwatcher +manapool:{2}{W} +[PLAYER2] +[DO] +aven riftwatcher +eot +[ASSERT] +untap +[PLAYER1] +inplay:Aven Riftwatcher +life:22 +[PLAYER2] +[END] diff --git a/projects/mtg/bin/Res/test/generic/lord_counter.txt b/projects/mtg/bin/Res/test/generic/lord_counter.txt new file mode 100644 index 000000000..7bbc0a67a --- /dev/null +++ b/projects/mtg/bin/Res/test/generic/lord_counter.txt @@ -0,0 +1,28 @@ +[INIT] +firstmain +[PLAYER1] +inplay:185811 +manapool:{W}{U} +[PLAYER2] +inplay:Shivan Dragon +library:Forest,Island +[DO] +185811 +Shivan Dragon +eot +next +next +next +next +next +Shivan Dragon +eot +[ASSERT] +untap +[PLAYER1] +inplay:185811 +life:20 +[PLAYER2] +inplay:Shivan Dragon +hand:Forest,Island +[END] diff --git a/projects/mtg/bin/Res/test/generic/lord_counter_any.txt b/projects/mtg/bin/Res/test/generic/lord_counter_any.txt new file mode 100644 index 000000000..b70236404 --- /dev/null +++ b/projects/mtg/bin/Res/test/generic/lord_counter_any.txt @@ -0,0 +1,29 @@ +[INIT] +MAINPHASE +[PLAYER1] +inplay:Kulrath Knight,Cinderbones +[PLAYER2] +inplay:Shivan Dragon +[DO] +next +next +Cinderbones +next +Shivan Dragon +eot +next +next +next +next +next +Shivan Dragon +eot +[ASSERT] +UNTAP +[PLAYER1] +graveyard:Cinderbones +inplay:Kulrath Knight +life:20 +[PLAYER2] +inplay:Shivan Dragon +[END] diff --git a/projects/mtg/bin/daily_build/template.exe b/projects/mtg/bin/daily_build/template.exe index 37daadca1..94975aa64 100644 Binary files a/projects/mtg/bin/daily_build/template.exe and b/projects/mtg/bin/daily_build/template.exe differ diff --git a/projects/mtg/include/CardDescriptor.h b/projects/mtg/include/CardDescriptor.h index 34e1eb1cd..6c67c7804 100644 --- a/projects/mtg/include/CardDescriptor.h +++ b/projects/mtg/include/CardDescriptor.h @@ -7,6 +7,7 @@ #include "MTGCardInstance.h" #include "MTGGameZones.h" +#include "Counters.h" #define CD_OR 1 #define CD_AND 2 @@ -32,11 +33,17 @@ class CardDescriptor: public MTGCardInstance{ int powerComparisonMode; int toughnessComparisonMode; int manacostComparisonMode; + int counterComparisonMode; int convertedManacost; // might fit better into MTGCardInstance? + int anyCounter; int init(); CardDescriptor(); void unsecureSetTapped(int i); void setNegativeSubtype( string value); + int counterPower; + int counterToughness; + int counterNB; + string counterName; MTGCardInstance * match(MTGCardInstance * card); MTGCardInstance * match(MTGGameZone * zone); MTGCardInstance * nextmatch(MTGGameZone * zone, MTGCardInstance * previous); diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index da8767fd4..209541f88 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -12,6 +12,7 @@ class MTGGameZone; class Player; class AManaProducer; class WEvent; +class Counter; #include "../include/GameObserver.h" #include "ActionElement.h" @@ -255,6 +256,7 @@ class AbilityFactory{ TriggeredAbility * parseTrigger(string s, int id, Spell * spell, MTGCardInstance *card, Targetable * target); int parseRestriction(string s); public: + Counter * parseCounter(string s, MTGCardInstance * target); int parsePowerToughness(string s, int *power, int *toughness); int getAbilities(vector * v, Spell * spell, MTGCardInstance * card = NULL, int id = 0,MTGGameZone * dest = NULL); MTGAbility * parseMagicLine(string s, int id, Spell * spell, MTGCardInstance *card, int activated = 0, int forceUEOT = 0,MTGGameZone * dest = NULL); diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index 4a5f4283a..e5e4be303 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -6,10 +6,15 @@ CardDescriptor::CardDescriptor(): MTGCardInstance(){ init(); + counterName = ""; + counterPower = 0; + counterToughness = 0; + counterNB = 0; mode = CD_AND; powerComparisonMode = COMPARISON_NONE; toughnessComparisonMode = COMPARISON_NONE; manacostComparisonMode = COMPARISON_NONE; + counterComparisonMode = COMPARISON_NONE; convertedManacost = -1; } @@ -18,6 +23,7 @@ int CardDescriptor::init(){ attacker = 0; defenser = NULL; banding = NULL; + anyCounter = 0; //Remove unnecessary pointers SAFE_DELETE(counters); SAFE_DELETE(previous); @@ -134,7 +140,7 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card){ } - + //Abilities for(map::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it){ @@ -175,6 +181,27 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card){ } } + //Counters + if (anyCounter) { + if (!(card->counters->mCount)) { + match = NULL; + }else{ + int hasCounter = 0; + for (int i = 0; i < card->counters->mCount; i++) { + if (card->counters->counters[i]->nb > 0) hasCounter = 1; + } + if (!hasCounter) match = NULL; + } + }else{ + if (counterComparisonMode) { + Counter * targetCounter = card->counters->hasCounter(counterName.c_str(),counterPower,counterToughness); + if (targetCounter) { + if (!valueInRange(counterComparisonMode,targetCounter->nb,counterNB)) match = NULL; + } else { + if (counterComparisonMode != COMPARISON_LESS && counterComparisonMode != COMPARISON_AT_MOST) match = NULL; + } + } + } return match; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index a179501df..670391a38 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -35,6 +35,34 @@ int AbilityFactory::countCards(TargetChooser * tc, Player * player, int option){ return result; } +Counter * AbilityFactory::parseCounter(string s, MTGCardInstance * target) { + int nb = 1; + string name = ""; + size_t start = s.find("(") + 1; + size_t end = s.find(")", start); + size_t separator = s.find(",", start); + if (separator == string::npos) separator = s.find(".", start); + if (separator != string::npos){ + size_t separator2 = s.find(",", separator+1); + if (separator2 == string::npos) separator2 = s.find(".", separator+1); + if (separator2 != string::npos) { + name = s.substr(separator2+1,end-separator2-1); + } + string nbstr = s.substr(separator+1,separator2-separator-1); + nb = atoi(nbstr.c_str()); + end = separator; + } + + string spt = s.substr(start,end-start); + int power, toughness; + if ( parsePowerToughness(spt,&power, &toughness)){ + Counter * counter = NEW Counter(target,name.c_str(),power,toughness); + counter->nb = nb; + return counter; + } + return NULL; +} + int AbilityFactory::parsePowerToughness(string s, int *power, int *toughness){ size_t found = s.find("/"); if (found != string::npos){ @@ -700,25 +728,12 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG //counter found = s.find("counter("); if (found != string::npos){ - found+=8; - int nb = 1; - string name = ""; - size_t end = s.find(")", found); - size_t separator = s.find(",", found); - if (separator != string::npos){ - size_t separator2 = s.find(",", separator+1); - if (separator2 != string::npos) { - name = s.substr(separator2+1,end-separator2-1); - } - string nbstr = s.substr(separator+1,separator2-separator-1); - nb = atoi(nbstr.c_str()); - end = separator; - } - - string spt = s.substr(found,end-found); - int power, toughness; - if ( parsePowerToughness(spt,&power, &toughness)){ - MTGAbility * a = NEW AACounter(id,card,target,name.c_str(),power,toughness,nb); + size_t start = s.find("("); + size_t end = s.find(")"); + string counterString = s.substr(start,end-start+1); + Counter * counter = parseCounter(counterString,target); + if (counter){ + MTGAbility * a = NEW AACounter(id,card,target,counter->name.c_str(),counter->power,counter->toughness,counter->nb); a->oneShot = 1; return a; } diff --git a/projects/mtg/src/ManaCost.cpp b/projects/mtg/src/ManaCost.cpp index 67ec21d32..6ae2c4f22 100644 --- a/projects/mtg/src/ManaCost.cpp +++ b/projects/mtg/src/ManaCost.cpp @@ -69,29 +69,14 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan //Counters OutputDebugString("Counter\n"); size_t counter_start = value.find("("); - int nb = 1; - string name = ""; size_t counter_end = value.find(")", counter_start); - size_t end = value.find(")", counter_start); - size_t separator = value.find(",", counter_start); + AbilityFactory * abf = NEW AbilityFactory(); + string counterString = value.substr(counter_start,counter_end-counter_start); + Counter * counter = abf->parseCounter(counterString,c); + size_t separator = value.find(",",counter_start); size_t separator2 = string::npos; - if (separator != string::npos){ - separator2 = value.find(",", separator+1); - if (separator2 != string::npos) { - name = value.substr(separator2+1,counter_end-separator2-1); - } - string nbstr = value.substr(separator+1,separator2-separator-1); - nb = atoi(nbstr.c_str()); - counter_end = separator; - } - - string spt = value.substr(counter_start+1,counter_end-counter_start-1); - int power, toughness; - Counter * counter = NULL; - AbilityFactory abf; - if ( abf.parsePowerToughness(spt,&power, &toughness)){ - counter = NEW Counter(c,name.c_str(),power,toughness); - counter->nb = nb; + if (separator != string::npos) { + separator2 = value.find(",",separator + 1); } TargetChooserFactory tcf; TargetChooser * tc = NULL; @@ -99,7 +84,7 @@ ManaCost * ManaCost::parseManaCost(string s, ManaCost * _manaCost, MTGCardInstan if (separator2 != string::npos) { target_start = value.find(",",separator2+1); } - size_t target_end = end; + size_t target_end = counter_end; if (target_start!=string::npos && target_end!=string::npos){ string target = value.substr(target_start+1, target_end-1 - target_start); tc = tcf.createTargetChooser(target,c); diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 0187175e0..d48e8a780 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -4,6 +4,7 @@ #include "../include/MTGGameZones.h" #include "../include/GameObserver.h" #include "../include/Subtypes.h" +#include "../include/Counters.h" @@ -196,6 +197,30 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta }else if (attribute.find("manacost") != string::npos){ cd->convertedManacost = comparisonCriterion; cd->manacostComparisonMode = comparisonMode; + //Counter Restrictions + }else if (attribute.find("counter") != string::npos) { + if (attribute.find("{any}") != string::npos) { + cd->anyCounter = 1; + }else{ + size_t start = attribute.find("{"); + size_t end = attribute.find("}"); + string counterString = attribute.substr(start,end-start+1); + counterString.replace(0,1,"("); + counterString.replace(counterString.length() - 1,1,")"); + AbilityFactory * abf = NEW AbilityFactory(); + Counter * counter = abf->parseCounter(counterString,card); + if (counter) { + cd->counterName = counter->name; + cd->counterNB = counter->nb; + cd->counterPower = counter->power; + cd->counterToughness = counter->toughness; + } + if (minus) { + cd->counterComparisonMode = COMPARISON_LESS; + }else{ + cd->counterComparisonMode = COMPARISON_AT_MOST; + } + } }else{ int attributefound = 0; //Colors