Erwan
- fixed issue 595 (MaxCast not working). Root cause was the stupidest typo ever in the code (maxCost instead of maxCast...) - fixed an issue with Storm mentioned by zethfox (was counting only spells played by current player) - Moved "max lands per turn" rule outside of the code (yay!) Please be sure to update your Rules folder!
This commit is contained in:
@@ -4,4 +4,5 @@ mode=mtg
|
||||
life:20
|
||||
auto=shuffle
|
||||
auto=draw:7
|
||||
auto=@each my draw:draw:1
|
||||
auto=@each my draw:draw:1
|
||||
auto=maxPlay(land)1
|
||||
@@ -3,4 +3,5 @@
|
||||
mode=mtg
|
||||
[PLAYERS]
|
||||
life:20
|
||||
auto=@each my draw:draw:1
|
||||
auto=@each my draw:draw:1
|
||||
auto=maxPlay(land)1
|
||||
@@ -414,6 +414,7 @@ ondu_cleric.txt
|
||||
OneDozenEyes.txt
|
||||
orcish_artillery.txt
|
||||
orcish_lumberjack.txt
|
||||
orims_chant_i595.txt
|
||||
overrun.txt
|
||||
paradise_mantle.txt
|
||||
paralysis.txt
|
||||
|
||||
23
projects/mtg/bin/Res/test/orims_chant_i595.txt
Normal file
23
projects/mtg/bin/Res/test/orims_chant_i595.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
#Bug with maxCast, see http://code.google.com/p/wagic/issues/detail?id=595
|
||||
#1. Have at least two or more spells in your hand, include Orim's Chant; and have enough mana in your mana pool for these spells
|
||||
#2. Cast Orim's Chant on yourself
|
||||
#3. Cast other spells in your hand
|
||||
[init]
|
||||
firstmain
|
||||
[player1]
|
||||
manapool:{W}{R}{1}{G}
|
||||
hand:Orim's chant,raging goblin, grizzly bears
|
||||
[player2]
|
||||
[do]
|
||||
Orim's chant
|
||||
p1
|
||||
raging goblin
|
||||
grizzly bears
|
||||
[assert]
|
||||
firstmain
|
||||
[player1]
|
||||
graveyard:Orim's chant
|
||||
hand:raging goblin, grizzly bears
|
||||
manapool:{R}{1}{G}
|
||||
[player2]
|
||||
[end]
|
||||
@@ -1469,7 +1469,7 @@ public:
|
||||
abilitygranted = ability;
|
||||
nbTargets = 0;
|
||||
tc = _tc;
|
||||
if (!tc) tc = NEW CreatureTargetChooser(_source);
|
||||
if (!tc) tc = NEW TypeTargetChooser("creature",_source);
|
||||
}
|
||||
|
||||
void Update(float dt)
|
||||
@@ -4738,7 +4738,7 @@ public:
|
||||
counter = NEW TypeTargetChooser("land");
|
||||
landsPlayedThisTurn = source->controller()->game->inPlay->seenThisTurn(counter);
|
||||
PlayRestrictions * restrictions = source->controller()->game->playRestrictions;
|
||||
landsRestriction = (MaxPerTurnRestriction *) (restrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID));
|
||||
landsRestriction = restrictions->getMaxPerTurnRestrictionByTargetChooser(counter);
|
||||
restrictions->removeRestriction(landsRestriction);
|
||||
|
||||
}
|
||||
@@ -4773,7 +4773,7 @@ public:
|
||||
int destroy()
|
||||
{
|
||||
PlayRestrictions * restrictions = source->controller()->game->playRestrictions;
|
||||
if(restrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID))
|
||||
if(restrictions->getMaxPerTurnRestrictionByTargetChooser(counter))
|
||||
return 1;
|
||||
|
||||
restrictions->addRestriction(landsRestriction);
|
||||
@@ -5590,7 +5590,7 @@ class AMinionofLeshrac: public TargetAbility
|
||||
public:
|
||||
int paidThisTurn;
|
||||
AMinionofLeshrac(int _id, MTGCardInstance * source) :
|
||||
TargetAbility(_id, source, NEW CreatureTargetChooser(), 0, 1, 0)
|
||||
TargetAbility(_id, source, NEW TypeTargetChooser("creature"), 0, 1, 0)
|
||||
{
|
||||
paidThisTurn = 1;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,6 @@ class PlayRestriction
|
||||
{
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
LANDS_RULE_ID,
|
||||
UNDEF_ID
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -23,12 +18,11 @@ public:
|
||||
NO_OPINION
|
||||
};
|
||||
|
||||
unsigned int id;
|
||||
TargetChooser * tc;
|
||||
|
||||
virtual int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone) = 0;
|
||||
|
||||
PlayRestriction(unsigned int id, TargetChooser * tc);
|
||||
PlayRestriction(TargetChooser * tc);
|
||||
~PlayRestriction();
|
||||
};
|
||||
|
||||
@@ -41,7 +35,7 @@ public:
|
||||
};
|
||||
int maxPerTurn;
|
||||
MTGGameZone * zone;
|
||||
MaxPerTurnRestriction(unsigned int id, TargetChooser * tc, int maxPerTurn, MTGGameZone * zone);
|
||||
MaxPerTurnRestriction(TargetChooser * tc, int maxPerTurn, MTGGameZone * zone);
|
||||
int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone);
|
||||
};
|
||||
|
||||
@@ -51,7 +45,8 @@ class PlayRestrictions
|
||||
protected:
|
||||
vector<PlayRestriction *>restrictions;
|
||||
public:
|
||||
PlayRestriction * getRestrictionById(unsigned int id);
|
||||
MaxPerTurnRestriction * getMaxPerTurnRestrictionByTargetChooser(TargetChooser * tc);
|
||||
|
||||
void addRestriction(PlayRestriction * restriction);
|
||||
void removeRestriction(PlayRestriction * restriction);
|
||||
int canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone);
|
||||
|
||||
@@ -56,6 +56,11 @@ public:
|
||||
int targetsReadyCheck();
|
||||
virtual int addTarget(Targetable * target);
|
||||
virtual bool canTarget(Targetable * _target);
|
||||
|
||||
//returns true if tc is equivalent to this TargetChooser
|
||||
//Two targetchoosers are equivalent if they target exactly the same cards
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
|
||||
virtual int full()
|
||||
{
|
||||
if (maxtargets != -1 && cursor >= maxtargets)
|
||||
@@ -100,6 +105,7 @@ public:
|
||||
virtual bool canTarget(Targetable * _card);
|
||||
int setAllZones();
|
||||
virtual TargetZoneChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class CardTargetChooser: public TargetZoneChooser
|
||||
@@ -110,43 +116,7 @@ public:
|
||||
CardTargetChooser(MTGCardInstance * card, MTGCardInstance * source, int * zones = NULL, int nbzones = 0);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual CardTargetChooser * clone() const;
|
||||
};
|
||||
|
||||
class CreatureTargetChooser: public TargetZoneChooser
|
||||
{
|
||||
public:
|
||||
CreatureTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false);
|
||||
CreatureTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false);
|
||||
virtual bool canTarget(Targetable * _card);
|
||||
virtual CreatureTargetChooser * clone() const;
|
||||
|
||||
};
|
||||
|
||||
class DamageableTargetChooser: public CreatureTargetChooser
|
||||
{
|
||||
public:
|
||||
DamageableTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) :
|
||||
CreatureTargetChooser(_zones, _nbzones, card, _maxtargets, other)
|
||||
{
|
||||
}
|
||||
;
|
||||
DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) :
|
||||
CreatureTargetChooser(card, _maxtargets, other)
|
||||
{
|
||||
}
|
||||
;
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual DamageableTargetChooser * clone() const;
|
||||
};
|
||||
|
||||
class PlayerTargetChooser: public TargetChooser
|
||||
{
|
||||
protected:
|
||||
Player * p; //In Case we can only target a specific player
|
||||
public:
|
||||
PlayerTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, Player *_p = NULL);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual PlayerTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class TypeTargetChooser: public TargetZoneChooser
|
||||
@@ -160,6 +130,36 @@ public:
|
||||
void addType(const char * type);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual TypeTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class DamageableTargetChooser: public TypeTargetChooser
|
||||
{
|
||||
public:
|
||||
DamageableTargetChooser(int * _zones, int _nbzones, MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) :
|
||||
TypeTargetChooser("creature",_zones, _nbzones, card, _maxtargets, other)
|
||||
{
|
||||
}
|
||||
;
|
||||
DamageableTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, bool other = false) :
|
||||
TypeTargetChooser("creature", card, _maxtargets, other)
|
||||
{
|
||||
}
|
||||
;
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual DamageableTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class PlayerTargetChooser: public TargetChooser
|
||||
{
|
||||
protected:
|
||||
Player * p; //In Case we can only target a specific player
|
||||
public:
|
||||
PlayerTargetChooser(MTGCardInstance * card = NULL, int _maxtargets = 1, Player *_p = NULL);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual PlayerTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class DescriptorTargetChooser: public TargetZoneChooser
|
||||
@@ -171,6 +171,7 @@ public:
|
||||
virtual bool canTarget(Targetable * target);
|
||||
~DescriptorTargetChooser();
|
||||
virtual DescriptorTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class SpellTargetChooser: public TargetChooser
|
||||
@@ -180,6 +181,7 @@ public:
|
||||
SpellTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, bool other = false);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual SpellTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class SpellOrPermanentTargetChooser: public TargetZoneChooser
|
||||
@@ -189,6 +191,7 @@ public:
|
||||
SpellOrPermanentTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, bool other = false);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual SpellOrPermanentTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
class DamageTargetChooser: public TargetChooser
|
||||
@@ -199,6 +202,7 @@ public:
|
||||
DamageTargetChooser(MTGCardInstance * card = NULL, int _color = -1, int _maxtargets = 1, int state = NOT_RESOLVED);
|
||||
virtual bool canTarget(Targetable * target);
|
||||
virtual DamageTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
//Should only be used for triggered abilities.
|
||||
@@ -211,6 +215,7 @@ public:
|
||||
virtual bool targetsZone(MTGGameZone * z);
|
||||
virtual bool canTarget(Targetable * _target);
|
||||
virtual TriggerTargetChooser * clone() const;
|
||||
virtual bool equals(TargetChooser * tc);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1484,14 +1484,14 @@ int ACastRestriction::addToGame()
|
||||
//For now the only modifying rule is the one for lands, so this is hardcoded here.
|
||||
//This means that a modifying rule for anything lands will actually modify the lands rule.
|
||||
//In the future, we need a way to "identify" rules that modify an existing restriction, probably by doing a comparison of the TargetChoosers
|
||||
existingRestriction = (MaxPerTurnRestriction *) (targetPlayer->game->playRestrictions->getRestrictionById(PlayRestriction::LANDS_RULE_ID));
|
||||
existingRestriction = targetPlayer->game->playRestrictions->getMaxPerTurnRestrictionByTargetChooser(restrictionsScope);
|
||||
if(existingRestriction && existingRestriction->maxPerTurn != MaxPerTurnRestriction::NO_MAX)
|
||||
existingRestriction->maxPerTurn += value->getValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetChooser * _tc = restrictionsScope->clone();
|
||||
existingRestriction = NEW MaxPerTurnRestriction(PlayRestriction::UNDEF_ID, _tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer));
|
||||
existingRestriction = NEW MaxPerTurnRestriction(_tc, value->getValue(), MTGGameZone::intToZone(zoneId, source->controller(), targetPlayer));
|
||||
targetPlayer->game->playRestrictions->addRestriction(existingRestriction);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ const size_t kLordKeywordsCount = 5;
|
||||
const string kThisKeywords[] = { "this(", "thisforeach(" };
|
||||
const size_t kThisKeywordsCount = 2;
|
||||
|
||||
const string kMaxCastKeywords[] = { "maxplay(", "maxcost("};
|
||||
const string kMaxCastKeywords[] = { "maxplay(", "maxcast("};
|
||||
const int kMaxCastZones[] = { MTGGameZone::BATTLEFIELD, MTGGameZone::STACK};
|
||||
const size_t kMaxCastKeywordsCount = 2;
|
||||
|
||||
|
||||
@@ -260,10 +260,7 @@ void MTGPlayerCards::init()
|
||||
garbage = NEW MTGGameZone();
|
||||
temp = NEW MTGGameZone();
|
||||
|
||||
//This is a Rule that should ideally be moved as an ability in the game...
|
||||
playRestrictions = NEW PlayRestrictions();
|
||||
TargetChooser * tc = NEW TypeTargetChooser("land");
|
||||
playRestrictions->addRestriction(NEW MaxPerTurnRestriction(PlayRestriction::LANDS_RULE_ID, tc, 1, inPlay));
|
||||
}
|
||||
|
||||
void MTGPlayerCards::showHand()
|
||||
|
||||
@@ -149,7 +149,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
|
||||
|
||||
if (card->has(Constants::STORM))
|
||||
{
|
||||
int storm = player->game->stack->seenThisTurn("*");
|
||||
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
|
||||
ManaCost * spellCost = player->getManaPool();
|
||||
for (int i = storm; i > 1; i--)
|
||||
{
|
||||
@@ -314,8 +314,8 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
|
||||
|
||||
if (card->has(Constants::STORM))
|
||||
{
|
||||
int storm = player->game->stack->seenThisTurn("*");
|
||||
for (int i = storm; i > 1; i--)
|
||||
int storm = player->game->stack->seenThisTurn("*") + player->opponent()->game->stack->seenThisTurn("*");
|
||||
for (int i = storm; i > 1; i--)
|
||||
{
|
||||
game->mLayers->stackLayer()->addSpell(copy, NULL, playerMana, alternateCostType, 1);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "MTGCardInstance.h"
|
||||
|
||||
|
||||
PlayRestriction::PlayRestriction(unsigned int id, TargetChooser * tc): id(id), tc(tc)
|
||||
PlayRestriction::PlayRestriction(TargetChooser * tc): tc(tc)
|
||||
{
|
||||
tc->setAllZones(); // This is to allow targetting cards without caring about the actual zone
|
||||
tc->targetter = NULL;
|
||||
@@ -17,8 +17,8 @@ PlayRestriction::~PlayRestriction()
|
||||
};
|
||||
|
||||
|
||||
MaxPerTurnRestriction::MaxPerTurnRestriction(unsigned int id, TargetChooser * tc, int maxPerTurn, MTGGameZone * zone):
|
||||
PlayRestriction(id, tc), maxPerTurn(maxPerTurn), zone(zone)
|
||||
MaxPerTurnRestriction::MaxPerTurnRestriction(TargetChooser * tc, int maxPerTurn, MTGGameZone * zone):
|
||||
PlayRestriction(tc), maxPerTurn(maxPerTurn), zone(zone)
|
||||
{}
|
||||
|
||||
int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone * destZone)
|
||||
@@ -38,17 +38,22 @@ int MaxPerTurnRestriction::canPutIntoZone(MTGCardInstance * card, MTGGameZone *
|
||||
};
|
||||
|
||||
|
||||
PlayRestriction * PlayRestrictions::getRestrictionById(unsigned int id)
|
||||
MaxPerTurnRestriction * PlayRestrictions::getMaxPerTurnRestrictionByTargetChooser(TargetChooser * tc)
|
||||
{
|
||||
if (id == PlayRestriction::UNDEF_ID)
|
||||
return NULL; // do not request Restrictions that don't have an id, there are several of them
|
||||
TargetChooser * _tc = tc->clone();
|
||||
_tc->setAllZones(); // we don't care about the actual zone for the "equals" check
|
||||
|
||||
for (vector<PlayRestriction *>::iterator iter = restrictions.begin(); iter != restrictions.end(); ++iter)
|
||||
{
|
||||
if ((*iter)->id == id)
|
||||
return *iter;
|
||||
MaxPerTurnRestriction * mptr = dynamic_cast<MaxPerTurnRestriction *> (*iter);
|
||||
if (mptr && mptr->tc->equals(_tc))
|
||||
{
|
||||
delete _tc;
|
||||
return mptr;
|
||||
}
|
||||
}
|
||||
|
||||
delete _tc;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +745,7 @@ bool TargetChooser::canTarget(Targetable * target)
|
||||
}
|
||||
if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card))
|
||||
return true;
|
||||
//this is kinda cheating but by defualt we let auras and equipments always contenue to target a phased creature.
|
||||
//this is kinda cheating but by default we let auras and equipments always continue to target a phased creature.
|
||||
else if(card->isPhased)
|
||||
return false;
|
||||
if (source && targetter && card->isInPlay())
|
||||
@@ -830,6 +830,14 @@ bool TargetChooser::validTargetsExist()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
//This function always return 1 for now, since the default TargetChooser targets everything
|
||||
//In the future we might need to check some of "targetter" settings to take protection into account...
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
a specific Card
|
||||
**/
|
||||
@@ -860,6 +868,20 @@ CardTargetChooser * CardTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool CardTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
CardTargetChooser * ctc = dynamic_cast<CardTargetChooser *> (tc);
|
||||
if (!ctc)
|
||||
return false;
|
||||
|
||||
if (validTarget != ctc->validTarget) //todo, check also previous cards, see "cantarget"...
|
||||
return false;
|
||||
|
||||
return TargetZoneChooser::equals(tc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Choose anything that has a given list of types
|
||||
**/
|
||||
@@ -940,6 +962,34 @@ TypeTargetChooser * TypeTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool TypeTargetChooser ::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
TypeTargetChooser * ttc = dynamic_cast<TypeTargetChooser *> (tc);
|
||||
if (!ttc)
|
||||
return false;
|
||||
|
||||
if (nbtypes != ttc->nbtypes)
|
||||
return false;
|
||||
|
||||
map<int,int> counts;
|
||||
|
||||
for (int i = 0; i < nbtypes; ++i)
|
||||
{
|
||||
counts[types[i]] +=1;
|
||||
counts[ttc->types[i]] -=1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nbtypes; ++i)
|
||||
{
|
||||
if (counts[types[i]] || counts[ttc->types[i]])
|
||||
return false;
|
||||
}
|
||||
|
||||
return TargetZoneChooser::equals(tc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A Target Chooser associated to a Card Descriptor object, for fine tuning of targets description
|
||||
**/
|
||||
@@ -1001,46 +1051,16 @@ DescriptorTargetChooser * DescriptorTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
Choose a creature
|
||||
**/
|
||||
|
||||
CreatureTargetChooser::CreatureTargetChooser(MTGCardInstance * card, int _maxtargets, bool other) :
|
||||
TargetZoneChooser(card, _maxtargets, other)
|
||||
bool DescriptorTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD };
|
||||
init(default_zones, 2);
|
||||
}
|
||||
|
||||
CreatureTargetChooser::CreatureTargetChooser(int * _zones, int nbzones, MTGCardInstance * card, int _maxtargets, bool other) :
|
||||
TargetZoneChooser(card, _maxtargets, other)
|
||||
{
|
||||
if (nbzones == 0)
|
||||
{
|
||||
int default_zones[] = { MTGGameZone::MY_BATTLEFIELD, MTGGameZone::OPPONENT_BATTLEFIELD };
|
||||
init(default_zones, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
init(_zones, nbzones);
|
||||
}
|
||||
}
|
||||
DescriptorTargetChooser * dtc = dynamic_cast<DescriptorTargetChooser *> (tc);
|
||||
if (!dtc)
|
||||
return false;
|
||||
|
||||
//TODO Descriptors need to have an "equals" method too -_-
|
||||
|
||||
bool CreatureTargetChooser::canTarget(Targetable * target)
|
||||
{
|
||||
if (!TargetZoneChooser::canTarget(target)) return false;
|
||||
if (target->typeAsTarget() == TARGET_CARD)
|
||||
{
|
||||
MTGCardInstance * card = (MTGCardInstance *) target;
|
||||
return card->isCreature();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CreatureTargetChooser * CreatureTargetChooser::clone() const
|
||||
{
|
||||
CreatureTargetChooser * a = NEW CreatureTargetChooser(*this);
|
||||
return a;
|
||||
return TargetZoneChooser::equals(tc);
|
||||
}
|
||||
|
||||
/* TargetzoneChooser targets everything in a given zone */
|
||||
@@ -1114,6 +1134,35 @@ TargetZoneChooser * TargetZoneChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool TargetZoneChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
TargetZoneChooser * tzc = dynamic_cast<TargetZoneChooser *> (tc);
|
||||
if (!tzc)
|
||||
return false;
|
||||
|
||||
if (nbzones!= tzc->nbzones)
|
||||
return false;
|
||||
|
||||
map<int,int> counts;
|
||||
|
||||
for (int i = 0; i < nbzones; ++i)
|
||||
{
|
||||
counts[zones[i]] +=1;
|
||||
counts[tzc->zones[i]] -=1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nbzones; ++i)
|
||||
{
|
||||
if (counts[zones[i]] || counts[tzc->zones[i]])
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: ALL_ZONES should be equivalent to something actually targetting all zones...
|
||||
|
||||
return TargetChooser::equals(tc);
|
||||
}
|
||||
|
||||
/* Player Target */
|
||||
PlayerTargetChooser::PlayerTargetChooser(MTGCardInstance * card, int _maxtargets, Player *p) :
|
||||
TargetChooser(card, _maxtargets), p(p)
|
||||
@@ -1140,6 +1189,19 @@ PlayerTargetChooser* PlayerTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool PlayerTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
PlayerTargetChooser * ptc = dynamic_cast<PlayerTargetChooser *> (tc);
|
||||
if (!ptc)
|
||||
return false;
|
||||
|
||||
if (p != ptc->p)
|
||||
return false;
|
||||
|
||||
return TargetChooser::equals(tc);
|
||||
}
|
||||
|
||||
/*Damageable Target */
|
||||
bool DamageableTargetChooser::canTarget(Targetable * target)
|
||||
{
|
||||
@@ -1156,7 +1218,7 @@ bool DamageableTargetChooser::canTarget(Targetable * target)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return CreatureTargetChooser::canTarget(target);
|
||||
return TypeTargetChooser::canTarget(target);
|
||||
}
|
||||
|
||||
DamageableTargetChooser* DamageableTargetChooser::clone() const
|
||||
@@ -1165,6 +1227,16 @@ DamageableTargetChooser* DamageableTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool DamageableTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
DamageableTargetChooser * dtc = dynamic_cast<DamageableTargetChooser *> (tc);
|
||||
if (!dtc)
|
||||
return false;
|
||||
|
||||
return TypeTargetChooser::equals(tc);
|
||||
}
|
||||
|
||||
/*Spell */
|
||||
|
||||
SpellTargetChooser::SpellTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) :
|
||||
@@ -1196,6 +1268,19 @@ SpellTargetChooser* SpellTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool SpellTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
SpellTargetChooser * stc = dynamic_cast<SpellTargetChooser *> (tc);
|
||||
if (!stc)
|
||||
return false;
|
||||
|
||||
if (color != stc->color)
|
||||
return false;
|
||||
|
||||
return TargetChooser::equals(tc);
|
||||
}
|
||||
|
||||
/*Spell or Permanent */
|
||||
SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, bool other) :
|
||||
TargetZoneChooser(card, _maxtargets, other)
|
||||
@@ -1232,6 +1317,19 @@ SpellOrPermanentTargetChooser* SpellOrPermanentTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool SpellOrPermanentTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
SpellOrPermanentTargetChooser * sptc = dynamic_cast<SpellOrPermanentTargetChooser *> (tc);
|
||||
if (!sptc)
|
||||
return false;
|
||||
|
||||
if (color != sptc->color)
|
||||
return false;
|
||||
|
||||
return TargetZoneChooser::equals(tc);
|
||||
}
|
||||
|
||||
/*Damage */
|
||||
DamageTargetChooser::DamageTargetChooser(MTGCardInstance * card, int _color, int _maxtargets, int _state) :
|
||||
TargetChooser(card, _maxtargets)
|
||||
@@ -1262,6 +1360,19 @@ DamageTargetChooser* DamageTargetChooser::clone() const
|
||||
return a;
|
||||
}
|
||||
|
||||
bool DamageTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
DamageTargetChooser * dtc = dynamic_cast<DamageTargetChooser *> (tc);
|
||||
if (!dtc)
|
||||
return false;
|
||||
|
||||
if (color != dtc->color || state != dtc->state)
|
||||
return false;
|
||||
|
||||
return TargetChooser::equals(tc);
|
||||
}
|
||||
|
||||
TriggerTargetChooser::TriggerTargetChooser(int _triggerTarget)
|
||||
{
|
||||
triggerTarget = _triggerTarget;
|
||||
@@ -1284,3 +1395,16 @@ TriggerTargetChooser * TriggerTargetChooser::clone() const
|
||||
TriggerTargetChooser * a = NEW TriggerTargetChooser(*this);
|
||||
return a;
|
||||
}
|
||||
|
||||
bool TriggerTargetChooser::equals(TargetChooser * tc)
|
||||
{
|
||||
|
||||
TriggerTargetChooser * ttc = dynamic_cast<TriggerTargetChooser *> (tc);
|
||||
if (!ttc)
|
||||
return false;
|
||||
|
||||
if (triggerTarget != ttc->triggerTarget)
|
||||
return false;
|
||||
|
||||
return TargetChooser::equals(tc);
|
||||
}
|
||||
Reference in New Issue
Block a user