No code change. Reformat code

This commit is contained in:
techdragon.nguyen@gmail.com
2010-12-11 22:42:48 +00:00
parent b3650bcccf
commit fe75493ffa
8 changed files with 2208 additions and 2018 deletions
-2
View File
@@ -5226,6 +5226,4 @@ void PopulateColorIndexVector( list<int>& colors, const string& colorsString, ch
void PopulateAbilityIndexVector(list<int>& abilities, const string& abilitiesString, char delimiter = ','); void PopulateAbilityIndexVector(list<int>& abilities, const string& abilitiesString, char delimiter = ',');
void PopulateSubtypesIndexVector(list<int>& subtypes, const string& subtypesString, char delimiter = ' '); void PopulateSubtypesIndexVector(list<int>& subtypes, const string& subtypesString, char delimiter = ' ');
#endif #endif
+80 -35
View File
@@ -9,7 +9,8 @@
#include "WEvent.h" #include "WEvent.h"
#include "CardSelector.h" #include "CardSelector.h"
class OtherAbilitiesEventReceiver:public MTGAbility{ class OtherAbilitiesEventReceiver: public MTGAbility
{
public: public:
int testDestroy(); int testDestroy();
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
@@ -17,62 +18,83 @@ public:
OtherAbilitiesEventReceiver * clone() const; OtherAbilitiesEventReceiver * clone() const;
}; };
class MTGPutInPlayRule:public MTGAbility{ class MTGPutInPlayRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGPutInPlayRule(int _id); MTGPutInPlayRule(int _id);
const char * getMenuText(){return "Play Card Normally";} const char * getMenuText()
{
return "Play Card Normally";
}
virtual MTGPutInPlayRule * clone() const; virtual MTGPutInPlayRule * clone() const;
}; };
class MTGAlternativeCostRule:public MTGAbility{ class MTGAlternativeCostRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGAlternativeCostRule(int _id); MTGAlternativeCostRule(int _id);
const char * getMenuText(){return "Pay Alternative Cost";} const char * getMenuText()
{
return "Pay Alternative Cost";
}
virtual MTGAlternativeCostRule * clone() const; virtual MTGAlternativeCostRule * clone() const;
}; };
class MTGBuyBackRule:public MTGAbility{ class MTGBuyBackRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGBuyBackRule(int _id); MTGBuyBackRule(int _id);
const char * getMenuText(){return "Cast And Buy Back";} const char * getMenuText()
{
return "Cast And Buy Back";
}
virtual MTGBuyBackRule * clone() const; virtual MTGBuyBackRule * clone() const;
}; };
class MTGFlashBackRule:public MTGAbility{ class MTGFlashBackRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGFlashBackRule(int _id); MTGFlashBackRule(int _id);
const char * getMenuText(){return "Flash Back";} const char * getMenuText()
{
return "Flash Back";
}
virtual MTGFlashBackRule * clone() const; virtual MTGFlashBackRule * clone() const;
}; };
class MTGRetraceRule:public MTGAbility{ class MTGRetraceRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGRetraceRule(int _id); MTGRetraceRule(int _id);
const char * getMenuText(){return "Retrace";} const char * getMenuText()
{
return "Retrace";
}
virtual MTGRetraceRule * clone() const; virtual MTGRetraceRule * clone() const;
}; };
class MTGAttackRule:public MTGAbility, public Limitor{ class MTGAttackRule: public MTGAbility, public Limitor
{
public: public:
virtual bool select(Target*); virtual bool select(Target*);
virtual bool greyout(Target*); virtual bool greyout(Target*);
@@ -81,14 +103,17 @@ class MTGAttackRule:public MTGAbility, public Limitor{
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGAttackRule(int _id); MTGAttackRule(int _id);
const char * getMenuText(){return "Attacker";} const char * getMenuText()
{
return "Attacker";
}
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
virtual MTGAttackRule * clone() const; virtual MTGAttackRule * clone() const;
}; };
/* handles combat trigger send recieve events*/ /* handles combat trigger send recieve events*/
class MTGCombatTriggersRule:public MTGAbility{ class MTGCombatTriggersRule: public MTGAbility
{
public: public:
MTGCombatTriggersRule(int _id); MTGCombatTriggersRule(int _id);
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
@@ -97,20 +122,24 @@ class MTGCombatTriggersRule:public MTGAbility{
virtual MTGCombatTriggersRule * clone() const; virtual MTGCombatTriggersRule * clone() const;
}; };
class MTGBlockRule:public MTGAbility{ class MTGBlockRule: public MTGAbility
{
public: public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int testDestroy(); int testDestroy();
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
MTGBlockRule(int _id); MTGBlockRule(int _id);
const char * getMenuText(){return "Blocker";} const char * getMenuText()
{
return "Blocker";
}
virtual MTGBlockRule * clone() const; virtual MTGBlockRule * clone() const;
}; };
/* Persist Rule */ /* Persist Rule */
class MTGPersistRule:public MTGAbility{ class MTGPersistRule: public MTGAbility
{
public: public:
MTGPersistRule(int _id); MTGPersistRule(int _id);
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
@@ -119,7 +148,8 @@ class MTGPersistRule:public MTGAbility{
virtual MTGPersistRule * clone() const; virtual MTGPersistRule * clone() const;
}; };
//affinity rules //affinity rules
class MTGAffinityRule:public MTGAbility{ class MTGAffinityRule: public MTGAbility
{
public: public:
MTGAffinityRule(int _id); MTGAffinityRule(int _id);
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
@@ -128,7 +158,8 @@ class MTGAffinityRule:public MTGAbility{
virtual MTGAffinityRule * clone() const; virtual MTGAffinityRule * clone() const;
}; };
//unearths destruction if leaves play effect //unearths destruction if leaves play effect
class MTGUnearthRule:public MTGAbility{ class MTGUnearthRule: public MTGAbility
{
public: public:
MTGUnearthRule(int _id); MTGUnearthRule(int _id);
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
@@ -136,7 +167,8 @@ class MTGUnearthRule:public MTGAbility{
int testDestroy(); int testDestroy();
virtual MTGUnearthRule * clone() const; virtual MTGUnearthRule * clone() const;
}; };
class MTGTokensCleanup:public MTGAbility{ class MTGTokensCleanup: public MTGAbility
{
public: public:
vector<MTGCardInstance *> list; vector<MTGCardInstance *> list;
MTGTokensCleanup(int _id); MTGTokensCleanup(int _id);
@@ -151,7 +183,8 @@ class MTGTokensCleanup:public MTGAbility{
* owners' graveyards. This is called the "legend rule." If only one of those permanents is * owners' graveyards. This is called the "legend rule." If only one of those permanents is
* legendary, this rule doesn't apply. * legendary, this rule doesn't apply.
*/ */
class MTGLegendRule:public ListMaintainerAbility{ class MTGLegendRule: public ListMaintainerAbility
{
public: public:
MTGLegendRule(int _id); MTGLegendRule(int _id);
int canBeInList(MTGCardInstance * card); int canBeInList(MTGCardInstance * card);
@@ -162,8 +195,8 @@ class MTGLegendRule:public ListMaintainerAbility{
virtual MTGLegendRule * clone() const; virtual MTGLegendRule * clone() const;
}; };
class MTGMomirRule: public MTGAbility
class MTGMomirRule:public MTGAbility{ {
private: private:
int genRandomCreatureId(int convertedCost); int genRandomCreatureId(int convertedCost);
static vector<int> pool[20]; static vector<int> pool[20];
@@ -183,14 +216,17 @@ public:
int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL); int isReactingToClick(MTGCardInstance * card, ManaCost * mana = NULL);
int reactToClick(MTGCardInstance * card); int reactToClick(MTGCardInstance * card);
int reactToClick(MTGCardInstance * card, int id); int reactToClick(MTGCardInstance * card, int id);
const char * getMenuText(){return "Momir";} const char * getMenuText()
{
return "Momir";
}
virtual ostream& toString(ostream& out) const; virtual ostream& toString(ostream& out) const;
virtual MTGMomirRule * clone() const; virtual MTGMomirRule * clone() const;
}; };
/* LifeLink */ /* LifeLink */
class MTGLifelinkRule:public MTGAbility{ class MTGLifelinkRule: public MTGAbility
{
public: public:
MTGLifelinkRule(int _id); MTGLifelinkRule(int _id);
@@ -204,29 +240,40 @@ class MTGLifelinkRule:public MTGAbility{
}; };
/* Deathtouch */ /* Deathtouch */
class MTGDeathtouchRule:public MTGAbility{ class MTGDeathtouchRule: public MTGAbility
{
public: public:
MTGDeathtouchRule(int _id); MTGDeathtouchRule(int _id);
int receiveEvent(WEvent * event); int receiveEvent(WEvent * event);
int testDestroy(); int testDestroy();
const char * getMenuText(){return "Deathtouch";} const char * getMenuText()
{
return "Deathtouch";
}
virtual MTGDeathtouchRule * clone() const; virtual MTGDeathtouchRule * clone() const;
}; };
/* HUD Display */ /* HUD Display */
class HUDString { class HUDString
{
public: public:
string value; string value;
float timestamp; float timestamp;
int quantity; int quantity;
HUDString(string s, float ts):value(s),timestamp(ts){quantity = 1;}; HUDString(string s, float ts) :
value(s), timestamp(ts)
{
quantity = 1;
}
;
}; };
class HUDDisplay:public MTGAbility{ class HUDDisplay: public MTGAbility
{
private: private:
list<HUDString *> events; list<HUDString *> events;
float timestamp; float timestamp;
@@ -244,6 +291,4 @@ public:
virtual HUDDisplay * clone() const; virtual HUDDisplay * clone() const;
}; };
#endif #endif
-1
View File
@@ -71,7 +71,6 @@ public:
return 0; return 0;
} }
virtual int isAI() virtual int isAI()
{ {
return 0; return 0;
+133 -73
View File
@@ -23,13 +23,15 @@ int AIAction::Act()
if (ability) if (ability)
{ {
g->mLayers->actionLayer()->reactToClick(ability, click); g->mLayers->actionLayer()->reactToClick(ability, click);
if (target) g->cardClick(target); if (target)
g->cardClick(target);
return 1; return 1;
} }
else if (click) else if (click)
{ //Shouldn't be used, really... { //Shouldn't be used, really...
g->cardClick(click, click); g->cardClick(click, click);
if (target) g->cardClick(target); if (target)
g->cardClick(target);
return 1; return 1;
} }
return 0; return 0;
@@ -76,7 +78,8 @@ MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * sou
int AIPlayer::Act(float dt) int AIPlayer::Act(float dt)
{ {
GameObserver * gameObs = GameObserver::GetInstance(); GameObserver * gameObs = GameObserver::GetInstance();
if (gameObs->currentPlayer == this) gameObs->userRequestNextGamePhase(); if (gameObs->currentPlayer == this)
gameObs->userRequestNextGamePhase();
return 1; return 1;
} }
@@ -105,7 +108,8 @@ bool AIPlayer::tapLandsForMana(ManaCost * cost, MTGCardInstance * target)
if (amp && canHandleCost(amp)) if (amp && canHandleCost(amp))
{ {
MTGCardInstance * card = amp->source; MTGCardInstance * card = amp->source;
if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 if (card == target)
used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1) if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1)
{ {
used[card] = true; used[card] = true;
@@ -144,7 +148,8 @@ ManaCost * AIPlayer::getPotentialMana(MTGCardInstance * target)
if (amp && canHandleCost(amp)) if (amp && canHandleCost(amp))
{ {
MTGCardInstance * card = amp->source; MTGCardInstance * card = amp->source;
if (card == target) used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76 if (card == target)
used[card] = true; //http://code.google.com/p/wagic/issues/detail?id=76
if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1) if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost() == 1)
{ {
result->add(amp->output); result->add(amp->output);
@@ -168,10 +173,12 @@ int AIPlayer::getEfficiency(AIAction * action)
//Can't yet handle extraCost objects (ex: sacrifice) if they require a target :( //Can't yet handle extraCost objects (ex: sacrifice) if they require a target :(
int AIPlayer::CanHandleCost(ManaCost * cost) int AIPlayer::CanHandleCost(ManaCost * cost)
{ {
if (!cost) return 1; if (!cost)
return 1;
ExtraCosts * ec = cost->extraCosts; ExtraCosts * ec = cost->extraCosts;
if (!ec) return 1; if (!ec)
return 1;
for (size_t i = 0; i < ec->costs.size(); ++i) for (size_t i = 0; i < ec->costs.size(); ++i)
{ {
@@ -193,12 +200,15 @@ int AIPlayer::canHandleCost(MTGAbility * ability)
int AIAction::getEfficiency() int AIAction::getEfficiency()
{ {
//TODO add multiplier according to what the player wants //TODO add multiplier according to what the player wants
if (efficiency != -1) return efficiency; if (efficiency != -1)
if (!ability) return 0; return efficiency;
if (!ability)
return 0;
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
ActionStack * s = g->mLayers->stackLayer(); ActionStack * s = g->mLayers->stackLayer();
Player * p = g->currentlyActing(); Player * p = g->currentlyActing();
if (s->has(ability)) return 0; if (s->has(ability))
return 0;
MTGAbility * a = AbilityFactory::getCoreAbility(ability); MTGAbility * a = AbilityFactory::getCoreAbility(ability);
@@ -208,7 +218,8 @@ int AIAction::getEfficiency()
return 0; return 0;
} }
if (!((AIPlayer *) p)->canHandleCost(ability)) return 0; if (!((AIPlayer *) p)->canHandleCost(ability))
return 0;
switch (a->aType) switch (a->aType)
{ {
case MTGAbility::DAMAGER: case MTGAbility::DAMAGER:
@@ -245,10 +256,12 @@ int AIAction::getEfficiency()
{ {
MTGCardInstance * _target = (MTGCardInstance *) (a->target); MTGCardInstance * _target = (MTGCardInstance *) (a->target);
efficiency = 0; efficiency = 0;
if (!_target) break; if (!_target)
break;
if (!_target->regenerateTokens && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS && (_target->defenser if (!_target->regenerateTokens && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS
|| _target->blockers.size())) && (_target->defenser || _target->blockers.size())
)
{ {
efficiency = 95; efficiency = 95;
} }
@@ -259,20 +272,22 @@ int AIAction::getEfficiency()
case MTGAbility::STANDARD_PREVENT: case MTGAbility::STANDARD_PREVENT:
{ {
efficiency = 0;//starts out low to avoid spamming it when its not needed. efficiency = 0;//starts out low to avoid spamming it when its not needed.
if (!target) break; if (!target)
break;
bool NeedPreventing; bool NeedPreventing;
NeedPreventing = false; NeedPreventing = false;
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS)
{ {
if ((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power) NeedPreventing if ((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power)
= true; NeedPreventing = true;
} }
if (p == target->controller() && NeedPreventing == true && !(target->getNextOpponent()->has(Constants::DEATHTOUCH) if (p == target->controller() && NeedPreventing == true && !(target->getNextOpponent()->has(Constants::DEATHTOUCH)
|| target->getNextOpponent()->has(Constants::WITHER))) || target->getNextOpponent()->has(Constants::WITHER)))
{ {
efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved".. efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved"..
if (target->toughness == 1 && target->getNextOpponent()->power == 1) efficiency += 15; if (target->toughness == 1 && target->getNextOpponent()->power == 1)
efficiency += 15;
//small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence. //small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence.
} }
//note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste. //note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste.
@@ -284,7 +299,8 @@ int AIAction::getEfficiency()
{ {
efficiency = 0; efficiency = 0;
if (!target) break; if (!target)
break;
int equips = p->game->battlefield->countByType("Equipment"); int equips = p->game->battlefield->countByType("Equipment");
int myArmy = p->game->battlefield->countByType("Creature"); int myArmy = p->game->battlefield->countByType("Creature");
@@ -293,8 +309,10 @@ int AIAction::getEfficiency()
if (p == target->controller() && target->equipment <= 1 && !a->source->target) if (p == target->controller() && target->equipment <= 1 && !a->source->target)
{ {
efficiency = 20 * (target->DangerRanking()); efficiency = 20 * (target->DangerRanking());
if (target->hasColor(5)) efficiency += 20;//this is to encourage Ai to equip white creatures in a weenie deck. ultimately it will depend on what had the higher dangerranking. if (target->hasColor(5))
if (target->power == 1 && target->toughness == 1 && target->isToken == 0) efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures. efficiency += 20;//this is to encourage Ai to equip white creatures in a weenie deck. ultimately it will depend on what had the higher dangerranking.
if (target->power == 1 && target->toughness == 1 && target->isToken == 0)
efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures.
} }
if (p == target->controller() && !a->source->target && target->equipment < equilized) if (p == target->controller() && !a->source->target && target->equipment < equilized)
@@ -344,7 +362,8 @@ int AIAction::getEfficiency()
case MTGAbility::STANDARD_PUMP: case MTGAbility::STANDARD_PUMP:
{ {
MTGCardInstance * _target = (MTGCardInstance *) (a->target); MTGCardInstance * _target = (MTGCardInstance *) (a->target);
if (!target) break; if (!target)
break;
//i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does. //i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does.
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS) if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS)
{ {
@@ -405,7 +424,8 @@ int AIAction::getEfficiency()
} }
} }
if (p->game->hand->hasX()) efficiency = 100; if (p->game->hand->hasX())
efficiency = 100;
} }
else else
@@ -434,7 +454,8 @@ int AIAction::getEfficiency()
{ {
efficiency = 0; efficiency = 0;
MTGCardInstance * _target = (MTGCardInstance *) (a->target); MTGCardInstance * _target = (MTGCardInstance *) (a->target);
if (!target) break; if (!target)
break;
//ensuring that Ai grants abilities to creatures during first main, so it can actually use them in combat. //ensuring that Ai grants abilities to creatures during first main, so it can actually use them in combat.
//quick note: the eff is multiplied by creatures ranking then divided by the number of cards in hand. //quick note: the eff is multiplied by creatures ranking then divided by the number of cards in hand.
//the reason i do this is to encourage more casting and less waste of mana on abilities. //the reason i do this is to encourage more casting and less waste of mana on abilities.
@@ -451,7 +472,9 @@ int AIAction::getEfficiency()
efficiency += efficiencyModifier; efficiency += efficiencyModifier;
} }
if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN && p == target->controller() && p->isAI()) if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN
&& p == target->controller() && p->isAI()
)
{ {
efficiency += efficiencyModifier; efficiency += efficiencyModifier;
} }
@@ -462,8 +485,9 @@ int AIAction::getEfficiency()
efficiency = 0; efficiency = 0;
} }
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller()) || (suggestion == BAKA_EFFECT_GOOD && p if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
!= target->controller())) || (suggestion == BAKA_EFFECT_GOOD && p != target->controller())
)
{ {
efficiency = 0; efficiency = 0;
//stop giving trample to the players creatures. //stop giving trample to the players creatures.
@@ -475,7 +499,8 @@ int AIAction::getEfficiency()
//untap things that Ai owns and are tapped. //untap things that Ai owns and are tapped.
{ {
efficiency = 0; efficiency = 0;
if (!target) break; if (!target)
break;
if (target->isTapped() && target->controller()->isAI()) if (target->isTapped() && target->controller()->isAI())
{ {
@@ -487,11 +512,14 @@ int AIAction::getEfficiency()
case MTGAbility::TAPPER: case MTGAbility::TAPPER:
//tap things the player owns and that are untapped. //tap things the player owns and that are untapped.
{ {
if (!target) break; if (!target)
break;
if (!target->controller()->isAI()) efficiency = (20 * target->DangerRanking()); if (!target->controller()->isAI())
efficiency = (20 * target->DangerRanking());
if (target->isTapped()) efficiency = 0; if (target->isTapped())
efficiency = 0;
break; break;
} }
@@ -550,8 +578,8 @@ int AIAction::getEfficiency()
{ {
AbilityFactory af; AbilityFactory af;
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY); int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller()) || (suggestion == BAKA_EFFECT_GOOD && p if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
!= target->controller())) || (suggestion == BAKA_EFFECT_GOOD && p != target->controller()))
{ {
efficiency = 0; efficiency = 0;
} }
@@ -567,11 +595,13 @@ int AIAction::getEfficiency()
break; break;
} }
if (p->game->hand->nb_cards == 0) efficiency = (int) ((float) efficiency * 1.3); //increase chance of using ability if hand is empty if (p->game->hand->nb_cards == 0)
efficiency = (int) ((float) efficiency * 1.3); //increase chance of using ability if hand is empty
if (ability->cost) if (ability->cost)
{ {
ExtraCosts * ec = ability->cost->extraCosts; ExtraCosts * ec = ability->cost->extraCosts;
if (ec) efficiency = efficiency / 3; //Decrease chance of using ability if there is an extra cost to use the ability if (ec)
efficiency = efficiency / 3; //Decrease chance of using ability if there is an extra cost to use the ability
} }
return efficiency; return efficiency;
} }
@@ -630,7 +660,8 @@ int AIPlayer::selectAbility()
{ //0 is not a mtgability...hackish { //0 is not a mtgability...hackish
MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]); MTGAbility * a = ((MTGAbility *) g->mLayers->actionLayer()->mObjects[i]);
//Skip mana abilities for performance //Skip mana abilities for performance
if (dynamic_cast<AManaProducer*> (a)) continue; if (dynamic_cast<AManaProducer*> (a))
continue;
//Make sure we can use the ability //Make sure we can use the ability
for (int j = 0; j < game->inPlay->nb_cards; j++) for (int j = 0; j < game->inPlay->nb_cards; j++)
{ {
@@ -650,7 +681,8 @@ int AIPlayer::selectAbility()
{ {
AIAction action = ranking.begin()->first; AIAction action = ranking.begin()->first;
int chance = 1; int chance = 1;
if (!forceBestAbilityUse) chance = 1 + WRand() % 100; if (!forceBestAbilityUse)
chance = 1 + WRand() % 100;
if (action.getEfficiency() >= chance) if (action.getEfficiency() >= chance)
{ {
if (!clickstream.size()) if (!clickstream.size())
@@ -685,7 +717,8 @@ int AIPlayer::effectBadOrGood(MTGCardInstance * card, int mode, TargetChooser *
int id = card->getMTGId(); int id = card->getMTGId();
AbilityFactory af; AbilityFactory af;
int autoGuess = af.magicText(id, NULL, card, mode, tc); int autoGuess = af.magicText(id, NULL, card, mode, tc);
if (autoGuess) return autoGuess; if (autoGuess)
return autoGuess;
return BAKA_EFFECT_DONTKNOW; return BAKA_EFFECT_DONTKNOW;
} }
@@ -704,9 +737,11 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
{ {
tc = gameObs->getCurrentTargetChooser(); tc = gameObs->getCurrentTargetChooser();
} }
if (!tc) return 0; if (!tc)
return 0;
tc->initTargets(); //cleanup the targetchooser just in case. tc->initTargets(); //cleanup the targetchooser just in case.
if (!(gameObs->currentlyActing() == this)) return 0; if (!(gameObs->currentlyActing() == this))
return 0;
Player * target = forceTarget; Player * target = forceTarget;
if (!target) if (!target)
@@ -726,7 +761,8 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
potentialTargets.push_back(target); potentialTargets.push_back(target);
nbtargets++; nbtargets++;
} }
if (checkOnly) return 1; if (checkOnly)
return 1;
} }
MTGPlayerCards * playerZones = target->game; MTGPlayerCards * playerZones = target->game;
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard }; MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard };
@@ -738,7 +774,8 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
MTGCardInstance * card = zone->cards[k]; MTGCardInstance * card = zone->cards[k];
if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50) if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50)
{ {
if (checkOnly) return 1; if (checkOnly)
return 1;
int multiplier = 1; int multiplier = 1;
if (getStats() && getStats()->isInTop(card, 10)) if (getStats() && getStats()->isInTop(card, 10))
{ {
@@ -785,9 +822,11 @@ int AIPlayer::chooseTarget(TargetChooser * _tc, Player * forceTarget)
//Couldn't find any valid target, //Couldn't find any valid target,
//usually that's because we played a card that has bad side effects (ex: when X comes into play, return target land you own to your hand) //usually that's because we played a card that has bad side effects (ex: when X comes into play, return target land you own to your hand)
//so we try again to choose a target in the other player's field... //so we try again to choose a target in the other player's field...
if (checkOnly) return 0; if (checkOnly)
return 0;
int cancel = gameObs->cancelCurrentAction(); int cancel = gameObs->cancelCurrentAction();
if (!cancel && !forceTarget) return chooseTarget(_tc, target->opponent()); if (!cancel && !forceTarget)
return chooseTarget(_tc, target->opponent());
//ERROR!!! //ERROR!!!
DebugTrace("AIPLAYER: ERROR! AI needs to choose a target but can't decide!!!"); DebugTrace("AIPLAYER: ERROR! AI needs to choose a target but can't decide!!!");
@@ -832,8 +871,8 @@ int AIPlayer::chooseAttackers()
{ {
opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1); opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1);
opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER, -1); opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER, -1);
attack = (myCreatures >= opponentCreatures && myForce > opponentForce) || (myForce > opponentForce) || (myForce attack = (myCreatures >= opponentCreatures && myForce > opponentForce)
> opponent()->life); || (myForce > opponentForce) || (myForce > opponent()->life);
} }
printf("Choose attackers : %i %i %i %i -> %i\n", opponentForce, opponentCreatures, myForce, myCreatures, attack); printf("Choose attackers : %i %i %i %i -> %i\n", opponentForce, opponentCreatures, myForce, myCreatures, attack);
if (attack) if (attack)
@@ -855,10 +894,14 @@ int AIPlayer::chooseAttackers()
/* Can I first strike my oponent and get away with murder ? */ /* Can I first strike my oponent and get away with murder ? */
int AIPlayer::canFirstStrikeKill(MTGCardInstance * card, MTGCardInstance *ennemy) int AIPlayer::canFirstStrikeKill(MTGCardInstance * card, MTGCardInstance *ennemy)
{ {
if (ennemy->has(Constants::FIRSTSTRIKE) || ennemy->has(Constants::DOUBLESTRIKE)) return 0; if (ennemy->has(Constants::FIRSTSTRIKE) || ennemy->has(Constants::DOUBLESTRIKE))
if (!(card->has(Constants::FIRSTSTRIKE) || card->has(Constants::DOUBLESTRIKE))) return 0; return 0;
if (!(card->power >= ennemy->toughness)) return 0; if (!(card->has(Constants::FIRSTSTRIKE) || card->has(Constants::DOUBLESTRIKE)))
if (!(card->power >= ennemy->toughness + 1) && ennemy->has(Constants::FLANKING)) return 0; return 0;
if (!(card->power >= ennemy->toughness))
return 0;
if (!(card->power >= ennemy->toughness + 1) && ennemy->has(Constants::FLANKING))
return 0;
return 1; return 1;
} }
@@ -866,9 +909,6 @@ int AIPlayer::chooseBlockers()
{ {
map<MTGCardInstance *, int> opponentsToughness; map<MTGCardInstance *, int> opponentsToughness;
int opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER); int opponentForce = getCreaturesInfo(opponent(), INFO_CREATURESPOWER);
//int opponentCreatures = getCreaturesInfo(opponent(), INFO_NBCREATURES, -1);
//int myForce = getCreaturesInfo(this,INFO_CREATURESPOWER);
//int myCreatures = getCreaturesInfo(this, INFO_NBCREATURES, -1);
CardDescriptor cd; CardDescriptor cd;
cd.init(); cd.init();
cd.setType("Creature"); cd.setType("Creature");
@@ -936,7 +976,8 @@ int AIPlayer::chooseBlockers()
{ {
MTGCardInstance * attacker = card->defenser; MTGCardInstance * attacker = card->defenser;
if (opponentsToughness[attacker] <= 0 || (card->toughness <= attacker->power && opponentForce * 2 < life if (opponentsToughness[attacker] <= 0 || (card->toughness <= attacker->power && opponentForce * 2 < life
&& !canFirstStrikeKill(card, attacker)) || attacker->nbOpponents() > 1 || attacker->controller()->isAI()) && !canFirstStrikeKill(card, attacker)) || attacker->nbOpponents() > 1
|| attacker->controller()->isAI())
{ {
g->mLayers->actionLayer()->reactToClick(a, card); g->mLayers->actionLayer()->reactToClick(a, card);
} }
@@ -981,9 +1022,11 @@ int AIPlayer::combatDamages()
GameObserver * gameObs = GameObserver::GetInstance(); GameObserver * gameObs = GameObserver::GetInstance();
int currentGamePhase = gameObs->getCurrentGamePhase(); int currentGamePhase = gameObs->getCurrentGamePhase();
if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS) return orderBlockers(); if (currentGamePhase == Constants::MTG_PHASE_COMBATBLOCKERS)
return orderBlockers();
if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE) return 0; if (currentGamePhase != Constants::MTG_PHASE_COMBATDAMAGE)
return 0;
return 0; return 0;
@@ -1033,7 +1076,8 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, Player * op
nbdecks++; nbdecks++;
} }
} }
if (!nbdecks) return NULL; if (!nbdecks)
return NULL;
deckid = 1 + WRand() % (nbdecks); deckid = 1 + WRand() % (nbdecks);
} }
sprintf(deckFile, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), deckid); sprintf(deckFile, JGE_GET_RES("ai/baka/deck%i.txt").c_str(), deckid);
@@ -1061,14 +1105,22 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
card = NULL; card = NULL;
while ((card = cd.nextmatch(game->hand, card))) while ((card = cd.nextmatch(game->hand, card)))
{ {
if (!CanHandleCost(card->getManaCost())) continue; if (!CanHandleCost(card->getManaCost()))
if (card->hasType(Subtypes::TYPE_CREATURE) && this->castrestrictedcreature == true && this->castrestrictedspell == true) continue; continue;
if (card->hasType(Subtypes::TYPE_ENCHANTMENT) && this->castrestrictedspell == true) continue; if (card->hasType(Subtypes::TYPE_CREATURE) && this->castrestrictedcreature == true && this->castrestrictedspell == true)
if (card->hasType(Subtypes::TYPE_ARTIFACT) && this->castrestrictedspell == true) continue; continue;
if (card->hasType(Subtypes::TYPE_SORCERY) && this->castrestrictedspell == true) continue; if (card->hasType(Subtypes::TYPE_ENCHANTMENT) && this->castrestrictedspell == true)
if (card->hasType(Subtypes::TYPE_INSTANT) && this->castrestrictedspell == true) continue; continue;
if (card->hasType(Subtypes::TYPE_LAND) && !this->canPutLandsIntoPlay) continue; if (card->hasType(Subtypes::TYPE_ARTIFACT) && this->castrestrictedspell == true)
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name)) continue; continue;
if (card->hasType(Subtypes::TYPE_SORCERY) && this->castrestrictedspell == true)
continue;
if (card->hasType(Subtypes::TYPE_INSTANT) && this->castrestrictedspell == true)
continue;
if (card->hasType(Subtypes::TYPE_LAND) && !this->canPutLandsIntoPlay)
continue;
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name))
continue;
int currentCost = card->getManaCost()->getConvertedCost(); int currentCost = card->getManaCost()->getConvertedCost();
int hasX = card->getManaCost()->hasX(); int hasX = card->getManaCost()->hasX();
if ((currentCost > maxCost || hasX) && pMana->canAfford(card->getManaCost())) if ((currentCost > maxCost || hasX) && pMana->canAfford(card->getManaCost()))
@@ -1080,7 +1132,8 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
{ {
int hasTarget = (chooseTarget(tc)); int hasTarget = (chooseTarget(tc));
delete tc; delete tc;
if (!hasTarget) continue; if (!hasTarget)
continue;
shouldPlayPercentage = 90; shouldPlayPercentage = 90;
} }
else else
@@ -1099,14 +1152,17 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
if (hasX) if (hasX)
{ {
int xDiff = pMana->getConvertedCost() - currentCost; int xDiff = pMana->getConvertedCost() - currentCost;
if (xDiff < 0) xDiff = 0; if (xDiff < 0)
xDiff = 0;
shouldPlayPercentage = shouldPlayPercentage - static_cast<int> ((shouldPlayPercentage * 1.9f) / (1 + xDiff)); shouldPlayPercentage = shouldPlayPercentage - static_cast<int> ((shouldPlayPercentage * 1.9f) / (1 + xDiff));
} }
if (WRand() % 100 > shouldPlayPercentage) continue; if (WRand() % 100 > shouldPlayPercentage)
continue;
nextCardToPlay = card; nextCardToPlay = card;
maxCost = currentCost; maxCost = currentCost;
if (hasX) maxCost = pMana->getConvertedCost(); if (hasX)
maxCost = pMana->getConvertedCost();
} }
} }
return nextCardToPlay; return nextCardToPlay;
@@ -1141,13 +1197,15 @@ int AIPlayerBaka::computeActions()
{ {
GameObserver * g = GameObserver::GetInstance(); GameObserver * g = GameObserver::GetInstance();
Player * p = g->currentPlayer; Player * p = g->currentPlayer;
if (!(g->currentlyActing() == this)) return 0; if (!(g->currentlyActing() == this))
return 0;
if (g->mLayers->actionLayer()->menuObject) if (g->mLayers->actionLayer()->menuObject)
{ {
g->mLayers->actionLayer()->doReactTo(0); g->mLayers->actionLayer()->doReactTo(0);
return 1; return 1;
} }
if (chooseTarget()) return 1; if (chooseTarget())
return 1;
int currentGamePhase = g->getCurrentGamePhase(); int currentGamePhase = g->getCurrentGamePhase();
if (g->isInterrupting == this) if (g->isInterrupting == this)
{ // interrupting { // interrupting
@@ -1294,7 +1352,8 @@ int AIPlayerBaka::computeActions()
int AIPlayer::receiveEvent(WEvent * event) int AIPlayer::receiveEvent(WEvent * event)
{ {
if (getStats()) return getStats()->receiveEvent(event); if (getStats())
return getStats()->receiveEvent(event);
return 0; return 0;
} }
@@ -1334,7 +1393,8 @@ int AIPlayerBaka::Act(float dt)
DebugTrace("Cannot interrupt"); DebugTrace("Cannot interrupt");
return 0; return 0;
} }
if (clickstream.empty()) computeActions(); if (clickstream.empty())
computeActions();
if (clickstream.empty()) if (clickstream.empty())
{ {
if (g->isInterrupting == this) if (g->isInterrupting == this)
+92 -52
View File
@@ -1,7 +1,6 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#include "AllAbilities.h" #include "AllAbilities.h"
//Activated Abilities //Activated Abilities
//Generic Activated Abilities //Generic Activated Abilities
@@ -21,19 +20,22 @@ int GenericActivatedAbility::resolve()
SAFE_DELETE(diff); SAFE_DELETE(diff);
//SAFE_DELETE(abilityCost); this line has been reported as a bug. removing it doesn't seem to break anything, although I didn't get any error in the test suite by leaving it either, so... leaving it for now as a comment, in case. //SAFE_DELETE(abilityCost); this line has been reported as a bug. removing it doesn't seem to break anything, although I didn't get any error in the test suite by leaving it either, so... leaving it for now as a comment, in case.
ability->target = target; //may have been updated... ability->target = target; //may have been updated...
if (ability) return ability->resolve(); if (ability)
return ability->resolve();
return 0; return 0;
} }
const char * GenericActivatedAbility::getMenuText() const char * GenericActivatedAbility::getMenuText()
{ {
if (ability) return ability->getMenuText(); if (ability)
return ability->getMenuText();
return "Error"; return "Error";
} }
int GenericActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) int GenericActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{ {
if (limitPerTurn && counters >= limitPerTurn) return 0; if (limitPerTurn && counters >= limitPerTurn)
return 0;
return ActivatedAbility::isReactingToClick(card, mana); return ActivatedAbility::isReactingToClick(card, mana);
} }
@@ -48,8 +50,10 @@ void GenericActivatedAbility::Update(float dt)
int GenericActivatedAbility::testDestroy() int GenericActivatedAbility::testDestroy()
{ {
if (!activeZone) return ActivatedAbility::testDestroy(); if (!activeZone)
if (activeZone->hasCard(source)) return 0; return ActivatedAbility::testDestroy();
if (activeZone->hasCard(source))
return 0;
return 1; return 1;
} }
@@ -195,7 +199,8 @@ int AADepleter::resolve()
MTGLibrary * library = player->game->library; MTGLibrary * library = player->game->library;
for (int i = 0; i < nbcards; i++) for (int i = 0; i < nbcards; i++)
{ {
if (library->nb_cards) player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard); if (library->nb_cards)
player->game->putInZone(library->cards[library->nb_cards - 1], library, player->game->graveyard);
} }
} }
return 1; return 1;
@@ -249,7 +254,8 @@ AACounter::AACounter(int id, MTGCardInstance * source, MTGCardInstance * target,
ActivatedAbility(id, source, cost, 0, doTap), nb(nb), power(power), toughness(toughness), name(_name) ActivatedAbility(id, source, cost, 0, doTap), nb(nb), power(power), toughness(toughness), name(_name)
{ {
this->target = target; this->target = target;
if (name.find("Level")) aType = MTGAbility::STANDARD_LEVELUP; if (name.find("Level"))
aType = MTGAbility::STANDARD_LEVELUP;
menu = ""; menu = "";
} }
@@ -329,7 +335,8 @@ AAFizzler::AAFizzler(int _id, MTGCardInstance * card, Spell * _target, ManaCost
int AAFizzler::resolve() int AAFizzler::resolve()
{ {
Spell * _target = (Spell *) target; Spell * _target = (Spell *) target;
if (target && _target->source->has(Constants::NOFIZZLE)) return 0; if (target && _target->source->has(Constants::NOFIZZLE))
return 0;
game->mLayers->stackLayer()->Fizzle(_target); game->mLayers->stackLayer()->Fizzle(_target);
return 1; return 1;
} }
@@ -350,7 +357,8 @@ AAFizzler* AAFizzler::clone() const
AABanishCard::AABanishCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, int _banishmentType) : AABanishCard::AABanishCard(int _id, MTGCardInstance * _source, MTGCardInstance * _target, int _banishmentType) :
ActivatedAbility(_id, _source, NULL), banishmentType(_banishmentType) ActivatedAbility(_id, _source, NULL), banishmentType(_banishmentType)
{ {
if (_target) target = _target; if (_target)
target = _target;
} }
const char * AABanishCard::getMenuText() const char * AABanishCard::getMenuText()
@@ -676,8 +684,10 @@ int AACloner::resolve()
MTGCardInstance * myClone = NULL; MTGCardInstance * myClone = NULL;
MTGCard* clone = (_target->isToken ? _target : GameApp::collection->getCardById(_target->getId())); MTGCard* clone = (_target->isToken ? _target : GameApp::collection->getCardById(_target->getId()));
if (who != 1) myClone = NEW MTGCardInstance(clone, source->controller()->game); if (who != 1)
if (who == 1) myClone = NEW MTGCardInstance(clone, source->controller()->opponent()->game); myClone = NEW MTGCardInstance(clone, source->controller()->game);
if (who == 1)
myClone = NEW MTGCardInstance(clone, source->controller()->opponent()->game);
if (who != 1) if (who != 1)
source->controller()->game->temp->addCard(myClone); source->controller()->game->temp->addCard(myClone);
else else
@@ -703,7 +713,8 @@ int AACloner::resolve()
const char * AACloner::getMenuText() const char * AACloner::getMenuText()
{ {
if (who == 1) return "Clone For Opponent"; if (who == 1)
return "Clone For Opponent";
return "Clone"; return "Clone";
} }
@@ -772,7 +783,8 @@ AAMoreLandPlz::~AAMoreLandPlz()
AAMover::AAMover(int _id, MTGCardInstance * _source, MTGCardInstance * _target, string dest, ManaCost * _cost, int doTap) : AAMover::AAMover(int _id, MTGCardInstance * _source, MTGCardInstance * _target, string dest, ManaCost * _cost, int doTap) :
ActivatedAbility(_id, _source, _cost, 0, doTap), destination(dest) ActivatedAbility(_id, _source, _cost, 0, doTap), destination(dest)
{ {
if (_target) target = _target; if (_target)
target = _target;
} }
MTGGameZone * AAMover::destinationZone() MTGGameZone * AAMover::destinationZone()
@@ -1156,7 +1168,6 @@ AAWinGame * AAWinGame::clone() const
return a; return a;
} }
//Generic Abilities //Generic Abilities
//May Abilities //May Abilities
@@ -1175,7 +1186,8 @@ void MayAbility::Update(float dt)
triggered = 1; triggered = 1;
if (TargetAbility * ta = dynamic_cast<TargetAbility *>(ability)) if (TargetAbility * ta = dynamic_cast<TargetAbility *>(ability))
{ {
if (!ta->tc->validTargetsExist()) return; if (!ta->tc->validTargetsExist())
return;
} }
game->mLayers->actionLayer()->setMenuObject(source, must); game->mLayers->actionLayer()->setMenuObject(source, must);
game->mLayers->stackLayer()->setIsInterrupting(source->controller()); game->mLayers->stackLayer()->setIsInterrupting(source->controller());
@@ -1189,15 +1201,19 @@ const char * MayAbility::getMenuText()
int MayAbility::testDestroy() int MayAbility::testDestroy()
{ {
if (!triggered) return 0; if (!triggered)
if (game->mLayers->actionLayer()->menuObject) return 0; return 0;
if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1) return 0; if (game->mLayers->actionLayer()->menuObject)
return 0;
if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1)
return 0;
return 1; return 1;
} }
int MayAbility::isReactingToTargetClick(Targetable * card) int MayAbility::isReactingToTargetClick(Targetable * card)
{ {
if (card == source) return 1; if (card == source)
return 1;
return 0; return 0;
} }
@@ -1226,7 +1242,8 @@ MayAbility::~MayAbility()
MultiAbility::MultiAbility(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int _tap) : MultiAbility::MultiAbility(int _id, MTGCardInstance * card, Targetable * _target, ManaCost * _cost, int _tap) :
ActivatedAbility(_id, card, _cost, 0, _tap) ActivatedAbility(_id, card, _cost, 0, _tap)
{ {
if (_target) target = _target; if (_target)
target = _target;
} }
int MultiAbility::Add(MTGAbility * ability) int MultiAbility::Add(MTGAbility * ability)
@@ -1240,9 +1257,11 @@ int MultiAbility::resolve()
vector<int>::size_type sz = abilities.size(); vector<int>::size_type sz = abilities.size();
for (unsigned int i = 0; i < sz; i++) for (unsigned int i = 0; i < sz; i++)
{ {
if (abilities[i] == NULL) continue; if (abilities[i] == NULL)
continue;
Targetable * backup = abilities[i]->target; Targetable * backup = abilities[i]->target;
if (target && target != source && abilities[i]->target == abilities[i]->source) abilities[i]->target = target; if (target && target != source && abilities[i]->target == abilities[i]->source)
abilities[i]->target = target;
abilities[i]->resolve(); abilities[i]->resolve();
abilities[i]->target = backup; abilities[i]->target = backup;
} }
@@ -1251,7 +1270,8 @@ int MultiAbility::resolve()
const char * MultiAbility::getMenuText() const char * MultiAbility::getMenuText()
{ {
if (abilities.size()) return abilities[0]->getMenuText(); if (abilities.size())
return abilities[0]->getMenuText();
return ""; return "";
} }
@@ -1275,7 +1295,6 @@ MultiAbility::~MultiAbility()
abilities.clear(); abilities.clear();
} }
//Generic Target Ability //Generic Target Ability
GenericTargetAbility::GenericTargetAbility(int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a, GenericTargetAbility::GenericTargetAbility(int _id, MTGCardInstance * _source, TargetChooser * _tc, MTGAbility * a,
ManaCost * _cost, int _tap, int limit, int restrictions, MTGGameZone * dest) : ManaCost * _cost, int _tap, int limit, int restrictions, MTGGameZone * dest) :
@@ -1283,13 +1302,15 @@ GenericTargetAbility::GenericTargetAbility(int _id, MTGCardInstance * _source, T
{ {
ability = a; ability = a;
MTGAbility * core = AbilityFactory::getCoreAbility(a); MTGAbility * core = AbilityFactory::getCoreAbility(a);
if (dynamic_cast<AACopier *> (core)) tc->other = true; //http://code.google.com/p/wagic/issues/detail?id=209 (avoid inifinite loop) if (dynamic_cast<AACopier *> (core))
tc->other = true; //http://code.google.com/p/wagic/issues/detail?id=209 (avoid inifinite loop)
counters = 0; counters = 0;
} }
const char * GenericTargetAbility::getMenuText() const char * GenericTargetAbility::getMenuText()
{ {
if (!ability) return "Error"; if (!ability)
return "Error";
MTGAbility * core = AbilityFactory::getCoreAbility(ability); MTGAbility * core = AbilityFactory::getCoreAbility(ability);
if (AAMover * move = dynamic_cast<AAMover *>(core)) if (AAMover * move = dynamic_cast<AAMover *>(core))
@@ -1318,7 +1339,9 @@ const char * GenericTargetAbility::getMenuText()
{ {
return "Reanimate"; return "Reanimate";
} }
else if ((tc->targetsZone(g->players[i]->game->inPlay) && dest == g->players[i]->game->library) || dest == g->players[i]->game->library ) else if ((tc->targetsZone(g->players[i]->game->inPlay)
&& dest == g->players[i]->game->library)
|| dest == g->players[i]->game->library)
{ {
return "Put in Library"; return "Put in Library";
} }
@@ -1361,7 +1384,8 @@ int GenericTargetAbility::resolve()
int GenericTargetAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana) int GenericTargetAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{ {
if (limitPerTurn && counters >= limitPerTurn) return 0; if (limitPerTurn && counters >= limitPerTurn)
return 0;
return TargetAbility::isReactingToClick(card, mana); return TargetAbility::isReactingToClick(card, mana);
} }
@@ -1376,8 +1400,10 @@ void GenericTargetAbility::Update(float dt)
int GenericTargetAbility::testDestroy() int GenericTargetAbility::testDestroy()
{ {
if (!activeZone) return TargetAbility::testDestroy(); if (!activeZone)
if (activeZone->hasCard(source)) return 0; return TargetAbility::testDestroy();
if (activeZone->hasCard(source))
return 0;
return 1; return 1;
} }
@@ -1388,7 +1414,8 @@ GenericTargetAbility * GenericTargetAbility::clone() const
a->ability = ability->clone(); a->ability = ability->clone();
a->cost = NEW ManaCost(); a->cost = NEW ManaCost();
a->cost->copy(cost); a->cost->copy(cost);
if (tc) a->tc = tc->clone(); if (tc)
a->tc = tc->clone();
return a; return a;
} }
@@ -1461,19 +1488,23 @@ ATransformer::ATransformer(int id, MTGCardInstance * source, MTGCardInstance * t
PopulateColorIndexVector(colors, sabilities); PopulateColorIndexVector(colors, sabilities);
remove = false; remove = false;
if (stypes == "removesubtypes") remove = true; if (stypes == "removesubtypes")
remove = true;
if (stypes == "allsubtypes" || stypes == "removesubtypes") if (stypes == "allsubtypes" || stypes == "removesubtypes")
{ {
for (int i = Subtypes::LAST_TYPE + 1;; i++) for (int i = Subtypes::LAST_TYPE + 1;; i++)
{ {
string s = Subtypes::subtypesList->find(i); string s = Subtypes::subtypesList->find(i);
{ {
if (s == "") break; if (s == "")
if (s.find(" ") != string::npos) continue; break;
if (s == "Nothing" || s == "Swamp" || s == "Plains" || s == "Mountain" || s == "Forest" || s == "Island" || s if (s.find(" ") != string::npos)
== "Shrine" || s == "Basic" || s == "Colony" || s == "Desert" || s == "Dismiss" || s == "Equipment" || s continue;
== "Everglades" || s == "Grasslands" || s == "Lair" || s == "Level" || s == "Levelup" || s == "Mine" || s if (s == "Nothing" || s == "Swamp" || s == "Plains" || s == "Mountain" || s == "Forest"
== "Oasis" || s == "World" || s == "Aura") || s == "Island" || s == "Shrine" || s == "Basic" || s == "Colony" || s == "Desert"
|| s == "Dismiss" || s == "Equipment" || s == "Everglades" || s == "Grasslands" || s == "Lair"
|| s == "Level" || s == "Levelup" || s == "Mine" || s == "Oasis" || s == "World" || s == "Aura"
)
{//dont add "nothing" or land type to this card. {//dont add "nothing" or land type to this card.
} }
else else
@@ -1500,13 +1531,16 @@ int ATransformer::addToGame()
_target = _target->next; _target = _target->next;
for (int j = 0; j < Constants::MTG_NB_COLORS; j++) for (int j = 0; j < Constants::MTG_NB_COLORS; j++)
{ {
if (_target->hasColor(j)) oldcolors.push_back(j); if (_target->hasColor(j))
oldcolors.push_back(j);
} }
for (int j = Subtypes::LAST_TYPE + 1;; j++) for (int j = Subtypes::LAST_TYPE + 1;; j++)
{ {
string otypes = Subtypes::subtypesList->find(j); string otypes = Subtypes::subtypesList->find(j);
if (otypes == "") break; if (otypes == "")
if (otypes.find(" ") != string::npos) continue; break;
if (otypes.find(" ") != string::npos)
continue;
if (_target->hasSubtype(j)) if (_target->hasSubtype(j))
{ {
oldtypes.push_back(j); oldtypes.push_back(j);
@@ -1554,7 +1588,8 @@ int ATransformer::destroy()
list<int>::iterator it; list<int>::iterator it;
for (it = types.begin(); it != types.end(); it++) for (it = types.begin(); it != types.end(); it++)
{ {
if (remove == false) _target->removeType(*it); if (remove == false)
_target->removeType(*it);
} }
for (it = colors.begin(); it != colors.end(); it++) for (it = colors.begin(); it != colors.end(); it++)
{ {
@@ -1572,7 +1607,8 @@ int ATransformer::destroy()
{ {
for (it = oldtypes.begin(); it != oldtypes.end(); it++) for (it = oldtypes.begin(); it != oldtypes.end(); it++)
{ {
if (!_target->hasSubtype(*it)) _target->addType(*it); if (!_target->hasSubtype(*it))
_target->addType(*it);
} }
} }
} }
@@ -1824,7 +1860,8 @@ const char * ABecomes::getMenuText()
ABecomes * ABecomes::clone() const ABecomes * ABecomes::clone() const
{ {
ABecomes * a = NEW ABecomes(*this); ABecomes * a = NEW ABecomes(*this);
if (a->wppt) a->wppt = NEW WParsedPT(*(a->wppt)); if (a->wppt)
a->wppt = NEW WParsedPT(*(a->wppt));
a->isClone = 1; a->isClone = 1;
return a; return a;
} }
@@ -1887,9 +1924,11 @@ int APreventDamageTypes::addToGame()
} }
TargetChooserFactory tcf; TargetChooserFactory tcf;
TargetChooser *toTc = tcf.createTargetChooser(to, source, this); TargetChooser *toTc = tcf.createTargetChooser(to, source, this);
if (toTc) toTc->targetter = NULL; if (toTc)
toTc->targetter = NULL;
TargetChooser *fromTc = tcf.createTargetChooser(from, source, this); TargetChooser *fromTc = tcf.createTargetChooser(from, source, this);
if (fromTc) fromTc->targetter = NULL; if (fromTc)
fromTc->targetter = NULL;
if (type != 1 && type != 2) if (type != 1 && type != 2)
{//not adding this creates a memory leak. {//not adding this creates a memory leak.
re = NEW REDamagePrevention(this, fromTc, toTc, -1, false, DAMAGE_COMBAT); re = NEW REDamagePrevention(this, fromTc, toTc, -1, false, DAMAGE_COMBAT);
@@ -1990,14 +2029,16 @@ void AUpkeep::Update(float dt)
{ {
ability->resolve(); ability->resolve();
} }
if (newPhase == phase + 1 && once) once = 2; if (newPhase == phase + 1 && once)
once = 2;
} }
ActivatedAbility::Update(dt); ActivatedAbility::Update(dt);
} }
int AUpkeep::isReactingToClick(MTGCardInstance * card, ManaCost * mana) int AUpkeep::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{ {
if (currentPhase != phase || paidThisTurn || once >= 2) return 0; if (currentPhase != phase || paidThisTurn || once >= 2)
return 0;
return ActivatedAbility::isReactingToClick(card, mana); return ActivatedAbility::isReactingToClick(card, mana);
} }
@@ -2031,7 +2072,6 @@ AUpkeep::~AUpkeep()
SAFE_DELETE(ability); SAFE_DELETE(ability);
} }
// utility functions // utility functions
// Given a delimited string of abilities, add the ones to the list that are "Basic" MTG abilities // Given a delimited string of abilities, add the ones to the list that are "Basic" MTG abilities
@@ -2047,7 +2087,6 @@ void PopulateAbilityIndexVector( list<int>& abilities, const string& abilityStri
} }
} }
void PopulateColorIndexVector(list<int>& colors, const string& colorStringList, char delimiter) void PopulateColorIndexVector(list<int>& colors, const string& colorStringList, char delimiter)
{ {
vector<string> abilitiesList = split(colorStringList, delimiter); vector<string> abilitiesList = split(colorStringList, delimiter);
@@ -2056,7 +2095,8 @@ void PopulateColorIndexVector( list<int>& colors, const string& colorStringList,
for (int colorIndex = Constants::MTG_COLOR_ARTIFACT; colorIndex < Constants::MTG_NB_COLORS; ++colorIndex) for (int colorIndex = Constants::MTG_COLOR_ARTIFACT; colorIndex < Constants::MTG_NB_COLORS; ++colorIndex)
{ {
// if the text is not a basic ability but contains a valid color add it to the color vector // if the text is not a basic ability but contains a valid color add it to the color vector
if ( (Constants::GetBasicAbilityIndex( *iter ) != -1) && ((*iter).find( Constants::MTGColorStrings[ colorIndex ] ) != string::npos) ) if ((Constants::GetBasicAbilityIndex(*iter) != -1)
&& ((*iter).find(Constants::MTGColorStrings[colorIndex]) != string::npos))
colors.push_back(colorIndex); colors.push_back(colorIndex);
} }
} }
+20 -17
View File
@@ -73,7 +73,7 @@ void GameObserver::nextGamePhase()
{ {
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE) if (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE)
if (FIRST_STRIKE == combatStep || END_FIRST_STRIKE == combatStep || DAMAGE == combatStep) if ((FIRST_STRIKE == combatStep) || (END_FIRST_STRIKE == combatStep) || (DAMAGE == combatStep))
{ {
nextCombatStep(); nextCombatStep();
return; return;
@@ -213,10 +213,12 @@ void GameObserver::userRequestNextGamePhase()
bool executeNextPhaseImmediately = true; bool executeNextPhaseImmediately = true;
Phase * cPhaseOld = phaseRing->getCurrentPhase(); Phase * cPhaseOld = phaseRing->getCurrentPhase();
if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER) || (cPhaseOld->id if ((cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == ORDER)
== Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS) || cPhaseOld->id || (cPhaseOld->id == Constants::MTG_PHASE_COMBATBLOCKERS && combatStep == TRIGGERS)
== Constants::MTG_PHASE_COMBATDAMAGE || opponent()->isAI() || (cPhaseOld->id == Constants::MTG_PHASE_COMBATDAMAGE)
|| options[Options::optionInterrupt(currentGamePhase)].number) || opponent()->isAI()
|| options[Options::optionInterrupt(currentGamePhase)].number
)
{ {
executeNextPhaseImmediately = false; executeNextPhaseImmediately = false;
} }
@@ -564,10 +566,8 @@ void GameObserver::gameStateBasedEffects()
game->receiveEvent(e); game->receiveEvent(e);
p->game->putInGraveyard(c); p->game->putInGraveyard(c);
} }
if (c->has(Constants::UNEARTH)) if (c->has(Constants::UNEARTH)) p->game->putInExile(c);
p->game->putInExile(c); if (c->fresh) c->fresh = 0;
if (c->fresh)
c->fresh = 0;
if (c->has(Constants::ONLYONEBOTH)) if (c->has(Constants::ONLYONEBOTH))
{ {
c->controller()->castcount = 0; c->controller()->castcount = 0;
@@ -597,28 +597,30 @@ void GameObserver::gameStateBasedEffects()
/////////////////////////////////// ///////////////////////////////////
if (combatStep == TRIGGERS) if (combatStep == TRIGGERS)
{ {
if (!mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED) && !targetChooser && !mLayers->actionLayer()->isWaitingForAnswer()) if (!mLayers->stackLayer()->getNext(NULL, 0, NOT_RESOLVED) && !targetChooser
&& !mLayers->actionLayer()->isWaitingForAnswer())
mLayers->stackLayer()->AddNextCombatStep(); mLayers->stackLayer()->AddNextCombatStep();
} }
//Auto skip Phases //Auto skip Phases
GameObserver * game = game->GetInstance(); GameObserver * game = game->GetInstance();
int skipLevel = (game->currentPlayer->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE : options[Options::ASPHASES].number; int skipLevel = (game->currentPlayer->playMode == Player::MODE_TEST_SUITE) ? Constants::ASKIP_NONE
: options[Options::ASPHASES].number;
int nrCreatures = currentPlayer->game->inPlay->countByType("Creature"); int nrCreatures = currentPlayer->game->inPlay->countByType("Creature");
if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL) if (skipLevel == Constants::ASKIP_SAFE || skipLevel == Constants::ASKIP_FULL)
{ {
if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UNTAP || currentGamePhase if ((opponent()->isAI() && !(isInterrupting)) && ((currentGamePhase == Constants::MTG_PHASE_UNTAP)
== Constants::MTG_PHASE_DRAW || currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN || ((currentGamePhase || (currentGamePhase == Constants::MTG_PHASE_DRAW) || (currentGamePhase == Constants::MTG_PHASE_COMBATBEGIN)
== Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0)) || currentGamePhase || ((currentGamePhase == Constants::MTG_PHASE_COMBATATTACKERS) && (nrCreatures == 0))
== Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN || currentGamePhase == Constants::MTG_PHASE_COMBATEND || currentGamePhase == Constants::MTG_PHASE_ENDOFTURN
|| ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8)))) || ((currentGamePhase == Constants::MTG_PHASE_CLEANUP) && (currentPlayer->game->hand->nb_cards < 8))))
userRequestNextGamePhase(); userRequestNextGamePhase();
} }
if (skipLevel == Constants::ASKIP_FULL) if (skipLevel == Constants::ASKIP_FULL)
{ {
if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UPKEEP || currentGamePhase if ((opponent()->isAI() && !(isInterrupting)) && (currentGamePhase == Constants::MTG_PHASE_UPKEEP
== Constants::MTG_PHASE_COMBATDAMAGE)) || currentGamePhase == Constants::MTG_PHASE_COMBATDAMAGE))
userRequestNextGamePhase(); userRequestNextGamePhase();
} }
} }
@@ -630,6 +632,7 @@ void GameObserver::Render()
JRenderer::GetInstance()->DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(255,255,0,0)); JRenderer::GetInstance()->DrawRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(255,255,0,0));
if (mExtraPayment) if (mExtraPayment)
mExtraPayment->Render(); mExtraPayment->Render();
for (int i = 0; i < nbPlayers; ++i) for (int i = 0; i < nbPlayers; ++i)
{ {
players[i]->Render(); players[i]->Render();
+103 -58
View File
@@ -19,9 +19,11 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
Player * currentPlayer = game->currentPlayer; Player * currentPlayer = game->currentPlayer;
if (!player->game->hand->hasCard(card)) if (!player->game->hand->hasCard(card))
return 0; return 0;
if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[Constants::LEYLINE]) && game->currentGamePhase if ((game->turn < 1) && (cardsinhand != 0) && (card->basicAbilities[Constants::LEYLINE])
== Constants::MTG_PHASE_FIRSTMAIN && game->players[0]->game->graveyard->nb_cards == 0 && game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
&& game->players[0]->game->exile->nb_cards == 0) && game->players[0]->game->graveyard->nb_cards == 0
&& game->players[0]->game->exile->nb_cards == 0
)
{ {
Player * p = game->currentPlayer; Player * p = game->currentPlayer;
if (card->basicAbilities[Constants::LEYLINE]) if (card->basicAbilities[Constants::LEYLINE])
@@ -35,15 +37,18 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
} }
if (card->hasType("land")) if (card->hasType("land"))
{ {
if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay
== Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)
)
{ {
return 1; return 1;
} }
} }
else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting else if ((card->hasType("instant")) || card->has(Constants::FLASH)
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase || (player == currentPlayer && !game->isInterrupting
== Constants::MTG_PHASE_SECONDMAIN))) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
)
{ {
ManaCost * playerMana = player->getManaPool(); ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
@@ -241,15 +246,17 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
return 0; return 0;
if (card->hasType("land")) if (card->hasType("land"))
{ {
if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay && (game->currentGamePhase if (player == currentPlayer && currentPlayer->canPutLandsIntoPlay
== Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
{ || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)
)
return 1; return 1;
} }
} else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer
else if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting && !game->isInterrupting
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
== Constants::MTG_PHASE_SECONDMAIN))) || game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
)
{ {
ManaCost * playerMana = player->getManaPool(); ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
@@ -621,9 +628,11 @@ int MTGFlashBackRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
return 0; return 0;
if (!card->getManaCost()->FlashBack) if (!card->getManaCost()->FlashBack)
return 0; return 0;
if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting if ((card->hasType("instant")) || card->has(Constants::FLASH)
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase || (player == currentPlayer && !game->isInterrupting
== Constants::MTG_PHASE_SECONDMAIN))) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
)
{ {
ManaCost * playerMana = player->getManaPool(); ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
@@ -805,9 +814,11 @@ int MTGRetraceRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
return 0; return 0;
if (!card->getManaCost()->Retrace) if (!card->getManaCost()->Retrace)
return 0; return 0;
if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer && !game->isInterrupting if ((card->hasType("instant")) || card->has(Constants::FLASH)
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN || game->currentGamePhase || (player == currentPlayer && !game->isInterrupting
== Constants::MTG_PHASE_SECONDMAIN))) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
)
{ {
ManaCost * playerMana = player->getManaPool(); ManaCost * playerMana = player->getManaPool();
ManaCost * cost = card->getManaCost(); ManaCost * cost = card->getManaCost();
@@ -874,7 +885,8 @@ int MTGRetraceRule::reactToClick(MTGCardInstance * card)
{ {
cost->Retrace->setExtraCostsAction(this, card); cost->Retrace->setExtraCostsAction(this, card);
game->mExtraPayment = cost->Retrace->extraCosts; game->mExtraPayment = cost->Retrace->extraCosts;
card->paymenttype = MTGAbility::RETRACE_COST;; card->paymenttype = MTGAbility::RETRACE_COST;
;
return 0; return 0;
} }
} }
@@ -1013,8 +1025,10 @@ int MTGAttackRule::receiveEvent(WEvent *e)
for (int i = 0; i < z->nb_cards; i++) for (int i = 0; i < z->nb_cards; i++)
{ {
MTGCardInstance * card = z->cards[i]; MTGCardInstance * card = z->cards[i];
if (!card->isAttacker() && card->has(Constants::MUSTATTACK)) reactToClick(card); if (!card->isAttacker() && card->has(Constants::MUSTATTACK))
if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI()) reactToClick(card); reactToClick(card);
if (!card->isAttacker() && card->has(Constants::TREASON) && p->isAI())
reactToClick(card);
if (card->isAttacker() && card->isTapped()) if (card->isAttacker() && card->isTapped())
card->setAttacker(0); card->setAttacker(0);
if (card->isAttacker() && !card->has(Constants::VIGILANCE)) if (card->isAttacker() && !card->has(Constants::VIGILANCE))
@@ -1223,8 +1237,9 @@ MTGBlockRule::MTGBlockRule(int _id) :
int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana) int MTGBlockRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
{ {
if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting && card->controller() if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS && !game->isInterrupting
== game->currentlyActing()) && card->controller() == game->currentlyActing()
)
{ {
if (card->canBlock()) if (card->canBlock())
return 1; return 1;
@@ -1315,8 +1330,10 @@ int MTGMomirRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
Player * currentPlayer = game->currentPlayer; Player * currentPlayer = game->currentPlayer;
if (!player->game->hand->hasCard(card)) if (!player->game->hand->hasCard(card))
return 0; return 0;
if (player == currentPlayer && !game->isInterrupting && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN if (player == currentPlayer && !game->isInterrupting
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)) && (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN)
)
{ {
return 1; return 1;
} }
@@ -1414,8 +1431,9 @@ void MTGMomirRule::Render()
ostream& MTGMomirRule::toString(ostream& out) const ostream& MTGMomirRule::toString(ostream& out) const
{ {
out << "MTGMomirRule ::: pool : " << pool << " ; initialized : " << initialized << " ; textAlpha : " << textAlpha << " ; text " out << "MTGMomirRule ::: pool : " << pool << " ; initialized : " << initialized << " ; textAlpha : " << textAlpha
<< text << " ; alreadyplayed : " << alreadyplayed << " ; collection : " << collection << "("; << " ; text " << text << " ; alreadyplayed : " << alreadyplayed
<< " ; collection : " << collection << "(";
return MTGAbility::toString(out) << ")"; return MTGAbility::toString(out) << ")";
} }
@@ -1696,10 +1714,19 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
//when cards with affinity enter you hand from anywhere a redux is applied to them for the artifacts in play. //when cards with affinity enter you hand from anywhere a redux is applied to them for the artifacts in play.
if (ok == 1) if (ok == 1)
{//enters play from anywhere {//enters play from anywhere
if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from if (e->from == p->game->graveyard
== p->game->exile || e->from == p->game->stack || e->from == p->opponent()->game->battlefield || e->from == p->game->hand
|| e->from == p->game->temp || e->from == p->game->battlefield) || e->from == p->game->library
|| e->from == p->game->exile
|| e->from == p->game->stack
|| e->from == p->opponent()->game->battlefield
|| e->from == p->game->temp
|| e->from == p->game->battlefield
)
{ {
// TODO:
// what happens if there are any cards with two or more affinity abilities? If no such card exist
// then could this block be changed to use else if? That will save on the number of operations.
MTGCardInstance * card = e->card->previous; MTGCardInstance * card = e->card->previous;
if (card && card->has(Constants::AFFINITYARTIFACTS)) if (card && card->has(Constants::AFFINITYARTIFACTS))
{ {
@@ -1743,13 +1770,14 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
{ {
MTGCardInstance * c = z->cards[j]; MTGCardInstance * c = z->cards[j];
int check = e->card->getManaCost()->getConvertedCost(); int check = e->card->getManaCost()->getConvertedCost();
if ((e->card->has(Constants::AFFINITYARTIFACTS) && c->hasSubtype("artifact")) || (e->card->has( if ((e->card->has(Constants::AFFINITYARTIFACTS) && c->hasSubtype("artifact"))
Constants::AFFINITYSWAMP) && c->hasSubtype("swamp")) || (e->card->has( || (e->card->has(Constants::AFFINITYSWAMP) && c->hasSubtype("swamp"))
Constants::AFFINITYMOUNTAIN) && c->hasSubtype("moutain")) || (e->card->has( || (e->card->has(Constants::AFFINITYMOUNTAIN) && c->hasSubtype("moutain"))
Constants::AFFINITYPLAINS) && c->hasSubtype("plains")) || (e->card->has( || (e->card->has(Constants::AFFINITYPLAINS) && c->hasSubtype("plains"))
Constants::AFFINITYISLAND) && c->hasSubtype("island")) || (e->card->has( || (e->card->has(Constants::AFFINITYISLAND) && c->hasSubtype("island"))
Constants::AFFINITYFOREST) && c->hasSubtype("forest")) || (e->card->has( || (e->card->has(Constants::AFFINITYFOREST) && c->hasSubtype("forest"))
Constants::AFFINITYGREENCREATURES) && c->hasColor(1) && c->isCreature())) || (e->card->has(Constants::AFFINITYGREENCREATURES) && c->hasColor(1) && c->isCreature())
)
{ {
if (check > 0) if (check > 0)
{ {
@@ -1776,8 +1804,13 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
ok = 2;//card enters play ok = 2;//card enters play
if (ok == 2) if (ok == 2)
{//enters play from anywhere {//enters play from anywhere
if (e->from == p->game->graveyard || e->from == p->game->hand || e->from == p->game->library || e->from if (e->from == p->game->graveyard
== p->game->exile || e->from == p->game->stack || e->from == p->game->temp) || e->from == p->game->hand
|| e->from == p->game->library
|| e->from == p->game->exile
|| e->from == p->game->stack
|| e->from == p->game->temp
)
{ {
//--redux effect //--redux effect
MTGGameZone * z = card->controller()->game->hand; MTGGameZone * z = card->controller()->game->hand;
@@ -1817,13 +1850,14 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
for (int j = 0; j < nbcards; ++j) for (int j = 0; j < nbcards; ++j)
{ {
MTGCardInstance * c = z->cards[j]; MTGCardInstance * c = z->cards[j];
if ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos) || (c->has( if ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos)
Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos) || (c->has( || (c->has(Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos)
Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos) || (c->has( || (c->has(Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos)
Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos) || (c->has( || (c->has(Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos)
Constants::AFFINITYISLAND) && etype.find("isl") != string::npos) || (c->has( || (c->has(Constants::AFFINITYISLAND) && etype.find("isl") != string::npos)
Constants::AFFINITYFOREST) && etype.find("for") != string::npos) || (c->has( || (c->has(Constants::AFFINITYFOREST) && etype.find("for") != string::npos)
Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos)) || (c->has(Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos)
)
{ {
if (c->getManaCost()->getConvertedCost() > 0) if (c->getManaCost()->getConvertedCost() > 0)
{ {
@@ -1839,9 +1873,15 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
}//--end of redux bracket ok == 2 }//--end of redux bracket ok == 2
//--------- //---------
ok = 0; ok = 0;
if (e->to == p->game->graveyard || e->to == p->game->hand || e->to == p->game->library || e->to == p->game->exile if (e->to == p->game->graveyard
|| e->to == p->game->stack || e->to == p->opponent()->game->battlefield) || e->to == p->game->hand
|| e->to == p->game->library
|| e->to == p->game->exile
|| e->to == p->game->stack
|| e->to == p->opponent()->game->battlefield
)
ok = 3;//card leaves play ok = 3;//card leaves play
if (ok == 3) if (ok == 3)
{//leave play from your battlefield {//leave play from your battlefield
if (e->from == p->game->battlefield) if (e->from == p->game->battlefield)
@@ -1883,13 +1923,14 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
for (int j = 0; j < nbcards; ++j) for (int j = 0; j < nbcards; ++j)
{ {
MTGCardInstance * c = z->cards[j]; MTGCardInstance * c = z->cards[j];
if (c && ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos) || (c->has( if (c && ((c->has(Constants::AFFINITYARTIFACTS) && etype.find("art") != string::npos)
Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos) || (c->has( || (c->has(Constants::AFFINITYSWAMP) && etype.find("swa") != string::npos)
Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos) || (c->has( || (c->has(Constants::AFFINITYMOUNTAIN) && etype.find("mou") != string::npos)
Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos) || (c->has( || (c->has(Constants::AFFINITYPLAINS) && etype.find("pla") != string::npos)
Constants::AFFINITYISLAND) && etype.find("isl") != string::npos) || (c->has( || (c->has(Constants::AFFINITYISLAND) && etype.find("isl") != string::npos)
Constants::AFFINITYFOREST) && etype.find("for") != string::npos) || (c->has( || (c->has(Constants::AFFINITYFOREST) && etype.find("for") != string::npos)
Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos))) || (c->has(Constants::AFFINITYGREENCREATURES) && etype.find("cre") != string::npos))
)
{ {
if (c->reduxamount > 0) if (c->reduxamount > 0)
{ {
@@ -1911,21 +1952,25 @@ int MTGAffinityRule::receiveEvent(WEvent * event)
} }
return 0; return 0;
} }
ostream& MTGAffinityRule::toString(ostream& out) const ostream& MTGAffinityRule::toString(ostream& out) const
{ {
out << "MTGAffinityRule ::: ("; out << "MTGAffinityRule ::: (";
return MTGAbility::toString(out) << ")"; return MTGAbility::toString(out) << ")";
} }
int MTGAffinityRule::testDestroy() int MTGAffinityRule::testDestroy()
{ {
return 0; return 0;
} }
MTGAffinityRule * MTGAffinityRule::clone() const MTGAffinityRule * MTGAffinityRule::clone() const
{ {
MTGAffinityRule * a = NEW MTGAffinityRule(*this); MTGAffinityRule * a = NEW MTGAffinityRule(*this);
a->isClone = 1; a->isClone = 1;
return a; return a;
} }
//------------------------------------------------------------------- //-------------------------------------------------------------------
MTGTokensCleanup::MTGTokensCleanup(int _id) : MTGTokensCleanup::MTGTokensCleanup(int _id) :