-Fix for issue 583 (fireball crash)

-- converted an array into a vector to avoid weird edge cases
-- fixed bugs with array "backupTargets"
This commit is contained in:
wagic.the.homebrew
2011-05-26 12:27:44 +00:00
parent ffda1d0548
commit a84eb8dc22
10 changed files with 96 additions and 72 deletions
+1
View File
@@ -275,6 +275,7 @@ fault_line.txt
feral_hydra.txt feral_hydra.txt
fieldmist_borderpost.txt fieldmist_borderpost.txt
fire_tempest.txt fire_tempest.txt
fireball_i583.txt
firebreathing.txt firebreathing.txt
fists_of_ironwood.txt fists_of_ironwood.txt
flagstones.txt flagstones.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]
+40 -40
View File
@@ -1,43 +1,43 @@
#ifndef _AIHINTS_H_ #ifndef _AIHINTS_H_
#define _AIHINTS_H_ #define _AIHINTS_H_
#include <string> #include <string>
#include <vector> #include <vector>
using std::string; using std::string;
using std::vector; using std::vector;
#include "AIPlayer.h" #include "AIPlayer.h"
class ManaCost; class ManaCost;
class MTGAbility; class MTGAbility;
class AIHint class AIHint
{ {
public: public:
string mCondition; string mCondition;
string mAction; string mAction;
int mSourceId; int mSourceId;
AIHint(string line); AIHint(string line);
}; };
class AIHints class AIHints
{ {
protected: protected:
AIPlayer * mPlayer; AIPlayer * mPlayer;
vector<AIHint *> hints; vector<AIHint *> hints;
AIHint * getByCondition (string condition); AIHint * getByCondition (string condition);
AIAction * findAbilityRecursive(AIHint * hint, ManaCost * potentialMana); AIAction * findAbilityRecursive(AIHint * hint, ManaCost * potentialMana);
vector<MTGAbility *> findAbilities(AIHint * hint); vector<MTGAbility *> findAbilities(AIHint * hint);
RankingContainer findActions(AIHint * hint); RankingContainer findActions(AIHint * hint);
string constraintsNotFulfilled(AIAction * a, AIHint * hint, ManaCost * potentialMana); string constraintsNotFulfilled(AIAction * a, AIHint * hint, ManaCost * potentialMana);
bool findSource(int sourceId); bool findSource(int sourceId);
bool abilityMatches(MTGAbility * a, AIHint * hint); bool abilityMatches(MTGAbility * a, AIHint * hint);
public: public:
AIHints (AIPlayer * player); AIHints (AIPlayer * player);
AIAction * suggestAbility(ManaCost * potentialMana); AIAction * suggestAbility(ManaCost * potentialMana);
void add(string line); void add(string line);
~AIHints(); ~AIHints();
}; };
#endif #endif
+1 -1
View File
@@ -114,7 +114,7 @@ public:
int typeAsTarget(){return TARGET_CARD;} int typeAsTarget(){return TARGET_CARD;}
const string getDisplayName() const; const string getDisplayName() const;
MTGCardInstance * target; MTGCardInstance * target;
Targetable * backupTargets[MAX_TARGETS]; vector<Targetable *> backupTargets;
//types //types
+2 -2
View File
@@ -67,7 +67,7 @@ public:
virtual int full() virtual int full()
{ {
if (maxtargets != -1 && cursor >= maxtargets) if (maxtargets != -1 && ((int) (targets.size())) >= maxtargets)
{ {
return 1; return 1;
} }
@@ -79,7 +79,7 @@ public:
; ;
virtual int ready() virtual int ready()
{ {
return cursor; return (int) (targets.size());
} }
; ;
virtual ~TargetChooser() virtual ~TargetChooser()
+5 -5
View File
@@ -1,8 +1,6 @@
#ifndef _TARGETSLIST_H_ #ifndef _TARGETSLIST_H_
#define _TARGETSLIST_H_ #define _TARGETSLIST_H_
#define MAX_TARGETS 20
class Targetable; class Targetable;
class MTGCardInstance; class MTGCardInstance;
class Player; class Player;
@@ -11,13 +9,15 @@ class Spell;
class Interruptible; class Interruptible;
class Damage; class Damage;
#include <vector>
using std::vector;
class TargetsList class TargetsList
{ {
public: public:
int cursor;
TargetsList(); TargetsList();
TargetsList(Targetable * _targets[], int nbtargets); TargetsList(Targetable * _targets[], int nbtargets);
Targetable* targets[MAX_TARGETS]; vector<Targetable*> targets;
int alreadyHasTarget(Targetable * target); int alreadyHasTarget(Targetable * target);
int removeTarget(Targetable * _card); int removeTarget(Targetable * _card);
int toggleTarget(Targetable * _card); int toggleTarget(Targetable * _card);
@@ -31,7 +31,7 @@ public:
Targetable * getNextTarget(Targetable * previous = 0, int type = -1); Targetable * getNextTarget(Targetable * previous = 0, int type = -1);
void initTargets() void initTargets()
{ {
cursor = 0; targets.clear();
} }
; ;
}; };
+6 -4
View File
@@ -217,10 +217,12 @@ Interruptible(id), tc(tc), cost(_cost), payResult(payResult)
mHeight = 40; mHeight = 40;
type = ACTION_SPELL; type = ACTION_SPELL;
from = _source->getCurrentZone(); from = _source->getCurrentZone();
for(int i = 0;i < MAX_TARGETS;i++)
_source->backupTargets.clear();
if (tc)
{ {
if(tc && tc->targets[i] != NULL) for(size_t i = 0;i < tc->targets.size();i++)
_source->backupTargets[i] = tc->targets[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... // 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) if (!tc)
return 0; return 0;
return tc->cursor; return (int) (tc->targets.size());
} }
void Spell::Render() void Spell::Render()
+1 -3
View File
@@ -1762,9 +1762,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
found = s.find("wingame"); found = s.find("wingame");
if (found != string::npos) if (found != string::npos)
{ {
Damageable * d = NULL; Damageable * d = spell ? spell->getNextDamageableTarget() : NULL;
if (spell)
d = spell->getNextDamageableTarget();
MTGAbility * a = NEW AAWinGame(id, card, d, NULL, who); MTGAbility * a = NEW AAWinGame(id, card, d, NULL, who);
a->oneShot = 1; a->oneShot = 1;
return a; return a;
+2 -2
View File
@@ -486,7 +486,7 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
size_t start = attribute.find("share!"); size_t start = attribute.find("share!");
size_t end = attribute.rfind("!"); size_t end = attribute.rfind("!");
string CDtype = attribute.substr(start + 6,end - start); string CDtype = attribute.substr(start + 6,end - start);
if( card && card->isSpell() && card->backupTargets[0]->typeAsTarget() == TARGET_STACKACTION) if( card && card->isSpell() && card->backupTargets.size() && card->backupTargets[0]->typeAsTarget() == TARGET_STACKACTION)
{ {
//spells always store their targets in :targets[] //spells always store their targets in :targets[]
//however they are all erased as the spell resolves //however they are all erased as the spell resolves
@@ -785,7 +785,7 @@ int TargetChooser::ForceTargetListReady()
int TargetChooser::targetsReadyCheck() int TargetChooser::targetsReadyCheck()
{ {
if (cursor <= 0) if (!targets.size())
{ {
return TARGET_NOK; return TARGET_NOK;
} }
+9 -15
View File
@@ -8,24 +8,19 @@
TargetsList::TargetsList() TargetsList::TargetsList()
{ {
cursor = 0;
} }
TargetsList::TargetsList(Targetable * _targets[], int nbtargets) TargetsList::TargetsList(Targetable * _targets[], int nbtargets)
{ {
for (int i = 0; i < nbtargets; i++) for (int i = 0; i < nbtargets; i++)
{ targets.push_back(_targets[i]);
targets[i] = _targets[i];
}
cursor = nbtargets;
} }
int TargetsList::addTarget(Targetable * target) int TargetsList::addTarget(Targetable * target)
{ {
if (!alreadyHasTarget(target)) if (!alreadyHasTarget(target))
{ {
targets[cursor] = target; targets.push_back(target);
cursor++;
return 1; return 1;
} }
return 0; return 0;
@@ -34,7 +29,7 @@ int TargetsList::addTarget(Targetable * target)
int TargetsList::alreadyHasTarget(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; if (targets[i] == target) return 1;
} }
@@ -43,13 +38,12 @@ int TargetsList::alreadyHasTarget(Targetable * target)
int TargetsList::removeTarget(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) if (targets[i] == target)
{ {
targets[i] = targets[cursor]; targets.erase(targets.begin() + i);
targets[cursor] = NULL; return 1;
cursor--;
} }
} }
@@ -74,7 +68,7 @@ Targetable * TargetsList::getNextTarget(Targetable * previous, int type)
{ {
int found = 0; int found = 0;
if (!previous) found = 1; 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)) if (found && (type == -1 || targets[i]->typeAsTarget() == type))
{ {
@@ -99,7 +93,7 @@ Interruptible * TargetsList::getNextInterruptible(Interruptible * previous, int
{ {
int found = 0; int found = 0;
if (!previous) found = 1; 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) if (found && targets[i]->typeAsTarget() == TARGET_STACKACTION)
{ {
@@ -131,7 +125,7 @@ Damageable * TargetsList::getNextDamageableTarget(Damageable * previous)
{ {
int found = 0; int found = 0;
if (!previous) found = 1; 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) if (targets[i]->typeAsTarget() == TARGET_PLAYER)