diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index f3f04e9e3..306ea4cb1 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -120,6 +120,7 @@ paralysis2.txt persuasion.txt plague_rats.txt protomatter_powder.txt +pygmy_troll.txt pyroclasm.txt recover.txt resurrection.txt diff --git a/projects/mtg/bin/Res/test/pygmy_troll.txt b/projects/mtg/bin/Res/test/pygmy_troll.txt new file mode 100644 index 000000000..f643d8b41 --- /dev/null +++ b/projects/mtg/bin/Res/test/pygmy_troll.txt @@ -0,0 +1,49 @@ +#Testing bug with Rampage +[INIT] +FIRSTMAIN +[PLAYER1] +inplay:pygmy troll,forest +[PLAYER2] +inplay:grizzly bears,hill giant +[DO] +forest +pygmy troll +next +#combat begins +next +#combat attackers +pygmy troll +next +grizzly bears +next +next +eot +eot +next +#upkeep +next +#draw +next +#firstmain +next +#begins +next +#attackers +pygmy troll +next +#blockers +hill giant +next +#damage +next +#end +[ASSERT] +COMBATEND +[PLAYER1] +graveyard:pygmy troll +inplay:forest +manapool:{0} +[PLAYER2] +graveyard:grizzly bears +inplay:hill giant +[END] \ No newline at end of file diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 412b4ce8a..3dd3e2d97 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1024,6 +1024,13 @@ class APowerToughnessModifierUntilEndOfTurn: public ActivatedAbility{ ability = NEW AInstantPowerToughnessModifierUntilEOT(id,_source,_target,_power,_toughness); } + void Update(float dt){ + if (newPhase != currentPhase && newPhase ==Constants::MTG_PHASE_AFTER_EOT){ + counters = 0; + } + ActivatedAbility::Update(dt); + } + int fireAbility(){ return resolve(); } @@ -3296,7 +3303,8 @@ class AFireball:public InstantAbility{ AFireball(int _id, MTGCardInstance * card, Spell * spell, int x):InstantAbility(_id, card){ int nbtargets = spell->cursor; int totaldamage = x+1-nbtargets; - int individualdamage = totaldamage / nbtargets; + int individualdamage = 0; + if (nbtargets) individualdamage = totaldamage / nbtargets; Damageable * _target = spell->getNextDamageableTarget(); while(_target){ game->mLayers->stackLayer()->addDamage(source,_target,individualdamage); @@ -3890,7 +3898,6 @@ class AMinionofLeshrac: public TargetAbility{ //Rampage ability class ARampageAbility:public MTGAbility{ public: - MTGCardInstance * opponents[20]; int nbOpponents; int PowerModifier; int ToughnessModifier; @@ -3899,44 +3906,26 @@ class ARampageAbility:public MTGAbility{ ARampageAbility(int _id, MTGCardInstance * _source,int _PowerModifier, int _ToughnessModifier, int _MaxOpponent):MTGAbility(_id, _source){ PowerModifier = _PowerModifier; ToughnessModifier = _ToughnessModifier; - MaxOpponent = _MaxOpponent; + MaxOpponent = _MaxOpponent; + nbOpponents = 0; } void Update(float dt){ - if (source->isAttacker()){ - if (newPhase != currentPhase){ - if( newPhase == Constants::MTG_PHASE_COMBATDAMAGE){ - nbOpponents = 0; - MTGCardInstance * opponent = source->getNextOpponent(); - while (opponent){ - opponents[nbOpponents] = opponent; - nbOpponents ++; - opponent = source->getNextOpponent(opponent); - if (nbOpponents > MaxOpponent){ - source->power+= PowerModifier; - source->addToToughness(ToughnessModifier); - - } + if (newPhase != currentPhase){ + if( source->isAttacker() && newPhase == Constants::MTG_PHASE_COMBATDAMAGE){ + nbOpponents = source->blockers.size(); + for (int i = MaxOpponent; i < nbOpponents; i++){ + source->power+= PowerModifier; + source->addToToughness(ToughnessModifier); + } + } + if( newPhase == Constants::MTG_PHASE_AFTER_EOT ){ + for (int i = MaxOpponent; i < nbOpponents; i++){ + source->power-= PowerModifier; + source->addToToughness(-ToughnessModifier); + } + nbOpponents = 0; + } } - } - if( newPhase == Constants::MTG_PHASE_AFTER_EOT ){ - for (int i = 0; i < nbOpponents; i++){ - source->power-= PowerModifier; - source->addToToughness(-ToughnessModifier); - } - } - } - } - } - - virtual ostream& toString(ostream& out) const - { - out << "ARampageAbility ::: opponents : " << opponents - << " ; nbOpponents : " << nbOpponents - << " ; PowerModifier : " << PowerModifier - << " ; ToughnessModifier : " << ToughnessModifier - << " ; MaxOpponent : " << MaxOpponent - << " ("; - return MTGAbility::toString(out) << ")"; } ARampageAbility * clone() const{ diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index 4523bfb32..450d3c04d 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -217,7 +217,7 @@ class AbilityFactory{ class AManaProducer: public MTGAbility{ protected: - ManaCost * output; + string menutext; float x0,y0,x1,y1,x,y; float animation; @@ -226,6 +226,7 @@ class AManaProducer: public MTGAbility{ hgeParticleSystem * mParticleSys; public: + ManaCost * output; int tap; static int currentlyTapping; AManaProducer(int id, MTGCardInstance * card, ManaCost * _output, ManaCost * _cost = NULL, int doTap = 1 ); diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index e7122145a..11a560cc6 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -5,6 +5,7 @@ #include "../include/DamagerDamaged.h" #include "../include/AIStats.h" #include "../include/AllAbilities.h" +#include "../include/ExtraCost.h" const char * const MTG_LAND_TEXTS[] = {"artifact","forest","island","mountain","swamp","plains","other lands"}; @@ -68,57 +69,54 @@ void AIPlayer::tapLandsForMana(ManaCost * potentialMana, ManaCost * cost){ #endif if (!cost) return; ManaCost * diff = potentialMana->Diff(cost); - GameObserver * gameObs = GameObserver::GetInstance(); - CardDescriptor cd; - cd.setColor(Constants::MTG_COLOR_LAND); - cd.unsecureSetTapped(-1); + GameObserver * g = GameObserver::GetInstance(); - MTGCardInstance * card = NULL; - while((card = cd.nextmatch(game->inPlay, card))){ - - int doTap = 1; - for (int i=Constants::MTG_NB_COLORS-1; i>= 0; i--){ - if (diff->getCost(i) && card->hasSubtype(MTG_LAND_TEXTS[i]) ){ - diff->remove(i,1); - doTap = 0; - break; + mapused; + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish + //Make sure we can use the ability + MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); + AManaProducer * amp = dynamic_cast(a); + if (amp){ + MTGCardInstance * card = amp->source; + if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ + int doTap = 1; + for (int i=Constants::MTG_NB_COLORS-1; i>= 0; i--){ + if (diff->getCost(i) && amp->output->getCost(i) ){ + diff->remove(i,1); + doTap = 0; + break; + } + } + if (doTap){ + AIAction * action = NEW AIAction(amp,card); + clickstream.push(action); + used[card] = true; + } } } - if (doTap){ - AIAction * a = NEW AIAction(card); - clickstream.push(a); - } } - delete(diff); } -//TODO a better function that does not take into account only basic lands + ManaCost * AIPlayer::getPotentialMana(){ SAFE_DELETE(potentialMana); potentialMana = NEW ManaCost(); - CardDescriptor cd; - cd.setColor(Constants::MTG_COLOR_LAND); - cd.unsecureSetTapped(-1); - MTGCardInstance * card = NULL; - while((card = cd.nextmatch(game->inPlay, card))){ - - if (card->hasSubtype("plains")){ - potentialMana->add(Constants::MTG_COLOR_WHITE,1); - }else if(card->hasSubtype("swamp")){ - potentialMana->add(Constants::MTG_COLOR_BLACK,1); - }else if(card->hasSubtype("forest")){ - potentialMana->add(Constants::MTG_COLOR_GREEN,1); - }else if(card->hasSubtype("mountain")){ - potentialMana->add(Constants::MTG_COLOR_RED,1); - }else if(card->hasSubtype("island")){ - potentialMana->add(Constants::MTG_COLOR_BLUE,1); - }else{ -#if defined (WIN32) || defined (LINUX) - OutputDebugString("WTF ????\n"); -#endif + GameObserver * g = GameObserver::GetInstance(); + mapused; + for (int i = 1; i < g->mLayers->actionLayer()->mCount; i++){ //0 is not a mtgability...hackish + //Make sure we can use the ability + MTGAbility * a = ((MTGAbility *)g->mLayers->actionLayer()->mObjects[i]); + AManaProducer * amp = dynamic_cast(a); + if (amp){ + MTGCardInstance * card = amp->source; + if (!used[card] && amp->isReactingToClick(card) && amp->output->getConvertedCost()==1){ + potentialMana->add(amp->output); + used[card] = true; + } } } + return potentialMana; } @@ -148,6 +146,15 @@ int AIAction::getEfficiency(){ return 0; } + //Can't handle sacrifice costs that require a target yet :( + if (a->cost){ + ExtraCosts * ec = a->cost->extraCosts; + if (ec){ + for (size_t i = 0; i < ec->costs.size(); i++){ + if (ec->costs[i]->tc) return 0; + } + } + } switch (a->aType){ case MTGAbility::DAMAGER: { diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index 68bb8ac63..130095b4b 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -519,7 +519,12 @@ MTGCardInstance * MTGCardInstance::getNextOpponent(MTGCardInstance * previous){ int MTGCardInstance::setDefenser(MTGCardInstance * opponent){ GameObserver * g = GameObserver::GetInstance(); - if (defenser) defenser->blockers.remove(this); + if (defenser) { + if (g->players[0]->game->battlefield->hasCard(defenser) || + g->players[1]->game->battlefield->hasCard(defenser) ) { + defenser->blockers.remove(this); + } + } WEvent * e = NEW WEventCreatureBlocker(this, defenser, opponent); defenser = opponent; if (defenser){