- some dangerous casts Player/MTGCardInstance fixed

- removed typeAsTarget function and replaced with dynamic casting
- The test suite passes, but it is possible that I busted some of AI's features :(
This commit is contained in:
wagic.the.homebrew
2011-11-19 14:07:57 +00:00
parent e9139bedab
commit 851e1f20f1
16 changed files with 237 additions and 317 deletions
+1
View File
@@ -98,6 +98,7 @@ class AIPlayerBaka: public AIPlayer{
//used by MomirPlayer, hence protected instead of private //used by MomirPlayer, hence protected instead of private
virtual int getEfficiency(OrderedAIAction * action); virtual int getEfficiency(OrderedAIAction * action);
virtual int getEfficiency(MTGAbility * ability);
virtual bool payTheManaCost(ManaCost * cost, MTGCardInstance * card = NULL,vector<MTGAbility*> gotPayment = vector<MTGAbility*>()); virtual bool payTheManaCost(ManaCost * cost, MTGCardInstance * card = NULL,vector<MTGAbility*> gotPayment = vector<MTGAbility*>());
virtual int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0); virtual int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
virtual ManaCost * getPotentialMana(MTGCardInstance * card = NULL); virtual ManaCost * getPotentialMana(MTGCardInstance * card = NULL);
+1 -6
View File
@@ -78,11 +78,6 @@ public:
{ {
} }
int typeAsTarget()
{
return TARGET_STACKACTION;
}
Interruptible(GameObserver* observer, int inID = 0, bool hasFocus = false) Interruptible(GameObserver* observer, int inID = 0, bool hasFocus = false)
: PlayGuiObject(40, x, y, inID, hasFocus), Targetable(observer), state(NOT_RESOLVED), display(0), source(NULL) : PlayGuiObject(40, x, y, inID, hasFocus), Targetable(observer), state(NOT_RESOLVED), display(0), source(NULL)
{ {
@@ -139,7 +134,7 @@ public:
Interruptible * getNextInterruptible(Interruptible * previous, int type); Interruptible * getNextInterruptible(Interruptible * previous, int type);
Spell * getNextSpellTarget(Spell * previous = 0); Spell * getNextSpellTarget(Spell * previous = 0);
Damage * getNextDamageTarget(Damage * previous = 0); Damage * getNextDamageTarget(Damage * previous = 0);
Targetable * getNextTarget(Targetable * previous = 0, int type = -1); Targetable * getNextTarget(Targetable * previous = 0);
int getNbTargets(); int getNbTargets();
}; };
-1
View File
@@ -113,7 +113,6 @@ public:
MTGCardInstance * changeController(Player * newcontroller); MTGCardInstance * changeController(Player * newcontroller);
Player * owner; Player * owner;
Counters * counters; Counters * counters;
int typeAsTarget(){return TARGET_CARD;}
const string getDisplayName() const; const string getDisplayName() const;
MTGCardInstance * target; MTGCardInstance * target;
vector<Targetable *> backupTargets; vector<Targetable *> backupTargets;
+1 -1
View File
@@ -250,7 +250,7 @@ class MTGVampireRule: public PermanentAbility
{ {
public: public:
MTGVampireRule(GameObserver* observer, int _id); MTGVampireRule(GameObserver* observer, int _id);
map<MTGCardInstance*,vector<MTGCardInstance*> > victems; map<MTGCardInstance*,vector<MTGCardInstance*> > victims;
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
virtual MTGVampireRule * clone() const; virtual MTGVampireRule * clone() const;
-4
View File
@@ -48,10 +48,6 @@ public:
return 1; return 1;
} }
const string getDisplayName() const; const string getDisplayName() const;
int typeAsTarget()
{
return TARGET_PLAYER;
}
int afterDamage(); int afterDamage();
-5
View File
@@ -1,17 +1,12 @@
#ifndef _TARGETABLE_H_ #ifndef _TARGETABLE_H_
#define _TARGETABLE_H_ #define _TARGETABLE_H_
#define TARGET_CARD 1
#define TARGET_PLAYER 2
#define TARGET_STACKACTION 3
class Targetable class Targetable
{ {
protected: protected:
GameObserver* observer; GameObserver* observer;
public: public:
Targetable(GameObserver* observer) : observer(observer) {}; Targetable(GameObserver* observer) : observer(observer) {};
virtual int typeAsTarget() = 0;
virtual const string getDisplayName() const = 0; virtual const string getDisplayName() const = 0;
inline GameObserver* getObserver() { return observer; }; inline GameObserver* getObserver() { return observer; };
virtual void setObserver(GameObserver*g) { observer = g; }; virtual void setObserver(GameObserver*g) { observer = g; };
+3 -1
View File
@@ -14,6 +14,8 @@ using std::vector;
class TargetsList class TargetsList
{ {
private:
size_t iterateTarget(Targetable * previous);
public: public:
TargetsList(); TargetsList();
TargetsList(Targetable * _targets[], int nbtargets); TargetsList(Targetable * _targets[], int nbtargets);
@@ -28,7 +30,7 @@ public:
Interruptible * getNextInterruptible(Interruptible * previous, int type); Interruptible * getNextInterruptible(Interruptible * previous, int type);
Spell * getNextSpellTarget(Spell * previous = 0); Spell * getNextSpellTarget(Spell * previous = 0);
Damage * getNextDamageTarget(Damage * previous = 0); Damage * getNextDamageTarget(Damage * previous = 0);
Targetable * getNextTarget(Targetable * previous = 0, int type = -1); Targetable * getNextTarget(Targetable * previous = 0);
void initTargets() void initTargets()
{ {
targets.clear(); targets.clear();
+23 -39
View File
@@ -98,24 +98,17 @@ int AIAction::clickMultiAct(vector<Targetable*>& actionTargets)
} }
ite++; ite++;
} }
owner->getRandomGenerator()->random_shuffle(actionTargets.begin(), actionTargets.end());
//shuffle to make it less predictable, otherwise ai will always seem to target from right to left. making it very obvious. //shuffle to make it less predictable, otherwise ai will always seem to target from right to left. making it very obvious.
for(int k = 0;k < int(actionTargets.size());k++) owner->getRandomGenerator()->random_shuffle(actionTargets.begin(), actionTargets.end());
for(int k = 0 ;k < int(actionTargets.size()) && k < tc->maxtargets; k++)
{ {
int type = actionTargets[k]->typeAsTarget(); if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(actionTargets[k]))
switch (type)
{ {
case TARGET_CARD: if(k+1 == int(actionTargets.size()))
{ tc->done = true;
if(k < tc->maxtargets) g->cardClick(card);
{
MTGCardInstance * card = ((MTGCardInstance *) actionTargets[k]);
if(k+1 == int(actionTargets.size()))
tc->done = true;
g->cardClick(card);
}
}
break;
} }
} }
tc->attemptsToFill++; tc->attemptsToFill++;
@@ -158,16 +151,15 @@ int AIPlayer::clickMultiTarget(TargetChooser * tc, vector<Targetable*>& potentia
vector<Targetable*>::iterator ite = potentialTargets.begin(); vector<Targetable*>::iterator ite = potentialTargets.begin();
while(ite != potentialTargets.end()) while(ite != potentialTargets.end())
{ {
MTGCardInstance * card = ((MTGCardInstance *) (*ite)); MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(*ite);
Player * pTarget = (Player*)(*ite); if(card && card == tc->source)//if the source is part of the targetting deal with it first. second click is "confirming click".
if(card && card == (MTGCardInstance*)tc->source)//if the source is part of the targetting deal with it first. second click is "confirming click".
{ {
clickstream.push(NEW AIAction(this, card)); clickstream.push(NEW AIAction(this, card));
DebugTrace("Ai clicked source as a target: " << (card ? card->name : "None" ) << endl ); DebugTrace("Ai clicked source as a target: " << (card ? card->name : "None" ) << endl );
ite = potentialTargets.erase(ite); ite = potentialTargets.erase(ite);
continue; continue;
} }
if(pTarget && pTarget->typeAsTarget() == TARGET_PLAYER) else if(Player * pTarget = dynamic_cast<Player *>(*ite))
{ {
clickstream.push(NEW AIAction(this, pTarget)); clickstream.push(NEW AIAction(this, pTarget));
DebugTrace("Ai clicked Player as a target"); DebugTrace("Ai clicked Player as a target");
@@ -192,26 +184,18 @@ int AIPlayer::clickMultiTarget(TargetChooser * tc, vector<Targetable*>& potentia
int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potentialTargets, MTGCardInstance * chosenCard) int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potentialTargets, MTGCardInstance * chosenCard)
{ {
int i = randomGenerator.random() % potentialTargets.size(); int i = randomGenerator.random() % potentialTargets.size();
int type = potentialTargets[i]->typeAsTarget();
switch (type) if(MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(potentialTargets[i]))
{ {
case TARGET_CARD: if (!chosenCard)
{ clickstream.push(NEW AIAction(this, card));
if(!chosenCard) }
{ else if(Player * player = dynamic_cast<Player *>(potentialTargets[i]))
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]); {
clickstream.push(NEW AIAction(this, card)); clickstream.push(NEW AIAction(this, player));
} }
break;
}
case TARGET_PLAYER:
{
Player * player = ((Player *) potentialTargets[i]);
clickstream.push(NEW AIAction(this, player));
break;
}
}
return 1; return 1;
} }
+48 -59
View File
@@ -19,9 +19,6 @@ Player * OrderedAIAction::getPlayerTarget()
if (playerAbilityTarget) if (playerAbilityTarget)
return (Player *)playerAbilityTarget; return (Player *)playerAbilityTarget;
if (target && target->typeAsTarget() == TARGET_PLAYER)
return (Player *)target;
return NULL; return NULL;
} }
@@ -408,9 +405,9 @@ int OrderedAIAction::getEfficiency()
AbilityFactory af(g); AbilityFactory af(g);
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
if(_t->typeAsTarget() == TARGET_CARD) if(MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(_t))
{ {
if((suggestion == BAKA_EFFECT_BAD && ((MTGCardInstance*)_t)->controller() == p) || (suggestion == BAKA_EFFECT_GOOD && ((MTGCardInstance*)_t)->controller() != p)) if((suggestion == BAKA_EFFECT_BAD && (cTarget)->controller() == p) || (suggestion == BAKA_EFFECT_GOOD && (cTarget)->controller() != p))
efficiency = 0; efficiency = 0;
} }
else if ((suggestion == BAKA_EFFECT_BAD && _t == p) || (suggestion == BAKA_EFFECT_GOOD && _t != p)) else if ((suggestion == BAKA_EFFECT_BAD && _t == p) || (suggestion == BAKA_EFFECT_GOOD && _t != p))
@@ -549,16 +546,16 @@ int OrderedAIAction::getEfficiency()
} }
else if (AAProliferate * aap = dynamic_cast<AAProliferate *>(a)) else if (AAProliferate * aap = dynamic_cast<AAProliferate *>(a))
{ {
if (aap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p) if (playerAbilityTarget && playerAbilityTarget != p)
{ {
efficiency = 60;//ai determines if the counters are good or bad on menu check. efficiency = 60;//ai determines if the counters are good or bad on menu check.
} }
else if (aap) else
efficiency = 90; efficiency = 90;
} }
else if (AAAlterPoison * aaap = dynamic_cast<AAAlterPoison *>(a)) else if (AAAlterPoison * aaap = dynamic_cast<AAAlterPoison *>(a))
{ {
if (aaap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p) if (playerAbilityTarget && playerAbilityTarget != p)
{ {
efficiency = 90; efficiency = 90;
} }
@@ -566,7 +563,7 @@ int OrderedAIAction::getEfficiency()
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a)) else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
{ {
efficiency = 80; efficiency = 80;
if(atc && atc->name.length() && atc->sabilities.length() && atc->types.size() && p->game->inPlay->findByName(atc->name)) if(atc->name.length() && atc->sabilities.length() && atc->types.size() && p->game->inPlay->findByName(atc->name))
{ {
list<int>::iterator it; list<int>::iterator it;
for (it = atc->types.begin(); it != atc->types.end(); it++) for (it = atc->types.begin(); it != atc->types.end(); it++)
@@ -1196,23 +1193,22 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
a->getActionTc()->done = true; a->getActionTc()->done = true;
return 0; return 0;
} }
int targetThis = 0;
while(potentialTargets.size()) while(potentialTargets.size())
{ {
OrderedAIAction * check = NULL; OrderedAIAction * check = NULL;
MTGCardInstance * targeting = dynamic_cast<MTGCardInstance*>(potentialTargets[0]); MTGCardInstance * cTargeting = dynamic_cast<MTGCardInstance*>(potentialTargets[0]);
if(targeting && targeting->typeAsTarget() == TARGET_CARD) if(cTargeting)
check = NEW OrderedAIAction(this, a,c,targeting); check = NEW OrderedAIAction(this, a,c,cTargeting);
Player * ptargeting = dynamic_cast<Player*>(potentialTargets[0]); Player * pTargeting = dynamic_cast<Player*>(potentialTargets[0]);
if(ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER) if(pTargeting)
check = NEW OrderedAIAction(this, a,ptargeting,c); check = NEW OrderedAIAction(this, a,pTargeting,c);
targetThis = getEfficiency(check); int targetThis = getEfficiency(check);
if(targetThis && ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER) if(targetThis && pTargeting)
{ {
OrderedAIAction aiAction(this, a,ptargeting,c); OrderedAIAction aiAction(this, a,pTargeting,c);
ranking[aiAction] = 1; ranking[aiAction] = 1;
} }
if(targetThis) if(targetThis)
@@ -1223,7 +1219,9 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
if(!realTargets.size() || (int(realTargets.size()) < a->getActionTc()->maxtargets && a->getActionTc()->targetMin)) if(!realTargets.size() || (int(realTargets.size()) < a->getActionTc()->maxtargets && a->getActionTc()->targetMin))
return 0; return 0;
OrderedAIAction aiAction(this, a, c,realTargets); OrderedAIAction aiAction(this, a, c,realTargets);
aiAction.target = dynamic_cast<MTGCardInstance*>(realTargets[0]); aiAction.target = dynamic_cast<MTGCardInstance*>(realTargets[0]);
aiAction.playerAbilityTarget = dynamic_cast<Player*>(realTargets[0]);
ranking[aiAction] = 1; ranking[aiAction] = 1;
} }
return 1; return 1;
@@ -1508,6 +1506,29 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
return 1; return 1;
} }
//Returns -1 if error, a number between 0 and 100 otherwise
int AIPlayerBaka::getEfficiency(MTGAbility * ability)
{
if (!ability)
return -1;
OrderedAIAction * check = NULL;
if(MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(ability->target))
check = NEW OrderedAIAction(this, ability, ability->source, cTarget);
else if(Player * pTarget = dynamic_cast<Player *>(ability->target))
check = NEW OrderedAIAction(this, ability, pTarget, ability->source);
else
check = NEW OrderedAIAction(this, ability, ability->source);
if (!check)
return -1;
int result = getEfficiency(check);
SAFE_DELETE(check);
return result;
}
int AIPlayerBaka::selectMenuOption() int AIPlayerBaka::selectMenuOption()
{ {
ActionLayer * object = observer->mLayers->actionLayer(); ActionLayer * object = observer->mLayers->actionLayer();
@@ -1515,10 +1536,10 @@ int AIPlayerBaka::selectMenuOption()
if (object->menuObject) if (object->menuObject)
{ {
int checkedLast = 0; int checkedLast = 0;
int checked = 0;
MenuAbility * currentMenu = NULL;
if(object->abilitiesMenu->isMultipleChoice && object->currentActionCard) if(object->abilitiesMenu->isMultipleChoice && object->currentActionCard)
{ {
MenuAbility * currentMenu = NULL;
for(size_t m = object->mObjects.size()-1;m > 0;m--) for(size_t m = object->mObjects.size()-1;m > 0;m--)
{ {
MenuAbility * ability = dynamic_cast<MenuAbility *>(object->mObjects[m]); MenuAbility * ability = dynamic_cast<MenuAbility *>(object->mObjects[m]);
@@ -1531,60 +1552,28 @@ int AIPlayerBaka::selectMenuOption()
if(currentMenu) if(currentMenu)
for(unsigned int mk = 0;mk < currentMenu->abilities.size();mk++) for(unsigned int mk = 0;mk < currentMenu->abilities.size();mk++)
{ {
MTGAbility * checkEff = NULL; int checked = getEfficiency(currentMenu->abilities[mk]);
OrderedAIAction * check = NULL;
checkEff = currentMenu->abilities[mk];
if(checkEff)
{
if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_CARD)
check = NEW OrderedAIAction(this, checkEff,checkEff->source,(MTGCardInstance*)checkEff->target);
else if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_PLAYER)
check = NEW OrderedAIAction(this, checkEff,(Player*)checkEff->target,checkEff->source);
else
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
}
if(check)
{
checked = getEfficiency(check);
SAFE_DELETE(check);
}
if(checked > 60 && checked > checkedLast) if(checked > 60 && checked > checkedLast)
{ {
doThis = mk; doThis = mk;
checkedLast = checked; checkedLast = checked;
} }
checked = 0;
} }
} }
else else
{ {
for(unsigned int k = 0;k < object->abilitiesMenu->mObjects.size();k++) for(unsigned int k = 0;k < object->abilitiesMenu->mObjects.size();k++)
{ {
MTGAbility * checkEff = NULL; if(object->abilitiesMenu->mObjects[k]->GetId() <= 0)
OrderedAIAction * check = NULL; continue;
if(object->abilitiesMenu->mObjects[k]->GetId() >= 0)
checkEff = (MTGAbility *)object->mObjects[object->abilitiesMenu->mObjects[k]->GetId()]; MTGAbility * checkEff = (MTGAbility *)object->mObjects[object->abilitiesMenu->mObjects[k]->GetId()];
if(checkEff) int checked = getEfficiency(checkEff);
{
Targetable * checkTarget = checkEff->target;
if(checkTarget && checkTarget->typeAsTarget() == TARGET_CARD)
check = NEW OrderedAIAction(this, checkEff,checkEff->source,(MTGCardInstance*)checkTarget);
else if(checkTarget && checkTarget->typeAsTarget() == TARGET_PLAYER)
check = NEW OrderedAIAction(this, checkEff,(Player*)checkTarget,checkEff->source);
else
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
}
if(check)
{
checked = getEfficiency(check);
SAFE_DELETE(check);
}
if(checked > 60 && checked > checkedLast) if(checked > 60 && checked > checkedLast)
{ {
doThis = k; doThis = k;
checkedLast = checked; checkedLast = checked;
} }
checked = 0;
} }
} }
} }
+4 -4
View File
@@ -39,14 +39,14 @@ int ActionElement::getActivity()
int ActionElement::isReactingToTargetClick(Targetable * object) int ActionElement::isReactingToTargetClick(Targetable * object)
{ {
if (object && object->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * cObject = dynamic_cast<MTGCardInstance *>(object))
return isReactingToClick((MTGCardInstance *) object); return isReactingToClick(cObject);
return 0; return 0;
} }
int ActionElement::reactToTargetClick(Targetable * object) int ActionElement::reactToTargetClick(Targetable * object)
{ {
if (object->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * cObject = dynamic_cast<MTGCardInstance *>(object))
return reactToClick((MTGCardInstance *) object); return reactToClick(cObject);
return 0; return 0;
} }
+3 -4
View File
@@ -148,8 +148,7 @@ void StackAbility::Render()
_target = t; _target = t;
} }
Damageable * target = NULL; Damageable * target = NULL;
if (_target != ability->source && (_target->typeAsTarget() == TARGET_CARD || _target->typeAsTarget() if (_target != ability->source && (dynamic_cast<MTGCardInstance *>(_target) || dynamic_cast<Player *>(_target)))
== TARGET_PLAYER))
{ {
target = (Damageable *) _target; target = (Damageable *) _target;
} }
@@ -346,11 +345,11 @@ Damage * Spell::getNextDamageTarget(Damage * previous)
return NULL; return NULL;
return tc->getNextDamageTarget(previous); return tc->getNextDamageTarget(previous);
} }
Targetable * Spell::getNextTarget(Targetable * previous, int type) Targetable * Spell::getNextTarget(Targetable * previous)
{ {
if (!tc) if (!tc)
return NULL; return NULL;
return tc->getNextTarget(previous, type); return tc->getNextTarget(previous);
} }
int Spell::getNbTargets() int Spell::getNbTargets()
+18 -12
View File
@@ -568,19 +568,23 @@ int AAProliferate::resolve()
return 0; return 0;
vector<MTGAbility*>pcounters; vector<MTGAbility*>pcounters;
if(target->typeAsTarget() == TARGET_PLAYER && ((Player*)target)->poisonCount && target != source->controller())
Player * pTarget = dynamic_cast<Player *>(target);
MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(target);
if(pTarget && pTarget->poisonCount && pTarget != source->controller())
{ {
MTGAbility * a = NEW AAAlterPoison(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL); MTGAbility * a = NEW AAAlterPoison(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL);
a->oneShot = true; a->oneShot = true;
pcounters.push_back(a); pcounters.push_back(a);
} }
else if (target->typeAsTarget() == TARGET_CARD && ((MTGCardInstance*)target)->counters) else if (cTarget && cTarget->counters)
{ {
Counters * counters = ((MTGCardInstance*)target)->counters; Counters * counters = cTarget->counters;
for(size_t i = 0; i < counters->counters.size(); ++i) for(size_t i = 0; i < counters->counters.size(); ++i)
{ {
Counter * counter = counters->counters[i]; Counter * counter = counters->counters[i];
MTGAbility * a = NEW AACounter(game, game->mLayers->actionLayer()->getMaxId(), source, (MTGCardInstance*)target,"", counter->name.c_str(), counter->power, counter->toughness, 1,0); MTGAbility * a = NEW AACounter(game, game->mLayers->actionLayer()->getMaxId(), source, cTarget,"", counter->name.c_str(), counter->power, counter->toughness, 1,0);
a->oneShot = true; a->oneShot = true;
pcounters.push_back(a); pcounters.push_back(a);
} }
@@ -651,13 +655,13 @@ int AAFizzler::resolve()
//ai is casting a spell from its hand to fizzle. //ai is casting a spell from its hand to fizzle.
target = stack->getActionElementFromCard(source->target); target = stack->getActionElementFromCard(source->target);
} }
else if(target->typeAsTarget() == TARGET_CARD) else if(MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(target))
{ {
//ai targeted using an ability on a card to fizzle. //ai targeted using an ability on a card to fizzle.
target = stack->getActionElementFromCard((MTGCardInstance*)target); target = stack->getActionElementFromCard(cTarget);
} }
Spell * sTarget = (Spell *) target; Spell * sTarget = (Spell *) target;
MTGCardInstance* sCard = (MTGCardInstance*)sTarget->source; MTGCardInstance* sCard = sTarget->source;
if(!sCard || !sTarget || sCard->has(Constants::NOFIZZLE)) if(!sCard || !sTarget || sCard->has(Constants::NOFIZZLE))
return 0; return 0;
stack->Fizzle(sTarget); stack->Fizzle(sTarget);
@@ -1062,7 +1066,7 @@ int AADynamic::resolve()
_target = OriginalSrc->controller()->opponent();//looking at controllers opponent for amount _target = OriginalSrc->controller()->opponent();//looking at controllers opponent for amount
if(!_target) if(!_target)
return 0; return 0;
while (_target->typeAsTarget() == TARGET_CARD && ((MTGCardInstance *)_target)->next) while (dynamic_cast<MTGCardInstance *>(_target) && ((MTGCardInstance *)_target)->next)
_target = ((MTGCardInstance *)_target)->next; _target = ((MTGCardInstance *)_target)->next;
//find the amount variables that will be used //find the amount variables that will be used
@@ -1178,7 +1182,7 @@ int AADynamic::resolve()
} }
if (_target) if (_target)
{ {
while (_target->typeAsTarget() == TARGET_CARD && ((MTGCardInstance *)_target)->next) while (dynamic_cast<MTGCardInstance *>(_target) && ((MTGCardInstance *)_target)->next)
_target = ((MTGCardInstance *)_target)->next; _target = ((MTGCardInstance *)_target)->next;
if(sourceamount < 0) if(sourceamount < 0)
sourceamount = 0; sourceamount = 0;
@@ -1306,7 +1310,7 @@ int AADynamic::resolve()
} }
case DYNAMIC_ABILITY_EFFECT_COUNTERSONEONE: case DYNAMIC_ABILITY_EFFECT_COUNTERSONEONE:
{ {
if(_target->typeAsTarget() != TARGET_CARD) if(!dynamic_cast<MTGCardInstance *>(_target))
_target = OriginalSrc; _target = OriginalSrc;
for(int j = 0;j < sourceamount;j++) for(int j = 0;j < sourceamount;j++)
((MTGCardInstance*)_target)->counters->addCounter(1,1); ((MTGCardInstance*)_target)->counters->addCounter(1,1);
@@ -2168,8 +2172,10 @@ int IfThenAbility::resolve()
MTGAbility * a1 = delayedAbility->clone(); MTGAbility * a1 = delayedAbility->clone();
if (!a1) if (!a1)
return 0; return 0;
if(a1->target && a1->target->typeAsTarget() != TARGET_PLAYER)
a1->target = aTarget; if(a1->target && !dynamic_cast<Player *>(a1->target))
a1->target = aTarget;
if(a1->oneShot) if(a1->oneShot)
{ {
a1->resolve(); a1->resolve();
+22 -63
View File
@@ -1043,7 +1043,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
if (amp) if (amp)
{ {
amp->setCost(cost); amp->setCost(cost);
if (cost && card->typeAsTarget() == TARGET_CARD) if (cost)
cost->setExtraCostsAction(a, card); cost->setExtraCostsAction(a, card);
amp->oneShot = 0; amp->oneShot = 0;
amp->tap = doTap; amp->tap = doTap;
@@ -3620,10 +3620,13 @@ Player * MTGAbility::getPlayerFromTarget(Targetable * target)
if (!target) if (!target)
return NULL; return NULL;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(target))
return ((MTGCardInstance *) target)->controller(); return cTarget->controller();
return (Player *) target; if (Player * cPlayer = dynamic_cast<Player *>(target))
return cPlayer;
return ((Interruptible *) target)->source->controller();
} }
Player * MTGAbility::getPlayerFromDamageable(Damageable * target) Player * MTGAbility::getPlayerFromDamageable(Damageable * target)
@@ -3770,8 +3773,8 @@ int ActivatedAbility::reactToTargetClick(Targetable * object)
ManaCost * cost = getCost(); ManaCost * cost = getCost();
if (cost) if (cost)
{ {
if (object->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * cObject = dynamic_cast<MTGCardInstance *>(object))
cost->setExtraCostsAction(this, (MTGCardInstance *) object); cost->setExtraCostsAction(this, cObject);
if (!cost->isExtraPaymentSet()) if (!cost->isExtraPaymentSet())
{ {
game->mExtraPayment = cost->extraCosts; game->mExtraPayment = cost->extraCosts;
@@ -3891,8 +3894,9 @@ TargetAbility::TargetAbility(GameObserver* observer, int id, MTGCardInstance * c
int TargetAbility::reactToTargetClick(Targetable * object) int TargetAbility::reactToTargetClick(Targetable * object)
{ {
if (object->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * cObject = dynamic_cast<MTGCardInstance *>(object))
return reactToClick((MTGCardInstance *) object); return reactToClick(cObject);
if (waitingForAnswer) if (waitingForAnswer)
{ {
if (tc->toggleTarget(object) == TARGET_OK_FULL) if (tc->toggleTarget(object) == TARGET_OK_FULL)
@@ -3976,7 +3980,7 @@ int TargetAbility::resolve()
ability->target = t; ability->target = t;
//do nothing if the target controller responded by phasing out the target. //do nothing if the target controller responded by phasing out the target.
if (t->typeAsTarget() == TARGET_CARD && ((MTGCardInstance*)t)->isPhased) if (dynamic_cast<MTGCardInstance *>(t) && ((MTGCardInstance*)t)->isPhased)
return 0; return 0;
if (ability->oneShot) if (ability->oneShot)
{ {
@@ -4575,21 +4579,12 @@ int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana)
int AManaProducer::resolve() int AManaProducer::resolve()
{ {
Targetable * _target = getTarget(); Targetable * _target = getTarget();
Player * player; Player * player = getPlayerFromTarget(_target);
if (_target) if (!player)
{ return 0;
if (_target->typeAsTarget() == TARGET_CARD)
{ player->getManaPool()->add(output, source);
player = ((MTGCardInstance *) _target)->controller(); return 1;
}
else
{
player = (Player *) _target;
}
player->getManaPool()->add(output, source);
return 1;
}
return 0;
} }
int AManaProducer::reactToClick(MTGCardInstance * _card) int AManaProducer::reactToClick(MTGCardInstance * _card)
@@ -4672,19 +4667,7 @@ Targetable * AbilityTP::getTarget()
switch (who) switch (who)
{ {
case TargetChooser::TARGET_CONTROLLER: case TargetChooser::TARGET_CONTROLLER:
if (target) return getPlayerFromTarget(target);
{
switch (target->typeAsTarget())
{
case TARGET_CARD:
return ((MTGCardInstance *) target)->controller();
case TARGET_STACKACTION:
return ((Interruptible *) target)->source->controller();
default:
return (Player *) target;
}
}
return NULL;
case TargetChooser::CONTROLLER: case TargetChooser::CONTROLLER:
return source->controller(); return source->controller();
case TargetChooser::OPPONENT: case TargetChooser::OPPONENT:
@@ -4709,19 +4692,7 @@ Targetable * ActivatedAbilityTP::getTarget()
switch (who) switch (who)
{ {
case TargetChooser::TARGET_CONTROLLER: case TargetChooser::TARGET_CONTROLLER:
if (target) return getPlayerFromTarget(target);
{
switch (target->typeAsTarget())
{
case TARGET_CARD:
return ((MTGCardInstance *) target)->controller();
case TARGET_STACKACTION:
return ((Interruptible *) target)->source->controller();
default:
return (Player *) target;
}
}
return NULL;
case TargetChooser::CONTROLLER: case TargetChooser::CONTROLLER:
return source->controller(); return source->controller();
case TargetChooser::OPPONENT: case TargetChooser::OPPONENT:
@@ -4747,19 +4718,7 @@ Targetable * InstantAbilityTP::getTarget()
switch (who) switch (who)
{ {
case TargetChooser::TARGET_CONTROLLER: case TargetChooser::TARGET_CONTROLLER:
if (target) return getPlayerFromTarget(target);
{
switch (target->typeAsTarget())
{
case TARGET_CARD:
return ((MTGCardInstance *) target)->controller();
case TARGET_STACKACTION:
return ((Interruptible *) target)->source->controller();
default:
return (Player *) target;
}
}
return NULL;
case TargetChooser::CONTROLLER: case TargetChooser::CONTROLLER:
return source->controller(); return source->controller();
case TargetChooser::OPPONENT: case TargetChooser::OPPONENT:
+17 -16
View File
@@ -1877,52 +1877,53 @@ PermanentAbility(observer, _id)
int MTGVampireRule::receiveEvent(WEvent * event) int MTGVampireRule::receiveEvent(WEvent * event)
{ {
WEventDamage * e = dynamic_cast<WEventDamage *> (event); if (WEventDamage * e = dynamic_cast<WEventDamage *> (event))
WEventZoneChange * z = dynamic_cast<WEventZoneChange *> (event);
WEventPhaseChange * pe = dynamic_cast<WEventPhaseChange*>(event);
if (e)
{ {
if(!e->damage->damage) if(!e->damage->damage)
return 0; return 0;
if (!e->damage->target) if (!e->damage->target)
return 0; return 0;
if(e->damage->target->typeAsTarget() != TARGET_CARD)
MTGCardInstance * newVictim = dynamic_cast<MTGCardInstance*>(e->damage->target);
if(!newVictim)
return 0; return 0;
MTGCardInstance * newVictem = (MTGCardInstance*)(e->damage->target);
MTGCardInstance * vampire = (MTGCardInstance*)(e->damage->source); MTGCardInstance * vampire = (MTGCardInstance*)(e->damage->source);
victems[newVictem].push_back(vampire); victims[newVictim].push_back(vampire);
} }
else if (z) else if ( WEventZoneChange * z = dynamic_cast<WEventZoneChange *> (event))
{ {
MTGCardInstance * card = z->card->previous; MTGCardInstance * card = z->card->previous;
if(card && victems[card].empty()) if(card && victims[card].empty())
return 0; return 0;
std::sort(victems[card].begin(), victems[card].end());
victems[card].erase(std::unique(victems[card].begin(), victems[card].end()), victems[card].end());
//sort and remove duplicates, we only want one event of a vampire damaging a card stored per victem. //sort and remove duplicates, we only want one event of a vampire damaging a card stored per victem.
for(unsigned int w = 0;w < victems[card].size();w++) std::sort(victims[card].begin(), victims[card].end());
victims[card].erase(std::unique(victims[card].begin(), victims[card].end()), victims[card].end());
for(unsigned int w = 0;w < victims[card].size();w++)
{ {
if(victems[card].at(w) == NULL) if(victims[card].at(w) == NULL)
continue; continue;
Player * p = card->controller(); Player * p = card->controller();
if (z->from == p->game->inPlay && z->to == p->game->graveyard) if (z->from == p->game->inPlay && z->to == p->game->graveyard)
{ {
if(card == z->card->previous) if(card == z->card->previous)
{ {
WEvent * e = NEW WEventVampire(card,victems[card].at(w),card); WEvent * e = NEW WEventVampire(card,victims[card].at(w),card);
game->receiveEvent(e); game->receiveEvent(e);
} }
} }
} }
return 0; return 0;
} }
else if (pe) else if (WEventPhaseChange * pe = dynamic_cast<WEventPhaseChange*>(event))
{ {
if( pe->from->id == Constants::MTG_PHASE_ENDOFTURN) if( pe->from->id == Constants::MTG_PHASE_ENDOFTURN)
{ {
victems.clear(); victims.clear();
} }
} }
return 0; return 0;
+49 -60
View File
@@ -467,16 +467,17 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
size_t start = attribute.find("share!"); size_t start = attribute.find("share!");
size_t end = attribute.rfind("!"); size_t end = attribute.rfind("!");
string CDtype = attribute.substr(start + 6,end - start); string CDtype = attribute.substr(start + 6,end - start);
if( card && card->isSpell() && card->backupTargets.size() && card->backupTargets[0]->typeAsTarget() == TARGET_STACKACTION)
if( card && card->isSpell() && card->backupTargets.size())
{ {
//spells always store their targets in :targets[] if (Spell * targetSpell = dynamic_cast<Spell *>(card->backupTargets[0]))
//however they are all erased as the spell resolves {
//added a array to store these backups incase theyre needed //spells always store their targets in :targets[]
//again for effects such as these. //however they are all erased as the spell resolves
Spell * spell; //added a array to store these backups incase theyre needed
spell = (Spell*)card->backupTargets[0]; //again for effects such as these.
if(spell) card->target = targetSpell->source;
card->target = spell->source; }
} }
if( CDtype.find("name") != string::npos ) if( CDtype.find("name") != string::npos )
{ {
@@ -715,9 +716,8 @@ TargetChooser::TargetChooser(GameObserver *observer, MTGCardInstance * card, int
bool TargetChooser::canTarget(Targetable * target,bool withoutProtections) bool TargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (!target) return false; if (!target) return false;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(target))
{ {
MTGCardInstance * card = (MTGCardInstance *) target;
if (other) if (other)
{ {
MTGCardInstance * tempcard = card; MTGCardInstance * tempcard = card;
@@ -747,7 +747,9 @@ bool TargetChooser::canTarget(Targetable * target,bool withoutProtections)
} }
return true; return true;
} }
else if (target->typeAsTarget() == TARGET_STACKACTION) return true; else if (dynamic_cast<Interruptible *>(target))
return true;
return false; return false;
} }
@@ -875,10 +877,12 @@ CardTargetChooser::CardTargetChooser(GameObserver *observer, MTGCardInstance * _
bool CardTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool CardTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (!target) return false; if (!target) return false;
if (target->typeAsTarget() != TARGET_CARD) return false;
MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(target);
if (!card) return false;
if (!nbzones && !TargetChooser::canTarget(target,withoutProtections)) return false; if (!nbzones && !TargetChooser::canTarget(target,withoutProtections)) return false;
if (nbzones && !TargetZoneChooser::canTarget(target,withoutProtections)) return false; if (nbzones && !TargetZoneChooser::canTarget(target,withoutProtections)) return false;
MTGCardInstance * card = (MTGCardInstance *) target;
while (card) while (card)
{ {
if (card == validTarget) return true; if (card == validTarget) return true;
@@ -953,9 +957,8 @@ void TypeTargetChooser::addType(int type)
bool TypeTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool TypeTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (!TargetZoneChooser::canTarget(target,withoutProtections)) return false; if (!TargetZoneChooser::canTarget(target,withoutProtections)) return false;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(target))
{ {
MTGCardInstance * card = (MTGCardInstance *) target;
for (int i = 0; i < nbtypes; i++) for (int i = 0; i < nbtypes; i++)
{ {
@@ -967,9 +970,9 @@ bool TypeTargetChooser::canTarget(Targetable * target,bool withoutProtections)
} }
return false; return false;
} }
else if (target->typeAsTarget() == TARGET_STACKACTION) else if (Interruptible * action = dynamic_cast<Interruptible *>(target))
{ {
Interruptible * action = (Interruptible *) target;
if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED)
{ {
Spell * spell = (Spell *) action; Spell * spell = (Spell *) action;
@@ -1049,15 +1052,13 @@ DescriptorTargetChooser::DescriptorTargetChooser(GameObserver *observer, CardDes
bool DescriptorTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool DescriptorTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (!TargetZoneChooser::canTarget(target,withoutProtections)) return false; if (!TargetZoneChooser::canTarget(target,withoutProtections)) return false;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * _target = dynamic_cast<MTGCardInstance *>(target))
{ {
MTGCardInstance * _target = (MTGCardInstance *) target;
if (cd->match(_target)) if (cd->match(_target))
return true; return true;
} }
else if (target->typeAsTarget() == TARGET_STACKACTION) else if (Interruptible * action = dynamic_cast<Interruptible *>(target))
{ {
Interruptible * action = (Interruptible *) target;
if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED)
{ {
Spell * spell = (Spell *) action; Spell * spell = (Spell *) action;
@@ -1126,22 +1127,19 @@ int TargetZoneChooser::setAllZones()
bool TargetZoneChooser::canTarget(Targetable * target,bool withoutProtections) bool TargetZoneChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (!TargetChooser::canTarget(target,withoutProtections)) return false; if (!TargetChooser::canTarget(target,withoutProtections)) return false;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(target))
{ {
MTGCardInstance * card = (MTGCardInstance *) target;
for (int i = 0; i < nbzones; i++) for (int i = 0; i < nbzones; i++)
{ {
if (zones[i] == MTGGameZone::ALL_ZONES) return true; if (zones[i] == MTGGameZone::ALL_ZONES) return true;
if (MTGGameZone::intToZone(observer, zones[i], source, card)->hasCard(card)) return true; if (MTGGameZone::intToZone(observer, zones[i], source, card)->hasCard(card)) return true;
} }
} }
else if (target->typeAsTarget() == TARGET_STACKACTION) else if (Spell * spell = dynamic_cast<Spell *>(target))
{ {
DebugTrace("CHECKING INTERRUPTIBLE\n"); DebugTrace("CHECKING Spell\n");
Interruptible * action = (Interruptible *) target; if (spell->state == NOT_RESOLVED)
if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED)
{ {
Spell * spell = (Spell *) action;
MTGCardInstance * card = spell->source; MTGCardInstance * card = spell->source;
for (int i = 0; i < nbzones; i++) for (int i = 0; i < nbzones; i++)
if (MTGGameZone::intToZone(Owner->getObserver(), zones[i], source, card)->hasCard(card)) return true; if (MTGGameZone::intToZone(Owner->getObserver(), zones[i], source, card)->hasCard(card)) return true;
@@ -1217,7 +1215,9 @@ bool PlayerTargetChooser::canTarget(Targetable * target,bool withoutProtections)
if (source && targetter && (targetter->controller() == targetter->controller()) if (source && targetter && (targetter->controller() == targetter->controller())
&& (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller() && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()
== target) return false; == target) return false;
return (target->typeAsTarget() == TARGET_PLAYER) && (!p || p == (Player*) target);
Player * pTarget = dynamic_cast<Player *>(target);
return (pTarget && (!p || p == pTarget));
} }
PlayerTargetChooser* PlayerTargetChooser::clone() const PlayerTargetChooser* PlayerTargetChooser::clone() const
@@ -1251,7 +1251,7 @@ bool DamageableTargetChooser::canTarget(Targetable * target,bool withoutProtecti
if (source && targetter && (targetter->controller() == targetter->controller()) if (source && targetter && (targetter->controller() == targetter->controller())
&& (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller() && (targetter->controller()->game->inPlay->hasAbility(Constants::PLAYERSHROUD)) && targetter->controller()
== target) return false; == target) return false;
if (target->typeAsTarget() == TARGET_PLAYER) if (dynamic_cast<Player *>(target))
{ {
return true; return true;
} }
@@ -1284,16 +1284,14 @@ SpellTargetChooser::SpellTargetChooser(GameObserver *observer, MTGCardInstance *
bool SpellTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool SpellTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
MTGCardInstance * card = NULL; Spell * spell = dynamic_cast<Spell *>(target);
if (target->typeAsTarget() == TARGET_STACKACTION) if (!spell)
return false;
if (spell->state == NOT_RESOLVED)
{ {
Interruptible * action = (Interruptible *) target; MTGCardInstance * card = spell->source;
if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED) if (card && (color == -1 || card->hasColor(color))) return true;
{
Spell * spell = (Spell *) action;
card = spell->source;
if (card && (color == -1 || card->hasColor(color))) return true;
}
} }
return false; return false;
@@ -1329,19 +1327,16 @@ SpellOrPermanentTargetChooser::SpellOrPermanentTargetChooser(GameObserver *obser
bool SpellOrPermanentTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool SpellOrPermanentTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
MTGCardInstance * card = NULL;
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance *>(target))
{ {
card = (MTGCardInstance *) target;
if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target,withoutProtections); if (color == -1 || card->hasColor(color)) return TargetZoneChooser::canTarget(target,withoutProtections);
} }
else if (target->typeAsTarget() == TARGET_STACKACTION) else if (Spell * spell = dynamic_cast<Spell *>(target))
{ {
Interruptible * action = (Interruptible *) target; if (spell->state == NOT_RESOLVED)
if (action->type == ACTION_SPELL && action->state == NOT_RESOLVED)
{ {
Spell * spell = (Spell *) action; MTGCardInstance * card = spell->source;
card = spell->source;
if (card && (color == -1 || card->hasColor(color))) return true; if (card && (color == -1 || card->hasColor(color))) return true;
} }
} }
@@ -1377,14 +1372,11 @@ DamageTargetChooser::DamageTargetChooser(GameObserver *observer, MTGCardInstance
bool DamageTargetChooser::canTarget(Targetable * target,bool withoutProtections) bool DamageTargetChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
MTGCardInstance * card = NULL; if ( Damage * damage = dynamic_cast<Damage *>(target))
if (target->typeAsTarget() == TARGET_STACKACTION)
{ {
Interruptible * action = (Interruptible *) target; if (damage->state == state || state == -1)
if (action->type == ACTION_DAMAGE && (action->state == state || state == -1))
{ {
Damage * damage = (Damage *) action; MTGCardInstance * card = damage->source;
card = damage->source;
if (card && (color == -1 || card->hasColor(color))) return true; if (card && (color == -1 || card->hasColor(color))) return true;
} }
} }
@@ -1450,16 +1442,14 @@ bool TriggerTargetChooser::equals(TargetChooser * tc)
/*Proliferate Target */ /*Proliferate Target */
bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections) bool ProliferateChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance*>(target))
{ {
MTGCardInstance * card = (MTGCardInstance*)target;
if(card->counters && card->counters->counters.empty()) if(card->counters && card->counters->counters.empty())
return false; return false;
return true; return true;
} }
if (target->typeAsTarget() == TARGET_PLAYER) else if (Player * p = dynamic_cast<Player*>(target))
{ {
Player * p = (Player*)target;
if(!p->poisonCount) if(!p->poisonCount)
return false; return false;
return true; return true;
@@ -1486,9 +1476,8 @@ bool ProliferateChooser::equals(TargetChooser * tc)
/*parents or children Target */ /*parents or children Target */
bool ParentChildChooser::canTarget(Targetable * target,bool withoutProtections) bool ParentChildChooser::canTarget(Targetable * target,bool withoutProtections)
{ {
if (target->typeAsTarget() == TARGET_CARD) if (MTGCardInstance * card = dynamic_cast<MTGCardInstance*>(target))
{ {
MTGCardInstance * card = (MTGCardInstance*)target;
if(type == 1) if(type == 1)
{ {
if(!source->childrenCards.size()) if(!source->childrenCards.size())
+46 -41
View File
@@ -24,7 +24,7 @@ int TargetsList::addTarget(Targetable * target)
if(!tc || (tc && tc->maxtargets == 1)) if(!tc || (tc && tc->maxtargets == 1))
{ {
//because this was originally coded with targets as an array //because this was originally coded with targets as an array
//we have to add this condiational to insure that cards with single target effects //we have to add this conditional to insure that cards with single target effects
//and abilities that seek the nextcardtarget still work correctly. //and abilities that seek the nextcardtarget still work correctly.
targets.clear(); targets.clear();
targets.push_back(target); targets.push_back(target);
@@ -76,46 +76,66 @@ int TargetsList::toggleTarget(Targetable * target)
} }
} }
Targetable * TargetsList::getNextTarget(Targetable * previous, int type) size_t TargetsList::iterateTarget(Targetable * previous){
{ if (!previous)
int found = 0; return 0;
if (!previous) found = 1;
for (size_t i = 0; i < targets.size(); i++) for (size_t i = 0; i < targets.size(); i++) {
{ if (targets[i] == previous)
if (found && (type == -1 || targets[i]->typeAsTarget() == type)) return i + 1;
{
return targets[i];
}
if (targets[i] == previous) found = 1;
} }
return targets.size() + 1;
}
Targetable * TargetsList::getNextTarget(Targetable * previous)
{
size_t nextIndex = iterateTarget(previous);
if (nextIndex < targets.size())
return targets[nextIndex];
return NULL; return NULL;
} }
MTGCardInstance * TargetsList::getNextCardTarget(MTGCardInstance * previous) MTGCardInstance * TargetsList::getNextCardTarget(MTGCardInstance * previous)
{ {
return ((MTGCardInstance *) getNextTarget(previous, TARGET_CARD)); size_t nextIndex = iterateTarget(previous);
for (size_t i = nextIndex; i < targets.size(); ++i)
{
if (MTGCardInstance * c = dynamic_cast<MTGCardInstance *>(targets[i]))
return c;
}
return NULL;
} }
Player * TargetsList::getNextPlayerTarget(Player * previous) Player * TargetsList::getNextPlayerTarget(Player * previous)
{ {
return ((Player *) getNextTarget(previous, TARGET_PLAYER)); size_t nextIndex = iterateTarget(previous);
for (size_t i = nextIndex; i < targets.size(); ++i)
{
if (Player * p = dynamic_cast<Player *>(targets[i]))
return p;
}
return NULL;
} }
Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int type) Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int type)
{ {
int found = 0; size_t nextIndex = iterateTarget(previous);
if (!previous) found = 1;
for (size_t i = 0; i < targets.size(); i++) for (size_t i = nextIndex; i < targets.size(); i++)
{ {
if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION) if (Interruptible * action = dynamic_cast<Interruptible *>(targets[i]))
{ {
Interruptible * action = (Interruptible *) targets[i];
if (action->type == type) if (action->type == type)
{ {
return action; return action;
} }
} }
if (targets[i] == previous) found = 1;
} }
return NULL; return NULL;
} }
@@ -135,32 +155,17 @@ Damage * TargetsList::getNextDamageTarget(Damage * previous)
Damageable * TargetsList::getNextDamageableTarget(Damageable * previous) Damageable * TargetsList::getNextDamageableTarget(Damageable * previous)
{ {
int found = 0; size_t nextIndex = iterateTarget(previous);
if (!previous) found = 1; for (size_t i = nextIndex; i < targets.size(); i++)
for (size_t i = 0; i < targets.size(); i++)
{ {
if (targets[i]->typeAsTarget() == TARGET_PLAYER) if (Player * pTarget = dynamic_cast<Player *>(targets[i]))
{ {
if (found) return pTarget;
{
return ((Player *) targets[i]);
}
else
{
if ((Player *) targets[i] == previous) found = 1;
}
} }
else if (targets[i]->typeAsTarget() == TARGET_CARD) else if (MTGCardInstance * cTarget = dynamic_cast<MTGCardInstance *>(targets[i]))
{ {
if (found) return cTarget;
{
return ((MTGCardInstance *) targets[i]);
}
else
{
if ((MTGCardInstance *) targets[i] == previous) found = 1;
}
} }
} }
return NULL; return NULL;