This is another patch by the great newcomer salmelo.

Salmelo:"Here is another patch, this time adding counters to target specifications, so now you should be able to target things with counters on them as well as use counters for criterion for Lord, aslongas, foreach, etc.
I had to muddle the syntax a little bit though, so heres an example, taken from gwafa hazid, whom I added to the primitives to test with.

lord(creature[counter{0/0.1.Bribe}]|opponentbattlefield) cantattack

obviously the part we are worried about is the counter part, note that those are curly braces { } and periods . instead of parentheses ( ) and commas , this is so that it does not conflict with how targets are normally parsed, which it did before I changed those. Counters still work the same way everywhere else though, you only need to use { } and periods in target code.

Also, you can use counter{any} to specify that it should look for things with any kind of counter on them, not just specific ones, this is used by Kulrath Knight, for example.

I also consolidated most of the code used to parse counter specifications, as it seemed unnecessary duplicating it three times.

Anyway, aside from this major addition, I also added Gwafa Hazid, Profiteer; and Kulrath Knight to the primitives, as well as a test file for each to make sure it worked.

Hopefully y'all will find this patch useful.

Oh, and I should point out that it only works with one Counter in the target specification, i imagine if you put two in the same one then it would either overwrite the first with the second or merge them into some sort of hybrid counter monstrosity, either way, I wouldn't suggest it. "

Cards with vanishing are also codable now. Have a look at the comments for explanation.

daily_build.
This commit is contained in:
solo81@web.de
2010-03-24 21:15:34 +00:00
parent 68d8da296a
commit 07361b19f5
14 changed files with 241 additions and 60 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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<MTGAbility *> * 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);

View File

@@ -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<int,int>::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;
}

View File

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

View File

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

View File

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