this is the first draft of a simple ai combo system,

format is as follows

HINT#combo hold(blah|myhand)^until(blah|mygraveyard)^until(blah|opponentshand)^restriction{type(creature|mybattlefield)~morethan~2}^cast(blah) targeting(blah|mygraveyard)^totalmananneeded({g}{g}{r}{u}{2})

the ai can be told to hold more then one card, until as many condiations as you want are met, until( is a TC and can basically be used in a fasion of saying "hold arbor elf until you have a lord of atlantas in play and a gaint growth in you hand" 

once the condiations are met you can later tell it to cast(gaint growth) targeting(arbor elf[fresh]|mybattlefield)...

I also included the whole of the games restrictions system...
so you can get really really creative with this so far.

the next thing I will do is ability targeting and card favoring.
This commit is contained in:
omegablast2002@yahoo.com
2012-08-19 21:53:57 +00:00
parent 6d4e677711
commit d078872dfc
14 changed files with 335 additions and 39 deletions

View File

@@ -16,10 +16,8 @@ AIHint::AIHint(string _line)
return;
}
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
vector<string> parameters = split(line,':');
mCondition = (parameters.size() == 1)? "" : parameters[0];
string action = parameters[parameters.size() - 1];
mCondition = line;
string action = line;
vector<string> splitAction = parseBetween(action, "sourceid(", ")");
if (splitAction.size())
{
@@ -43,6 +41,14 @@ AIHint::AIHint(string _line)
{
castOrder = split(splitCastOrder[1],',');
}
if(action.find( "combo ") != string::npos)
{
string Combo = "";
Combo = action.c_str() + 6;
combos.push_back(Combo);
}
}
AIHints::AIHints(AIPlayerBaka * player): mPlayer(player)
@@ -94,6 +100,141 @@ bool AIHints::HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card)
return false;
}
bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card)
{
TargetChooserFactory tfc(observer);
TargetChooser * hintTc = NULL;
bool forCombo = false;
for(unsigned int i = 0; i < hints.size();i++)
{
if (hints[i]->combos.size())
{
//time to find the parts and condiations of the combo.
string part = "";
if(!hints[i]->partOfCombo.size() && hints[i]->combos.size())
{
for(unsigned int cPart = 0; cPart < hints[i]->combos.size(); cPart++)
{
//here we disect the different parts of a given combo
part = hints[i]->combos[cPart];
hints[i]->partOfCombo = split(part,'^');
for(unsigned int dPart = 0; dPart < hints[i]->partOfCombo.size(); dPart++)
{
vector<string>asTc;
asTc = parseBetween(hints[i]->partOfCombo[dPart],"hold(",")");
if(asTc.size())
{
hints[i]->hold.push_back(asTc[1]);
asTc.clear();
}
asTc = parseBetween(hints[i]->partOfCombo[dPart],"until(",")");
if(asTc.size())
{
hints[i]->until.push_back(asTc[1]);
asTc.clear();
}
asTc = parseBetween(hints[i]->partOfCombo[dPart],"restriction{","}");
if(asTc.size())
{
hints[i]->restrict.push_back(asTc[1]);
asTc.clear();
}
asTc = parseBetween(hints[i]->partOfCombo[dPart],"cast(",")");
if(asTc.size())
{
hints[i]->cardTargets[asTc[1]] = parseBetween(hints[i]->partOfCombo[dPart],"targeting(",")")[1];
}
asTc = parseBetween(hints[i]->partOfCombo[dPart],"totalmananeeded(",")");
if(asTc.size())
{
hints[i]->manaNeeded = asTc[1];
asTc.clear();
}
}
}
}//we collect the peices of a combo on first run.
for(unsigned int hPart = 0; hPart < hints[i]->hold.size(); hPart++)
{
hintTc = tfc.createTargetChooser(hints[i]->hold[hPart],card);
if(hintTc && hintTc->canTarget(card,true) && hintTc->countValidTargets() <= hintTc->maxtargets)
{
forCombo = true;
}
SAFE_DELETE(hintTc);
}
}
}
return forCombo;//return forCombo that way all hints that are combos are predisected.
}
//if it's not part of a combo or there is more to gather, then return false
bool AIHints::canWeCombo(GameObserver* observer,MTGCardInstance * card,AIPlayerBaka * Ai)
{
TargetChooserFactory tfc(observer);
TargetChooser * hintTc = NULL;
bool gotCombo = false;
int comboPartsHold = 0;
int comboPartsUntil = 0;
int comboPartsRestriction = 0;
for(unsigned int i = 0; i < hints.size();i++)
{
comboPartsHold = 0;
comboPartsUntil = 0;
comboPartsRestriction = 0;
if(gotCombo)
return gotCombo;//because more then one might be possible at any time.
if (hints[i]->hold.size())
{
for(unsigned int hPart = 0; hPart < hints[i]->hold.size(); hPart++)
{
hintTc = tfc.createTargetChooser(hints[i]->hold[hPart],card);
int TcCheck = hintTc->countValidTargets();
if(hintTc && TcCheck >= hintTc->maxtargets)
{
comboPartsHold +=1;
}
SAFE_DELETE(hintTc);
}
}
if (hints[i]->until.size())
{
for(unsigned int hPart = 0; hPart < hints[i]->until.size(); hPart++)
{
hintTc = tfc.createTargetChooser(hints[i]->until[hPart],card);
int TcCheck = hintTc->countValidTargets();
if(hintTc && TcCheck >= hintTc->maxtargets)
{
comboPartsUntil +=1;
}
SAFE_DELETE(hintTc);
}
}
if (hints[i]->restrict.size())
{
for(unsigned int hPart = 0; hPart < hints[i]->restrict.size(); hPart++)
{
AbilityFactory af(observer);
int checkCond = af.parseCastRestrictions(card,card->controller(),hints[i]->restrict[hPart]);
if(checkCond >= 1)
{
comboPartsRestriction +=1;
}
}
}
if( comboPartsUntil >= int(hints[i]->until.size()) && comboPartsHold >= int(hints[i]->hold.size()) && comboPartsRestriction >= int(hints[i]->restrict.size()) && hints[i]->combos.size() )
{
ManaCost * needed = ManaCost::parseManaCost(hints[i]->manaNeeded, NULL, card);
if(Ai->canPayManaCost(card,needed).size()||!needed->getConvertedCost())
{
gotCombo = true;
Ai->comboHint = hints[i];//set the combo we are doing.
}
SAFE_DELETE(needed);
}
}
return gotCombo;
}
vector<string>AIHints::mCastOrder()
{
for(unsigned int i = 0; i < hints.size();i++)