diff --git a/projects/mtg/bin/Res/sets/LRW/_cards.dat b/projects/mtg/bin/Res/sets/LRW/_cards.dat index d5f445567..f19235e63 100644 --- a/projects/mtg/bin/Res/sets/LRW/_cards.dat +++ b/projects/mtg/bin/Res/sets/LRW/_cards.dat @@ -838,7 +838,7 @@ subtype=Aura [/card] [card] text=Whenever another nontoken Elf is put into your graveyard from play, you may put a 1/1 green Elf Warrior creature token into play. -auto=@movedTo(elf[-token]|graveyard):may token(Elf Warrior,creature elf warrior,1/1,green) +auto=@movedTo(other elf|graveyard) from(battlefield):may token(Elf Warrior,creature elf warrior,1/1,green) id=146167 name=Prowess of the Fair rarity=U diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 60944f0c0..4c7a4b1be 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -154,6 +154,9 @@ paralysis2.txt persuasion.txt plague_rats.txt protomatter_powder.txt +prowess_of_the_fair.txt +prowess_of_the_fair2.txt +prowess_of_the_fair3.txt pygmy_troll.txt pyroclasm.txt rampant_growth.txt diff --git a/projects/mtg/bin/Res/test/prowess_of_the_fair.txt b/projects/mtg/bin/Res/test/prowess_of_the_fair.txt new file mode 100644 index 000000000..1c68f304c --- /dev/null +++ b/projects/mtg/bin/Res/test/prowess_of_the_fair.txt @@ -0,0 +1,21 @@ +#Bug:Prowess of the fair works even when a card is dicarded from hand +[INIT] +FIRSTMAIN +[PLAYER1] +hand:Specter's Wail +manapool:{1}{B} +[PLAYER2] +inplay:prowess of the fair +hand:llanowar elves +[DO] +Specter's Wail +p2 +choice 0 +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:Specter's Wail +[PLAYER2] +graveyard:llanowar elves +inplay:prowess of the fair +[END] \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/prowess_of_the_fair2.txt b/projects/mtg/bin/Res/test/prowess_of_the_fair2.txt new file mode 100644 index 000000000..ea62fb545 --- /dev/null +++ b/projects/mtg/bin/Res/test/prowess_of_the_fair2.txt @@ -0,0 +1,20 @@ +#Prowess of the fair +[INIT] +FIRSTMAIN +[PLAYER1] +hand:shock +manapool:{R} +[PLAYER2] +inplay:prowess of the fair,llanowar elves +[DO] +shock +llanowar elves +choice 0 +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:shock +[PLAYER2] +graveyard:llanowar elves +inplay:prowess of the fair,* +[END] \ No newline at end of file diff --git a/projects/mtg/bin/Res/test/prowess_of_the_fair3.txt b/projects/mtg/bin/Res/test/prowess_of_the_fair3.txt new file mode 100644 index 000000000..1be839f9c --- /dev/null +++ b/projects/mtg/bin/Res/test/prowess_of_the_fair3.txt @@ -0,0 +1,19 @@ +#Prowess of the fair disenchanted: shouldn't trigger its ability +[INIT] +FIRSTMAIN +[PLAYER1] +hand:disenchant +manapool:{1}{W} +[PLAYER2] +inplay:prowess of the fair +[DO] +disenchant +prowess of the fair +choice 0 +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:disenchant +[PLAYER2] +graveyard:prowess of the fair +[END] \ No newline at end of file diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index aa4d21675..e8dd889df 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -25,6 +25,7 @@ class CardDescriptor; class TargetChooser: public TargetsList { protected: int forceTargetListReady; + bool other; public: enum{ @@ -35,10 +36,11 @@ class TargetChooser: public TargetsList { }; - TargetChooser(MTGCardInstance * card = NULL, int _maxtargets = -1); + TargetChooser(MTGCardInstance * card = NULL, int _maxtargets = -1, bool other = false); MTGCardInstance * source; MTGCardInstance * targetter; //Optional, usually equals source, used for protection from... + int maxtargets; //Set to -1 for "unlimited" virtual int targetsZone(MTGGameZone * z){return 0;}; int ForceTargetListReady(); @@ -67,8 +69,8 @@ class TargetZoneChooser:public TargetChooser{ int nbzones; int init(int * _zones, int _nbzones); int targetsZone(MTGGameZone * z); - TargetZoneChooser(MTGCardInstance * card = NULL, int _maxtargets = 1); - TargetZoneChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1); + TargetZoneChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); + TargetZoneChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * _card); }; @@ -85,8 +87,8 @@ class CreatureTargetChooser:public TargetZoneChooser{ public: int maxpower; int maxtoughness; - CreatureTargetChooser(int * _zones, int _nbzones,MTGCardInstance * card = NULL, int _maxtargets = 1); - CreatureTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1); + CreatureTargetChooser(int * _zones, int _nbzones,MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); + CreatureTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * _card); }; @@ -94,8 +96,8 @@ class CreatureTargetChooser:public TargetZoneChooser{ class DamageableTargetChooser:public CreatureTargetChooser{ public: - DamageableTargetChooser(int * _zones, int _nbzones,MTGCardInstance * card = NULL, int _maxtargets = 1):CreatureTargetChooser( _zones,_nbzones, card, _maxtargets){}; - DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1):CreatureTargetChooser(card, _maxtargets){}; + DamageableTargetChooser(int * _zones, int _nbzones,MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false):CreatureTargetChooser( _zones,_nbzones, card, _maxtargets,other){}; + DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false):CreatureTargetChooser(card, _maxtargets,other){}; virtual bool canTarget(Targetable * target); }; @@ -112,8 +114,8 @@ class TypeTargetChooser:public TargetZoneChooser{ public: int nbtypes; int types[10]; - TypeTargetChooser(const char * _type, MTGCardInstance * card = NULL, int _maxtargets = 1); - TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1); + TypeTargetChooser(const char * _type, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); + TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); void addType(int type); void addType(const char * type); virtual bool canTarget(Targetable * targe); @@ -122,8 +124,8 @@ class TypeTargetChooser:public TargetZoneChooser{ class DescriptorTargetChooser:public TargetZoneChooser{ public: CardDescriptor * cd; - DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card = NULL, int _maxtargets = 1); - DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1); + DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); + DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * target); ~DescriptorTargetChooser(); }; @@ -132,14 +134,14 @@ class DescriptorTargetChooser:public TargetZoneChooser{ class SpellTargetChooser:public TargetChooser{ public: int color; - SpellTargetChooser( MTGCardInstance * card = NULL,int _color = -1, int _maxtargets = 1 ); + SpellTargetChooser( MTGCardInstance * card = NULL,int _color = -1, int _maxtargets = 1 , bool other = false); virtual bool canTarget(Targetable * target); }; class SpellOrPermanentTargetChooser:public TargetZoneChooser{ public: int color; - SpellOrPermanentTargetChooser(MTGCardInstance * card = NULL,int _color = -1 , int _maxtargets = 1); + SpellOrPermanentTargetChooser(MTGCardInstance * card = NULL,int _color = -1 , int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * target); }; @@ -156,7 +158,7 @@ class DamageTargetChooser:public TargetChooser{ class DamageOrPermanentTargetChooser:public TargetZoneChooser{ public: int color; - DamageOrPermanentTargetChooser(MTGCardInstance * card = NULL,int _color = -1 , int _maxtargets = 1); + DamageOrPermanentTargetChooser(MTGCardInstance * card = NULL,int _color = -1 , int _maxtargets = 1, bool other = false); virtual bool canTarget(Targetable * target); }; #endif diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 0db43d182..d4e6c4e93 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -12,7 +12,14 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta int zones[10]; int nbzones = 0; - unsigned int found; + size_t found; + bool other = false; + + found = s.find("other "); + if (found == 0){ + other = true; + s=s.substr(6); + } found = s.find("player"); if (found != string::npos){ @@ -20,7 +27,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta unsigned int several = s.find_first_of('s',5); if (several != string::npos) maxtargets = -1; found = s.find("creature"); - if (found != string::npos) return NEW DamageableTargetChooser(card,maxtargets); //Any Damageable target (player, creature) + if (found != string::npos) return NEW DamageableTargetChooser(card,maxtargets,other); //Any Damageable target (player, creature) return NEW PlayerTargetChooser(card,maxtargets); //Any player } @@ -177,7 +184,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta if (!tc){ if (typeName.compare("*")!=0) cd->setSubtype(typeName); - tc = NEW DescriptorTargetChooser(cd,zones,nbzones,card,maxtargets); + tc = NEW DescriptorTargetChooser(cd,zones,nbzones,card,maxtargets,other); }else{ delete(cd); return NULL; @@ -185,11 +192,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta }else{ if (!tc){ if (typeName.compare("*")==0){ - return NEW TargetZoneChooser(zones, nbzones,card, maxtargets); + return NEW TargetZoneChooser(zones, nbzones,card, maxtargets,other); }else if (typeName.compare("this")==0){ return NEW CardTargetChooser(card,card,zones, nbzones); }else{ - tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets); + tc = NEW TypeTargetChooser(typeName.c_str(), zones, nbzones, card,maxtargets,other); } }else{ ((TypeTargetChooser *)tc)->addType(typeName.c_str()); @@ -251,11 +258,12 @@ TargetChooser * TargetChooserFactory::createTargetChooser(MTGCardInstance * card } -TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets): TargetsList(){ +TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets, bool _other): TargetsList(){ forceTargetListReady = 0; source = card; targetter = card; maxtargets = _maxtargets; + other = _other; } //Default targetter : every card can be targetted, unless it is protected from the targetter card @@ -263,6 +271,13 @@ TargetChooser::TargetChooser(MTGCardInstance * card, int _maxtargets): TargetsLi bool TargetChooser::canTarget(Targetable * target){ if (target->typeAsTarget() == TARGET_CARD){ MTGCardInstance * card = (MTGCardInstance *) target; + if (other){ + MTGCardInstance * tempcard = card; + while (tempcard) { + if (tempcard == source) return false; + tempcard = tempcard->previous; + } + } if (source && targetter && card->isInPlay() && (card->has(Constants::SHROUD)|| card->protectedAgainst(targetter) )) return false; if (source && targetter && card->isInPlay() && (targetter->controller() != card->controller()) && (card->has(Constants::OPPONENTSHROUD) || card->protectedAgainst(targetter))) return false; return true; @@ -342,7 +357,7 @@ bool CardTargetChooser::canTarget(Targetable * target ){ /** Choose anything that has a given list of types **/ -TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, int _maxtargets,bool other):TargetZoneChooser(card, _maxtargets,other){ int id = Subtypes::subtypesList->Add(_type); nbtypes = 0; addType(id); @@ -350,7 +365,7 @@ TypeTargetChooser::TypeTargetChooser(const char * _type, MTGCardInstance * card, init(default_zones,2); } -TypeTargetChooser::TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +TypeTargetChooser::TypeTargetChooser(const char * _type, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets,bool other):TargetZoneChooser(card, _maxtargets,other){ int id = Subtypes::subtypesList->Add(_type); nbtypes = 0; addType(id); @@ -400,13 +415,13 @@ bool TypeTargetChooser::canTarget(Targetable * target){ /** A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description **/ -DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); cd = _cd; } -DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +DescriptorTargetChooser::DescriptorTargetChooser(CardDescriptor * _cd, int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ if (nbzones == 0){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); @@ -440,14 +455,14 @@ DescriptorTargetChooser::~DescriptorTargetChooser(){ Choose a creature **/ -CreatureTargetChooser::CreatureTargetChooser( MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +CreatureTargetChooser::CreatureTargetChooser( MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); maxpower= -1; maxtoughness= -1; } -CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ if (nbzones == 0){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); @@ -472,11 +487,11 @@ bool CreatureTargetChooser::canTarget(Targetable * target){ /* TargetzoneChooser targets everything in a given zone */ -TargetZoneChooser::TargetZoneChooser(MTGCardInstance * card, int _maxtargets):TargetChooser(card,_maxtargets){ +TargetZoneChooser::TargetZoneChooser(MTGCardInstance * card, int _maxtargets, bool other):TargetChooser(card,_maxtargets, other){ init(NULL,0); } -TargetZoneChooser::TargetZoneChooser(int * _zones, int _nbzones,MTGCardInstance * card, int _maxtargets):TargetChooser(card,_maxtargets){ +TargetZoneChooser::TargetZoneChooser(int * _zones, int _nbzones,MTGCardInstance * card, int _maxtargets, bool other):TargetChooser(card,_maxtargets, other){ init(_zones, _nbzones); } @@ -535,7 +550,7 @@ bool DamageableTargetChooser::canTarget(Targetable * target){ -SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card,int _color, int _maxtargets ):TargetChooser(card, _maxtargets){ +SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, bool other ):TargetChooser(card, _maxtargets, other){ color = _color; } @@ -555,7 +570,7 @@ bool SpellTargetChooser::canTarget(Targetable * target){ /*Spell or Permanent */ -SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); color = _color; @@ -600,7 +615,7 @@ bool DamageTargetChooser::canTarget(Targetable * target){ /*Damage or Permanent */ -DamageOrPermanentTargetChooser::DamageOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets):TargetZoneChooser(card, _maxtargets){ +DamageOrPermanentTargetChooser::DamageOrPermanentTargetChooser(MTGCardInstance * card,int _color, int _maxtargets, bool other):TargetZoneChooser(card, _maxtargets, other){ int default_zones[] = {MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD}; init(default_zones,2); color = _color;