From a84eb8dc2202b27a83ff88c8d31e135dfa75d7b7 Mon Sep 17 00:00:00 2001 From: "wagic.the.homebrew" Date: Thu, 26 May 2011 12:27:44 +0000 Subject: [PATCH] -Fix for issue 583 (fireball crash) -- converted an array into a vector to avoid weird edge cases -- fixed bugs with array "backupTargets" --- projects/mtg/bin/Res/test/_tests.txt | 1 + projects/mtg/bin/Res/test/fireball_i583.txt | 29 ++++++++ projects/mtg/include/AIHints.h | 80 ++++++++++----------- projects/mtg/include/MTGCardInstance.h | 2 +- projects/mtg/include/TargetChooser.h | 4 +- projects/mtg/include/TargetsList.h | 10 +-- projects/mtg/src/ActionStack.cpp | 10 +-- projects/mtg/src/MTGAbility.cpp | 4 +- projects/mtg/src/TargetChooser.cpp | 4 +- projects/mtg/src/TargetsList.cpp | 24 +++---- 10 files changed, 96 insertions(+), 72 deletions(-) create mode 100644 projects/mtg/bin/Res/test/fireball_i583.txt diff --git a/projects/mtg/bin/Res/test/_tests.txt b/projects/mtg/bin/Res/test/_tests.txt index 5a8030db9..70c015aef 100644 --- a/projects/mtg/bin/Res/test/_tests.txt +++ b/projects/mtg/bin/Res/test/_tests.txt @@ -275,6 +275,7 @@ fault_line.txt feral_hydra.txt fieldmist_borderpost.txt fire_tempest.txt +fireball_i583.txt firebreathing.txt fists_of_ironwood.txt flagstones.txt diff --git a/projects/mtg/bin/Res/test/fireball_i583.txt b/projects/mtg/bin/Res/test/fireball_i583.txt new file mode 100644 index 000000000..4675e87d9 --- /dev/null +++ b/projects/mtg/bin/Res/test/fireball_i583.txt @@ -0,0 +1,29 @@ +#Bug: fireball can crash the game if unselecting a target +#see http://code.google.com/p/wagic/issues/detail?id=583 +#Target 8 creatures and remove 1 of them +[INIT] +FIRSTMAIN +[PLAYER1] +hand:fireball +manapool:{7}{R}{R}{R}{R}{R}{R}{R}{R} +inplay:raging goblin,Akrasan Squire,Alpha Myr,Ambush Party,Apprentice Wizard,Arbor Elf,Aven Squire,Bay Falcon +[PLAYER2] +[DO] +fireball +raging goblin +Akrasan Squire +Alpha Myr +Ambush Party +Apprentice Wizard +Arbor Elf +Aven Squire +Bay Falcon +Alpha Myr +fireball +[ASSERT] +FIRSTMAIN +[PLAYER1] +graveyard:raging goblin,Akrasan Squire,Ambush Party,Apprentice Wizard,Arbor Elf,Aven Squire,Bay Falcon, Fireball +inplay:Alpha Myr +[PLAYER2] +[END] \ No newline at end of file diff --git a/projects/mtg/include/AIHints.h b/projects/mtg/include/AIHints.h index 6d3a764f6..5f1040dfb 100644 --- a/projects/mtg/include/AIHints.h +++ b/projects/mtg/include/AIHints.h @@ -1,43 +1,43 @@ -#ifndef _AIHINTS_H_ -#define _AIHINTS_H_ - +#ifndef _AIHINTS_H_ +#define _AIHINTS_H_ + #include #include -using std::string; -using std::vector; - -#include "AIPlayer.h" - -class ManaCost; -class MTGAbility; - -class AIHint -{ -public: - string mCondition; - string mAction; - int mSourceId; - AIHint(string line); -}; - - -class AIHints -{ -protected: - AIPlayer * mPlayer; - vector hints; - AIHint * getByCondition (string condition); - AIAction * findAbilityRecursive(AIHint * hint, ManaCost * potentialMana); - vector findAbilities(AIHint * hint); - RankingContainer findActions(AIHint * hint); - string constraintsNotFulfilled(AIAction * a, AIHint * hint, ManaCost * potentialMana); - bool findSource(int sourceId); - bool abilityMatches(MTGAbility * a, AIHint * hint); -public: - AIHints (AIPlayer * player); - AIAction * suggestAbility(ManaCost * potentialMana); - void add(string line); - ~AIHints(); -}; - +using std::string; +using std::vector; + +#include "AIPlayer.h" + +class ManaCost; +class MTGAbility; + +class AIHint +{ +public: + string mCondition; + string mAction; + int mSourceId; + AIHint(string line); +}; + + +class AIHints +{ +protected: + AIPlayer * mPlayer; + vector hints; + AIHint * getByCondition (string condition); + AIAction * findAbilityRecursive(AIHint * hint, ManaCost * potentialMana); + vector findAbilities(AIHint * hint); + RankingContainer findActions(AIHint * hint); + string constraintsNotFulfilled(AIAction * a, AIHint * hint, ManaCost * potentialMana); + bool findSource(int sourceId); + bool abilityMatches(MTGAbility * a, AIHint * hint); +public: + AIHints (AIPlayer * player); + AIAction * suggestAbility(ManaCost * potentialMana); + void add(string line); + ~AIHints(); +}; + #endif \ No newline at end of file diff --git a/projects/mtg/include/MTGCardInstance.h b/projects/mtg/include/MTGCardInstance.h index 47075b9ae..286b6cbe2 100644 --- a/projects/mtg/include/MTGCardInstance.h +++ b/projects/mtg/include/MTGCardInstance.h @@ -114,7 +114,7 @@ public: int typeAsTarget(){return TARGET_CARD;} const string getDisplayName() const; MTGCardInstance * target; - Targetable * backupTargets[MAX_TARGETS]; + vector backupTargets; //types diff --git a/projects/mtg/include/TargetChooser.h b/projects/mtg/include/TargetChooser.h index b6b7895d1..7396f1cd4 100644 --- a/projects/mtg/include/TargetChooser.h +++ b/projects/mtg/include/TargetChooser.h @@ -67,7 +67,7 @@ public: virtual int full() { - if (maxtargets != -1 && cursor >= maxtargets) + if (maxtargets != -1 && ((int) (targets.size())) >= maxtargets) { return 1; } @@ -79,7 +79,7 @@ public: ; virtual int ready() { - return cursor; + return (int) (targets.size()); } ; virtual ~TargetChooser() diff --git a/projects/mtg/include/TargetsList.h b/projects/mtg/include/TargetsList.h index b2c3dbbcd..afc67bb56 100644 --- a/projects/mtg/include/TargetsList.h +++ b/projects/mtg/include/TargetsList.h @@ -1,8 +1,6 @@ #ifndef _TARGETSLIST_H_ #define _TARGETSLIST_H_ -#define MAX_TARGETS 20 - class Targetable; class MTGCardInstance; class Player; @@ -11,13 +9,15 @@ class Spell; class Interruptible; class Damage; +#include +using std::vector; + class TargetsList { public: - int cursor; TargetsList(); TargetsList(Targetable * _targets[], int nbtargets); - Targetable* targets[MAX_TARGETS]; + vector targets; int alreadyHasTarget(Targetable * target); int removeTarget(Targetable * _card); int toggleTarget(Targetable * _card); @@ -31,7 +31,7 @@ public: Targetable * getNextTarget(Targetable * previous = 0, int type = -1); void initTargets() { - cursor = 0; + targets.clear(); } ; }; diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index 47f67b7e0..a849925ba 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -217,10 +217,12 @@ Interruptible(id), tc(tc), cost(_cost), payResult(payResult) mHeight = 40; type = ACTION_SPELL; from = _source->getCurrentZone(); - for(int i = 0;i < MAX_TARGETS;i++) + + _source->backupTargets.clear(); + if (tc) { - if(tc && tc->targets[i] != NULL) - _source->backupTargets[i] = tc->targets[i]; + for(size_t i = 0;i < tc->targets.size();i++) + _source->backupTargets.push_back(tc->targets[i]); } // fill information on how the card came into this zone. Right now the quickest way is to do it here, based on how the mana was paid... @@ -360,7 +362,7 @@ int Spell::getNbTargets() { if (!tc) return 0; - return tc->cursor; + return (int) (tc->targets.size()); } void Spell::Render() diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 9d7e45873..e458d8359 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1762,9 +1762,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG found = s.find("wingame"); if (found != string::npos) { - Damageable * d = NULL; - if (spell) - d = spell->getNextDamageableTarget(); + Damageable * d = spell ? spell->getNextDamageableTarget() : NULL; MTGAbility * a = NEW AAWinGame(id, card, d, NULL, who); a->oneShot = 1; return a; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index f283cc282..6675ddc75 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -486,7 +486,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta size_t start = attribute.find("share!"); size_t end = attribute.rfind("!"); string CDtype = attribute.substr(start + 6,end - start); - if( card && card->isSpell() && card->backupTargets[0]->typeAsTarget() == TARGET_STACKACTION) + if( card && card->isSpell() && card->backupTargets.size() && card->backupTargets[0]->typeAsTarget() == TARGET_STACKACTION) { //spells always store their targets in :targets[] //however they are all erased as the spell resolves @@ -785,7 +785,7 @@ int TargetChooser::ForceTargetListReady() int TargetChooser::targetsReadyCheck() { - if (cursor <= 0) + if (!targets.size()) { return TARGET_NOK; } diff --git a/projects/mtg/src/TargetsList.cpp b/projects/mtg/src/TargetsList.cpp index b51abe531..2c3f5457a 100644 --- a/projects/mtg/src/TargetsList.cpp +++ b/projects/mtg/src/TargetsList.cpp @@ -8,24 +8,19 @@ TargetsList::TargetsList() { - cursor = 0; } TargetsList::TargetsList(Targetable * _targets[], int nbtargets) { for (int i = 0; i < nbtargets; i++) - { - targets[i] = _targets[i]; - } - cursor = nbtargets; + targets.push_back(_targets[i]); } int TargetsList::addTarget(Targetable * target) { if (!alreadyHasTarget(target)) { - targets[cursor] = target; - cursor++; + targets.push_back(target); return 1; } return 0; @@ -34,7 +29,7 @@ int TargetsList::addTarget(Targetable * target) int TargetsList::alreadyHasTarget(Targetable * target) { - for (int i = 0; i < cursor; i++) + for (size_t i = 0; i < targets.size(); i++) { if (targets[i] == target) return 1; } @@ -43,13 +38,12 @@ int TargetsList::alreadyHasTarget(Targetable * target) int TargetsList::removeTarget(Targetable * target) { - for (int i = 0; i < cursor; i++) + for (size_t i = 0; i < targets.size(); i++) { if (targets[i] == target) { - targets[i] = targets[cursor]; - targets[cursor] = NULL; - cursor--; + targets.erase(targets.begin() + i); + return 1; } } @@ -74,7 +68,7 @@ Targetable * TargetsList::getNextTarget(Targetable * previous, int type) { int found = 0; if (!previous) found = 1; - for (int i = 0; i < cursor; i++) + for (size_t i = 0; i < targets.size(); i++) { if (found && (type == -1 || targets[i]->typeAsTarget() == type)) { @@ -99,7 +93,7 @@ Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int { int found = 0; if (!previous) found = 1; - for (int i = 0; i < cursor; i++) + for (size_t i = 0; i < targets.size(); i++) { if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION) { @@ -131,7 +125,7 @@ Damageable * TargetsList::getNextDamageableTarget(Damageable * previous) { int found = 0; if (!previous) found = 1; - for (int i = 0; i < cursor; i++) + for (size_t i = 0; i < targets.size(); i++) { if (targets[i]->typeAsTarget() == TARGET_PLAYER)