From 810c3967d6a5babfffcaab0ffcdce96152ff63f3 Mon Sep 17 00:00:00 2001 From: "omegablast2002@yahoo.com" Date: Tue, 26 Mar 2013 02:10:45 +0000 Subject: [PATCH] after much testing and corrections, our user Holgern from the forums has completely recreated and reworked the gauntlet mode originally coded for ai vs ai into a completely new way to play wagic, you can choose the number of matchs, various modes, and other wonderful additions. Don't take my word for it, try all the fun new stuff out yourself! THANK YOU Holgern! --- projects/mtg/include/Credits.h | 8 + projects/mtg/include/GameStateDuel.h | 173 ++ projects/mtg/src/AIPlayer.cpp | 2 + projects/mtg/src/Credits.cpp | 193 +- projects/mtg/src/GameStateDuel.cpp | 2434 +++++++++++++++++++++++++- 5 files changed, 2767 insertions(+), 43 deletions(-) diff --git a/projects/mtg/include/Credits.h b/projects/mtg/include/Credits.h index 5fd9d323d..a6db0b04d 100644 --- a/projects/mtg/include/Credits.h +++ b/projects/mtg/include/Credits.h @@ -48,6 +48,13 @@ private: int IsMoreAIDecksUnlocked(DeckStats * stats); string unlockedTextureName; JQuadPtr GetUnlockedQuad(string texturename); + bool mTournament; + bool mMatch; + bool mPlayerWin; + int mGamesWon; + int mGamesPlayed; + int mMatchesWon; + int mMatchesPlayed; public: int value; Player * p1, *p2; @@ -60,6 +67,7 @@ public: Credits(); ~Credits(); void compute(GameObserver* observer, GameApp * _app); + void computeTournament(GameObserver* g, GameApp * _app,bool tournament,bool match, bool playerWin,int gamesWon,int gamesPlayed,int matchesWon,int matchesPlayed); void Render(); static int unlockRandomSet(bool force = false); static int unlockSetByName(string name); 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/AIPlayer.cpp b/projects/mtg/src/AIPlayer.cpp index bef4aa55b..931f443c8 100644 --- a/projects/mtg/src/AIPlayer.cpp +++ b/projects/mtg/src/AIPlayer.cpp @@ -243,6 +243,8 @@ AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards * AIPlayerBaka * baka = NEW AIPlayerBaka(observer, deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting)); baka->deckId = deckid; baka->comboHint = NULL; + if (baka->opponent() && baka->opponent()->isHuman()) + baka->setFastTimerMode(false); return baka; } diff --git a/projects/mtg/src/Credits.cpp b/projects/mtg/src/Credits.cpp index 0efc3b550..1e07fcb49 100644 --- a/projects/mtg/src/Credits.cpp +++ b/projects/mtg/src/Credits.cpp @@ -148,6 +148,13 @@ Credits::Credits() p1 = NULL; p2 = NULL; observer = NULL; + mTournament=false; + mMatch=false; + mPlayerWin=false; + mGamesWon=0; + mGamesPlayed=0; + mMatchesWon=0; + mMatchesPlayed=0; } Credits::~Credits() @@ -327,6 +334,156 @@ void Credits::compute(GameObserver* g, GameApp * _app) SAFE_DELETE(playerdata); } +/////// Tournament Mod /////////// +void Credits::computeTournament(GameObserver* g, GameApp * _app,bool tournament,bool match,bool playerWin,int gamesWon,int gamesPlayed,int matchesWon,int matchesPlayed) +{ + mTournament=tournament; + mMatch=match; + mPlayerWin=playerWin; + mGamesWon=gamesWon; + mGamesPlayed=gamesPlayed; + mMatchesWon=matchesWon; + mMatchesPlayed=matchesPlayed; + + if (!g->turn) + return; + p1 = g->players[0]; + p2 = g->players[1]; + observer = g; + app = _app; + showMsg = (WRand() % 3); + + //no credits when the AI plays :) + if (p1->isAI()) + return; + + PlayerData * playerdata = NEW PlayerData(MTGCollection()); + if (p2->isAI() && mPlayerWin) + { + value = 400; + if (app->gameType != GAME_TYPE_CLASSIC) + value = 200; + int difficulty = options[Options::DIFFICULTY].number; + if (options[Options::DIFFICULTY_MODE_UNLOCKED].number && difficulty) + { + CreditBonus * b = NEW CreditBonus(100 * mGamesWon * difficulty, _("Difficulty Bonus")); + bonus.push_back(b); + } + if (mGamesWon>1) + { + CreditBonus * b = NEW CreditBonus(mGamesWon * 200, _("Won Game Bonus")); + bonus.push_back(b); + } + if (mMatchesWon>1) + { + CreditBonus * b = NEW CreditBonus(mMatchesWon * 200, _("Won Matches Bonus")); + bonus.push_back(b); + } + if ((mGamesWon==mGamesPlayed && mGamesPlayed>0) || (matchesWon==mMatchesPlayed && mMatchesPlayed>0)) + { + CreditBonus * b = NEW CreditBonus(500, _("Perfect Bonus")); + bonus.push_back(b); + } + if (mGamesWon>mGamesPlayed*0.80 && mGamesWon + + // + + if (unlocked == -1) + { + DeckStats * stats = DeckStats::GetInstance(); + stats->load(p1->GetCurrentDeckStatsFile()); + unlocked = isDifficultyUnlocked(stats); + if (unlocked) + { + unlockedTextureName = "unlocked.png"; + goa = (GameOptionAward*) &options[Options::DIFFICULTY_MODE_UNLOCKED]; + goa->giveAward(); + } + else + { + for (map::iterator it = Unlockable::unlockables.begin(); it != Unlockable::unlockables.end(); ++it) { + Unlockable * award = it->second; + if (award->tryToUnlock(g)) + { + unlocked = 1; + unlockedString = award->getValue("unlock_text"); + unlockedTextureName = award->getValue("unlock_img"); + break; + } + } + } + + if (!unlocked) + { + // EvilTwin and RandomDeck cannot be unlocked in tournamentmode + // for each won game, one change to unlock a set + for (int i=0;igetName(); //Show the set's pretty name for unlocks. + } + } + if (!unlocked) + { + if ((unlocked = IsMoreAIDecksUnlocked(stats))) + { + options[Options::AIDECKS_UNLOCKED].number += 10; + options.save(); + unlockedTextureName = "ai_unlocked.png"; + } + } + + if (unlocked && options[Options::SFXVOLUME].number > 0) + { + WResourceManager::Instance()->PlaySample("bonus.wav"); + } + + } + + vector::iterator it; + if (bonus.size()) + { + CreditBonus * b = NEW CreditBonus(value, _("Victory")); + bonus.insert(bonus.begin(), b); + for (it = bonus.begin() + 1; it < bonus.end(); ++it) + value += (*it)->value; + } + + playerdata->credits += value; + PriceList::updateKey(); + playerdata->taskList->passOneDay(); + if (playerdata->taskList->getTaskCount() < 6) + { + playerdata->taskList->addRandomTask(); + playerdata->taskList->addRandomTask(); + } + + } + else + { + unlocked = 0; + playerdata->taskList->passOneDay(); + } + + playerdata->save(); + SAFE_DELETE(playerdata); +} +/////// END Tournament Mod /////////// + JQuadPtr Credits::GetUnlockedQuad(string textureName) { if (!textureName.size()) return JQuadPtr(); @@ -367,7 +524,7 @@ void Credits::Render() { if (!p1->isAI() && p2->isAI()) { - if (observer->didWin(p1)) + if (observer->didWin(p1) || mPlayerWin) { sprintf(buffer, _("Congratulations! You earn %i credits").c_str(), value); JQuadPtr unlockedQuad = GetUnlockedQuad(unlockedTextureName); @@ -412,7 +569,39 @@ void Credits::Render() y += 15; //!! - if (observer->didWin(p1) && this->gameLength != 0) + + if (mMatch){ + if (mGamesPlayed>0){ + sprintf(buffer, _("Games Won: %i of %i (%i %%)").c_str(), mGamesWon,mGamesPlayed, (int)(mGamesWon*100/mGamesPlayed)); + f->DrawString(buffer, 10, y); + y += 10; + } + if (value>0 && mGamesPlayed>0){ + sprintf(buffer, _("Credits per game: %i").c_str(), (int) (value / mGamesPlayed)); + f->DrawString(buffer, 10, y); + y += 10; + } + showMsg = 0; + + } else if (mTournament){ + if (mGamesPlayed>0){ + sprintf(buffer, _("Games Won: %i of %i (%i %%)").c_str(),mGamesWon, mGamesPlayed,(int)(mGamesWon*100/mGamesPlayed)); + f->DrawString(buffer, 10, y); + y += 10; + } + if (mMatchesPlayed>0){ + sprintf(buffer, _("Matches Won: %i of %i (%i %%)").c_str(),mMatchesWon, mMatchesPlayed,(int)(mMatchesWon*100/mMatchesPlayed)); + f->DrawString(buffer, 10, y); + y += 10; + } + if (value>0 && mGamesPlayed>0){ + sprintf(buffer, _("Credits per game: %i").c_str(), (int) (value / mGamesPlayed)); + f->DrawString(buffer, 10, y); + y += 10; + } + showMsg = 0; + } + else if (observer->didWin(p1) && this->gameLength != 0) { sprintf(buffer, _("Game length: %i turns (%i seconds)").c_str(), observer->turn, this->gameLength); f->DrawString(buffer, 10, y); diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index a978b47cd..44550b17e 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -29,6 +29,7 @@ const float MENU_FONT_SCALE = 1.0f; + enum ENUM_DUEL_STATE { DUEL_STATE_UNSET = 0, @@ -38,8 +39,10 @@ enum ENUM_DUEL_STATE DUEL_STATE_DECK1_DETAILED_INFO, DUEL_STATE_DECK2_DETAILED_INFO, DUEL_STATE_CHOOSE_DECK1_TO_2, + DUEL_STATE_CHOOSE_DECK1_TO_PLAY, DUEL_STATE_CHOOSE_DECK2_TO_1, DUEL_STATE_CHOOSE_DECK2, + DUEL_STATE_CHOOSE_DECK2_TO_2, // for tournament selection DUEL_STATE_CHOOSE_DECK2_TO_PLAY, DUEL_STATE_ERROR_NO_DECK, DUEL_STATE_CANCEL, @@ -47,11 +50,23 @@ enum ENUM_DUEL_STATE DUEL_STATE_BACK_TO_MAIN_MENU, DUEL_STATE_MENU, DUEL_STATE_OPPONENT_WAIT, // used For Network only + DUEL_STATE_PREPARE_CNOGMENU, + DUEL_STATE_CHOOSE_NUMBER_OF_GAMES, + DUEL_STATE_CNOGMENU_IS_CLOSING, + DUEL_STATE_CANCEL_CNOGMENU, + DUEL_STATE_CONTINUE_TOURNAMENT, + DUEL_STATE_SHOW_SCORE, + DUEL_STATE_MENU_TO_SCORE, + DUEL_STATE_END_OF_GAME, + DUEL_STATE_END_OF_MATCH, + DUEL_STATE_END_OF_TOURNAMENT, DUEL_STATE_ERROR }; -const char * stateStrings[] = { "unset", "start", "end", "choose_deck1", "deck1_detailed_info", "deck2_detailed_info", "choose_deck1_to_2", "choose_deck2", "choose_deck2_to_play", - "error_no_deck", "cancel", "play", "back_to_main_menu", "menu", "oponent_wait", "error" }; +const char * stateStrings[] = { "unset", "start", "end", "choose_deck1", "deck1_detailed_info", "deck2_detailed_info", "choose_deck1_to_2", "choose_deck1_to_play","choose_deck2_to_1", "choose_deck2", + "choose_deck2_to_2", "choose_deck2_to_play","error_no_deck", "cancel", "play", "back_to_main_menu", "menu", "oponent_wait","prepare_cnogmenu", + "choose_number_games","cnogmenu_closes","cancel_cnogmenu","continue_tournament","show_score","menu_to_score","end_of_game","end_of_match","end_of_tournament", "error"}; + enum ENUM_DUEL_MENUS { @@ -59,15 +74,74 @@ enum ENUM_DUEL_MENUS DUEL_MENU_CHOOSE_DECK, DUEL_MENU_CHOOSE_OPPONENT, DUEL_MENU_DETAILED_DECK1_INFO, + DUEL_MENU_CHOOSE_NUMBER_OF_GAMES, DUEL_MENU_DETAILED_DECK2_INFO }; +enum ENUM_CNOGMENU_ITEMS +{ + CNOGMENU_ITEM_SINGLE_GAME, + CNOGMENU_ITEM_CONTINUE_TOURNAMENT, + CNOGMENU_ITEM_BESTOF3, + CNOGMENU_ITEM_BESTOF5, + CNOGMENU_ITEM_BESTOF7, + CNOGMENU_ITEM_BESTOF13, + CNOGMENU_ITEM_DELTA2, + CNOGMENU_ITEM_DELTA3, + CNOGMENU_ITEM_CONSECUTIVE2, + CNOGMENU_ITEM_CONSECUTIVE3, + CNOGMENU_ITEM_3GAMES, + CNOGMENU_ITEM_5GAMES, + CNOGMENU_ITEM_10GAMES, + CNOGMENU_ITEM_25GAMES, + CNOGMENU_ITEM_50GAMES, + CNOGMENU_ITEM_100GAMES, + CNOGMENU_ITEM_BESTOF7PLAYOFF, + CNOGMENU_ITEM_CANCEL +}; + +enum ENUM_MATCHMODES { + MATCHMODE_FIXED = 1, + MATCHMODE_BESTOF = 2, + MATCHMODE_DELTA = 3, + MATCHMODE_CONSECUTIVE = 4 +}; + +enum ENUM_TOURNAMENTMODES { + TOURNAMENTMODES_ENDLESS = 1, + TOURNAMENTMODES_GAUNTLET = 2, + TOURNAMENTMODES_KO = 3, + TOURNAMENTMODES_DOUBLEKO = 4, + TOURNAMENTMODES_ROUNDROBIN = 5 +}; + + +//enum ENUM_GAMEMENU_ITEMS +//{ +// GAMEMENU_ITEM_CONTINUE, +// GAMEMENU_ITEM_SPEED_STEPWISE, +// GAMEMENU_ITEM_CONCEDE_GAME, +// GAMEMENU_ITEM_CONCEDE_MATCH +//}; + +enum ENUM_OPERATION_LEVELS +{ + OPLEVEL_NEW = 1, + OPLEVEL_NEXT_MATCH = 2, + OPLEVEL_NEXT_GAME = 3, + OPLEVEL_GAME_ACTIV = 4 +}; + + int GameStateDuel::selectedPlayerDeckId = 0; int GameStateDuel::selectedAIDeckId = 0; GameStateDuel::GameStateDuel(GameApp* parent) : GameState(parent, "duel") { + + cnogmenu = NULL; + tournament = new Tournament(); premadeDeck = false; game = NULL; deckmenu = NULL; @@ -107,6 +181,7 @@ GameState(parent, "duel") GameStateDuel::~GameStateDuel() { End(); + SAFE_DELETE(tournament); } void GameStateDuel::Start() @@ -114,6 +189,7 @@ void GameStateDuel::Start() JRenderer * renderer = JRenderer::GetInstance(); renderer->EnableVSync(true); OpponentsDeckid = 0; + bool createDeckMenu=true; // create only a deckmenu if not in tournament #ifdef NETWORK_SUPPORT @@ -135,12 +211,29 @@ void GameStateDuel::Start() setGamePhase(DUEL_STATE_CHOOSE_DECK1); credits = NEW Credits(); - menu = NULL; + // match mode is available in classic and demo mode. + // in both modes player 1 is from type PLAYER_TYPE_CPU + if (mParent->players[1] == PLAYER_TYPE_CPU && (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)) + { + //initialize match + // only reset "Played Games" and "Victories" info if we didn't come here from within a match + tournament->Start(); + if (tournament->getOpLevel()< OPLEVEL_NEXT_GAME) + setGamePhase(DUEL_STATE_PREPARE_CNOGMENU); + else + { + createDeckMenu=false; //there is a tournament running and we do not need a deckmenu + SAFE_DELETE(deckmenu); + } + tournamentSelection=false; + } + + menu = NULL; int decksneeded = 0; for (int i = 0; i < 2; i++) { - if (mParent->players[i] == PLAYER_TYPE_HUMAN) + if (createDeckMenu && mParent->players[i] == PLAYER_TYPE_HUMAN) { //DeckManager::EndInstance(); decksneeded = 1; @@ -155,7 +248,7 @@ void GameStateDuel::Start() if (nbDecks) decksneeded = 0; - if (nbDecks > 1) + if (nbDecks > 1) deckmenu->Add(MENUITEM_RANDOM_PLAYER, "Random", "Play with a random deck."); renderDeckMenu(deckmenu, playerDeckList); @@ -175,7 +268,7 @@ void GameStateDuel::Start() { //translate deck creating desc Translator * t = Translator::GetInstance(); - string desc = _("Highly recommended to get the full Wagic experience!").c_str(); + string desc = _("Highly recommended to get\nthe full Wagic experience!").c_str(); map::iterator it = t->deckValues.find(_("Create your Deck!").c_str()); if (it != t->deckValues.end()) desc = it->second; @@ -191,6 +284,34 @@ void GameStateDuel::Start() } deckmenu->Add(MENUITEM_CANCEL, _("Main Menu").c_str(), _("Return to Main Menu").c_str()); } + else if(createDeckMenu && (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU)) + { + //DeckManager::EndInstance(); + deckmenu = NEW DeckMenu(DUEL_MENU_CHOOSE_DECK, this, Fonts::OPTION_FONT, "Choose a Deck", GameStateDuel::selectedPlayerDeckId, true); + int nmbDecks = options[Options::CHEATMODEAIDECK].number ? 1000 : options[Options::AIDECKS_UNLOCKED].number; + if (nmbDecks > 1) + { + deckmenu->Add(MENUITEM_ENDLESSDEMO,"Endless demo",_("Random AI decks plays\n again each other").c_str()); + deckmenu->Add(MENUITEM_KO_TOURNAMENT,"KO Tournament",_("Starts a Knockout Tournament of all available AI-Decks.\n ").c_str()); + deckmenu->Add(MENUITEM_DOUBLEKO_TOURNAMENT,"Double KO Tournament",_("Starts a double Knockout Tournament of all available AI-Decks.\n ").c_str()); + deckmenu->Add(MENUITEM_GAUNTLET,"Gauntlet",_("Prove your mettle against each and\nevery opponent, one at a time.").c_str()); + deckmenu->Add(MENUITEM_RANDOM_PLAYER, "Random", _("Selects a random deck.").c_str()); + } + //deckmenu->enableDisplayDetailsOverride(); + DeckManager *deckManager = DeckManager::GetInstance(); + vector playerDeckList; + + playerDeckList = fillDeckMenu(deckmenu, "ai/baka","ai_baka",NULL,nmbDecks); + //printf("nmbDecks %i\n",playerDeckList.size()); + renderDeckMenu(deckmenu, playerDeckList); + // save the changes to the player deck list maintained in DeckManager + deckManager->updateMetaDataList(&playerDeckList, true); + //save the real number of available decks + tournament->setAvailableDecks(playerDeckList.size()); + playerDeckList.clear(); + deckmenu->Add(MENUITEM_CANCEL, _("Main Menu").c_str(), _("Return to Main Menu").c_str()); + + } mEngine->ResetInput(); } @@ -239,6 +360,9 @@ void GameStateDuel::End() SAFE_DELETE(deckmenu); SAFE_DELETE(popupScreen); + //reset player for next match (only if actual match is finished) + tournament->End(); + #ifdef TESTSUITE SAFE_DELETE(testSuite); #endif @@ -259,14 +383,51 @@ void GameStateDuel::ConstructOpponentMenu() { opponentMenu = NEW DeckMenu(DUEL_MENU_CHOOSE_OPPONENT, this, Fonts::OPTION_FONT, "Choose Opponent", GameStateDuel::selectedAIDeckId, true); - opponentMenu->Add(MENUITEM_RANDOM_AI, "Random"); - if (options[Options::EVILTWIN_MODE_UNLOCKED].number) opponentMenu->Add(MENUITEM_EVIL_TWIN, "Evil Twin", - _("Can you defeat yourself?").c_str()); + + int nbUnlockedDecks = options[Options::CHEATMODEAIDECK].number ? 1000 : options[Options::AIDECKS_UNLOCKED].number; + if ((mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)&&mParent->players[1] == PLAYER_TYPE_CPU) + { + if (!tournamentSelection) + { + if (!tournament->isGauntlet()) + { + if (mParent->players[0] == PLAYER_TYPE_HUMAN){ + opponentMenu->Add(MENUITEM_KO_TOURNAMENT,"KO Tournament",_("Starts a Knockout Tournament against selected AI-Decks! You have to win all matches.\n 4 Decks -> 2 Matches\n7 Decks -> 3 Matches\n16 Decks -> 4 Matches\n32 Decks -> 5 Matches\n64 Decks -> 6 Matches\n128 Decks -> 7 Matches\n256 Decks -> 8 Matches").c_str()); + opponentMenu->Add(MENUITEM_DOUBLEKO_TOURNAMENT,"Double KO",_("Starts a Double Knockout Tournament against selected AI-Decks! You can loose once, but not more!\n 4 Decks -> 3 Matches\n7 Decks -> 4 Matches\n16 Decks -> 5 Matches\n32 Decks -> 6 Matches\n64 Decks -> 7 Matches\n128 Decks -> 8 Matches\n256 Decks -> 9 Matches").c_str()); + } + opponentMenu->Add(MENUITEM_RR_TOURNAMENT,"Round Robin Tournament",_("Starts an all vs all tournament!\nFirstly, in a selection process participating AI-Decks can be chosen.\n The tournament state is saved after each game and can be\n continued!").c_str()); + } + if (mParent->players[0] == PLAYER_TYPE_CPU) + opponentMenu->Add(MENUITEM_GAUNTLET,"Gauntlet",_("Prove your mettle against each and\nevery opponent, one at a time.").c_str()); + opponentMenu->Add(MENUITEM_RANDOM_AI, "Random"); + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + opponentMenu->Add(MENUITEM_RANDOM_AI_HARD, "Random (Not easy)",_("Selects a random AI deck\nwith hard or normal difficulty.").c_str()); + } + else + { + opponentMenu->Add(MENUITEM_START_TOURNAMENT,"Begin Tournament",(std::string("Stop selection and start ")+tournament->exportTournamentDescription()).c_str()); + if (tournament->getTournamentMode()==TOURNAMENTMODES_KO || tournament->getTournamentMode()==TOURNAMENTMODES_DOUBLEKO) + { + opponentMenu->Add(MENUITEM_FILL_NEXT_STAGE_HARD,"Fill stage (Not easy)",_("Fill next stage with random hard or normal opponents.\n1 opponent -> 1 stage\n3 opponents -> 2 stages\n7 opponents -> 3 stages\n15 opponents -> 4 stages\n31 opponents -> 5 stages\n63 opponents -> 6 stages\n127 opponents -> 7 stages\n255 opponents -> 8 stages").c_str()); + opponentMenu->Add(MENUITEM_FILL_NEXT_STAGE,"Fill stage",_("Fill next stage with random opponents.\n1 opponent -> 1 stage\n3 opponents -> 2 stages\n7 opponents -> 3 stages\n15 opponents -> 4 stages\n31 opponents -> 5 stages\n63 opponents -> 6 stages\n127 opponents -> 7 stages\n255 opponents -> 8 stages").c_str()); + } + else + { + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + opponentMenu->Add(MENUITEM_RANDOM_AI_HARD, "Random (Not easy)",_("Selects a random AI deck\nwith hard or normal difficulty.").c_str()); + opponentMenu->Add(MENUITEM_RANDOM_AI, "Random"); + } + + } + } + if (options[Options::EVILTWIN_MODE_UNLOCKED].number && !tournamentSelection) + opponentMenu->Add(MENUITEM_EVIL_TWIN, "Evil Twin", _("Can you defeat yourself?").c_str()); DeckManager * deckManager = DeckManager::GetInstance(); vector opponentDeckList; - int nbUnlockedDecks = options[Options::CHEATMODEAIDECK].number ? 1000 : options[Options::AIDECKS_UNLOCKED].number; + opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", game->getPlayer(0), nbUnlockedDecks); deckManager->updateMetaDataList(&opponentDeckList, true); + tournament->setAvailableDecks(opponentDeckList.size()); opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); opponentDeckList.clear(); } @@ -332,6 +493,88 @@ void GameStateDuel::Update(float dt) case DUEL_STATE_ERROR_NO_DECK: if (JGE_BTN_OK == mEngine->ReadButton()) mParent->SetNextState(GAME_STATE_DECK_VIEWER); break; + // The next state prepares the "Choose number of games" menu (PSY) + case DUEL_STATE_PREPARE_CNOGMENU: + SAFE_DELETE(cnogmenu); + + cnogmenu = NEW SimpleMenu(JGE::GetInstance(),DUEL_MENU_CHOOSE_NUMBER_OF_GAMES, this, Fonts::MENU_FONT,35,25,"How many games per match?"); + cnogmenu->Add(CNOGMENU_ITEM_SINGLE_GAME,"Single Game",""); + if (tournament->checkTournamentFile(mParent->players[0] == PLAYER_TYPE_CPU)) + cnogmenu->Add(CNOGMENU_ITEM_CONTINUE_TOURNAMENT,"Continue Tournament",""); + cnogmenu->Add(CNOGMENU_ITEM_BESTOF3,"Best of 3",""); + cnogmenu->Add(CNOGMENU_ITEM_BESTOF5,"Best of 5",""); + cnogmenu->Add(CNOGMENU_ITEM_BESTOF7,"Best of 7",""); + cnogmenu->Add(CNOGMENU_ITEM_BESTOF13,"Best of 13",""); + cnogmenu->Add(CNOGMENU_ITEM_DELTA2,"2 wins difference",""); + cnogmenu->Add(CNOGMENU_ITEM_DELTA3,"3 wins difference",""); + cnogmenu->Add(CNOGMENU_ITEM_CONSECUTIVE2,"2 in a row",""); + cnogmenu->Add(CNOGMENU_ITEM_CONSECUTIVE3,"3 in a row",""); + if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU) + { + //games with fixed game lenght are boring for human player + cnogmenu->Add(CNOGMENU_ITEM_3GAMES,"3 Games",""); + cnogmenu->Add(CNOGMENU_ITEM_5GAMES,"5 Games",""); + cnogmenu->Add(CNOGMENU_ITEM_10GAMES,"10 Games",""); + + // i think nobody will play 25 games against the ai + cnogmenu->Add(CNOGMENU_ITEM_25GAMES,"25 Games",""); + // i think nobody will play 50 games against the ai + cnogmenu->Add(CNOGMENU_ITEM_50GAMES,"50 Games",""); + // i think nobody will play 100 games against the ai + cnogmenu->Add(CNOGMENU_ITEM_100GAMES,"100 Games",""); + cnogmenu->Add(CNOGMENU_ITEM_BESTOF7PLAYOFF,"Best of 7 Playoff",""); + } + cnogmenu->Add(CNOGMENU_ITEM_CANCEL,"Cancel",""); + setGamePhase(DUEL_STATE_CHOOSE_NUMBER_OF_GAMES); + break; + + /* The next state displays the "Choose number of games" menu + and waits for input. (PSY) */ + case DUEL_STATE_CHOOSE_NUMBER_OF_GAMES: + cnogmenu->Update(dt); + break; + + // The next state waits until cnogmenu is fully closed + case DUEL_STATE_CNOGMENU_IS_CLOSING: + if (cnogmenu->isClosed()) + { // Is the closing animation finished? + setGamePhase(DUEL_STATE_CHOOSE_DECK1); + SAFE_DELETE(cnogmenu); + + } + else cnogmenu->Update(dt); + break; + // The next state waits until cnogmenu is fully closed + case DUEL_STATE_CONTINUE_TOURNAMENT: + if (cnogmenu && cnogmenu->isClosed()) + { // Is the closing animation finished? + // contruct and close opponentmenu for loading decknames + ConstructOpponentMenu(); + opponentMenu->Close(); + + //setGamePhase(DUEL_STATE_PLAY); + SAFE_DELETE(cnogmenu); + + } else if (opponentMenu && opponentMenu->isClosed()) + { + // Is the closing animation finished then we can start to play! + setGamePhase(DUEL_STATE_PLAY); + SAFE_DELETE(opponentMenu); + } + else if (cnogmenu) cnogmenu->Update(dt); + else if (opponentMenu) opponentMenu->Update(dt); + break; + + // The next state occurs when the player selected "Cancel" in the cnogmenu + case DUEL_STATE_CANCEL_CNOGMENU: + cnogmenu->Update(dt); + if (cnogmenu->isClosed()) + { + // wait until menu has closed, then go back to main menu + setGamePhase(DUEL_STATE_BACK_TO_MAIN_MENU); + SAFE_DELETE(cnogmenu); + } + break; case DUEL_STATE_DECK1_DETAILED_INFO: case DUEL_STATE_DECK2_DETAILED_INFO: @@ -375,10 +618,27 @@ void GameStateDuel::Update(float dt) } else { - game->loadPlayer(0, mParent->players[0]); - setGamePhase(DUEL_STATE_CHOOSE_DECK2); + if (mParent->players[1] == PLAYER_TYPE_CPU && (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)) + { + if (deckmenu && (!popupScreen || popupScreen->isClosed())) deckmenu->Update(dt); + } + else + { + game->loadPlayer(0, mParent->players[0]); + setGamePhase(DUEL_STATE_CHOOSE_DECK2); + } } } + break; + case DUEL_STATE_CHOOSE_DECK1_TO_PLAY: + if (deckmenu->isClosed()) + { + setGamePhase(DUEL_STATE_PLAY); + SAFE_DELETE(deckmenu); + } + else + deckmenu->Update(dt); + break; case DUEL_STATE_CHOOSE_DECK1_TO_2: if (deckmenu->isClosed()) @@ -387,9 +647,19 @@ void GameStateDuel::Update(float dt) deckmenu->Update(dt); break; case DUEL_STATE_CHOOSE_DECK2_TO_1: - if (opponentMenu->isClosed()) { + if (opponentMenu->isClosed()) + { setGamePhase(DUEL_STATE_CHOOSE_DECK1); SAFE_DELETE(opponentMenu); + } + else + opponentMenu->Update(dt); + break; + case DUEL_STATE_CHOOSE_DECK2_TO_2: + if (opponentMenu->isClosed()) + { + setGamePhase(DUEL_STATE_CHOOSE_DECK2); + SAFE_DELETE(opponentMenu); } else opponentMenu->Update(dt); break; @@ -405,8 +675,16 @@ void GameStateDuel::Update(float dt) } else { - game->loadPlayer(1, mParent->players[1]); - setGamePhase(DUEL_STATE_PLAY); + if (mParent->players[1] == PLAYER_TYPE_CPU && (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)) + { + ConstructOpponentMenu(); + opponentMenu->Update(dt); + } + else + { + game->loadPlayer(1, mParent->players[1]); + setGamePhase(DUEL_STATE_PLAY); + } } } break; @@ -420,14 +698,59 @@ void GameStateDuel::Update(float dt) } else { - ConstructOpponentMenu(); if (opponentMenu->isClosed()) + { setGamePhase(DUEL_STATE_PLAY); + SAFE_DELETE(opponentMenu); + } else opponentMenu->Update(dt); } break; + // this called after each match and tournament + case DUEL_STATE_SHOW_SCORE: + if ((JGE_BTN_OK == mEngine->ReadButton()) || ( mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU && !(game && !game->didWin()) && !tournament->isMatchFinished())) + { + //check if Match and tournament is over + if (game->didWin() && tournament->isMatchFinished() && !tournament->isNextDeckFound()) + { + tournament->setScoreDisplayed(true); + tournament->setOpLevel(OPLEVEL_NEW); + tournament->End(); + //Display credits for human player + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + { + tournament->save(false); + setGamePhase(DUEL_STATE_END); + } + else + { + setGamePhase(DUEL_STATE_END_OF_TOURNAMENT); + } + + } + else + { // we have to play again + if (game->didWin()) + tournament->setScoreDisplayed(true); + setGamePhase(DUEL_STATE_PLAY); + } + } + break; + // The next state occurs after the *match* has ended: + case DUEL_STATE_END_OF_MATCH: + break; + + // The next state occurs after the end of the last match of the tournament: + case DUEL_STATE_END_OF_TOURNAMENT: + if ( (JGE_BTN_OK == mEngine->ReadButton()) || (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU) ) + { + setGamePhase(DUEL_STATE_BACK_TO_MAIN_MENU); + } + + break; case DUEL_STATE_PLAY: + if (!game->isStarted()) { game->startGame(mParent->gameType, mParent->rules); @@ -452,6 +775,12 @@ void GameStateDuel::Update(float dt) musictrack = "ai_baka_music.mp3"; GameApp::playMusic(musictrack); + // init Score table + if ( (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)&& mParent->players[1] == PLAYER_TYPE_CPU) + { + tournament->updateScoreTable(game->players[0], game->players[1], mParent->gameType); + tournament->setScoreDisplayed(false); + } } game->Update(dt); //run a "post update" init call in the rules. This is for things such as Manapool, which gets emptied in the update @@ -464,8 +793,82 @@ void GameStateDuel::Update(float dt) if (game->didWin()) { - if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game, mParent); - setGamePhase(DUEL_STATE_END); + //the following section will be called only in a classic or demo gamemode and if a tournament or match with more then one game is activ + if ( (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)&& mParent->players[1] == PLAYER_TYPE_CPU && (tournament->isTournament() || tournament->getGamesToPlay()>1 )) + { + setGamePhase(DUEL_STATE_SHOW_SCORE); + /* Determine the winner of this game. + This could be done more elegantly in credits.cpp (PSY) */ + // (PSY!) check how the game handles draws, does it think it has a winner? + if (!tournament->wasScoreDisplayed() || mParent->players[0]==PLAYER_TYPE_CPU) + { + tournament->gameFinished(game->didWin(game->players[0]),game->didWin(game->players[1])); + tournament->updateScoreTable(game->players[0], game->players[1], mParent->gameType); + if (tournament->isMatchFinished()) + { + // Hack for the competition: swap players back if swapped + tournament->revertSwapPlayer(); + //save match results in ai_test.csv only for ai vs ai games + if (mParent->players[0]==PLAYER_TYPE_CPU) + tournament->saveMatchResults(); + + if (tournament->isTournament()) + { // We are in Tournament mode + tournament->updateTournament(); + // if first player is human then other results are random + // It would be to boring for human player to watch all other ai decks to finish + if (mParent->players[0]==PLAYER_TYPE_HUMAN) + tournament->leaveOutAIvsAIMatches(); + tournament->calculateRanking(); + tournament->updateScoreforTournament(); + if (tournament->isNextDeckFound()) + // first player is either human or cpu + mParent->players[0] = tournament->getDeckType(0); + } + } + + if (!tournament->isNextDeckFound() && tournament->isMatchFinished()) + { + //save tournament status + tournament->save(mParent->players[0]==PLAYER_TYPE_CPU); + if (mParent->players[0]==PLAYER_TYPE_HUMAN) + { + credits->computeTournament(game, mParent,tournament->isTournament(),!tournament->isTournament(),tournament->didHumanWin(),tournament->gamesWonbyHuman(),tournament->gamesPlayedbyHuman(),tournament->matchesWonbyHuman(),tournament->matchesPlayedbyHuman()); + } + } + } + + if (tournament->wasScoreDisplayed() || mParent->players[0]==PLAYER_TYPE_CPU) + { + tournament->setScoreDisplayed(false); + // load next deck if actual match is not finished or a next match is available + if (tournament->isNextDeckFound() || !tournament->isMatchFinished()) + { + tournament->setOpLevel(OPLEVEL_NEXT_GAME); + End(); + Start(); + tournament->setOpLevel(OPLEVEL_GAME_ACTIV); + // Hack for the competition: swap players (human must be on deck[0]) + tournament->swapPlayer(); + for (int i = 0; i < NMB_PLAYERS; i++) + { + game->loadPlayer(i, tournament->getDeckType(i), tournament->getDeckNumber(i), premadeDeck); + } + //saves actual tournament state + tournament->save(mParent->players[0]==PLAYER_TYPE_CPU); + setAISpeed(); + setGamePhase(DUEL_STATE_PLAY); + + } + } + + + } + else + { + if (game->players[1]->playMode != Player::MODE_TEST_SUITE) credits->compute(game, mParent); + setGamePhase(DUEL_STATE_END); + } #ifdef TESTSUITE if (mParent->players[1] == PLAYER_TYPE_TESTSUITE) { @@ -506,11 +909,14 @@ void GameStateDuel::Update(float dt) } } #endif - if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU) - { - End(); - Start(); - } +// if (mParent->players[0] == PLAYER_TYPE_CPU && mParent->players[1] == PLAYER_TYPE_CPU) +// { +/////// Tournament Mod /////////// +// End(); +// Start(); +/////// END Tournament Mod /////////// +// } + //this is handled elsewhere. } if (mEngine->GetButtonClick(JGE_BTN_MENU)) { @@ -535,6 +941,19 @@ void GameStateDuel::Update(float dt) #ifdef TESTSUITE menu->Add(MENUITEM_LOAD, "Load"); #endif + + if (mParent->players[1] == PLAYER_TYPE_CPU && (mParent->gameType == GAME_TYPE_CLASSIC || mParent->gameType == GAME_TYPE_DEMO)) + { + menu->Add(MENUITEM_SHOW_SCORE, "Show current score"); + if (mParent->players[0] == PLAYER_TYPE_CPU) + { + if (tournament->getFastTimerMode()) + menu->Add(MENUITEM_SPEED_NORMAL, "set Speed to NORMAL"); + else + menu->Add(MENUITEM_SPEED_FAST, "set Speed to FAST"); + + } + } menu->Add(MENUITEM_CANCEL, "Cancel"); } setGamePhase(DUEL_STATE_MENU); @@ -566,6 +985,14 @@ void GameStateDuel::Update(float dt) case DUEL_STATE_MENU: menu->Update(dt); break; + case DUEL_STATE_MENU_TO_SCORE: + menu->Update(dt); + if (menu->isClosed()) + { + setGamePhase(DUEL_STATE_SHOW_SCORE); + SAFE_DELETE(menu); + } + break; case DUEL_STATE_CANCEL: menu->Update(dt); if (menu->isClosed()) @@ -577,6 +1004,8 @@ void GameStateDuel::Update(float dt) case DUEL_STATE_BACK_TO_MAIN_MENU: if (menu) { + tournament->setOpLevel(OPLEVEL_NEW); + tournament->End(); #ifdef AI_CHANGE_TESTING while(mWorkerThread.size()) { @@ -609,7 +1038,9 @@ void GameStateDuel::Render() JRenderer * r = JRenderer::GetInstance(); r->ClearScreen(ARGB(0,0,0,0)); - if (game) game->Render(); + //render the game until someone did win the game (otherwise it crashes sometimes under linux) + if (game && !game->didWin()) + game->Render(); #ifdef AI_CHANGE_TESTING if (game && totalTestGames) @@ -638,6 +1069,21 @@ void GameStateDuel::Render() switch (mGamePhase) { + case DUEL_STATE_START: + break; + + case DUEL_STATE_SHOW_SCORE: + { + r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); + tournament->renderScoreTable(); + break; + } + case DUEL_STATE_END_OF_GAME: + break; + case DUEL_STATE_END_OF_MATCH: + break; + case DUEL_STATE_END_OF_TOURNAMENT: + break; case DUEL_STATE_END: { r->FillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, ARGB(200,0,0,0)); @@ -689,9 +1135,19 @@ void GameStateDuel::Render() mFont->DrawString(_("AN ERROR OCCURRED, CHECK FILE NAMES").c_str(), 0, SCREEN_HEIGHT / 2); break; } + case DUEL_STATE_PREPARE_CNOGMENU: + case DUEL_STATE_CHOOSE_NUMBER_OF_GAMES: + case DUEL_STATE_CNOGMENU_IS_CLOSING: + case DUEL_STATE_CANCEL_CNOGMENU: + if (cnogmenu) + cnogmenu->Render(); + break; + case DUEL_STATE_CHOOSE_DECK1: case DUEL_STATE_CHOOSE_DECK1_TO_2: + case DUEL_STATE_CHOOSE_DECK1_TO_PLAY: case DUEL_STATE_CHOOSE_DECK2: + case DUEL_STATE_CHOOSE_DECK2_TO_2: case DUEL_STATE_CHOOSE_DECK2_TO_PLAY: case DUEL_STATE_DECK1_DETAILED_INFO: case DUEL_STATE_DECK2_DETAILED_INFO: @@ -729,6 +1185,7 @@ void GameStateDuel::Render() #endif //NETWORK_SUPPORT case DUEL_STATE_MENU: case DUEL_STATE_CANCEL: + case DUEL_STATE_MENU_TO_SCORE: case DUEL_STATE_BACK_TO_MAIN_MENU: if (game) { @@ -763,6 +1220,85 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) switch (controllerId) { + case DUEL_MENU_CHOOSE_NUMBER_OF_GAMES: // We're in the "Choose number of Games" menu + { + switch (controlId) + { + case CNOGMENU_ITEM_SINGLE_GAME: + tournament->setMatchType(1,MATCHMODE_FIXED);break; + case CNOGMENU_ITEM_CONTINUE_TOURNAMENT: + if (cnogmenu) cnogmenu->Close(); + if (!tournament->load(mParent->players[0] == PLAYER_TYPE_CPU,true)) + { + setGamePhase(DUEL_STATE_CANCEL_CNOGMENU); + return; + } + tournament->calculateRanking(); + tournament->updateScoreforTournament(); + + if (tournament->isNextDeckFound() || !tournament->isMatchFinished()) + { + tournament->setOpLevel(OPLEVEL_GAME_ACTIV); + + + mParent->players[0] = tournament->getDeckType(0); + mParent->players[1] = tournament->getDeckType(1); + for (int i = 0; i < NMB_PLAYERS; i++) + { + game->loadPlayer(i, tournament->getDeckType(i),tournament->getDeckNumber(i) , premadeDeck); + } + setAISpeed(); + setGamePhase(DUEL_STATE_CONTINUE_TOURNAMENT); + return; + + } + else + { //end of match or end of tournament was already reached, the tournament cannot be continued + setGamePhase(DUEL_STATE_CANCEL_CNOGMENU); + return; + + } + break; + case CNOGMENU_ITEM_BESTOF3: + tournament->setMatchType(3,MATCHMODE_BESTOF); break; + case CNOGMENU_ITEM_BESTOF5: + tournament->setMatchType(5,MATCHMODE_BESTOF); break; + case CNOGMENU_ITEM_BESTOF7: + tournament->setMatchType(7,MATCHMODE_BESTOF); break; + case CNOGMENU_ITEM_BESTOF13: + tournament->setMatchType(13,MATCHMODE_BESTOF); break; + case CNOGMENU_ITEM_DELTA2: + tournament->setMatchType(2,MATCHMODE_DELTA); break; + case CNOGMENU_ITEM_DELTA3: + tournament->setMatchType(3,MATCHMODE_DELTA); break; + case CNOGMENU_ITEM_CONSECUTIVE2: + tournament->setMatchType(2,MATCHMODE_CONSECUTIVE); break; + case CNOGMENU_ITEM_CONSECUTIVE3: + tournament->setMatchType(3,MATCHMODE_CONSECUTIVE); break; + case CNOGMENU_ITEM_3GAMES: + tournament->setMatchType(3,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_5GAMES: + tournament->setMatchType(5,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_10GAMES: + tournament->setMatchType(10,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_25GAMES: + tournament->setMatchType(25,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_50GAMES: + tournament->setMatchType(50,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_100GAMES: + tournament->setMatchType(100,MATCHMODE_FIXED); break; + case CNOGMENU_ITEM_BESTOF7PLAYOFF: + tournament->setMatchType(7,MATCHMODE_BESTOF,true); break; + case CNOGMENU_ITEM_CANCEL: + cnogmenu->Close(); + setGamePhase(DUEL_STATE_CANCEL_CNOGMENU); + + return; + } + } + cnogmenu->Close(); + setGamePhase(DUEL_STATE_CNOGMENU_IS_CLOSING); + break; case DUEL_MENU_DETAILED_DECK1_INFO: if ((popupScreen || deckmenu->showDetailsScreen())) { @@ -804,16 +1340,64 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) { case MENUITEM_RANDOM_AI: game->loadPlayer(1, mParent->players[1]); - opponentMenu->Close(); - setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + tournament->addDeck(1,game->players.at(1)->deckId,mParent->players[1]); + setAISpeed(); + if (opponentMenu) opponentMenu->Close(); + if (tournamentSelection) + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + else + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + break; + case MENUITEM_RANDOM_AI_HARD: + { + int deck=tournament->getRandomDeck(true); + if (deck>0) + { + game->loadPlayer(1, mParent->players[1], deck, premadeDeck); + tournament->addDeck(1,game->players.at(1)->deckId,mParent->players[1]); + } + } + setAISpeed(); + if (opponentMenu) opponentMenu->Close(); + if (tournamentSelection) + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + else + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + + break; + case MENUITEM_FILL_NEXT_STAGE: + case MENUITEM_FILL_NEXT_STAGE_HARD: + { + int deck=0; + do + { + deck=tournament->getRandomDeck(controlId==MENUITEM_FILL_NEXT_STAGE_HARD); + if (deck>0) + { + game->loadPlayer(1, mParent->players[1], deck, premadeDeck); + tournament->addDeck(1,game->players.at(1)->deckId,mParent->players[1]); + } + } + while(tournament->remainingDecksToNextStage()>0 && deck>0); + } + setAISpeed(); + if (opponentMenu) opponentMenu->Close(); + if (tournamentSelection) + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + else + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + break; default: // cancel option. return to player deck selection if (controlId == MENUITEM_CANCEL) { - opponentMenu->Close(); - deckmenu->Close(); + if (opponentMenu) opponentMenu->Close(); + if (deckmenu) deckmenu->Close(); + //reset tournament + tournamentSelection=false; + tournament->resetTournamentSelection(); setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_1); break; } @@ -840,11 +1424,73 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) // do nothing, ignore all key requests until popup is dismissed. break; } + else if (controlId == MENUITEM_GAUNTLET) + { + tournament->enableTournamantMode(TOURNAMENTMODES_GAUNTLET,1); + deckNumber = 1;// start Gauntlet with first deck + } + else if (controlId == MENUITEM_KO_TOURNAMENT) + { + tournamentSelection=true; + tournament->enableTournamantMode(TOURNAMENTMODES_KO,1); + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + break; + + } + else if (controlId == MENUITEM_DOUBLEKO_TOURNAMENT) + { + tournamentSelection=true; + tournament->enableTournamantMode(TOURNAMENTMODES_DOUBLEKO,1); + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + break; + + } + else if (controlId == MENUITEM_RR_TOURNAMENT) + { + tournamentSelection=true; + tournament->enableTournamantMode(TOURNAMENTMODES_ROUNDROBIN); + + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + break; + } + else if (controlId == MENUITEM_START_TOURNAMENT) + { + if (tournament->getNumberofTournamentDecks()>2) + { + tournamentSelection=false; + tournament->initTournament(); + game->loadPlayer(1, mParent->players[1], tournament->getDeckNumber(1), premadeDeck); + setAISpeed(); + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + } + else + { + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + } + break; + + } + else if (tournamentSelection) + { + deckNumber = deckManager->getAIDeckOrderList()->at(controlId - 1)->getDeckId(); + OpponentsDeckid = deckNumber; + tournament->addDeck(1,deckNumber,mParent->players[1]); + if (opponentMenu) opponentMenu->Close(); + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_2); + break; + } else if (controlId != MENUITEM_EVIL_TWIN && aiDeckSize > 0) // evil twin deckNumber = deckManager->getAIDeckOrderList()->at(controlId - 1)->getDeckId(); game->loadPlayer(1, mParent->players[1], deckNumber, premadeDeck); + tournament->addDeck(1,deckNumber,mParent->players[1]); + setAISpeed(); OpponentsDeckid = deckNumber; - opponentMenu->Close(); + if (opponentMenu) opponentMenu->Close(); setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); break; } @@ -854,10 +1500,14 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) if (controlId == MENUITEM_RANDOM_PLAYER) // Random Player Deck Selection { - deckmenu->selectRandomDeck(false); - + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + deckmenu->selectRandomDeck(false); + else + deckmenu->selectRandomDeck(true); + tournament->addDeck(0,deckmenu->getSelectedDeckId(),mParent->players[0]); game->loadPlayer(0, mParent->players[0], deckmenu->getSelectedDeckId(), premadeDeck); - deckmenu->Close(); + if (deckmenu) deckmenu->Close(); + ConstructOpponentMenu(); setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); break; } @@ -889,6 +1539,38 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) // do nothing break; } + else if (controlId == MENUITEM_GAUNTLET) + { + tournament->enableTournamantMode(TOURNAMENTMODES_GAUNTLET,0); + controlId = 1; + } + else if (controlId == MENUITEM_ENDLESSDEMO) + { + tournament->enableTournamantMode(TOURNAMENTMODES_ENDLESS); + + game->loadPlayer(0, mParent->players[0], tournament->getDeckNumber(0), premadeDeck); + setAISpeed(); + setGamePhase(DUEL_STATE_CHOOSE_DECK1_TO_PLAY); + controlId = tournament->getDeckNumber(1); + } + else if (controlId == MENUITEM_KO_TOURNAMENT) + { + tournament->enableTournamantMode(TOURNAMENTMODES_KO); + + game->loadPlayer(0, mParent->players[0], tournament->getDeckNumber(0), premadeDeck); + setAISpeed(); + setGamePhase(DUEL_STATE_CHOOSE_DECK1_TO_PLAY); + controlId = tournament->getDeckNumber(1); + } + else if (controlId == MENUITEM_DOUBLEKO_TOURNAMENT) + { + tournament->enableTournamantMode(TOURNAMENTMODES_DOUBLEKO); + + game->loadPlayer(0, mParent->players[0], tournament->getDeckNumber(0), premadeDeck); + setAISpeed(); + setGamePhase(DUEL_STATE_CHOOSE_DECK1_TO_PLAY); + controlId = tournament->getDeckNumber(1); + } if (controlId < 0) { mParent->SetNextState(GAME_STATE_DECK_VIEWER); @@ -896,11 +1578,29 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) } if (mGamePhase == DUEL_STATE_CHOOSE_DECK1) { - vector * playerDeck = deckManager->getPlayerDeckOrderList(); - if (!premadeDeck && controlId > 0) - deckNumber = playerDeck->at(controlId - 1)->getDeckId(); - game->loadPlayer(0, mParent->players[0], deckNumber, premadeDeck); - deckmenu->Close(); + if (mParent->players[0] == PLAYER_TYPE_HUMAN) + { + vector * playerDeck = deckManager->getPlayerDeckOrderList(); + if (!premadeDeck && controlId > 0) + deckNumber = playerDeck->at(controlId - 1)->getDeckId(); + game->loadPlayer(0, mParent->players[0], deckNumber, premadeDeck); + tournament->addDeck(0,deckNumber,mParent->players[0]); + playerDeck = NULL; + } + else + { //demo first player is CPU + if (tournament->isGauntlet() || tournament->getTournamentMode() == TOURNAMENTMODES_KO || tournament->getTournamentMode() == TOURNAMENTMODES_DOUBLEKO) + // start Gauntlet with first deck + deckNumber = tournament->getDeckNumber(0); + else + { + deckNumber = deckManager->getAIDeckOrderList()->at(controlId - 1)->getDeckId(); + tournament->addDeck(0,deckNumber,mParent->players[0]); + } + game->loadPlayer(0, mParent->players[0], deckNumber, premadeDeck); + + } + if (deckmenu) deckmenu->Close(); #ifdef NETWORK_SUPPORT if(mParent->mpNetwork) { // no need to choose an opponent deck in network mode @@ -911,20 +1611,54 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) { setGamePhase(DUEL_STATE_CHOOSE_DECK1_TO_2); } - playerDeck = NULL; } else { game->loadPlayer(1, mParent->players[1], controlId, premadeDeck); - deckmenu->Close(); - setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); + if (deckmenu) deckmenu->Close(); + if (!tournament->isEndlessDemo() && tournament->getTournamentMode()!=TOURNAMENTMODES_KO && tournament->getTournamentMode()!=TOURNAMENTMODES_DOUBLEKO) // no oppenent has to be selected for these modes + setGamePhase(DUEL_STATE_CHOOSE_DECK2_TO_PLAY); } break; default: switch (controlId) { - +// case GAMEMENU_ITEM_CONCEDE_MATCH: +// // This is a hack for 1-Player mode, it won't work in 2-player mode: +// if (mParent->players[0] == PLAYER_TYPE_HUMAN) { +// mVictories[0] = 0; +// mVictories[1] = mNbGames; +// mGamesPlayed = mNbGames; +// } +// // falling through +// case GAMEMENU_ITEM_CONCEDE_GAME: +// // This is a hack for 1-Player mode, it won't work in 2-player mode: +// if (mParent->players[0] == PLAYER_TYPE_HUMAN) { +// game->players[0]->life = -99; +// } +// // falling through +// case GAMEMENU_ITEM_CONTINUE: +// menu->Close(); +// mGamePhase = DUEL_STATE_CONTINUE; +// break; + case MENUITEM_SPEED_FAST: + tournament->setFastTimerMode(true); + setAISpeed(); + menu->Close(); + setGamePhase(DUEL_STATE_CANCEL); + break; + case MENUITEM_SPEED_NORMAL: + tournament->setFastTimerMode(false); + setAISpeed(); + menu->Close(); + setGamePhase(DUEL_STATE_CANCEL); + break; + case MENUITEM_SHOW_SCORE: + menu->Close(); + //delete menu and display score + setGamePhase(DUEL_STATE_MENU_TO_SCORE); + break; case MENUITEM_MAIN_MENU: menu->Close(); setGamePhase(DUEL_STATE_BACK_TO_MAIN_MENU); @@ -966,6 +1700,7 @@ void GameStateDuel::ButtonPressed(int controllerId, int controlId) } } + void GameStateDuel::OnScroll(int inXVelocity, int inYVelocity) { // ignore magnitude for now, since no action requires scrolling @@ -987,3 +1722,1620 @@ void GameStateDuel::OnScroll(int inXVelocity, int inYVelocity) } } + +void GameStateDuel::setAISpeed() +{ + for (int i = 0; iplayers[i] == PLAYER_TYPE_CPU) + { + if(game) + ((AIPlayer *)game->players[i])->setFastTimerMode(tournament->getFastTimerMode()); + } + } +} + + + +TDeck::TDeck(int deck,PlayerType deckType, int victories, int lastWin, int wonMatches, int playedMatches,int wonGames,int playedGames) + :mDeckNumber(deck),mDeckType(deckType),mVictories(victories),mLastWin(lastWin),mWonMatches(wonMatches),mMatchesPlayed(playedMatches),mWonGames(wonGames),mGamesPlayed(playedGames) +{ + mRanking=-1; + mDifficulty=0; +} + +TDeck::TDeck() +{ + reset(); +} + +void TDeck::reset() +{ + mDeckNumber=0; + mDeckType=PLAYER_TYPE_CPU; + mVictories=0; + mLastWin=0; + mWonMatches=0; + mGamesPlayed=0; + mMatchesPlayed=0; + mRanking=-1; + mWonGames=0; + mDifficulty=0; +} + + +TDeck::~TDeck() +{ + + +} + +void TDeck::increaseDeckNumber() +{ + mDeckNumber++; +} + +std::string TDeck::getDeckName() +{ + DeckManager * deckManager = DeckManager::GetInstance(); + return deckManager->getDeckMetaDataById(getDeckNumber(), isAI())->getName(); +} + +Tournament::Tournament() +{ + + for (int i = 0; i *deckList = deckManager->getAIDeckOrderList(); + + int deckNumber; + unsigned int random=0; + int k=0; + bool isDouble=true; + vector decks; + for (unsigned int i=0;isize();i++) + if (noEasyDecks && (deckList->at(i)->getDifficulty()==HARD || deckList->at(i)->getDifficulty()==NORMAL)) + { + decks.push_back(i); + //printf("hard deck%i/%i\n",i,deckList->size()); + } else + decks.push_back(i); + + + while(isDouble && decks.size()>0) + { + isDouble=false; + k = rand() % (int)decks.size(); + random = decks.at(k); + + deckNumber = deckList->at(random)->getDeckId(); + if ( mTournamentMode==TOURNAMENTMODES_ROUNDROBIN || mTournamentMode==TOURNAMENTMODES_KO||mTournamentMode==TOURNAMENTMODES_DOUBLEKO) + for (unsigned int i=0;i= mNbGames) + endOfMatch = true; + break; + case MATCHMODE_BESTOF: + if ((Deck[0].getVictories() > mNbGames/2 || Deck[1].getVictories() > mNbGames/2) && (!mCompetition || abs(Deck[0].getVictories() - Deck[1].getVictories()) >1)) endOfMatch = true; + break; + case MATCHMODE_DELTA: + if ((Deck[0].getVictories() - Deck[1].getVictories() >= mNbGames) || (Deck[1].getVictories() - Deck[0].getVictories() >= mNbGames)) endOfMatch = true; + break; + case MATCHMODE_CONSECUTIVE: + if (Deck[0].getLastWin() >= mNbGames || Deck[1].getLastWin() >= mNbGames) endOfMatch = true; + break; + default: + endOfMatch = true; + } + + + return endOfMatch; +} + +void Tournament::saveMatchResults() +{ + std::ofstream file; + if (JFileSystem::GetInstance()->openForWrite(file,AI_RESULTS_FILE,ios_base::app)) + { + time_t rawtime; + struct tm * timeinfo; + char timestamp [80]; + time ( &rawtime ); + timeinfo = localtime ( &rawtime ); + strftime (timestamp,20,"%m/%d/%y, %H:%M:%S", timeinfo); + int deck0 = 0; + if (Deck[0].isAI()) + deck0 = Deck[0].getDeckNumber(); + else + deck0 = -Deck[0].getDeckNumber(); + + int deck1 = 0; + if (Deck[1].isAI()) + deck1 = Deck[1].getDeckNumber(); + else + deck1 = -Deck[1].getDeckNumber(); + + int temp = 0; if (mCompetition) temp = 1; + char buf[256]; + sprintf(buf, "%s,% 6i,% 6i,% 5i,% 5i,% 5i,% 1i,% 5i,% 1i\n", timestamp, deck0, deck1, Deck[0].getVictories(), Deck[1].getVictories(), mGamesPlayed, mMatchMode, mNbGames, temp); + file << buf; + file.close(); + } +} +void Tournament::resetTournamentSelection() +{ + mTournamentMode=0; + TournamentsDecks.clear(); + TournamentsDecks.push_back(Deck[0]); + TournamentsDecksID[0]=0; + TournamentsDecksID[1]=1; + +} + +std::string Tournament::exportTournamentDescription() +{ + std::string describtion; + char buf[1024]; + switch(mTournamentMode) + { + case TOURNAMENTMODES_KO: + sprintf(buf, "knockout tournament!:\n"); + describtion.append(buf); + break; + case TOURNAMENTMODES_DOUBLEKO: + sprintf(buf, "double knockout tournament!:\n"); + describtion.append(buf); + break; + case TOURNAMENTMODES_ROUNDROBIN: + sprintf(buf, "round robin tournament!:\n"); + describtion.append(buf); + break; + } + + sprintf(buf, "%i Decks selected:\n",(int)TournamentsDecks.size()-1); + describtion.append(buf); + for (unsigned int i=1;i0) + { + + mTournamentMode=tournamentMode; + // the first two decks are the first playing decks + TournamentsDecksID[0]=0; + TournamentsDecksID[1]=1; + switch(mTournamentMode) + { + case TOURNAMENTMODES_ENDLESS: + if (nmbDecks>1) + { + Deck[0].setDeckNumber((rand() % nmbDecks) + 1); + Deck[1].setDeckNumber((rand() % nmbDecks) + 1); + } + else + { + Deck[0].setDeckNumber(1); + Deck[1].setDeckNumber(1); + } + Deck[0].setDeckType(PLAYER_TYPE_CPU); + Deck[1].setDeckType(PLAYER_TYPE_CPU); + nextDeckFound = true; + scoreMatchesPlayed=0; + break; + case TOURNAMENTMODES_GAUNTLET: + Deck[player].setDeckNumber(1); + Deck[player].setDeckType(PLAYER_TYPE_CPU); + gauntletLastDeckNumber[player]=nmbDecks; + break; + case TOURNAMENTMODES_KO: + TournamentsDecks.clear(); + if (player>0) + { + TournamentsDecks.push_back(Deck[0]); + } + else + { + for (unsigned int i=0;i0) + std::random_shuffle ( TournamentsDecks.begin()+1, TournamentsDecks.end() ); + else + std::random_shuffle ( TournamentsDecks.begin(), TournamentsDecks.end() ); + Deck[0]=TournamentsDecks[0]; + Deck[1]=TournamentsDecks[1]; + } + break; + case TOURNAMENTMODES_DOUBLEKO: + looserDecks=false; + TournamentsDecks.clear(); + if (player>0) + { + TournamentsDecks.push_back(Deck[0]); + } + else + { + //only AI-vs-AI + for (unsigned int i=0;ireadIntoString(options.profileFile(PLAYER_TOURNAMENT), contents); + else + readTournament = JFileSystem::GetInstance()->readIntoString(AI_TOURNAMENT, contents); + + if (readTournament) + { + + TournamentsDecks.clear(); + std::stringstream stream(contents); + std::string s; + endOfMatch=false; + nextDeckFound=false; + TDeck newDeck; + while (std::getline(stream, s)) + { + + if (!s.size()) continue; + if (s[s.size() - 1] == '\r') s.erase(s.size() - 1); //Handle DOS files + if (s.size() && s[0] == '#') continue; + size_t i = s.find_first_of("="); + if (i == string::npos) continue; + //printf("string %s\n",s.c_str()); + string key = s.substr(0, i); + string value = s.substr(i + 1); + //printf("key %s, value %s\n",key.c_str(),value.c_str()); + + if (key.find("TournamentMode")!=string::npos) + mTournamentMode=atoi(value.c_str()); + if (key.find("endOfMatch")!=string::npos) + endOfMatch=atoi(value.c_str())>0; + if (key.find("nextDeckFound")!=string::npos) + nextDeckFound=atoi(value.c_str())>0; + if (loadComplete){ + if (key.find("Competition")!=string::npos) + mCompetition=atoi(value.c_str())>0; + if (key.find("PlayerSwaped")!=string::npos) + mPlayerSwaped=atoi(value.c_str())>0; + if (key.find("NbGames")!=string::npos) + mNbGames=atoi(value.c_str()); + if (key.find("MatchMode")!=string::npos) + mMatchMode=atoi(value.c_str()); + if (key.find("GamesPlayed")!=string::npos) + mGamesPlayed=atoi(value.c_str()); + if (key.find("nmbDecks")!=string::npos) + nmbDecks=atoi(value.c_str()); + if (key.find("FastTimerMode")!=string::npos) + mFastTimerMode=atoi(value.c_str())>0; + if (key.find("looserDecks")!=string::npos) + looserDecks=atoi(value.c_str())>0; + if (s.find_first_of("[") != string::npos) + { + size_t p1 = s.find_first_of("["); + key = s.substr(0, p1); + string player = s.substr(p1 + 1,1); + + // printf("player %i\n",atoi(player.c_str())); + if (key.find("PlayDeck")!=string::npos) + { + size_t t1 = value.find_first_of(","); + Deck[atoi(player.c_str())].setDeckNumber(atoi(value.substr(0,t1).c_str())); + size_t t2 = value.find(",",t1+1); + Deck[atoi(player.c_str())].setDeckType((PlayerType)atoi(value.substr(t1+1,t2).c_str())); + size_t t3 = value.find(",",t2+1); + Deck[atoi(player.c_str())].setVictories(atoi(value.substr(t2+1,t3).c_str())); + size_t t4 = value.find(",",t3+1); + Deck[atoi(player.c_str())].setLastWin(atoi(value.substr(t3+1,t4).c_str())); + size_t t5 = value.find(",",t4+1); + gauntletLastDeckNumber[atoi(player.c_str())]=atoi(value.substr(t4+1,t5).c_str()); + TournamentsDecksID[atoi(player.c_str())]=atoi(value.substr(t5+1).c_str()); + } + if (key.find("TDeck")!=string::npos) + { + newDeck.reset(); + size_t t1 = value.find_first_of(","); + newDeck.setDeckNumber(atoi(value.substr(0,t1).c_str())); + size_t t2 = value.find(",",t1+1); + newDeck.setDeckType((PlayerType)atoi(value.substr(t1+1,t2).c_str())); + size_t t3 = value.find(",",t2+1); + newDeck.setMatchesWon(atoi(value.substr(t2+1,t3).c_str())); + size_t t4 = value.find(",",t3+1); + newDeck.setMatchesPlayed(atoi(value.substr(t3+1,t4).c_str())); + size_t t5 = value.find(",",t4+1); + newDeck.setGamesWon(atoi(value.substr(t4+1,t5).c_str())); + newDeck.setGamesPlayed(atoi(value.substr(t5+1).c_str())); + addDeck(0,newDeck); + } + } + } + } + // copy played games and matches back to Deck (only for tournaments) + if (TournamentsDecks.size()>1) + { + if (TournamentsDecksID[0]openForWrite(Tfile,options.profileFile(PLAYER_TOURNAMENT),ios_base::out); + else + saveTournament = JFileSystem::GetInstance()->openForWrite(Tfile,AI_TOURNAMENT,ios_base::out); + + if (saveTournament) + { + char buf[256]; + sprintf(buf, "TournamentMode=%i\n",mTournamentMode); + Tfile << buf; + sprintf(buf, "Competition=%i\n",mCompetition); + Tfile << buf; + sprintf(buf, "PlayerSwaped=%i\n",mPlayerSwaped); + Tfile << buf; + sprintf(buf, "NbGames=%i\n",mNbGames); + Tfile << buf; + sprintf(buf, "MatchMode=%i\n",mMatchMode); + Tfile << buf; + sprintf(buf, "GamesPlayed=%i\n",mGamesPlayed); + Tfile << buf; + sprintf(buf, "nmbDecks=%i\n",nmbDecks); + Tfile << buf; + sprintf(buf, "FastTimerMode=%i\n",mFastTimerMode); + Tfile << buf; + sprintf(buf, "endOfMatch=%i\n",endOfMatch); + Tfile << buf; + sprintf(buf, "nextDeckFound=%i\n",nextDeckFound); + Tfile << buf; + if (mTournamentMode==TOURNAMENTMODES_DOUBLEKO) + { + sprintf(buf, "looserDecks=%i\n",looserDecks); + Tfile << buf; + } + sprintf(buf, "#PlayDeck[number]=decknumber,deckType,victories,lastWin,LastDeckNumber,TournamentsID\n"); + Tfile << buf; + for (int i = 0; i < NMB_PLAYERS; i++) + { + sprintf(buf, "PlayDeck[%i]=%i,%i,%i,%i,%i,%i\n",i,Deck[i].getDeckNumber(),Deck[i].getDeckType(),Deck[i].getVictories(),Deck[i].getLastWin(),gauntletLastDeckNumber[i],TournamentsDecksID[i]); + Tfile << buf; + } + if (mTournamentMode>2) + { + sprintf(buf, "#TournamentDeck[number]=decknumber,deckType,matchWins,playedMatches,gameWins,playedGames\n"); + Tfile << buf; + for (unsigned int i = 0; i < TournamentsDecks.size(); i++) + { + sprintf(buf, "TDeck[%i]=%i,%i,%i,%i,%i,%i\n",i,TournamentsDecks.at(i).getDeckNumber(),TournamentsDecks.at(i).getDeckType(),TournamentsDecks.at(i).getMatchesWon(),TournamentsDecks.at(i).getMatchesPlayed(),TournamentsDecks.at(i).getGamesWon(),TournamentsDecks.at(i).getGamesPlayed()); + Tfile << buf; + } + } + Tfile.close(); + } +} + +void Tournament::swapPlayer() +{ + if ((mCompetition && Deck[0].isAI()) || !Deck[1].isAI()) + { + TDeck tmpDeck; + tmpDeck = Deck[0]; Deck[0] = Deck[1]; Deck[1] = tmpDeck; + mPlayerSwaped = !mPlayerSwaped; + } +} + +void Tournament::revertSwapPlayer() +{ + if (mPlayerSwaped) + { + TDeck tmpDeck; + tmpDeck = Deck[0]; Deck[0] = Deck[1]; Deck[1] = tmpDeck; + mPlayerSwaped = !mPlayerSwaped; + } +} + +void Tournament::updateScoreTable(Player * _p0, Player * _p1, int gt, bool gameEnd) +{ + if (_p0) p0Quad = _p0->getIcon(); + if (_p1) p1Quad = _p1->getIcon(); + mgameType = gt; + mVictories0=Deck[0].getVictories(); + mVictories1=Deck[1].getVictories(); + p0IsAI=Deck[0].isAI(); + p1IsAI=Deck[1].isAI(); + scoreFinal=isMatchFinished() || gameEnd; + tournamentFinal=!isNextDeckFound() && isMatchFinished() && mTournamentMode>0; + + +} + +void Tournament::updateScoreforTournament() +{ + tournamentFinal=!isNextDeckFound() && isMatchFinished() && mTournamentMode>0; + scoreMatchesPlayed++; + switch(mTournamentMode) + { + case 0: //no tournament + scoreMatchesPlayed=0; + case TOURNAMENTMODES_GAUNTLET: + if ((gauntletLastDeckNumber[0])*(gauntletLastDeckNumber[1])>0) + scoreMatchesToPlay=(gauntletLastDeckNumber[0]*gauntletLastDeckNumber[1])-(Deck[0].getDeckNumber()-1)*gauntletLastDeckNumber[0]-Deck[1].getDeckNumber()-1; + else if ((gauntletLastDeckNumber[0])>0) + scoreMatchesToPlay=(gauntletLastDeckNumber[0])-Deck[0].getDeckNumber(); + else + scoreMatchesToPlay=(gauntletLastDeckNumber[1])-Deck[1].getDeckNumber(); + break; + case TOURNAMENTMODES_KO: + scoreMatchesToPlay=TournamentsDecks.size()-1; + break; + case TOURNAMENTMODES_DOUBLEKO: + scoreMatchesToPlay=(TournamentsDecks.size()); + break; + case TOURNAMENTMODES_ROUNDROBIN: + //player 0 is always the player (RR is only available for human) + scoreMatchesToPlay=(TournamentsDecks.size()-1)-TournamentsDecks.at(0).getMatchesPlayed(); + break; + } +} + +void Tournament::renderScoreTable() +{ + + JRenderer * r = JRenderer::GetInstance(); + WFont * f2 = WResourceManager::Instance()->GetWFont(Fonts::MENU_FONT); + char buffer[256]; + + f2->SetColor(ARGB(255,255,255,255)); + float y = 25; + float x_score = 150; + f2->SetScale(2); + if (tournamentFinal && mTournamentMode>0) + { + f2->SetScale(1); + switch(mTournamentMode) + { + case TOURNAMENTMODES_ENDLESS: + break; + case TOURNAMENTMODES_GAUNTLET: + //f2->DrawString(_("Gauntletmode").c_str() ,380, y2); + break; + case TOURNAMENTMODES_KO: + f2->DrawString(_("KO Tournament is over. Results:").c_str() ,80, y); + f2->SetScale(1); + break; + case TOURNAMENTMODES_DOUBLEKO: + f2->DrawString(_("Double KO Tournament is over. Results:").c_str() ,80, y); + f2->SetScale(1); + break; + case TOURNAMENTMODES_ROUNDROBIN: + f2->DrawString(_("Round robin Tournament is over. Results:").c_str() ,80, y); + f2->SetScale(0.8f); + break; + } + + y+=30; + f2->SetScale(0.8f); + f2->DrawString(_("Deck").c_str() ,80, y); + f2->DrawString(_("Matches").c_str() ,300, y); + f2->DrawString(_("Games").c_str() ,400, y); + y+=30; + for (unsigned int i=0;i<10;i++ ) + { + if (sortedTournamentDecks[i].getDeckNumber()>0 && i<10) + { + if (sortedTournamentDecks[i].getDeckType()==PLAYER_TYPE_CPU) + sprintf(buffer, _("%i.: %s").c_str(),sortedTournamentDecks[i].getRanking(), sortedTournamentDecks[i].getDeckName().c_str()); + else + sprintf(buffer, _("%i.: Player Deck: %s").c_str(),sortedTournamentDecks[i].getRanking(), sortedTournamentDecks[i].getDeckName().c_str()); + f2->DrawString(buffer, 30, y); + sprintf(buffer, _("%i/%i").c_str(), sortedTournamentDecks[i].getMatchesWon(), sortedTournamentDecks[i].getMatchesPlayed()); + f2->DrawString(buffer, 300, y); + sprintf(buffer, _("%i/%i").c_str(), sortedTournamentDecks[i].getGamesWon(), sortedTournamentDecks[i].getGamesPlayed()); + f2->DrawString(buffer, 400, y); + y+=20; + } + } + + } + else + { + int gamesPlayed=0; + if (scoreFinal) + { + f2->SetScale(1.5f); + f2->DrawString(_("Final Score:").c_str() ,80, y); + gamesPlayed=mVictories0+mVictories1; + } + else if (mCompetition) + { + f2->SetScale(1.5f); + gamesPlayed=mVictories0+mVictories1+1; + sprintf(buffer, _("Starting Game %i ...").c_str(), gamesPlayed); + f2->DrawString(buffer, 80, y); + } + else + { + f2->SetScale(1.5f); + gamesPlayed=mVictories0+mVictories1+1; + f2->DrawString(_("Current Score:").c_str() ,80, y); + } + + + f2->SetScale(1); + switch(mMatchMode) + { + case MATCHMODE_FIXED: + sprintf(buffer, _("Game %i of %i games. ").c_str(),gamesPlayed,mNbGames); + f2->DrawString(buffer ,30, 250); + break; + case MATCHMODE_BESTOF: + //sprintf(buffer, _("Game %i, Best of %i mode, win at least %i games. ").c_str(),gamesPlayed,mNbGames,(int)ceil((double)mNbGames/2.)); + sprintf(buffer, _("Game %i, Best of %i mode, win at least %i games. ").c_str(),gamesPlayed,mNbGames,(int)(((float)mNbGames/2.0f)+0.5f)); + f2->DrawString(buffer ,30, 250); + break; + case MATCHMODE_DELTA: + sprintf(buffer, _("Game %i, Win the match with %i wins difference. ").c_str(),gamesPlayed,mNbGames); + f2->DrawString(buffer ,30, 250); + break; + case MATCHMODE_CONSECUTIVE: + sprintf(buffer, _("Game %i, Win the match with %i wins in a row. ").c_str(), gamesPlayed,mNbGames); + f2->DrawString(buffer ,30, 250); + break; + + } + f2->SetScale(0.8f); + float y2=30; + switch(mTournamentMode) + { + + case TOURNAMENTMODES_ENDLESS: + x_score=80; + f2->DrawString(_("Endless demo mode").c_str() ,330, y2); + sprintf(buffer, _("%i matches played.").c_str(),scoreMatchesPlayed-1); + y2+=20; + f2->DrawString(buffer ,330, y2); + break; + case TOURNAMENTMODES_GAUNTLET: + x_score=80; + //f2->DrawString(_("Gauntletmode").c_str() ,380, y2); + f2->DrawString(_("Tournament:").c_str() ,330, y2); + y2+=20; + sprintf(buffer,_("Gauntlet \n(%i matches left)").c_str(),scoreMatchesToPlay); + f2->DrawString(buffer ,330, y2); + break; + case TOURNAMENTMODES_KO: + x_score=80; + f2->DrawString(_("Tournament:").c_str() ,300, y2); + y2+=20; + sprintf(buffer,_("Knockout \n(%i decks left)").c_str(),scoreMatchesToPlay); + f2->DrawString(buffer ,300, y2); + y2+=20; + f2->SetScale(0.7f); + for (int i=0;i<8;i++) + { + if (sortedTournamentDecks[i].getDeckNumber()>0) + { + y2+=20; + if (sortedTournamentDecks[i].getDeckType()==PLAYER_TYPE_HUMAN) + sprintf(buffer, _("Player: %s (%i/%i)").c_str(), sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + else + sprintf(buffer, _("%s (%i/%i)").c_str(), sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + f2->DrawString(buffer ,300, y2); + } + + } + break; + case TOURNAMENTMODES_DOUBLEKO: + x_score=80; + f2->DrawString(_("Tournament:").c_str() ,300, y2); + y2+=20; + sprintf(buffer,_("Double Knockout \n%i decks left:").c_str(),scoreMatchesToPlay); + f2->DrawString(buffer ,300, y2); + y2+=20; + f2->SetScale(0.7f); + for (int i=0;i<8;i++) + { + if (sortedTournamentDecks[i].getDeckNumber()>0) + { + y2+=20; + if (sortedTournamentDecks[i].getDeckType()==PLAYER_TYPE_HUMAN) + sprintf(buffer, _("Player: %s (%i/%i)").c_str(), sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + else + sprintf(buffer, _("%s (%i/%i)").c_str(), sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + f2->DrawString(buffer ,300, y2); + } + + } + break; + case TOURNAMENTMODES_ROUNDROBIN: + // move results to the left + x_score=80; + f2->DrawString(_("Tournament:").c_str() ,300, y2); + y2+=20; + sprintf(buffer,_("Round robin (%i left)").c_str(),scoreMatchesToPlay); + f2->DrawString(buffer ,300, y2); + //displays the first 6 decks + f2->SetScale(0.7f); + for (int i=0;i<6;i++) + { + if (sortedTournamentDecks[i].getDeckNumber()>0) + { + y2+=20; + if (sortedTournamentDecks[i].getDeckType()==PLAYER_TYPE_HUMAN) + sprintf(buffer, _("%i. Player: %s (%i/%i)").c_str(), i+1,sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + else + //sprintf(buffer, _("%i. deck%i (%i/%i)").c_str(), i+1,sortedTournamentDecks[i].getDeckNumber()); + sprintf(buffer, _("%i. %s (%i/%i)").c_str(), i+1,sortedTournamentDecks[i].getDeckName().c_str(),sortedTournamentDecks[i].getMatchesWon(),sortedTournamentDecks[i].getMatchesPlayed()); + f2->DrawString(buffer ,300, y2); + } + + } + break; + + } + y+=50; + f2->SetScale(3); + sprintf(buffer, _("%i").c_str(), mVictories1); + f2->DrawString(buffer, x_score+80, y); + y+=50; + f2->DrawString(_("-").c_str() ,x_score+85, y); + y+=50; + sprintf(buffer, _("%i").c_str(), mVictories0); + f2->DrawString(buffer, x_score+80, y); + // For some reason, there's currently no player avatar prepared in-game: + if (p1IsAI) + { + if (mgameType == GAME_TYPE_CLASSIC || mgameType == GAME_TYPE_DEMO) + r->RenderQuad(p1Quad.get(), x_score, 70, 0,1,1); + } + else + { + f2->SetScale(1); + f2->DrawString(_("Player").c_str() ,x_score, 80); + } + if (p0IsAI) + { + if (mgameType == GAME_TYPE_CLASSIC || mgameType == GAME_TYPE_DEMO) + r->RenderQuad(p0Quad.get(), x_score+190, 215, 0,1,1); + } + else + { + f2->SetScale(1); + f2->DrawString(_("Player").c_str() ,x_score+160, y+25); + } + f2->SetScale(1); + } + +} + + +void Tournament::initTournament() +{ + scoreMatchesToPlay=0; + scoreMatchesPlayed=0; + + if (mTournamentMode==TOURNAMENTMODES_KO || mTournamentMode==TOURNAMENTMODES_DOUBLEKO || mTournamentMode==TOURNAMENTMODES_ROUNDROBIN) + { + if (TournamentsDecksID[0]=0; i--) + { + if (nmbDecks>1) + { + Deck[i].increaseDeckNumber(); + //second player must not be a human player + if (i==1 && Deck[i].getDeckNumber() <= gauntletLastDeckNumber[i] && !Deck[i].isAI()) + Deck[i].increaseDeckNumber(); + if (Deck[i].getDeckNumber() > gauntletLastDeckNumber[i]) + { + Deck[i].setDeckNumber(1); + + } + else + { + nextDeckFound = true; + break; + } + } + } + Deck[0].deleteStats(); + Deck[1].deleteStats(); + } + else if (mTournamentMode==TOURNAMENTMODES_KO) + { + assert(TournamentsDecksID[0]Deck[1].getVictories()) + { + TournamentsDecks[TournamentsDecksID[0]].winMatch(); + TournamentsDecks[TournamentsDecksID[1]].looseMatch(); + } + else + { + TournamentsDecks[TournamentsDecksID[1]].winMatch(); + TournamentsDecks[TournamentsDecksID[0]].looseMatch(); + } + //update played games and won games stats + TournamentsDecks[TournamentsDecksID[1]].setGamesPlayed(Deck[1].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[1]].setGamesWon(Deck[1].getGamesWon()); + TournamentsDecks[TournamentsDecksID[0]].setGamesPlayed(Deck[0].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[0]].setGamesWon(Deck[0].getGamesWon()); + + int n = TournamentsDecks.size(); + int r = (int)ceil(log(double(n))/log(2.)); + int Nbye=(int)pow(2.,double(r)) -n; + //printf("n:%i r:%i nbye:%i\n",n,r,Nbye); + + if (TournamentsDecks.size()>0) + { + + TournamentsDecksID[0]=TournamentsDecksID[0]+2; + TournamentsDecksID[1]=TournamentsDecksID[1]+2; + + //is Deck available? + if (TournamentsDecks.size()>2 && (TournamentsDecksID[1] >= TournamentsDecks.size()-Nbye || TournamentsDecksID[0] >= TournamentsDecks.size()-Nbye)) + { + // next Stage + //remove looser Decks + unsigned int k=0; + while(k1) + nextDeckFound = true; + + } + else if (TournamentsDecks.size()==2) + { + TournamentsDecksID[0]=0; + TournamentsDecksID[1]=1; + // final match if both last decks win all matches until now. + if (TournamentsDecks.at(0).getMatchesWon()==TournamentsDecks.at(0).getMatchesPlayed() && TournamentsDecks.at(1).getMatchesWon()==TournamentsDecks.at(1).getMatchesPlayed()) + { + nextDeckFound = true; + } + } + else + { + nextDeckFound = true; + } + } + + + if (nextDeckFound) + { + Deck[0]=TournamentsDecks.at(TournamentsDecksID[0]); + Deck[1]=TournamentsDecks.at(TournamentsDecksID[1]); + //printf("Deckfound %i vs %i (%i)\n",TournamentsDecksID[0],TournamentsDecksID[1],TournamentsDecks.size()); + } + + + } + else if (mTournamentMode==TOURNAMENTMODES_DOUBLEKO) + { + assert(TournamentsDecksID[0]Deck[1].getVictories()) + { + TournamentsDecks[TournamentsDecksID[0]].winMatch(); + TournamentsDecks[TournamentsDecksID[1]].looseMatch(); + } + else + { + TournamentsDecks[TournamentsDecksID[1]].winMatch(); + TournamentsDecks[TournamentsDecksID[0]].looseMatch(); + } + //update played games and won games stats + TournamentsDecks[TournamentsDecksID[1]].setGamesPlayed(Deck[1].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[1]].setGamesWon(Deck[1].getGamesWon()); + TournamentsDecks[TournamentsDecksID[0]].setGamesPlayed(Deck[0].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[0]].setGamesWon(Deck[0].getGamesWon()); + + + int n = TournamentsDecks.size(); + int r = (int)ceil(log(double(n))/log(2.)); + int Nbye=(int)pow(2.,double(r)) -n; + if (TournamentsDecks.size()>0) + { + + if (looserDecks) + { + // find next to teams who had loose one time wonMatches != playedMatches + TournamentsDecksID[0]=TournamentsDecksID[1]+1; + + while ((TournamentsDecksID[0] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[0]].getMatchesPlayed()!=(TournamentsDecks[TournamentsDecksID[0]].getMatchesWon()+1)) + TournamentsDecksID[0]++; + TournamentsDecksID[1]=TournamentsDecksID[0]+1; + while ((TournamentsDecksID[1] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[1]].getMatchesPlayed()!=(TournamentsDecks[TournamentsDecksID[1]].getMatchesWon()+1)) + TournamentsDecksID[1]++; + } + else + { + // find next to teams who had never loose one time wonMatches == playedMatches + TournamentsDecksID[0]=TournamentsDecksID[1]+1; + + while ((TournamentsDecksID[0] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[0]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[0]].getMatchesWon()) + TournamentsDecksID[0]++; + TournamentsDecksID[1]=TournamentsDecksID[0]+1; + while ((TournamentsDecksID[1] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[1]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[1]].getMatchesWon()) + TournamentsDecksID[1]++; + + + //byes are only allowed in the first round + for ( unsigned int i=0;i1) + { + Nbye=0; + break; + } + + if (TournamentsDecks.size()>2 && (TournamentsDecksID[1] >= TournamentsDecks.size()-Nbye || TournamentsDecksID[0] >= TournamentsDecks.size()-Nbye)) + { + looserDecks=true; + TournamentsDecksID[0]=0; + TournamentsDecksID[1]=1; + while ((TournamentsDecksID[0] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[0]].getMatchesPlayed()!=(TournamentsDecks[TournamentsDecksID[0]].getMatchesWon()+1)) + TournamentsDecksID[0]++; + TournamentsDecksID[1]=TournamentsDecksID[0]+1; + while ((TournamentsDecksID[1] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[1]].getMatchesPlayed()!=(TournamentsDecks[TournamentsDecksID[1]].getMatchesWon()+1)) + TournamentsDecksID[1]++; + + } + + } + + + + + //is Deck available? + if (looserDecks && TournamentsDecks.size()>2 && (TournamentsDecksID[1] >= TournamentsDecks.size() || TournamentsDecksID[0] >= TournamentsDecks.size())) + { + printf("next stage %i,%i\n",TournamentsDecksID[0],TournamentsDecksID[1]); + // next Stage + //remove double looser Decks + unsigned int k=0; + while(k2) + { + //check if only one winner deck is available + int winnerDecks=0; + for (unsigned int i=0;i1) + looserDecks=false; + else + looserDecks=true; + if (!looserDecks) + { + // find next to teams who had never loose one time wonMatches == playedMatches + while ((TournamentsDecksID[0] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[0]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[0]].getMatchesWon()) + TournamentsDecksID[0]++; + TournamentsDecksID[1]=TournamentsDecksID[0]+1; + while ((TournamentsDecksID[1] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[1]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[1]].getMatchesWon()) + TournamentsDecksID[1]++; + } + else + { + while ((TournamentsDecksID[0] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[0]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[0]].getMatchesWon()+1) + TournamentsDecksID[0]++; + TournamentsDecksID[1]=TournamentsDecksID[0]+1; + while ((TournamentsDecksID[1] < TournamentsDecks.size()) && TournamentsDecks[TournamentsDecksID[1]].getMatchesPlayed()!=TournamentsDecks[TournamentsDecksID[1]].getMatchesWon()+1) + TournamentsDecksID[1]++; + + } + } + else + looserDecks=true; + //decks ok? + if (TournamentsDecks.size()>1) + nextDeckFound = true; + + } + else if (TournamentsDecks.size()==2) + { + TournamentsDecksID[0]=0; + TournamentsDecksID[1]=1; + // final match if both last decks win all matches until now. + if (!looserDecks) + { + nextDeckFound = true; + looserDecks=true; + } + } + else + { + nextDeckFound = true; + } + } + + + if (nextDeckFound) + { + Deck[0]=TournamentsDecks.at(TournamentsDecksID[0]); + Deck[1]=TournamentsDecks.at(TournamentsDecksID[1]); + //printf("Deckfound %i vs %i (%i)\n",TournamentsDecksID[0],TournamentsDecksID[1],TournamentsDecks.size()); + } + + + } + else if (mTournamentMode==TOURNAMENTMODES_ROUNDROBIN) + { + assert(TournamentsDecksID[0]Deck[1].getVictories()) + { + TournamentsDecks[TournamentsDecksID[0]].winMatch(); + TournamentsDecks[TournamentsDecksID[1]].looseMatch(); + } + else if (Deck[1].getVictories()>Deck[0].getVictories()) + { + TournamentsDecks[TournamentsDecksID[1]].winMatch(); + TournamentsDecks[TournamentsDecksID[0]].looseMatch(); + } + else + { //draw + TournamentsDecks[TournamentsDecksID[1]].drawMatch(); + TournamentsDecks[TournamentsDecksID[0]].drawMatch(); + } + //update played games and won games stats + TournamentsDecks[TournamentsDecksID[0]].setGamesPlayed(Deck[0].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[0]].setGamesWon(Deck[0].getGamesWon()); + TournamentsDecks[TournamentsDecksID[1]].setGamesPlayed(Deck[1].getGamesPlayed()); + TournamentsDecks[TournamentsDecksID[1]].setGamesWon(Deck[1].getGamesWon()); + + if (TournamentsDecks.size()>0) + { + // decks are chosen in following way: 1-2,1-3,2-3,1-4,2-4,3-4, ... until 1-n,...,(n-1)-n + TournamentsDecksID[0]++; + //is Deck available? + if (TournamentsDecksID[0] == TournamentsDecksID[1]) + { + TournamentsDecksID[0]=0; + TournamentsDecksID[1]++; + //decks ok? + if (TournamentsDecksID[0] < TournamentsDecksID[1] && TournamentsDecksID[1] < TournamentsDecks.size()) + nextDeckFound = true; + } + else + { + nextDeckFound = true; + } + } + + + if (nextDeckFound) + { + Deck[0]=TournamentsDecks.at(TournamentsDecksID[0]); + Deck[1]=TournamentsDecks.at(TournamentsDecksID[1]); + //printf("Deckfound %i vs %i (%i)\n",TournamentsDecksID[0],TournamentsDecksID[1],TournamentsDecks.size()); + } + }//endif round robin + else if (isEndlessDemo()) + { + Deck[0].deleteStats(); + Deck[1].deleteStats(); + if (nmbDecks>1) + { + Deck[0].setDeckNumber(rand() % nmbDecks + 1); + Deck[1].setDeckNumber(rand() % nmbDecks + 1); + } + else + { + Deck[0].setDeckNumber(1); + Deck[1].setDeckNumber(1); + } + nextDeckFound = true; + } + + return nextDeckFound; +} + +void Tournament::calculateRanking() +{ + int rankingPos=1; + unsigned int numberOfDecks=0; + switch(mTournamentMode) + { + case 0://no tournament + if (Deck[0].getVictories()>Deck[1].getVictories()) + { + Deck[0].setRanking(1); + Deck[1].setRanking(2); + } + else + { + Deck[1].setRanking(1); + Deck[0].setRanking(2); + } + break; + case TOURNAMENTMODES_ROUNDROBIN: + + rankingPos=1; + // starting from the maximal possible number of matchWins + for (int maximalWin=TournamentsDecks.size();maximalWin>-1;maximalWin--) + { + // goes trough each deck and search for the deck which has matchwins equal to maximalwins + for (unsigned int j=0;j8) + numberOfDecks=8; + for (unsigned int i=0;iTournamentsDecks[1].getMatchesWon()) + { + TournamentsDecks[0].setRanking(1); + TournamentsDecks[1].setRanking(2); + sortedTournamentDecks[0]=TDeck(TournamentsDecks.at(0)); + sortedTournamentDecks[1]=TDeck(TournamentsDecks.at(1)); + } + else + { + TournamentsDecks[1].setRanking(1); + TournamentsDecks[0].setRanking(2); + sortedTournamentDecks[0]=TDeck(TournamentsDecks.at(1)); + sortedTournamentDecks[1]=TDeck(TournamentsDecks.at(0)); + } + } + else + { + numberOfDecks=TournamentsDecks.size(); + if (numberOfDecks>8) + numberOfDecks=8; + for (unsigned int i=0;iDeck[1].getVictories(); + else + didWin=Deck[1].getVictories()>Deck[0].getVictories(); + break; + case TOURNAMENTMODES_KO: + case TOURNAMENTMODES_DOUBLEKO: + case TOURNAMENTMODES_ROUNDROBIN: + for (unsigned int player=0;player