void DeckStats::load(const std::string& filename) { currentDeck = filename; if ( masterDeckStats.find(filename) != masterDeckStats.end() ) { return; } std::string contents; if (JFileSystem::GetInstance()->readIntoString(filename, contents)) { std::stringstream stream(contents); std::string s; // get the associated player deck file: int deckId = atoi(filename.substr(filename.find("_deck") + 5, filename.find(".txt")).c_str()); char buffer[512]; sprintf(buffer, "deck%i.txt", deckId); string playerDeckFilePath = options.profileFile( buffer); DeckMetaData *playerDeckMetaData = DeckManager::GetInstance()->getDeckMetaDataByFilename( playerDeckFilePath, false); if (!playerDeckMetaData) { DebugTrace("DeckStats.cpp:CONSISTENCY ERROR: DeckStats are set, but no deck meta data"); return; } // check if this player deck has already been profiled for manacolors char next = stream.peek(); string manaColorIndex = ""; if ( next == 'M') { std::getline(stream, s ); manaColorIndex = s.substr( s.find(":") + 1); playerDeckMetaData->setColorIndex( manaColorIndex ); } while (std::getline(stream, s)) { string deckfile = s; std::getline(stream, s); int games = atoi(s.c_str()); std::getline(stream, s); int victories = atoi(s.c_str()); next = stream.peek(); if ( next == 'M') { std::getline(stream, s ); manaColorIndex = s.substr( s.find(":") + 1); } if ( masterDeckStats[filename].find(deckfile) != masterDeckStats[filename].end()) { SAFE_DELETE( masterDeckStats[filename][deckfile] ); } DeckStat * newDeckStat = NEW DeckStat(games, victories, manaColorIndex); (masterDeckStats[filename])[deckfile] = newDeckStat; } } }
AIPlayer * AIPlayerFactory::createAIPlayerTest(GameObserver *observer, MTGAllCards * collection, Player * opponent, string _folder) { char deckFile[512]; string avatarFilename; // default imagename char deckFileSmall[512]; string folder = _folder.size() ? _folder : "ai/baka/"; int deckid = 0; //random deck int nbdecks = 0; int found = 1; while (found && nbdecks < options[Options::AIDECKS_UNLOCKED].number) { found = 0; char buffer[512]; sprintf(buffer, "%sdeck%i.txt", folder.c_str(), nbdecks + 1); if (FileExists(buffer)) { found = 1; nbdecks++; } } if (!nbdecks) { if (_folder.size()) return createAIPlayerTest(observer, collection, opponent, ""); return NULL; } deckid = 1 + WRand() % (nbdecks); sprintf(deckFile, "%sdeck%i.txt", folder.c_str(), deckid); DeckMetaData *aiMeta = observer->getDeckManager()->getDeckMetaDataByFilename( deckFile, true); avatarFilename = aiMeta->getAvatarFilename(); sprintf(deckFileSmall, "ai_baka_deck%i", deckid); int deckSetting = EASY; if ( opponent ) { bool isOpponentAI = opponent->isAI() == 1; DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI); if ( meta->getVictoryPercentage() >= 65) deckSetting = HARD; } // AIPlayerBaka will delete MTGDeck when it's time AIPlayerBaka * baka = opponent ? NEW AIPlayerBakaB(observer, deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting)) : NEW AIPlayerBaka(observer, deckFile, deckFileSmall, avatarFilename, NEW MTGDeck(deckFile, collection,0, deckSetting)); baka->deckId = deckid; baka->setObserver(observer); return baka; }
// p1 is assumed to be the player you want stats for // p2 is the opponent int DeckManager::getDifficultyRating(Player *statsPlayer, Player *player) { if(player->deckFile != "") { DeckMetaData *meta = getDeckMetaDataByFilename(player->deckFile, (player->isAI() == 1) ); return meta->getDifficulty(); } else return EASY; }
bool DeckMenu::showDetailsScreen() { DeckMetaData * currentMenuItem = getSelectedDeck(); if (currentMenuItem) { if (mAlwaysShowDetailsButton) return true; if (mShowDetailsScreen && currentMenuItem->getVictories() > DeckMenuConst::DETAILED_INFO_THRESHOLD) return true; } return false; }
AIPlayer * AIPlayerFactory::createAIPlayer(GameObserver *observer, MTGAllCards * collection, Player * opponent, int deckid) { char deckFile[512]; string avatarFilename; // default imagename char deckFileSmall[512]; if (deckid == GameStateDuel::MENUITEM_EVIL_TWIN) { //Evil twin sprintf(deckFile, "%s", opponent->deckFile.c_str()); DebugTrace("Evil Twin => " << opponent->deckFile); avatarFilename = "avatar.jpg"; sprintf(deckFileSmall, "%s", "ai_baka_eviltwin"); } else { if (!deckid) { //random deck int nbdecks = MIN(AIPlayer::getTotalAIDecks(), options[Options::AIDECKS_UNLOCKED].number); if (!nbdecks) return NULL; deckid = 1 + WRand() % (nbdecks); } sprintf(deckFile, "ai/baka/deck%i.txt", deckid); DeckMetaData *aiMeta = observer->getDeckManager()->getDeckMetaDataByFilename( deckFile, true); avatarFilename = aiMeta->getAvatarFilename(); sprintf(deckFileSmall, "ai_baka_deck%i", deckid); } int deckSetting = EASY; if ( opponent ) { bool isOpponentAI = opponent->isAI() == 1; DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent->deckFile, isOpponentAI); if ( meta && meta->getVictoryPercentage() >= 65) deckSetting = HARD; } // AIPlayerBaka will delete MTGDeck when it's time 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; }
void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game) { int victory = 1; if (!game->didWin()) { if (player->life == opponent->life) return; if (player->life < opponent->life) victory = 0; } else if (!game->didWin(player)) { victory = 0; } load(currentDeck); map<string, DeckStat *> *stats = &masterDeckStats[currentDeck]; map<string, DeckStat *>::iterator it = stats->find(opponent->deckFileSmall); string manaColorIndex = ""; DeckManager *deckManager = DeckManager::GetInstance(); DeckMetaData *aiDeckMeta = deckManager->getDeckMetaDataByFilename( opponent->deckFile, true); StatsWrapper *stw = deckManager->getExtendedDeckStats( aiDeckMeta, MTGAllCards::getInstance(), true); manaColorIndex = stw->getManaColorIndex(); if (it == stats->end()) { stats->insert( make_pair( opponent->deckFileSmall, NEW DeckStat(1, victory, manaColorIndex) )); } else { it->second->victories += victory; it->second->nbgames += 1; if ( it->second->manaColorIndex == "" ) { it->second->manaColorIndex = manaColorIndex; } } save(currentDeck); DeckMetaData* playerMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename(player->deckFile, false); // metadata caches its internal data (number of games, victories, etc) // tell it to refresh when stats are updated if (playerMeta) playerMeta->Invalidate(); DeckMetaData* aiMeta = DeckManager::GetInstance()->getDeckMetaDataByFilename(opponent->deckFile, true); if (aiMeta) aiMeta->Invalidate(); }
void DeckStats::save(const std::string& filename) { std::ofstream file; if (JFileSystem::GetInstance()->openForWrite(file, filename)) { char writer[512]; map<string, DeckStat *> stats = masterDeckStats[currentDeck]; map<string, DeckStat *>::iterator it; string manaColorIndex = ""; int deckId = atoi(filename.substr(filename.find("_deck") + 5, filename.find(".txt")).c_str()); char buffer[512]; sprintf(buffer, "deck%i.txt", deckId); string playerDeckFilePath= options.profileFile( buffer); DeckManager *deckManager = DeckManager::GetInstance(); DeckMetaData *playerDeckMeta = deckManager->getDeckMetaDataByFilename(playerDeckFilePath, false); if (playerDeckMeta && playerDeckMeta->getColorIndex() == "" ) { StatsWrapper *stw = deckManager->getExtendedDeckStats( playerDeckMeta, MTGAllCards::getInstance(), false); manaColorIndex = stw->getManaColorIndex(); playerDeckMeta->setColorIndex( manaColorIndex ); } file << "MANA:" << manaColorIndex << endl; if(file) for (it = stats.begin(); it != stats.end(); it++) { sprintf(writer, "%s\n", it->first.c_str()); file << writer; sprintf(writer, "%i\n", it->second->nbgames); file << writer; sprintf(writer, "%i\n", it->second->victories); file << writer; file << "MANA:" << it->second->manaColorIndex <<endl; } file.close(); if(playerDeckMeta) playerDeckMeta->Invalidate(); } }
bool Player::parseLine(const string& s) { if(((Damageable*)this)->parseLine(s)) return true; size_t limiter = s.find("="); if (limiter == string::npos) limiter = s.find(":"); string areaS; if (limiter != string::npos) { areaS = s.substr(0, limiter); if (areaS.compare("manapool") == 0) { SAFE_DELETE(manaPool); manaPool = new ManaPool(this); ManaCost::parseManaCost(s.substr(limiter + 1), manaPool); return true; } else if (areaS.compare("mode") == 0) { this->playMode = (Player::Mode)atoi(s.substr(limiter + 1).c_str()); return true; } else if (areaS.compare("avatar") == 0) { mAvatarName = s.substr(limiter + 1); loadAvatar(mAvatarName, "bakaAvatar"); return true; } else if (areaS.compare("customphasering") == 0) { phaseRing = s.substr(limiter + 1); return true; } else if (areaS.compare("premade") == 0) { premade = (atoi(s.substr(limiter + 1).c_str())==1); return true; } else if (areaS.compare("deckfile") == 0) { deckFile = s.substr(limiter + 1); if(playMode == Player::MODE_AI) { sscanf(deckFile.c_str(), "ai/baka/deck%i.txt", &deckId); int deckSetting = EASY; if ( opponent() ) { bool isOpponentAI = opponent()->isAI() == 1; DeckMetaData *meta = observer->getDeckManager()->getDeckMetaDataByFilename( opponent()->deckFile, isOpponentAI); if ( meta && meta->getVictoryPercentage() >= 65) deckSetting = HARD; } SAFE_DELETE(mDeck); SAFE_DELETE(game); mDeck = NEW MTGDeck(deckFile.c_str(), MTGCollection(),0, deckSetting); game = NEW MTGPlayerCards(mDeck); // This automatically sets the observer pointer on all the deck cards game->setOwner(this); deckName = mDeck->meta_name; } return true; } else if (areaS.compare("deckfilesmall") == 0) { deckFileSmall = s.substr(limiter + 1); return true; } else if (areaS.compare("offerinterruptonphase") == 0) { for (int i = 0; i < NB_MTG_PHASES; i++) { string phaseStr = Constants::MTGPhaseCodeNames[i]; if (s.find(phaseStr) != string::npos) { offerInterruptOnPhase = PhaseRing::phaseStrToInt(phaseStr); return true; } } } } if(!game) { game = new MTGPlayerCards(); game->setOwner(this); } if(game->parseLine(s)) return true; return false; }
vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks) { vector<DeckMetaData*> retList; int found = 1; int nbDecks = 1; DeckManager *deckManager = DeckManager::GetInstance(); bool isAI = path.find("baka") != string::npos; while (found && (!maxDecks || nbDecks <= maxDecks)) { found = 0; std::ostringstream filename; filename << path << "/deck" << nbDecks << ".txt"; DeckMetaData * meta = deckManager->getDeckMetaDataByFilename(filename.str(), isAI); if (meta) { found = 1; //Check if the deck is unlocked based on sets etc... bool unlocked = true; vector<int> unlockRequirements = meta->getUnlockRequirements(); for (size_t i = 0; i < unlockRequirements.size(); ++i) { if (! options[unlockRequirements[i]].number) { unlocked = false; break; } } if (unlocked) { if (statsPlayer) { std::ostringstream aiStatsDeckName; aiStatsDeckName << smallDeckPrefix << "_deck" << nbDecks; meta->mStatsFilename = aiStatsDeckName.str(); meta->mIsAI = true; if (meta->mPlayerDeck != statsPlayer->GetCurrentDeckStatsFile()) { meta->mPlayerDeck = statsPlayer->GetCurrentDeckStatsFile(); meta->Invalidate(); } } else { std::ostringstream playerStatsDeckName; playerStatsDeckName << "stats/player_deck" << nbDecks << ".txt"; meta->mStatsFilename = options.profileFile(playerStatsDeckName.str()); meta->mIsAI = false; } retList.push_back(meta); } else { //updateMetaDataList in DeckManager.cpp performs some weird magic, swapping data between its cache and the "retList" from this function //Bottom line, we need to guarantee retList contains exactly the same items as (or updated versions of) the items in DeckManager Cache //In other words, any meta data that didn't make it to retList in this function must be erased from the DeckManager cache deckManager->DeleteMetaData(filename.str(), isAI); } nbDecks++; } meta = NULL; } std::sort(retList.begin(), retList.end(), sortByName); return retList; }
void DeckMenu::Render() { JRenderer * renderer = JRenderer::GetInstance(); float height = mHeight; if (!menuInitialized) { initMenuItems(); stars->Fire(); timeOpen = 0; menuInitialized = true; } if (timeOpen < 1) height *= timeOpen > 0 ? timeOpen : -timeOpen; for (int i = startId; i < startId + maxItems; i++) { if (i > mCount - 1) break; DeckMenuItem *currentMenuItem = static_cast<DeckMenuItem*> (mObjects[i]); if (currentMenuItem->getY() - DeckMenuConst::kLineHeight * startId < mY + height - DeckMenuConst::kLineHeight + 7) { // only load stats for visible items in the list DeckMetaData* metaData = currentMenuItem->getMetaData(); if (metaData && !metaData->mStatsLoaded) { metaData->LoadStats(); } if (currentMenuItem->hasFocus()) { mSelectedDeck = metaData; WFont *descriptionFont = WResourceManager::Instance()->GetWFont(Fonts::MAIN_FONT); // display the "more info" button if special condition is met if (showDetailsScreen()) { dismissButton->setIsSelectionValid(true); dismissButton->Render(); } else { dismissButton->setIsSelectionValid(false); } // display the avatar image string currentAvatarImageName = currentMenuItem->getImageFilename(); if (currentAvatarImageName.size() > 0) { JQuadPtr quad = WResourceManager::Instance()->RetrieveTempQuad(currentAvatarImageName, TEXTURE_SUB_AVATAR); if(quad.get()) { quad->mWidth = 35.f; quad->mHeight = 50.f; if (currentMenuItem->getText() == "Evil Twin") { JQuad * evil = quad.get(); evil->SetHFlip(true); renderer->RenderQuad(quad.get(), avatarX, avatarY); evil = NULL; } else renderer->RenderQuad(quad.get(), avatarX, avatarY); } } // fill in the description part of the screen string text = wordWrap(_(currentMenuItem->getDescription()), descWidth, descriptionFont->mFontID ); descriptionFont->SetColor(ARGB(255,255,255,255)); descriptionFont->DrawString(text.c_str(), descX, descY); // fill in the statistical portion if (currentMenuItem->hasMetaData()) { ostringstream oss; oss << _("Deck: ") << currentMenuItem->getDeckName() << endl; oss << currentMenuItem->getDeckStatsSummary(); descriptionFont->SetColor(ARGB(255,255,255,255)); descriptionFont->DrawString(oss.str(), statsX, statsY); } // change the font color of the current menu item mFont->SetColor(ARGB(255,255,255,255)); } else // reset the font color to be slightly muted mFont->SetColor(ARGB(150,255,255,255)); currentMenuItem->RenderWithOffset(-DeckMenuConst::kLineHeight * startId); } } if (!title.empty()) { mFont->SetColor(ARGB(255,255,255,255)); mFont->DrawString(title.c_str(), titleX, titleY, JGETEXT_CENTER); } mScroller->Render(); RenderBackground(); RenderDeckManaColors(); renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE); stars->Render(); renderer->SetTexBlend(BLEND_SRC_ALPHA, BLEND_ONE_MINUS_SRC_ALPHA); }