diff --git a/projects/mtg/bin/Res/test/manual/ai_clone_i209.txt b/projects/mtg/bin/Res/test/manual/ai_clone_i209.txt new file mode 100644 index 000000000..b100e0792 --- /dev/null +++ b/projects/mtg/bin/Res/test/manual/ai_clone_i209.txt @@ -0,0 +1,16 @@ +#Bug:AI clone +[INIT] +FIRSTMAIN +[PLAYER1] +manapool:{3}{U} +hand:clone +[PLAYER2] +[DO] +ai +ai +[ASSERT] +COMBATEND +[PLAYER1] +graveyard:clone +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/include/AIPlayer.h b/projects/mtg/include/AIPlayer.h index 186e47e9e..2a10a8ba1 100644 --- a/projects/mtg/include/AIPlayer.h +++ b/projects/mtg/include/AIPlayer.h @@ -22,7 +22,6 @@ class AIAction{ protected: int efficiency; static int currentId; - static MTGAbility * getCoreAbility(MTGAbility * a); public: MTGAbility * ability; Player * player; diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 71f094cd9..fc4aa0c77 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -438,6 +438,35 @@ class GenericActivatedAbility:public ActivatedAbility{ }; +//Copier. ActivatedAbility +class AACopier:public ActivatedAbility{ + public: + AACopier(int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost=NULL):ActivatedAbility(_id,_source,_cost,0,0){ + target = _target; + } + + int resolve(){ + MTGCardInstance * _target = (MTGCardInstance *) target; + if(_target){ + source->copy(_target); + return 1; + } + return 0; + } + + const char * getMenuText(){ + return "Copy"; + } + + + AACopier * clone() const{ + AACopier * a = NEW AACopier(*this); + a->isClone = 1; + return a; + } +}; + + /* Generic TargetAbility */ class GenericTargetAbility:public TargetAbility{ @@ -447,6 +476,8 @@ public: MTGGameZone * activeZone; GenericTargetAbility(int _id, MTGCardInstance * _source, TargetChooser * _tc,MTGAbility * a, ManaCost * _cost = NULL, int _tap=0, int limit = 0, int restrictions = 0, MTGGameZone * dest = NULL):TargetAbility(_id,_source, _tc,_cost,restrictions,_tap),limitPerTurn(limit), activeZone(dest){ ability = a; + MTGAbility * core = AbilityFactory::getCoreAbility(a); + if (dynamic_cast(core)) tc->other = true; //http://code.google.com/p/wagic/issues/detail?id=209 (avoid inifinite loop) counters = 0; } @@ -750,36 +781,6 @@ public: }; - -//Copier. ActivatedAbility -class AACopier:public ActivatedAbility{ - public: - AACopier(int _id, MTGCardInstance * _source, MTGCardInstance * _target = NULL, ManaCost * _cost=NULL):ActivatedAbility(_id,_source,_cost,0,0){ - target = _target; - } - - int resolve(){ - MTGCardInstance * _target = (MTGCardInstance *) target; - if(_target){ - source->copy(_target); - return 1; - } - return 0; - } - - const char * getMenuText(){ - return "Copy"; - } - - - AACopier * clone() const{ - AACopier * a = NEW AACopier(*this); - a->isClone = 1; - return a; - } -}; - - class AADestroyer:public ActivatedAbility{ public: int bury; diff --git a/projects/mtg/include/MTGAbility.h b/projects/mtg/include/MTGAbility.h index 525417b13..d5b2c0bbe 100644 --- a/projects/mtg/include/MTGAbility.h +++ b/projects/mtg/include/MTGAbility.h @@ -229,6 +229,7 @@ class AbilityFactory{ int abilityEfficiency(MTGAbility * a, Player * p, int mode = MODE_ABILITY, TargetChooser * tc = NULL); int magicText(int id, Spell * spell, MTGCardInstance * card = NULL, int mode = MODE_PUTINTOPLAY, TargetChooser * tc = NULL, MTGGameZone * dest = NULL); static int computeX(Spell * spell, MTGCardInstance * card); + static MTGAbility * getCoreAbility(MTGAbility * a); int destroyAllInPlay(TargetChooser * tc, int bury = 0); int moveAll(TargetChooser * tc, string destinationZone); int damageAll(TargetChooser * tc, int damage); diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index cd46db4af..fe3a573c1 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -25,7 +25,6 @@ class CardDescriptor; class TargetChooser: public TargetsList { protected: int forceTargetListReady; - bool other; public: enum{ @@ -34,7 +33,7 @@ class TargetChooser: public TargetsList { CONTROLLER = 1, TARGET_CONTROLLER = 2 }; - + bool other; TargetChooser(MTGCardInstance * card = NULL, int _maxtargets = -1, bool other = false); diff --git a/projects/mtg/src/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index de565d23f..335056b47 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -142,17 +142,7 @@ int AIPlayer::canHandleCost(MTGAbility * ability){ return 1; } -MTGAbility * AIAction::getCoreAbility(MTGAbility * a){ - GenericTargetAbility * gta = dynamic_cast(a); - if (gta) return getCoreAbility(gta->ability); - GenericActivatedAbility * gaa = dynamic_cast(a); - if (gaa) return getCoreAbility(gaa->ability); - - if (MultiAbility * abi = dynamic_cast(a)) return getCoreAbility(abi->abilities[0]); - - return a; -} int AIAction::getEfficiency(){ //TODO add multiplier according to what the player wants @@ -163,7 +153,7 @@ int AIAction::getEfficiency(){ Player * p = g->currentlyActing(); if (s->has(ability)) return 0; - MTGAbility * a = getCoreAbility(ability); + MTGAbility * a = AbilityFactory::getCoreAbility(ability); if (!a){ OutputDebugString("FATAL: Ability is NULL in AIAction::getEfficiency()"); @@ -341,7 +331,6 @@ int AIPlayer::chooseTarget(TargetChooser * tc){ target = this->opponent(); } - if (!tc->alreadyHasTarget(target) && tc->canTarget(target) && nbtargets < 50){ for (int i = 0; i < 3; i++){ //Increase probability to target a player when this is possible potentialTargets.push_back(target); @@ -356,21 +345,21 @@ int AIPlayer::chooseTarget(TargetChooser * tc){ for (int k=0; k< zone->nb_cards; k++){ MTGCardInstance * card = zone->cards[k]; if (!tc->alreadyHasTarget(card) && tc->canTarget(card) && nbtargets < 50){ - if (checkOnly) return 1; - int multiplier = 1; - if (getStats() && getStats()->isInTop(card,10)){ - multiplier++; - if (getStats()->isInTop(card,5)){ - multiplier++; - if (getStats()->isInTop(card,3)){ - multiplier++; - } - } - } - for (int l=0; l < multiplier; l++){ - potentialTargets.push_back(card); - nbtargets++; - } + if (checkOnly) return 1; + int multiplier = 1; + if (getStats() && getStats()->isInTop(card,10)){ + multiplier++; + if (getStats()->isInTop(card,5)){ + multiplier++; + if (getStats()->isInTop(card,3)){ + multiplier++; + } + } + } + for (int l=0; l < multiplier; l++){ + potentialTargets.push_back(card); + nbtargets++; + } } } } @@ -394,7 +383,7 @@ int AIPlayer::chooseTarget(TargetChooser * tc){ } } } - //BIG PROBLEM + //Couldn't find any valid target (why did we play that in the first place ?) gameObs->cancelCurrentAction(); return 0; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 1b5a8fcbd..fa5807908 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -162,6 +162,18 @@ int AbilityFactory::parseRestriction(string s){ return ActivatedAbility::NO_RESTRICTION; } +MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a){ + GenericTargetAbility * gta = dynamic_cast(a); + if (gta) return getCoreAbility(gta->ability); + + GenericActivatedAbility * gaa = dynamic_cast(a); + if (gaa) return getCoreAbility(gaa->ability); + + if (MultiAbility * abi = dynamic_cast(a)) return getCoreAbility(abi->abilities[0]); + + return a; +} + //Parses a string and returns the corresponding MTGAbility object // Returns NULL if parsing failed