AI considers playing from exile and graveyard
This commit is contained in:
@@ -627,6 +627,14 @@ int OrderedAIAction::getEfficiency()
|
|||||||
{
|
{
|
||||||
efficiency += 65;
|
efficiency += 65;
|
||||||
}
|
}
|
||||||
|
else if (dynamic_cast<MTGAlternativeCostRule *>(a))
|
||||||
|
{
|
||||||
|
efficiency += 55;
|
||||||
|
}
|
||||||
|
else if (dynamic_cast<MTGPlayFromGraveyardRule *>(a))
|
||||||
|
{
|
||||||
|
efficiency += 45;
|
||||||
|
}
|
||||||
SAFE_DELETE(transAbility);
|
SAFE_DELETE(transAbility);
|
||||||
return efficiency;
|
return efficiency;
|
||||||
}
|
}
|
||||||
@@ -1726,6 +1734,302 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
|||||||
cd.setType(type);
|
cd.setType(type);
|
||||||
card = NULL;
|
card = NULL;
|
||||||
gotPayments = vector<MTGAbility*>();
|
gotPayments = vector<MTGAbility*>();
|
||||||
|
//canplayfromgraveyard
|
||||||
|
while ((card = cd.nextmatch(game->graveyard, card))&& card->has(Constants::CANPLAYFROMGRAVEYARD))
|
||||||
|
{
|
||||||
|
if (!CanHandleCost(card->getManaCost(),card))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_LAND))
|
||||||
|
{
|
||||||
|
if (game->playRestrictions->canPutIntoZone(card, game->inPlay) == PlayRestriction::CANT_PLAY)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (game->playRestrictions->canPutIntoZone(card, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(hints && hints->HintSaysItsForCombo(observer,card))
|
||||||
|
{
|
||||||
|
if(hints->canWeCombo(observer,card,this))
|
||||||
|
{
|
||||||
|
AbilityFactory af(observer);
|
||||||
|
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||||
|
if(!canPlay)
|
||||||
|
continue;
|
||||||
|
nextCardToPlay = card;
|
||||||
|
gotPayments.clear();
|
||||||
|
if((!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker()))
|
||||||
|
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost());
|
||||||
|
return activateCombo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextCardToPlay = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int currentCost = card->getManaCost()->getConvertedCost();
|
||||||
|
int hasX = card->getManaCost()->hasX();
|
||||||
|
gotPayments.clear();
|
||||||
|
if((!pMana->canAfford(card->getManaCost()) || card->getManaCost()->getKicker()))
|
||||||
|
gotPayments = canPayMana(card,card->getManaCost());
|
||||||
|
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||||
|
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost())))
|
||||||
|
{
|
||||||
|
TargetChooserFactory tcf(observer);
|
||||||
|
TargetChooser * tc = tcf.createTargetChooser(card);
|
||||||
|
int shouldPlayPercentage = 0;
|
||||||
|
if (tc)
|
||||||
|
{
|
||||||
|
int hasTarget = chooseTarget(tc,NULL,NULL,true);
|
||||||
|
if(
|
||||||
|
(tc->maxtargets > hasTarget && tc->maxtargets > 1 && !tc->targetMin && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS) ||//target=<3>creature
|
||||||
|
(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS && hasTarget < 1)//target=creatures
|
||||||
|
)
|
||||||
|
hasTarget = 0;
|
||||||
|
if (!hasTarget)//single target covered here.
|
||||||
|
{
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
if(tc->targetMin && hasTarget < tc->maxtargets)
|
||||||
|
shouldPlayPercentage = 0;
|
||||||
|
if(tc->maxtargets > 1 && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS && hasTarget <= tc->maxtargets)
|
||||||
|
{
|
||||||
|
int maxA = hasTarget-tc->maxtargets;
|
||||||
|
shouldPlayPercentage += (10*maxA);//reduce the chances of playing multitarget if we are not above max targets.
|
||||||
|
}
|
||||||
|
if(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 40 + (10*hasTarget);
|
||||||
|
int totalCost = pMana->getConvertedCost()-currentCost;
|
||||||
|
int totalTargets = hasTarget+hasTarget;
|
||||||
|
if(hasX && totalCost <= totalTargets)// {x} spell with unlimited targeting tend to divide damage, we want atleast 1 damage per target before casting.
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int shouldPlay = effectBadOrGood(card);
|
||||||
|
if (shouldPlay == BAKA_EFFECT_GOOD)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
}
|
||||||
|
else if (BAKA_EFFECT_DONTKNOW == shouldPlay)
|
||||||
|
{
|
||||||
|
//previously shouldPlayPercentage = 80;, I found this a little to high
|
||||||
|
//for cards which AI had no idea how to use.
|
||||||
|
shouldPlayPercentage = 60;
|
||||||
|
}
|
||||||
|
else if (card->isLand())
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance.
|
||||||
|
shouldPlayPercentage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//Reduce the chances of playing a spell with X cost if available mana is low
|
||||||
|
if (hasX)
|
||||||
|
{
|
||||||
|
int xDiff = pMana->getConvertedCost() - currentCost;
|
||||||
|
if (xDiff < 0)
|
||||||
|
xDiff = 0;
|
||||||
|
shouldPlayPercentage = shouldPlayPercentage - static_cast<int> ((shouldPlayPercentage * 1.9f) / (1 + xDiff));
|
||||||
|
}
|
||||||
|
if(card->getManaCost() && card->getManaCost()->getKicker() && card->getManaCost()->getKicker()->isMulti)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 10* size_t(gotPayments.size())/int(1+(card->getManaCost()->getConvertedCost()+card->getManaCost()->getKicker()->getConvertedCost()));
|
||||||
|
if(shouldPlayPercentage <= 10)
|
||||||
|
shouldPlayPercentage = shouldPlayPercentage/3;
|
||||||
|
}
|
||||||
|
DebugTrace("Should I play " << (card ? card->name : "Nothing" ) << "?" << endl
|
||||||
|
<<"shouldPlayPercentage = "<< shouldPlayPercentage);
|
||||||
|
if(card->getRestrictions().size())
|
||||||
|
{
|
||||||
|
AbilityFactory af(observer);
|
||||||
|
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||||
|
if(!canPlay)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int randomChance = randomGenerator.random();
|
||||||
|
int chance = randomChance % 100;
|
||||||
|
if (chance > shouldPlayPercentage)
|
||||||
|
continue;
|
||||||
|
if(shouldPlayPercentage <= 10)
|
||||||
|
{
|
||||||
|
DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG");
|
||||||
|
}
|
||||||
|
nextCardToPlay = card;
|
||||||
|
maxCost = currentCost;
|
||||||
|
if (hasX)
|
||||||
|
maxCost = pMana->getConvertedCost();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//canplayfromexile
|
||||||
|
while ((card = cd.nextmatch(game->exile, card))&& card->has(Constants::CANPLAYFROMEXILE))
|
||||||
|
{
|
||||||
|
if (!CanHandleCost(card->getManaCost(),card))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_LAND))
|
||||||
|
{
|
||||||
|
if (game->playRestrictions->canPutIntoZone(card, game->inPlay) == PlayRestriction::CANT_PLAY)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (game->playRestrictions->canPutIntoZone(card, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_LEGENDARY) && game->inPlay->findByName(card->name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(hints && hints->HintSaysItsForCombo(observer,card))
|
||||||
|
{
|
||||||
|
if(hints->canWeCombo(observer,card,this))
|
||||||
|
{
|
||||||
|
AbilityFactory af(observer);
|
||||||
|
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||||
|
if(!canPlay)
|
||||||
|
continue;
|
||||||
|
nextCardToPlay = card;
|
||||||
|
gotPayments.clear();
|
||||||
|
if((!pMana->canAfford(nextCardToPlay->getManaCost()) || nextCardToPlay->getManaCost()->getKicker()))
|
||||||
|
gotPayments = canPayMana(nextCardToPlay,nextCardToPlay->getManaCost());
|
||||||
|
return activateCombo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextCardToPlay = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int currentCost = card->getManaCost()->getConvertedCost();
|
||||||
|
int hasX = card->getManaCost()->hasX();
|
||||||
|
gotPayments.clear();
|
||||||
|
if((!pMana->canAfford(card->getManaCost()) || card->getManaCost()->getKicker()))
|
||||||
|
gotPayments = canPayMana(card,card->getManaCost());
|
||||||
|
//for preformence reason we only look for specific mana if the payment couldn't be made with pmana.
|
||||||
|
if ((currentCost > maxCost || hasX) && (gotPayments.size() || pMana->canAfford(card->getManaCost())))
|
||||||
|
{
|
||||||
|
TargetChooserFactory tcf(observer);
|
||||||
|
TargetChooser * tc = tcf.createTargetChooser(card);
|
||||||
|
int shouldPlayPercentage = 0;
|
||||||
|
if (tc)
|
||||||
|
{
|
||||||
|
int hasTarget = chooseTarget(tc,NULL,NULL,true);
|
||||||
|
if(
|
||||||
|
(tc->maxtargets > hasTarget && tc->maxtargets > 1 && !tc->targetMin && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS) ||//target=<3>creature
|
||||||
|
(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS && hasTarget < 1)//target=creatures
|
||||||
|
)
|
||||||
|
hasTarget = 0;
|
||||||
|
if (!hasTarget)//single target covered here.
|
||||||
|
{
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
if(tc->targetMin && hasTarget < tc->maxtargets)
|
||||||
|
shouldPlayPercentage = 0;
|
||||||
|
if(tc->maxtargets > 1 && tc->maxtargets != TargetChooser::UNLITMITED_TARGETS && hasTarget <= tc->maxtargets)
|
||||||
|
{
|
||||||
|
int maxA = hasTarget-tc->maxtargets;
|
||||||
|
shouldPlayPercentage += (10*maxA);//reduce the chances of playing multitarget if we are not above max targets.
|
||||||
|
}
|
||||||
|
if(tc->maxtargets == TargetChooser::UNLITMITED_TARGETS)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 40 + (10*hasTarget);
|
||||||
|
int totalCost = pMana->getConvertedCost()-currentCost;
|
||||||
|
int totalTargets = hasTarget+hasTarget;
|
||||||
|
if(hasX && totalCost <= totalTargets)// {x} spell with unlimited targeting tend to divide damage, we want atleast 1 damage per target before casting.
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_DELETE(tc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int shouldPlay = effectBadOrGood(card);
|
||||||
|
if (shouldPlay == BAKA_EFFECT_GOOD)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
}
|
||||||
|
else if (BAKA_EFFECT_DONTKNOW == shouldPlay)
|
||||||
|
{
|
||||||
|
//previously shouldPlayPercentage = 80;, I found this a little to high
|
||||||
|
//for cards which AI had no idea how to use.
|
||||||
|
shouldPlayPercentage = 60;
|
||||||
|
}
|
||||||
|
else if (card->isLand())
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 90;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// shouldPlay == baka_effect_bad giving it a 1 for odd ball lottery chance.
|
||||||
|
shouldPlayPercentage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//Reduce the chances of playing a spell with X cost if available mana is low
|
||||||
|
if (hasX)
|
||||||
|
{
|
||||||
|
int xDiff = pMana->getConvertedCost() - currentCost;
|
||||||
|
if (xDiff < 0)
|
||||||
|
xDiff = 0;
|
||||||
|
shouldPlayPercentage = shouldPlayPercentage - static_cast<int> ((shouldPlayPercentage * 1.9f) / (1 + xDiff));
|
||||||
|
}
|
||||||
|
if(card->getManaCost() && card->getManaCost()->getKicker() && card->getManaCost()->getKicker()->isMulti)
|
||||||
|
{
|
||||||
|
shouldPlayPercentage = 10* size_t(gotPayments.size())/int(1+(card->getManaCost()->getConvertedCost()+card->getManaCost()->getKicker()->getConvertedCost()));
|
||||||
|
if(shouldPlayPercentage <= 10)
|
||||||
|
shouldPlayPercentage = shouldPlayPercentage/3;
|
||||||
|
}
|
||||||
|
DebugTrace("Should I play " << (card ? card->name : "Nothing" ) << "?" << endl
|
||||||
|
<<"shouldPlayPercentage = "<< shouldPlayPercentage);
|
||||||
|
if(card->getRestrictions().size())
|
||||||
|
{
|
||||||
|
AbilityFactory af(observer);
|
||||||
|
int canPlay = af.parseCastRestrictions(card,card->controller(),card->getRestrictions());
|
||||||
|
if(!canPlay)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int randomChance = randomGenerator.random();
|
||||||
|
int chance = randomChance % 100;
|
||||||
|
if (chance > shouldPlayPercentage)
|
||||||
|
continue;
|
||||||
|
if(shouldPlayPercentage <= 10)
|
||||||
|
{
|
||||||
|
DebugTrace("shouldPlayPercentage was less than 10 this was a lottery roll on RNG");
|
||||||
|
}
|
||||||
|
nextCardToPlay = card;
|
||||||
|
maxCost = currentCost;
|
||||||
|
if (hasX)
|
||||||
|
maxCost = pMana->getConvertedCost();
|
||||||
|
}
|
||||||
|
}
|
||||||
while ((card = cd.nextmatch(game->hand, card)))
|
while ((card = cd.nextmatch(game->hand, card)))
|
||||||
{
|
{
|
||||||
if (!CanHandleCost(card->getManaCost(),card))
|
if (!CanHandleCost(card->getManaCost(),card))
|
||||||
|
|||||||
@@ -1156,7 +1156,7 @@ void GameObserver::Affinity()
|
|||||||
card->getManaCost()->remove(color,1);
|
card->getManaCost()->remove(color,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//SAFE_DELETE(original);
|
SAFE_DELETE(original);
|
||||||
}//end
|
}//end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3689,9 +3689,6 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ
|
|||||||
badAbilities[(int)Constants::WEAK] = true;
|
badAbilities[(int)Constants::WEAK] = true;
|
||||||
badAbilities[(int)Constants::NOLIFEGAIN] = true;
|
badAbilities[(int)Constants::NOLIFEGAIN] = true;
|
||||||
badAbilities[(int)Constants::NOLIFEGAINOPPONENT] = true;
|
badAbilities[(int)Constants::NOLIFEGAINOPPONENT] = true;
|
||||||
badAbilities[(int)Constants::CANTLOSE] = false;
|
|
||||||
badAbilities[(int)Constants::CANTLIFELOSE] = false;
|
|
||||||
badAbilities[(int)Constants::CANTMILLLOSE] = false;
|
|
||||||
|
|
||||||
if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast<AInstantBasicAbilityModifierUntilEOT *>(a))
|
if (AInstantBasicAbilityModifierUntilEOT * abi = dynamic_cast<AInstantBasicAbilityModifierUntilEOT *>(a))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user