ai simple combo system is finally fully working.
added ai hint dontblockwith(targetchooser)
This commit is contained in:
@@ -18,6 +18,7 @@ public:
|
|||||||
string mCondition;
|
string mCondition;
|
||||||
string mAction;
|
string mAction;
|
||||||
string mCombatAttackTip;
|
string mCombatAttackTip;
|
||||||
|
string mCombatBlockTip;
|
||||||
vector<string>castOrder;
|
vector<string>castOrder;
|
||||||
vector<string>combos;
|
vector<string>combos;
|
||||||
//for preformance we disect the combo on first run.
|
//for preformance we disect the combo on first run.
|
||||||
@@ -25,6 +26,7 @@ public:
|
|||||||
vector<string>hold;
|
vector<string>hold;
|
||||||
vector<string>until;
|
vector<string>until;
|
||||||
vector<string>restrict;
|
vector<string>restrict;
|
||||||
|
vector<string>casting;
|
||||||
map<string,string>cardTargets;
|
map<string,string>cardTargets;
|
||||||
string manaNeeded;
|
string manaNeeded;
|
||||||
int mSourceId;
|
int mSourceId;
|
||||||
@@ -48,6 +50,7 @@ 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 HintSaysDontBlock(GameObserver* observer,MTGCardInstance * card = NULL);
|
||||||
bool HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card = NULL);
|
bool HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card = NULL);
|
||||||
bool canWeCombo(GameObserver* observer,MTGCardInstance * card = NULL,AIPlayerBaka * Ai = NULL);
|
bool canWeCombo(GameObserver* observer,MTGCardInstance * card = NULL,AIPlayerBaka * Ai = NULL);
|
||||||
vector<string> mCastOrder();
|
vector<string> mCastOrder();
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define CHOOSE_OPPONENT 7
|
#define CHOOSE_OPPONENT 7
|
||||||
|
#define NMB_PLAYERS 2 // Number of players in the game. Currently that's always 2.
|
||||||
|
|
||||||
#ifdef TESTSUITE
|
#ifdef TESTSUITE
|
||||||
class TestSuite;
|
class TestSuite;
|
||||||
@@ -22,6 +23,156 @@ class Credits;
|
|||||||
class JNetwork;
|
class JNetwork;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/////// Tournament Mod ///////////
|
||||||
|
#define PLAYER_TOURNAMENT "tournament.dat"
|
||||||
|
#define AI_TOURNAMENT "/ai/baka/tournament.dat"
|
||||||
|
#define AI_RESULTS_FILE "/ai/baka/ai_test.csv"
|
||||||
|
class TDeck{
|
||||||
|
public:
|
||||||
|
TDeck(int deck,PlayerType deckType,int victories = 0,int lastWin = 0, int wonMatches=0, int playedMatches=0, int wonGames=0, int playedGames=0);
|
||||||
|
TDeck();
|
||||||
|
~TDeck();
|
||||||
|
int getDeckNumber(){return mDeckNumber;}
|
||||||
|
void setDeckNumber(int deck){mDeckNumber=deck;}
|
||||||
|
void setDeckType(PlayerType ptype){mDeckType=ptype;}
|
||||||
|
PlayerType getDeckType(){return mDeckType;}
|
||||||
|
bool isAI(){return mDeckType==PLAYER_TYPE_CPU;}
|
||||||
|
void reset();
|
||||||
|
void increaseDeckNumber();
|
||||||
|
void winGame(){mVictories++;mLastWin++;mGamesPlayed++;mWonGames++;}
|
||||||
|
void winMatch(){mWonMatches++;mMatchesPlayed++;}
|
||||||
|
void setMatchesWon(int w){mWonMatches=w;}
|
||||||
|
int getMatchesWon(){return mWonMatches;}
|
||||||
|
void looseGame(){mLastWin = 0;mGamesPlayed++;}
|
||||||
|
void looseMatch(){mMatchesPlayed++;}
|
||||||
|
void drawMatch(){mMatchesPlayed++;}
|
||||||
|
int getLastWin(){return mLastWin;}
|
||||||
|
int getVictories(){return mVictories;}
|
||||||
|
void newMatch(){mVictories=0;mLastWin=0;}
|
||||||
|
void deleteStats(){mVictories=0;mLastWin=0;mWonMatches=0;mMatchesPlayed=0;mWonGames=0;mGamesPlayed=0;mRanking=0;}
|
||||||
|
void resetTournament(){mWonMatches=0;}
|
||||||
|
void setVictories(int v){mVictories=v;}
|
||||||
|
void setLastWin(int lastWin){mLastWin=lastWin;}
|
||||||
|
int getGamesPlayed(){return mGamesPlayed;}
|
||||||
|
void setGamesPlayed(int games){mGamesPlayed=games;}
|
||||||
|
int getGamesWon(){return mWonGames;}
|
||||||
|
void setGamesWon(int games){mWonGames=games;}
|
||||||
|
int getMatchesPlayed(){return mMatchesPlayed;}
|
||||||
|
void setMatchesPlayed(int matches){mMatchesPlayed=matches;}
|
||||||
|
void setRanking(int ranking){mRanking=ranking;}
|
||||||
|
int getRanking(){return mRanking;}
|
||||||
|
std::string getDeckName();
|
||||||
|
private:
|
||||||
|
int mDeckNumber;
|
||||||
|
PlayerType mDeckType;
|
||||||
|
int mVictories;
|
||||||
|
int mLastWin;
|
||||||
|
int mWonMatches;
|
||||||
|
int mMatchesPlayed;
|
||||||
|
int mWonGames;
|
||||||
|
int mGamesPlayed;
|
||||||
|
int mRanking;
|
||||||
|
int mDifficulty;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Tournament{
|
||||||
|
public:
|
||||||
|
Tournament();
|
||||||
|
~Tournament();
|
||||||
|
void addDeck(int player,int deck,PlayerType deckType);
|
||||||
|
void addDeck(int player,TDeck newDeck);
|
||||||
|
int getDeckNumber(int player){return Deck[player].getDeckNumber();}
|
||||||
|
PlayerType getDeckType(int player){return Deck[player].getDeckType();}
|
||||||
|
unsigned int getAvailableDecks(){return nmbDecks;}
|
||||||
|
void setAvailableDecks(unsigned int a){nmbDecks=a;}
|
||||||
|
void setGamesToPlay(int games){mNbGames=games;}
|
||||||
|
int getGamesToPlay(){return mNbGames;}
|
||||||
|
void setMatchType(int gamestoplay,int matchMode,bool swapPlayer=false){mNbGames=gamestoplay;mMatchMode=matchMode;mCompetition=swapPlayer;}
|
||||||
|
void setMatchMode(int m){mMatchMode=m;}
|
||||||
|
int getMatchMode(){return mMatchMode;}
|
||||||
|
int getTournamentMode(){return mTournamentMode;}
|
||||||
|
bool isGauntlet();
|
||||||
|
bool isEndlessDemo();
|
||||||
|
bool isTournament(){return mTournamentMode>0;}
|
||||||
|
void setTournamentMode(int b){mTournamentMode=b;}
|
||||||
|
bool getFastTimerMode(){return mFastTimerMode;}
|
||||||
|
void setFastTimerMode(bool timerMode){mFastTimerMode=timerMode;}
|
||||||
|
void updateScoreTable(Player * _p0, Player * _p1, int gt = GAME_TYPE_CLASSIC, bool gameEnd=false);
|
||||||
|
void renderScoreTable();
|
||||||
|
bool gameFinished(bool,bool);
|
||||||
|
bool isMatchFinished(){return endOfMatch;}
|
||||||
|
bool isNextDeckFound(){return nextDeckFound;}
|
||||||
|
void swapPlayer();
|
||||||
|
void revertSwapPlayer();
|
||||||
|
void Start(); //may change the gamephase
|
||||||
|
void End();
|
||||||
|
void saveMatchResults();
|
||||||
|
bool updateTournament();
|
||||||
|
void save(bool isAI);
|
||||||
|
bool load(bool isAI, bool loadComplete);
|
||||||
|
void setOpLevel(int o){mOpLevel=o;}
|
||||||
|
int getOpLevel(){return mOpLevel;}
|
||||||
|
void initTournament();
|
||||||
|
void resetTournamentSelection(); //resets the choosen oppent decks
|
||||||
|
std::string exportTournamentDescription();
|
||||||
|
unsigned int getNumberofTournamentDecks(){return TournamentsDecks.size();}
|
||||||
|
void enableTournamantMode(int tournamentMode, int player = 0);
|
||||||
|
bool wasScoreDisplayed(){return scoreDisplayed;}
|
||||||
|
void setScoreDisplayed(bool s){scoreDisplayed=s;}
|
||||||
|
bool didHumanWin();
|
||||||
|
int gamesPlayedbyHuman();
|
||||||
|
int gamesWonbyHuman();
|
||||||
|
int matchesPlayedbyHuman();
|
||||||
|
int matchesWonbyHuman();
|
||||||
|
void calculateRanking();
|
||||||
|
void initTournamentResults();
|
||||||
|
void setRankedDeck(int rank,TDeck deck){if (rank<11&&rank>0)sortedTournamentDecks[rank-1]=deck;}
|
||||||
|
bool checkTournamentFile(bool isAI);
|
||||||
|
void leaveOutAIvsAIMatches();
|
||||||
|
void updateScoreforTournament();
|
||||||
|
int getHardRandomDeck();
|
||||||
|
int getRandomDeck(bool noEasyDecks);
|
||||||
|
int remainingDecksToNextStage();
|
||||||
|
private:
|
||||||
|
bool mCompetition;
|
||||||
|
bool mPlayerSwaped;
|
||||||
|
int mSpeed;
|
||||||
|
int mNbGames;
|
||||||
|
int mMatchMode;
|
||||||
|
int mGamesPlayed;
|
||||||
|
unsigned int TournamentsDecksID[NMB_PLAYERS];
|
||||||
|
int gauntletLastDeckNumber[NMB_PLAYERS];
|
||||||
|
TDeck Deck[NMB_PLAYERS];
|
||||||
|
std::vector<TDeck> TournamentsDecks;
|
||||||
|
int mOpLevel;
|
||||||
|
unsigned int nmbDecks; // number of decks in the last constructed deckmenu
|
||||||
|
bool mFastTimerMode;
|
||||||
|
int mTournamentMode;
|
||||||
|
bool endOfMatch;
|
||||||
|
bool nextDeckFound;
|
||||||
|
bool looserDecks; //double KO
|
||||||
|
// variables for scoretable
|
||||||
|
bool scoreDisplayed;
|
||||||
|
JQuadPtr p0Quad;
|
||||||
|
JQuadPtr p1Quad;
|
||||||
|
int mgameType;
|
||||||
|
TDeck sortedTournamentDecks[10];
|
||||||
|
int mVictories0;
|
||||||
|
int mVictories1;
|
||||||
|
bool p0IsAI;
|
||||||
|
bool p1IsAI;
|
||||||
|
bool scoreFinal;
|
||||||
|
bool tournamentFinal;
|
||||||
|
int scoreMatchesToPlay;
|
||||||
|
int scoreMatchesPlayed;
|
||||||
|
};
|
||||||
|
|
||||||
|
/////// End Tournament Mod ///////////
|
||||||
|
|
||||||
class GameStateDuel: public GameState, public JGuiListener
|
class GameStateDuel: public GameState, public JGuiListener
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -38,6 +189,13 @@ private:
|
|||||||
SimplePopup * popupScreen; // used for informational screens, modal
|
SimplePopup * popupScreen; // used for informational screens, modal
|
||||||
static int selectedPlayerDeckId;
|
static int selectedPlayerDeckId;
|
||||||
static int selectedAIDeckId;
|
static int selectedAIDeckId;
|
||||||
|
/////// Tournament Mod ///////////
|
||||||
|
//std::ofstream ai_file;
|
||||||
|
SimpleMenu * cnogmenu; // to choose the number of games to play in the match
|
||||||
|
void setAISpeed();
|
||||||
|
Tournament* tournament;
|
||||||
|
bool tournamentSelection;
|
||||||
|
/////// End Tournament Mod ///////////
|
||||||
|
|
||||||
bool premadeDeck;
|
bool premadeDeck;
|
||||||
int OpponentsDeckid;
|
int OpponentsDeckid;
|
||||||
@@ -48,6 +206,7 @@ private:
|
|||||||
void initScroller();
|
void initScroller();
|
||||||
void setGamePhase(int newGamePhase);
|
void setGamePhase(int newGamePhase);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GameStateDuel(GameApp* parent);
|
GameStateDuel(GameApp* parent);
|
||||||
virtual ~GameStateDuel();
|
virtual ~GameStateDuel();
|
||||||
@@ -105,6 +264,20 @@ public:
|
|||||||
MENUITEM_REMOTE_CLIENT = -18,
|
MENUITEM_REMOTE_CLIENT = -18,
|
||||||
MENUITEM_REMOTE_SERVER = -19,
|
MENUITEM_REMOTE_SERVER = -19,
|
||||||
#endif
|
#endif
|
||||||
|
/////// Tournament Mod ///////////
|
||||||
|
MENUITEM_SHOW_SCORE = -20,
|
||||||
|
MENUITEM_SPEED_FAST = -21,
|
||||||
|
MENUITEM_SPEED_NORMAL = -22,
|
||||||
|
MENUITEM_GAUNTLET = -23,
|
||||||
|
MENUITEM_KO_TOURNAMENT = -24,
|
||||||
|
MENUITEM_RR_TOURNAMENT = -25,
|
||||||
|
MENUITEM_START_TOURNAMENT = -26,
|
||||||
|
MENUITEM_ENDLESSDEMO = -27,
|
||||||
|
MENUITEM_RANDOM_AI_HARD = -28,
|
||||||
|
MENUITEM_DOUBLEKO_TOURNAMENT = -29,
|
||||||
|
MENUITEM_FILL_NEXT_STAGE_HARD = -30,
|
||||||
|
MENUITEM_FILL_NEXT_STAGE = -31,
|
||||||
|
/////// End Tournament Mod ///////////
|
||||||
MENUITEM_MORE_INFO = kInfoMenuID
|
MENUITEM_MORE_INFO = kInfoMenuID
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,12 @@ AIHint::AIHint(string _line)
|
|||||||
mCombatAttackTip = splitDontAttack[1];
|
mCombatAttackTip = splitDontAttack[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<string> splitDontBlock = parseBetween(action, "dontblockwith(", ")");
|
||||||
|
if(splitDontBlock.size())
|
||||||
|
{
|
||||||
|
mCombatBlockTip = splitDontBlock[1];
|
||||||
|
}
|
||||||
|
|
||||||
vector<string> splitCastOrder = parseBetween(action, "castpriority(", ")");
|
vector<string> splitCastOrder = parseBetween(action, "castpriority(", ")");
|
||||||
if(splitCastOrder.size())
|
if(splitCastOrder.size())
|
||||||
{
|
{
|
||||||
@@ -100,6 +106,26 @@ bool AIHints::HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AIHints::HintSaysDontBlock(GameObserver* observer,MTGCardInstance * card)
|
||||||
|
{
|
||||||
|
TargetChooserFactory tfc(observer);
|
||||||
|
TargetChooser * hintTc = NULL;
|
||||||
|
for(unsigned int i = 0; i < hints.size();i++)
|
||||||
|
{
|
||||||
|
if (hints[i]->mCombatBlockTip.size())
|
||||||
|
{
|
||||||
|
hintTc = tfc.createTargetChooser(hints[i]->mCombatBlockTip,card);
|
||||||
|
if(hintTc && hintTc->canTarget(card,true))
|
||||||
|
{
|
||||||
|
SAFE_DELETE(hintTc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SAFE_DELETE(hintTc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card)
|
bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card)
|
||||||
{
|
{
|
||||||
TargetChooserFactory tfc(observer);
|
TargetChooserFactory tfc(observer);
|
||||||
@@ -142,6 +168,7 @@ bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card)
|
|||||||
asTc = parseBetween(hints[i]->partOfCombo[dPart],"cast(",")");
|
asTc = parseBetween(hints[i]->partOfCombo[dPart],"cast(",")");
|
||||||
if(asTc.size())
|
if(asTc.size())
|
||||||
{
|
{
|
||||||
|
hints[i]->casting.push_back(asTc[1]);
|
||||||
vector<string>cht = parseBetween(hints[i]->partOfCombo[dPart],"targeting(",")");
|
vector<string>cht = parseBetween(hints[i]->partOfCombo[dPart],"targeting(",")");
|
||||||
if(cht.size())
|
if(cht.size())
|
||||||
hints[i]->cardTargets[asTc[1]] = cht[1];
|
hints[i]->cardTargets[asTc[1]] = cht[1];
|
||||||
@@ -353,6 +380,11 @@ string AIHints::constraintsNotFulfilled(AIAction * action, AIHint * hint, ManaCo
|
|||||||
out << "to see if this can attack[" << hint->mCombatAttackTip << "]";
|
out << "to see if this can attack[" << hint->mCombatAttackTip << "]";
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
if (hint->mCombatBlockTip.size())
|
||||||
|
{
|
||||||
|
out << "to see if this can block[" << hint->mCombatBlockTip << "]";
|
||||||
|
return out.str();
|
||||||
|
}
|
||||||
if (hint->mSourceId && !findSource(hint->mSourceId))
|
if (hint->mSourceId && !findSource(hint->mSourceId))
|
||||||
{
|
{
|
||||||
out << "needcardinplay[" << hint->mSourceId << "]";
|
out << "needcardinplay[" << hint->mSourceId << "]";
|
||||||
@@ -414,7 +446,7 @@ AIAction * AIHints::findAbilityRecursive(AIHint * hint, ManaCost * potentialMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
string s = constraintsNotFulfilled(a, hint, potentialMana);
|
string s = constraintsNotFulfilled(a, hint, potentialMana);
|
||||||
if (hint->mCombatAttackTip.size() || hint->castOrder.size())
|
if (hint->mCombatAttackTip.size() || hint->mCombatBlockTip.size() || hint->castOrder.size())
|
||||||
return NULL;
|
return NULL;
|
||||||
if (s.size())
|
if (s.size())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1851,7 +1851,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty
|
|||||||
|
|
||||||
if(hints && hints->HintSaysItsForCombo(observer,nextCardToPlay))
|
if(hints && hints->HintSaysItsForCombo(observer,nextCardToPlay))
|
||||||
{
|
{
|
||||||
DebugTrace(" AI wants to play a card that belongs to a combo.")
|
DebugTrace(" AI wants to play a card that belongs to a combo.");
|
||||||
nextCardToPlay = NULL;
|
nextCardToPlay = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1866,9 +1866,9 @@ MTGCardInstance * AIPlayerBaka::activateCombo()
|
|||||||
TargetChooser * hintTc = NULL;
|
TargetChooser * hintTc = NULL;
|
||||||
TargetChooserFactory tfc(observer);
|
TargetChooserFactory tfc(observer);
|
||||||
ManaCost * totalCost = ManaCost::parseManaCost(comboHint->manaNeeded);
|
ManaCost * totalCost = ManaCost::parseManaCost(comboHint->manaNeeded);
|
||||||
for(unsigned int k = 0;k < comboHint->hold.size(); k++)
|
for(unsigned int k = 0;k < comboHint->casting.size(); k++)
|
||||||
{
|
{
|
||||||
hintTc = tfc.createTargetChooser(comboHint->hold[k],nextCardToPlay);
|
hintTc = tfc.createTargetChooser(comboHint->casting[k],nextCardToPlay);
|
||||||
int combohand = game->hand->cards.size();
|
int combohand = game->hand->cards.size();
|
||||||
for(int j = 0; j < combohand;j++)
|
for(int j = 0; j < combohand;j++)
|
||||||
{
|
{
|
||||||
@@ -2252,6 +2252,8 @@ int AIPlayerBaka::chooseBlockers()
|
|||||||
// We first try to block the major threats, those that are marked in the Top 3 of our stats
|
// We first try to block the major threats, those that are marked in the Top 3 of our stats
|
||||||
while ((card = cd.nextmatch(game->inPlay, card)))
|
while ((card = cd.nextmatch(game->inPlay, card)))
|
||||||
{
|
{
|
||||||
|
if(hints && hints->HintSaysDontBlock(observer,card))
|
||||||
|
continue;
|
||||||
observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE);
|
observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE);
|
||||||
int set = 0;
|
int set = 0;
|
||||||
while (!set)
|
while (!set)
|
||||||
@@ -2287,6 +2289,8 @@ int AIPlayerBaka::chooseBlockers()
|
|||||||
card = NULL;
|
card = NULL;
|
||||||
while ((card = cd.nextmatch(game->inPlay, card)))
|
while ((card = cd.nextmatch(game->inPlay, card)))
|
||||||
{
|
{
|
||||||
|
if(hints && hints->HintSaysDontBlock(observer,card))
|
||||||
|
continue;
|
||||||
if (card->defenser && opponentsToughness[card->defenser] > 0)
|
if (card->defenser && opponentsToughness[card->defenser] > 0)
|
||||||
{
|
{
|
||||||
while (card->defenser)
|
while (card->defenser)
|
||||||
@@ -2300,6 +2304,8 @@ int AIPlayerBaka::chooseBlockers()
|
|||||||
card = NULL;
|
card = NULL;
|
||||||
while ((card = cd.nextmatch(game->inPlay, card)))
|
while ((card = cd.nextmatch(game->inPlay, card)))
|
||||||
{
|
{
|
||||||
|
if(hints && hints->HintSaysDontBlock(observer,card))
|
||||||
|
continue;
|
||||||
if (!card->defenser)
|
if (!card->defenser)
|
||||||
{
|
{
|
||||||
observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE);
|
observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE);
|
||||||
|
|||||||
Reference in New Issue
Block a user