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