#ifndef _CARDS_H_
#define _CARDS_H_

#include "DebugRoutines.h" 
#include "MTGAbility.h"
#include "ManaCost.h"
#include "CardDescriptor.h"
#include "AIPlayer.h"
#include "CardDisplay.h"
#include "Subtypes.h"
#include "CardGui.h"
#include "Token.h"
#include "Counters.h"
#include "WEvent.h"
#include "GuiStatic.h"
#include "GameObserver.h"
#include "Subtypes.h"
#include "ThisDescriptor.h"
#include <JGui.h>
#include <hge/hgeparticle.h>
#include "IconButton.h"
#include "ExtraCost.h"

#include <map>
using std::map;

//
// Misc classes
//
class MTGEventText: public MTGAbility
{
public:
    int textAlpha;
    string text;
    void Update(float dt);
    void Render();
    MTGEventText(GameObserver* observer, int _id,MTGCardInstance * card, string text);
    virtual MTGEventText * clone() const;
};

class MTGRevealingCards : public MTGAbility, public CardDisplay
{
public:
    vector<CardView*> cards;
    Player * playerForZone;
    MTGGameZone * RevealZone;
    MTGGameZone * RevealFromZone;
    string revealCertainTypes;
    string revealUntil;

    CardDisplay * revealDisplay;
    vector<CardDisplay*>trashDisplays;//used for repeat
    int nbCard;
    string abilityString;
    string number;
    string abilityOne;
    string abilityTwo;
    string afterReveal;
    bool afterEffectActivated;
    MTGAbility * abilityToCast;
    MTGAbility * abilityFirst;
    MTGAbility * abilitySecond;
    MTGAbility * abilityAfter;
    vector<MTGAbility*>abilities;
    bool repeat;//only the first ability can be repeated, and it must be targeted.
    bool initCD;

    void Update(float dt);
    int testDestroy();
    int toResolve();
    void CardViewBackup(MTGCardInstance * backup);
    void Render();
    bool CheckUserInput(JButton key);
    MTGAbility * contructAbility(string abilityToMake = "");
    MTGRevealingCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
    virtual MTGRevealingCards * clone() const;
    ~MTGRevealingCards();
    int receiveEvent(WEvent*);
};

class RevealDisplay : public CardDisplay
{
public:
    RevealDisplay(int id, GameObserver* game, int x, int y, JGuiListener * listener = NULL, TargetChooser * tc = NULL,
        int nb_displayed_items = 7);
    void AddCard(MTGCardInstance * _card);
    bool CheckUserInput(JButton key);
};

class GenericRevealAbility : public ActivatedAbility
{
public:
    string howMany;
    MTGRevealingCards * ability;
    GenericRevealAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
    int resolve();
    const string getMenuText();
    GenericRevealAbility * clone() const;
    ~GenericRevealAbility();

};

class MTGScryCards : public MTGAbility, public CardDisplay
{
public:
    vector<CardView*> cards;
    MTGGameZone * RevealZone;
    MTGGameZone * RevealFromZone;

    CardDisplay * revealDisplay;
    vector<CardDisplay*>trashDisplays;//used for repeat
    int nbCard;
    bool delayed;
    bool dontRevealAfter;
    int revealTopAmount;
    string delayedAbilityString;
    string abilityString;
    string number;
    string abilityOne;
    string abilityTwo;
    MTGAbility * abilityToCast;
    MTGAbility * abilityFirst;
    MTGAbility * abilitySecond;
    vector<MTGAbility*>abilities;
    bool initCD;
    void Update(float dt);
    int testDestroy();
    void initDisplay(int value = 0);
    int toResolve();
    void Render();
    bool CheckUserInput(JButton key);
    MTGAbility * contructAbility(string abilityToMake = "");
    MTGScryCards(GameObserver* observer, int _id, MTGCardInstance * card, string text);
    virtual MTGScryCards * clone() const;
    ~MTGScryCards();
    int receiveEvent(WEvent*);
};

class GenericScryAbility : public ActivatedAbility
{
public:
    string howMany;
    MTGScryCards * ability;
    GenericScryAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string _howMany);
    int resolve();
    const string getMenuText();
    GenericScryAbility * clone() const;
    ~GenericScryAbility();

};

class WParsedInt
{
public:
    int intValue;

    int computeX(Spell * spell, MTGCardInstance * card)
    {
        if (spell) return spell->computeX(card);
        if (card) return card->X;
        return 1; //this should only hapen when the ai calls the ability. This is to give it an idea of the "direction" of X (positive/negative)
    }

private:
    void init(string s, Spell * spell, MTGCardInstance * card)
    {
        if(!s.size())
            return;
        if (!card)
        {
            intValue = atoi(s.c_str());//if there is no card, try parsing a number.
            return;
        }
        MTGCardInstance * target = card->target;
        if(!card->storedCard)
            card->storedCard = card->storedSourceCard;
        intValue = 0;
        bool halfup = false;
        bool halfdown = false;
        bool twice = false;
        bool thrice = false;
        bool other = false;//othertype:[subtype]

        if (!target) target = card;
        int multiplier = 1;
        if (s[0] == '-')
        {
            s = s.substr(1);
            multiplier = -1;
            if(s.find("stored") != string::npos)
            {
                string altered ="-";
                altered.append(s.substr(+6));
                return init(altered,spell,card->storedCard);
            }
        }
        if(s[0] == '+')
        {
            //ignore "+" signs....
            s = s.substr(1);
        }
        if(s.find("stored") != string::npos)
        {
            return init(s.substr(+6),spell,card->storedCard);
        }
        //rounding values, the words can be written anywhere in the line,
        //they are erased after parsing.
        if(s.find("halfup") != string::npos)
        {
            halfup = true;
            size_t hU = s.find("halfup");
            s.erase(hU,hU + 6);
        }
        if(s.find("halfdown") != string::npos)
        {
            halfdown = true;
            size_t hD = s.find("halfdown");
            s.erase(hD,hD + 8);
        }
        if(s.find("twice") != string::npos)
        {
            twice = true;
            size_t tXX = s.find("twice");
            s.erase(tXX,tXX + 5);
        }
        if(s.find("thrice") != string::npos)
        {
            thrice = true;
            size_t tXXX = s.find("thrice");
            s.erase(tXXX,tXXX + 6);
        }

        if(s.find("othertype") != string::npos)
        {
            other = true;
            size_t oth = s.find("othertype");
            s.erase(oth,oth + 5);
        }
        if(s.find("otherpower") != string::npos)
        {
            other = true;
            size_t otp = s.find("otherpower");
            s.erase(otp,otp + 5);
        }
        if(s.find("othertoughness") != string::npos)
        {
            other = true;
            size_t ott = s.find("othertoughness");
            s.erase(ott,ott + 5);
        }
        if(s.find("otherconvertedcost") != string::npos)
        {
            other = true;
            size_t otc = s.find("otherconvertedcost");
            s.erase(otc,otc + 5);
        }

        if (s.find("plusend") != string::npos || s.find("minusend") != string::npos || s.find("math") != string::npos)
        {
            //plus#plusend and minus#minusend splits the first part and second parts and parses the
            //ints for each part, then either adds or subtracts those 2 variables as specified.
            vector<string>mathFound = parseBetween(s, "math", "mathend", true);
            if (mathFound.size())//maths allows us to get the value before applying multipliers
            {
                WParsedInt numPar(mathFound[1], NULL, card);
                intValue = numPar.getValue();

            }
            else
            {
                vector<string>plusSplit = parseBetween(s, "", "plus", true);
                if (plusSplit.size())
                {
                    WParsedInt numPar(plusSplit[1], NULL, card);
                    intValue = numPar.getValue();
                }
                vector<string>plusFound = parseBetween(s, "plus", "plusend", true);
                if (plusFound.size())
                {
                    WParsedInt numPar(plusFound[1], NULL, card);
                    intValue += numPar.getValue();
                }
                vector<string>minusSplit = parseBetween(s, "", "minus", true);
                if (minusSplit.size())
                {
                    WParsedInt numPar(minusSplit[1], NULL, card);
                    intValue = numPar.getValue();
                }
                vector<string>minusFound = parseBetween(s, "minus", "minusend", true);
                if (minusFound.size())
                {
                    WParsedInt numPar(minusFound[1], NULL, card);
                    intValue -= numPar.getValue();
                }
            }
        }
        else if(s == "prex")
        {
            if (card->setX > -1)
            {
                intValue = card->setX;
            }
            else
            {
                ManaCost * cX = card->controller()->getManaPool()->Diff(card->getManaCost());
                intValue = cX->getCost(Constants::NB_Colors);
                delete cX;
            }
        }
        else if (s == "x" || s == "X")
        {
            intValue = computeX(spell, card);
            if(intValue < 0)
                intValue = 0;
        }
        else if (s == "xx" || s == "XX")
        {
            intValue = computeX(spell, card) / 2;
            if(intValue < 0)
                intValue = 0;
        }
        else if (s == "castx")
        {
            intValue = card->castX;
        }
        else if (s == "gear")
        {
            intValue = target->equipment;
        }
        else if (s == "colors")
        {
            intValue = target->countColors();
        }
        else if (s == "auras")
        {
            intValue = target->auras;
        }
        else if (s == "manacost")
        {
            if (target->currentZone == target->controller()->game->stack)//X is 0 except if it's on the stack
                intValue = target->myconvertedcost + target->castX;
            else
                intValue = target->myconvertedcost;
        }
        else if (s == "azorius")//devotion blue white
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_WHITE);
        }
        else if (s == "boros")//devotion red white
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_WHITE,Constants::MTG_COLOR_RED);
        }
        else if (s == "dimir")//devotion blue black
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_BLUE);
        }
        else if (s == "golgari")//devotion to green black
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_GREEN);
        }
        else if (s == "gruul")//devotion to green red
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_RED);
        }
        else if (s == "izzet")//devotion to red blue
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_RED);
        }
        else if (s == "orzhov")//devotion to white black
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_WHITE);
        }
        else if (s == "rakdos")//devotion to red black
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLACK,Constants::MTG_COLOR_RED);
        }
        else if (s == "selesnya")//devotion to green white
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_GREEN,Constants::MTG_COLOR_WHITE);
        }
        else if (s == "simic")//devotion to green blue
        {
            intValue = countDevotionTo(card,card->controller()->inPlay(),Constants::MTG_COLOR_BLUE,Constants::MTG_COLOR_GREEN);
        }
        else if (s == "Iroas")//devotion to red white
        {
            intValue = countDevotionTo(card, card->controller()->inPlay(), Constants::MTG_COLOR_RED, Constants::MTG_COLOR_WHITE);
        }
        else if (s.find("type:") != string::npos)
        {
            size_t begins = s.find("type:");
            string theType = s.substr(begins + 5);
            size_t zoned = theType.find(":");
            if(zoned == string::npos)
            {
                theType.append("|mybattlefield");
            }
            else
            {
                replace(theType.begin(), theType.end(), ':', '|');
            }
            int color = 0;
            if (theType.find("mana") != string::npos) {
                color = ManaCost::parseManaSymbol(theType[4]);
                theType.replace(0, 5, "*");
            }
            TargetChooserFactory tf(card->getObserver());
            TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL);
            tc->other = other;
            for (int i = 0; i < 2; i++)
            {
                Player * p = card->getObserver()->players[i];
                MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile };
                for (int k = 0; k < 5; k++)
                {
                    MTGGameZone * zone = zones[k];
                    if (tc->targetsZone(zone, card))
                    {
                        if (color)
                        {
                            intValue += zone->countTotalManaSymbols(tc, color);
                        }
                        else
                        {
                            intValue += zone->countByCanTarget(tc);
                        }
                    }
                }
            }
            SAFE_DELETE(tc);
        }
        else if (s.find("restriction{") != string::npos)
        {
            vector<string> splitRest = parseBetween(s,"restriction{","}");
            if (splitRest.size())
            {
                AbilityFactory abf(target->getObserver());
                int checkCond = abf.parseCastRestrictions(target,target->controller(),splitRest[1].c_str());
                if(checkCond)
                    intValue = 1;
            }
        }
        else if (s.find("counter{") != string::npos)
        {
            intValue = 0;
            vector<string>counterName = parseBetween(s,"counter{","}");
            if(counterName.size())
            {
                AbilityFactory abf(target->getObserver());
                Counter * counter = abf.parseCounter(counterName[1], NULL);
                if(counter && target->counters && target->counters->hasCounter(counter->name.c_str(),counter->power,counter->toughness))
                {
                    Counter * targetCounter = target->counters->hasCounter(counter->name.c_str(), counter->power, counter->toughness);
                    intValue = targetCounter->nb;
                }
                SAFE_DELETE(counter);
            }
        }
        else if (s.find("convertedcost:") != string::npos || s.find("power:") != string::npos || s.find("toughness:") != string::npos)
        {
            bool powerCheck = false;
            bool toughnessCheck = false;
            bool costCheck = false;
            intValue = 0;
            vector<string>convertedType = parseBetween(s,"convertedcost:",":");
            if(convertedType.size())
                costCheck = true;
            else
            {
                convertedType = parseBetween(s,"power:",":");
                if(convertedType.size())
                    powerCheck = true;
                else
                {
                    convertedType = parseBetween(s,"toughness:",":");
                    if(convertedType.size())
                        toughnessCheck = true;
                }
            }
            if(!convertedType.size())
                return;
            bool high = false;
            int highest = 0;
            int lowest = 5000;
            if(convertedType[1].find("highest") != string::npos)
                high = true;

            string theType = convertedType[2];
            size_t zoned = theType.find(":");
            if(zoned == string::npos)
            {
                theType.append("|mybattlefield");
            }
            else
            {
                replace(theType.begin(), theType.end(), ':', '|');
            }
            TargetChooserFactory tf(card->getObserver());
            TargetChooser * tc = tf.createTargetChooser(theType.c_str(),NULL);
            tc->other = other;
            int check = 0;
            for (int i = 0; i < 2; i++)
            {
                Player * p = card->getObserver()->players[i];
                MTGGameZone * zones[] = { p->game->battlefield, p->game->graveyard, p->game->hand, p->game->library, p->game->exile };
                for (int k = 0; k < 5; k++)
                {
                    MTGGameZone * zone = zones[k];
                    if(tc->targetsZone(zone,target))
                    {
                        for(unsigned int w = 0;w < zone->cards.size();++w)
                        {
                            MTGCardInstance * cCard = zone->cards[w];
                            if(tc->canTarget(cCard))
                            {
                                if(costCheck)
                                    check = cCard->getManaCost()->getConvertedCost();
                                if(powerCheck)
                                    check = cCard->power;
                                if(toughnessCheck)
                                    check = cCard->toughness;

                                if(check > highest)
                                    highest = check;
                                if(check <= lowest)
                                    lowest = check;
                            }
                        }
                    }
                }
            }
            if(lowest == 5000)
                lowest = 0;
            SAFE_DELETE(tc);
            intValue = high?highest:lowest;
        }
        else if (s == "sunburst")
        {
            intValue = 0;
            if (card && card->previous && card->previous->previous)
            {
                intValue = card->previous->previous->sunburst;
            }
        }
        else if (s == "converge")
        {
            intValue = 0;
            for (int i = Constants::MTG_COLOR_GREEN; i <= Constants::MTG_COLOR_WHITE; ++i)
            {
                if(card->getManaCost()->getManaUsedToCast()->hasColor(i))
                    intValue +=1;
            }
        }
        else if (s == "evictg")
        {
            intValue = card->imprintG;
        }
        else if (s == "evictu")
        {
            intValue = card->imprintU;
        }
        else if (s == "evictr")
        {
            intValue = card->imprintR;
        }
        else if (s == "evictb")
        {
            intValue = card->imprintB;
        }
        else if (s == "evictw")
        {
            intValue = card->imprintW;
        }
        else if (s == "commongreen")
        {
            intValue = mostCommonColor(Constants::MTG_COLOR_GREEN, card);
        }
        else if (s == "commonblue")
        {
            intValue = mostCommonColor(Constants::MTG_COLOR_BLUE, card);
        }
        else if (s == "commonred")
        {
            intValue = mostCommonColor(Constants::MTG_COLOR_RED, card);
        }
        else if (s == "commonblack")
        {
            intValue = mostCommonColor(Constants::MTG_COLOR_BLACK, card);
        }
        else if (s == "commonwhite")
        {
            intValue = mostCommonColor(Constants::MTG_COLOR_WHITE, card);
        }
        else if (s == "targetedcurses")
        {
            if(card->playerTarget)
                intValue = card->playerTarget->curses.size();
        }
        else if (s == "lifetotal")
        {
            intValue = target->controller()->life;
        }
        else if (s == "startinglife")
        {
            intValue = target->controller()->initLife;
        }
        else if (s == "abundantlife")//current life is morethan or equal to starting life
        {
            intValue = 0;
            if (target->controller()->life >= target->controller()->initLife)
                intValue = 1;
        }
        else if (s == "plibrarycount")
        {
            intValue = 0;
            if (target->controller()->game->library->nb_cards)
                intValue = target->controller()->game->library->nb_cards;
        }
        else if (s == "olibrarycount")
        {
            intValue = 0;
            if (target->controller()->opponent()->game->library->nb_cards)
                intValue = target->controller()->opponent()->game->library->nb_cards;
        }
        else if (s == "highestlifetotal")
        {
            intValue = target->controller()->life <= target->controller()->opponent()->life? target->controller()->opponent()->life:target->controller()->life;
        }
        else if (s == "lowestlifetotal")
        {
            intValue = target->controller()->life <= target->controller()->opponent()->life? target->controller()->life:target->controller()->opponent()->life;
        }
        else if (s == "thatmuch")
        {
            //the value that much is a variable to be used with triggered abilities.
            //ie:when ever you gain life, draw that many cards. when used in a trigger draw:thatmuch, will return the value
            //that the triggered event stored in the card for "that much".
            intValue = 0;
            intValue = target->thatmuch;
            int checkagain = 0;
            if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT))
            {
            if(target->target)
            {
            checkagain = target->target->thatmuch;
            }
            }
            if(checkagain > intValue)
                intValue = checkagain;
            if(card && card->thatmuch > intValue)
                intValue = card->thatmuch;
        }
        else if (s == "oplifelost")
        {
            intValue = target->controller()->opponent()->lifeLostThisTurn;
        }
        else if (s == "lifelost")
        {
            intValue = target->controller()->lifeLostThisTurn;
        }
        else if (s == "pdcount")
        {
            intValue = target->controller()->damageCount;
        }
        else if (s == "odcount")
        {
            intValue = target->controller()->opponent()->damageCount;
        }
        else if (s == "playerpoisoncount")
        {
            intValue = target->controller()->poisonCount;
        }
        else if (s == "opponentpoisoncount")
        {
            intValue = target->controller()->opponent()->poisonCount;
        }
        else if (s == "opponentlifetotal")
        {
            intValue = target->controller()->opponent()->life;
        }
        else if (s == "pdrewcount")
        {
            intValue = target->controller()->drawCounter;
        }
        else if (s == "odrewcount")
        {
            intValue = target->controller()->opponent()->drawCounter;
        }
        else if (s == "epicactivated")
        {
            intValue = target->controller()->epic;
        }
        else if (s == "snowcount")
        {//this is just to count the number of snow mana produced ... just for debugging purposes...
            intValue = target->controller()->snowManaG + target->controller()->snowManaU +target->controller()->snowManaR + target->controller()->snowManaB + target->controller()->snowManaW + target->controller()->snowManaC;
        }
        else if (s == "p" || s == "power")
        {
            intValue = target->getCurrentPower();
        }
        else if (s == "t" || s == "toughness")
        {
            intValue = target->getCurrentToughness();
        }
        else if (s == "countedamount")
        {
            intValue = target->CountedObjects;
        }
        else if (s == "kicked")
        {
            intValue = target->kicked;
        }
        else if (s == "handsize")
        {
            intValue = target->controller()->handsize;
        }
        else if (s == "olandg")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller()->opponent());
        }
        else if (s == "olandu")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller()->opponent());
        }
        else if (s == "olandr")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller()->opponent());
        }
        else if (s == "olandb")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller()->opponent());
        }
        else if (s == "olandw")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller()->opponent());
        }
        else if (s == "olandc")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()->opponent()) +
                countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller()->opponent());
        }
        else if (s == "plandg")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_GREEN, target, target->controller());
        }
        else if (s == "plandu")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_BLUE, target, target->controller());
        }
        else if (s == "plandr")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_RED, target, target->controller());
        }
        else if (s == "plandb")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_BLACK, target, target->controller());
        }
        else if (s == "plandw")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_WHITE, target, target->controller());
        }
        else if (s == "plandc")
        {
            intValue = countManaProducedby(Constants::MTG_COLOR_ARTIFACT, target, target->controller()) +
                countManaProducedby(Constants::MTG_COLOR_WASTE, target, target->controller());
        }
        else if (s == "cantargetmycre")// can target my creature
        {
            intValue = countCanTargetby("creature", card, card->controller());
        }
        else if (s == "cantargetoppocre")// can target opponent creature
        {
            intValue = countCanTargetby("creature", card, card->controller()->opponent());
        }
        else if (s == "cantargetcre")// can target any creature
        {
            intValue = countCanTargetby("creature", card, card->controller()) + countCanTargetby("creature", card, card->controller()->opponent());
        }
        else if (s == "controllerturn")//intvalue = 1 if its your turn this(variable{controllerturn})
        {
            intValue = 0;
            if ( target->controller() == target->getObserver()->currentPlayer)
                intValue = 1;
        }
        else if (s == "opponentturn")//intvalue = 1 if its your turn this(variable{opponentturn})
        {
            intValue = 0;
            if ( target->controller()->opponent() == target->getObserver()->currentPlayer)
                intValue = 1;
        }
        else if (s == "phandcount")
        {
            intValue = target->controller()->game->hand->nb_cards;
        }
        else if (s == "ohandcount")
        {
            intValue = target->controller()->opponent()->game->hand->nb_cards;
        }
        else if (s == "urzatron")//Urza lands
        {
            if(card->controller()->game->battlefield->hasAlias(4192) && card->controller()->game->battlefield->hasAlias(4193) && card->controller()->game->battlefield->hasAlias(4194))
                intValue = 1;
            else
                intValue = 0;
        }
        else if (s == "worshipped")//Worship
        {
            if(card->controller()->game->battlefield->hasType("creature"))
                intValue = card->controller()->life;
            else
                intValue = 0;
        }
        else if (s == "pancientooze")//Ancient Ooze
        {
            intValue = 0;
            for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
                if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE) && card->controller()->game->inPlay->cards[j] != card)
                    intValue += card->controller()->game->inPlay->cards[j]->getManaCost()->getConvertedCost();
        }
        else if (s == "pdauntless")//Dauntless Dourbark
        {
            MTGGameZone * checkZone = card->controller()->inPlay();
            intValue =
                countCardTypeinZone("forest",checkZone) +
                countCardTypeinZone("treefolk",checkZone);
        }
        else if (s == "pbasiclandtypes")//Basic Land types
        {
            MTGGameZone * checkZone = card->controller()->inPlay();
            intValue = //mtg rules 205.4c
                cardHasTypeinZone("waste", checkZone) +
                cardHasTypeinZone("forest", checkZone) +
                cardHasTypeinZone("plains", checkZone) +
                cardHasTypeinZone("swamp", checkZone) +
                cardHasTypeinZone("island", checkZone) +
                cardHasTypeinZone("mountain", checkZone) +
                cardHasTypeinZone("snow-covered forest", checkZone) +
                cardHasTypeinZone("snow-covered plains", checkZone) +
                cardHasTypeinZone("snow-covered swamp", checkZone) +
                cardHasTypeinZone("snow-covered island", checkZone) +
                cardHasTypeinZone("snow-covered mountain", checkZone);
        }
        else if (s == "myname")//Name of the card you control
        {
            intValue = countCardNameinZone(card->name,card->controller()->inPlay());
        }
        else if (s == "allmyname")//Plague Rats and others
        {
            intValue = 0;
            for (int i = 0; i < 2; i++)
                intValue += countCardNameinZone(card->name,card->getObserver()->players[i]->game->battlefield);
        }
        else if (s == "pgbzombie")//Soulless One
        {
            intValue = 0;
            for (int i = 0; i < 2; i++)
            {
                intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->graveyard);
                intValue += countCardTypeinZone("zombie",card->getObserver()->players[i]->game->battlefield);
            }
        }
        else if (s == "pginstantsorcery")//Spellheart Chimera
        {
            intValue = 0;
            for (int j = card->controller()->game->graveyard->nb_cards - 1; j >= 0; --j)
            {
                if (card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_INSTANT)
                    ||card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_SORCERY))
                    intValue += 1;
            }
        }
        else if (s == "gravecardtypes")//Tarmogoyf
        {
            for (int i = 0; i < 2; i++)
            {
                MTGGameZone * checkZone = card->getObserver()->players[i]->game->graveyard;
                intValue = 
                    cardHasTypeinZone("planeswalker",checkZone) +
                    cardHasTypeinZone("tribal",checkZone) +
                    cardHasTypeinZone("sorcery",checkZone) +
                    cardHasTypeinZone("land",checkZone) +
                    cardHasTypeinZone("instant",checkZone) +
                    cardHasTypeinZone("enchantment",checkZone) +
                    cardHasTypeinZone("creature",checkZone) +
                    cardHasTypeinZone("artifact",checkZone);
            }
        }
        else if (s == "powertotalinplay")//Count Total Power of Creatures you control... Formidable
        {
            intValue = 0;
            for (int j = card->controller()->game->inPlay->nb_cards - 1; j >= 0; --j)
            {
                if (card->controller()->game->inPlay->cards[j]->hasType(Subtypes::TYPE_CREATURE))
                    intValue += card->controller()->game->inPlay->cards[j]->power;
            }
        }
        else if (s == "revealedp")
        {
            if (card->revealedLast)
                intValue = card->revealedLast->power;
        }
        else if (s == "revealedt")
        {
            if (card->revealedLast)
                intValue = card->revealedLast->toughness;
        }
        else if (s == "revealedmana")
        {
            if (card->revealedLast)
                intValue = card->revealedLast->getManaCost()->getConvertedCost();
        }
        else if(!intValue)//found nothing, try parsing a atoi
        {
            intValue = atoi(s.c_str());
        }
        if (intValue > 0)//dont divide by 0 the rest are valid.
        {
            if (halfup)
            {
                if (intValue % 2 == 1)
                    intValue++;
                intValue = intValue / 2;
            }
            if (halfdown)
                intValue = intValue / 2;
        }
        if (twice)
            intValue = intValue * 2;
        if (thrice)
            intValue = intValue * 3;
        if (intValue < 0)
        {
            //we remove "-" at the start and are parsing for real values.
            //if we ended up with a value less than 0, then we return just 0
            intValue = 0;
        }

        intValue *= multiplier;
    }
public:

    int countDevotionTo(MTGCardInstance * card, MTGGameZone * zone, int color1, int color2)
    {
        int counthybrid = 0;
        TargetChooserFactory dtf(card->getObserver());
        TargetChooser * dtc = dtf.createTargetChooser("*",NULL);
        if (dtc->targetsZone(zone, card))
        {
            counthybrid += zone->countDevotion(dtc, color1, color2);
        }
        SAFE_DELETE(dtc);
        return counthybrid;
    }

    int countCardNameinZone(string name, MTGGameZone * zone)
    {
        int count = 0;
        for( int i= 0; i < zone->nb_cards; i ++)
            if(zone->cards[i]->name == name)
                count += 1;
        return count;
    }

    int countCardsInPlaybyColor(int color, GameObserver * observer)
    {
        int count = 0;
        for (int i = 0; i < 2; i++)
        {
            for( int j= 0; j < observer->players[i]->inPlay()->nb_cards; j++)
                if(observer->players[i]->inPlay()->cards[j]->hasColor(color))
                    count += 1;
        }
        return count;
    }

    int mostCommonColor(int color, MTGCardInstance * card)
    {
        int maxColor = 0;
        vector<int> colors;

        for(int i = 1; i < 6; i++)
            colors.push_back( countCardsInPlaybyColor(i, card->getObserver()) );
        
        for(int j = 0; j < 5; j++)
            if ( colors[j] > maxColor )
                maxColor = colors[j];

        if (countCardsInPlaybyColor(color, card->getObserver()) >= maxColor && maxColor > 0)
            return 1;

        return 0;
    }

    int countCardTypeinZone(string type, MTGGameZone * zone)
    {
        int count = 0;
        for( int i= 0; i < zone->nb_cards; i ++)
            if(zone->cards[i]->hasType(type))
                count += 1;
        return count;
    }

    int cardHasTypeinZone(const char * type, MTGGameZone * zone)
    {
        int count = 0;
        if(zone->hasType(type))
            count = 1;
        return count;
    }

    int countCanTargetby(string type, MTGCardInstance * card, Player * player)
    {
        int count = 0;
            for (int j = player->game->battlefield->nb_cards - 1; j >= 0; --j)
            {
                if (player->game->battlefield->cards[j]->hasType(type) && !player->game->battlefield->cards[j]->protectedAgainst(card))
                    count += 1;
            }
        return count;
    }

    int countManaProducedby(int color, MTGCardInstance * target, Player * player)
    {
        int count = 0;
        for (size_t i = 0; i < target->getObserver()->mLayers->actionLayer()->manaObjects.size(); i++)
            {
                if (dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])) && 
                    (dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->source->isLand() && 
                    (dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->source->controller() == player && 
                    (dynamic_cast<AManaProducer*> (((MTGAbility *) target->getObserver()->mLayers->actionLayer()->manaObjects[i])))->output->hasColor(color))
                    count += 1;
            }
        return count;
    }

    WParsedInt(int value = 0)
    {
        intValue = value;
    }

    WParsedInt(string s, Spell * spell, MTGCardInstance * card)
    {
        init(s, spell, card);
    }

    WParsedInt(string s, MTGCardInstance * card)
    {
        init(s, NULL, card);
    }

    int getValue()
    {
        return intValue;
    }
};

class WParsedPT
{
public:
    bool ok;
    WParsedInt power, toughness;

    WParsedPT(int p, int t)
    {
        power.intValue = p;
        toughness.intValue = t;
        ok = true;
    }

    WParsedPT(string s, Spell * spell, MTGCardInstance * card)
    {
        size_t found = s.find("/");
        ok = false;
        if (found != string::npos)
        {
            size_t end = s.find(" ", found);
            if (end == string::npos) end = s.size();
            size_t start = s.find_last_of(" ", found);
            if (start == string::npos)
                start = 0;
            else
                start++;
            power = WParsedInt(s.substr(start, found - start), spell, card);
            toughness = WParsedInt(s.substr(found + 1, end - found - 1), spell, card);

            ok = true;
        }
    }
};

//
//Triggers
//


// Triggers When a card gets added to a zone (@movedTo)
class TrCardAddedToZone: public Trigger
{
public:
    TargetZoneChooser * toTcZone, *fromTcZone;
    TargetChooser * toTcCard, *fromTcCard;
    bool sourceUntapped;
    bool isSuspended;
    TrCardAddedToZone(GameObserver* observer, int id, MTGCardInstance * source, TargetZoneChooser * toTcZone, TargetChooser * toTcCard,
            TargetZoneChooser * fromTcZone = NULL, TargetChooser * fromTcCard = NULL,bool once = false,bool sourceUntapped = false,bool isSuspended = false) :
        Trigger(observer, id, source, once), toTcZone(toTcZone), fromTcZone(fromTcZone), toTcCard(toTcCard), fromTcCard(fromTcCard),sourceUntapped(sourceUntapped),isSuspended(isSuspended)
    {
    };


    int triggerOnEventImpl(WEvent * event)
    {
        WEventZoneChange * e = dynamic_cast<WEventZoneChange*> (event);
        if (!e) return 0;
        if(sourceUntapped && source->isTapped() == 1)
            return 0;
        if(isSuspended && !source->suspended)
            return 0;
        if (!toTcZone->targetsZone(e->to)) return 0;
        if (!toTcCard->canTarget(e->card)) return 0;
        if (fromTcZone && !fromTcZone->targetsZone(e->from)) return 0;
        if (fromTcCard && !fromTcCard->canTarget(e->card->previous)) return 0;

        //Battlefield is a special case. We usually don't want to trigger when a card comes from battlefield to battlefield
        // http://code.google.com/p/wagic/issues/detail?id=179
        if ((e->from == game->players[0]->game->battlefield || e->from == game->players[1]->game->battlefield) && (e->to
                == game->players[0]->game->battlefield || e->to == game->players[1]->game->battlefield))
        {
            return 0;
        }

        return 1;
    }

    ~TrCardAddedToZone()
    {
        SAFE_DELETE(toTcZone);
        SAFE_DELETE(toTcCard);
        SAFE_DELETE(fromTcZone);
        SAFE_DELETE(fromTcCard);
    }

    TrCardAddedToZone * clone() const
    {
        return NEW TrCardAddedToZone(*this);
    }
};

class TrCardTapped: public Trigger
{
public:
    bool tap;
    TrCardTapped(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false) :
        Trigger(observer, id, source, once, tc), tap(tap)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventCardTap * e = dynamic_cast<WEventCardTap *> (event);
        if (!e) return 0;
        if (e->noTrigger)
            return 0;
        if (e->before == e->after) return 0;
        if (e->after != tap) return 0;
        if (!tc->canTarget(e->card)) return 0;
        return 1;
    }

    TrCardTapped * clone() const
    {
        return NEW TrCardTapped(*this);
    }
};

class TrCardTappedformana: public Trigger
{
public:
    bool tap;
    TrCardTappedformana(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false) :
        Trigger(observer, id, source, once, tc), tap(tap)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventCardTappedForMana * e = dynamic_cast<WEventCardTappedForMana *> (event);
        if (!e) return 0;
        if (e->before == e->after) return 0;
        if (e->after != tap) return 0;
        if (!tc->canTarget(e->card)) return 0;
        return 1;
    }

    TrCardTappedformana * clone() const
    {
        return NEW TrCardTappedformana(*this);
    }
};

class TrCombatTrigger: public Trigger
{
public:
    TargetChooser * fromTc;//from(card)
    bool limitOnceATurn;//can activate one time per turn
    int triggeredTurn;//the turn it last activated
    bool sourceUntapped;
    bool opponentPoisoned;
    //trigger types
    bool attackingTrigger;
    bool attackedAloneTrigger;
    bool notBlockedTrigger;
    bool attackBlockedTrigger;
    bool blockingTrigger;
    TrCombatTrigger(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,TargetChooser * fromTc = NULL,
    bool once = false,bool limitOnceATurn = false,bool sourceUntapped = false,bool opponentPoisoned = false,
    bool attackingTrigger = false,bool attackedAloneTrigger = false,bool notBlockedTrigger = false,bool attackBlockedTrigger = false,bool blockingTrigger = false) :
    Trigger(observer, id, source,once, tc), fromTc(fromTc),limitOnceATurn(limitOnceATurn),sourceUntapped(sourceUntapped),opponentPoisoned(opponentPoisoned),
    attackingTrigger(attackingTrigger),attackedAloneTrigger(attackedAloneTrigger),notBlockedTrigger(notBlockedTrigger),
    attackBlockedTrigger(attackBlockedTrigger),blockingTrigger(blockingTrigger)
    {
        triggeredTurn = -1;
    }

    int triggerOnEventImpl(WEvent * event)
    {
        //general restrictions
        if (opponentPoisoned && !source->controller()->opponent()->isPoisoned())
            return 0;
        if (sourceUntapped  && source->isTapped() == 1)
            return 0;
        if (limitOnceATurn && triggeredTurn == game->turn)
            return 0;
        //the follow cases are not "else'd" on purpose, triggers which are conjoined such as
        //"whenever this card attacks, or attacks and is not blocked, are supposed to gernerally
        //trigger only once MTG rule 509.a-d, from either/or..not else'ing the statements and
        //listing them in order allows just that, a return on an event before hitting the 
        //next trigger condiational.
        //when triggers are not conjoined you can simply add another combat trigger to the card as normal.
        //an attacking creature can not also be a blocking creature.
        WEventCardAttacked * attacked = dynamic_cast<WEventCardAttacked *> (event);
        //event when a card was declared an attacker.
        if (attacked && attackingTrigger && !attacked->card->didblocked)
        {
            if (!attacked->card->didattacked) 
                return 0;
            if (!tc->canTarget(attacked->card)) 
                return 0;
            return returnResult();
        }
        WEventCardAttackedAlone * attackedAlone = dynamic_cast<WEventCardAttackedAlone *> (event);
        //event when a card was declared an attacker, and attacked alone.
        if (attackedAlone && attackedAloneTrigger && !attackedAlone->card->didblocked)
        {
            if (!attackedAlone->card->didattacked) 
                return 0;
            if (!tc->canTarget(attackedAlone->card)) 
                return 0;
            return returnResult();
        }
        WEventCardBlocked * blocked = dynamic_cast<WEventCardBlocked *> (event);
        //event when a card was declared a blocker.
        if (blocked && blockingTrigger && !blocked->card->didattacked)
        {
            if(!blocked->card->didblocked)
                return 0;
            if (fromTc && !fromTc->canTarget(blocked->opponent)) 
                return 0;
            if (!tc->canTarget(blocked->card)) 
                return 0;
            return returnResult();
        }
        WEventCardAttackedNotBlocked * notblocked = dynamic_cast<WEventCardAttackedNotBlocked *> (event);
        //event when a card was declared an attacker, but the attack was not blocked.
        if (notblocked && notBlockedTrigger && !notblocked->card->didblocked)
        {
            if (!notblocked->card->didattacked) 
                return 0;
            if (notblocked->card->isBlocked()) 
                return 0;
            if (!tc->canTarget(notblocked->card))
                return 0;
            return returnResult();
        }
        WEventCardAttackedBlocked * attackblocked = dynamic_cast<WEventCardAttackedBlocked *> (event);
        //event when a card was declared an attacker, then it became "blocked".
        if (attackblocked && attackBlockedTrigger && !attackblocked->card->didblocked)
        {
            if (!attackblocked->card->didattacked) 
                return 0;
            if (!attackblocked->card->isBlocked()) 
                return 0;
            if (fromTc && !fromTc->canTarget(attackblocked->opponent)) 
                return 0;
            if (!tc->canTarget(attackblocked->card)) 
                return 0;
            return returnResult();
        }
        //default return is 0 || not triggered.
        return 0;
    }
    
    int returnResult()
    {
        triggeredTurn = game->turn;
        return 1;
    }
    
    ~TrCombatTrigger()
    {
        SAFE_DELETE(fromTc);
    }

    TrCombatTrigger * clone() const
    {
        return NEW TrCombatTrigger(*this);
    }
};

class TrcardDrawn: public Trigger
{
public:
    bool thiscontroller, thisopponent;
    TrcardDrawn(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false, bool thiscontroller = false, bool thisopponent = false) :
        Trigger(observer, id, source,once, tc),thiscontroller(thiscontroller),thisopponent(thisopponent)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventcardDraw * e = dynamic_cast<WEventcardDraw *> (event);
        if (!e) return 0;
        if (!tc->canTarget(e->player)) return 0;
        if(thiscontroller)
            if(e->player != source->controller())
                return 0;
        if(thisopponent)
            if(e->player == source->controller())
                return 0;
        return 1;
    }

    TrcardDrawn * clone() const
    {
        return NEW TrcardDrawn(*this);
    }
};

class TrCardSacrificed: public Trigger
{
public:
    TrCardSacrificed(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false) :
        Trigger(observer, id, source, once, tc)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventCardSacrifice * e = dynamic_cast<WEventCardSacrifice *> (event);
        if (!e) return 0;
        MTGCardInstance * check = e->cardAfter;
        MTGGameZone * oldZone = e->cardAfter->currentZone;
        check->currentZone = check->previousZone;
        if (check->next && check->next->currentZone)
        {
            check = e->cardAfter->next;
            oldZone = e->cardAfter->next->currentZone;
            check->currentZone = e->cardAfter->next->previousZone;
        }
        if (!tc->canTarget(check,true))
        {
            check->currentZone = oldZone;
            return 0;
        }
        check->currentZone = oldZone;
        return 1;
    }

    TrCardSacrificed * clone() const
    {
        return NEW TrCardSacrificed(*this);
    }
};

class TrCardDiscarded: public Trigger
{
public:
    bool cycledTrigger;
    TrCardDiscarded(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false, bool cycledTrigger = false) :
    Trigger(observer, id, source, once, tc),cycledTrigger(cycledTrigger)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        MTGCardInstance * targetCard = NULL;
        if(cycledTrigger)
        {
            WEventCardCycle * c = dynamic_cast<WEventCardCycle *> (event);
            if (!c) return 0;
            targetCard = c->card;
        }
        else
        {
            WEventCardDiscard * e = dynamic_cast<WEventCardDiscard *> (event);
            if (!e) return 0;
            targetCard = e->card;
        }
        if (!targetCard || !tc->canTarget(targetCard)) return 0;
        return 1;
    }

    TrCardDiscarded * clone() const
    {
        return NEW TrCardDiscarded(*this);
    }
};

class TrDamaged: public Trigger
{
public:
    TargetChooser * fromTc;
    int type;//this allows damagenoncombat and combatdamage to share this trigger
    bool sourceUntapped;
    bool limitOnceATurn;
    int triggeredTurn;
    bool thiscontroller;
    bool thisopponent;
    TrDamaged(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0,bool sourceUntapped = false,bool limitOnceATurn = false,bool once = false, bool thiscontroller = false, bool thisopponent = false) :
        Trigger(observer, id, source, once, tc), fromTc(fromTc), type(type) , sourceUntapped(sourceUntapped),limitOnceATurn(limitOnceATurn),thiscontroller(thiscontroller),thisopponent(thisopponent)
    {
        triggeredTurn = -1;
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventDamage * e = dynamic_cast<WEventDamage *> (event);
        if (!e) return 0;
        if (limitOnceATurn && triggeredTurn == game->turn)
            return 0;
        if (sourceUntapped  && source->isTapped() == 1)
            return 0;
        if (!tc->canTarget(e->damage->target)) return 0;
        if (fromTc && !fromTc->canTarget(e->damage->source)) return 0;
        if (type == 1 && e->damage->typeOfDamage != Damage::DAMAGE_COMBAT) return 0;
        if (type == 2 && e->damage->typeOfDamage == Damage::DAMAGE_COMBAT) return 0;
        if (e->damage->target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER)
        {
            if(thiscontroller)
                if(e->damage->target != (Damageable *)source->controller())
                    return 0;
            if(thisopponent)
                if(e->damage->target == (Damageable *)source->controller())
                    return 0;
        }
        e->damage->target->thatmuch = e->damage->damage;
        e->damage->source->thatmuch = e->damage->damage;
        this->source->thatmuch = e->damage->damage;
        triggeredTurn = game->turn;

        return 1;
    }

    ~TrDamaged()
    {
        SAFE_DELETE(fromTc);
    }

    TrDamaged * clone() const
    {
        return NEW TrDamaged(*this);
    }
};

class TrLifeGained: public Trigger
{
public:
    TargetChooser * fromTc;
    int type;//this allows damagenoncombat and combatdamage to share this trigger
    bool sourceUntapped, thiscontroller, thisopponent;
    TrLifeGained(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0,bool sourceUntapped = false,bool once = false, bool thiscontroller = false, bool thisopponent = false) :
        Trigger(observer, id, source, once , tc),  fromTc(fromTc), type(type) , sourceUntapped(sourceUntapped) , thiscontroller(thiscontroller) , thisopponent(thisopponent)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventLife * e = dynamic_cast<WEventLife *> (event);
        if (!e) return 0;
        if (sourceUntapped  && source->isTapped() == 1)
            return 0;
        if (!tc->canTarget(e->player)) return 0;
        if (fromTc && !fromTc->canTarget(e->player)) return 0;
        if (type == 1 && (e->amount > 0)) return 0;
        if (type == 0 && (e->amount < 0)) return 0;
        if(thiscontroller)
            if(e->player != source->controller())
                return 0;
        if(thisopponent)
            if(e->player == source->controller())
                return 0;
        e->player->thatmuch = abs(e->amount);
        this->source->thatmuch = abs(e->amount);

        return 1;
    }

    ~TrLifeGained()
    {
        SAFE_DELETE(fromTc);
    }

    TrLifeGained * clone() const
    {
        return NEW TrLifeGained(*this);
    }
};

//vampire trigger
class TrVampired: public Trigger
{
public:
    TargetChooser * fromTc;
    TrVampired(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL,bool once = false) :
    Trigger(observer, id, source, once, tc), fromTc(fromTc)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventVampire * vamp = dynamic_cast<WEventVampire*>(event);
        if (!vamp)
            return 0;

        if(fromTc && !fromTc->canTarget(vamp->source))
            return 0;
        tc->setAllZones();
        //creature that were "vampired" only happens in battlefield, and event sent when they hit a grave.
        //setting allzones, as we don't care since we know the preexisting condiations cover the zones.
        if(!tc->canTarget(vamp->victem))
            return 0;
        return 1;

    }

    ~TrVampired()
    {
        SAFE_DELETE(fromTc);
    }

    TrVampired * clone() const
    {
        return NEW TrVampired(*this);
    }
};

//targetted trigger
class TrTargeted: public Trigger
{
public:
    TargetChooser * fromTc;
    int type;
    TrTargeted(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0,bool once = false) :
    Trigger(observer, id, source, once, tc), fromTc(fromTc), type(type)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventTarget * e = dynamic_cast<WEventTarget *> (event);
        if (!e) return 0;
        if (!tc->canTarget(e->card)) return 0;
        if (fromTc && !fromTc->canTarget(e->source)) return 0;

        return 1;
    }

    ~TrTargeted()
    {
        SAFE_DELETE(fromTc);
    }

    TrTargeted * clone() const
    {
        return NEW TrTargeted(*this);
    }
};

//counter trigger
class TrCounter: public Trigger
{
public:
    Counter * counter;
    int type;
    TrCounter(GameObserver* observer, int id, MTGCardInstance * source, Counter * counter, TargetChooser * tc, int type = 0,bool once = false) :
    Trigger(observer, id, source, once, tc),counter(counter), type(type)
    {
    }

    int triggerOnEventImpl(WEvent * event)
    {
        WEventCounters * e = dynamic_cast<WEventCounters *> (event);
        if (!e) return 0;
        if (type == 0 && !e->removed) return 0;
        if (type == 1 && !e->added) return 0;
        if (!(e->power == counter->power && e->toughness == counter->toughness && e->name == counter->name)) return 0;
        if (tc && !tc->canTarget(e->targetCard)) return 0;
        return 1;
    }

    ~TrCounter()
    {
        SAFE_DELETE(counter);
    }

    TrCounter * clone() const
    {
        TrCounter * mClone = NEW TrCounter(*this);
        mClone->counter = NEW Counter(*this->counter);
        return mClone;
    }
};

//Tutorial Messaging
class ATutorialMessage: public MTGAbility, public IconButtonsController
{
public:
    string mMessage;
    float mElapsed, mSH, mSW;
    JTexture * mBgTex;
    JQuad * mBg[9];
    bool mUserCloseRequest, mDontShow;
    bool mIsImage;
    int mLimit;

    ATutorialMessage(GameObserver* observer, MTGCardInstance * source, string message, int limit = 1);

    void Update(float dt);
    bool CheckUserInput(JButton key);
    void Render();
    string getOptionName();
    int alreadyShown();

    ATutorialMessage * clone() const;
    ~ATutorialMessage();

    //JGuiListener Implementation
    using JGuiObject::ButtonPressed;
    void ButtonPressed(int controllerId, int controlId);
};

//counters
class AACounter: public ActivatedAbility
{
public:
    string counterstring;
    int nb;
    int maxNb;
    int power;
    int toughness;
    string name;
    string menu;

    AACounter(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target,string counterstring, const char * _name, int power, int toughness, int nb,int maxNb = 0,
            ManaCost * cost = NULL);

    int resolve();
    const string getMenuText();
    AACounter * clone() const;
};

//counters
class AARemoveAllCounter: public ActivatedAbility
{
public:
    int nb;
    int power;
    int toughness;
    string name;
    string menu;
    bool all;

    AARemoveAllCounter(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, const char * _name, int power, int toughness, int nb,
            bool all,ManaCost * cost = NULL);

    int resolve();
    const string getMenuText();
    AARemoveAllCounter * clone() const;
};


class AAResetDamage: public ActivatedAbility
{
public:
    AAResetDamage(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    AAResetDamage * clone() const;
};

class AAFakeAbility: public ActivatedAbility
{
public:
    string named;
    AAFakeAbility(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target,string _newName, ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    AAFakeAbility * clone() const;
};

class AAEPIC: public ActivatedAbility
{
public:
    string named;
    bool FField;
    AAEPIC(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target,string _newName, ManaCost * cost = NULL, bool ffield = false );
    int resolve();
    const string getMenuText();
    AAEPIC * clone() const;
};

class AAFizzler: public ActivatedAbility
{
public:
    ActionStack::FizzleMode fizzleMode; // action to do after fizzling

    AAFizzler(GameObserver* observer, int _id, MTGCardInstance * card, Spell * _target, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AAFizzler* clone() const;
};

/*
 Generic classes
 */

class ANewAffinity: public MTGAbility
{
public:
    string tcString;
    string manaString;
    ANewAffinity(GameObserver* observer, int _id, MTGCardInstance * _source,string Tc = "", string mana ="");
    void Update(float dt);
    int testDestroy();
    ANewAffinity * clone() const;
};

//if/ifnot Cond then EFFECT
class IfThenAbility: public InstantAbility
{
public:
    MTGAbility * delayedAbility;
    MTGAbility * delayedElseAbility;
    int type;
    string Cond;
    IfThenAbility(GameObserver* observer, int _id,MTGAbility * delayedAbility = NULL,MTGAbility * delayedElseAbility = NULL, MTGCardInstance * _source=NULL, Targetable * target = NULL, int type = 1,string Cond = "");
    int resolve();
    const string getMenuText();
    IfThenAbility * clone() const;
    ~IfThenAbility();
};

//MayAbility: May do ...
class MayAbility: public MTGAbility, public NestedAbility
{
public:
    int triggered;
    bool must;
    string Cond;
    Player * previousInterrupter;
    MTGAbility * mClone;

    MayAbility(GameObserver* observer, int _id, MTGAbility * _ability, MTGCardInstance * _source, bool must = false, string restriction = "");

    void Update(float dt);

    const string getMenuText();
    int testDestroy();

    int isReactingToTargetClick(Targetable * card);

    int reactToTargetClick(Targetable * object);

    MayAbility * clone() const;
    ~MayAbility();

};

//MayAbility with custom menues.
class MenuAbility: public MayAbility
{
public:
    int triggered;
    bool removeMenu;
    bool must;
    bool processed;
    MTGAbility * mClone;
    ManaCost * toPay;
    vector<MTGAbility*>abilities;
    vector<ManaCost*>optionalCosts;
    Player * who;
    string newNameString;
    MenuAbility(GameObserver* observer, int _id, Targetable * target, MTGCardInstance * _source, bool must = false, vector<MTGAbility*>abilities = vector<MTGAbility*>(),Player * who = NULL,string _newName = "");
    bool CheckUserInput(JButton key);
    void Update(float dt);
    int resolve();
    const string getMenuText();
    int testDestroy();
    int isReactingToTargetClick(Targetable * card);
    int reactToTargetClick(Targetable * object);
    int reactToChoiceClick(Targetable * object,int choice,int control);
    int processAbility();
    MenuAbility * clone() const;
    ~MenuAbility();

};

class AAProliferate: public ActivatedAbility
{
public:
    AAProliferate(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target,ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    AAProliferate * clone() const;
    ~AAProliferate();
};

//MultiAbility : triggers several actions for a cost
class MultiAbility: public ActivatedAbility
{
public:
    vector<MTGAbility *> abilities;
    //Maintains abilities created by this instance, for cleanup
    vector<MTGAbility *> clones;

    MultiAbility(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost);
    int Add(MTGAbility * ability);
    int resolve();
    int addToGame();
    int destroy();
    const string getMenuText();
    MultiAbility * clone() const;
    ~MultiAbility();
};

//Generic Activated Ability

class GenericActivatedAbility: public ActivatedAbility, public NestedAbility
{
public:
    MTGGameZone * activeZone;
    string newName;

    GenericActivatedAbility(GameObserver* observer, string newName,string castRestriction,int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "",
            int restrictions = 0, MTGGameZone * dest = NULL);
    GenericActivatedAbility(const GenericActivatedAbility& other);
    int resolve();
    const string getMenuText();
    int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
    void Update(float dt);
    int testDestroy();
    GenericActivatedAbility * clone() const;
    ~GenericActivatedAbility();

};

//place a card on the bottom of owners library
class AALibraryBottom: public ActivatedAbility
{
public:
    AALibraryBottom(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AALibraryBottom * clone() const;
};

//Copier. ActivatedAbility
class AACopier: public ActivatedAbility
{
public:
    AACopier(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AACopier * clone() const;
};
//phaseout
class AAPhaseOut: public ActivatedAbility
{
public:
    AAPhaseOut(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AAPhaseOut * clone() const;
};
//AAImprint
class AAImprint: public ActivatedAbility
{
public:
    AAImprint(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AAImprint * clone() const;
};
//cloning...this makes a token thats a copy of the target.
class AACloner: public ActivatedAbility
{
public:
    int who;
    string with;
    string types;
    list<int> awith;
    list<int> colors;
    list<int> typesToAdd;

    AACloner(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost = NULL, int who = 0,
            string abilitiesStringList = "",string typeslist = "");
    int resolve();
    const string getMenuText();
    virtual ostream& toString(ostream& out) const;
    AACloner * clone() const;
    ~AACloner();
};

// AAMover
class AAMover: public ActivatedAbility
{
public:
    string destination;
    MTGAbility * andAbility;
    string named;
    bool undying;
    bool persist;
    AAMover(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, string dest,string _name, ManaCost * _cost = NULL, bool undying = false, bool persist = false);
    MTGGameZone * destinationZone(Targetable * target = NULL);
    int resolve();
    const string getMenuText();
    const char * getMenuText(TargetChooser * fromTc);
    AAMover * clone() const;
    ~AAMover();
};

// AARandomMover
class AARandomMover: public ActivatedAbility
{
public:
    string abilityTC;
    string fromZone;
    string toZone;
    AARandomMover(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, string tcs, string from, string to);
    MTGGameZone * destinationZone(Targetable * target = NULL,string zone = "");
    int resolve();
    const string getMenuText();
    AARandomMover * clone() const;
    ~AARandomMover();
};

//-----------------------------------------------------------------------------------------------

class AABuryCard: public ActivatedAbility
{
public:
    MTGAbility * andAbility;
    string menu;
    AABuryCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
    int resolve();
    const string getMenuText();
    AABuryCard * clone() const;
    ~AABuryCard();
};

class AADestroyCard: public ActivatedAbility
{
public:
    MTGAbility * andAbility;
    AADestroyCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
    int resolve();
    const string getMenuText();
    AADestroyCard * clone() const;
    ~AADestroyCard();
};

class AASacrificeCard: public ActivatedAbility
{
public:
    MTGAbility * andAbility;
    AASacrificeCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
    int resolve();
    const string getMenuText();
    AASacrificeCard * clone() const;
    ~AASacrificeCard();
};

class AADiscardCard: public ActivatedAbility
{
public:
    MTGAbility * andAbility;
    AADiscardCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target);
    int resolve();
    const string getMenuText();
    AADiscardCard * clone() const;
    ~AADiscardCard();
};

/* Generic Target Ability */
class GenericTargetAbility: public TargetAbility
{

public:
    int limitPerTurn;
    string limit;
    int counters;
    MTGGameZone * activeZone;
    string newName;
    MTGAbility * sideEffects;
    string usesBeforeSideEffects;
    string tcString;

    GenericTargetAbility(GameObserver* observer, string newName, string castRestriction, int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, ManaCost * _cost = NULL, string limit = "",MTGAbility * sideEffects = NULL,string usesBeforeSideEffects = "", int restrictions = 0, MTGGameZone * dest = NULL,string tcString ="");
    const string getMenuText();
    ~GenericTargetAbility();
    GenericTargetAbility * clone() const;
    int resolve();
    int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
    void Update(float dt);
    int testDestroy();

};

//ninjutsu

class ANinja: public ActivatedAbility
{
public:
    ANinja(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target) :
        ActivatedAbility(observer, _id, card)
    {
        target = _target;
    }

    int resolve()
    {
    MTGCardInstance * _target = (MTGCardInstance *) target;
    if(!_target)
    return 0;
        MTGCardInstance * copy = _target->controller()->game->putInZone(_target,_target->currentZone,
                source->controller()->game->temp);
        Spell * spell = NEW Spell(game, copy);
        spell->resolve();
        MTGCardInstance * newcard = spell->source;
        newcard->summoningSickness = 0;
        newcard->tap();
        newcard->setAttacker(1);
        delete spell;
        return 1;
    }

    const string getMenuText()
    {
        return "Ninjutsu";
    }

    ANinja * clone() const
    {
        return NEW ANinja(*this);
    }
};

//remove from combat

class ACombatRemoval: public ActivatedAbility
{
public:
    ACombatRemoval(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target) :
        ActivatedAbility(observer, _id, card)
    {
        target = _target;
    }

    int resolve()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (_target)
        {
            _target->initAttackersDefensers();
        }
        return 1;
    }

    const string getMenuText()
    {
        return "Remove From Combat";
    }

    ACombatRemoval * clone() const
    {
        return NEW ACombatRemoval(*this);
    }
};

//Drawer, allows to draw a card for a cost:

class AADrawer: public ActivatedAbilityTP
{
public:

    string nbcardsStr;
    bool noReplace;
    AADrawer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost,string nbcardsStr, int who =
            TargetChooser::UNSET,bool noReplace = false);
    int resolve();
    const string getMenuText();
    AADrawer * clone() const;
    int getNumCards();
};



class ACastRestriction: public AbilityTP
{
public:
    TargetChooser * restrictionsScope; //a minimalist TargetChooser object describing the cards impacted by the restriction (for example: lands)
    WParsedInt *value; //"maxPerTurn" value
    MaxPerTurnRestriction * existingRestriction; // a pointer to the restriction that is being modified or that has been created (for restriction deletion purpose)
    bool modifyExisting; //if set to true, means we want to modify an existing restriction, otherwise we create a new one
    int zoneId; // identifier of the zone id impacted by the restriction
    Player * targetPlayer; // Reference to the player impacted by the restriction (for restriction deletion purpose)

    ACastRestriction(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who = TargetChooser::UNSET);
    int addToGame();
    int destroy();
    const string getMenuText();
    ACastRestriction * clone() const;
    ~ACastRestriction();

};


class  AInstantCastRestrictionUEOT: public InstantAbilityTP
{
public:
    ACastRestriction * ability;


    AInstantCastRestrictionUEOT(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, TargetChooser * _restrictionsScope, WParsedInt * _value, bool _modifyExisting, int _zoneId, int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AInstantCastRestrictionUEOT * clone() const;
    ~AInstantCastRestrictionUEOT();
};

/*Gives life to target controller*/
class AALifer: public ActivatedAbilityTP
{
public:
    string life_s;
    AALifer(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string life_s, ManaCost * _cost = NULL,
            int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AALifer * clone() const;
    int getLife();

};

/*Player Wins Game*/
class AAWinGame: public ActivatedAbilityTP
{
public:
    AAWinGame(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int who =
            TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAWinGame * clone() const;
};

/*Changes one of the basic abilities of target
 source : spell
 target : spell target (creature)
 modifier : 1 to add the ability, 0 to remove it
 _ability : Id of the ability, as described in mtgdefinitions
 */
class ABasicAbilityModifier : public MTGAbility
{
public:
    int modifier;
    int ability;
    bool value_before_modification;
    ABasicAbilityModifier(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, int _ability, int _modifier = 1) :
        MTGAbility(observer, _id, _source, _target), modifier(_modifier), ability(_ability)
    {
        aType = MTGAbility::STANDARDABILITYGRANT;
        abilitygranted = ability;
    }

    int addToGame()
    {
        value_before_modification = ((MTGCardInstance *) target)->basicAbilities.test(ability);

        assert(modifier < 2);
        ((MTGCardInstance *) target)->basicAbilities.set(ability, modifier > 0);

        return MTGAbility::addToGame();
    }

    int destroy()
    {
         assert(modifier < 2);
        ((MTGCardInstance *) target)->basicAbilities.set(ability, value_before_modification);

        return 1;
    }

    const string getMenuText()
    {
        return Constants::MTGBasicAbilities[ability];
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ABasicAbilityModifier ::: modifier : " << modifier << " ; ability : " << ability
                << " ; value_before_modification : " << value_before_modification << " (";
        return MTGAbility::toString(out) << ")";
    }

    ABasicAbilityModifier * clone() const
    {
        return NEW ABasicAbilityModifier(*this);
    }
};

/*Instants that modifies a basic ability until end of turn */
class AInstantBasicAbilityModifierUntilEOT : public InstantAbility
{
public:
    bool stateBeforeActivation;
    int ability;
    int value;
    AInstantBasicAbilityModifierUntilEOT(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, int _ability, int value)
        : InstantAbility(observer, _id, _source, _target), ability(_ability), value(value)
        {
            aType = MTGAbility::STANDARDABILITYGRANT;
            abilitygranted = ability;
        }

        int addToGame()
        {
            MTGCardInstance * _target = (MTGCardInstance *) target;
            stateBeforeActivation = _target->basicAbilities.test(ability);

            assert(value < 2);
            _target->basicAbilities.set(ability, value > 0);
            _target->modifiedbAbi += 1;
            return InstantAbility::addToGame();
        }

        const string getMenuText()
        {
            return Constants::MTGBasicAbilities[ability];
        }

    int destroy()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (_target)
        {
            _target->basicAbilities.set(ability, stateBeforeActivation);
            _target->modifiedbAbi -= 1;
        }
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ABasicAbilityModifierUntilEOT ::: stateBeforeActivation : " << stateBeforeActivation << " ability : " << ability
                << " (";
        return InstantAbility::toString(out) << ")";
    }

    AInstantBasicAbilityModifierUntilEOT * clone() const
    {
        return NEW AInstantBasicAbilityModifierUntilEOT(*this);
    }
};

//Alteration of Ability until of turn (Aura)
class ABasicAbilityAuraModifierUntilEOT: public ActivatedAbility
{
public:
    AInstantBasicAbilityModifierUntilEOT * ability;
    ABasicAbilityAuraModifierUntilEOT(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost,
            int _ability, int _value = 1) :
        ActivatedAbility(observer, _id, _source, _cost, 0)
    {
        target = _target;
        ability = NEW AInstantBasicAbilityModifierUntilEOT(observer, _id, _source, _target, _ability, _value);
        aType = MTGAbility::STANDARDABILITYGRANT;
        abilitygranted = _ability;
    }

    int isReactingToClick(MTGCardInstance *, ManaCost *)
    {
        //The upper level "GenericTargetAbility" takes care of the click so we always return 0 here
        return 0;
    }

    int resolve()
    {
        MTGAbility * a = ability->clone();
        a->target = target;
        a->addToGame();
        return 1;
    }

    int addToGame()
    {
        resolve();
        return ActivatedAbility::addToGame();
    }

    const string getMenuText()
    {
        return ability->getMenuText();
    }

    ABasicAbilityAuraModifierUntilEOT * clone() const
    {
        ABasicAbilityAuraModifierUntilEOT * a = NEW ABasicAbilityAuraModifierUntilEOT(*this);
        a->ability = ability->clone();
        return a;
    }

    ~ABasicAbilityAuraModifierUntilEOT()
    {
        SAFE_DELETE(ability);
    }
};

/*Gives life each time a spell matching CardDescriptor's criteria are match . Optionnal manacost*/
class ASpellCastLife: public MTGAbility
{
public:
    CardDescriptor trigger;
    ManaCost * cost;
    int life;
    MTGCardInstance * lastUsedOn;
    MTGCardInstance * lastChecked;
    ASpellCastLife(GameObserver* observer, int id, MTGCardInstance * _source, CardDescriptor _trigger, ManaCost * _cost, int _life) :
        MTGAbility(observer, id, _source), trigger(_trigger), cost(_cost), life(_life), lastUsedOn(NULL), lastChecked(NULL)
    {
        aType = MTGAbility::LIFER;
    }
    ASpellCastLife(GameObserver* observer, int id, MTGCardInstance * _source, int color, ManaCost * _cost, int _life) :
        MTGAbility(observer, id, _source), cost(_cost), life(_life), lastUsedOn(NULL), lastChecked(NULL)
    {
        trigger.setColor(color);
    }

    int isReactingToClick(MTGCardInstance * _card, ManaCost * = NULL)
    {
        if (_card == source && game->currentlyActing()->game->inPlay->hasCard(source))
        {
            if (game->currentlyActing()->getManaPool()->canAfford(cost))
            {
                Interruptible * laststackitem = game->mLayers->stackLayer()->getAt(-1);
                if (laststackitem && laststackitem->type == ACTION_SPELL)
                {
                    Spell * spell = (Spell*) laststackitem;
                    if (spell->source != lastUsedOn && trigger.match(spell->source))
                    {
                        lastChecked = spell->source;
                        return 1;
                    }
                }
            }
        }
        return 0;
    }

    int reactToClick(MTGCardInstance * _card)
    {
        if (!isReactingToClick(_card)) return 0;
        game->currentlyActing()->getManaPool()->pay(cost);
        if(!game->currentlyActing()->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
            game->currentlyActing()->life += life;
        lastUsedOn = lastChecked;
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ASpellCastLife ::: trigger : ? " // << trigger
                << " ; cost : " << cost << " ; life : " << life << " ; lastUsedOn : " << lastUsedOn << " ; lastChecked : "
                << lastChecked << " (";
        return MTGAbility::toString(out) << ")";
    }

    ASpellCastLife * clone() const
    {
        return NEW ASpellCastLife(*this);
    }

    ~ASpellCastLife()
    {
        SAFE_DELETE(cost);
    }

};

//Allows to untap at any moment for an amount of mana
class AUnBlocker: public MTGAbility
{
public:
    ManaCost * cost;
    AUnBlocker(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost) :
        MTGAbility(observer, id, _source, _target), cost(_cost)
    {
    }

    int isReactingToClick(MTGCardInstance * _card, ManaCost * = NULL)
    {
        if (_card == target && game->currentlyActing()->game->inPlay->hasCard(source) && _card->isTapped())
        {
            if (game->currentlyActing()->getManaPool()->canAfford(cost))
            {
                return 1;
            }
        }
        return 0;
    }

    int reactToClick(MTGCardInstance * _card)
    {
        if (!isReactingToClick(_card)) return 0;
        game->currentlyActing()->getManaPool()->pay(cost);
        _card->attemptUntap();
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AUnBlocker ::: cost : " << cost << " (";
        return MTGAbility::toString(out) << ")";
    }

    AUnBlocker * clone() const
    {
        return NEW AUnBlocker(*this);
    }

};

//Protection From (creature/aura)
class AProtectionFrom: public MTGAbility
{
public:
    TargetChooser * fromTc;
    string tcstr;
    AProtectionFrom(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc,string tcstr) :
        MTGAbility(observer, id, _source, _target), fromTc(fromTc),tcstr(tcstr)
    {

    }

    int addToGame()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        _target->addProtection(fromTc);
        return MTGAbility::addToGame();
    }

    int destroy()
    {
        ((MTGCardInstance *) target)->removeProtection(fromTc);
        return 1;
    }

    const string getMenuText()
    {
        sprintf(menuText,"Protection from %s",tcstr.c_str());
        return menuText;
    }
    
    AProtectionFrom * clone() const
    {
        AProtectionFrom * a = NEW AProtectionFrom(*this);
        a->fromTc = fromTc->clone();
        return a;
    }

    ~AProtectionFrom()
    {
        SAFE_DELETE(fromTc);
    }

};

//cant be target of...
class ACantBeTargetFrom: public MTGAbility
{
public:
    TargetChooser * fromTc;
    ACantBeTargetFrom(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc) :
        MTGAbility(observer, id, _source, _target), fromTc(fromTc)
    {

    }

    int addToGame()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        _target->addCantBeTarget(fromTc);
        return MTGAbility::addToGame();
    }

    int destroy()
    {
        ((MTGCardInstance *) target)->removeCantBeTarget(fromTc);
        return 1;
    }

    ACantBeTargetFrom * clone() const
    {
        ACantBeTargetFrom * a = NEW ACantBeTargetFrom(*this);
        a->fromTc = fromTc->clone();
        return a;
    }

    ~ACantBeTargetFrom()
    {
        SAFE_DELETE(fromTc);
    }

};
//Can't be blocked by...
class ACantBeBlockedBy: public MTGAbility
{
public:
    TargetChooser * fromTc;
    ACantBeBlockedBy(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc) :
        MTGAbility(observer, id, _source, _target), fromTc(fromTc)
    {

    }

    int addToGame()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        _target->addCantBeBlockedBy(fromTc);
        return MTGAbility::addToGame();
    }

    int destroy()
    {
        ((MTGCardInstance *) target)->removeCantBeBlockedBy(fromTc);
        return 1;
    }

    ACantBeBlockedBy * clone() const
    {
        ACantBeBlockedBy * a = NEW ACantBeBlockedBy(*this);
        a->fromTc = fromTc->clone();
        return a;
    }

    ~ACantBeBlockedBy()
    {
        SAFE_DELETE(fromTc);
    }

};
//cant be the blocker of targetchooser
//Can't be blocked by...
class ACantBeBlockerOf: public MTGAbility
{
public:
    TargetChooser * fromTc;
    bool thisCard;
    ACantBeBlockerOf(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, TargetChooser *fromTc,bool aThis) :
        MTGAbility(observer, id, _source, _target), fromTc(fromTc),thisCard(aThis)
    {

    }

        int addToGame()
        {
            MTGCardInstance * _target = (MTGCardInstance *) target;
            if(!thisCard)
                _target->addCantBeBlockerOf(fromTc);
            else
                _target->addCantBeBlockerOfCard((MTGCardInstance*)source);
            return MTGAbility::addToGame();
        }

        int destroy()
        {
            if(!thisCard)
                ((MTGCardInstance *) target)->removeCantBeBlockerOf(fromTc);
            else
                ((MTGCardInstance *) target)->removeCantBeBlockerOfCard((MTGCardInstance*)source);
            return 1;
        }

    ACantBeBlockerOf * clone() const
    {
        ACantBeBlockerOf * a = NEW ACantBeBlockerOf(*this);
        if(fromTc)
            a->fromTc = fromTc->clone();
        return a;
    }

    ~ACantBeBlockerOf()
    {
        SAFE_DELETE(fromTc);
    }

};
//Alteration of Power and Toughness  (enchantments)
class APowerToughnessModifier: public MTGAbility
{
public:
    WParsedPT * wppt;
    string PT;
    bool nonstatic;
    bool cda;
    APowerToughnessModifier(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, WParsedPT * wppt,string PT,bool nonstatic) :
        MTGAbility(observer, id, _source, _target), wppt(wppt),PT(PT),nonstatic(nonstatic)
    {
        aType = MTGAbility::STANDARD_PUMP;
        cda = PT.find("cdaactive") != string::npos;
    }
    
    void Update(float)
    {
        if(!nonstatic)
            return;
        if(!cda || (cda && (((MTGCardInstance *) target)->isSettingBase < 1)))
        {
            if(((MTGCardInstance *) target)->isSwitchedPT)
                ((MTGCardInstance *) target)->switchPT(false);//revert

            ((MTGCardInstance *) target)->power -= wppt->power.getValue();
            ((MTGCardInstance *) target)->addToToughness(-wppt->toughness.getValue());
            if(PT.size())
                {
                    SAFE_DELETE(wppt);
                    if(cda)
                        wppt = NEW WParsedPT(cReplaceString(PT, " cdaactive", ""),NULL,(MTGCardInstance *) source);
                    else
                        wppt = NEW WParsedPT(cReplaceString(PT, " nonstatic", ""),NULL,(MTGCardInstance *) source);
                }
            MTGCardInstance * _target = (MTGCardInstance *) target;
            _target->power += wppt->power.getValue();
            _target->addToToughness(wppt->toughness.getValue());

            if(_target->isSwitchedPT)
                _target->switchPT(true);//reaapply
        }
        if(cda)
        {//update but not apply
            if(PT.size())
                {
                    SAFE_DELETE(wppt);
                    if(cda)
                        wppt = NEW WParsedPT(cReplaceString(PT, " cdaactive", ""),NULL,(MTGCardInstance *) source);
                    else
                        wppt = NEW WParsedPT(cReplaceString(PT, " nonstatic", ""),NULL,(MTGCardInstance *) source);
                }
            ((MTGCardInstance *) target)->origpower = wppt->power.getValue();
            ((MTGCardInstance *) target)->origtoughness = (wppt->toughness.getValue() + ((MTGCardInstance *) target)->life)-((MTGCardInstance *) target)->life;//what?
        }
    }
    int addToGame()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if(PT.size())
        {
            SAFE_DELETE(wppt);
            if(cda)
                wppt = NEW WParsedPT(cReplaceString(PT, " cdaactive", ""),NULL,(MTGCardInstance *) source);
            else
                wppt = NEW WParsedPT(cReplaceString(PT, " nonstatic", ""),NULL,(MTGCardInstance *) source);
        }
        if(cda)
        {//Characteristic-defining abilities
            if(_target->isSwitchedPT)
            {
                _target->switchPT(false);
                _target->cdaPT(wppt->power.getValue(),wppt->toughness.getValue());
                _target->switchPT(true);
            }
            else
                _target->cdaPT(wppt->power.getValue(),wppt->toughness.getValue());

            _target->isCDA = true;
        }
        else
        {
            if(_target->isSwitchedPT)
            {
                _target->switchPT(false);
                _target->addptbonus(wppt->power.getValue(),wppt->toughness.getValue());
                _target->switchPT(true);
            }
            else
                _target->addptbonus(wppt->power.getValue(),wppt->toughness.getValue());
        }
        if(_target->has(Constants::INDESTRUCTIBLE) && wppt->toughness.getValue() < 0 && _target->toughness <= 0)
        {
            _target->controller()->game->putInGraveyard(_target);
        }
        return MTGAbility::addToGame();
    }
    int destroy()
    {
        if(cda)
        {
            /*??Do Nothing??*/;
        }
        else
        {
            ((MTGCardInstance *) target)->removeptbonus(wppt->power.getValue(),wppt->toughness.getValue());
        }
        return 1;
    }
    const string getMenuText()
    {                
        if(PT.size())
        {
            SAFE_DELETE(wppt);
            if(cda)
                wppt = NEW WParsedPT(cReplaceString(PT, " cdaactive", ""),NULL,(MTGCardInstance *) source);
            else
                wppt = NEW WParsedPT(cReplaceString(PT, " nonstatic", ""),NULL,(MTGCardInstance *) source);
        }
        sprintf(menuText, "%i/%i", wppt->power.getValue(), wppt->toughness.getValue());
        return menuText;
    }
    APowerToughnessModifier * clone() const
    {
        APowerToughnessModifier * a = NEW APowerToughnessModifier(*this);
        a->wppt = NEW WParsedPT(*(a->wppt));
        return a;
    }
    ~APowerToughnessModifier()
    {
        delete (wppt);
    }
};

class GenericInstantAbility: public InstantAbility, public NestedAbility
{
public:
    GenericInstantAbility(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
        InstantAbility(observer, _id, _source, _target), NestedAbility(ability)
    {
        ability->target = _target;
    }

    int addToGame()
    {
        ability->forceDestroy = -1;
        ability->target = target; //Might have changed since initialization
        ability->addToGame();
        return InstantAbility::addToGame();
    }

    int destroy()
    {
        if (game->removeObserver(ability))
            ability = NULL;
        else
            SAFE_DELETE(ability);
        return InstantAbility::destroy();
    }

    GenericInstantAbility * clone() const
    {
        GenericInstantAbility * a = NEW GenericInstantAbility(*this);
        a->ability = ability->clone();
        return a;
    }

    ~GenericInstantAbility()
    {
        SAFE_DELETE(ability);
    }
};

//this generic ability assumes that what is added will take care of its own removel.
class GenericAbilityMod: public InstantAbility, public NestedAbility
{
public:
    GenericAbilityMod(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
      InstantAbility(observer, _id, _source,_target), NestedAbility(ability)
      {
          ability->target = _target;
      }

      int addToGame()
      {
          InstantAbility::addToGame();
          return 1;
      }

      int resolve()
      {
          MTGAbility * toAdd = ability->clone();
          toAdd->forceDestroy = -1;
          toAdd->target = target;
          if(toAdd->getActionTc())
          {
              toAdd->reactToTargetClick(source);
              return 1;
          }
          toAdd->addToGame();
          return 1;
      }

      const string getMenuText()
      {
          return ability->getMenuText();
      }

      GenericAbilityMod * clone() const
      {
          GenericAbilityMod * a = NEW GenericAbilityMod(*this);
          a->ability = ability->clone();
          return a;
      }

      ~GenericAbilityMod()
      {
          SAFE_DELETE(ability);
      }
};
//generic addtogame
class GenericAddToGame: public InstantAbility, public NestedAbility
{
public:
    GenericAddToGame(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
      InstantAbility(observer, _id, _source,_target), NestedAbility(ability)
      {
          ability->target = _target;
      }

      int addToGame()
      {
          InstantAbility::addToGame();
          return 1;
      }

      int resolve()
      {
          MTGAbility * toAdd = ability->clone();
          toAdd->target = target;
          if(toAdd->getActionTc())
              return toAdd->reactToTargetClick(source);
          return toAdd->addToGame();
      }

      const string getMenuText()
      {
          return ability->getMenuText();
      }

      GenericAddToGame * clone() const
      {
          GenericAddToGame * a = NEW GenericAddToGame(*this);
          a->ability = ability->clone();
          return a;
      }

      ~GenericAddToGame()
      {
          SAFE_DELETE(ability);
      }
};
//Circle of Protections
class ACircleOfProtection: public TargetAbility
{
protected:
    map<ReplacementEffect*, int> current;
public:
    ACircleOfProtection(GameObserver* observer, int _id, MTGCardInstance * source, int _color) :
        TargetAbility(observer, _id, source, NEW SpellOrPermanentTargetChooser(source->owner->getObserver(), source, _color), NEW ManaCost(), 0)
    {
        getCost()->add(Constants::MTG_COLOR_ARTIFACT, 1);
        tc->targetter = NULL; //Circle of Protection doesn't use the word "source"
    }

    int resolve()
    {
        MTGCardInstance * _target = NULL;
        if (!(_target = tc->getNextCardTarget()))
        {
            Spell * starget = tc->getNextSpellTarget();
            _target = starget->source;
        }
        if (!_target) return 0;
        REDamagePrevention * re = NEW REDamagePrevention(this, NEW CardTargetChooser(game, _target, NULL), NEW PlayerTargetChooser(game, 0, 1,
                source->controller()));
        current[re] = 1;
        game->replacementEffects->add(re);
        return 1;
    }

    void clear()
    {
        for (map<ReplacementEffect*, int>::iterator it = current.begin(); it != current.end(); it++)
        {
            ReplacementEffect* re = (*it).first;
            game->replacementEffects->remove(re);
            delete re;
        }
        current.clear();
    }

    void Update(float dt)
    {
        if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP) clear();
        TargetAbility::Update(dt);
    }

    ~ACircleOfProtection()
    {
        clear();
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ACircleOfProtection ::: (";
        return TargetAbility::toString(out) << ")";
    }
    ACircleOfProtection * clone() const
    {
        return NEW ACircleOfProtection(*this);
    }
};

//Basic regeneration mechanism for a Mana cost
class AStandardRegenerate: public ActivatedAbility
{
public:
    AStandardRegenerate(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, ManaCost * _cost = NULL) :
        ActivatedAbility(observer, _id, _source, _cost, 0)
    {
        target = _target;
        aType = MTGAbility::STANDARD_REGENERATE;
    }

    int resolve()
    {

        MTGCardInstance * _target = (MTGCardInstance *) target;
        _target->regenerate();
        return 1;
    }

    const string getMenuText()
    {
        return "Regenerate";
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AStandardRegenerate ::: (";
        return ActivatedAbility::toString(out) << ")";
    }
    AStandardRegenerate * clone() const
    {
        return NEW AStandardRegenerate(*this);
    }
};

//Aura Enchantments that provide controller of target life or damages at a given phase of their turn
class ARegularLifeModifierAura: public MTGAbility
{
public:
    int life;
    int phase;
    int onlyIfTargetTapped;
    ARegularLifeModifierAura(GameObserver* observer, int id, MTGCardInstance * _source, MTGCardInstance * _target, int _phase, int _life,
            int _onlyIfTargetTapped = 0) :
        MTGAbility(observer, id, _source, _target), life(_life), phase(_phase), onlyIfTargetTapped(_onlyIfTargetTapped)
    {
    }

    void Update(float)
    {
        if (newPhase != currentPhase && newPhase == phase && game->currentPlayer == ((MTGCardInstance *) target)->controller())
        {
            if ((!onlyIfTargetTapped || ((MTGCardInstance *) target)->isTapped()) && (!game->currentPlayer->inPlay()->hasAbility(Constants::CANTCHANGELIFE)))
            {
                if (life > 0)
                {
                    game->currentPlayer->life += life;
                }
                else
                {
                    game->mLayers->stackLayer()->addDamage(source, game->currentPlayer, -life);
                }
            }
        }
    }
    virtual ostream& toString(ostream& out) const
    {
        out << "ARegularLifeModifierAura ::: life : " << life << " ; phase : " << phase << " ; onlyIfTargetTapped : "
                << onlyIfTargetTapped << " (";
        return MTGAbility::toString(out) << ")";
    }
    ARegularLifeModifierAura * clone() const
    {
        return NEW ARegularLifeModifierAura(*this);
    }
};
//Generic Kird Ape
class AAsLongAs: public ListMaintainerAbility, public NestedAbility
{
public:
    MTGAbility * a;
    int includeSelf;
    int mini, maxi;
    bool miniFound, maxiFound, compareZone;
    int amount[2];
    AAsLongAs(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, TargetChooser * _tc, int _includeSelf,
        MTGAbility * ability, int mini = 0, int maxi = 0,bool miniFound = false,bool maxiFound = false,bool compareZone = false) :
    ListMaintainerAbility(observer, _id, _source, _target), NestedAbility(ability), mini(mini), maxi(maxi),miniFound(miniFound),maxiFound(maxiFound),compareZone(compareZone)
    {
        for (int j = 0; j < 2; j++)
            amount[j] = 0;
        tc = _tc;
        includeSelf = _includeSelf;
        tc->targetter = NULL;
        ability->source = source;
        ability->target = target;
        a = NULL;
    }

    void Update(float dt)
    {
        ListMaintainerAbility::Update(dt);
        if(!ability->oneShot) {
            SorterFunction();
        }
    }

    void findMatchingAmount()
    {
        int Value = 0;
        for (int i = 0; i < 2; i++)
        {
            Player * p = game->players[i];
            MTGGameZone * zones[] = { p->game->inPlay, p->game->graveyard, p->game->hand, p->game->library, p->game->exile };
            for (int k = 0; k < 5; k++)
            {
                MTGGameZone * zone = zones[k];
                Value = zone->countByCanTarget(tc);
            }
            amount[i] = Value;
        }
    }

    int SorterFunction()
    {
        updateTargets();
        int size = 0;
        size = (int) cards.size();
        if(compareZone)
            findMatchingAmount();
        //compare like tc zones to find a matching amount.
        //if any player has less/more of Tc targetable cards, ability is valid.
        /////////////////DO NOT REFACTOR THIS SECTION/////////////////////////////////////////
        //these were seperated becuase previous methods were far too confusing to understand//
        //////////////////////////////////////////////////////////////////////////////////////
        if (miniFound)
        {
            if (size > mini || (compareZone && (amount[0] > mini || amount[1] > mini))) 
            {
                addAbilityToGame();
            }
            else
            {
                removeAbilityFromGame();
            }
        }
        if (maxiFound)
        {
            if (size < maxi || (compareZone && (amount[0] < maxi || amount[1] < maxi))) 
            {
                addAbilityToGame();
            }
            else
            {
                removeAbilityFromGame();
            }
        }
        /////////////////////////////////////////////////////////////////////////
        cards.clear();
        players.clear();
        return 1;
    }

    int canBeInList(MTGCardInstance * card)
    {
        if(card->isPhased || source->isPhased)
            return 0;
        if ((includeSelf || card != source) && tc->canTarget(card)) 
            return 1;

        return 0;
    }
    //////////resolve is used when the aslongas is nested, or used on instants and sorceries/////////
    int resolve()
    {
        SorterFunction();
        if (ability->oneShot)
        {
            a = NULL; //allows to call the effect several times
        }
        return 1;
    }

    int addAbilityToGame()
    {
        if (a) return 0;
        a = ability->clone();
        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            a->addToGame();
        }
        return 1;
    }

    int removeAbilityFromGame()
    {
        if (!a) return 0;
        game->removeObserver(a);
        a = NULL;
        return 1;
    }
    /////////////////section required/////////////////////
    int added(MTGCardInstance *)
    {
        return 1;
    }
    int added(Player *)
    {
        return 1;
    }
    int removed(MTGCardInstance *)
    {
        return 1;
    }
    ///////////////////////////////////////////////////////
    ~AAsLongAs()
    {
        SAFE_DELETE(ability);
    }

    const string getMenuText()
    {
        if(ability)
        {
            return ability->getMenuText();
        }
        else
        {
            return "Ability";
        }
    }

    AAsLongAs * clone() const
    {
        AAsLongAs * a = NEW AAsLongAs(*this);
        a->ability = ability->clone();
        return a;
    }
};

//Lords (Merfolk lord...) give power and toughness to OTHER creatures of their type, they can give them special abilities, regeneration
class ALord: public ListMaintainerAbility, public NestedAbility
{
public:
    int includeSelf;
    map<Damageable *, MTGAbility *> abilities;

    ALord(GameObserver* observer, int _id, MTGCardInstance * card, TargetChooser * _tc, int _includeSelf, MTGAbility * a) :
        ListMaintainerAbility(observer, _id, card), NestedAbility(a)
    {
        tc = _tc;
        tc->targetter = NULL;
        includeSelf = _includeSelf;
        if(ability->aType == MTGAbility::STANDARD_PREVENT)
            aType = MTGAbility::STANDARD_PREVENT;
    }
     
    //returns true if it is me who created ability a attached to Damageable d
    bool isParentOf(Damageable * d, MTGAbility * a)
    {
        if (abilities.find(d) != abilities.end())
            return (abilities[d] == a);
        return false;
    }

    int canBeInList(Player *p)
    {
        if (tc->canTarget(p)) return 1;
        return 0;
    }

    int canBeInList(MTGCardInstance * card)
    {
        if(card->isPhased || source->isPhased)
        {
            removed(card);
            return 0;
        }
        if ((includeSelf || card != source) && tc->canTarget(card)) 
            return 1;
        return 0;
    }

    int resolve()
    {
        //TODO check if ability is oneShot ?
        updateTargets();
        cards.clear();
        players.clear();
        return 1;
    }

    int _added(Damageable * d)
    {
        MTGAbility * a = ability->clone();
        a->target = d;
        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            if (d->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE)
            {
                a->source = (MTGCardInstance *) d;
            }
            if (oneShot)
            {
                MTGAbility * wrapper = NEW GenericInstantAbility(game, 1, source, d, a);
                wrapper->addToGame();
            }
            else
            {
                a->addToGame();
                abilities[d] = a;
            }
        }
        return 1;
    }

    int added(MTGCardInstance * card)
    {
        return _added(card);
    }

    int added(Player * p)
    {
        return _added(p);
    }

    int removed(MTGCardInstance * card)
    {
        if (abilities.find(card) != abilities.end()
            && !(forceDestroy == -1 && forcedAlive == 1)) //only embelms have forcedestroy = -1 and forcedalive = 1
        { 
            game->removeObserver(abilities[card]);
            abilities.erase(card);
        }
        return 1;
    }

    ~ALord()
    {
        SAFE_DELETE(ability);
    }

    const string getMenuText()
    {
        //Special case for move
        if (AAMover * move = dynamic_cast<AAMover *>(ability))
            return move->getMenuText(tc);

        return ability->getMenuText();
    }

    ALord * clone() const
    {
        ALord * a = NEW ALord(*this);
        a->ability = ability->clone();
        return a;
    }
};
////////////////////////////////////////////////////////////////////////////////////////////////////
//a different lord for auras and enchantments. http://code.google.com/p/wagic/issues/detail?id=244
class ATeach: public ListMaintainerAbility, public NestedAbility
{
public:
    int includeSelf;
    map<Damageable *, MTGAbility *> skills;

    ATeach(GameObserver* observer, int _id, MTGCardInstance * card, TargetChooser * _tc, int, MTGAbility * a) :
        ListMaintainerAbility(observer, _id, card), NestedAbility(a)
    {
        tc = _tc;
        tc->targetter = NULL;
        includeSelf = 0;
        aType = MTGAbility::STANDARD_TEACH;
    }

        int canBeInList(MTGCardInstance * card)
        {
            if(card->isPhased || source->isPhased)
                return 0;
            if(tc->canTarget(card) && card != tc->source)
            {
                if ((tc->source->hasSubtype(Subtypes::TYPE_AURA) || tc->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || tc->source->hasSubtype("instant")
                    || tc->source->hasSubtype("sorcery")) && card == tc->source->target ) 
                    return 1;
                if(tc->source->hasSubtype(Subtypes::TYPE_CREATURE))
                {
                    for(size_t myChild = 0; myChild < tc->source->parentCards.size();++myChild)
                    {
                        if(tc->source->parentCards[myChild] == card)
                            return 1;
                    }
                }
            }
            return 0;
        }

    int resolve()
    {
        updateTargets();
        cards.clear();
        players.clear();
        return 1;
    }

    int added(MTGCardInstance * card)
    {
        return _added(card);
    }

    int removed(MTGCardInstance * card)
    {
        if (skills.find(card) != skills.end())
        {
            if(!game->removeObserver(skills[card]))
            {
                skills[card]->destroy();
            }
            if(skills[card])
                skills.erase(card);
        }
        return 1;
    }

    int _added(Damageable * d)
    {
        MTGAbility * a = ability->clone();

        if (a->source->hasSubtype(Subtypes::TYPE_AURA) || a->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || a->source->hasSubtype("instant")
                || a->source->hasSubtype("sorcery"))
        {
            a->target = a->source->target;
        }
        else
        {
            if(tc->source->hasSubtype(Subtypes::TYPE_CREATURE))
                a->target = d;
            else
                return 0;
        }

        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            if (d->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE)
            {
                a->source = (MTGCardInstance *) d;
            }
            if (oneShot)
            {
                MTGAbility * wrapper = NEW GenericInstantAbility(game, 1, source, d, a);
                wrapper->addToGame();
            }
            else
            {
                skills[d] = a;
                a->addToGame();
            }
        }
        return 1;
    }
    ~ATeach()
    {
        SAFE_DELETE(ability);
    }

    ATeach * clone() const
    {
        ATeach * a =  NEW ATeach(*this);
        a->ability = ability->clone();
        return a;
    }

};
//

/* assign a creature to block a target */
class AABlock: public InstantAbility
{
public:
    AABlock(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    AABlock * clone() const;
};

/* assign a creature as a pair to target */
class PairCard: public InstantAbility
{
public:
    PairCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    PairCard * clone() const;
};
//pick a card to dredge
class dredgeCard: public InstantAbility
{
public:
    dredgeCard(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    dredgeCard * clone() const;
};
/* create a parent child association between cards */
class AAConnect: public InstantAbility
{
public:
    AAConnect(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    AAConnect * clone() const;
};

//equipment
class AEquip: public TargetAbility
{
private:
    bool isAttach;
    vector<MTGAbility *> currentAbilities;

public:
    AEquip(GameObserver* observer, int _id, MTGCardInstance * _source, ManaCost * _cost = NULL,
        int restrictions = ActivatedAbility::AS_SORCERY);
    
    int unequip();
    int equip(MTGCardInstance * equipped);

    int resolve();
    const string getMenuText();

    int testDestroy();
    int destroy();

    AEquip * clone() const;
};

class ATokenCreator: public ActivatedAbility
{
public:
    list<int> abilities;
    list<int> types;
    list<int> colors;
    int power, toughness;
    int tokenId;
    string _cardName;
    string name;
    string sabilities;
    string starfound;
    WParsedInt * multiplier;
    int who;
    bool aLivingWeapon;
    string spt;
    bool battleReady;
    MTGCardInstance * myToken;
    vector<MTGAbility *> currentAbilities;
    Player * tokenReciever;
    //by id
    ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, int tokenId,string starfound, WParsedInt * multiplier = NULL,
        int who = 0,bool aLivingWeapon = false) :
    ActivatedAbility(observer, _id, _source, _cost, 0), tokenId(tokenId), starfound(starfound),multiplier(multiplier), who(who),aLivingWeapon(aLivingWeapon)
    {
        if (!multiplier) this->multiplier = NEW WParsedInt(1);
        MTGCard * card = MTGCollection()->getCardById(tokenId);
        if (card) name = card->data->getName();
        battleReady = false;
    }
    //by name, card still require valid card.dat info, this just makes the primitive code far more readable. token(Eldrazi scion) instead of token(-1234234)...
    ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string cardName, string starfound, WParsedInt * multiplier = NULL,
        int who = 0, bool aLivingWeapon = false) :
        ActivatedAbility(observer, _id, _source, _cost, 0), _cardName(cardName), starfound(starfound), multiplier(multiplier), who(who), aLivingWeapon(aLivingWeapon)
    {
        if (!multiplier) this->multiplier = NEW WParsedInt(1);
        MTGCard * card = MTGCollection()->getCardByName(_cardName);
        tokenId = card->getId();
        if (card) name = card->data->getName();
        battleReady = false;
    }
    //by construction
    ATokenCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost, string sname, string stypes, int _power, int _toughness,
        string sabilities, string starfound,WParsedInt * multiplier = NULL, int _who = 0,bool aLivingWeapon = false,string spt = "") :
    ActivatedAbility(observer, _id, _source, _cost, 0),sabilities(sabilities),starfound(starfound), multiplier(multiplier), who(_who),aLivingWeapon(aLivingWeapon),spt(spt)
    {
        power = _power;
        toughness = _toughness;
        name = sname;
        tokenId = 0;
        aType = MTGAbility::STANDARD_TOKENCREATOR;
        battleReady = false;
        if (!multiplier) this->multiplier = NEW WParsedInt(1);
        //TODO this is a copy/past of other code that's all around the place, everything should be in a dedicated parser class;

        for (int j = 0; j < Constants::NB_BASIC_ABILITIES; j++)
        {
            size_t found = sabilities.find(Constants::MTGBasicAbilities[j]);
            if (found != string::npos)
            {
                abilities.push_back(j);
            }
        }

        if(sabilities.find("battleready") != string::npos)
            battleReady = true;

        if(sabilities.find("chosencolor") != string::npos)
        {
            colors.push_back(source->chooseacolor);
        }

        for (int j = 0; j < Constants::NB_Colors; j++)
        {
            size_t found = sabilities.find(Constants::MTGColorStrings[j]);
            if (found != string::npos)
            {
                colors.push_back(j);
            }
        }

        string s = stypes;
        while (s.size())
        {
            size_t found = s.find(" ");
            if (found != string::npos)
            {
                string toCheck = s.substr(0, found);
                if(toCheck.find("chosentype") != string::npos || toCheck.find("Chosentype") != string::npos)
                {
                    toCheck = source->chooseasubtype;
                }
                int id = MTGAllCards::findType(toCheck);
                types.push_back(id);
                s = s.substr(found + 1);
            }
            else
            {
                if(s.find("chosentype") != string::npos || s.find("Chosentype") != string::npos)
                {
                    s = source->chooseasubtype;
                }
                int id = MTGAllCards::findType(s);
                types.push_back(id);
                s = "";
            }
        }
    }

    int resolve()
    {
        if(!starfound.empty())
        {
            SAFE_DELETE(multiplier);
            multiplier = NEW WParsedInt(starfound, NULL, (MTGCardInstance *)source);
        }
        if(!spt.empty())
        {
            vector<string> powertoughness = split( spt, '/');
            WParsedInt * NewPow = NEW WParsedInt(powertoughness[0].c_str(),NULL,source);
            WParsedInt * NewTou = NEW WParsedInt(powertoughness[1].c_str(),NULL,source);
            power = NewPow->getValue();
            toughness = NewTou->getValue();
            SAFE_DELETE(NewPow);
            SAFE_DELETE(NewTou);
        }
        for (int i = 0; i < Tokenizer(); ++i)
        {
            //MTGCardInstance * myToken;
            if (tokenId)
            {
                MTGCard * card = MTGCollection()->getCardById(tokenId);
                setTokenOwner();
                myToken = NEW MTGCardInstance(card, tokenReciever->game);
            }
            else
            {
                myToken = NEW Token(name, source, power, toughness);
                list<int>::iterator it;
                for (it = types.begin(); it != types.end(); it++)
                {
                    myToken->addType(*it);
                }
                for (it = colors.begin(); it != colors.end(); it++)
                {
                    myToken->setColor(*it);
                }
                for (it = abilities.begin(); it != abilities.end(); it++)
                {
                    myToken->basicAbilities[*it] = 1;
                }
            }
            string tokenText = "";
            if(sabilities.find("token(") == string::npos)
            {
                tokenText = "(";
                size_t endAbility = sabilities.find(")");
                string words = sabilities.substr(0,endAbility);
                tokenText.append(words);
                string sourcename = ((MTGCardInstance*)source)->name;
                tokenText.append(") source: ");
                tokenText.append( sourcename);
                myToken->setText(tokenText);
            }
            setTokenOwner();
            tokenReciever->game->temp->addCard(myToken);
            Spell * spell = NEW Spell(game, myToken);
            spell->resolve();
            myToken = spell->source;
            spell->source->owner = tokenReciever;
            spell->source->isToken = 1;
            spell->source->fresh = 1;
            if(aLivingWeapon)
            {
                livingWeaponToken(spell->source);
            }
            if(battleReady)
            {
                battleReadyToken(spell->source);
            }
            delete spell;
        }
        return 1;
    }

    int Tokenizer()//tokenizer
    {
        int tokenize = 1;
        if (source->controller()->game->battlefield->hasAbility(Constants::TOKENIZER))
        {
            int nbcards = source->controller()->game->battlefield->nb_cards;
            for (int j = 0; j < nbcards; j++)
            {
                if (source->controller()->game->battlefield->cards[j]->has(Constants::TOKENIZER))
                    tokenize *= 2;
            }
            return multiplier->getValue()*tokenize;
        }
        else
            return multiplier->getValue();
    }
   
    void setTokenOwner()
    {
        switch(who)
        {
        case TargetChooser::CONTROLLER:
            tokenReciever = source->controller();
            break;
        case TargetChooser::OPPONENT:
            tokenReciever = source->controller()->opponent();
            break;
        case TargetChooser::TARGET_CONTROLLER:
            if(target)
            {
                tokenReciever = ((MTGCardInstance*)target)->controller();
                break;
            }
        case TargetChooser::TARGETED_PLAYER:
            {
                tokenReciever = source->playerTarget;
                break;
            }
        default:
            tokenReciever = source->controller();
            break;
        }
    }
    
    void livingWeaponToken(MTGCardInstance * card)
    {
        for (size_t i = 1; i < game->mLayers->actionLayer()->mObjects.size(); i++)
        {
            MTGAbility * a = ((MTGAbility *) game->mLayers->actionLayer()->mObjects[i]);
            if (a->aType == MTGAbility::STANDARD_EQUIP && a->source == source)
            {
                AEquip* ae = dynamic_cast<AEquip*>(a);
                ae->unequip();
                ae->equip(card);  
            }
        }
    }

    void battleReadyToken(MTGCardInstance * card)
    {
        card->summoningSickness = 0;
        card->tap();
        card->setAttacker(1);
    }

    const string getMenuText()
    {
        sprintf(menuText, "Create %s", name.c_str());
        return menuText;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ATokenCreator ::: abilities : ?" // << abilities
                << " ; types : ?" // << types
                << " ; colors : ?" // << colors
                << " ; power : " << power << " ; toughness : " << toughness << " ; name : " << name << " ; who : " << who << " (";
        return ActivatedAbility::toString(out) << ")";
    }

    ATokenCreator * clone() const
    {
        ATokenCreator * a = NEW ATokenCreator(*this);
        a->multiplier = NEW WParsedInt(*(multiplier));
        return a;
    }

    ~ATokenCreator()
    {
        SAFE_DELETE(multiplier);
    }

};

//targetable abilities which are added to targeted players game.
class ATargetedAbilityCreator: public ActivatedAbility
{
public:
    string name;
    string sabilities;
    int who;
    MTGCardInstance * myDummy;
    Player * abilityReciever;
    ATargetedAbilityCreator(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable *, ManaCost * _cost,string _name, string abilityToAdd, int who = 0) :
    ActivatedAbility(observer, _id, _source, _cost, 0),name(_name),sabilities(abilityToAdd), who(who)
    {
    }

    int resolve()
    {
        setAbilityOwner();
        myDummy = NEW MTGCardInstance();
        setAbilityOwner();
        myDummy->setObserver(abilityReciever->getObserver());
        myDummy->owner = abilityReciever;
        myDummy->lastController = abilityReciever;
        myDummy->storedSourceCard = source;
        vector<string>magictextlines = split(sabilities,'_');
        if(magictextlines.size())
        {
            string newMagicText = "";
            for(unsigned int i = 0; i < magictextlines.size(); i++)
            {
                newMagicText.append(magictextlines[i]);
                newMagicText.append("\n");
            }
            myDummy->magicText = newMagicText;
        }
        else
        myDummy->magicText = sabilities;
        abilityReciever->game->garbage->addCard(myDummy);
        Spell * spell = NEW Spell(game, myDummy);
        spell->resolve();
        myDummy = spell->source;
        spell->source->owner = abilityReciever;
        delete spell;
        return 1;
    }

    void setAbilityOwner()
    {
        switch(who)
        {
        case TargetChooser::CONTROLLER:
            abilityReciever = source->controller();
            break;
        case TargetChooser::OPPONENT:
            abilityReciever = source->controller()->opponent();
            break;
        case TargetChooser::TARGET_CONTROLLER:
            if(target)
            {
                abilityReciever = ((MTGCardInstance*)target)->controller();
                break;
            }
        case TargetChooser::TARGETED_PLAYER:
            {
                abilityReciever = source->playerTarget;
                break;
            }
        default:
            abilityReciever = source->controller()->opponent();
            break;
        }
    }
    
    const string getMenuText()
    {
        if(name.size())
            return name.c_str();
        return "Ability";
    }

    ATargetedAbilityCreator * clone() const
    {
        ATargetedAbilityCreator * a = NEW ATargetedAbilityCreator(*this);
        return a;
    }

    ~ATargetedAbilityCreator()
    {
    }

};
///
//a paired lord
class APaired: public MTGAbility, public NestedAbility
{
public:
    MTGAbility * a;
    MTGAbility * b;
    APaired(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, MTGAbility * ability) :
        MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
    {
        ability->source = source;
        ability->target = target;
        a = NULL;
    }

    int removeFromGame()
    {
        return removeAbilityFromGame();
    }

    int addToGame()
    {
        return MTGAbility::addToGame();
    }

    void Update(float)
    {
        resolve();
    }

    int resolve()
    {
        if (source->myPair)
        {
            addAbilityToGame();
        }
        else
        {
            removeAbilityFromGame();
        }
        if (ability->oneShot) a = NULL; //allows to call the effect several times
        return 1;
    }

    int addAbilityToGame()
    {
        if (a && b) return 0;
        a = ability->clone();
        b = ability->clone();
        a->source = source;
        a->target = source;
        b->source = source->myPair;
        b->target = source->myPair;
        if (a->oneShot)
        {
            a->resolve();
            b->resolve();
            SAFE_DELETE(a);
            SAFE_DELETE(b);
        }
        else
        {
            a->addToGame();
            b->addToGame();
        }
        return 1;
    }

    int destroy()
    {
        return removeAbilityFromGame();
    }

    int removeAbilityFromGame()
    {
        if (!a && !b) return 0;
        game->removeObserver(a);
        a = NULL;
        game->removeObserver(b);
        b = NULL;
        return 1;
    }

    ~APaired()
    {
        SAFE_DELETE(ability);
    }

    APaired * clone() const
    {
        APaired * a =  NEW APaired(*this);
        a->ability = ability->clone();
        return a;
    }
};

//Foreach (plague rats...)
class AForeach: public ListMaintainerAbility, public NestedAbility
{
public:
    int includeSelf;
    int mini;
    int maxi;
    map<Damageable *, MTGAbility *> abilities;
    AForeach(GameObserver* observer, int _id, MTGCardInstance * card, Damageable * _target, TargetChooser * _tc, int _includeSelf, MTGAbility * a,
            int mini = 0, int maxi = 0) :
        ListMaintainerAbility(observer, _id, card, _target), NestedAbility(a), mini(mini), maxi(maxi)
    {
        tc = _tc;
        tc->targetter = NULL;
        includeSelf = _includeSelf;
        ability->target = _target;
        aType = MTGAbility::FOREACH;
        naType = ability->aType;
    }

        int canBeInList(MTGCardInstance * card)
        {
            if(card->isPhased || source->isPhased)
                return 0;
            if ((includeSelf || card != source) && tc->canTarget(card)) return 1;
            return 0;
        }

    int added(MTGCardInstance * card)
    {
        if (mini && cards.size() <= (size_t) mini) return 0;
        if (maxi && cards.size() >= (size_t) maxi) return 0;

        MTGAbility * a = ability->clone();
        a->target = target;
        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            a->addToGame();
            abilities[card] = a;
        }
        return 1;
    }

    int removed(MTGCardInstance * card)
    {
        if (abilities.find(card) != abilities.end())
        {
            game->removeObserver(abilities[card]);
            abilities.erase(card);
            return 1;
        }
        return 0;
    }

    const string getMenuText()
    {
        return ability->getMenuText();
    }

    AForeach * clone() const
    {
        AForeach * a = NEW AForeach(*this);
        a->ability = ability->clone();
        return a;
    }

    int resolve()
    {
        //TODO check if ability is oneShot ?
        updateTargets();
        cards.clear();
        players.clear();
        return 1;
    }

    int checkActivation()
    {
        checkCards.clear();
        checkTargets();
        return checkCards.size();
    }

    ~AForeach()
    {
        SAFE_DELETE(ability);
    }

};

class AThis: public MTGAbility, public NestedAbility
{
public:
    MTGAbility * a;
    ThisDescriptor * td;
    string restrictionCheck;
    AThis(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability, string restriction = "") :
        MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
    {
        td = _td;
        restrictionCheck = restriction;
        ability->source = source;
        ability->target = target;
        a = NULL;
        SAFE_DELETE(tc);
    }

    int removeFromGame()
    {
        return removeAbilityFromGame();
    }

    int addToGame()
    {
        return MTGAbility::addToGame();
    }

    void Update(float)
    {
        resolve();
    }

    int resolve()
    {
        int match = 0;
        if (td)
        {
            match = td->match(source);
        }
        else
        {//restriction check instead of Targetchooser
            AbilityFactory abf(target->getObserver());
            int checkCond = abf.parseCastRestrictions(source, source->controller(), restrictionCheck);
            if (checkCond)
                match = 1;
        }
        if (match > 0)
        {
            addAbilityToGame();
        }
        else
        {
            removeAbilityFromGame();
        }
        if (ability->oneShot) a = NULL; //allows to call the effect several times
        return 1;
    }

    int addAbilityToGame()
    {
        if (a) return 0;
        a = ability->clone();
        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            a->addToGame();
        }
        return 1;
    }

    int removeAbilityFromGame()
    {
        if (!a) return 0;
        game->removeObserver(a);
        a = NULL;
        return 1;
    }

    ~AThis()
    {
        SAFE_DELETE(ability);
        SAFE_DELETE(td);
    }

    AThis * clone() const
    {
        AThis * a =  NEW AThis(*this);
        a->ability = ability->clone();
        if(a->td)
        a->td = td->clone();
        return a;
    }
};

class AThisForEach: public MTGAbility, public NestedAbility
{
public:
    ThisDescriptor * td;
    vector<MTGAbility *> abilities;
    AThisForEach(GameObserver* observer, int _id, MTGCardInstance * _source, Damageable * _target, ThisDescriptor * _td, MTGAbility * ability) :
        MTGAbility(observer, _id, _source, _target), NestedAbility(ability)
    {
        td = _td;
        ability->source = source;
        ability->target = target;
        SAFE_DELETE(tc);
        aType = FOREACH;
    }

    int removeFromGame()
    {
        return removeAbilityFromGame();
    }

    int addToGame()
    {
        return MTGAbility::addToGame();
    }

    void Update(float)
    {
        resolve();
    }

    int resolve()
    {
        //TODO check if ability is oneShot ?
        int matches;
        matches = td->match(source);
        if (matches > 0)
        {
            if (abilities.size() > (size_t)matches)
            {
                removeAbilityFromGame();
            }
            // i will equal abilities size, then we increment from there
            //abilities size was previously being subtracted from matches
            //tho since it was a nonstatic number, it would stop adding abilities prematurely.
            for (size_t i = abilities.size(); i < (size_t)matches; i++)
            {
                addAbilityToGame();
            }
        }
        return 1;
    }

    int addAbilityToGame()
    {
        MTGAbility * a = ability->clone();
        a->target = target;
        if (a->oneShot)
        {
            a->resolve();
            SAFE_DELETE(a);
        }
        else
        {
            a->addToGame();
            abilities.push_back(a);
            //abilities[abilities.size()] = a;
        }
        return 1;
    }

    int removeAbilityFromGame()
    {
        for (int i = abilities.size(); i > 0; i--)
        {
            game->removeObserver(abilities[i - 1]);
        }
        abilities.clear();
        return 1;
    }

    ~AThisForEach()
    {
        SAFE_DELETE(ability);
        SAFE_DELETE(td);

        if (abilities.size())
        {
            removeAbilityFromGame();
        }
    }

    const string getMenuText()
    {
        return ability->getMenuText();
    }

    AThisForEach * clone() const
    {
        AThisForEach * a =  NEW AThisForEach(*this);
        a->ability = ability->clone();
        a->td = td->clone();
        return a;
    }
};

//Modify Hand
class AModifyHand: public AbilityTP
{
public:
    string hand;
    AModifyHand(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, string hand, int who = TargetChooser::UNSET);
    int addToGame();
    int destroy();
    const string getMenuText();
    AModifyHand * clone() const;
    //~AModifyHand();

};

//set a players hand size
class AASetHand: public ActivatedAbilityTP
{
public:
    int hand;

    AASetHand(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int hand, ManaCost * _cost = NULL,
            int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AASetHand * clone() const;

};

//lifeset
class AALifeSet: public ActivatedAbilityTP
{
public:
    WParsedInt * life;

    AALifeSet(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, WParsedInt * life, ManaCost * _cost = NULL,
            int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AALifeSet * clone() const;
    ~AALifeSet();

};

//lifesetend

class AADamager: public ActivatedAbilityTP
{
public:
    string d;
    bool redirected;

    AADamager(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, string d, ManaCost * _cost = NULL,
             int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    int getDamage();
    AADamager * clone() const;

};

//prevent next damage
class AADamagePrevent: public ActivatedAbilityTP
{
public:
    int preventing;

    AADamagePrevent(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int preventing, ManaCost * _cost = NULL, int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AADamagePrevent * clone() const;
    ~AADamagePrevent();
};

//poison removel
class AAAlterPoison: public ActivatedAbilityTP
{
public:
    int poison;

    AAAlterPoison(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int poison, ManaCost * _cost = NULL,
            int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAAlterPoison * clone() const;
    ~AAAlterPoison();
};
/* Standard Damager, can choose a NEW target each time the price is paid */
class TADamager: public TargetAbility
{
public:

    TADamager(GameObserver* observer, int id, MTGCardInstance * card, ManaCost * _cost, string d, TargetChooser * _tc = NULL) :
        TargetAbility(observer, id, card, _tc, _cost, 0)
    {
        if (!tc) tc = NEW DamageableTargetChooser(game, card);
        ability = NEW AADamager(game, id, card, NULL, d);
    }

    TADamager * clone() const
    {
        return NEW TADamager(*this);
    }
};
//bestow
class ABestow : public ActivatedAbility
{
public:
    MTGCardInstance * _card;
    ABestow(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    ABestow * clone() const;
};

/* Can tap a target for a cost */
class AATapper: public ActivatedAbility
{
public:
    bool _sendNoEvent;
    AATapper(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL, bool _sendNoEvent = true);
    int resolve();
    const string getMenuText();
    AATapper * clone() const;
};

/* Can untap a target for a cost */
class AAUntapper: public ActivatedAbility
{
public:
    AAUntapper(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AAUntapper * clone() const;
};

/*announce card X*/
class AAWhatsX : public ActivatedAbility
{
public:
    int value;
    MTGAbility * costRule;
    AAWhatsX(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * source, int value = 0, MTGAbility * costRule = NULL);
    int resolve();
    const string getMenuText()
    {
        sprintf(menuText, "%i", value);
        return menuText;
    };
    AAWhatsX * clone() const;
};

/* set max level up on a levelup creature this is an Ai hint ability, no effect for players.*/
class AAWhatsMax: public ActivatedAbility
{
public:
    int value;

    AAWhatsMax(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * source, ManaCost * _cost = NULL, int value = 0);
    int resolve();
    AAWhatsMax * clone() const;
};
//counts a targetchooser for use later by other effects
class AACountObject : public ActivatedAbility
{
public:
    string value;

    AACountObject(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * source, ManaCost * _cost = NULL, string value ="");
    int resolve();
    AACountObject * clone() const;
};
/* Can prevent a card from untapping next untap */
class AAFrozen: public ActivatedAbility
{
public:
    bool freeze;
    AAFrozen(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, bool tap, ManaCost * _cost = NULL);
    int resolve();
    const string getMenuText();
    AAFrozen * clone() const;
};
/* ghetto new target*/
class AANewTarget: public ActivatedAbility
{
public:
bool retarget;
bool reequip;
bool newhook;
    AANewTarget(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,bool retarget = false, ManaCost * _cost = NULL, bool reequip = false, bool newhook = false);
    int resolve();
    const string getMenuText();
    AANewTarget * clone() const;
};
/* morph*/
class AAMorph: public ActivatedAbility
{
public:
    vector<MTGAbility *> currentAbilities;
    AAMorph(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target, ManaCost * _cost = NULL);
    int resolve();
    int testDestroy();
    const string getMenuText();
    AAMorph * clone() const;
};
/* flip*/
class AAFlip: public InstantAbility
{
public:
    vector<MTGAbility *> currentAbilities;
    string flipStats;
    AAFlip(GameObserver* observer, int id, MTGCardInstance * card, MTGCardInstance * _target,string flipStats);
    int resolve();
    int testDestroy();
    const string getMenuText();
    AAFlip * clone() const;
};
/* dynamic ability build*/
class AADynamic: public ActivatedAbility
{
public:
enum
{
DYNAMIC_SOURCE_AMOUNT = 1,
DYNAMIC_MYTGT_AMOUNT = 2,
DYNAMIC_MYSELF_AMOUNT = 3,
DYNAMIC_MYFOE_AMOUNT = 4,
DYNAMIC_NB_AMOUNT = 5,

DYNAMIC_ABILITY_TYPE_POWER = 0,
DYNAMIC_ABILITY_TYPE_TOUGHNESS = 1,
DYNAMIC_ABILITY_TYPE_MANACOST = 2,
DYNAMIC_ABILITY_TYPE_COLORS = 3,
DYNAMIC_ABILITY_TYPE_AGE = 4,
DYNAMIC_ABILITY_TYPE_CHARGE = 5,
DYNAMIC_ABILITY_TYPE_ONEONECOUNTERS = 6,
DYNAMIC_ABILITY_TYPE_THATMUCH = 7,
DYNAMIC_ABILITY_TYPE_NB = 8,

DYNAMIC_ABILITY_EFFECT_STRIKE = 0,
DYNAMIC_ABILITY_EFFECT_DRAW = 1,
DYNAMIC_ABILITY_EFFECT_LIFEGAIN = 2,
DYNAMIC_ABILITY_EFFECT_PUMPPOWER = 3,
DYNAMIC_ABILITY_EFFECT_PUMPTOUGHNESS = 4,
DYNAMIC_ABILITY_EFFECT_PUMPBOTH = 5,
DYNAMIC_ABILITY_EFFECT_LIFELOSS = 6,
DYNAMIC_ABILITY_EFFECT_DEPLETE = 7,
DYNAMIC_ABILITY_EFFECT_COUNTERSONEONE = 8,
DYNAMIC_ABILITY_EFFECT_NB = 9,

DYNAMIC_ABILITY_WHO_EACHOTHER = 1,
DYNAMIC_ABILITY_WHO_ITSELF = 2,
DYNAMIC_ABILITY_WHO_TARGETCONTROLLER = 3,
DYNAMIC_ABILITY_WHO_TARGETOPPONENT = 4,
DYNAMIC_ABILITY_WHO_TOSOURCE = 5,
DYNAMIC_ABILITY_WHO_SOURCECONTROLLER = 6,
DYNAMIC_ABILITY_WHO_SOURCEOPPONENT = 7,
DYNAMIC_ABILITY_WHO_NB = 8,

};
int type;
int effect;
int who;
int sourceamount;
int targetamount;
int amountsource;
bool eachother;
bool tosrc;
MTGCardInstance * OriginalSrc;
MTGCardInstance * storedTarget;
MTGAbility * storedAbility;
MTGAbility * clonedStored;
MTGAbility * mainAbility;
string menu;

    AADynamic(GameObserver* observer, int id, MTGCardInstance * card, Damageable * _target,int type = 0,int effect = 0,int who = 0,int amountsource = 1,MTGAbility * storedAbility = NULL, ManaCost * _cost = NULL);
    int resolve();
    int activateMainAbility(MTGAbility * toActivate,MTGCardInstance * source , Damageable * target);
    int activateStored();
    const string getMenuText();
    AADynamic * clone() const;
    ~AADynamic();
};

/* switch power and toughness of target */
class ASwapPT: public InstantAbility
{
public:
    ASwapPT(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        InstantAbility(observer, _id, _source, _target)
    {
        target = _target;
    }

    int resolve()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (_target)
        {
            while (_target->next)
                _target = _target->next; //This is for cards such as rampant growth
            
            if(!_target->isSwitchedPT)
            {
                _target->isSwitchedPT = true;
                _target->switchPT(true);
            }
            else
            {
                _target->isSwitchedPT = false;
                _target->switchPT(false);
            }
        }
        return 1;
    }

    int destroy()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (_target)
        {
            while (_target->next)
                _target = _target->next; //This is for cards such as rampant growth
            
            if(_target->isSwitchedPT)
            {
                _target->isSwitchedPT = false;
                _target->switchPT(false);
            }
        }
        return 1;
    }

    const string getMenuText()
    {
        return "Swap power and toughness";
    }
    ASwapPT * clone() const
    {
        return NEW ASwapPT(*this);
    }
};

class AAExchangeLife: public ActivatedAbilityTP
{
public:
    AAExchangeLife(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, ManaCost * _cost = NULL,
             int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAExchangeLife * clone() const;

};

// Add life of gives damage if a given zone has more or less than [condition] cards at the beginning of [phase]
//Ex : the rack, ivory tower...
class ALifeZoneLink: public MTGAbility
{
public:
    int phase;
    int condition;
    int life;
    int controller;
    int nbcards;
    MTGGameZone * zone;
    ALifeZoneLink(GameObserver* observer, int _id, MTGCardInstance * card, int _phase, int _condition, int _life = -1, int _controller = 0,
            MTGGameZone * _zone = NULL) :
        MTGAbility(observer, _id, card)
    {
        phase = _phase;
        condition = _condition;
        controller = _controller;
        life = _life;
        zone = _zone;
        if (zone == NULL)
        {
            if (controller)
            {
                zone = game->currentPlayer->game->hand;
            }
            else
            {
                zone = game->opponent()->game->hand;
            }
        }
    }

    void Update(float)
    {
        if (newPhase != currentPhase && newPhase == phase && !game->currentPlayer->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
        {
            if ((controller && game->currentPlayer == source->controller()) || (!controller && game->currentPlayer
                    != source->controller()))
            {
                if ((condition < 0 && zone->nb_cards < -condition) || (condition > 0 && zone->nb_cards > condition))
                {
                    int diff = zone->nb_cards - condition;
                    if (condition < 0) diff = -condition - zone->nb_cards;
                    if (life > 0)
                    {
                        game->currentPlayer->life += life * diff;
                    }
                    else
                    {
                        game->mLayers->stackLayer()->addDamage(source, game->currentPlayer, -life * diff);
                    }
                }
            }
        }
    }
    virtual ostream& toString(ostream& out) const
    {
        out << "ALifeZoneLink ::: phase : " << phase << " ; condition : " << condition << " ; life : " << life
                << " ; controller : " << controller << " ; nbcards : " << nbcards << " (";
        return MTGAbility::toString(out) << ")";
    }
    ALifeZoneLink * clone() const
    {
        return NEW ALifeZoneLink(*this);
    }
};

//Creatures that cannot attack if opponent has not a given type of land, and die if controller has not this type of land
//Ex : pirate ship...
class AStrongLandLinkCreature: public MTGAbility
{
public:
    char land[20];
    AStrongLandLinkCreature(GameObserver* observer, int _id, MTGCardInstance * _source, const char * _land) :
        MTGAbility(observer, _id, _source)
    {
        sprintf(land, "%s", _land);
    }

    void Update(float)
    {
        if (newPhase != currentPhase && (newPhase == MTG_PHASE_COMBATBEGIN || newPhase == MTG_PHASE_COMBATATTACKERS))
        {
            if (source->controller()->opponent()->game->inPlay->hasType(land))
            {
                source->basicAbilities[(int)Constants::CANTATTACK] = 0;
            }
            else
            {
                source->basicAbilities[(int)Constants::CANTATTACK] = 1;
            }
        }
        Player * player = source->controller();
        if (!player->game->inPlay->hasType(land))
        {
            player->game->putInGraveyard(source);
        }
    }
    virtual ostream& toString(ostream& out) const
    {
        out << "AStrongLandLinkCreature ::: land : " << land << " (";
        return MTGAbility::toString(out) << ")";
    }
    AStrongLandLinkCreature * clone() const
    {
        return NEW AStrongLandLinkCreature(*this);
    }
};

//Steal control of a target
class AControlStealAura: public MTGAbility
{
public:
    Player * originalController;
    AControlStealAura(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        MTGAbility(observer, _id, _source, _target)
    {
        originalController = _target->controller();
        MTGCardInstance * copy = _target->changeController(game->currentlyActing());
        target = copy;
        source->target = copy;
    }

    int destroy()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        Player * p = _target->controller();
        if (p && p->game->inPlay->hasCard(_target))
        { //if the target is still in game -> spell was destroyed
            _target->changeController(originalController);
        }
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AControlStealAura ::: originalController : " << originalController << " (";
        return MTGAbility::toString(out) << ")";
    }
    AControlStealAura * clone() const
    {
        return NEW AControlStealAura(*this);
    }
};
//bloodthirst ability------------------------------------------
class ABloodThirst: public MTGAbility
{
public:
    int amount;
    ABloodThirst(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int amount) :
        MTGAbility(observer, id, source, target), amount(amount)
    {
    }

    int addToGame()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        for (int i = 0; i < amount; i++)
        {
            if (_target->controller()->opponent()->damaged() > 0)
            {
                _target->counters->addCounter(1, 1);
            }
        }
        return MTGAbility::addToGame();
    }

    ABloodThirst * clone() const
    {
        return NEW ABloodThirst(*this);
    }

    ~ABloodThirst()
    {
    }
};

//reduce or increase manacost of target by color:amount------------------------------------------
class AAlterCost: public MTGAbility
{
public:
MTGCardInstance * manaReducer;
    int amount;
    int tempAmount;
    int type;
    AAlterCost(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int amount, int type);
    int addToGame();
    int destroy();
    int testDestroy();
    void refreshCost(MTGCardInstance * card = NULL);
    void increaseTheCost(MTGCardInstance * card = NULL);
    void decreaseTheCost(MTGCardInstance * card = NULL);
    AAlterCost * clone() const;
    ~AAlterCost();
};

//------------------------------------
class ATransformer: public MTGAbility
{
public:
    list<int> abilities;
    list<int> types;
    list<int> colors;
    list<int> oldcolors;
    list<int> oldtypes;
    vector<int> dontremove;
    bool addNewColors;
    bool remove;
    bool removeCreatureSubtypes;
    bool removeTypes;
    string menu;
    
    string newpower;
    bool newpowerfound;
    string newtoughness;
    bool newtoughnessfound;

    map<Damageable *, vector<MTGAbility *> > newAbilities;
    vector<string> newAbilitiesList;
    bool newAbilityFound;
    bool aForever;
    bool UYNT;
    int myCurrentTurn;
    string menutext; //this overrides the previous.
    ATransformer(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string stypes, string sabilities,string newpower,bool newpowerfound,string newtoughness,bool newtoughnessfound,vector<string> newAbilitiesList,bool newAbilityFound = false,bool aForever = false ,bool UYNT = false,string menutext = "");
    int addToGame();
    int reapplyCountersBonus(MTGCardInstance * rtarget= NULL,bool powerapplied=false,bool toughnessapplied=false);
    int testDestroy();
    int destroy();
    const string getMenuText();
    ATransformer * clone() const;
    ~ATransformer();
};

//Adds types/abilities/changes color to a card (generally until end of turn)
class ATransformerInstant: public InstantAbility
{
public:
    ATransformer * ability;
    string newpower;
    bool newpowerfound;
    string newtoughness;
    bool newtoughnessfound;
    vector<string> newAbilitiesList;
    map<Damageable *, vector<MTGAbility *> > newAbilities;
    bool newAbilityFound;
    bool aForever;
    bool UYNT;
    string menu;

    ATransformerInstant(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string types = "", string abilities = "",string newpower = "",bool newpowerfound = false,string newtoughness = "",bool newtoughnessfound = false,vector<string>newAbilitiesList = vector<string>(),bool newAbilityFound = false,bool aForever = false, bool UYNT = false,string menutext = "");
    int resolve();
    const string getMenuText();
    ATransformerInstant * clone() const;
    ~ATransformerInstant();
};

//Adds types/abilities/changes color to a card (generally until end of turn)
class PTInstant: public InstantAbility
{
public:
    APowerToughnessModifier * ability;
    WParsedPT * wppt;
    string s;
    bool nonstatic;
    WParsedPT * newWppt;
    PTInstant(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, WParsedPT * wppt,string s = "",bool nonstatic = false);
    int resolve();
    const string getMenuText();
    PTInstant * clone() const;
    ~PTInstant();
};

//ExaltedAbility (Shards of Alara)
class AExalted: public TriggeredAbility
{
public:
    int power, toughness;
    MTGCardInstance * luckyWinner;
    AExalted(GameObserver* observer, int _id, MTGCardInstance * _source, int _power = 1, int _toughness = 1) :
        TriggeredAbility(observer, _id, _source), power(_power), toughness(_toughness)
    {
        luckyWinner = NULL;
    }

    int triggerOnEvent(WEvent * event)
    {
        if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event))
        {
            if (luckyWinner && MTG_PHASE_AFTER_EOT == pe->from->id)
            {
                luckyWinner = NULL;
            }

            if (MTG_PHASE_COMBATATTACKERS == pe->from->id)
            {
                int nbattackers = 0;
                MTGGameZone * z = source->controller()->game->inPlay;
                int nbcards = z->nb_cards;
                for (int i = 0; i < nbcards; ++i)
                {
                    MTGCardInstance * c = z->cards[i];
                    if (c->attacker)
                    {
                        nbattackers++;
                        luckyWinner = c;
                    }
                }
                if (nbattackers == 1)
                    return 1;
                else
                    luckyWinner = NULL;
            }
        }
        return 0;
    }

    int resolve()
    {
        if (!luckyWinner) return 0;
        PTInstant * a = NEW PTInstant(game, this->GetId(), source, luckyWinner,NEW WParsedPT(1,1));
        GenericInstantAbility * wrapper = NEW GenericInstantAbility(game, 1, source,luckyWinner, a);
        wrapper->addToGame();
        luckyWinner = NULL;
        return 1;
    }

    const string getMenuText()
    {
        return "Exalted";
    }

    AExalted * clone() const
    {
        return NEW AExalted(*this);
    }
};

//switch p/t ueot
class ASwapPTUEOT: public InstantAbility
{
public:
    ASwapPT * ability;
    ASwapPTUEOT(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target);
    int resolve();
    const string getMenuText();
    ASwapPTUEOT * clone() const;
    ~ASwapPTUEOT();
};

class APreventDamageTypes: public MTGAbility
{
public:
    string to, from;
    REDamagePrevention * re;
    int type;

    APreventDamageTypes(GameObserver* observer, int id, MTGCardInstance * source, string to, string from, int type = 0);
    int addToGame();
    int destroy();
    APreventDamageTypes * clone() const;
    ~APreventDamageTypes();
};
//prevent counters
class ACounterShroud: public MTGAbility
{
public:
    TargetChooser * csTc;
    Counter * counter;
    RECountersPrevention * re;
    ACounterShroud(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target,TargetChooser * tc, Counter * counter = NULL);
    int addToGame();
    int destroy();
    ACounterShroud * clone() const;
    ~ACounterShroud();
};
//track an effect using counters.
class ACounterTracker: public MTGAbility
{
public:
    string scounter;
    int removed;
    ACounterTracker(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, string scounter = "");
    int addToGame();
    int destroy();
    int testDestroy();
    ACounterTracker * clone() const;
    ~ACounterTracker();
};
//Remove all abilities from target
class ALoseAbilities: public MTGAbility
{
public:
    vector <MTGAbility *> storedAbilities;
    ALoseAbilities(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target);
    int addToGame();
    int destroy();
    ALoseAbilities * clone() const;
};

//Remove subtypes (of a given type) from target
class ALoseSubtypes: public MTGAbility
{
public:
    int parentType;
    vector <int> storedSubtypes;
    ALoseSubtypes(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int parentType);
    int addToGame();
    int destroy();
    ALoseSubtypes * clone() const;
};

//Adds types/abilities/P/T to a card (until end of turn)
class APreventDamageTypesUEOT: public InstantAbility
{
public:
    APreventDamageTypes * ability;
    vector<APreventDamageTypes *> clones;
    int type;
    APreventDamageTypesUEOT(GameObserver* observer, int id, MTGCardInstance * source, string to, string from, int type = 0);
    int resolve();
    int destroy();
    const string getMenuText();
    APreventDamageTypesUEOT * clone() const;
    ~APreventDamageTypesUEOT();
};

//vanishing
class AVanishing: public MTGAbility
{
public:
    int timeLeft;
    int amount;
    string counterName;
    int next;

    AVanishing(GameObserver* observer, int _id, MTGCardInstance * card, ManaCost * _cost, int restrictions = 0,int amount = 0,string counterName = "");
    void Update(float dt);
    int resolve();
    const string getMenuText();
    AVanishing * clone() const;
    ~AVanishing();
};

//Produce Mana when tapped for mana...
class AProduceMana: public MTGAbility
{
public:
    string ManaDescription;
    string mana[5];

    AProduceMana(GameObserver* observer, int _id, MTGCardInstance * _source, string _ManaDescription);
    int receiveEvent(WEvent * event);
    int produce();
    const string getMenuText();
    //virtual ostream& toString(ostream& out) const;
    AProduceMana * clone() const;
    ~AProduceMana();
};

//Produce Mana when a mana is engaged...
class AEngagedManaAbility: public MTGAbility
{
public:
    string colorname;
    AEngagedManaAbility(GameObserver* observer, int _id, MTGCardInstance * _source, string _colorname) :
    MTGAbility(observer, _id, _source)
    {
        colorname = _colorname;
    }
    int receiveEvent(WEvent * event)
    {
        if(WEventEngageMana * isManaProduced = dynamic_cast<WEventEngageMana *> (event))
        {
            if ((isManaProduced->card == source) && isManaProduced->color == Constants::GetColorStringIndex(colorname))
            {
                source->controller()->getManaPool()->add(Constants::GetColorStringIndex(colorname),1,source,true);
            }
        }
        return 1;
    }
    AEngagedManaAbility * clone() const
    {
        return NEW AEngagedManaAbility(*this);
    }
};

//Upkeep Cost
class AUpkeep: public ActivatedAbility, public NestedAbility
{
public:
    int paidThisTurn;
    int phase;
    int once;
    bool Cumulative;
    int currentage;
    ManaCost * backupMana;

    AUpkeep(GameObserver* observer, int _id, MTGCardInstance * card, MTGAbility * a, ManaCost * _cost, int restrictions = 0, int _phase =
        MTG_PHASE_UPKEEP, int _once = 0,bool Cumulative = false);
    int receiveEvent(WEvent * event);
    void Update(float dt);
    int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
    int resolve();
    const string getMenuText();
    virtual ostream& toString(ostream& out) const;
    AUpkeep * clone() const;
    ~AUpkeep();
};

//phase based actions
class APhaseAction: public MTGAbility
{
public:
    string psMenuText;
    int abilityId;
    string sAbility;
    int phase;
    MTGAbility * ability;
    bool forcedestroy;
    bool next;
    bool myturn;
    bool opponentturn;
    bool once;
    bool checkexile;
    Player * abilityOwner;

    APhaseAction(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase =
        MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = true,bool opponentturn = true,bool once = false, bool checkexile = false);
    void Update(float dt);
    int resolve();
    const string getMenuText();
    APhaseAction * clone() const;
    ~APhaseAction();
};

//Adds types/abilities/P/T to a card (until end of turn)
class APhaseActionGeneric: public InstantAbility
{
public:
    string sAbility;
    APhaseAction * ability;
    APhaseActionGeneric(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * target, string sAbility, int restrictions = 0, int _phase =
            MTG_PHASE_UPKEEP,bool forcedestroy = false,bool next = true,bool myturn = false,bool opponentturn = false,bool once = false,bool checkexile = false);
    int resolve();
    const string getMenuText();
    APhaseActionGeneric * clone() const;
    ~APhaseActionGeneric();

};

//AAttackSetCost
class AAttackSetCost: public MTGAbility
{
public:
    string number;
    bool pw;
    AAttackSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number, bool pw = false);
    void Update(float dt);
    int addToGame();
    int destroy();
    const string getMenuText();
    AAttackSetCost * clone() const;
};

//ABlockSetCost
class ABlockSetCost: public MTGAbility
{
public:
    string number;
    ABlockSetCost(GameObserver* observer, int _id, MTGCardInstance * _source, string number);
    void Update(float dt);
    int addToGame();
    int destroy();
    const string getMenuText();
    ABlockSetCost * clone() const;
};

//AShackle
class AShackle: public MTGAbility
{
public:
    MTGCardInstance * Shackled;
    Player * previousController;
    bool resolved;
    AShackle(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target);
    void Update(float dt);
    void resolveShackle();
    int resolve();
    const string getMenuText();
    AShackle * clone() const;
    ~AShackle();
private:
    void returntoOwner(MTGCardInstance *_target);
};

//ShackleWrapper
class AShackleWrapper: public InstantAbility
{
public:
    AShackle * ability;
    AShackleWrapper(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target);
    int resolve();
    const string getMenuText();
    AShackleWrapper * clone() const;
    ~AShackleWrapper();

};
//Grant
class AGrant : public MTGAbility
{
public:
    MTGCardInstance * Blessed;
    bool resolved;
    MTGAbility * Granted;
    MTGAbility * toGrant;
    AGrant(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target, MTGAbility * toGrant);
    void Update(float dt);
    void resolveGrant();
    int resolve();
    const string getMenuText();
    AGrant * clone() const;
    ~AGrant();
private:
    void removeGranted(MTGCardInstance *_target);
};

//GrantWrapper
class AGrantWrapper : public InstantAbility
{
public:
    AGrant * ability;
    MTGAbility * Granted;
    AGrantWrapper(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target, MTGAbility * toGrant);
    int resolve();
    const string getMenuText();
    AGrantWrapper * clone() const;
    ~AGrantWrapper();

};
//ABlink
class ABlink: public MTGAbility
{
public:
    bool blinkueot;
    bool blinkForSource;
    bool blinkhand;
    MTGCardInstance * Blinked;
    bool resolved;
    MTGAbility * stored;
    ABlink(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target, bool blinkueot = false, bool blinkForSource = false, bool blinkhand = false, MTGAbility * stored = NULL);
    void Update(float dt);
    void resolveBlink();
    int resolve();
    const string getMenuText();
    ABlink * clone() const;
    ~ABlink();
private:
    void returnCardIntoPlay(MTGCardInstance *_target);
};

//blinkinstant
class ABlinkGeneric: public InstantAbility
{
public:
    bool blinkueot;
    bool blinkForSource;
    bool blinkhand;
    ABlink * ability;
    MTGAbility * stored;
    ABlinkGeneric(GameObserver* observer, int _id, MTGCardInstance * card, MTGCardInstance * _target,bool blinkueot=false,bool blinkForSource = false,bool blinkhand = false,MTGAbility * stored = NULL);
    int resolve();
    const string getMenuText();
    ABlinkGeneric * clone() const;
    ~ABlinkGeneric();

};

class AManaPoolSaver: public MTGAbility
{
public:
    string Color;
    bool OtherPlayer;
    AManaPoolSaver(GameObserver* observer, int id, MTGCardInstance * source,string Color = "",bool otherPlayer = false);
    int addToGame();
    int destroy();
    AManaPoolSaver * clone() const;
    ~AManaPoolSaver();
};

class ADrawReplacer: public MTGAbility
{
public:
    REDrawReplacement * re;
    MTGAbility * replacer;
    bool OtherPlayer;
    ADrawReplacer(GameObserver* observer, int id, MTGCardInstance * source, MTGAbility * _replace = NULL,bool otherPlayer = false);
    int addToGame();
    int destroy();
    ADrawReplacer * clone() const;
    ~ADrawReplacer();
};
/*
 Specific Classes
 */

// 1092 Specific to Aladdin's Lamp
class AAladdinsLamp: public TargetAbility
{
public:
    CardDisplay cd;
    int nbcards;
    int init;

    AAladdinsLamp(GameObserver* observer, int id, MTGCardInstance * card) :
        TargetAbility(observer, id, card), cd(1, game, SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2, NULL)
    {
        setCost(NEW ManaCost(), true);
        getCost()->x();
        int zones[] = { MTGGameZone::MY_LIBRARY };
        tc = NEW TargetZoneChooser(game, zones, 1, source);
        nbcards = 0;
        init = 0;
    }

    void Update(float dt)
    {
        if (waitingForAnswer)
        {
            if (!init)
            {
                cd.resetObjects();
                int wished = game->currentlyActing()->getManaPool()->getConvertedCost();
                game->currentlyActing()->getManaPool()->pay(getCost());
                nbcards = 0;
                MTGGameZone * library = game->currentlyActing()->game->library;
                while (nbcards < wished)
                {
                    cd.AddCard(library->cards[library->nb_cards - 1 - nbcards]);
                    nbcards++;
                }
                init = 1;
                Render(dt);
            }
            cd.Update(dt);

            //      cd.CheckUserInput(dt);
        }
    }

    using TargetAbility::Render;
    void Render(float)
    {
        if (waitingForAnswer)
        {
            cd.Render();
        }
    }

    int fireAbility()
    {
        source->tap();
        MTGLibrary * library = game->currentlyActing()->game->library;
                MTGHand * hand = game->currentlyActing()->game->hand;
        MTGCardInstance * card = library->removeCard(tc->getNextCardTarget());
        //library->shuffleTopToBottom(nbcards - 1);
        hand->addCard(card);
        init = 0;
        return 1;
    }

    int resolve()
    {
        return 1;
    }
    ;

    virtual ostream& toString(ostream& out) const
    {
        out << "AAladdinsLamp ::: cd : " << cd << " ; nbcards  : " << nbcards << " ; init : " << init << " (";
        return TargetAbility::toString(out) << ")";
    }
    AAladdinsLamp * clone() const
    {
        return NEW AAladdinsLamp(*this);
    }
};

// Armageddon Clock
class AArmageddonClock: public MTGAbility
{
public:
    int counters;
    ManaCost cost;
    AArmageddonClock(GameObserver* observer, int id, MTGCardInstance * _source) :
        MTGAbility(observer, id, _source)
    {
        counters = 0;
        std::vector<int16_t> _cost;
        _cost.push_back(Constants::MTG_COLOR_ARTIFACT);
        _cost.push_back(4);
        cost = ManaCost(_cost, 1);
    }

    void Update(float)
    {
        if (newPhase != currentPhase)
        {
            if (newPhase == MTG_PHASE_UPKEEP && game->currentPlayer->game->inPlay->hasCard(source))
            {
                counters++;
            }
            else if (newPhase == MTG_PHASE_DRAW && counters > 0 && game->currentPlayer->game->inPlay->hasCard(source))
            { //End of upkeep = beginning of draw
                game->mLayers->stackLayer()->addDamage(source, game->players[0],
                        counters);
                game->mLayers->stackLayer()->addDamage(source, game->players[1],
                        counters);
            }
        }
    }
    int isReactingToClick(MTGCardInstance * _card, ManaCost * = NULL)
    {
        if (counters > 0 && _card == source && currentPhase == MTG_PHASE_UPKEEP)
        {
            if (game->currentlyActing()->getManaPool()->canAfford(&cost))
            {
                return 1;
            }
        }
        return 0;
    }

    int reactToClick(MTGCardInstance * _card)
    {
        if (!isReactingToClick(_card)) return 0;
        game->currentlyActing()->getManaPool()->pay(&cost);
        counters--;
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AArmageddonClock ::: counters : " << counters << " ; cost : " << cost << " (";
        return MTGAbility::toString(out) << ")";
    }
    AArmageddonClock * clone() const
    {
        return NEW AArmageddonClock(*this);
    }
};

//1102: Conservator
class AConservator: public MTGAbility
{
public:
    int canprevent;
    ManaCost cost;
    AConservator(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
        canprevent = 0;
        std::vector<int16_t> _cost;
        _cost.push_back(Constants::MTG_COLOR_ARTIFACT);
        _cost.push_back(2);
        cost = ManaCost(_cost, 1);
    }

    int alterDamage(Damage * damage)
    {
        if (canprevent && damage->target == source->controller())
        {
            if (damage->damage >= canprevent)
            {
                damage->damage -= canprevent;
                canprevent = 0;
            }
            else
            {
                canprevent -= damage->damage;
                damage->damage = 0;
            }
        }
        return 1;
    }
    int alterDamage()
    {
        if (canprevent)
        {
            ActionStack * stack = game->mLayers->stackLayer();
            for (int i = stack->mObjects.size() - 1; i >= 0; i--)
            {
                if (!canprevent) return 1;
                Interruptible * current = ((Interruptible *) stack->mObjects[i]);
                if (current->type == ACTION_DAMAGE && current->state == NOT_RESOLVED)
                {
                    Damage * damage = (Damage *) current;
                    alterDamage(damage);
                }
                else if (current->type == ACTION_DAMAGES && current->state == NOT_RESOLVED)
                {
                    DamageStack * damages = (DamageStack *) current;
                    for (int j = damages->mObjects.size() - 1; j >= 0; j--)
                    {
                        alterDamage(((Damage *) damages->mObjects[j]));
                    }
                }
            }
        }
        return 1;
    }

    void Update(float)
    {
        alterDamage();
    }

    int isReactingToClick(MTGCardInstance * _card, ManaCost * = NULL)
    {
        if (_card == source && game->currentlyActing()->game->inPlay->hasCard(source) && !_card->isTapped())
        {
            if (game->currentlyActing()->getManaPool()->canAfford(&cost))
            {
                return 1;
            }
        }
        return 0;
    }

    int reactToClick(MTGCardInstance * _card)
    {
        if (!isReactingToClick(_card)) return 0;
        game->currentlyActing()->getManaPool()->pay(&cost);
        source->tap();
        canprevent = 2;
        alterDamage();
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AConservator ::: canprevent : " << canprevent << " ; cost : " << cost << " (";
        return MTGAbility::toString(out) << ")";
    }
    AConservator * clone() const
    {
        return NEW AConservator(*this);
    }
};

//Kjeldoran Frostbeast
class AKjeldoranFrostbeast: public MTGAbility
{
public:
    MTGCardInstance * opponents[20];
    int nbOpponents;
    AKjeldoranFrostbeast(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
        nbOpponents = 0;
    }

    void Update(float)
    {
        if (newPhase != currentPhase)
        {
            if (newPhase == MTG_PHASE_COMBATEND)
            {
                nbOpponents = 0;
                MTGCardInstance * opponent = source->getNextOpponent();
                while (opponent)
                {
                    opponents[nbOpponents] = opponent;
                    nbOpponents++;
                    opponent = source->getNextOpponent(opponent);
                }
                if (source->isInPlay(game))
                {
                    for (int i = 0; i < nbOpponents; i++)
                    {
                        opponents[i]->destroy();
                    }
                }
            }
        }
    }

    int testDestroy()
    {
        if (!game->isInPlay(source) && currentPhase != MTG_PHASE_UNTAP)
        {
            return 0;
        }
        else
        {
            return MTGAbility::testDestroy();
        }
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AKjeldoranFrostbeast ::: opponents : " << opponents << " ; nbOpponents : " << nbOpponents << " (";
        return MTGAbility::toString(out) << ")";
    }
    AKjeldoranFrostbeast * clone() const
    {
        return NEW AKjeldoranFrostbeast(*this);
    }
};

//1143 Animate Dead
class AAnimateDead: public MTGAbility
{
public:
    AAnimateDead(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        MTGAbility(observer, _id, _source, _target)
    {
        MTGCardInstance * card = _target;

        //Put the card in play again, with all its abilities !
        //AbilityFactory af;
        MTGCardInstance * copy = source->controller()->game->putInZone(card, _target->controller()->game->graveyard,
                source->controller()->game->temp);
        Spell * spell = NEW Spell(game, copy);
        spell->resolve();
        target = spell->source;
        card = spell->source;
        card->power--;
        card->life = card->toughness;
        delete spell;
    }

    int destroy()
    {
        MTGCardInstance * card = (MTGCardInstance *) target;
        card->power++;
        card->controller()->game->putInZone(card, card->controller()->game->inPlay, card->owner->game->graveyard);
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AAnimateDead ::: (";
        return MTGAbility::toString(out) << ")";
    }
    AAnimateDead * clone() const
    {
        return NEW AAnimateDead(*this);
    }
};

//1159 Erg Raiders
class AErgRaiders: public MTGAbility
{
public:
    int attackedThisTurn;
    AErgRaiders(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
        attackedThisTurn = 1;
    }

        void Update(float)
        {
            if (newPhase != currentPhase)
            {
                Player * controller = source->controller();
                if(newPhase == MTG_PHASE_ENDOFTURN)
                {
                    if(!attackedThisTurn && game->currentPlayer == source->controller() && !source->fresh)
                        game->mLayers->stackLayer()->addDamage(source, controller, 2);
                }
                else if (newPhase == MTG_PHASE_UNTAP)
                {

                    if (game->currentPlayer == controller)
                    {
                        attackedThisTurn = 0;
                    }
                }
            }
        }
    
    int receiveEvent(WEvent * event)
    {
        WEventCardAttacked * attacked = dynamic_cast<WEventCardAttacked *> (event);
        if (attacked && !attacked->card->didblocked && attacked->card == source)
        {
            attackedThisTurn = 1;
            return 1;
        }
        return 0;
    }

    AErgRaiders * clone() const
    {
        return NEW AErgRaiders(*this);
    }
};

//Fastbond
class AFastbond: public TriggeredAbility
{
public:

    TargetChooser * counter;
    MaxPerTurnRestriction * landsRestriction;
    int landsPlayedThisTurn;
    AFastbond(GameObserver* observer, int _id, MTGCardInstance * card) :
        TriggeredAbility(observer, _id, card)
    {

        counter = NEW TypeTargetChooser(game, "land");
        landsPlayedThisTurn = source->controller()->game->inPlay->seenThisTurn(counter, Constants::CAST_ALL);
        PlayRestrictions * restrictions = source->controller()->game->playRestrictions;
        landsRestriction = restrictions->getMaxPerTurnRestrictionByTargetChooser(counter);
        restrictions->removeRestriction(landsRestriction);

    }

    void Update(float dt)
    {
        if (newPhase != currentPhase && newPhase == MTG_PHASE_UNTAP)
        {
            landsPlayedThisTurn = 0;
        }
        TriggeredAbility::Update(dt);
    }

    int trigger()
    {
        int landsPlayedThisTurnUpdated = source->controller()->game->inPlay->seenThisTurn(counter, Constants::CAST_ALL);
        if (landsPlayedThisTurnUpdated > 1 && landsPlayedThisTurnUpdated > landsPlayedThisTurn)
        {
            landsPlayedThisTurn = landsPlayedThisTurnUpdated;
            return 1;
        }
        return 0;
    }

    int resolve()
    {
        game->mLayers->stackLayer()->addDamage(source, source->controller(), 1);
        game->mLayers->stackLayer()->resolve();
        return 1;
    }

    int destroy()
    {
        PlayRestrictions  * restrictions = source->controller()->game->playRestrictions;
        if(restrictions->getMaxPerTurnRestrictionByTargetChooser(counter))
            return 1;

        restrictions->addRestriction(landsRestriction);
            return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        return TriggeredAbility::toString(out) << ")";
    }
    AFastbond * clone() const
    {
        return NEW AFastbond(*this);
    }

    ~AFastbond()
    {
        delete counter;
    }
};

//1117 Jandor's Ring
class AJandorsRing: public ActivatedAbility
{
public:
    AJandorsRing(GameObserver* observer, int _id, MTGCardInstance * _source) :
        ActivatedAbility(observer, _id, _source, NEW ManaCost())
    {
        getCost()->add(Constants::MTG_COLOR_ARTIFACT, 2);
    }

    int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL)
    {
        if (!source->controller()->game->hand->hasCard(source->controller()->game->library->lastCardDrawn)) return 0;
        return ActivatedAbility::isReactingToClick(card, mana);
    }

    int resolve()
    {
        source->controller()->game->putInGraveyard(source->controller()->game->library->lastCardDrawn);
        game->mLayers->stackLayer()->addDraw(source->controller());
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AJandorsRing ::: (";
        return ActivatedAbility::toString(out) << ")";
    }
    AJandorsRing * clone() const
    {
        return NEW AJandorsRing(*this);
    }
};

//Power Leak
class APowerLeak: public TriggeredAbility
{
public:
    int damagesToDealThisTurn;
    ManaCost cost;
    APowerLeak(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        TriggeredAbility(observer, _id, _source, _target)
    {
        cost.add(Constants::MTG_COLOR_ARTIFACT, 1);
        damagesToDealThisTurn = 0;
    }

    void Update(float dt)
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (newPhase != currentPhase && newPhase == MTG_PHASE_UPKEEP && _target->controller() == game->currentPlayer)
        {
            damagesToDealThisTurn = 2;
        }
        TriggeredAbility::Update(dt);
    }

    int isReactingToClick(MTGCardInstance * card, ManaCost * = NULL)
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (damagesToDealThisTurn && currentPhase == MTG_PHASE_UPKEEP && card == source && _target->controller()
                == game->currentPlayer)
        {
            if (game->currentPlayer->getManaPool()->canAfford(&cost)) return 1;
        }
        return 0;
    }

    int reactToclick(MTGCardInstance *)
    {
        game->currentPlayer->getManaPool()->pay(&cost);
        damagesToDealThisTurn--;
        return 1;
    }

    int trigger()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (newPhase != currentPhase && newPhase == MTG_PHASE_DRAW && _target->controller() == game->currentPlayer)
        {
            if (damagesToDealThisTurn) return 1;
        }
        return 0;
    }

    int resolve()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        game->mLayers->stackLayer()->addDamage(source, _target->controller(), damagesToDealThisTurn);
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "APowerLeak ::: damagesToDealThisTurn : " << damagesToDealThisTurn << " ; cost : " << cost << " (";
        return TriggeredAbility::toString(out) << ")";
    }
    APowerLeak * clone() const
    {
        return NEW APowerLeak(*this);
    }
};

//1176 Sacrifice
class ASacrifice: public InstantAbility
{
public:
    ASacrifice(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        InstantAbility(observer, _id, _source)
    {
        target = _target;
    }

    int resolve()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (_target->isInPlay(game))
        {
            game->currentlyActing()->game->putInGraveyard(_target);
            int x = _target->getManaCost()->getConvertedCost();
            game->currentlyActing()->getManaPool()->add(Constants::MTG_COLOR_BLACK, x);
        }
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "ASacrifice ::: (";
        return InstantAbility::toString(out) << ")";
    }
    ASacrifice * clone() const
    {
        return NEW ASacrifice(*this);
    }
};

//1288 EarthBind
class AEarthbind: public ABasicAbilityModifier
{
public:
    AEarthbind(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        ABasicAbilityModifier(observer, _id, _source, _target, Constants::FLYING, 0)
    {
        if (value_before_modification)
        {
            Damageable * _target = (Damageable *) target;
            game->mLayers->stackLayer()->addDamage(source, _target, 2);
        }
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AEarthbind ::: (";
        return ABasicAbilityModifier::toString(out) << ")";
    }
    AEarthbind * clone() const
    {
        return NEW AEarthbind(*this);
    }
};

//1291 Fireball
class AFireball: public InstantAbility
{
public:
    AFireball(GameObserver* observer, int _id, MTGCardInstance * card, Spell * spell, int x) :
        InstantAbility(observer, _id, card)
    {
        int nbtargets = spell->getNbTargets();
        int totaldamage = x + 1 - nbtargets;
        int individualdamage = 0;
        if (nbtargets) individualdamage = totaldamage / nbtargets;
        Damageable * _target = spell->getNextDamageableTarget();
        while (_target)
        {
            game->mLayers->stackLayer()->addDamage(source, _target, individualdamage);
            _target = spell->getNextDamageableTarget(_target);
        }
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AFireball ::: (";
        return InstantAbility::toString(out) << ")";
    }
    AFireball * clone() const
    {
        return NEW AFireball(*this);
    }
};

//1351 Island Sanctuary
class AIslandSanctuary: public MTGAbility
{
public:
    int initThisTurn;
    vector<MTGCardInstance*> effectedCards;
    AIslandSanctuary(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
        initThisTurn = 0;
    }

    void Update(float)
    {
        if (currentPhase == MTG_PHASE_UNTAP && game->currentPlayer == source->controller())
        {
            initThisTurn = 0;
            for(unsigned int i = 0; i < effectedCards.size(); i++)
            effectedCards.at(i)->basicAbilities[(int)Constants::CANTATTACK] = 0;
            effectedCards.clear();
        }
        if (initThisTurn && currentPhase == MTG_PHASE_COMBATBEGIN && game->currentPlayer != source->controller())
        {
            MTGGameZone * zone = game->currentPlayer->game->inPlay;
            for (int i = 0; i < zone->nb_cards; i++)
            {
                MTGCardInstance * card = zone->cards[i];
                if (!card->has(Constants::FLYING) && !card->has(Constants::ISLANDWALK) && !card->has(Constants::CANTATTACK))
                {
                    card->basicAbilities[(int)Constants::CANTATTACK] = 1;
                    effectedCards.push_back(card);
                }
            }
        }
    }

    int isReactingToClick(MTGCardInstance * card, ManaCost * = NULL)
    {
        if (card == source && game->currentPlayer == card->controller())
        {
        
            Interruptible * action = game->mLayers->stackLayer()->getAt(-1);
            AADrawer * draw = dynamic_cast <AADrawer *> (action);
            if (draw && draw->aType == MTGAbility::STANDARD_DRAW) 
            return 1;
        }
        return 0;
    }

    int reactToClick(MTGCardInstance * card)
    {
        if (!isReactingToClick(card)) return 0;
        game->mLayers->stackLayer()->Remove(game->mLayers->stackLayer()->getAt(-1));
        initThisTurn = 1;
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AIslandSanctuary ::: initThisTurn : " << initThisTurn << " (";
        return MTGAbility::toString(out) << ")";
    }
    AIslandSanctuary * clone() const
    {
        return NEW AIslandSanctuary(*this);
    }
};

//remove or add a phase.
class APhaseAlter: public TriggeredAbility
{
public:
    Targetable * targetPlayerWho;
    bool adding;
    bool applied;
    Player * who;
    string phaseToAlter;
    int phasetoAlter;
    string targetingString;
    string after;
    bool aNext;
    APhaseAlter(GameObserver* observer, int _id, MTGCardInstance * card,Targetable * targetPlayer, bool _adding,string _phaseToAlter,string targeting, bool _aNext,string _after = "") :
        TriggeredAbility(observer, _id, card),targetPlayerWho(targetPlayer),adding(_adding),phaseToAlter(_phaseToAlter),targetingString(targeting),after(_after),aNext(_aNext)
    {
            applied = false;
            who = NULL;
            phasetoAlter = PhaseRing::phaseStrToInt(phaseToAlter);
    }

        int triggerOnEvent(WEvent * event)
        {
            if(!who)
            {
                Player * targetedPlayer = dynamic_cast<Player*>(target);
                if (targetingString.find("targetedplayer") != string::npos && targetedPlayer)
                {
                    who = targetedPlayer;
                }
                if (targetingString.find("controller") != string::npos)
                    who = source->controller();
                if (targetingString.find("opponent") != string::npos)
                    who = source->controller()->opponent();
                if (targetingString.find("targetcontroller") != string::npos)
                    who = source->target?source->target->controller():source->controller();
                if (targetingString.find("owner") != string::npos)
                    who = source->owner;
            }

            if (after == "this")//apply it right now.
            {
                if(!applied)
                    if (who == game->currentPlayer)
                    {
                        after = game->phaseRing->phaseIntToStr(game->oldGamePhase);
                        addTheEffect(game->currentPlayer->getId());
                        return 1;
                    }
            }

            if (WEventPhasePreChange* pe = dynamic_cast<WEventPhasePreChange*>(event))
            {
                if (MTG_PHASE_CLEANUP == pe->to->id)
                {
                    if( aNext && applied && who != game->currentPlayer)
                    {
                        forceDestroy = 1;
                    }
                }
                if(adding)
                {
                    if(!applied)
                        if (PhaseRing::phaseStrToInt(after) == pe->to->id && who == game->currentPlayer)
                        {
                            pe->eventChanged = true;
                            return 1;
                        }
                }
                else if (PhaseRing::phaseStrToInt(phaseToAlter) == pe->to->id && who == game->currentPlayer)
                {
                    pe->eventChanged = true;
                    return 1;
                }
            }
            return 0;
        }

    int resolve()
    {
        for (int i = 0; i < 2; i++)
        {
            if(who == game->players[i] && game->currentPlayer == game->players[i])
            {
                addTheEffect(i);
            }
        }
        return 1;
    }
    void addTheEffect(int i)
    {
        int turnSteps = game->phaseRing->turn.size();
        if(adding && !applied)
        {
            if(phaseToAlter == "combatphases")
            {
                game->phaseRing->addCombatAfter(game->players[i], PhaseRing::phaseStrToInt(after));
            }
            else if(phaseToAlter == "combatphaseswithmain")
            {
                game->phaseRing->addCombatAfter(game->players[i], PhaseRing::phaseStrToInt(after),true);
            }
            else
                game->phaseRing->addPhaseAfter(PhaseRing::phaseStrToInt(phaseToAlter), game->players[i], PhaseRing::phaseStrToInt(after));
        }
        else if(!adding)
            game->phaseRing->removePhase(PhaseRing::phaseStrToInt(phaseToAlter));
        int turnAfterChange = game->phaseRing->turn.size();
        if(turnSteps != turnAfterChange)
            applied = true;
        return;
    }

    void removeTheEffect(int i)//readd this!!!!!!!!!!!!!
    {
        if(applied)
        {
            if(adding)
                game->phaseRing->removePhase(PhaseRing::phaseStrToInt(phaseToAlter));
            else
                game->phaseRing->addPhaseAfter(PhaseRing::phaseStrToInt(phaseToAlter), game->players[i], PhaseRing::phaseStrToInt(after));
            applied = false;
        }
        return;
    }

    int testDestroy()
    {
        if(forceDestroy != -1)
            return 1;
        if(!(source->hasType(Subtypes::TYPE_INSTANT)||source->hasType(Subtypes::TYPE_INSTANT)) && !source->isInPlay(game))
            return 1;
        return 0;
    }

    int destroy()
    {
        for (int i = 0; i < 2; i++)
        {
            if(who == game->players[i] && game->currentPlayer == game->players[i])
            {
                removeTheEffect(i);
            }
        }
        return 1;
    }

    const string getMenuText()
    {
        return "phase alter";
    }

    APhaseAlter * clone() const
    {
        return NEW APhaseAlter(*this);
    }
};
//Generic Millstone
class AADepleter: public ActivatedAbilityTP
{
public:
    string nbcardsStr;
    bool toexile;
    AADepleter(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost = NULL,
    int who = TargetChooser::UNSET, bool toexile = false);
    int resolve();
    const string getMenuText();
    AADepleter * clone() const;
};


//AACascade
class AACascade: public ActivatedAbility
{
public:
    string nbcardsStr;
    vector<MTGCardInstance*>selectedCards;
    vector<MTGCardInstance *>oldOrder;
    vector<MTGCardInstance *>newOrder;
    AACascade(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target, string nbcardsStr, ManaCost * _cost = NULL);
    int resolve();
    void toCastCard(MTGCardInstance * card);
    const string getMenuText();
    AACascade * clone() const;
};

//Generic skip turn/extra turn
class AAModTurn: public ActivatedAbilityTP
{
public:
    string nbTurnStr;

    AAModTurn(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbTurnStr, ManaCost * _cost = NULL,
            int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAModTurn * clone() const;
};

//Shuffle
class AAShuffle: public ActivatedAbilityTP
{
public:
    AAShuffle(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int who =
            TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAShuffle * clone() const;
};

//Mulligan
class AAMulligan: public ActivatedAbilityTP
{
public:
    AAMulligan(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost = NULL, int who =
            TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AAMulligan * clone() const;
};

//Remove Mana From ManaPool
class AARemoveMana: public ActivatedAbilityTP
{
public:
    ManaCost * mManaDesc;
    bool mRemoveAll;

    AARemoveMana(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target, string ManaDesc, int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AARemoveMana * clone() const;
    ~AARemoveMana();

};

//Random Discard
class AARandomDiscarder: public ActivatedAbilityTP
{
public:
    string nbcardsStr;

    AARandomDiscarder(GameObserver* observer, int _id, MTGCardInstance * card, Targetable * _target,string nbcardsStr, ManaCost * _cost = NULL,
             int who = TargetChooser::UNSET);
    int resolve();
    const string getMenuText();
    AARandomDiscarder * clone() const;
};

//Rampage ability
class ARampageAbility: public MTGAbility
{
public:
    int nbOpponents;
    int PowerModifier;
    int ToughnessModifier;
    int MaxOpponent;

    ARampageAbility(GameObserver* observer, int _id, MTGCardInstance * _source, int _PowerModifier, int _ToughnessModifier, int _MaxOpponent) :
        MTGAbility(observer, _id, _source)
    {
        PowerModifier = _PowerModifier;
        ToughnessModifier = _ToughnessModifier;
        MaxOpponent = _MaxOpponent;
        nbOpponents = 0;
    }
    int receiveEvent(WEvent * event)
    {
        if (dynamic_cast<WEventBlockersChosen*> (event))
        {
            nbOpponents = source->blockers.size();
            if (nbOpponents <= MaxOpponent) return 0;
            if(source->isSwitchedPT)
            {
                source->switchPT(false);
                source->addptbonus(PowerModifier * (nbOpponents - MaxOpponent),ToughnessModifier * (nbOpponents - MaxOpponent));
                source->switchPT(true);
            }
            else
                source->addptbonus(PowerModifier * (nbOpponents - MaxOpponent),ToughnessModifier * (nbOpponents - MaxOpponent));
        }
        else if (WEventPhaseChange* pe = dynamic_cast<WEventPhaseChange*>(event))
        {
            if (MTG_PHASE_AFTER_EOT == pe->to->id && nbOpponents > MaxOpponent)
            {
                if(source->isSwitchedPT)
                {
                    source->switchPT(false);
                    source->removeptbonus(PowerModifier * (nbOpponents - MaxOpponent),ToughnessModifier * (nbOpponents - MaxOpponent));
                    source->switchPT(true);
                }
                else
                    source->removeptbonus(PowerModifier * (nbOpponents - MaxOpponent),ToughnessModifier * (nbOpponents - MaxOpponent));

                    nbOpponents = 0;
            }
        }
        return 1;
    }

    ARampageAbility * clone() const
    {
        return NEW ARampageAbility(*this);
    }
};

//Evole ability
class AEvolveAbility: public MTGAbility
{
public:
    AEvolveAbility(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
    }
        int receiveEvent(WEvent * event)
        {
            WEventZoneChange * enters = dynamic_cast<WEventZoneChange *> (event);
            if (enters && enters->to == enters->card->controller()->game->inPlay)
                if(enters->from != enters->card->controller()->game->inPlay && enters->from != enters->card->controller()->opponent()->game->inPlay) //cards changing from inplay to inplay don't re-enter battlefield
                    if(enters->card->controller() == source->controller() && enters->card->isCreature())
                    {
                        if(enters->card != source && (enters->card->power > source->power || enters->card->toughness > source->toughness))
                        {
                            source->counters->addCounter(1,1);
                        }
                    }
                    return 1;
        }

    AEvolveAbility * clone() const
    {
        return NEW AEvolveAbility(*this);
    }
};

//Reduce to .. Ali from Cairo...
class AReduceToAbility: public MTGAbility
{
public:
    string life_s;

    AReduceToAbility(GameObserver* observer, int _id, MTGCardInstance * _source, string _life_s) :
    MTGAbility(observer, _id, _source)
    {
        life_s = _life_s;
    }
    int receiveEvent(WEvent * event)
    {
        if(WEventDamage * isDamaged = dynamic_cast<WEventDamage *> (event))
        {
            if (isDamaged->damage->target->type_as_damageable == Damageable::DAMAGEABLE_PLAYER)
            {
                Player * p = (Player *) isDamaged->damage->target;
                WParsedInt lifetoset(life_s, NULL, source);
                if(p && p == source->controller() && p->life <= lifetoset.getValue() && !p->inPlay()->hasAbility(Constants::CANTCHANGELIFE))
                    p->life = lifetoset.getValue();
            }
        }
        return 1;
    }
    AReduceToAbility * clone() const
    {
        return NEW AReduceToAbility(*this);
    }
};

//flanking ability
class AFlankerAbility: public MTGAbility
{
public:
    MTGCardInstance * opponents[20];
    int nbOpponents;
    AFlankerAbility(GameObserver* observer, int _id, MTGCardInstance * _source) :
        MTGAbility(observer, _id, _source)
    {
        nbOpponents = 0;
    }
    int receiveEvent(WEvent * event)
    {
        if (dynamic_cast<WEventBlockersChosen*> (event))
        {
            nbOpponents = 0;
            MTGCardInstance * opponent = source->getNextOpponent();
            while (opponent && !opponent->has(Constants::FLANKING) && game->currentlyActing() == source->controller()->opponent())
            {
                opponents[nbOpponents] = opponent;
                nbOpponents++;
                opponent = source->getNextOpponent(opponent);
            }
            for (int i = 0; i < nbOpponents; i++)
            {
                opponents[i]->power -= 1;
                opponents[i]->addToToughness(-1);
                opponents[i]->flanked += 1;
                if (opponents[i]->life == 0)
                {
                    opponents[i]->setPower(0);
                }
            }
        }
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AFlankerAbility ::: opponents : " << opponents << " ; nbOpponents : " << nbOpponents << " (";
        return MTGAbility::toString(out) << ")";
    }

    AFlankerAbility * clone() const
    {
        return NEW AFlankerAbility(*this);
    }
};

//Bushido ability todo:add bushido count.
class ABushidoAbility: public MTGAbility
{
public:
    string PowerToughnessModifier;

    ABushidoAbility(GameObserver* observer, int _id, MTGCardInstance * _source, string _PowerToughnessModifier) :
        MTGAbility(observer, _id, _source)
    {
        PowerToughnessModifier = _PowerToughnessModifier;
    }
        int receiveEvent(WEvent * event)
        {
            if (dynamic_cast<WEventBlockersChosen*> (event))
            {
                MTGCardInstance * opponent = source->getNextOpponent();
                if (!opponent) return 0;
                PTInstant * a = NEW PTInstant(game, this->GetId(), source, source,NEW WParsedPT(PowerToughnessModifier,NULL,source));
                GenericInstantAbility * wrapper = NEW GenericInstantAbility(game, 1, source,source, a);
                wrapper->addToGame();
            }
            return 1;
        }

    ABushidoAbility * clone() const
    {
        return NEW ABushidoAbility(*this);
    }
};

class AACastCard: public MTGAbility
{
public:
    MTGAbility * andAbility;
    bool processed;
    bool restricted;
    bool asCopy;
    bool normal;
    string cardNamed;
    string nameThis;
    MTGCardInstance * theNamedCard;
    bool noEvent;
    bool putinplay;
    bool asNormalMadness;
    AACastCard(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target,bool restricted,bool copied,bool _asNormal,string nameCard,string abilityName,bool _noEvent, bool putinplay,bool asNormalMadness = false);

    int testDestroy(){return 0;};
    void Update(float dt);
    const string getMenuText();
    int isReactingToTargetClick(Targetable * card);
    int reactToTargetClick(Targetable * object);
    MTGCardInstance * makeCard();
    int resolveSpell();
    
    AACastCard * clone() const;
    ~AACastCard();
};

//A Spirit Link Ability
class ASpiritLinkAbility: public MTGAbility
{
public:
    MTGCardInstance * source;
    bool combatonly;
    ASpiritLinkAbility(GameObserver* observer, int _id, MTGCardInstance * _source,bool combatonly = false) :
    MTGAbility(observer, _id, _source),source(_source),combatonly(combatonly)
    {
    }
    int receiveEvent(WEvent * event)
    {
        if (event->type == WEvent::DAMAGE)
        {
            WEventDamage * e = (WEventDamage *) event;
            Damage * d = e->damage;
            if (combatonly && e->damage->typeOfDamage != Damage::DAMAGE_COMBAT)
                return 0;
            MTGCardInstance * card = d->source;
            if (d->damage > 0 && card && (card == source || card == source->target))
            {
                source->owner->gainLife(d->damage);
                return 1;
            }
        }
        return 0;
    }
    ASpiritLinkAbility * clone() const
    {
        return NEW ASpiritLinkAbility(*this);
    }
};

//Instant Steal control of a target
class AInstantControlSteal: public InstantAbility
{
public:
    Player * TrueController;
    Player * TheftController;
    AInstantControlSteal(GameObserver* observer, int _id, MTGCardInstance * _source, MTGCardInstance * _target) :
        InstantAbility(observer, _id, _source, _target)
    {

    }

        int resolve()
        {
            MTGCardInstance * _theftTarget = (MTGCardInstance*)target;
            bool recast = false;
            if(!_theftTarget->isInPlay(game))
            {
                recast = true;
            }
            while(_theftTarget->next)
            {
                _theftTarget= _theftTarget->next;
            }
            if(_theftTarget)
            {
                TrueController = _theftTarget->controller();
                TheftController = source->controller();
                MTGCardInstance * copy = _theftTarget->changeController(TheftController);
                target = copy;
                source->target = copy;
                copy->summoningSickness = 0;
                if(recast)
                {
                    Spell * spell = NEW Spell(game, copy);
                    spell->resolve();
                    SAFE_DELETE(spell);
                }
            }
            return 1;
        }

    int destroy()
    {
        MTGCardInstance * _target = (MTGCardInstance *) target;
        if (TheftController && TheftController->game->inPlay->hasCard(_target))
        { //if the target is still in game -> spell was destroyed
            _target->changeController(TrueController);

        }
        return 1;
    }

    virtual ostream& toString(ostream& out) const
    {
        out << "AInstantControlSteal ::: TrueController : " << TrueController << " ; TheftController : " << TheftController << " (";
        return InstantAbility::toString(out) << ")";
    }

    AInstantControlSteal * clone() const
    {
        return NEW AInstantControlSteal(*this);
    }
};

//----------------------------------------------
class AASetColorChosen: public InstantAbility
{
public:
    int color;
    string abilityToAlter;
    MTGAbility * abilityAltered;
    AASetColorChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int _color = 0 ,string toAdd = "");
    int resolve();
    const string getMenuText();
    AASetColorChosen * clone() const;
    ~AASetColorChosen();
};
class AASetTypeChosen: public InstantAbility
{
public:
    int type;
    string abilityToAlter;
    string menutext;
    MTGAbility * abilityAltered;
    AASetTypeChosen(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int _type = 0,string menu = "error" ,string toAdd = "");
    int resolve();
    const string getMenuText();
    AASetTypeChosen * clone() const;
    ~AASetTypeChosen();
};
class GenericChooseTypeColor: public ActivatedAbility
{
public:
    string baseAbility;
    bool chooseColor;
    AASetColorChosen * setColor;
    AASetTypeChosen * setType;
    bool ANonWall;
    GenericChooseTypeColor(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string toAdd = "",bool chooseColor = false,bool nonwall = false, ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    GenericChooseTypeColor * clone() const;
    ~GenericChooseTypeColor();

};
//------------------------------------------------
//flip a coin and call it, with win or lose abilities
class AASetCoin: public InstantAbility
{
public:
    int side;
    string abilityToAlter;
    string abilityWin;
    string abilityLose;
    MTGAbility * abilityAltered;
    AASetCoin(GameObserver* observer, int id, MTGCardInstance * source, MTGCardInstance * target, int side = -1,string toAdd = "");
    int resolve();
    const string getMenuText();
    AASetCoin * clone() const;
    ~AASetCoin();
};
class GenericFlipACoin: public ActivatedAbility
{
public:
    string baseAbility;
    AASetCoin * setCoin;
    GenericFlipACoin(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, string toAdd = "", ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    GenericFlipACoin * clone() const;
    ~GenericFlipACoin();

};
//------------
class GenericPaidAbility: public ActivatedAbility
{
public:
    MTGAbility * baseAbility;
    ManaCost * optionalCost;
    string newName;
    string restrictions;
    string baseCost;
    string baseAbilityStr;
    bool asAlternate;

    GenericPaidAbility(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target,string _newName,string _castRestriction,string _mayCost, string toAdd, bool asAlternate = false, ManaCost * cost = NULL);
    int resolve();
    const string getMenuText();
    GenericPaidAbility * clone() const;
    ~GenericPaidAbility();

};
// utility functions

void PopulateColorIndexVector(list<int>& colors, const string& colorsString, char delimiter = ',');
void PopulateAbilityIndexVector(list<int>& abilities, const string& abilitiesString, char delimiter = ',');
void PopulateSubtypesIndexVector(list<int>& types, const string& subtypesString, char delimiter = ' ');

#endif
