Found & fixed two memory leaks:
- computeActions would leak a ManaCost. This was fairly minor. - AIPlayer::SelectAbility had a major leak. Basically, there's some code that pulls a random number for an efficiency check - if the action's efficiency value was below that random number, the action pointer was cleared, and none of the actions that were to be discarded would be deleted out of the rankings map. I've switched out the rankings container to not contain action pointers, but real action objects, so regardless what kind of logic is implemented, the map will properly clear out its objects upon destruction.
This commit is contained in:
@@ -21,39 +21,58 @@ using std::queue;
|
|||||||
|
|
||||||
class AIStats;
|
class AIStats;
|
||||||
|
|
||||||
class AIAction{
|
class AIAction
|
||||||
|
{
|
||||||
protected:
|
protected:
|
||||||
int efficiency;
|
int efficiency;
|
||||||
static int currentId;
|
static int currentId;
|
||||||
public:
|
public:
|
||||||
MTGAbility * ability;
|
MTGAbility * ability;
|
||||||
NestedAbility * nability;
|
NestedAbility * nability;
|
||||||
Player * player;
|
Player * player;
|
||||||
int id;
|
int id;
|
||||||
bool checked;
|
bool checked;
|
||||||
MTGCardInstance * click;
|
MTGCardInstance * click;
|
||||||
MTGCardInstance * target; // TODO Improve
|
MTGCardInstance * target; // TODO Improve
|
||||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL):ability(a),click(c),target(t){player = NULL; efficiency = -1; id = currentId++;};
|
|
||||||
AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL):click(c),target(t){player = NULL; ability = NULL; efficiency = -1; id = currentId++;};
|
|
||||||
AIAction(Player * p):player(p){ability = NULL; target = NULL; click = NULL; efficiency = -1;};
|
|
||||||
int getEfficiency();
|
|
||||||
int Act();
|
|
||||||
|
|
||||||
|
|
||||||
|
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||||
|
: ability(a),click(c),target(t), player(NULL), efficiency(-1)
|
||||||
|
{
|
||||||
|
id = currentId++;
|
||||||
|
};
|
||||||
|
|
||||||
|
AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||||
|
: click(c),target(t), player(NULL), ability(NULL), efficiency(-1)
|
||||||
|
{
|
||||||
|
id = currentId++;
|
||||||
|
};
|
||||||
|
|
||||||
|
AIAction(Player * p)
|
||||||
|
: player(p), ability(NULL), target(NULL), click(NULL), efficiency(-1)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
int getEfficiency();
|
||||||
|
int Act();
|
||||||
};
|
};
|
||||||
|
|
||||||
class CmpAbilities { // compares Abilities efficiency
|
// compares Abilities efficiency
|
||||||
public:
|
class CmpAbilities
|
||||||
bool operator()(AIAction * a1, AIAction * a2) const {
|
{
|
||||||
int e1 = 0;
|
public:
|
||||||
e1 = a1->getEfficiency();
|
bool operator()(const AIAction& a1, const AIAction& a2) const
|
||||||
int e2 = 0;
|
{
|
||||||
e2 = a2->getEfficiency();
|
AIAction* a1Ptr = const_cast<AIAction*>(&a1);
|
||||||
if (e1 == e2) return a1->id < a2->id;
|
AIAction* a2Ptr = const_cast<AIAction*>(&a2);
|
||||||
return (e1 > e2);
|
int e1 = a1Ptr->getEfficiency();
|
||||||
}
|
int e2 = a2Ptr->getEfficiency();
|
||||||
|
if (e1 == e2) return a1Ptr->id < a2Ptr->id;
|
||||||
|
return (e1 > e2);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef std::map<AIAction, int, CmpAbilities> RankingContainer;
|
||||||
|
|
||||||
class AIPlayer: public Player{
|
class AIPlayer: public Player{
|
||||||
protected:
|
protected:
|
||||||
//Variables used by Test suite
|
//Variables used by Test suite
|
||||||
@@ -92,7 +111,7 @@ public:
|
|||||||
int isAI(){return 1;};
|
int isAI(){return 1;};
|
||||||
int canHandleCost(MTGAbility * ability);
|
int canHandleCost(MTGAbility * ability);
|
||||||
int selectAbility();
|
int selectAbility();
|
||||||
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAction *, int,CmpAbilities> * ranking);
|
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
||||||
int useAbility();
|
int useAbility();
|
||||||
virtual int getEfficiency(AIAction * action);
|
virtual int getEfficiency(AIAction * action);
|
||||||
|
|
||||||
|
|||||||
@@ -576,12 +576,12 @@ int AIAction::getEfficiency()
|
|||||||
return efficiency;
|
return efficiency;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAction *, int, CmpAbilities> * ranking)
|
int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking)
|
||||||
{
|
{
|
||||||
if (!a->tc)
|
if (!a->tc)
|
||||||
{
|
{
|
||||||
AIAction * as = NEW AIAction(a, c, NULL);
|
AIAction aiAction(a, c, NULL);
|
||||||
(*ranking)[as] = 1;
|
ranking[aiAction] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
@@ -598,8 +598,8 @@ int AIPlayer::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, map<AIAc
|
|||||||
if (a->tc->canTarget(t))
|
if (a->tc->canTarget(t))
|
||||||
{
|
{
|
||||||
|
|
||||||
AIAction * as = NEW AIAction(a, c, t);
|
AIAction aiAction(a, c, t);
|
||||||
(*ranking)[as] = 1;
|
ranking[aiAction] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -621,7 +621,7 @@ int AIPlayer::selectAbility()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
findingAbility = true;//im looking now safely!
|
findingAbility = true;//im looking now safely!
|
||||||
map<AIAction *, int, CmpAbilities> ranking;
|
RankingContainer ranking;
|
||||||
list<int>::iterator it;
|
list<int>::iterator it;
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
//This loop is extrmely inefficient. TODO: optimize!
|
//This loop is extrmely inefficient. TODO: optimize!
|
||||||
@@ -636,9 +636,10 @@ int AIPlayer::selectAbility()
|
|||||||
{
|
{
|
||||||
MTGCardInstance * card = game->inPlay->cards[j];
|
MTGCardInstance * card = game->inPlay->cards[j];
|
||||||
if (a->isReactingToClick(card, totalPotentialMana))
|
if (a->isReactingToClick(card, totalPotentialMana))
|
||||||
{ //This test is to avod the huge call to getPotentialManaCost after that
|
{ //This test is to avoid the huge call to getPotentialManaCost after that
|
||||||
ManaCost * pMana = getPotentialMana(card);
|
ManaCost * pMana = getPotentialMana(card);
|
||||||
if (a->isReactingToClick(card, pMana)) createAbilityTargets(a, card, &ranking);
|
if (a->isReactingToClick(card, pMana))
|
||||||
|
createAbilityTargets(a, card, ranking);
|
||||||
delete (pMana);
|
delete (pMana);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -647,30 +648,17 @@ int AIPlayer::selectAbility()
|
|||||||
|
|
||||||
if (ranking.size())
|
if (ranking.size())
|
||||||
{
|
{
|
||||||
AIAction * a = 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 (getEfficiency(a) < chance)
|
if (action.getEfficiency() >= chance)
|
||||||
{
|
|
||||||
a = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (!clickstream.size())
|
if (!clickstream.size())
|
||||||
{
|
{
|
||||||
DebugTrace("AIPlayer:Using Activated ability");
|
DebugTrace("AIPlayer:Using Activated ability");
|
||||||
if (tapLandsForMana(a->ability->cost, a->click))
|
if (tapLandsForMana(action.ability->cost, action.click))
|
||||||
clickstream.push(a);
|
clickstream.push(NEW AIAction(action));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
a = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map<AIAction *, int, CmpAbilities>::iterator it2;
|
|
||||||
for (it2 = ranking.begin(); it2 != ranking.end(); it2++)
|
|
||||||
{
|
|
||||||
if (a && a != it2->first) delete (it2->first);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
findingAbility = false;//ok to start looking again.
|
findingAbility = false;//ok to start looking again.
|
||||||
@@ -1224,7 +1212,8 @@ int AIPlayerBaka::computeActions()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (potential) delete (currentMana);
|
if (currentMana != NULL)
|
||||||
|
delete (currentMana);
|
||||||
if (nextCardToPlay)
|
if (nextCardToPlay)
|
||||||
{
|
{
|
||||||
if (potential)
|
if (potential)
|
||||||
|
|||||||
Reference in New Issue
Block a user