From ae927576c591e1676fbe36b7af4d726ecac957c5 Mon Sep 17 00:00:00 2001 From: Dmitry Panin Date: Mon, 2 Dec 2013 04:20:04 +0400 Subject: [PATCH 1/5] Draft of new feature: canplayfromgraveyard this will allow playing cards from graveyard examples: tbd --- projects/mtg/bin/Res/rules/mtg.txt | 1 + projects/mtg/include/MTGDefinitions.h | 3 +- projects/mtg/include/MTGRules.h | 16 ++++++++++ projects/mtg/src/MTGAbility.cpp | 6 ++++ projects/mtg/src/MTGDefinitions.cpp | 3 +- projects/mtg/src/MTGRules.cpp | 42 +++++++++++++++++++++++++++ 6 files changed, 69 insertions(+), 2 deletions(-) diff --git a/projects/mtg/bin/Res/rules/mtg.txt b/projects/mtg/bin/Res/rules/mtg.txt index 10bbdd90f..38f2f9b84 100644 --- a/projects/mtg/bin/Res/rules/mtg.txt +++ b/projects/mtg/bin/Res/rules/mtg.txt @@ -16,6 +16,7 @@ auto=flashbackrule auto=retracerule auto=suspendrule auto=morphrule +auto=playfromgraveyardrule auto=attackrule auto=blockrule auto=combattriggerrule diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 86d11e14d..08667058e 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -218,7 +218,8 @@ class Constants soulbond = 100, LURE = 101, NOLEGEND = 102, - NB_BASIC_ABILITIES = 103, + CANPLAYFROMGRAVEYARD = 103, + NB_BASIC_ABILITIES = 104, RARITY_S = 'S', //Special Rarity diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index b524e42e2..5a5fbf2cb 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -66,6 +66,7 @@ public: MTGEventBonus(GameObserver* observer, int _id); virtual MTGEventBonus * clone() const; }; + class MTGPutInPlayRule: public PermanentAbility { public: @@ -172,6 +173,21 @@ public: virtual MTGMorphCostRule * clone() const; }; +class MTGPlayFromGraveyardRule: public MTGAlternativeCostRule +{ +public: + int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); + int reactToClick(MTGCardInstance * card); + virtual ostream& toString(ostream& out) const; + MTGPlayFromGraveyardRule(GameObserver* observer, int _id); + const string getMenuText() + { + return "cast card from graveyard"; + } + virtual MTGPlayFromGraveyardRule * clone() const; +}; + + class MTGSuspendRule: public MTGAlternativeCostRule { public: diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 022efba29..4d9cd985c 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1039,6 +1039,12 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG observer->addObserver(NEW MTGMorphCostRule(observer, -1)); return NULL; } + found = s.find("playfromgraveyardrule"); + if(found != string::npos) + { + observer->addObserver(NEW MTGPlayFromGraveyardRule(observer, -1)); + return NULL; + } //this rule handles attacking ability during attacker phase found = s.find("attackrule"); if(found != string::npos) diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index eaecce696..3161c3749 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -131,7 +131,8 @@ const char* Constants::MTGBasicAbilities[] = { "poisondamager",//deals damage to players as poison counters. "soulbond", "lure", - "nolegend" + "nolegend", + "canplayfromgraveyard" }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index b3ba2cd86..c12cd3b86 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -273,6 +273,7 @@ MTGEventBonus * MTGEventBonus::clone() const { return NEW MTGEventBonus(*this); } + MTGPutInPlayRule::MTGPutInPlayRule(GameObserver* observer, int _id) : PermanentAbility(observer, _id) { @@ -1140,8 +1141,49 @@ MTGMorphCostRule * MTGMorphCostRule::clone() const //------------------------------------------------------------------------- //------------------------------------------------------------------------- +MTGPlayFromGraveyardRule::MTGPlayFromGraveyardRule(GameObserver* observer, int _id) : +MTGAlternativeCostRule(observer, _id) +{ + aType = MTGAbility::PUT_INTO_PLAY; +} +int MTGPlayFromGraveyardRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) +{ + Player * player = game->currentlyActing(); + ManaCost * cost = card->getManaCost(); + if (!player->game->graveyard->hasCard(card)) + return 0; + if (!card->has(Constants::CANPLAYFROMGRAVEYARD)) + return 0; + + return MTGAlternativeCostRule::isReactingToClick(card, mana, cost); +} + +int MTGPlayFromGraveyardRule::reactToClick(MTGCardInstance * card) +{ + if (!isReactingToClick(card)) + return 0; + + ManaCost * cost = card->getManaCost(); + + card->paymenttype = MTGAbility::PUT_INTO_PLAY; + + return MTGAlternativeCostRule::reactToClick(card, cost, ManaCost::MANA_PAID); +} + +ostream& MTGPlayFromGraveyardRule::toString(ostream& out) const +{ + out << "MTGPlayFromGraveyardRule ::: ("; + return MTGAbility::toString(out) << ")"; +} + +MTGPlayFromGraveyardRule * MTGPlayFromGraveyardRule::clone() const +{ + return NEW MTGPlayFromGraveyardRule(*this); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// bool MTGAttackRule::select(Target* t) { From 0d4db9ee547239f6539d10b45882408e3ef8d8f1 Mon Sep 17 00:00:00 2001 From: Dmitry Panin Date: Mon, 2 Dec 2013 04:33:39 +0400 Subject: [PATCH 2/5] Fixed bug in alternative cost when playing lands --- projects/mtg/src/MTGRules.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index c12cd3b86..c804a2ed5 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -717,7 +717,6 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter copy->alternateCostPaid[alternateCostType] = 1; spell->resolve(); SAFE_DELETE(spell); - game->mLayers->stackLayer()->addSpell(copy, NULL, NULL, alternateCostType, 1); } else { From 02be213d1e84ede221e49a7a169eb5e92263b816 Mon Sep 17 00:00:00 2001 From: Dmitry Panin Date: Mon, 2 Dec 2013 04:36:58 +0400 Subject: [PATCH 3/5] Test for keyword "CanPlayFromGraveyard" Also added card [Crucible of Worlds] as example of it. --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 7 +++++ .../bin/Res/sets/primitives/unsupported.txt | 13 ---------- projects/mtg/bin/Res/test/_tests.txt | 1 + .../mtg/bin/Res/test/crucible_of_worlds.txt | 26 +++++++++++++++++++ 4 files changed, 34 insertions(+), 13 deletions(-) create mode 100644 projects/mtg/bin/Res/test/crucible_of_worlds.txt diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 038e29d22..e05d799af 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -18104,6 +18104,13 @@ mana={3}{R} type=Enchantment [/card] [card] +name=Crucible of Worlds +auto=lord(land|mygraveyard) CanPlayFromGraveyard +text=You may play land cards from your graveyard. +mana={3} +type=Artifact +[/card] +[card] name=Crude Rampart abilities=defender facedown={3} diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index b3a4789af..6443d6a53 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -3187,19 +3187,6 @@ mana={2} type=Artifact [/card] [card] -name=Crucible of Worlds -auto={0}:may moveTo(myBattlefield) target(land|mygraveyard) limit:1 myTurnOnly -# Above line does not work: "May moveto" from graveyards does -# not work due to interface issues. The "limit:1" doesn't work -# here either. Even if both worked, then the card would allow -# you to play lands *in addition* to the 1 land you can play per -# turn. Instead it should just give you the option to play this -# 1 land from your hand or your graveyard. -text=You may play land cards from your graveyard. -mana={3} -type=Artifact -[/card] -[card] name=Cruel Deceiver text={1}: Look at the top card of your library. -- {2}: Reveal the top card of your library. If it's a land card, Cruel Deceiver gains "Whenever Cruel Deceiver deals damage to a creature, destroy that creature" until end of turn. Activate this ability only once each turn. mana={1}{B} diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 7a5448816..3e351b82e 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -249,6 +249,7 @@ curiosity2_i217.txt crimson_kobolds.txt crosis_s_catacombs_1.txt crosis_s_catacombs_2.txt +crucible_of_worlds.txt crumble.txt crystal_rod_i172.txt cursed_land1_i188.txt diff --git a/projects/mtg/bin/Res/test/crucible_of_worlds.txt b/projects/mtg/bin/Res/test/crucible_of_worlds.txt new file mode 100644 index 000000000..6ceb346a0 --- /dev/null +++ b/projects/mtg/bin/Res/test/crucible_of_worlds.txt @@ -0,0 +1,26 @@ +# Testing crucible of worlds (keyword: CANPLAYFROMGRAVEYARD) + +# name=Crucible of Worlds +# text=You may play land cards from your graveyard. + +[INIT] +FIRSTMAIN +[PLAYER1] +hand:island,plains +inplay:crucible of worlds +graveyard:forest,mountain +[PLAYER2] +[DO] +forest +# all next lands shouldn't be played +island +mountain +plains +[ASSERT] +FIRSTMAIN +[PLAYER1] +inplay:crucible of worlds,forest +hand:island,plains +graveyard:mountain +[PLAYER2] +[END] From ed03fb744dca31d506d9ad7e13e7eace0b1a458b Mon Sep 17 00:00:00 2001 From: Dmitry Panin Date: Mon, 2 Dec 2013 13:42:31 +0400 Subject: [PATCH 4/5] Added [Yawgmoth's Will] --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index e05d799af..d5939b4c1 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -103475,6 +103475,14 @@ mana={1}{B} type=Enchantment [/card] [card] +name=Yawgmoth's Will +auto=@movedTo(*|mygraveyard):all(trigger[to]) moveTo(exile) +auto=lord(*|mygraveyard) canplayfromgraveyard +text=Until end of turn, you may play cards from your graveyard. -- If a card would be put into your graveyard from anywhere this turn, exile that card instead. +mana={2}{B} +type=Sorcery +[/card] +[card] name=Yawning Fissure auto=ability$!name(sacrifice land) notatarget(land|mybattlefield) sacrifice!$ opponent text=Each opponent sacrifices a land. From b7a4b7f6b9779cfbd9147b03330770cbb6f2cd70 Mon Sep 17 00:00:00 2001 From: Dmitry Panin Date: Mon, 2 Dec 2013 21:26:55 +0400 Subject: [PATCH 5/5] Fixing Yawgmoth's will --- projects/mtg/bin/Res/sets/primitives/mtg.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index d5939b4c1..f07510b44 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -103476,8 +103476,9 @@ type=Enchantment [/card] [card] name=Yawgmoth's Will -auto=@movedTo(*|mygraveyard):all(trigger[to]) moveTo(exile) -auto=lord(*|mygraveyard) canplayfromgraveyard +auto=lord(*|mygraveyard) canPlayFromGraveyard +auto=emblem transforms((,newability[@movedTo(*|mygraveyard):all(trigger[to]) moveTo(exile)])) ueot +auto=moveTo(exile) text=Until end of turn, you may play cards from your graveyard. -- If a card would be put into your graveyard from anywhere this turn, exile that card instead. mana={2}{B} type=Sorcery