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:
@@ -7,6 +7,7 @@ using std::string;
|
|||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
#include "AIPlayerBaka.h"
|
#include "AIPlayerBaka.h"
|
||||||
|
#include "AllAbilities.h"
|
||||||
|
|
||||||
class ManaCost;
|
class ManaCost;
|
||||||
class MTGAbility;
|
class MTGAbility;
|
||||||
@@ -18,6 +19,14 @@ public:
|
|||||||
string mAction;
|
string mAction;
|
||||||
string mCombatAttackTip;
|
string mCombatAttackTip;
|
||||||
vector<string>castOrder;
|
vector<string>castOrder;
|
||||||
|
vector<string>combos;
|
||||||
|
//for preformance we disect the combo on first run.
|
||||||
|
vector<string>partOfCombo;
|
||||||
|
vector<string>hold;
|
||||||
|
vector<string>until;
|
||||||
|
vector<string>restrict;
|
||||||
|
map<string,string>cardTargets;
|
||||||
|
string manaNeeded;
|
||||||
int mSourceId;
|
int mSourceId;
|
||||||
AIHint(string line);
|
AIHint(string line);
|
||||||
};
|
};
|
||||||
@@ -39,6 +48,8 @@ public:
|
|||||||
AIHints (AIPlayerBaka * player);
|
AIHints (AIPlayerBaka * player);
|
||||||
AIAction * suggestAbility(ManaCost * potentialMana);
|
AIAction * suggestAbility(ManaCost * potentialMana);
|
||||||
bool HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card = NULL);
|
bool HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card = NULL);
|
||||||
|
bool HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card = NULL);
|
||||||
|
bool canWeCombo(GameObserver* observer,MTGCardInstance * card = NULL,AIPlayerBaka * Ai = NULL);
|
||||||
vector<string> mCastOrder();
|
vector<string> mCastOrder();
|
||||||
void add(string line);
|
void add(string line);
|
||||||
~AIHints();
|
~AIHints();
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
class AIStats;
|
class AIStats;
|
||||||
class AIHints;
|
class AIHints;
|
||||||
|
class AIHint;
|
||||||
|
|
||||||
|
|
||||||
//Would love to define those classes as private nested classes inside of AIPlayerBaka, but they are used by AIHints (which itself should be known only by AIPlayerBaka anyways)
|
//Would love to define those classes as private nested classes inside of AIPlayerBaka, but they are used by AIHints (which itself should be known only by AIPlayerBaka anyways)
|
||||||
@@ -91,11 +92,14 @@ class AIPlayerBaka: public AIPlayer{
|
|||||||
virtual AIStats * getStats();
|
virtual AIStats * getStats();
|
||||||
|
|
||||||
MTGCardInstance * nextCardToPlay;
|
MTGCardInstance * nextCardToPlay;
|
||||||
|
MTGCardInstance * activateCombo();
|
||||||
|
TargetChooser * GetComboTc(GameObserver * observer, TargetChooser * tc = NULL);
|
||||||
AIHints * hints;
|
AIHints * hints;
|
||||||
AIStats * stats;
|
AIStats * stats;
|
||||||
int oldGamePhase;
|
int oldGamePhase;
|
||||||
float timer;
|
float timer;
|
||||||
virtual MTGCardInstance * FindCardToPlay(ManaCost * potentialMana, const char * type);
|
virtual MTGCardInstance * FindCardToPlay(ManaCost * potentialMana, const char * type);
|
||||||
|
vector<MTGCardInstance*>comboCards;
|
||||||
|
|
||||||
//used by MomirPlayer, hence protected instead of private
|
//used by MomirPlayer, hence protected instead of private
|
||||||
virtual int getEfficiency(OrderedAIAction * action);
|
virtual int getEfficiency(OrderedAIAction * action);
|
||||||
@@ -115,7 +119,9 @@ class AIPlayerBaka: public AIPlayer{
|
|||||||
};
|
};
|
||||||
|
|
||||||
vector<MTGAbility*>gotPayments;
|
vector<MTGAbility*>gotPayments;
|
||||||
|
|
||||||
AIPlayerBaka(GameObserver *observer, string deckFile, string deckfileSmall, string avatarFile, MTGDeck * deck = NULL);
|
AIPlayerBaka(GameObserver *observer, string deckFile, string deckfileSmall, string avatarFile, MTGDeck * deck = NULL);
|
||||||
|
AIHint * comboHint;
|
||||||
virtual int Act(float dt);
|
virtual int Act(float dt);
|
||||||
void initTimer();
|
void initTimer();
|
||||||
virtual int computeActions();
|
virtual int computeActions();
|
||||||
@@ -125,6 +131,7 @@ class AIPlayerBaka: public AIPlayer{
|
|||||||
virtual int affectCombatDamages(CombatStep step);
|
virtual int affectCombatDamages(CombatStep step);
|
||||||
virtual int canHandleCost(MTGAbility * ability);
|
virtual int canHandleCost(MTGAbility * ability);
|
||||||
virtual int chooseTarget(TargetChooser * tc = NULL, Player * forceTarget = NULL,MTGCardInstance * Chosencard = NULL,bool checkonly = false);
|
virtual int chooseTarget(TargetChooser * tc = NULL, Player * forceTarget = NULL,MTGCardInstance * Chosencard = NULL,bool checkonly = false);
|
||||||
|
virtual vector<MTGAbility*> canPayManaCost(MTGCardInstance * card = NULL, ManaCost * mCost = NULL){ return canPayMana(card, mCost);};
|
||||||
|
|
||||||
//used by AIHInts, therefore public instead of private :/
|
//used by AIHInts, therefore public instead of private :/
|
||||||
virtual int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
virtual int createAbilityTargets(MTGAbility * a, MTGCardInstance * c, RankingContainer& ranking);
|
||||||
|
|||||||
@@ -4360,7 +4360,7 @@ public:
|
|||||||
MTGAbility(observer, id, _source)
|
MTGAbility(observer, id, _source)
|
||||||
{
|
{
|
||||||
counters = 0;
|
counters = 0;
|
||||||
std::vector<int8_t> _cost;
|
std::vector<int16_t> _cost;
|
||||||
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
_cost.push_back(4);
|
_cost.push_back(4);
|
||||||
cost = ManaCost(_cost, 1);
|
cost = ManaCost(_cost, 1);
|
||||||
@@ -4424,7 +4424,7 @@ public:
|
|||||||
MTGAbility(observer, _id, _source)
|
MTGAbility(observer, _id, _source)
|
||||||
{
|
{
|
||||||
canprevent = 0;
|
canprevent = 0;
|
||||||
std::vector<int8_t> _cost;
|
std::vector<int16_t> _cost;
|
||||||
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
_cost.push_back(2);
|
_cost.push_back(2);
|
||||||
cost = ManaCost(_cost, 1);
|
cost = ManaCost(_cost, 1);
|
||||||
@@ -4520,7 +4520,7 @@ public:
|
|||||||
AFarmstead(GameObserver* observer, int _id, MTGCardInstance * source, MTGCardInstance * _target) :
|
AFarmstead(GameObserver* observer, int _id, MTGCardInstance * source, MTGCardInstance * _target) :
|
||||||
ActivatedAbility(observer, _id, source, 0, 1)
|
ActivatedAbility(observer, _id, source, 0, 1)
|
||||||
{
|
{
|
||||||
std::vector<int8_t> _cost;
|
std::vector<int16_t> _cost;
|
||||||
_cost.push_back(Constants::MTG_COLOR_WHITE);
|
_cost.push_back(Constants::MTG_COLOR_WHITE);
|
||||||
_cost.push_back(2);
|
_cost.push_back(2);
|
||||||
setCost(NEW ManaCost(_cost, 1), true);
|
setCost(NEW ManaCost(_cost, 1), true);
|
||||||
|
|||||||
@@ -66,9 +66,15 @@ public:
|
|||||||
static void ThreadProc(void* inParam);
|
static void ThreadProc(void* inParam);
|
||||||
void handleResults(GameObserver* aGame){
|
void handleResults(GameObserver* aGame){
|
||||||
mMutex.lock();
|
mMutex.lock();
|
||||||
totalTestGames++;
|
|
||||||
if (aGame->didWin(aGame->players[1]))
|
if (aGame->didWin(aGame->players[1]))
|
||||||
|
{
|
||||||
testPlayer2Victories++;
|
testPlayer2Victories++;
|
||||||
|
totalTestGames++;
|
||||||
|
}
|
||||||
|
else if( aGame->didWin(aGame->players[0]))
|
||||||
|
{
|
||||||
|
totalTestGames++;
|
||||||
|
}
|
||||||
mMutex.unlock();
|
mMutex.unlock();
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class ManaCost
|
|||||||
friend std::ostream& operator<<(std::ostream& out, ManaCost m);
|
friend std::ostream& operator<<(std::ostream& out, ManaCost m);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
std::vector<ManaCostHybrid> hybrids;
|
std::vector<ManaCostHybrid> hybrids;
|
||||||
|
|
||||||
virtual void init();
|
virtual void init();
|
||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
int hasSpecificX();
|
int hasSpecificX();
|
||||||
int xColor;
|
int xColor;
|
||||||
int hasAnotherCost();
|
int hasAnotherCost();
|
||||||
ManaCost(std::vector<int8_t>& _cost, int nb_elems = 1);
|
ManaCost(std::vector<int16_t>& _cost, int nb_elems = 1);
|
||||||
ManaCost();
|
ManaCost();
|
||||||
~ManaCost();
|
~ManaCost();
|
||||||
ManaCost(ManaCost * _manaCost);
|
ManaCost(ManaCost * _manaCost);
|
||||||
@@ -89,8 +89,8 @@ public:
|
|||||||
ExtraCost * getExtraCost(unsigned int i);
|
ExtraCost * getExtraCost(unsigned int i);
|
||||||
|
|
||||||
int addHybrid(int c1, int v1, int c2, int v2);
|
int addHybrid(int c1, int v1, int c2, int v2);
|
||||||
int tryToPayHybrids(std::vector<ManaCostHybrid>& _hybrids, int _nbhybrids,std::vector<int8_t>& diff);
|
int tryToPayHybrids(std::vector<ManaCostHybrid>& _hybrids, int _nbhybrids,std::vector<int16_t>& diff);
|
||||||
void randomDiffHybrids(ManaCost * _cost, std::vector<int8_t>& diff);
|
void randomDiffHybrids(ManaCost * _cost, std::vector<int16_t>& diff);
|
||||||
int add(ManaCost * _cost);
|
int add(ManaCost * _cost);
|
||||||
int remove(ManaCost * _cost);
|
int remove(ManaCost * _cost);
|
||||||
int removeAll(int color);
|
int removeAll(int color);
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ AIHint::AIHint(string _line)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
|
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
|
||||||
vector<string> parameters = split(line,':');
|
mCondition = line;
|
||||||
mCondition = (parameters.size() == 1)? "" : parameters[0];
|
string action = line;
|
||||||
string action = parameters[parameters.size() - 1];
|
|
||||||
|
|
||||||
vector<string> splitAction = parseBetween(action, "sourceid(", ")");
|
vector<string> splitAction = parseBetween(action, "sourceid(", ")");
|
||||||
if (splitAction.size())
|
if (splitAction.size())
|
||||||
{
|
{
|
||||||
@@ -43,6 +41,14 @@ AIHint::AIHint(string _line)
|
|||||||
{
|
{
|
||||||
castOrder = split(splitCastOrder[1],',');
|
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)
|
AIHints::AIHints(AIPlayerBaka * player): mPlayer(player)
|
||||||
@@ -94,6 +100,141 @@ bool AIHints::HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card)
|
|||||||
return false;
|
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()
|
vector<string>AIHints::mCastOrder()
|
||||||
{
|
{
|
||||||
for(unsigned int i = 0; i < hints.size();i++)
|
for(unsigned int i = 0; i < hints.size();i++)
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ int AIMomirPlayer::momir()
|
|||||||
if (efficiency >= chance)
|
if (efficiency >= chance)
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<int8_t> _cost;
|
std::vector<int16_t> _cost;
|
||||||
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
_cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
_cost.push_back(converted);
|
_cost.push_back(converted);
|
||||||
ManaCost * cost = NEW ManaCost(_cost);
|
ManaCost * cost = NEW ManaCost(_cost);
|
||||||
|
|||||||
@@ -242,6 +242,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards *
|
|||||||
// AIPlayerBaka will delete MTGDeck when it's time
|
// AIPlayerBaka will delete MTGDeck when it's time
|
||||||
AIPlayerBaka * baka = NEW AIPlayerBaka(observer, deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting));
|
AIPlayerBaka * baka = NEW AIPlayerBaka(observer, deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting));
|
||||||
baka->deckId = deckid;
|
baka->deckId = deckid;
|
||||||
|
baka->comboHint = NULL;
|
||||||
return baka;
|
return baka;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -645,6 +645,10 @@ int AIPlayerBaka::getEfficiency(OrderedAIAction * action)
|
|||||||
MTGCardInstance * AIPlayerBaka::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random)
|
MTGCardInstance * AIPlayerBaka::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random)
|
||||||
{
|
{
|
||||||
MTGPlayerCards * playerZones = source->controller()->game;
|
MTGPlayerCards * playerZones = source->controller()->game;
|
||||||
|
if (comboHint && comboHint->cardTargets.size())
|
||||||
|
{
|
||||||
|
tc = GetComboTc(observer,tc);
|
||||||
|
}
|
||||||
for(int players = 0; players < 2;++players)
|
for(int players = 0; players < 2;++players)
|
||||||
{
|
{
|
||||||
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack };
|
MTGGameZone * zones[] = { playerZones->hand, playerZones->library, playerZones->inPlay, playerZones->graveyard,playerZones->stack };
|
||||||
@@ -654,11 +658,9 @@ MTGCardInstance * AIPlayerBaka::chooseCard(TargetChooser * tc, MTGCardInstance *
|
|||||||
for (int k = 0; k < zone->nb_cards; k++)
|
for (int k = 0; k < zone->nb_cards; k++)
|
||||||
{
|
{
|
||||||
MTGCardInstance * card = zone->cards[k];
|
MTGCardInstance * card = zone->cards[k];
|
||||||
if (card != source && !tc->alreadyHasTarget(card) && tc->canTarget(card))
|
if (card != source && card != tc->source && !tc->alreadyHasTarget(card) && tc->canTarget(card))
|
||||||
{
|
{
|
||||||
|
|
||||||
return card;
|
return card;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -681,6 +683,8 @@ bool AIPlayerBaka::payTheManaCost(ManaCost * cost, MTGCardInstance * target,vect
|
|||||||
}
|
}
|
||||||
|
|
||||||
ExtraCosts * ec = cost->extraCosts;
|
ExtraCosts * ec = cost->extraCosts;
|
||||||
|
if(!ec && observer->mExtraPayment)
|
||||||
|
ec = observer->mExtraPayment;
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < ec->costs.size(); ++i)
|
for (size_t i = 0; i < ec->costs.size(); ++i)
|
||||||
@@ -1206,6 +1210,10 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
ranking[aiAction] = 1;
|
ranking[aiAction] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
if (comboHint && comboHint->cardTargets.size())
|
||||||
|
{
|
||||||
|
a->setActionTC(GetComboTc(observer,a->getActionTc()));
|
||||||
|
}
|
||||||
vector<Targetable*>potentialTargets;
|
vector<Targetable*>potentialTargets;
|
||||||
for (int i = 0; i < 2; i++)
|
for (int i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
@@ -1284,6 +1292,37 @@ int AIPlayerBaka::createAbilityTargets(MTGAbility * a, MTGCardInstance * c, Rank
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TargetChooser * AIPlayerBaka::GetComboTc( GameObserver * observer,TargetChooser * tc)
|
||||||
|
{
|
||||||
|
TargetChooser * gathertc = NULL;
|
||||||
|
TargetChooserFactory tcf(observer);
|
||||||
|
map<string, string>::iterator it = comboHint->cardTargets.begin();
|
||||||
|
for(map<string, string>::iterator it = comboHint->cardTargets.begin();it != comboHint->cardTargets.end();it++)
|
||||||
|
{
|
||||||
|
gathertc = tcf.createTargetChooser(it->first.c_str(),tc->source);
|
||||||
|
gathertc->setAllZones();
|
||||||
|
if(gathertc->canTarget(tc->source))
|
||||||
|
{
|
||||||
|
MTGCardInstance * cardBackUp = tc->source;
|
||||||
|
Player * Oowner = tc->Owner;
|
||||||
|
TargetChooser * testTc = tcf.createTargetChooser(it->second.c_str(),cardBackUp);
|
||||||
|
if(testTc->countValidTargets())
|
||||||
|
{
|
||||||
|
tc = testTc;
|
||||||
|
tc->Owner = Oowner;
|
||||||
|
tc->other = true;
|
||||||
|
}
|
||||||
|
//I know I shouldn't redefine a passed variable,
|
||||||
|
//if anyone knows a way that doesn't add a major function for this that does this correctly
|
||||||
|
//then feel free to change this redefine. I do it this way becuase the method is the
|
||||||
|
//fastest I could find that doesn't produce a noticible lag on ai.
|
||||||
|
//recreate the targetchooser for this card becuase we planned to use it in a combo
|
||||||
|
}
|
||||||
|
SAFE_DELETE(gathertc);
|
||||||
|
}
|
||||||
|
return tc;
|
||||||
|
}
|
||||||
|
|
||||||
int AIPlayerBaka::selectHintAbility()
|
int AIPlayerBaka::selectHintAbility()
|
||||||
{
|
{
|
||||||
if (!hints)
|
if (!hints)
|
||||||
@@ -1312,6 +1351,7 @@ int AIPlayerBaka::selectHintAbility()
|
|||||||
|
|
||||||
int AIPlayerBaka::selectAbility()
|
int AIPlayerBaka::selectAbility()
|
||||||
{
|
{
|
||||||
|
observer->mExtraPayment = NULL;
|
||||||
// Try Deck hints first
|
// Try Deck hints first
|
||||||
if (selectHintAbility())
|
if (selectHintAbility())
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1428,6 +1468,9 @@ int AIPlayerBaka::effectBadOrGood(MTGCardInstance * card, int mode, TargetChoose
|
|||||||
|
|
||||||
int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCardInstance * chosenCard,bool checkOnly)
|
int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCardInstance * chosenCard,bool checkOnly)
|
||||||
{
|
{
|
||||||
|
observer->mExtraPayment = NULL;
|
||||||
|
//there should never be a case where a extra cost target selection is happening at the same time as this..
|
||||||
|
//extracost uses "chooseCard()" to determine its targets.
|
||||||
vector<Targetable *> potentialTargets;
|
vector<Targetable *> potentialTargets;
|
||||||
TargetChooser * tc = _tc;
|
TargetChooser * tc = _tc;
|
||||||
if (!(observer->currentlyActing() == this))
|
if (!(observer->currentlyActing() == this))
|
||||||
@@ -1439,6 +1482,10 @@ int AIPlayerBaka::chooseTarget(TargetChooser * _tc, Player * forceTarget,MTGCard
|
|||||||
if (!tc || !tc->source || tc->maxtargets < 1)
|
if (!tc || !tc->source || tc->maxtargets < 1)
|
||||||
return 0;
|
return 0;
|
||||||
assert(tc);
|
assert(tc);
|
||||||
|
if (comboHint && comboHint->cardTargets.size())
|
||||||
|
{
|
||||||
|
tc = GetComboTc(observer,tc);
|
||||||
|
}
|
||||||
if(!checkOnly && tc->maxtargets > 1)
|
if(!checkOnly && tc->maxtargets > 1)
|
||||||
{
|
{
|
||||||
tc->initTargets();//just incase....
|
tc->initTargets();//just incase....
|
||||||
@@ -1641,6 +1688,14 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
|||||||
int maxCost = -1;
|
int maxCost = -1;
|
||||||
MTGCardInstance * nextCardToPlay = NULL;
|
MTGCardInstance * nextCardToPlay = NULL;
|
||||||
MTGCardInstance * card = NULL;
|
MTGCardInstance * card = NULL;
|
||||||
|
if(comboCards.size())
|
||||||
|
{
|
||||||
|
nextCardToPlay = comboCards.back();
|
||||||
|
comboCards.pop_back();
|
||||||
|
if(!comboHint->cardTargets.size() && !comboCards.size())
|
||||||
|
comboHint = NULL;//becuase it's no longer needed.
|
||||||
|
return nextCardToPlay;
|
||||||
|
}
|
||||||
CardDescriptor cd;
|
CardDescriptor cd;
|
||||||
cd.init();
|
cd.init();
|
||||||
cd.setType(type);
|
cd.setType(type);
|
||||||
@@ -1668,7 +1723,24 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
|||||||
if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1]))
|
if (card->hasType(Subtypes::TYPE_PLANESWALKER) && card->types.size() > 0 && game->inPlay->hasTypeSpecificInt(Subtypes::TYPE_PLANESWALKER,card->types[1]))
|
||||||
continue;
|
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;
|
||||||
|
return activateCombo();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int chance = int(getRandomGenerator()->random() % 100);
|
||||||
|
if(chance > 1)
|
||||||
|
continue;//1% chance to just continue evaluating the card to cast.
|
||||||
|
}
|
||||||
|
}
|
||||||
int currentCost = card->getManaCost()->getConvertedCost();
|
int currentCost = card->getManaCost()->getConvertedCost();
|
||||||
int hasX = card->getManaCost()->hasX();
|
int hasX = card->getManaCost()->hasX();
|
||||||
gotPayments.clear();
|
gotPayments.clear();
|
||||||
@@ -1780,6 +1852,41 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
|||||||
return nextCardToPlay;
|
return nextCardToPlay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MTGCardInstance * AIPlayerBaka::activateCombo()
|
||||||
|
{
|
||||||
|
if(!comboHint)
|
||||||
|
return NULL;
|
||||||
|
TargetChooser * hintTc = NULL;
|
||||||
|
TargetChooserFactory tfc(observer);
|
||||||
|
ManaCost * totalCost = ManaCost::parseManaCost(comboHint->manaNeeded);
|
||||||
|
for(unsigned int k = 0;k < comboHint->hold.size(); k++)
|
||||||
|
{
|
||||||
|
hintTc = tfc.createTargetChooser(comboHint->hold[k],nextCardToPlay);
|
||||||
|
for(unsigned int j = 0; j < game->hand->cards.size();j++)
|
||||||
|
{
|
||||||
|
if(!hintTc)
|
||||||
|
break;
|
||||||
|
if(hintTc->canTarget(game->hand->cards[j]))
|
||||||
|
{
|
||||||
|
comboCards.push_back(game->hand->cards[j]);
|
||||||
|
SAFE_DELETE(hintTc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_DELETE(hintTc);
|
||||||
|
}
|
||||||
|
if(payTheManaCost(totalCost,nextCardToPlay,gotPayments))
|
||||||
|
{
|
||||||
|
if(comboCards.size())
|
||||||
|
{
|
||||||
|
nextCardToPlay = comboCards.back();
|
||||||
|
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
|
return NULL;
|
||||||
|
comboCards.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SAFE_DELETE(totalCost);
|
||||||
|
return nextCardToPlay;
|
||||||
|
}
|
||||||
|
|
||||||
void AIPlayerBaka::initTimer()
|
void AIPlayerBaka::initTimer()
|
||||||
{
|
{
|
||||||
@@ -1910,9 +2017,8 @@ int AIPlayerBaka::computeActions()
|
|||||||
currentMana->add(this->getManaPool());
|
currentMana->add(this->getManaPool());
|
||||||
|
|
||||||
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
nextCardToPlay = FindCardToPlay(currentMana, "land");
|
||||||
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
if (nextCardToPlay && nextCardToPlay->isLand() && game->playRestrictions->canPutIntoZone(nextCardToPlay, game->battlefield) == PlayRestriction::CANT_PLAY)
|
||||||
nextCardToPlay = NULL;//look for a land, did we find one we can play..if not set to null now.
|
nextCardToPlay = NULL;//look for a land, did we find one we can play..if not set to null now.
|
||||||
|
|
||||||
if(hints && hints->mCastOrder().size())
|
if(hints && hints->mCastOrder().size())
|
||||||
{
|
{
|
||||||
vector<string>findType = hints->mCastOrder();
|
vector<string>findType = hints->mCastOrder();
|
||||||
@@ -1928,6 +2034,8 @@ int AIPlayerBaka::computeActions()
|
|||||||
nextCardToPlay = FindCardToPlay(currentMana, findType[j].c_str());
|
nextCardToPlay = FindCardToPlay(currentMana, findType[j].c_str());
|
||||||
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
nextCardToPlay = NULL;
|
nextCardToPlay = NULL;
|
||||||
|
if (nextCardToPlay && nextCardToPlay->isLand() && game->playRestrictions->canPutIntoZone(nextCardToPlay, game->battlefield) == PlayRestriction::CANT_PLAY)
|
||||||
|
nextCardToPlay = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1945,6 +2053,8 @@ int AIPlayerBaka::computeActions()
|
|||||||
nextCardToPlay = FindCardToPlay(currentMana, types[count]);
|
nextCardToPlay = FindCardToPlay(currentMana, types[count]);
|
||||||
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
if (game->playRestrictions->canPutIntoZone(nextCardToPlay, game->stack) == PlayRestriction::CANT_PLAY)
|
||||||
nextCardToPlay = NULL;
|
nextCardToPlay = NULL;
|
||||||
|
if (nextCardToPlay && nextCardToPlay->isLand() && game->playRestrictions->canPutIntoZone(nextCardToPlay, game->battlefield) == PlayRestriction::CANT_PLAY)
|
||||||
|
nextCardToPlay = NULL;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1978,6 +2088,11 @@ int AIPlayerBaka::computeActions()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(observer->mExtraPayment)
|
||||||
|
//no extra payment should be waiting before selecting an ability.
|
||||||
|
observer->mExtraPayment = NULL;
|
||||||
|
//this is a fix for a rare bug that somehow ai trips over an extra payment without paying
|
||||||
|
//then locks in a loop of trying to choose something different to do and trying to pay the extra payment.
|
||||||
selectAbility();
|
selectAbility();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -293,18 +293,20 @@ void GameStateDuel::ThreadProc(void* inParam)
|
|||||||
int oldTurn = -1;
|
int oldTurn = -1;
|
||||||
int oldPhase = -1;
|
int oldPhase = -1;
|
||||||
int stagnationCounter = -1;
|
int stagnationCounter = -1;
|
||||||
|
|
||||||
observer.loadPlayer(0, PLAYER_TYPE_CPU_TEST);
|
observer.loadPlayer(0, PLAYER_TYPE_CPU_TEST);
|
||||||
observer.loadPlayer(1, PLAYER_TYPE_CPU_TEST);
|
observer.loadPlayer(1, PLAYER_TYPE_CPU_TEST);
|
||||||
observer.startGame(instance->mParent->gameType, instance->mParent->rules);
|
observer.startGame(instance->mParent->gameType, instance->mParent->rules);
|
||||||
|
while(!observer.didWin())
|
||||||
while(!observer.didWin()) {
|
{
|
||||||
if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase) {
|
if(observer.turn == oldTurn && observer.currentGamePhase == oldPhase)
|
||||||
|
{
|
||||||
stagnationCounter++;
|
stagnationCounter++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
stagnationCounter = 0;
|
stagnationCounter = 0;
|
||||||
oldTurn = observer.turn;
|
oldTurn = observer.turn;
|
||||||
oldPhase = observer.currentGamePhase;
|
oldPhase = observer.getCurrentGamePhase();
|
||||||
}
|
}
|
||||||
if(stagnationCounter >= 1000)
|
if(stagnationCounter >= 1000)
|
||||||
{
|
{
|
||||||
@@ -606,7 +608,7 @@ void GameStateDuel::Render()
|
|||||||
if (totalTestGames < 2.5 * totalAIDecks)
|
if (totalTestGames < 2.5 * totalAIDecks)
|
||||||
{
|
{
|
||||||
mFont->SetColor(ARGB(255,255,255,0));
|
mFont->SetColor(ARGB(255,255,255,0));
|
||||||
sprintf(buf, "Results are not significant, you should let at least %i more games run", (int)(totalAIDecks * 2.5) - totalTestGames);
|
sprintf(buf, " Results are not significant, you should let at least %i more games run", (int)(totalAIDecks * 2.5) - totalTestGames);
|
||||||
mFont->DrawString(buf,0,SCREEN_HEIGHT/2 - 20);
|
mFont->DrawString(buf,0,SCREEN_HEIGHT/2 - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -616,8 +618,8 @@ void GameStateDuel::Render()
|
|||||||
mFont->SetColor(ARGB(255,255,0,0));
|
mFont->SetColor(ARGB(255,255,0,0));
|
||||||
if (ratio > 0.52)
|
if (ratio > 0.52)
|
||||||
mFont->SetColor(ARGB(255,0,255,0));
|
mFont->SetColor(ARGB(255,0,255,0));
|
||||||
sprintf(buf, "Victories Player 2/total Games: %i/%i - Games/second: %f",
|
sprintf(buf, " Victories Player 2/total Games: %i/%i - Game Turn: %i",
|
||||||
testPlayer2Victories, totalTestGames, (float)(1000*totalTestGames)/(currentTime - startTime));
|
testPlayer2Victories, totalTestGames, /*(float)(1000*totalTestGames)/(currentTime - startTime)*/game->turn);
|
||||||
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
|
mFont->DrawString(buf,0,SCREEN_HEIGHT/2);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -289,6 +289,18 @@ void GuiMana::RenderStatic()
|
|||||||
|
|
||||||
void GuiMana::Render()
|
void GuiMana::Render()
|
||||||
{
|
{
|
||||||
|
if (manas.size() > 20)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (vector<ManaIcon*>::iterator it = manas.begin(); it != manas.end(); ++it)
|
||||||
|
{
|
||||||
|
if (count > 20)
|
||||||
|
break;
|
||||||
|
count++;
|
||||||
|
(*it)->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
for (vector<ManaIcon*>::iterator it = manas.begin(); it != manas.end(); ++it)
|
for (vector<ManaIcon*>::iterator it = manas.begin(); it != manas.end(); ++it)
|
||||||
(*it)->Render();
|
(*it)->Render();
|
||||||
|
|
||||||
|
|||||||
@@ -3490,7 +3490,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
case 1103: //Crystal Rod
|
case 1103: //Crystal Rod
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
cost.push_back(1);
|
cost.push_back(1);
|
||||||
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_BLUE, NEW ManaCost(cost, 1), 1);
|
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_BLUE, NEW ManaCost(cost, 1), 1);
|
||||||
@@ -3525,7 +3525,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
case 1113: //Iron Star
|
case 1113: //Iron Star
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
cost.push_back(1);
|
cost.push_back(1);
|
||||||
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_RED, NEW ManaCost(cost, 1), 1);
|
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_RED, NEW ManaCost(cost, 1), 1);
|
||||||
@@ -3539,7 +3539,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
}
|
}
|
||||||
case 1114: //Ivory cup
|
case 1114: //Ivory cup
|
||||||
{
|
{
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
cost.push_back(1);
|
cost.push_back(1);
|
||||||
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_WHITE, NEW ManaCost(cost, 1), 1);
|
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_WHITE, NEW ManaCost(cost, 1), 1);
|
||||||
@@ -3614,7 +3614,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
|
|
||||||
case 1140: //Throne of Bone
|
case 1140: //Throne of Bone
|
||||||
{
|
{
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
cost.push_back(1);
|
cost.push_back(1);
|
||||||
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_BLACK, NEW ManaCost(cost, 1), 1);
|
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_BLACK, NEW ManaCost(cost, 1), 1);
|
||||||
@@ -3624,7 +3624,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
|
|||||||
|
|
||||||
case 1142: //Wooden Sphere
|
case 1142: //Wooden Sphere
|
||||||
{
|
{
|
||||||
std::vector<int8_t> cost;
|
std::vector<int16_t> cost;
|
||||||
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
cost.push_back(Constants::MTG_COLOR_ARTIFACT);
|
||||||
cost.push_back(1);
|
cost.push_back(1);
|
||||||
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_GREEN, NEW ManaCost(cost, 1), 1);
|
ASpellCastLife* ability = NEW ASpellCastLife(observer, _id, card, Constants::MTG_COLOR_GREEN, NEW ManaCost(cost, 1), 1);
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ ManaCost::ManaCost()
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
ManaCost::ManaCost(vector<int8_t>& _cost, int nb_elems)
|
ManaCost::ManaCost(vector<int16_t>& _cost, int nb_elems)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
for (int i = 0; i < nb_elems; i++)
|
for (int i = 0; i < nb_elems; i++)
|
||||||
@@ -628,7 +628,7 @@ int ManaCost::getConvertedCost()
|
|||||||
int ManaCost::remove(int color, int value)
|
int ManaCost::remove(int color, int value)
|
||||||
{
|
{
|
||||||
assert (value >= 0);
|
assert (value >= 0);
|
||||||
int8_t toRemove = min(cost[color], (int8_t)value);
|
int16_t toRemove = min(cost[color], (int16_t)value);
|
||||||
cost[color] -= toRemove;
|
cost[color] -= toRemove;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -661,7 +661,7 @@ int ManaCost::remove(ManaCost * _cost)
|
|||||||
return 0;
|
return 0;
|
||||||
for ( int i = 0; i < Constants::NB_Colors; i++)
|
for ( int i = 0; i < Constants::NB_Colors; i++)
|
||||||
{
|
{
|
||||||
int8_t toRemove = min(cost[i], (int8_t)_cost->getCost(i)); //we don't want to be negative
|
int16_t toRemove = min(cost[i], (int16_t)_cost->getCost(i)); //we don't want to be negative
|
||||||
cost[i] -= toRemove;
|
cost[i] -= toRemove;
|
||||||
assert(cost[i] >= 0);
|
assert(cost[i] >= 0);
|
||||||
}
|
}
|
||||||
@@ -773,7 +773,7 @@ int ManaCost::isPositive()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManaCost::randomDiffHybrids(ManaCost * _cost, std::vector<int8_t>& diff)
|
void ManaCost::randomDiffHybrids(ManaCost * _cost, std::vector<int16_t>& diff)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < _cost->hybrids.size(); i++)
|
for (size_t i = 0; i < _cost->hybrids.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -785,7 +785,7 @@ void ManaCost::randomDiffHybrids(ManaCost * _cost, std::vector<int8_t>& diff)
|
|||||||
/**
|
/**
|
||||||
starting from the end of the array (diff)
|
starting from the end of the array (diff)
|
||||||
*/
|
*/
|
||||||
int ManaCost::tryToPayHybrids(std::vector<ManaCostHybrid>& _hybrids, int _nbhybrids, std::vector<int8_t>& diff)
|
int ManaCost::tryToPayHybrids(std::vector<ManaCostHybrid>& _hybrids, int _nbhybrids, std::vector<int16_t>& diff)
|
||||||
{
|
{
|
||||||
if (!_nbhybrids)
|
if (!_nbhybrids)
|
||||||
return 1;
|
return 1;
|
||||||
@@ -816,7 +816,7 @@ ManaCost * ManaCost::Diff(ManaCost * _cost)
|
|||||||
if (!_cost)
|
if (!_cost)
|
||||||
return NEW ManaCost(*this); //diff with null is equivalent to diff with 0
|
return NEW ManaCost(*this); //diff with null is equivalent to diff with 0
|
||||||
|
|
||||||
vector<int8_t> diff;
|
vector<int16_t> diff;
|
||||||
diff.resize((Constants::NB_Colors + 1) * 2);
|
diff.resize((Constants::NB_Colors + 1) * 2);
|
||||||
diff[Constants::NB_Colors * 2] = Constants::NB_Colors;
|
diff[Constants::NB_Colors * 2] = Constants::NB_Colors;
|
||||||
for (int i = 0; i < Constants::NB_Colors; i++)
|
for (int i = 0; i < Constants::NB_Colors; i++)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ TestSuiteAI::TestSuiteAI(TestSuiteGame *tsGame, int playerId) :
|
|||||||
timer = 0;
|
timer = 0;
|
||||||
playMode = MODE_TEST_SUITE;
|
playMode = MODE_TEST_SUITE;
|
||||||
this->deckName = "Test Suite AI";
|
this->deckName = "Test Suite AI";
|
||||||
|
this->comboHint = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MTGCardInstance * TestSuiteAI::getCard(string action)
|
MTGCardInstance * TestSuiteAI::getCard(string action)
|
||||||
|
|||||||
Reference in New Issue
Block a user