From b436550150f24841dcfe825582ff687aa45f4bcb Mon Sep 17 00:00:00 2001 From: "omegablast2002@yahoo.com" Date: Sat, 16 Mar 2013 21:35:10 +0000 Subject: [PATCH] ai simple combo system is finally fully working. added ai hint dontblockwith(targetchooser) --- projects/mtg/include/AIHints.h | 3 + projects/mtg/include/GameStateDuel.h | 173 +++++++++++++++++++++++++++ projects/mtg/src/AIHints.cpp | 34 +++++- projects/mtg/src/AIPlayerBaka.cpp | 12 +- 4 files changed, 218 insertions(+), 4 deletions(-) diff --git a/projects/mtg/include/AIHints.h b/projects/mtg/include/AIHints.h index 3db429a49..6591b63b2 100644 --- a/projects/mtg/include/AIHints.h +++ b/projects/mtg/include/AIHints.h @@ -18,6 +18,7 @@ public: string mCondition; string mAction; string mCombatAttackTip; + string mCombatBlockTip; vectorcastOrder; vectorcombos; //for preformance we disect the combo on first run. @@ -25,6 +26,7 @@ public: vectorhold; vectoruntil; vectorrestrict; + vectorcasting; mapcardTargets; string manaNeeded; int mSourceId; @@ -48,6 +50,7 @@ public: AIHints (AIPlayerBaka * player); AIAction * suggestAbility(ManaCost * potentialMana); bool HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card = NULL); + bool HintSaysDontBlock(GameObserver* observer,MTGCardInstance * card = NULL); bool HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card = NULL); bool canWeCombo(GameObserver* observer,MTGCardInstance * card = NULL,AIPlayerBaka * Ai = NULL); vector mCastOrder(); diff --git a/projects/mtg/include/GameStateDuel.h b/projects/mtg/include/GameStateDuel.h index 39be04add..d788e0b00 100644 --- a/projects/mtg/include/GameStateDuel.h +++ b/projects/mtg/include/GameStateDuel.h @@ -13,6 +13,7 @@ #define CHOOSE_OPPONENT 7 +#define NMB_PLAYERS 2 // Number of players in the game. Currently that's always 2. #ifdef TESTSUITE class TestSuite; @@ -22,6 +23,156 @@ class Credits; class JNetwork; #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 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 { private: @@ -38,6 +189,13 @@ private: SimplePopup * popupScreen; // used for informational screens, modal static int selectedPlayerDeckId; 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; int OpponentsDeckid; @@ -48,6 +206,7 @@ private: void initScroller(); void setGamePhase(int newGamePhase); + public: GameStateDuel(GameApp* parent); virtual ~GameStateDuel(); @@ -105,6 +264,20 @@ public: MENUITEM_REMOTE_CLIENT = -18, MENUITEM_REMOTE_SERVER = -19, #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 }; diff --git a/projects/mtg/src/AIHints.cpp b/projects/mtg/src/AIHints.cpp index 6b61cc9a4..8207cc567 100644 --- a/projects/mtg/src/AIHints.cpp +++ b/projects/mtg/src/AIHints.cpp @@ -36,6 +36,12 @@ AIHint::AIHint(string _line) mCombatAttackTip = splitDontAttack[1]; } + vector splitDontBlock = parseBetween(action, "dontblockwith(", ")"); + if(splitDontBlock.size()) + { + mCombatBlockTip = splitDontBlock[1]; + } + vector splitCastOrder = parseBetween(action, "castpriority(", ")"); if(splitCastOrder.size()) { @@ -100,6 +106,26 @@ bool AIHints::HintSaysDontAttack(GameObserver* observer,MTGCardInstance * card) 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) { TargetChooserFactory tfc(observer); @@ -142,6 +168,7 @@ bool AIHints::HintSaysItsForCombo(GameObserver* observer,MTGCardInstance * card) asTc = parseBetween(hints[i]->partOfCombo[dPart],"cast(",")"); if(asTc.size()) { + hints[i]->casting.push_back(asTc[1]); vectorcht = parseBetween(hints[i]->partOfCombo[dPart],"targeting(",")"); if(cht.size()) 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 << "]"; 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)) { out << "needcardinplay[" << hint->mSourceId << "]"; @@ -414,7 +446,7 @@ AIAction * AIHints::findAbilityRecursive(AIHint * hint, ManaCost * 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; if (s.size()) { diff --git a/projects/mtg/src/AIPlayerBaka.cpp b/projects/mtg/src/AIPlayerBaka.cpp index 32886f4e6..e0f7ac50d 100644 --- a/projects/mtg/src/AIPlayerBaka.cpp +++ b/projects/mtg/src/AIPlayerBaka.cpp @@ -1851,7 +1851,7 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * pMana, const char * ty 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; } @@ -1866,9 +1866,9 @@ MTGCardInstance * AIPlayerBaka::activateCombo() TargetChooser * hintTc = NULL; TargetChooserFactory tfc(observer); 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(); 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 while ((card = cd.nextmatch(game->inPlay, card))) { + if(hints && hints->HintSaysDontBlock(observer,card)) + continue; observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE); int set = 0; while (!set) @@ -2287,6 +2289,8 @@ int AIPlayerBaka::chooseBlockers() card = NULL; while ((card = cd.nextmatch(game->inPlay, card))) { + if(hints && hints->HintSaysDontBlock(observer,card)) + continue; if (card->defenser && opponentsToughness[card->defenser] > 0) { while (card->defenser) @@ -2300,6 +2304,8 @@ int AIPlayerBaka::chooseBlockers() card = NULL; while ((card = cd.nextmatch(game->inPlay, card))) { + if(hints && hints->HintSaysDontBlock(observer,card)) + continue; if (!card->defenser) { observer->cardClick(card, MTGAbility::MTG_BLOCK_RULE);