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:
|
||||
static int currentId;
|
||||
public:
|
||||
Player * owner;
|
||||
MTGAbility * ability;
|
||||
NestedAbility * nability;
|
||||
Player * player;
|
||||
@@ -38,27 +39,27 @@ public:
|
||||
Targetable * playerAbilityTarget;
|
||||
//player targeting through abilities is handled completely seperate from spell targeting.
|
||||
|
||||
AIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||
: ability(a), player(NULL), click(c), target(t),playerAbilityTarget(NULL)
|
||||
AIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||
: owner(owner), ability(a), player(NULL), click(c), target(t),playerAbilityTarget(NULL)
|
||||
{
|
||||
id = currentId++;
|
||||
};
|
||||
|
||||
AIAction(MTGCardInstance * c, MTGCardInstance * t = NULL);
|
||||
AIAction(Player * owner, MTGCardInstance * c, MTGCardInstance * t = NULL);
|
||||
|
||||
AIAction(Player * p)//player targeting through spells
|
||||
: ability(NULL), player(p), click(NULL), target(NULL),playerAbilityTarget(NULL)
|
||||
AIAction(Player * owner, Player * p)//player targeting through spells
|
||||
: owner(owner), ability(NULL), player(p), click(NULL), target(NULL),playerAbilityTarget(NULL)
|
||||
{
|
||||
};
|
||||
|
||||
AIAction(MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||
: ability(a), player(NULL), click(c), mAbilityTargets(targetCards),playerAbilityTarget(NULL)
|
||||
AIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||
: owner(owner), ability(a), player(NULL), click(c), mAbilityTargets(targetCards),playerAbilityTarget(NULL)
|
||||
{
|
||||
id = currentId++;
|
||||
};
|
||||
|
||||
AIAction(MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||
: ability(a), click(c),target(NULL), playerAbilityTarget(p)
|
||||
AIAction(Player * owner, MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||
: owner(owner), ability(a), click(c),target(NULL), playerAbilityTarget(p)
|
||||
{
|
||||
id = currentId++;
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define _AI_PLAYER_BAKA_H_
|
||||
|
||||
#include "AIPlayer.h"
|
||||
#include "AllAbilities.h"
|
||||
|
||||
class AIStats;
|
||||
class AIHints;
|
||||
@@ -12,33 +13,37 @@ class AIHints;
|
||||
class OrderedAIAction: public AIAction
|
||||
{
|
||||
protected:
|
||||
|
||||
Player * getPlayerTarget();
|
||||
|
||||
public:
|
||||
int efficiency;
|
||||
|
||||
OrderedAIAction(MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||
: AIAction(a, c, t), efficiency(-1)
|
||||
OrderedAIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, MTGCardInstance * t = NULL)
|
||||
: 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
|
||||
: AIAction(p), efficiency(-1)
|
||||
OrderedAIAction(Player * owner, Player * p)//player targeting through spells
|
||||
: AIAction(owner,p), efficiency(-1)
|
||||
{
|
||||
};
|
||||
|
||||
OrderedAIAction(MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||
: AIAction(a, c, targetCards), efficiency(-1)
|
||||
OrderedAIAction(Player * owner, MTGAbility * a, MTGCardInstance * c, vector<Targetable*>targetCards)
|
||||
: AIAction(owner,a, c, targetCards), efficiency(-1)
|
||||
{
|
||||
};
|
||||
|
||||
OrderedAIAction(MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||
: AIAction(a, p, c), efficiency(-1)
|
||||
OrderedAIAction(Player * owner, MTGAbility * a, Player * p, MTGCardInstance * c)//player targeting through abilities.
|
||||
: AIAction(owner, a, p, c), efficiency(-1)
|
||||
{
|
||||
};
|
||||
int getEfficiency();
|
||||
|
||||
// Functions depending on the type of Ability
|
||||
int getEfficiency(AADamager * aad);
|
||||
|
||||
};
|
||||
|
||||
// compares Abilities efficiency
|
||||
@@ -60,7 +65,7 @@ typedef std::map<OrderedAIAction, int, CmpAbilities> RankingContainer;
|
||||
|
||||
|
||||
class AIPlayerBaka: public AIPlayer{
|
||||
private:
|
||||
protected:
|
||||
virtual int orderBlockers();
|
||||
virtual int combatDamages();
|
||||
virtual int interruptIfICan();
|
||||
@@ -84,7 +89,6 @@ private:
|
||||
|
||||
virtual AIStats * getStats();
|
||||
|
||||
protected:
|
||||
MTGCardInstance * nextCardToPlay;
|
||||
AIHints * hints;
|
||||
AIStats * stats;
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
#include "config.h"
|
||||
#ifdef AI_CHANGE_TESTING
|
||||
|
||||
#ifndef _AI_PLAYER_BAKA_B_H_
|
||||
#include "config.h"
|
||||
#ifdef AI_CHANGE_TESTING
|
||||
|
||||
#ifndef _AI_PLAYER_BAKA_B_H_
|
||||
#define _AI_PLAYER_BAKA_B_H_
|
||||
|
||||
#include "AIPlayerBaka.h"
|
||||
#include "AllAbilities.h"
|
||||
|
||||
class AIStats;
|
||||
class AIHints;
|
||||
|
||||
|
||||
class AIPlayerBakaB: public AIPlayerBaka{
|
||||
private:
|
||||
protected:
|
||||
int orderBlockers();
|
||||
int combatDamages();
|
||||
int interruptIfICan();
|
||||
@@ -36,16 +37,16 @@ private:
|
||||
|
||||
AIStats * getStats();
|
||||
|
||||
protected:
|
||||
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*>());
|
||||
int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
|
||||
ManaCost * getPotentialMana(MTGCardInstance * card = NULL);
|
||||
int selectAbility();
|
||||
|
||||
//used by MomirPlayer, hence protected instead of private
|
||||
virtual int getEfficiency(OrderedAIAction * action);
|
||||
|
||||
public:
|
||||
|
||||
AIPlayerBakaB(string deckFile, string deckfileSmall, string avatarFile, MTGDeck * deck = NULL);
|
||||
@@ -62,7 +63,7 @@ private:
|
||||
//used by AIHInts, therefore public instead of private :/
|
||||
int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -86,8 +86,8 @@ class MTGGameZone {
|
||||
void cleanupPhase();
|
||||
void beforeBeginPhase();
|
||||
|
||||
int countByType(const char * value);
|
||||
int countByCanTarget(TargetChooser * tc);
|
||||
unsigned int countByType(const char * value);
|
||||
unsigned int countByCanTarget(TargetChooser * tc);
|
||||
MTGCardInstance * findByName(string name);
|
||||
|
||||
//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))
|
||||
{
|
||||
payTheManaCost(cost);
|
||||
AIAction * a = NEW AIAction(ability, card);
|
||||
AIAction * a = NEW AIAction(this, ability, card);
|
||||
clickstream.push(a);
|
||||
result = 1;
|
||||
}
|
||||
@@ -112,7 +112,7 @@ int AIMomirPlayer::computeActions()
|
||||
if (card && (canPutLandsIntoPlay == PlayRestriction::CAN_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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ const char * const MTG_LAND_TEXTS[] = { "artifact", "forest", "island", "mountai
|
||||
|
||||
int AIAction::currentId = 0;
|
||||
|
||||
AIAction::AIAction(MTGCardInstance * c, MTGCardInstance * t)
|
||||
: ability(NULL), player(NULL), click(c), target(t)
|
||||
AIAction::AIAction(Player * owner, MTGCardInstance * c, MTGCardInstance * t)
|
||||
: owner(owner), ability(NULL), player(NULL), click(c), target(t)
|
||||
{
|
||||
id = currentId++;
|
||||
|
||||
@@ -165,21 +165,21 @@ int AIPlayer::clickMultiTarget(TargetChooser * tc, vector<Targetable*>& potentia
|
||||
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".
|
||||
{
|
||||
clickstream.push(NEW AIAction(card));
|
||||
clickstream.push(NEW AIAction(this, card));
|
||||
DebugTrace("Ai clicked source as a target: " << (card ? card->name : "None" ) << endl );
|
||||
potentialTargets.erase(potentialTargets.begin() + f);
|
||||
sourceIncluded = true;
|
||||
}
|
||||
if(pTarget && pTarget->typeAsTarget() == TARGET_PLAYER)
|
||||
{
|
||||
clickstream.push(NEW AIAction(pTarget));
|
||||
clickstream.push(NEW AIAction(this, pTarget));
|
||||
DebugTrace("Ai clicked Player as a target");
|
||||
potentialTargets.erase(potentialTargets.begin() + f);
|
||||
}
|
||||
}
|
||||
std::random_shuffle(potentialTargets.begin(), potentialTargets.end());
|
||||
if(potentialTargets.size())
|
||||
clickstream.push(NEW AIAction(NULL,tc->source,potentialTargets));
|
||||
clickstream.push(NEW AIAction(this, NULL,tc->source,potentialTargets));
|
||||
while(clickstream.size())
|
||||
{
|
||||
AIAction * action = clickstream.front();
|
||||
@@ -201,7 +201,7 @@ int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potenti
|
||||
if(!chosenCard)
|
||||
{
|
||||
MTGCardInstance * card = ((MTGCardInstance *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(card));
|
||||
clickstream.push(NEW AIAction(this, card));
|
||||
chosenCard = card;
|
||||
}
|
||||
break;
|
||||
@@ -209,7 +209,7 @@ int AIPlayer::clickSingleTarget(TargetChooser * tc, vector<Targetable*>& potenti
|
||||
case TARGET_PLAYER:
|
||||
{
|
||||
Player * player = ((Player *) potentialTargets[i]);
|
||||
clickstream.push(NEW AIAction(player));
|
||||
clickstream.push(NEW AIAction(this, player));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,58 @@
|
||||
#include "AIHints.h"
|
||||
#include "ManaCostHybrid.h"
|
||||
|
||||
|
||||
//
|
||||
// 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
|
||||
int OrderedAIAction::getEfficiency()
|
||||
{
|
||||
@@ -24,6 +70,8 @@ int OrderedAIAction::getEfficiency()
|
||||
return 0;
|
||||
GameObserver * g = GameObserver::GetInstance();
|
||||
ActionStack * s = g->mLayers->stackLayer();
|
||||
int currentPhase = g->getCurrentGamePhase();
|
||||
|
||||
Player * p = g->currentlyActing();
|
||||
if (s->has(ability))
|
||||
return 0;
|
||||
@@ -34,97 +82,61 @@ int OrderedAIAction::getEfficiency()
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!((AIPlayerBaka *) p)->canHandleCost(ability))
|
||||
if (!((AIPlayerBaka *)owner)->canHandleCost(ability))
|
||||
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)
|
||||
{
|
||||
case MTGAbility::DAMAGER:
|
||||
{
|
||||
AADamager * aad = (AADamager *) a;
|
||||
MTGCardInstance * dTarget = (MTGCardInstance*)target;
|
||||
if(!target && !playerAbilityTarget)
|
||||
{
|
||||
dTarget = (MTGCardInstance*)aad->getTarget();
|
||||
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;
|
||||
efficiency = getEfficiency ((AADamager *) a);
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
efficiency = 0;//starts out low to avoid spamming it when its not needed.
|
||||
if (!target && !dynamic_cast<ALord*> (a))
|
||||
|
||||
if (!target)
|
||||
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;
|
||||
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;
|
||||
if ((target->defenser || target->blockers.size()) && target->preventable < target->getNextOpponent()->power)
|
||||
if ((target->defenser || target->blockers.size()) && target->preventable < nextOpponent->power)
|
||||
NeedPreventing = true;
|
||||
if (p == target->controller() && target->controller()->isAI() && NeedPreventing && !(target->getNextOpponent()->has(Constants::DEATHTOUCH)
|
||||
|| target->getNextOpponent()->has(Constants::WITHER)))
|
||||
if (p == target->controller() && target->controller()->isAI() && NeedPreventing && !(nextOpponent->has(Constants::DEATHTOUCH)
|
||||
||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"..
|
||||
if (target->toughness == 1 && target->getNextOpponent()->power == 1)
|
||||
if (target->toughness == 1 && nextOpponent->power == 1)
|
||||
efficiency += 15;
|
||||
//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.
|
||||
@@ -133,7 +145,7 @@ int OrderedAIAction::getEfficiency()
|
||||
int damages = 0;
|
||||
if((target->defenser || target->blockers.size()) && target->controller() == p)
|
||||
{
|
||||
damages = target->getNextOpponent()->power;
|
||||
damages = nextOpponent->power;
|
||||
calculateAfterDamage = int(target->toughness - damages);
|
||||
if((calculateAfterDamage + target->preventable) > 0)
|
||||
{
|
||||
@@ -154,10 +166,10 @@ int OrderedAIAction::getEfficiency()
|
||||
if (!target)
|
||||
break;
|
||||
|
||||
int equips = p->game->battlefield->countByType("Equipment");
|
||||
int myArmy = p->game->battlefield->countByType("Creature");
|
||||
unsigned int equips = p->game->battlefield->countByType("Equipment");
|
||||
unsigned int myArmy = p->game->battlefield->countByType("Creature");
|
||||
// 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)
|
||||
{
|
||||
@@ -168,7 +180,7 @@ int OrderedAIAction::getEfficiency()
|
||||
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 -= 5 * (target->equipment);
|
||||
@@ -177,82 +189,80 @@ int OrderedAIAction::getEfficiency()
|
||||
}
|
||||
case MTGAbility::STANDARD_LEVELUP:
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
||||
efficiency = 0;
|
||||
Counter * targetCounter = NULL;
|
||||
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);
|
||||
currentlevel = targetCounter->nb;
|
||||
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 (currentlevel < _target->MaxLevelUp)
|
||||
|
||||
if (g->getCurrentGamePhase() == Constants::MTG_PHASE_SECONDMAIN)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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.
|
||||
}
|
||||
efficiency = 100;
|
||||
//in 2nd main, go all out and try to max stuff.
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MTGAbility::COUNTERS:
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) target;
|
||||
if(!_target)
|
||||
_target = (MTGCardInstance *) (a->target);
|
||||
MTGCardInstance * _target = target ? target : coreAbilityCardTarget;
|
||||
efficiency = 0;
|
||||
|
||||
if (!_target)
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
case MTGAbility::STANDARD_PUMP:
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
||||
efficiency = 0;
|
||||
if(!_target)
|
||||
if(!coreAbilityCardTarget)
|
||||
break;
|
||||
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)
|
||||
_target = ((MTGCardInstance *)a->source)->target;
|
||||
target = (MTGCardInstance *)a->source;
|
||||
if(a->source->target)
|
||||
coreAbilityCardTarget = a->source->target; //TODO use intermediate value?
|
||||
target = a->source;
|
||||
}
|
||||
if (!target && !dynamic_cast<ALord*> (a))
|
||||
break;
|
||||
@@ -260,76 +270,78 @@ int OrderedAIAction::getEfficiency()
|
||||
{
|
||||
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.
|
||||
efficiency = 20 * _target->DangerRanking();
|
||||
MTGCardInstance * opponent = coreAbilityCardTarget->getNextOpponent();
|
||||
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:
|
||||
{
|
||||
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.
|
||||
{
|
||||
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
|
||||
MTGAbility * a = AbilityFactory::getCoreAbility(ability);
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
|
||||
efficiency = 0;
|
||||
|
||||
if(!coreAbilityCardTarget)
|
||||
break;
|
||||
|
||||
AManaProducer * amp = dynamic_cast<AManaProducer*>(a);
|
||||
|
||||
//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
|
||||
|| 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--)
|
||||
{
|
||||
if ((p->game->hand->hasColor(i) || p->game->hand->hasColor(0))
|
||||
&& amp->output->hasColor(i))
|
||||
{
|
||||
|
||||
{
|
||||
efficiency = 100;
|
||||
}
|
||||
}
|
||||
|
||||
if (amp->getCost() && amp->getCost()->getConvertedCost() && p->game->hand->hasX())
|
||||
efficiency = 100;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -356,150 +368,144 @@ int OrderedAIAction::getEfficiency()
|
||||
case MTGAbility::STANDARDABILITYGRANT:
|
||||
{
|
||||
efficiency = 0;
|
||||
MTGCardInstance * _target = (MTGCardInstance*)(a->target);
|
||||
if(!_target)
|
||||
|
||||
if (!target)
|
||||
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.
|
||||
//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.
|
||||
AbilityFactory af;
|
||||
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
||||
//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.
|
||||
//the reason i do this is to encourage more casting and less waste of mana on abilities.
|
||||
AbilityFactory af;
|
||||
int suggestion = af.abilityEfficiency(a, p, MODE_ABILITY);
|
||||
|
||||
int efficiencyModifier = (25 * target->DangerRanking());
|
||||
if (p->game->hand->nb_cards > 1)
|
||||
{
|
||||
efficiencyModifier -= p->game->hand->nb_cards*3;
|
||||
}
|
||||
if (suggestion == BAKA_EFFECT_BAD && p != target->controller() && !target->has(a->abilitygranted))
|
||||
{
|
||||
efficiency += efficiencyModifier;
|
||||
}
|
||||
int efficiencyModifier = (25 * target->DangerRanking());
|
||||
if (p->game->hand->nb_cards > 1)
|
||||
{
|
||||
efficiencyModifier -= p->game->hand->nb_cards*3;
|
||||
}
|
||||
if (suggestion == BAKA_EFFECT_BAD && p != target->controller() && !target->has(a->abilitygranted))
|
||||
{
|
||||
efficiency += efficiencyModifier;
|
||||
}
|
||||
|
||||
if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN
|
||||
&& p == target->controller()
|
||||
)
|
||||
{
|
||||
efficiency += efficiencyModifier;
|
||||
}
|
||||
if (!target->has(a->abilitygranted) && g->getCurrentGamePhase() == Constants::MTG_PHASE_COMBATBEGIN
|
||||
&& p == target->controller()
|
||||
)
|
||||
{
|
||||
efficiency += efficiencyModifier;
|
||||
}
|
||||
|
||||
if (suggestion == BAKA_EFFECT_GOOD && target->has(a->abilitygranted))
|
||||
{
|
||||
//trying to avoid Ai giving ie:flying creatures ie:flying twice.
|
||||
efficiency = 0;
|
||||
}
|
||||
if (suggestion == BAKA_EFFECT_GOOD && target->has(a->abilitygranted))
|
||||
{
|
||||
//trying to avoid Ai giving ie:flying creatures ie:flying twice.
|
||||
efficiency = 0;
|
||||
}
|
||||
|
||||
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
|
||||
|| (suggestion == BAKA_EFFECT_GOOD && p != target->controller())
|
||||
)
|
||||
{
|
||||
efficiency = 0;
|
||||
//stop giving trample to the players creatures.
|
||||
if ((suggestion == BAKA_EFFECT_BAD && p == target->controller())
|
||||
|| (suggestion == BAKA_EFFECT_GOOD && p != target->controller())
|
||||
)
|
||||
{
|
||||
efficiency = 0;
|
||||
//stop giving trample to the players creatures.
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MTGAbility::UNTAPPER:
|
||||
//untap things that Ai owns and are tapped.
|
||||
{
|
||||
efficiency = 0;
|
||||
if (!target && !dynamic_cast<ALord*> (a))
|
||||
if (!target)
|
||||
break;
|
||||
if(dynamic_cast<ALord*> (a) && !target)
|
||||
{
|
||||
target = a->source;
|
||||
}
|
||||
|
||||
if (target->isTapped() && target->controller() == p)
|
||||
{
|
||||
target->isCreature()?efficiency = (20 * target->DangerRanking()):efficiency = 100;
|
||||
efficiency = target->isCreature()? (20 * target->DangerRanking()) : 100;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MTGAbility::TAPPER:
|
||||
//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;
|
||||
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:
|
||||
{
|
||||
//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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
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:
|
||||
{
|
||||
if(target)
|
||||
{
|
||||
Interruptible * action = g->mLayers->stackLayer()->getAt(-1);
|
||||
Spell * spell = (Spell *) action;
|
||||
Player * lastStackActionController = NULL;
|
||||
if(spell && spell->type == ACTION_SPELL)
|
||||
lastStackActionController = spell->source->controller();
|
||||
if(p != target->controller() && lastStackActionController && lastStackActionController != p)
|
||||
efficiency = 60;//we want ai to fizzle at higher than "unknown" ability %.
|
||||
}
|
||||
efficiency = 0;
|
||||
|
||||
if(!target)
|
||||
break;
|
||||
|
||||
Interruptible * action = g->mLayers->stackLayer()->getAt(-1);
|
||||
if (!action)
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
default:
|
||||
@@ -557,7 +563,7 @@ int OrderedAIAction::getEfficiency()
|
||||
efficiency = 100;
|
||||
}
|
||||
}
|
||||
if (AAMover * aam = dynamic_cast<AAMover *>(a))
|
||||
else if (AAMover * aam = dynamic_cast<AAMover *>(a))
|
||||
{
|
||||
MTGGameZone * z = aam->destinationZone(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)
|
||||
{
|
||||
@@ -587,14 +593,14 @@ int OrderedAIAction::getEfficiency()
|
||||
else if (aap)
|
||||
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)
|
||||
{
|
||||
efficiency = 90;
|
||||
}
|
||||
}
|
||||
if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
|
||||
else if (ATokenCreator * atc = dynamic_cast<ATokenCreator *>(a))
|
||||
{
|
||||
efficiency = 80;
|
||||
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);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
return efficiency;
|
||||
}
|
||||
|
||||
@@ -689,13 +699,13 @@ bool AIPlayerBaka::payTheManaCost(ManaCost * cost, MTGCardInstance * target,vect
|
||||
{
|
||||
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);
|
||||
paid->add(amp->output);
|
||||
}
|
||||
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);
|
||||
if(AForeach * fmp = dynamic_cast<AForeach*>(gmp->ability))
|
||||
{
|
||||
@@ -775,7 +785,7 @@ bool AIPlayerBaka::payTheManaCost(ManaCost * cost, MTGCardInstance * target,vect
|
||||
}
|
||||
if (doUse)
|
||||
{
|
||||
AIAction * action = NEW AIAction(amp, card);
|
||||
AIAction * action = NEW AIAction(this, amp, card);
|
||||
clickstream.push(action);
|
||||
}
|
||||
}
|
||||
@@ -1139,7 +1149,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
{
|
||||
if (!a->getActionTc())
|
||||
{
|
||||
OrderedAIAction aiAction(a, c, NULL);
|
||||
OrderedAIAction aiAction(this, a, c, NULL);
|
||||
ranking[aiAction] = 1;
|
||||
return 1;
|
||||
}
|
||||
@@ -1153,7 +1163,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
{
|
||||
if(a->getActionTc()->maxtargets == 1)
|
||||
{
|
||||
OrderedAIAction aiAction(a, p, c);
|
||||
OrderedAIAction aiAction(this, a, p, c);
|
||||
ranking[aiAction] = 1;
|
||||
}
|
||||
else
|
||||
@@ -1169,7 +1179,7 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
{
|
||||
if(a->getActionTc()->maxtargets == 1)
|
||||
{
|
||||
OrderedAIAction aiAction(a, c, t);
|
||||
OrderedAIAction aiAction(this, a, c, t);
|
||||
ranking[aiAction] = 1;
|
||||
}
|
||||
else
|
||||
@@ -1195,16 +1205,16 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
||||
|
||||
MTGCardInstance * targeting = dynamic_cast<MTGCardInstance*>(potentialTargets[0]);
|
||||
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]);
|
||||
if(ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
||||
check = NEW OrderedAIAction(a,ptargeting,c);
|
||||
check = NEW OrderedAIAction(this, a,ptargeting,c);
|
||||
|
||||
targetThis = getEfficiency(check);
|
||||
if(targetThis && ptargeting && ptargeting->typeAsTarget() == TARGET_PLAYER)
|
||||
{
|
||||
OrderedAIAction aiAction(a,ptargeting,c);
|
||||
OrderedAIAction aiAction(this, a,ptargeting,c);
|
||||
ranking[aiAction] = 1;
|
||||
}
|
||||
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))
|
||||
return 0;
|
||||
OrderedAIAction aiAction(a, c,realTargets);
|
||||
OrderedAIAction aiAction(this, a, c,realTargets);
|
||||
aiAction.target = (MTGCardInstance*)realTargets[0];
|
||||
ranking[aiAction] = 1;
|
||||
}
|
||||
@@ -1473,7 +1483,7 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
||||
{
|
||||
AbilityFactory af;
|
||||
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())
|
||||
{
|
||||
potentialTargets.push_back(card);
|
||||
@@ -1552,11 +1562,11 @@ int AIPlayerBaka::selectMenuOption()
|
||||
if(checkEff)
|
||||
{
|
||||
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)
|
||||
check = NEW OrderedAIAction(checkEff,(Player*)checkEff->target,checkEff->source);
|
||||
check = NEW OrderedAIAction(this, checkEff,(Player*)checkEff->target,checkEff->source);
|
||||
else
|
||||
check = NEW OrderedAIAction(checkEff,checkEff->source);
|
||||
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
|
||||
}
|
||||
if(check)
|
||||
{
|
||||
@@ -1583,11 +1593,11 @@ int AIPlayerBaka::selectMenuOption()
|
||||
{
|
||||
Targetable * checkTarget = checkEff->target;
|
||||
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)
|
||||
check = NEW OrderedAIAction(checkEff,(Player*)checkTarget,checkEff->source);
|
||||
check = NEW OrderedAIAction(this, checkEff,(Player*)checkTarget,checkEff->source);
|
||||
else
|
||||
check = NEW OrderedAIAction(checkEff,checkEff->source);
|
||||
check = NEW OrderedAIAction(this, checkEff,checkEff->source);
|
||||
}
|
||||
if(check)
|
||||
{
|
||||
@@ -1826,7 +1836,7 @@ int AIPlayerBaka::computeActions()
|
||||
{
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
@@ -1885,7 +1895,7 @@ int AIPlayerBaka::computeActions()
|
||||
vector<MTGAbility*>checking = canPaySunBurst(nextCardToPlay->getManaCost());
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),NULL,checking))
|
||||
{
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
return 1;
|
||||
}
|
||||
@@ -1895,7 +1905,7 @@ int AIPlayerBaka::computeActions()
|
||||
}
|
||||
if(payTheManaCost(nextCardToPlay->getManaCost(),nextCardToPlay,gotPayments))
|
||||
{
|
||||
AIAction * a = NEW AIAction(nextCardToPlay);
|
||||
AIAction * a = NEW AIAction(this, nextCardToPlay);
|
||||
clickstream.push(a);
|
||||
gotPayments.clear();
|
||||
}
|
||||
|
||||
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)
|
||||
MTGAbility * AbilityFactory::getCoreAbility(MTGAbility * a)
|
||||
{
|
||||
AForeach * fea = dynamic_cast<AForeach*>(a);
|
||||
if(fea)
|
||||
if(AForeach * fea = dynamic_cast<AForeach*>(a))
|
||||
return getCoreAbility(fea->ability);
|
||||
|
||||
AAsLongAs * aea = dynamic_cast<AAsLongAs*>(a);
|
||||
if(aea)
|
||||
if( AAsLongAs * aea = dynamic_cast<AAsLongAs*>(a))
|
||||
return getCoreAbility(aea->ability);
|
||||
|
||||
GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a);
|
||||
if (gta)
|
||||
if (GenericTargetAbility * gta = dynamic_cast<GenericTargetAbility*> (a))
|
||||
return getCoreAbility(gta->ability);
|
||||
|
||||
GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*> (a);
|
||||
if (gaa)
|
||||
if (GenericActivatedAbility * gaa = dynamic_cast<GenericActivatedAbility*> (a))
|
||||
return getCoreAbility(gaa->ability);
|
||||
|
||||
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.
|
||||
return getCoreAbility(na->ability);
|
||||
}
|
||||
|
||||
if (MenuAbility * ma = dynamic_cast<MenuAbility*>(a))
|
||||
return ma->abilities[0];
|
||||
return getCoreAbility(ma->abilities[0]);
|
||||
|
||||
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 subTypeId = Subtypes::subtypesList->find(value);
|
||||
@@ -506,10 +506,11 @@ int MTGGameZone::countByType(const char * value)
|
||||
return result;
|
||||
}
|
||||
|
||||
int MTGGameZone::countByCanTarget(TargetChooser * tc)
|
||||
unsigned int MTGGameZone::countByCanTarget(TargetChooser * tc)
|
||||
{
|
||||
if(!tc)
|
||||
return 0;
|
||||
if(!tc)
|
||||
return 0;
|
||||
|
||||
int result = 0;
|
||||
for (int i = 0; i < (nb_cards); i++)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user