• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kgoldrunner

kgrgameio.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *  Copyright (C) 2006 by Ian Wadham
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Lesser General Public
00015  *  License along with this library; if not, write to the 
00016  *  Free Software Foundation, Inc., 
00017  *  51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00018  ***************************************************************************/
00019 
00020 
00021 #include "kgrgameio.h"
00022 #include <KDebug>
00023 #include <QDir>
00024 
00025 KGrGameIO::KGrGameIO()
00026 {
00027 }
00028 
00029 IOStatus KGrGameIO::fetchGameListData
00030         (const QString & dir, QList<GameData *> & gameList)
00031 {
00032     QDir directory (dir);
00033     QStringList pattern;
00034     pattern << "game_*";
00035     QStringList files = directory.entryList (pattern, QDir::Files, QDir::Name);
00036 
00037     // KGr 3 has a game's data and all its levels in one file.
00038     // KGr 2 has all game-data in "games.dat" and each level in a separate file.
00039     bool kgr3Format = (files.count() > 0);
00040     if (! kgr3Format) {
00041         files << "games.dat";
00042     }
00043 
00044     // Loop to read each file containing game-data.
00045     foreach (const QString &filename, files) {
00046         if (filename == "game_ende.txt") {
00047             continue;           // Skip the "ENDE" file.
00048         }
00049 
00050         GameData * g = initGameData (dir + filename);
00051         gameList.append (g);
00052         // kDebug()<< "GAME PATH:" << g->filePath;
00053 
00054         openFile.setFileName (g->filePath);
00055 
00056         // Check that the game-file exists.
00057         if (! openFile.exists()) {
00058             return (NotFound);
00059         }
00060 
00061         // Open the file for read-only.
00062         if (! openFile.open (QIODevice::ReadOnly)) {
00063             return (NoRead);
00064         }
00065 
00066         char c;
00067         QByteArray textLine;
00068 
00069         // Find the first line of game-data.
00070         c = getALine (kgr3Format, textLine);
00071         if (kgr3Format) {
00072             while ((c != 'G') && (c != '\0')) {
00073                 c = getALine (kgr3Format, textLine);
00074             }
00075         }
00076         if (c == '\0') {
00077             openFile.close();
00078             return (UnexpectedEOF); // We reached end-of-file unexpectedly.
00079         }
00080 
00081         // Loop to extract the game-data for each game on the file.
00082         while (c != '\0') {
00083             if (kgr3Format && (c == 'L')) {
00084                 break;          // End of KGr 3 game-file header.
00085             }
00086             // Decode line 1 of the game-data.
00087             QList<QByteArray> fields = textLine.split (' ');
00088             g->nLevels = fields.at (0).toInt();
00089             g->rules   = fields.at (1).at (0);
00090             g->prefix  = fields.at (2);
00091             // kDebug() << "Levels:" << g->nLevels << "Rules:" << g->rules <<
00092                 // "Prefix:" << g->prefix;
00093 
00094             if (kgr3Format) {
00095                 // KGr 3 Format: get skill, get game-name from next line.
00096                 g->skill = fields.at (3).at (0);
00097                 c = getALine (kgr3Format, textLine);
00098                 if (c == ' ') {
00099                     g->name = removeNewline (textLine);
00100                 }
00101             }
00102             else {
00103                 // KGr 2 Format: get game-name from end of line 1.
00104                 int n = 0;
00105                 // Skip the first 3 fields and extract the rest of the line.
00106                 n = textLine.indexOf (' ', n) + 1;
00107                 n = textLine.indexOf (' ', n) + 1;
00108                 n = textLine.indexOf (' ', n) + 1;
00109                 g->name = removeNewline (textLine.right (textLine.size() - n));
00110             }
00111             // kDebug() << "Skill:" << g->skill << "Name:" << g->name;
00112 
00113             // Loop to accumulate lines of about-data.  If kgr3Format, exit on
00114             // EOF or 'L' line.  If not kgr3Format, exit on EOF or numeric line.
00115             while (c != '\0') {
00116                 c = getALine (kgr3Format, textLine);
00117                 if ((c == '\0') ||
00118                     (kgr3Format && (c == 'L')) ||
00119                     ((! kgr3Format) &&
00120                     (textLine.at (0) >= '0') && (textLine.at (0) <= '9'))) {
00121                     break;
00122                 }
00123                 g->about.append (textLine);
00124             }
00125             g->about = removeNewline (g->about);    // Remove final '\n'.
00126             // kDebug() << "Info about: [" + g->about + "]";
00127 
00128             if ((! kgr3Format) && (c != '\0')) {
00129                 g = initGameData (dir + filename);
00130                 gameList.append (g);
00131             }
00132         } // END: game-data loop
00133 
00134         openFile.close();
00135 
00136     } // END: filename loop
00137 
00138     return (OK);
00139 }
00140 
00141 IOStatus KGrGameIO::fetchLevelData
00142         (const QString & dir, const QString & prefix,
00143                 const int level, LevelData & d)
00144 {
00145     d.filePath = getFilePath (dir, prefix, level);
00146     d.level  = level;       // Level number.
00147     d.layout = "";      // Codes for the level layout (mandatory).
00148     d.name   = "";      // Level name (optional).
00149     d.hint   = "";      // Level hint (optional).
00150 
00151     // kDebug()<< "LEVEL PATH:" << d.filePath;
00152     openFile.setFileName (d.filePath);
00153 
00154     // Check that the level-file exists.
00155     if (! openFile.exists()) {
00156         return (NotFound);
00157     }
00158 
00159     // Open the file for read-only.
00160     if (! openFile.open (QIODevice::ReadOnly)) {
00161         return (NoRead);
00162     }
00163 
00164     char c;
00165     QByteArray textLine;
00166     IOStatus result = UnexpectedEOF;
00167 
00168     // Determine whether the file is in KGoldrunner v3 or v2 format.
00169     bool kgr3Format = (d.filePath.endsWith (".txt"));
00170 
00171     if (kgr3Format) {
00172         // In KGr 3 format, if a line starts with 'L', check the number.
00173         while ((c = getALine (kgr3Format, textLine)) != '\0') {
00174             if ((c == 'L') && (textLine.left (3).toInt() == level)) {
00175                 break;          // We have found the required level.
00176             } 
00177         }
00178         if (c == '\0') {
00179             openFile.close();       // We reached end-of-file.
00180             return (UnexpectedEOF);
00181         }
00182     }  
00183 
00184     // Read in the character-codes for the level layout.
00185     if ((c = getALine (kgr3Format, textLine)) == ' ') {
00186         result = OK;
00187         d.layout = removeNewline (textLine);        // Remove '\n'.
00188 
00189         // Look for a line containing a level name (optional).
00190         if ((c = getALine (kgr3Format, textLine)) == ' ') {
00191             d.name = removeNewline (textLine);      // Remove '\n'.
00192 
00193             // Look for one or more lines containing a hint (optional).
00194             while ((c = getALine (kgr3Format, textLine)) == ' ') {
00195                 d.hint.append (textLine);
00196             }
00197             d.hint = removeNewline (d.hint);        // Remove final '\n'.
00198         }
00199     }
00200 
00201     // kDebug() << "Level:" << level << "Layout length:" << d.layout.size();
00202     // kDebug() << "Name:" << "[" + d.name + "]";
00203     // kDebug() << "Hint:" << "[" + d.hint + "]";
00204 
00205     openFile.close();
00206     return (result);
00207 }
00208 
00209 QString KGrGameIO::getFilePath
00210         (const QString & dir, const QString & prefix, const int level)
00211 {
00212     QString filePath = ((level == 0) ? "ende" : prefix);
00213     filePath = dir + "game_" + filePath + ".txt";
00214     QFile test (filePath);
00215 
00216     // See if there is a game-file or "ENDE" screen in KGoldrunner 3 format.
00217     if (test.exists()) {
00218         return (filePath);
00219     }
00220 
00221     // If not, we are looking for a file in KGoldrunner 2 format.
00222     if (level == 0) {
00223         // End of game: show the "ENDE" screen.
00224         filePath = dir + "levels/level000.grl";
00225     }
00226     else {
00227         QString num;
00228         num.setNum (level);         // Convert INT -> QString.
00229         num = num.rightJustified (3,'0');   // Add 0-2 zeros at left.
00230         filePath = dir + "levels/" + prefix + num + ".grl";
00231     }
00232 
00233     return (filePath);
00234 }
00235 
00236 char KGrGameIO::getALine (const bool kgr3, QByteArray & line)
00237 {
00238     char c;
00239     line = "";
00240     while (openFile.getChar (&c)) {
00241         line = line.append (c);
00242         if (c == '\n') {
00243             break;
00244         }
00245     }
00246 
00247     // kDebug() << "Raw line:" << line;
00248     if (line.size() <= 0) {
00249         // Return a '\0' byte if end-of-file.
00250         return ('\0');
00251     }
00252     if (kgr3) {
00253         // In KGr 3 format, strip off leading and trailing syntax.
00254         if (line.startsWith ("// ")) {
00255             line = line.right (line.size() - 3);
00256             // kDebug() << "Stripped comment is:" << line;
00257         }
00258         else {
00259             if (line.startsWith (" i18n(\"")) {
00260                 line = ' ' + line.right (line.size() - 7);
00261             }
00262             else if (line.startsWith (" NOTi18n(\"")) {
00263                 line = ' ' + line.right (line.size() - 10);
00264             }
00265             else if (line.startsWith (" \"")) {
00266                 line = ' ' + line.right (line.size() - 2);
00267             }
00268             if (line.endsWith ("\");\n")) {
00269                 line = line.left (line.size() - 4) + '\n';
00270             }
00271             else if (line.endsWith ("\\n\"\n")) {
00272                 line = line.left (line.size() - 4) + '\n';
00273             }
00274             else if (line.endsWith ("\"\n")) {
00275                 line = line.left (line.size() - 2);
00276             }
00277             // kDebug() << "Stripped syntax is:" << line;
00278         }
00279         // In Kgr 3 format, return the first byte if not end-of-file.
00280         c = line.at (0);
00281         line = line.right (line.size() - 1);
00282         return (c);
00283     }
00284     else {
00285         // In KGr 2 format, return a space if not end-of-file.
00286         return (' ');
00287     }
00288 }
00289 
00290 QByteArray KGrGameIO::removeNewline (const QByteArray & line)
00291 {
00292     int len = line.size();
00293     if ((len > 0) && (line.endsWith ('\n'))) {
00294         return (line.left (len -1));
00295     }
00296     else {
00297         return (line);
00298     }
00299 }
00300 
00301 GameData * KGrGameIO::initGameData (const QString & filePath)
00302 {
00303     GameData * g = new GameData;
00304     g->filePath = filePath;
00305     g->owner    = USER; // Owner of the game: "System" or "User".
00306     g->nLevels  = 0;    // Number of levels in the game.
00307     g->rules    = 'T';  // Game's rules: KGoldrunner or Traditional.
00308     g->prefix   = "";   // Game's filename prefix.
00309     g->skill    = 'N';  // Game's skill: Tutorial, Normal or Champion.
00310     g->name     = "";   // Name of the game.
00311     g->about    = "";   // Optional text about the game.
00312     return (g);
00313 }
00314 
00315 #include "kgrgameio.moc"

kgoldrunner

Skip menu "kgoldrunner"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members

API Reference

Skip menu "API Reference"
  • kblackbox
  • kgoldrunner
  • kmahjongg
  • ksquares
  • libkdegames
  •   highscore
  •   kgame
  •   kggzgames
  •   kggzmod
  •   kggznet
  • libkmahjongg
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal