AIPlayer minor tweaks:
- In order to clarify getEfficiency, started creating "getEfficiency" functions specific to each type of ability (see example with Damager). This won't reduce the file size but should make things bit clearer - Minor cleanup of getEfficiency - bug fixes in getEfficiency
This commit is contained in:
@@ -28,6 +28,7 @@ class AIAction
|
|||||||
protected:
|
protected:
|
||||||
static int currentId;
|
static int currentId;
|
||||||
public:
|
public:
|
||||||
|
Player * owner;
|
||||||
MTGAbility * ability;
|
MTGAbility * ability;
|
||||||
NestedAbility * nability;
|
NestedAbility * nability;
|
||||||
Player * player;
|
Player * player;
|
||||||
@@ -38,27 +39,27 @@ public:
|
|||||||
Targetable * playerAbilityTarget;
|
Targetable * playerAbilityTarget;
|
||||||
//player targeting through abilities is handled completely seperate from spell targeting.
|
//player targeting through abilities is handled completely seperate from spell targeting.
|
||||||
|
|
||||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
AIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||||
: ability(a), player(NULL), click(c), target(t),playerAbilityTarget(NULL)
|
: owner(owner), ability(a), player(NULL), click(c), target(t),playerAbilityTarget(NULL)
|
||||||
{
|
{
|
||||||
id = currentId++;
|
id = currentId++;
|
||||||
};
|
};
|
||||||
|
|
||||||
AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL);
|
AIAction(Player * owner, MTGCardInstance * c, MTGCardInstance * t = NULL);
|
||||||
|
|
||||||
AIAction(Player * p)//player targeting through spells
|
AIAction(Player * owner, Player * p)//player targeting through spells
|
||||||
: ability(NULL), player(p), click(NULL), target(NULL),playerAbilityTarget(NULL)
|
: owner(owner), ability(NULL), player(p), click(NULL), target(NULL),playerAbilityTarget(NULL)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
AIAction(MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
AIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||||
: ability(a), player(NULL), click(c), mAbilityTargets(targetCards),playerAbilityTarget(NULL)
|
: owner(owner), ability(a), player(NULL), click(c), mAbilityTargets(targetCards),playerAbilityTarget(NULL)
|
||||||
{
|
{
|
||||||
id = currentId++;
|
id = currentId++;
|
||||||
};
|
};
|
||||||
|
|
||||||
AIAction(MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
AIAction(Player * owner, MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||||
: ability(a), click(c),target(NULL), playerAbilityTarget(p)
|
: owner(owner), ability(a), click(c),target(NULL), playerAbilityTarget(p)
|
||||||
{
|
{
|
||||||
id = currentId++;
|
id = currentId++;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define _AI_PLAYER_BAKA_H_
|
#define _AI_PLAYER_BAKA_H_
|
||||||
|
|
||||||
#include "AIPlayer.h"
|
#include "AIPlayer.h"
|
||||||
|
#include "AllAbilities.h"
|
||||||
|
|
||||||
class AIStats;
|
class AIStats;
|
||||||
class AIHints;
|
class AIHints;
|
||||||
@@ -12,33 +13,37 @@ class AIHints;
|
|||||||
class OrderedAIAction: public AIAction
|
class OrderedAIAction: public AIAction
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
Player * getPlayerTarget();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
int efficiency;
|
int efficiency;
|
||||||
|
|
||||||
OrderedAIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
OrderedAIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||||
: AIAction(a, c, t), efficiency(-1)
|
: AIAction(owner, a, c, t), efficiency(-1)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
OrderedAIAction(MTGCardInstance * c, MTGCardInstance * t = NULL);
|
OrderedAIAction(Player * owner, MTGCardInstance * c, MTGCardInstance * t = NULL);
|
||||||
|
|
||||||
OrderedAIAction(Player * p)//player targeting through spells
|
OrderedAIAction(Player * owner, Player * p)//player targeting through spells
|
||||||
: AIAction(p), efficiency(-1)
|
: AIAction(owner,p), efficiency(-1)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
OrderedAIAction(MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
OrderedAIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||||
: AIAction(a, c, targetCards), efficiency(-1)
|
: AIAction(owner,a, c, targetCards), efficiency(-1)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
OrderedAIAction(MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
OrderedAIAction(Player * owner, MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||||
: AIAction(a, p, c), efficiency(-1)
|
: AIAction(owner, a, p, c), efficiency(-1)
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
int getEfficiency();
|
int getEfficiency();
|
||||||
|
|
||||||
|
// Functions depending on the type of Ability
|
||||||
|
int getEfficiency(AADamager * aad);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// compares Abilities efficiency
|
// compares Abilities efficiency
|
||||||
@@ -60,7 +65,7 @@ typedef std::map<OrderedAIAction, int, CmpAbilities> RankingContainer;
|
|||||||
|
|
||||||
|
|
||||||
class AIPlayerBaka: public AIPlayer{
|
class AIPlayerBaka: public AIPlayer{
|
||||||
private:
|
protected:
|
||||||
virtual int orderBlockers();
|
virtual int orderBlockers();
|
||||||
virtual int combatDamages();
|
virtual int combatDamages();
|
||||||
virtual int interruptIfICan();
|
virtual int interruptIfICan();
|
||||||
@@ -84,7 +89,6 @@ private:
|
|||||||
|
|
||||||
virtual AIStats * getStats();
|
virtual AIStats * getStats();
|
||||||
|
|
||||||
protected:
|
|
||||||
MTGCardInstance * nextCardToPlay;
|
MTGCardInstance * nextCardToPlay;
|
||||||
AIHints * hints;
|
AIHints * hints;
|
||||||
AIStats * stats;
|
AIStats * stats;
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#ifdef AI_CHANGE_TESTING
|
#ifdef AI_CHANGE_TESTING
|
||||||
|
|
||||||
#ifndef _AI_PLAYER_BAKA_B_H_
|
#ifndef _AI_PLAYER_BAKA_B_H_
|
||||||
#define _AI_PLAYER_BAKA_B_H_
|
#define _AI_PLAYER_BAKA_B_H_
|
||||||
|
|
||||||
#include "AIPlayerBaka.h"
|
#include "AIPlayerBaka.h"
|
||||||
|
#include "AllAbilities.h"
|
||||||
|
|
||||||
class AIStats;
|
class AIStats;
|
||||||
class AIHints;
|
class AIHints;
|
||||||
|
|
||||||
|
|
||||||
class AIPlayerBakaB: public AIPlayerBaka{
|
class AIPlayerBakaB: public AIPlayerBaka{
|
||||||
private:
|
protected:
|
||||||
int orderBlockers();
|
int orderBlockers();
|
||||||
int combatDamages();
|
int combatDamages();
|
||||||
int interruptIfICan();
|
int interruptIfICan();
|
||||||
@@ -36,16 +37,16 @@ private:
|
|||||||
|
|
||||||
AIStats * getStats();
|
AIStats * getStats();
|
||||||
|
|
||||||
protected:
|
|
||||||
MTGCardInstance * FindCardToPlay(ManaCost * potentialMana, const char * type);
|
MTGCardInstance * FindCardToPlay(ManaCost * potentialMana, const char * type);
|
||||||
|
|
||||||
//used by MomirPlayer, hence protected instead of private
|
|
||||||
virtual int getEfficiency(OrderedAIAction * action);
|
|
||||||
bool payTheManaCost(ManaCost * cost, MTGCardInstance * card = NULL,vector<MTGAbility*> gotPayment = vector<MTGAbility*>());
|
bool payTheManaCost(ManaCost * cost, MTGCardInstance * card = NULL,vector<MTGAbility*> gotPayment = vector<MTGAbility*>());
|
||||||
int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
|
int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
|
||||||
ManaCost * getPotentialMana(MTGCardInstance * card = NULL);
|
ManaCost * getPotentialMana(MTGCardInstance * card = NULL);
|
||||||
int selectAbility();
|
int selectAbility();
|
||||||
|
|
||||||
|
//used by MomirPlayer, hence protected instead of private
|
||||||
|
virtual int getEfficiency(OrderedAIAction * action);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
AIPlayerBakaB(string deckFile, string deckfileSmall, string avatarFile, MTGDeck * deck = NULL);
|
AIPlayerBakaB(string deckFile, string deckfileSmall, string avatarFile, MTGDeck * deck = NULL);
|
||||||
@@ -62,7 +63,7 @@ private:
|
|||||||
//used by AIHInts, therefore public instead of private :/
|
//used by AIHInts, therefore public instead of private :/
|
||||||
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -86,8 +86,8 @@ class MTGGameZone {
|
|||||||
void cleanupPhase();
|
void cleanupPhase();
|
||||||
void beforeBeginPhase();
|
void beforeBeginPhase();
|
||||||
|
|
||||||
int countByType(const char * value);
|
unsigned int countByType(const char * value);
|
||||||
int countByCanTarget(TargetChooser * tc);
|
unsigned int countByCanTarget(TargetChooser * tc);
|
||||||
MTGCardInstance * findByName(string name);
|
MTGCardInstance * findByName(string name);
|
||||||
|
|
||||||
//returns true if one of the cards in the zone has the ability
|
//returns true if one of the cards in the zone has the ability
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ int AIMomirPlayer::momir()
|
|||||||
if (ability->isReactingToClick(card, cost))
|
if (ability->isReactingToClick(card, cost))
|
||||||
{
|
{
|
||||||
payTheManaCost(cost);
|
payTheManaCost(cost);
|
||||||
AIAction * a = NEW AIAction(ability, card);
|
AIAction * a = NEW AIAction(this, ability, card);
|
||||||
clickstream.push(a);
|
clickstream.push(a);
|
||||||
result = 1;
|
result = 1;
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,7 @@ int AIMomirPlayer::computeActions()
|
|||||||
if (card && (canPutLandsIntoPlay == PlayRestriction::CAN_PLAY))
|
if (card && (canPutLandsIntoPlay == PlayRestriction::CAN_PLAY))
|
||||||
{
|
{
|
||||||
MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY);
|
MTGAbility * putIntoPlay = g->mLayers->actionLayer()->getAbility(MTGAbility::PUT_INTO_PLAY);
|
||||||
AIAction * a = NEW AIAction(putIntoPlay, card); //TODO putinplay action
|
AIAction * a = NEW AIAction(this, putIntoPlay, card); //TODO putinplay action
|
||||||
clickstream.push(a);
|
clickstream.push(a);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ const char * const MTG_LAND_TEXTS[] = { "artifact", "forest", "island", "mountai
|
|||||||
|
|
||||||
int AIAction::currentId = 0;
|
int AIAction::currentId = 0;
|
||||||
|
|
||||||
AIAction::AIAction(MTGCardInstance * c, MTGCardInstance * t)
|
AIAction::AIAction(Player * owner, MTGCardInstance * c, MTGCardInstance * t)
|
||||||
: ability(NULL), player(NULL), click(c), target(t)
|
: owner(owner), ability(NULL), player(NULL), click(c), target(t)
|
||||||
{
|
{
|
||||||
id = currentId++;
|
id = currentId++;
|
||||||
|
|
||||||
@@ -165,21 +165,21 @@ int AIPlayer::clickMultiTarget(TargetChooser * tc, vector<Targetable*>& potentia
|
|||||||
Player * pTarget = (Player*)potentialTargets[f];
|
Player * pTarget = (Player*)potentialTargets[f];
|
||||||
if(card && card == (MTGCardInstance*)tc->source)//if the source is part of the targetting deal with it first. second click is "confirming click".
|
if(card && card == (MTGCardInstance*)tc->source)//if the source is part of the targetting deal with it first. second click is "confirming click".
|
||||||
{
|
{
|
||||||
clickstream.push(NEW AIAction(card));
|
clickstream.push(NEW AIAction(this, card));
|
||||||
DebugTrace("Ai clicked source as a target: " << (card ? card->name : "None" ) << endl );
|
DebugTrace("Ai clicked source as a target: " << (card ? card->name : "None" ) << endl );
|
||||||
potentialTargets.erase(potentialTargets.begin() + f);
|
potentialTargets.erase(potentialTargets.begin() + f);
|
||||||
sourceIncluded = true;
|
sourceIncluded = true;
|
||||||
}
|
}
|
||||||
if(pTarget && pTarget->typeAsTarget() == TARGET_PLAYER)
|
if(pTarget && pTarget->typeAsTarget() == TARGET_PLAYER)
|
||||||
{
|
{
|
||||||
clickstream.push(NEW AIAction(pTarget));
|
clickstream.push(NEW AIAction(this, pTarget));
|
||||||
DebugTrace("Ai clicked Player as a target");
|
DebugTrace("Ai clicked Player as a target");
|
||||||
potentialTargets.erase(potentialTargets.begin() + f);
|
potentialTargets.erase(potentialTargets.begin() + f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::random_shuffle(potentialTargets.begin(), potentialTargets.end());
|
std::random_shuffle(potentialTargets.begin(), potentialTargets.end());
|
||||||
if(potentialTargets.size())
|
if(potentialTargets.size())
|
||||||
clickstream.push(NEW AIAction(NULL,tc->source,potentialTargets));
|
clickstream.push(NEW AIAction(this, NULL,tc->source,potentialTargets));
|
||||||
while(clickstream.size())
|
while(clickstream.size())
|
||||||
{
|
{
|
||||||
AIAction * action = clickstream.front();
|
AIAction * action = clickstream.front();
|
||||||
@@ -201,7 +201,7 @@ int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potenti
|
|||||||
if(!chosenCard)
|
if(!chosenCard)
|
||||||
{
|
{
|
||||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||||
clickstream.push(NEW AIAction(card));
|
clickstream.push(NEW AIAction(this, card));
|
||||||
chosenCard = card;
|
chosenCard = card;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -209,7 +209,7 @@ int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potenti
|
|||||||
case TARGET_PLAYER:
|
case TARGET_PLAYER:
|
||||||
{
|
{
|
||||||
Player * player = ((Player *) potentialTargets[i]);
|
Player * player = ((Player *) potentialTargets[i]);
|
||||||
clickstream.push(NEW AIAction(player));
|
clickstream.push(NEW AIAction(this, player));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+312
-302
@@ -9,12 +9,58 @@
|
|||||||
#include "AIHints.h"
|
#include "AIHints.h"
|
||||||
#include "ManaCostHybrid.h"
|
#include "ManaCostHybrid.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// AIAction
|
// AIAction
|
||||||
//
|
//
|
||||||
|
|
||||||
// In this function, target represents the target of the currentAIAction object, while _target is the target of the ability of this AIAction object
|
|
||||||
|
Player * OrderedAIAction::getPlayerTarget()
|
||||||
|
{
|
||||||
|
if (playerAbilityTarget)
|
||||||
|
return (Player *)playerAbilityTarget;
|
||||||
|
|
||||||
|
if (target && target->typeAsTarget() == TARGET_PLAYER)
|
||||||
|
return (Player *)target;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int OrderedAIAction::getEfficiency(AADamager * aad)
|
||||||
|
{
|
||||||
|
Player * playerTarget = getPlayerTarget();
|
||||||
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
|
Player * p = g->currentlyActing();
|
||||||
|
|
||||||
|
MTGCardInstance * dTarget = target ? target : dynamic_cast<MTGCardInstance *>(aad->getTarget());
|
||||||
|
|
||||||
|
if(!target && !playerTarget && dTarget)
|
||||||
|
{
|
||||||
|
//no action target, but damage has a target...this is most likely a card like pestilence.
|
||||||
|
return int(p->opponent()->game->battlefield->countByType("creature") - p->game->battlefield->countByType("creature")) * 25 % 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(playerTarget)
|
||||||
|
{
|
||||||
|
TargetChooser * checkT = g->getCurrentTargetChooser();
|
||||||
|
int otherTargets = checkT ? checkT->countValidTargets() : 0;
|
||||||
|
if (playerTarget == p->opponent())
|
||||||
|
return 90 - otherTargets;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p == target->controller())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (aad->getDamage() >= dTarget->toughness)
|
||||||
|
return 100;
|
||||||
|
|
||||||
|
if (dTarget->toughness)
|
||||||
|
return (50 * aad->getDamage()) / dTarget->toughness;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In this function, target represents the target of the currentAIAction object, while coreAbilityCardTarget is the target of the ability of this AIAction object
|
||||||
// I can't remember as I type this in which condition we use one or the other for this function, if you find out please replace this comment
|
// I can't remember as I type this in which condition we use one or the other for this function, if you find out please replace this comment
|
||||||
int OrderedAIAction::getEfficiency()
|
int OrderedAIAction::getEfficiency()
|
||||||
{
|
{
|
||||||
@@ -24,6 +70,8 @@ int OrderedAIAction::getEfficiency()
|
|||||||
return 0;
|
return 0;
|
||||||
GameObserver * g = GameObserver::GetInstance();
|
GameObserver * g = GameObserver::GetInstance();
|
||||||
ActionStack * s = g->mLayers->stackLayer();
|
ActionStack * s = g->mLayers->stackLayer();
|
||||||
|
int currentPhase = g->getCurrentGamePhase();
|
||||||
|
|
||||||
Player * p = g->currentlyActing();
|
Player * p = g->currentlyActing();
|
||||||
if (s->has(ability))
|
if (s->has(ability))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -34,97 +82,61 @@ int OrderedAIAction::getEfficiency()
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((AIPlayerBaka *) p)->canHandleCost(ability))
|
if (!((AIPlayerBaka *)owner)->canHandleCost(ability))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
MTGCardInstance * coreAbilityCardTarget = dynamic_cast<MTGCardInstance *>(a->target);
|
||||||
|
|
||||||
|
//CoreAbility shouldn't return a Lord, but it does.
|
||||||
|
//When we don't have a target for a lord action, we assume it's the lord itself
|
||||||
|
if (!target && dynamic_cast<ALord*> (a))
|
||||||
|
{
|
||||||
|
target = a->source;
|
||||||
|
}
|
||||||
|
|
||||||
switch (a->aType)
|
switch (a->aType)
|
||||||
{
|
{
|
||||||
case MTGAbility::DAMAGER:
|
case MTGAbility::DAMAGER:
|
||||||
{
|
|
||||||
AADamager * aad = (AADamager *) a;
|
|
||||||
MTGCardInstance * dTarget = (MTGCardInstance*)target;
|
|
||||||
if(!target && !playerAbilityTarget)
|
|
||||||
{
|
{
|
||||||
dTarget = (MTGCardInstance*)aad->getTarget();
|
efficiency = getEfficiency ((AADamager *) a);
|
||||||
if(dTarget)//no action target, but damage has a target...this is most likely a card like pestilence.
|
|
||||||
{
|
|
||||||
efficiency = int(p->opponent()->game->battlefield->countByType("creature") - p->game->battlefield->countByType("creature")) * 25 % 100;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(playerAbilityTarget || (target && target->typeAsTarget() == TARGET_PLAYER))
|
|
||||||
{
|
|
||||||
TargetChooser * checkT = g->getCurrentTargetChooser();
|
|
||||||
int otherTargets = 0;
|
|
||||||
if(checkT) otherTargets = checkT->countValidTargets();
|
|
||||||
if (playerAbilityTarget == p->opponent()||(target && (Player*)target == p->opponent()))
|
|
||||||
efficiency = 90 - otherTargets;
|
|
||||||
else
|
|
||||||
efficiency = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(p == target->controller())
|
|
||||||
{
|
|
||||||
efficiency = 0;
|
|
||||||
}
|
|
||||||
else if (aad->getDamage() >= dTarget->toughness)
|
|
||||||
{
|
|
||||||
efficiency = 100;
|
|
||||||
}
|
|
||||||
else if (dTarget->toughness)
|
|
||||||
{
|
|
||||||
efficiency = (50 * aad->getDamage()) / dTarget->toughness;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
efficiency = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::STANDARD_REGENERATE:
|
case MTGAbility::STANDARD_REGENERATE:
|
||||||
{
|
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
|
||||||
efficiency = 0;
|
|
||||||
if (!_target)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!_target->regenerateTokens && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS
|
|
||||||
&& (_target->defenser || _target->blockers.size())
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
efficiency = 95;
|
efficiency = 0;
|
||||||
|
if (!coreAbilityCardTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!coreAbilityCardTarget->regenerateTokens && currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS
|
||||||
|
&& (coreAbilityCardTarget->defenser || coreAbilityCardTarget->blockers.size())
|
||||||
|
)
|
||||||
|
{
|
||||||
|
efficiency = 95;
|
||||||
|
}
|
||||||
|
//TODO If the card is the target of a damage spell
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//TODO If the card is the target of a damage spell
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::STANDARD_PREVENT:
|
case MTGAbility::STANDARD_PREVENT:
|
||||||
{
|
{
|
||||||
efficiency = 0;//starts out low to avoid spamming it when its not needed.
|
efficiency = 0;//starts out low to avoid spamming it when its not needed.
|
||||||
if (!target && !dynamic_cast<ALord*> (a))
|
|
||||||
|
if (!target)
|
||||||
break;
|
break;
|
||||||
if(dynamic_cast<ALord*> (a) && !target)
|
|
||||||
{
|
|
||||||
//this is a special case for all(this) targetting workaround.
|
|
||||||
//adding a direct method for targetting the source is planned for
|
|
||||||
//the coming releases, all(this) workaround prevents eff from being returned
|
|
||||||
//as its not targetted the same as abilities
|
|
||||||
//for now this dirty hack will calculate eff on lords as tho the source is
|
|
||||||
//the target...otherwise these abilities will never be used.
|
|
||||||
target = a->source;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NeedPreventing;
|
bool NeedPreventing;
|
||||||
NeedPreventing = false;
|
NeedPreventing = false;
|
||||||
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBLOCKERS)
|
if (currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS)
|
||||||
{
|
{
|
||||||
if(target->getNextOpponent() && !target->getNextOpponent()->typeAsTarget() == TARGET_CARD)
|
MTGCardInstance * nextOpponent = target->getNextOpponent();
|
||||||
|
if(!nextOpponent)
|
||||||
break;
|
break;
|
||||||
if ((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power)
|
if ((target->defenser || target->blockers.size()) && target->preventable < nextOpponent->power)
|
||||||
NeedPreventing = true;
|
NeedPreventing = true;
|
||||||
if (p == target->controller() && target->controller()->isAI() && NeedPreventing && !(target->getNextOpponent()->has(Constants::DEATHTOUCH)
|
if (p == target->controller() && target->controller()->isAI() && NeedPreventing && !(nextOpponent->has(Constants::DEATHTOUCH)
|
||||||
|| target->getNextOpponent()->has(Constants::WITHER)))
|
||nextOpponent->has(Constants::WITHER)))
|
||||||
{
|
{
|
||||||
efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved"..
|
efficiency = 20 * (target->DangerRanking());//increase this chance to be used in combat if the creature blocking/blocked could kill the creature this chance is taking into consideration how good the creature is, best creature will always be the first "saved"..
|
||||||
if (target->toughness == 1 && target->getNextOpponent()->power == 1)
|
if (target->toughness == 1 && nextOpponent->power == 1)
|
||||||
efficiency += 15;
|
efficiency += 15;
|
||||||
//small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence.
|
//small bonus added for the poor 1/1s, if we can save them, we will unless something else took precidence.
|
||||||
//note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste.
|
//note is the target is being blocked or blocking a creature with wither or deathtouch, it is not even considered for preventing as it is a waste.
|
||||||
@@ -133,7 +145,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
int damages = 0;
|
int damages = 0;
|
||||||
if((target->defenser || target->blockers.size()) && target->controller() == p)
|
if((target->defenser || target->blockers.size()) && target->controller() == p)
|
||||||
{
|
{
|
||||||
damages = target->getNextOpponent()->power;
|
damages = nextOpponent->power;
|
||||||
calculateAfterDamage = int(target->toughness - damages);
|
calculateAfterDamage = int(target->toughness - damages);
|
||||||
if((calculateAfterDamage + target->preventable) > 0)
|
if((calculateAfterDamage + target->preventable) > 0)
|
||||||
{
|
{
|
||||||
@@ -154,10 +166,10 @@ int OrderedAIAction::getEfficiency()
|
|||||||
if (!target)
|
if (!target)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int equips = p->game->battlefield->countByType("Equipment");
|
unsigned int equips = p->game->battlefield->countByType("Equipment");
|
||||||
int myArmy = p->game->battlefield->countByType("Creature");
|
unsigned int myArmy = p->game->battlefield->countByType("Creature");
|
||||||
// when can this ever be negative?
|
// when can this ever be negative?
|
||||||
int equilized = myArmy ? abs(equips / myArmy) : 0;
|
int equalized = myArmy ? equips / myArmy : 0;
|
||||||
|
|
||||||
if (p == target->controller() && target->equipment <= 1 && !a->source->target)
|
if (p == target->controller() && target->equipment <= 1 && !a->source->target)
|
||||||
{
|
{
|
||||||
@@ -168,7 +180,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures.
|
efficiency += 10; //small bonus to encourage equipping nontoken 1/1 creatures.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == target->controller() && !a->source->target && target->equipment < equilized)
|
if (p == target->controller() && !a->source->target && target->equipment < equalized)
|
||||||
{
|
{
|
||||||
efficiency = 15 * (target->DangerRanking());
|
efficiency = 15 * (target->DangerRanking());
|
||||||
efficiency -= 5 * (target->equipment);
|
efficiency -= 5 * (target->equipment);
|
||||||
@@ -177,82 +189,80 @@ int OrderedAIAction::getEfficiency()
|
|||||||
}
|
}
|
||||||
case MTGAbility::STANDARD_LEVELUP:
|
case MTGAbility::STANDARD_LEVELUP:
|
||||||
{
|
{
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
Counter * targetCounter = NULL;
|
Counter * targetCounter = NULL;
|
||||||
int currentlevel = 0;
|
int currentlevel = 0;
|
||||||
|
|
||||||
if (_target)
|
if (!coreAbilityCardTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (coreAbilityCardTarget->counters && coreAbilityCardTarget->counters->hasCounter("level", 0, 0))
|
||||||
{
|
{
|
||||||
if (_target->counters && _target->counters->hasCounter("level", 0, 0))
|
targetCounter = coreAbilityCardTarget->counters->hasCounter("level", 0, 0);
|
||||||
|
currentlevel = targetCounter->nb;
|
||||||
|
}
|
||||||
|
if (currentlevel < coreAbilityCardTarget->MaxLevelUp)
|
||||||
|
{
|
||||||
|
efficiency = 85;
|
||||||
|
//increase the efficeincy of leveling up by a small amount equal to current level.
|
||||||
|
efficiency += currentlevel;
|
||||||
|
|
||||||
|
if (p->game->hand->nb_cards > 0 && p->isAI())
|
||||||
{
|
{
|
||||||
targetCounter = _target->counters->hasCounter("level", 0, 0);
|
efficiency -= (10 * p->game->hand->nb_cards);//reduce the eff if by 10 times the amount of cards in Ais hand.
|
||||||
currentlevel = targetCounter->nb;
|
//it should always try playing more cards before deciding
|
||||||
}
|
}
|
||||||
if (currentlevel < _target->MaxLevelUp)
|
|
||||||
|
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN)
|
||||||
{
|
{
|
||||||
efficiency = 85;
|
efficiency = 100;
|
||||||
//increase the efficeincy of leveling up by a small amount equal to current level.
|
//in 2nd main, go all out and try to max stuff.
|
||||||
efficiency += currentlevel;
|
|
||||||
|
|
||||||
if (p->game->hand->nb_cards > 0 && p->isAI())
|
|
||||||
{
|
|
||||||
efficiency -= (10 * p->game->hand->nb_cards);//reduce the eff if by 10 times the amount of cards in Ais hand.
|
|
||||||
//it should always try playing more cards before deciding
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN)
|
|
||||||
{
|
|
||||||
efficiency = 100;
|
|
||||||
//in 2nd main, go all out and try to max stuff.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MTGAbility::COUNTERS:
|
case MTGAbility::COUNTERS:
|
||||||
{
|
{
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
MTGCardInstance * _target = target ? target : coreAbilityCardTarget;
|
||||||
if(!_target)
|
|
||||||
_target = (MTGCardInstance *) (a->target);
|
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
|
|
||||||
|
if (!_target)
|
||||||
|
break;
|
||||||
|
|
||||||
if(AACounter * cc = dynamic_cast<AACounter*> (a))
|
if(AACounter * cc = dynamic_cast<AACounter*> (a))
|
||||||
{
|
{
|
||||||
if(cc && _target)
|
if(_target->controller() == p && cc->toughness>=0)
|
||||||
{
|
{
|
||||||
if(_target->controller() == p && cc->toughness>=0)
|
efficiency = 90;
|
||||||
{
|
|
||||||
efficiency = 90;
|
|
||||||
|
|
||||||
}
|
|
||||||
if(_target->controller() != p && ((_target->toughness + cc->toughness <= 0 && _target->toughness) || (cc->toughness < 0 && cc->power < 0)))
|
|
||||||
{
|
|
||||||
efficiency = 90;
|
|
||||||
|
|
||||||
}
|
|
||||||
if(_target->counters && _target->counters->hasCounter(cc->power,cc->toughness) && _target->counters->hasCounter(cc->power,cc->toughness)->nb > 15)
|
|
||||||
{
|
|
||||||
efficiency = _target->counters->hasCounter(cc->power,cc->toughness)->nb;
|
|
||||||
}
|
|
||||||
if(cc->maxNb && _target->counters && _target->counters->hasCounter(cc->power,cc->toughness)->nb >= cc->maxNb)
|
|
||||||
efficiency = 0;
|
|
||||||
if(a->target == a->source && a->getCost() && a->getCost()->hasX())
|
|
||||||
efficiency -= 10 * int(p->game->hand->cards.size());
|
|
||||||
}
|
}
|
||||||
|
if(_target->controller() != p && ((_target->toughness + cc->toughness <= 0 && _target->toughness) || (cc->toughness < 0 && cc->power < 0)))
|
||||||
|
{
|
||||||
|
efficiency = 90;
|
||||||
|
|
||||||
|
}
|
||||||
|
if(_target->counters && _target->counters->hasCounter(cc->power,cc->toughness) && _target->counters->hasCounter(cc->power,cc->toughness)->nb > 15)
|
||||||
|
{
|
||||||
|
efficiency = _target->counters->hasCounter(cc->power,cc->toughness)->nb;
|
||||||
|
}
|
||||||
|
if(cc->maxNb && _target->counters && _target->counters->hasCounter(cc->power,cc->toughness)->nb >= cc->maxNb)
|
||||||
|
efficiency = 0;
|
||||||
|
if(a->target == a->source && a->getCost() && a->getCost()->hasX())
|
||||||
|
efficiency -= 10 * int(p->game->hand->cards.size());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MTGAbility::STANDARD_PUMP:
|
case MTGAbility::STANDARD_PUMP:
|
||||||
{
|
{
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
if(!_target)
|
if(!coreAbilityCardTarget)
|
||||||
break;
|
break;
|
||||||
if(!target && !dynamic_cast<ALord*> (a) && (((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_AURA) || ((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_EQUIPMENT)))
|
if(!target && !dynamic_cast<ALord*> (a) && (((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_AURA) || ((MTGCardInstance *)a->source)->hasSubtype(Subtypes::TYPE_EQUIPMENT)))
|
||||||
{
|
{
|
||||||
if(((MTGCardInstance *)a->source)->target)
|
if(a->source->target)
|
||||||
_target = ((MTGCardInstance *)a->source)->target;
|
coreAbilityCardTarget = a->source->target; //TODO use intermediate value?
|
||||||
target = (MTGCardInstance *)a->source;
|
target = a->source;
|
||||||
}
|
}
|
||||||
if (!target && !dynamic_cast<ALord*> (a))
|
if (!target && !dynamic_cast<ALord*> (a))
|
||||||
break;
|
break;
|
||||||
@@ -260,76 +270,78 @@ int OrderedAIAction::getEfficiency()
|
|||||||
{
|
{
|
||||||
target = a->source;
|
target = a->source;
|
||||||
}
|
}
|
||||||
AbilityFactory af;
|
|
||||||
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
|
||||||
//i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does.
|
|
||||||
int currentPhase = g->getCurrentGamePhase();
|
|
||||||
if ((currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS) || (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS))
|
|
||||||
{
|
|
||||||
if (suggestion == BAKA_EFFECT_GOOD && target->controller() == p)
|
|
||||||
{
|
|
||||||
if(_target->defenser || _target->blockers.size())
|
|
||||||
{
|
|
||||||
MTGCardInstance * opponent = _target->getNextOpponent();
|
|
||||||
if (!opponent)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (_target->power < opponent->toughness ||( _target->toughness < opponent->power) || (_target->has(Constants::TRAMPLE)))
|
AbilityFactory af;
|
||||||
|
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
||||||
|
//i do not set a starting eff. on this ability, this allows Ai to sometimes randomly do it as it normally does.
|
||||||
|
int currentPhase = g->getCurrentGamePhase();
|
||||||
|
if ((currentPhase == Constants::MTG_PHASE_COMBATBLOCKERS) || (currentPhase == Constants::MTG_PHASE_COMBATATTACKERS))
|
||||||
|
{
|
||||||
|
if (suggestion == BAKA_EFFECT_GOOD && target->controller() == p)
|
||||||
|
{
|
||||||
|
if(coreAbilityCardTarget->defenser || coreAbilityCardTarget->blockers.size())
|
||||||
{
|
{
|
||||||
//this pump is based on a start eff. of 20 multiplied by how good the creature is.
|
MTGCardInstance * opponent = coreAbilityCardTarget->getNextOpponent();
|
||||||
efficiency = 20 * _target->DangerRanking();
|
if (!opponent)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (coreAbilityCardTarget->power < opponent->toughness ||( coreAbilityCardTarget->toughness < opponent->power) || (coreAbilityCardTarget->has(Constants::TRAMPLE)))
|
||||||
|
{
|
||||||
|
//this pump is based on a start eff. of 20 multiplied by how good the creature is.
|
||||||
|
efficiency = 20 * coreAbilityCardTarget->DangerRanking();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (coreAbilityCardTarget->isAttacker() && !coreAbilityCardTarget->blockers.size())
|
||||||
|
{
|
||||||
|
//this means im heading directly for the player, pump this creature as much as possible.
|
||||||
|
efficiency = 100;
|
||||||
|
if(coreAbilityCardTarget->power > 50)
|
||||||
|
efficiency -= coreAbilityCardTarget->power;//we don't need to go overboard. better to not put all your eggs in a single basket.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_target->isAttacker() && !_target->blockers.size())
|
|
||||||
{
|
|
||||||
//this means im heading directly for the player, pump this creature as much as possible.
|
|
||||||
efficiency = 100;
|
|
||||||
if(_target->power > 50)
|
|
||||||
efficiency -= _target->power;//we don't need to go overboard. better to not put all your eggs in a single basket.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (suggestion == BAKA_EFFECT_BAD && target->controller() != p && target->toughness > 0)
|
||||||
|
{
|
||||||
|
efficiency = 100;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (suggestion == BAKA_EFFECT_BAD && target->controller() != p && target->toughness > 0)
|
|
||||||
{
|
|
||||||
efficiency = 100;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::STANDARD_BECOMES:
|
case MTGAbility::STANDARD_BECOMES:
|
||||||
{
|
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
|
||||||
//nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat.
|
|
||||||
if (_target && !_target->isCreature() && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN)
|
|
||||||
{
|
{
|
||||||
efficiency = 100;
|
if(!coreAbilityCardTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat.
|
||||||
|
if (coreAbilityCardTarget && !coreAbilityCardTarget->isCreature() && currentPhase == Constants::MTG_PHASE_FIRSTMAIN)
|
||||||
|
{
|
||||||
|
efficiency = 100;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::FOREACH:
|
|
||||||
case MTGAbility::MANA_PRODUCER://only way to hit this condition is nested manaabilities, ai skips manaproducers by defualt when finding an ability to use.
|
case MTGAbility::MANA_PRODUCER://only way to hit this condition is nested manaabilities, ai skips manaproducers by defualt when finding an ability to use.
|
||||||
{
|
{
|
||||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
|
||||||
MTGAbility * a = AbilityFactory::getCoreAbility(ability);
|
|
||||||
AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
|
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
|
|
||||||
|
if(!coreAbilityCardTarget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
|
||||||
|
|
||||||
//trying to encourage Ai to use his foreach manaproducers in first main
|
//trying to encourage Ai to use his foreach manaproducers in first main
|
||||||
if (amp && amp->output && amp->output->getConvertedCost() && (g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN
|
if (amp && amp->output && amp->output->getConvertedCost() && (g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN
|
||||||
|| g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN) && _target->controller()->game->hand->nb_cards > 0)
|
|| g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN) && coreAbilityCardTarget->controller()->game->hand->nb_cards > 0)
|
||||||
{
|
{
|
||||||
efficiency = 0;
|
|
||||||
for (int i = Constants::MTG_NB_COLORS - 1; i > 0; i--)
|
for (int i = Constants::MTG_NB_COLORS - 1; i > 0; i--)
|
||||||
{
|
{
|
||||||
if ((p->game->hand->hasColor(i) || p->game->hand->hasColor(0))
|
if ((p->game->hand->hasColor(i) || p->game->hand->hasColor(0))
|
||||||
&& amp->output->hasColor(i))
|
&& amp->output->hasColor(i))
|
||||||
{
|
{
|
||||||
|
|
||||||
efficiency = 100;
|
efficiency = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amp->getCost() && amp->getCost()->getConvertedCost() && p->game->hand->hasX())
|
if (amp->getCost() && amp->getCost()->getConvertedCost() && p->game->hand->hasX())
|
||||||
efficiency = 100;
|
efficiency = 100;
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -356,150 +368,144 @@ int OrderedAIAction::getEfficiency()
|
|||||||
case MTGAbility::STANDARDABILITYGRANT:
|
case MTGAbility::STANDARDABILITYGRANT:
|
||||||
{
|
{
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
MTGCardInstance * _target = (MTGCardInstance*)(a->target);
|
|
||||||
if(!_target)
|
if (!target)
|
||||||
break;
|
break;
|
||||||
if (!target && !dynamic_cast<ALord*> (a))
|
|
||||||
break;
|
|
||||||
if(dynamic_cast<ALord*> (a) && !target)
|
|
||||||
{
|
|
||||||
target = a->source;
|
|
||||||
}
|
|
||||||
|
|
||||||
//ensuring that Ai grants abilities to creatures during first main, so it can actually use them in combat.
|
//ensuring that Ai grants abilities to creatures during first main, so it can actually use them in combat.
|
||||||
//quick note: the eff is multiplied by creatures ranking then divided by the number of cards in hand.
|
//quick note: the eff is multiplied by creatures ranking then divided by the number of cards in hand.
|
||||||
//the reason i do this is to encourage more casting and less waste of mana on abilities.
|
//the reason i do this is to encourage more casting and less waste of mana on abilities.
|
||||||
AbilityFactory af;
|
AbilityFactory af;
|
||||||
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
||||||
|
|
||||||
int efficiencyModifier = (25 * target->DangerRanking());
|
int efficiencyModifier = (25 * target->DangerRanking());
|
||||||
if (p->game->hand->nb_cards > 1)
|
if (p->game->hand->nb_cards > 1)
|
||||||
{
|
{
|
||||||
efficiencyModifier -= p->game->hand->nb_cards*3;
|
efficiencyModifier -= p->game->hand->nb_cards*3;
|
||||||
}
|
}
|
||||||
if (suggestion == BAKA_EFFECT_BAD && p != target->controller() && !target->has(a->abilitygranted))
|
if (suggestion == BAKA_EFFECT_BAD && p != target->controller() && !target->has(a->abilitygranted))
|
||||||
{
|
{
|
||||||
efficiency += efficiencyModifier;
|
efficiency += efficiencyModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN
|
if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN
|
||||||
&& p == target->controller()
|
&& p == target->controller()
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
efficiency += efficiencyModifier;
|
efficiency += efficiencyModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suggestion == BAKA_EFFECT_GOOD && target->has(a->abilitygranted))
|
if (suggestion == BAKA_EFFECT_GOOD && target->has(a->abilitygranted))
|
||||||
{
|
{
|
||||||
//trying to avoid Ai giving ie:flying creatures ie:flying twice.
|
//trying to avoid Ai giving ie:flying creatures ie:flying twice.
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
|
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
|
||||||
|| (suggestion == BAKA_EFFECT_GOOD && p != target->controller())
|
|| (suggestion == BAKA_EFFECT_GOOD && p != target->controller())
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
//stop giving trample to the players creatures.
|
//stop giving trample to the players creatures.
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MTGAbility::UNTAPPER:
|
case MTGAbility::UNTAPPER:
|
||||||
//untap things that Ai owns and are tapped.
|
//untap things that Ai owns and are tapped.
|
||||||
{
|
{
|
||||||
efficiency = 0;
|
efficiency = 0;
|
||||||
if (!target && !dynamic_cast<ALord*> (a))
|
if (!target)
|
||||||
break;
|
break;
|
||||||
if(dynamic_cast<ALord*> (a) && !target)
|
|
||||||
{
|
|
||||||
target = a->source;
|
|
||||||
}
|
|
||||||
if (target->isTapped() && target->controller() == p)
|
if (target->isTapped() && target->controller() == p)
|
||||||
{
|
{
|
||||||
target->isCreature()?efficiency = (20 * target->DangerRanking()):efficiency = 100;
|
efficiency = target->isCreature()? (20 * target->DangerRanking()) : 100;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case MTGAbility::TAPPER:
|
case MTGAbility::TAPPER:
|
||||||
//tap things the player owns and that are untapped.
|
//tap things the player owns and that are untapped.
|
||||||
{
|
{
|
||||||
if (!target && !dynamic_cast<ALord*> (a))
|
if (!target)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (target->controller() != p)
|
||||||
|
efficiency = (20 * target->DangerRanking());
|
||||||
|
|
||||||
|
if (target->isTapped())
|
||||||
|
efficiency = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
if(dynamic_cast<ALord*> (a) && !target)
|
}
|
||||||
{
|
|
||||||
target = a->source;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target->controller() != p)
|
|
||||||
efficiency = (20 * target->DangerRanking());
|
|
||||||
|
|
||||||
if (target->isTapped())
|
|
||||||
efficiency = 0;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case MTGAbility::LIFER:
|
case MTGAbility::LIFER:
|
||||||
{
|
|
||||||
//use life abilities whenever possible.
|
|
||||||
AALifer * alife = (AALifer *) a;
|
|
||||||
Targetable * _t = alife->getTarget();
|
|
||||||
|
|
||||||
efficiency = 100;
|
|
||||||
AbilityFactory af;
|
|
||||||
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
|
||||||
|
|
||||||
if ((suggestion == BAKA_EFFECT_BAD && _t == p) || (suggestion == BAKA_EFFECT_GOOD && _t != p))
|
|
||||||
{
|
{
|
||||||
efficiency = 0;
|
//use life abilities whenever possible.
|
||||||
}
|
AALifer * alife = (AALifer *) a;
|
||||||
|
Targetable * _t = alife->getTarget();
|
||||||
|
|
||||||
break;
|
efficiency = 100;
|
||||||
}
|
AbilityFactory af;
|
||||||
|
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
||||||
|
|
||||||
|
if ((suggestion == BAKA_EFFECT_BAD && _t == p) || (suggestion == BAKA_EFFECT_GOOD && _t != p))
|
||||||
|
{
|
||||||
|
efficiency = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MTGAbility::STANDARD_DRAW:
|
case MTGAbility::STANDARD_DRAW:
|
||||||
{
|
|
||||||
AADrawer * drawer = (AADrawer *)a;
|
|
||||||
//adding this case since i played a few games where Ai litterally decided to mill himself to death. fastest and easiest win ever.
|
|
||||||
//this should help a little, tho ultimately it will be decided later what the best course of action is.
|
|
||||||
//eff of drawing ability is calculated by base 20 + the amount of cards in library minus the amount of cards in hand times 7.
|
|
||||||
//drawing is never going to return a hundred eff because later eff is multiplied by 1.3 if no cards in hand.
|
|
||||||
efficiency = int(20 + p->game->library->nb_cards) - int(p->game->hand->nb_cards * 7);
|
|
||||||
if (p->game->hand->nb_cards > 8)//reduce by 50 if cards in hand are over 8, high chance ai cant play them.
|
|
||||||
{
|
{
|
||||||
efficiency -= 70;
|
AADrawer * drawer = (AADrawer *)a;
|
||||||
|
//adding this case since i played a few games where Ai litterally decided to mill himself to death. fastest and easiest win ever.
|
||||||
|
//this should help a little, tho ultimately it will be decided later what the best course of action is.
|
||||||
|
//eff of drawing ability is calculated by base 20 + the amount of cards in library minus the amount of cards in hand times 7.
|
||||||
|
//drawing is never going to return a hundred eff because later eff is multiplied by 1.3 if no cards in hand.
|
||||||
|
efficiency = int(20 + p->game->library->nb_cards) - int(p->game->hand->nb_cards * 7);
|
||||||
|
if (p->game->hand->nb_cards > 8)//reduce by 50 if cards in hand are over 8, high chance ai cant play them.
|
||||||
|
{
|
||||||
|
efficiency -= 70;
|
||||||
|
}
|
||||||
|
if ((drawer->getNumCards() >= p->game->library->nb_cards && (Targetable*)p == drawer->getTarget()) || (p->game->hand->nb_cards > 10 && (Targetable*)p == drawer->getTarget()))
|
||||||
|
{
|
||||||
|
//if the amount im drawing will mill me to death or i have more then 10 cards in hand, eff is 0;
|
||||||
|
efficiency = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if ((drawer->getNumCards() >= p->game->library->nb_cards && (Targetable*)p == drawer->getTarget()) || (p->game->hand->nb_cards > 10 && (Targetable*)p == drawer->getTarget()))
|
|
||||||
{
|
|
||||||
//if the amount im drawing will mill me to death or i have more then 10 cards in hand, eff is 0;
|
|
||||||
efficiency = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::CLONING:
|
case MTGAbility::CLONING:
|
||||||
{
|
|
||||||
efficiency = 0;
|
|
||||||
if(!target)
|
|
||||||
efficiency = 100;//a clone ability with no target is an "clone all("
|
|
||||||
else if (p == target->controller())
|
|
||||||
{
|
{
|
||||||
efficiency = 20 * target->DangerRanking();
|
efficiency = 0;
|
||||||
|
if(!target)
|
||||||
|
efficiency = 100;//a clone ability with no target is an "clone all("
|
||||||
|
else if (p == target->controller())
|
||||||
|
{
|
||||||
|
efficiency = 20 * target->DangerRanking();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MTGAbility::STANDARD_FIZZLER:
|
case MTGAbility::STANDARD_FIZZLER:
|
||||||
{
|
{
|
||||||
if(target)
|
efficiency = 0;
|
||||||
{
|
|
||||||
Interruptible * action = g->mLayers->stackLayer()->getAt(-1);
|
if(!target)
|
||||||
Spell * spell = (Spell *) action;
|
break;
|
||||||
Player * lastStackActionController = NULL;
|
|
||||||
if(spell && spell->type == ACTION_SPELL)
|
Interruptible * action = g->mLayers->stackLayer()->getAt(-1);
|
||||||
lastStackActionController = spell->source->controller();
|
if (!action)
|
||||||
if(p != target->controller() && lastStackActionController && lastStackActionController != p)
|
break;
|
||||||
efficiency = 60;//we want ai to fizzle at higher than "unknown" ability %.
|
|
||||||
}
|
Spell * spell = dynamic_cast<Spell *>(action);
|
||||||
|
if (!spell)
|
||||||
|
break;
|
||||||
|
|
||||||
|
Player * lastStackActionController = spell->source->controller();
|
||||||
|
if(p != target->controller() && lastStackActionController != p)
|
||||||
|
efficiency = 60;//we want ai to fizzle at higher than "unknown" ability %.
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -557,7 +563,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
efficiency = 100;
|
efficiency = 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AAMover * aam = dynamic_cast<AAMover *>(a))
|
else if (AAMover * aam = dynamic_cast<AAMover *>(a))
|
||||||
{
|
{
|
||||||
MTGGameZone * z = aam->destinationZone(target);
|
MTGGameZone * z = aam->destinationZone(target);
|
||||||
if (target)
|
if (target)
|
||||||
@@ -578,7 +584,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AAProliferate * aap = dynamic_cast<AAProliferate *>(a))
|
else if (AAProliferate * aap = dynamic_cast<AAProliferate *>(a))
|
||||||
{
|
{
|
||||||
if (aap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p)
|
if (aap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p)
|
||||||
{
|
{
|
||||||
@@ -587,14 +593,14 @@ int OrderedAIAction::getEfficiency()
|
|||||||
else if (aap)
|
else if (aap)
|
||||||
efficiency = 90;
|
efficiency = 90;
|
||||||
}
|
}
|
||||||
if (AAAlterPoison * aaap = dynamic_cast<AAAlterPoison *>(a))
|
else if (AAAlterPoison * aaap = dynamic_cast<AAAlterPoison *>(a))
|
||||||
{
|
{
|
||||||
if (aaap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p)
|
if (aaap && target && target->typeAsTarget() == TARGET_PLAYER && (Player*)target != p)
|
||||||
{
|
{
|
||||||
efficiency = 90;
|
efficiency = 90;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
|
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
|
||||||
{
|
{
|
||||||
efficiency = 80;
|
efficiency = 80;
|
||||||
if(atc && atc->name.length() && atc->sabilities.length() && atc->types.size() && p->game->inPlay->findByName(atc->name))
|
if(atc && atc->name.length() && atc->sabilities.length() && atc->types.size() && p->game->inPlay->findByName(atc->name))
|
||||||
@@ -607,6 +613,9 @@ int OrderedAIAction::getEfficiency()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//At this point the "basic" efficiency is computed, we further tweak it depending on general decisions, independent of theAbility type
|
||||||
|
|
||||||
MayAbility * may = dynamic_cast<MayAbility*>(ability);
|
MayAbility * may = dynamic_cast<MayAbility*>(ability);
|
||||||
if (!efficiency && may)
|
if (!efficiency && may)
|
||||||
{
|
{
|
||||||
@@ -633,6 +642,7 @@ int OrderedAIAction::getEfficiency()
|
|||||||
//Decrease chance of using ability if there is an extra cost to use the ability, ignore tap
|
//Decrease chance of using ability if there is an extra cost to use the ability, ignore tap
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return efficiency;
|
return efficiency;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,13 +699,13 @@ bool AIPlayerBaka::payTheManaCost(ManaCost * cost, MTGCardInstance * target,vect
|
|||||||
{
|
{
|
||||||
if ( AManaProducer * amp = dynamic_cast<AManaProducer*> (gotPayments[k]))
|
if ( AManaProducer * amp = dynamic_cast<AManaProducer*> (gotPayments[k]))
|
||||||
{
|
{
|
||||||
AIAction * action = NEW AIAction(amp,amp->source);
|
AIAction * action = NEW AIAction(this, amp,amp->source);
|
||||||
clicks.push_back(action);
|
clicks.push_back(action);
|
||||||
paid->add(amp->output);
|
paid->add(amp->output);
|
||||||
}
|
}
|
||||||
else if(GenericActivatedAbility * gmp = dynamic_cast<GenericActivatedAbility*>(gotPayments[k]))
|
else if(GenericActivatedAbility * gmp = dynamic_cast<GenericActivatedAbility*>(gotPayments[k]))
|
||||||
{
|
{
|
||||||
AIAction * action = NEW AIAction(gmp,gmp->source);
|
AIAction * action = NEW AIAction(this, gmp,gmp->source);
|
||||||
clicks.push_back(action);
|
clicks.push_back(action);
|
||||||
if(AForeach * fmp = dynamic_cast<AForeach*>(gmp->ability))
|
if(AForeach * fmp = dynamic_cast<AForeach*>(gmp->ability))
|
||||||
{
|
{
|
||||||
@@ -775,7 +785,7 @@ bool AIPlayerBaka::payTheManaCost(ManaCost * cost, MTGCardInstance * target,vect
|
|||||||
}
|
}
|
||||||
if (doUse)
|
if (doUse)
|
||||||
{
|
{
|
||||||
AIAction * action = NEW AIAction(amp, card);
|
AIAction * action = NEW AIAction(this, amp, card);
|
||||||
clickstream.push(action);
|
clickstream.push(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1139,7 +1149,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
{
|
{
|
||||||
if (!a->getActionTc())
|
if (!a->getActionTc())
|
||||||
{
|
{
|
||||||
OrderedAIAction aiAction(a, c, NULL);
|
OrderedAIAction aiAction(this, a, c, NULL);
|
||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1153,7 +1163,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
{
|
{
|
||||||
if(a->getActionTc()->maxtargets == 1)
|
if(a->getActionTc()->maxtargets == 1)
|
||||||
{
|
{
|
||||||
OrderedAIAction aiAction(a, p, c);
|
OrderedAIAction aiAction(this, a, p, c);
|
||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1169,7 +1179,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
{
|
{
|
||||||
if(a->getActionTc()->maxtargets == 1)
|
if(a->getActionTc()->maxtargets == 1)
|
||||||
{
|
{
|
||||||
OrderedAIAction aiAction(a, c, t);
|
OrderedAIAction aiAction(this, a, c, t);
|
||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1195,16 +1205,16 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
|
|
||||||
MTGCardInstance * targeting = dynamic_cast<MTGCardInstance*>(potentialTargets[0]);
|
MTGCardInstance * targeting = dynamic_cast<MTGCardInstance*>(potentialTargets[0]);
|
||||||
if(targeting && targeting->typeAsTarget() == TARGET_CARD)
|
if(targeting && targeting->typeAsTarget() == TARGET_CARD)
|
||||||
check = NEW OrderedAIAction(a,c,targeting);
|
check = NEW OrderedAIAction(this, a,c,targeting);
|
||||||
|
|
||||||
Player * ptargeting = dynamic_cast<Player*>(potentialTargets[0]);
|
Player * ptargeting = dynamic_cast<Player*>(potentialTargets[0]);
|
||||||
if(ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
if(ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
||||||
check = NEW OrderedAIAction(a,ptargeting,c);
|
check = NEW OrderedAIAction(this, a,ptargeting,c);
|
||||||
|
|
||||||
targetThis = getEfficiency(check);
|
targetThis = getEfficiency(check);
|
||||||
if(targetThis && ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
if(targetThis && ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
||||||
{
|
{
|
||||||
OrderedAIAction aiAction(a,ptargeting,c);
|
OrderedAIAction aiAction(this, a,ptargeting,c);
|
||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
}
|
}
|
||||||
if(targetThis)
|
if(targetThis)
|
||||||
@@ -1214,7 +1224,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
}
|
}
|
||||||
if(!realTargets.size() || (int(realTargets.size()) < a->getActionTc()->maxtargets && a->getActionTc()->targetMin))
|
if(!realTargets.size() || (int(realTargets.size()) < a->getActionTc()->maxtargets && a->getActionTc()->targetMin))
|
||||||
return 0;
|
return 0;
|
||||||
OrderedAIAction aiAction(a, c,realTargets);
|
OrderedAIAction aiAction(this, a, c,realTargets);
|
||||||
aiAction.target = (MTGCardInstance*)realTargets[0];
|
aiAction.target = (MTGCardInstance*)realTargets[0];
|
||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
}
|
}
|
||||||
@@ -1473,7 +1483,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
|||||||
{
|
{
|
||||||
AbilityFactory af;
|
AbilityFactory af;
|
||||||
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,NULL,NULL,tc->source);
|
MTGAbility * withoutGuessing = af.parseMagicLine(tc->belongsToAbility,NULL,NULL,tc->source);
|
||||||
OrderedAIAction * effCheck = NEW OrderedAIAction(withoutGuessing,(MTGCardInstance*)tc->source,card);
|
OrderedAIAction * effCheck = NEW OrderedAIAction(this, withoutGuessing,(MTGCardInstance*)tc->source,card);
|
||||||
if(effCheck->getEfficiency())
|
if(effCheck->getEfficiency())
|
||||||
{
|
{
|
||||||
potentialTargets.push_back(card);
|
potentialTargets.push_back(card);
|
||||||
@@ -1552,11 +1562,11 @@ int AIPlayerBaka::selectMenuOption()
|
|||||||
if(checkEff)
|
if(checkEff)
|
||||||
{
|
{
|
||||||
if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_CARD)
|
if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_CARD)
|
||||||
check = NEW OrderedAIAction(checkEff,checkEff->source,(MTGCardInstance*)checkEff->target);
|
check = NEW OrderedAIAction(this, checkEff,checkEff->source,(MTGCardInstance*)checkEff->target);
|
||||||
else if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_PLAYER)
|
else if(checkEff->target && checkEff->target->typeAsTarget() == TARGET_PLAYER)
|
||||||
check = NEW OrderedAIAction(checkEff,(Player*)checkEff->target,checkEff->source);
|
check = NEW OrderedAIAction(this, checkEff,(Player*)checkEff->target,checkEff->source);
|
||||||
else
|
else
|
||||||
check = NEW OrderedAIAction(checkEff,checkEff->source);
|
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
|
||||||
}
|
}
|
||||||
if(check)
|
if(check)
|
||||||
{
|
{
|
||||||
@@ -1583,11 +1593,11 @@ int AIPlayerBaka::selectMenuOption()
|
|||||||
{
|
{
|
||||||
Targetable * checkTarget = checkEff->target;
|
Targetable * checkTarget = checkEff->target;
|
||||||
if(checkTarget && checkTarget->typeAsTarget() == TARGET_CARD)
|
if(checkTarget && checkTarget->typeAsTarget() == TARGET_CARD)
|
||||||
check = NEW OrderedAIAction(checkEff,checkEff->source,(MTGCardInstance*)checkTarget);
|
check = NEW OrderedAIAction(this, checkEff,checkEff->source,(MTGCardInstance*)checkTarget);
|
||||||
else if(checkTarget && checkTarget->typeAsTarget() == TARGET_PLAYER)
|
else if(checkTarget && checkTarget->typeAsTarget() == TARGET_PLAYER)
|
||||||
check = NEW OrderedAIAction(checkEff,(Player*)checkTarget,checkEff->source);
|
check = NEW OrderedAIAction(this, checkEff,(Player*)checkTarget,checkEff->source);
|
||||||
else
|
else
|
||||||
check = NEW OrderedAIAction(checkEff,checkEff->source);
|
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
|
||||||
}
|
}
|
||||||
if(check)
|
if(check)
|
||||||
{
|
{
|
||||||
@@ -1826,7 +1836,7 @@ int AIPlayerBaka::computeActions()
|
|||||||
{
|
{
|
||||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
||||||
{
|
{
|
||||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||||
clickstream.push(a);
|
clickstream.push(a);
|
||||||
gotPayments.clear();
|
gotPayments.clear();
|
||||||
}
|
}
|
||||||
@@ -1885,7 +1895,7 @@ int AIPlayerBaka::computeActions()
|
|||||||
vector<MTGAbility*>checking = canPaySunBurst(nextCardToPlay->getManaCost());
|
vector<MTGAbility*>checking = canPaySunBurst(nextCardToPlay->getManaCost());
|
||||||
if(payTheManaCost(nextCardToPlay->getManaCost(),NULL,checking))
|
if(payTheManaCost(nextCardToPlay->getManaCost(),NULL,checking))
|
||||||
{
|
{
|
||||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||||
clickstream.push(a);
|
clickstream.push(a);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -1895,7 +1905,7 @@ int AIPlayerBaka::computeActions()
|
|||||||
}
|
}
|
||||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
||||||
{
|
{
|
||||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||||
clickstream.push(a);
|
clickstream.push(a);
|
||||||
gotPayments.clear();
|
gotPayments.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
+40
-2131
File diff suppressed because it is too large
Load Diff
@@ -719,20 +719,16 @@ int AbilityFactory::parseRestriction(string s)
|
|||||||
// When abilities encapsulate each other, gets the deepest one (it is the one likely to have the most relevant information)
|
// When abilities encapsulate each other, gets the deepest one (it is the one likely to have the most relevant information)
|
||||||
MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
||||||
{
|
{
|
||||||
AForeach * fea = dynamic_cast<AForeach*>(a);
|
if(AForeach * fea = dynamic_cast<AForeach*>(a))
|
||||||
if(fea)
|
|
||||||
return getCoreAbility(fea->ability);
|
return getCoreAbility(fea->ability);
|
||||||
|
|
||||||
AAsLongAs * aea = dynamic_cast<AAsLongAs*>(a);
|
if( AAsLongAs * aea = dynamic_cast<AAsLongAs*>(a))
|
||||||
if(aea)
|
|
||||||
return getCoreAbility(aea->ability);
|
return getCoreAbility(aea->ability);
|
||||||
|
|
||||||
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a);
|
if (GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a))
|
||||||
if (gta)
|
|
||||||
return getCoreAbility(gta->ability);
|
return getCoreAbility(gta->ability);
|
||||||
|
|
||||||
GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*> (a);
|
if (GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*> (a))
|
||||||
if (gaa)
|
|
||||||
return getCoreAbility(gaa->ability);
|
return getCoreAbility(gaa->ability);
|
||||||
|
|
||||||
if (MultiAbility * abi = dynamic_cast<MultiAbility*>(a))
|
if (MultiAbility * abi = dynamic_cast<MultiAbility*>(a))
|
||||||
@@ -744,8 +740,10 @@ MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
|||||||
//only atempt to return a nestedability if it contains a valid ability. example where this causes a bug otherwise. AEquip is considered nested, but contains no ability.
|
//only atempt to return a nestedability if it contains a valid ability. example where this causes a bug otherwise. AEquip is considered nested, but contains no ability.
|
||||||
return getCoreAbility(na->ability);
|
return getCoreAbility(na->ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MenuAbility * ma = dynamic_cast<MenuAbility*>(a))
|
if (MenuAbility * ma = dynamic_cast<MenuAbility*>(a))
|
||||||
return ma->abilities[0];
|
return getCoreAbility(ma->abilities[0]);
|
||||||
|
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -492,7 +492,7 @@ MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGGameZone::countByType(const char * value)
|
unsigned int MTGGameZone::countByType(const char * value)
|
||||||
{
|
{
|
||||||
int result = 0;
|
int result = 0;
|
||||||
int subTypeId = Subtypes::subtypesList->find(value);
|
int subTypeId = Subtypes::subtypesList->find(value);
|
||||||
@@ -506,10 +506,11 @@ int MTGGameZone::countByType(const char * value)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MTGGameZone::countByCanTarget(TargetChooser * tc)
|
unsigned int MTGGameZone::countByCanTarget(TargetChooser * tc)
|
||||||
{
|
{
|
||||||
if(!tc)
|
if(!tc)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
for (int i = 0; i < (nb_cards); i++)
|
for (int i = 0; i < (nb_cards); i++)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user