Back to index

extremetuxracer  0.5beta
highscore.cpp
Go to the documentation of this file.
00001 /* 
00002  * ETRacer
00003  * Copyright (C) 2004-2006 Volker Stroebel <volker@planetpenguin.de>
00004  *
00005  * Copyright (C) 1999-2001 Jasmin F. Patry
00006  * 
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  * 
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020  *
00021  */
00022 
00023 #include "highscore.h"
00024 #include "stuff.h"
00025 #include "ppgltk/audio/audio.h"
00026 
00027 #include "textures.h"
00028 #include "joystick.h"
00029 
00030 #include "player.h"
00031 #include "game_mgr.h"
00032 
00033 
00034 
00035 /* class highscore
00036 handles reading and writing to the highscore.
00037 */
00038 
00039 highscore* Highscore = NULL;
00040 
00041 bool highscore::useHighscore=true;
00042 
00043 bool highscore::hsDebug=false;
00044 
00045 bool highscore::anyHighscore=false;
00046 
00047 highscore::highscore() {
00048        level_hs_length=0;
00049 }
00050 
00051 int
00052 highscore::addScore(std::string level, std::string nick,int score) {
00053        int n=findLevel(level);
00054        if(n == -1) {
00055               redim();
00056               level_hs[level_hs_length-1].level = level;
00057               n = level_hs_length-1;
00058        }
00059        //std::cout<<score << " > " << level_hs[n].post[9].score<<std::endl;
00060        if(score > level_hs[n].post[9].score) {
00061               /*
00062                      the list should be sorted, so if score is greater than the lowest score
00063                      we replace that post with this new one. Then we sort the list
00064               */
00065               level_hs[n].post[9].score = score;
00066               level_hs[n].post[9].nick.assign(nick,0,nick.length());
00067               if(level_hs[n].posts < 10)
00068                      level_hs[n].posts++;
00069               sort(n);
00070               anyHighscore=true;
00071               //printlist();
00072               for(int i=0;i<level_hs[n].posts;i++) {
00073                      if(level_hs[n].post[i].score == score) {
00074                             return (i+1);
00075                      }
00076               }
00077               return level_hs[n].posts;
00078        } else {
00079               return -1;
00080        }
00081               
00082 }
00083 
00084 std::string
00085 highscore::posToStr(int pos) {
00086        switch(pos) {
00087               case 1:
00088                      return _("1:st");
00089               case 2:
00090                      return _("2:nd");
00091               case 3:
00092                      return _("3:rd");
00093               case 4:
00094                      return _("4:th");
00095               case 5:
00096                      return _("5:th");
00097               case 6:
00098                      return _("6:th");
00099               case 7:
00100                      return _("7:th");
00101               case 8:
00102                      return _("8:th");
00103               case 9:
00104                      return _("9:th");
00105               case 10:
00106                      return _("10:th");
00107               default:
00108                      return "";
00109                      
00110        }
00111 }
00112 
00113 void
00114 highscore::sort(int l) {
00115               for(int i=1; i < 10; i++) {
00116                      int pos = i;
00117                      scorepost tmp = level_hs[l].post[i];
00118                      while(pos > 0 && level_hs[l].post[pos-1].score < tmp.score) {
00119                             level_hs[l].post[pos] = level_hs[l].post[pos-1];
00120                             pos--;
00121                      }
00122                      level_hs[l].post[pos] = tmp;
00123               }
00124 }
00125 
00126 int
00127 highscore::findLevel(std::string level) {
00128        for(int i=0;i<level_hs_length;i++) {
00129               if(level_hs[i].level.compare(level) == 0) {
00130                      return i;
00131               }
00132        }
00133        return -1;
00134 }
00135 
00136 std::string
00137 highscore::toOutputFormat(std::string str) {
00138        while(str.find(" ") != std::string::npos) {
00139               str.replace(str.find(" "),1,"_");
00140        }
00141        return str;
00142 }
00143 
00144 std::string
00145 highscore::fromOutputFormat(std::string str) {
00146        while(str.find("_") != std::string::npos) {
00147               str.replace(str.find("_"),1," ");
00148        }
00149        return str;
00150 }
00151 
00152 bool
00153 highscore::saveData()
00154 {
00155        if(!anyHighscore) {
00156               //std::cout << "No highscore to write, skipping"<<std::endl;
00157               return true;
00158        }
00159        
00160     char buff[256];
00161 
00162     if (get_config_dir_name( buff, 255 ) != 0) {
00163               return false;
00164     }
00165        
00166        std::string filename(buff);
00167        
00168        filename+="/highscore.dat";
00169        
00170        //std::cout <<"Writing highscore: "<<filename<<std::endl;
00171        
00172        std::ofstream sfile(filename.c_str());
00173        
00174        sfile << "ETRacer HIGHSCORE "<< version << std::endl;
00175        
00176        for(int n=0;n<level_hs_length;n++) {
00177               sfile << "<level>" << std::endl;
00178               sfile << toOutputFormat(level_hs[n].level) << std::endl;
00179               for(int i=0;i<level_hs[n].posts;i++){
00180                      sfile << toOutputFormat(level_hs[n].post[i].nick) << " " << level_hs[n].post[i].score << std::endl;
00181               }
00182               sfile << "</level> 0" << std::endl;
00183        }
00184        sfile << "EOF" << std::endl;
00185        
00186        
00187        return true;
00188 }
00189 
00190 bool
00191 highscore::loadData()
00192 {
00193        char buff[256];
00194 
00195        if (get_config_dir_name( buff, 255 ) != 0) {
00196               return false;
00197        }
00198        
00199        std::string filename(buff);
00200        
00201        filename+="/highscore.dat";
00202        
00203        
00204        std::ifstream sfile(filename.c_str());
00205        
00206        if(!sfile) return false;
00207        
00208        int _version;
00209        int _posts;
00210        
00211                      
00212        sfile >> buff >> buff >> _version;
00213        if(_version == version) {
00214               bool end=false;
00215               bool loop=false;
00216               while(!end) {
00217                      memset(buff,256,'\0');
00218                      sfile >> buff;
00219                      if(std::string("<level>").compare(buff)==0) {
00220                             int n;
00221                             redim();
00222                             n = level_hs_length-1;
00223                             memset(buff,256,'\0');
00224                             sfile >> buff;
00225                             level_hs[n].level.assign(fromOutputFormat(buff));
00226                             loop=true;
00227                             for(_posts=0;loop&&_posts<10;_posts++) {
00228                                    char nick[256];
00229                                    memset(nick,256,'\0');
00230                                    int score;
00231                                    sfile >> nick >> score;
00232                                    if(std::string("</level>").compare(nick)!=0) {
00233                                           level_hs[n].post[_posts].nick.assign(fromOutputFormat(nick));
00234                                           level_hs[n].post[_posts].score = score;
00235                                    } else {
00236                                           _posts--;
00237                                           loop=false;
00238                                    }
00239                             }
00240                             level_hs[n].posts = _posts;
00241                      } else if(std::string("EOF").compare(buff)==0) {
00242                             end=true;
00243                      }
00244               }
00245               anyHighscore=true;
00246               return true;
00247        } else {
00248               std::cout<<"Highscore file version doesnt match current!"<<std::endl;
00249               return false;
00250        }
00251 }
00252 
00253 int
00254 highscore::posFromString(std::string level) {
00255        for(int i=0;i<level_hs_length;i++) {
00256               if(level_hs[i].level.compare(level) == 0) {
00257                      return i;
00258               }
00259        }
00260        return -1;
00261 }
00262 
00263 void
00264 highscore::printlist() {
00265        std::cout<<"== HIGHSCORE =="<<std::endl;
00266        for(int n=0;n<level_hs_length;n++) {
00267               std::cout<<"LEVEL: " << level_hs[n].level<<std::endl;
00268               for(int i=0;i<level_hs[n].posts;i++) {
00269                      std::cout<<level_hs[n].post[i].nick << ": " << level_hs[n].post[i].score<<std::endl;
00270               }
00271               std::cout<<"-----------"<<std::endl;
00272        }
00273        std::cout<<"== EOF HIGHSCORE =="<<std::endl;
00274 }
00275 
00276 
00277 void
00278 highscore::debug() {
00279        addScore("DEBUG","TUX_DEBUG",100);
00280        printlist();
00281 }
00282 
00283 void
00284 highscore::redim() {
00285        //std::cout<<"Highscore: redimming..."<<std::endl;
00286        level_highscore *tmp = level_hs;
00287        level_hs = new level_highscore[++level_hs_length];
00288 
00289        if(tmp != NULL) {
00290               for(int i=0;i<level_hs_length-1;i++) {
00291                      level_hs[i] = tmp[i];
00292               }
00293        }
00294 }
00295 
00296 std::list<std::string>
00297 highscore::getCourseList() {
00298        std::list<std::string> tmp;
00299        for(int i=0;i<level_hs_length;i++) {
00300               tmp.push_back(level_hs[i].level);
00301        }
00302        return tmp;
00303 }
00304 
00305 std::list<HighscoreData>
00306 highscore::getCourseList_hd() {
00307        std::list<HighscoreData> tmp;
00308        if(level_hs_length>0) {
00309               for(int i=0;i<level_hs_length;i++) {
00310                      HighscoreData tmp2;
00311                      tmp2.name = level_hs[i].level;
00312                      tmp2.highscore = level_hs[i].level;
00313                      tmp.push_back(tmp2);
00314               }
00315        } else {
00316               HighscoreData tmp2;
00317               tmp2.name = _("No records");
00318               tmp2.highscore = "";
00319               tmp.push_back(tmp2);
00320        }
00321        return tmp;
00322 }
00323 
00324 std::string
00325 highscore::scorepost::toString() {
00326        char buff[40];
00327        snprintf(buff, 40, ( nick + _(" (%d points)") ).c_str(), score );
00328        return std::string(buff);
00329 }
00330 
00331 
00332 
00333 
00334 /* class HighscoreShow
00335 The graphic list displaying the highscore
00336 */
00337 
00338 static int curCourse=0;
00339 
00340 HighscoreShow::HighscoreShow()
00341  {
00342  /*
00343   : m_titleLbl(_("Highscore"),"heading"),
00344  m_raceListBox(450,36),
00345  m_backBtn(_("Back"))
00346  */
00347        pp::Vec2d pos( getparam_x_resolution()/2,
00348                                getparam_y_resolution()/2+130);
00349        
00350        mp_titleLbl = new pp::Label(pos,"heading",_("Highscore"));
00351        mp_titleLbl->alignment.center();
00352        
00353        if(Highscore->level_hs_length>0) {
00354               std::list<std::string> courses=Highscore->getCourseList();
00355               m_raceList = Highscore->getCourseList_hd();
00356               
00357               pos.y-=60;
00358               
00359               mp_raceListBox = new pp::Listbox<HighscoreData>(pp::Vec2d(pos.x-200,pos.y),
00360                                       pp::Vec2d(450,36),
00361                                       "listbox_item",
00362                                       m_raceList);
00363               
00364               mp_raceListBox->alignment.center();
00365               mp_raceListBox->signalChange.Connect(pp::CreateSlot(this,&HighscoreShow::updateStatus));
00366               
00367               curCourse=Highscore->posFromString((*courses.begin()));
00368               
00369               
00370               //curCourse=0;
00371               pos.y-=20;
00372               
00373 
00374            
00375             for(int i=0;i<10;i++) {
00376                  pos.y-=30;
00377                  char buff[50];
00378                  sprintf(buff, "%s - %s",highscore::posToStr(i+1).c_str(),Highscore->level_hs[curCourse].post[i].toString().c_str());
00379               mp_post[i] = new pp::Label(pos,"menu_label",buff);
00380                      mp_post[i]->alignment.center();
00381             }
00382      } else {
00383        //No records stored
00384               pos.y-=60;
00385               m_raceList = Highscore->getCourseList_hd();
00386               mp_raceListBox = new pp::Listbox<HighscoreData>(pp::Vec2d(pos.x-200,pos.y),
00387                                       pp::Vec2d(450,36),
00388                                       "listbox_item",
00389                                       m_raceList);
00390               
00391               mp_raceListBox->alignment.center();
00392               
00393               
00394               
00395               //curCourse=0;
00396               pos.y-=20;
00397               
00398 
00399            
00400             for(int i=0;i<10;i++) {
00401                  pos.y-=30;
00402                  char buff[50];
00403                  sprintf(buff, "");
00404               mp_post[i] = new pp::Label(pos,"menu_label",buff);
00405                      mp_post[i]->alignment.center();
00406             }
00407      }
00408      pos.y-=50;
00409      
00410      mp_backBtn = new pp::Button( pp::Vec2d(pos.x-50,pos.y),
00411                            pp::Vec2d(100, 40), 
00412                            "button_label", 
00413                            _("Back") );
00414        mp_backBtn->setHilitFontBinding( "button_label_hilit" );
00415        mp_backBtn->alignment.center();
00416      mp_backBtn->signalClicked.Connect(pp::CreateSlot(this,&HighscoreShow::back));
00417      
00418  }
00419  
00420 bool
00421 HighscoreShow::keyReleaseEvent(SDLKey key)
00422 {
00423        switch (key){
00424               case SDLK_ESCAPE:
00425               case 'q':
00426                      back();
00427               return true;
00428               default:
00429                      return false;
00430        }      
00431 }
00432 
00433 void
00434 HighscoreShow::back()
00435 {
00436        set_game_mode( GAME_TYPE_SELECT );
00437        UIMgr.setDirty();
00438        
00439 }
00440 
00441 void
00442 HighscoreShow::loop(float timeStep)
00443 {
00444     update_audio();
00445     set_gl_options( GUI );
00446     clear_rendering_context();
00447     UIMgr.setupDisplay();
00448        drawSnow(timeStep);
00449     theme.drawMenuDecorations();
00450     UIMgr.draw();
00451     reshape( getparam_x_resolution(), getparam_y_resolution() );
00452     winsys_swap_buffers();
00453 }
00454   
00455 void
00456 HighscoreShow::updateStatus()
00457 {      
00458        HighscoreData tmp2=(*mp_raceListBox->getCurrentItem());
00459        std::string tmp= tmp2.name;
00460        //std::cout<<"Selected "<<tmp<<std::endl;
00461        curCourse=Highscore->posFromString(tmp);
00462      for(int i=0;i<10;i++) {
00463        char buff[50];
00464        sprintf(buff,"%s - %s",highscore::posToStr(i+1).c_str(),Highscore->level_hs[curCourse].post[i].toString().c_str());
00465        mp_post[i]->setText(buff);
00466      } 
00467 }
00468 
00469 HighscoreShow::~HighscoreShow() {
00470        delete mp_titleLbl;
00471        delete mp_raceListBox;
00472        delete mp_backBtn;
00473        for(int i=0;i<10;i++) {
00474               delete mp_post[i];
00475        }
00476 }
00477