00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "kgrgame.h"
00012
00013 #include "kgrconsts.h"
00014 #include "kgrobject.h"
00015 #include "kgrfigure.h"
00016 #include "kgrcanvas.h"
00017 #include "kgrdialog.h"
00018
00019
00020 #include <iostream>
00021 #include <stdlib.h>
00022 #include <ctype.h>
00023 #include <time.h>
00024
00025 #include <kpushbutton.h>
00026 #include <KStandardGuiItem>
00027 #include <KApplication>
00028 #include <kdebug.h>
00029
00030
00031
00032
00033
00034 #ifdef USE_KSCOREDIALOG
00035 #include <KScoreDialog>
00036 #include <QDate>
00037 #else
00038
00039 #include <QByteArray>
00040 #include <QTextStream>
00041 #include <QLabel>
00042 #include <QVBoxLayout>
00043 #include <QDate>
00044 #include <QSpacerItem>
00045 #include <QTreeWidget>
00046 #include <QHeaderView>
00047 #include <QTreeWidgetItem>
00048 #include <QDir>
00049
00050 #endif
00051
00052
00053
00054
00055
00056 KGrGame::KGrGame (KGrCanvas * theView,
00057 const QString &theSystemDir, const QString &theUserDir) :
00058 view(theView), systemDataDir(theSystemDir), userDataDir(theUserDir), level(0)
00059 {
00060
00061
00062
00063
00064
00065 editMode = false;
00066 paintEditObj = false;
00067 paintAltObj = false;
00068 editObj = BRICK;
00069 shouldSave = false;
00070
00071 hero = new KGrHero (view, 0, 0);
00072 hero->setPlayfield (&playfield);
00073
00074 setBlankLevel (true);
00075
00076 enemy = NULL;
00077 newLevel = true;
00078 loading = true;
00079
00080 modalFreeze = false;
00081 messageFreeze = false;
00082
00083 connect (hero, SIGNAL (gotNugget(int)), SLOT (incScore(int)));
00084 connect (hero, SIGNAL (caughtHero()), SLOT (herosDead()));
00085 connect (hero, SIGNAL (haveAllNuggets()), SLOT (showHiddenLadders()));
00086 connect (hero, SIGNAL (leaveLevel()), SLOT (goUpOneLevel()));
00087
00088 dyingTimer = new QTimer (this);
00089 connect (dyingTimer, SIGNAL (timeout()), SLOT (finalBreath()));
00090
00091
00092 mouseSampler = new QTimer (this);
00093 connect (mouseSampler, SIGNAL(timeout()), SLOT (readMousePos ()));
00094 mouseSampler->start (40);
00095
00096 srand (time(0));
00097 }
00098
00099 KGrGame::~KGrGame()
00100 {
00101
00102 while (!collections.isEmpty())
00103 delete collections.takeFirst();
00104 }
00105
00106
00107
00108
00109
00110 void KGrGame::quickStartDialog()
00111 {
00112
00113 freeze();
00114
00115 qs = new KDialog (view);
00116
00117
00118 qs->setModal (true);
00119 qs->setCaption ("Quick Start");
00120 qs->setButtons
00121 (KDialog::Ok | KDialog::Cancel | KDialog::User1 | KDialog::User2);
00122 qs->setButtonFocus (KDialog::Ok);
00123 qs->setButtonsOrientation (Qt::Vertical);
00124
00125
00126 qs->setButtonText (KDialog::Ok,
00127 i18nc("Button text: start playing a game", "&PLAY"));
00128 qs->setButtonToolTip (KDialog::Ok, i18n("Start playing this level"));
00129 qs->setButtonWhatsThis (KDialog::Ok,
00130 i18n("Set up to start playing the game and level being shown, "
00131 "as soon as you click, move the mouse or press a key"));
00132
00133
00134 qs->setButtonText (KDialog::Cancel, i18n("&Quit"));
00135 qs->setButtonToolTip (KDialog::Cancel, i18n("Close KGoldrunner"));
00136
00137
00138 qs->setButtonText (KDialog::User1, i18n("&New Game..."));
00139 qs->setButtonToolTip (KDialog::User1,
00140 i18n("Start a different game or level"));
00141 qs->setButtonWhatsThis (KDialog::User1,
00142 i18n("Use the Select Game dialog box to choose a "
00143 "different game or level and start playing it"));
00144
00145
00146 qs->setButtonText (KDialog::User2, i18n("&Use Menu"));
00147 qs->setButtonToolTip (KDialog::User2,
00148 i18n("Use the menus to choose other actions"));
00149 qs->setButtonWhatsThis (KDialog::User2,
00150 i18n("Before playing, use the menus to choose other actions, "
00151 "such as loading a saved game or changing the theme"));
00152
00153
00154 QLabel * logo = new QLabel();
00155 qs->setMainWidget (logo);
00156 logo->setPixmap (kapp->windowIcon().pixmap (240));
00157 logo->setAlignment (Qt::AlignTop | Qt::AlignHCenter);
00158
00159 connect (qs, SIGNAL (okClicked()), this, SLOT (quickStartPlay()));
00160 connect (qs, SIGNAL (user1Clicked()), this, SLOT (quickStartNewGame()));
00161 connect (qs, SIGNAL (user2Clicked()), this, SLOT (quickStartUseMenu()));
00162 connect (qs, SIGNAL (cancelClicked()), this, SLOT (quickStartQuit()));
00163
00164 qs->show();
00165 }
00166
00167 void KGrGame::quickStartPlay()
00168 {
00169
00170
00171 qs->hide();
00172 showTutorialMessages (level);
00173 unfreeze();
00174 }
00175
00176 void KGrGame::quickStartNewGame()
00177 {
00178 qs->accept();
00179 unfreeze();
00180 startAnyLevel();
00181 }
00182
00183 void KGrGame::quickStartUseMenu()
00184 {
00185 qs->accept();
00186 myMessage (view, i18n("Game Paused"),
00187 i18n("The game is halted. You will need to press the Pause key "
00188 "(default P or Esc) when you are ready to play."));
00189 }
00190
00191 void KGrGame::quickStartQuit()
00192 {
00193 emit quitGame();
00194 }
00195
00196
00197
00198
00199
00200 void KGrGame::startLevelOne()
00201 {
00202 startLevel (SL_START, 1);
00203 }
00204
00205 void KGrGame::startAnyLevel()
00206 {
00207 startLevel (SL_ANY, level);
00208 }
00209
00210 void KGrGame::startNextLevel()
00211 {
00212 startLevel (SL_ANY, level + 1);
00213 }
00214
00215 void KGrGame::startLevel (int startingAt, int requestedLevel)
00216 {
00217 if (! saveOK (false)) {
00218 return;
00219 }
00220
00221 int selectedLevel = selectLevel (startingAt, requestedLevel);
00222 if (selectedLevel > 0) {
00223 newGame (selectedLevel, selectedGame);
00224 showTutorialMessages (level);
00225 } else {
00226 level = 0;
00227 }
00228 }
00229
00230
00231
00232
00233
00234 void KGrGame::incScore (int n)
00235 {
00236 score = score + n;
00237 emit showScore (score);
00238 }
00239
00240 void KGrGame::herosDead()
00241 {
00242 if ((level < 1) || (lives <= 0))
00243 return;
00244
00245
00246 if (--lives > 0) {
00247
00248 emit showLives (lives);
00249 KGrObject::frozen = true;
00250 dyingTimer->setSingleShot(true);
00251 dyingTimer->start (1500);
00252 view->fadeOut();
00253 }
00254 else {
00255
00256 emit showLives (lives);
00257 freeze();
00258 QString gameOver = "<NOBR><B>" + i18n("GAME OVER !!!") + "</B></NOBR>";
00259 KGrMessage::information (view, collection->name, gameOver);
00260 checkHighScore();
00261
00262
00263 switch (KGrMessage::warning (view, i18n("Retry Level?"),
00264 i18n("Would you like to try this level again?"),
00265 i18n("&Try Again"), i18n("&Finish"))) {
00266 case 0:
00267 unfreeze();
00268 newGame (level, collnIndex);
00269 showTutorialMessages (level);
00270 return;
00271 break;
00272 case 1:
00273 break;
00274 }
00275
00276
00277 enemyCount = 0;
00278
00279 while (!enemies.isEmpty())
00280 delete enemies.takeFirst();
00281
00282 view->deleteEnemySprites();
00283 unfreeze();
00284 newLevel = true;
00285 level = 0;
00286 loadLevel (level);
00287 newLevel = false;
00288 }
00289 }
00290
00291 void KGrGame::finalBreath()
00292 {
00293
00294
00295 if (! editMode) {
00296 enemyCount = 0;
00297 loadLevel (level);
00298 }
00299 KGrObject::frozen = false;
00300 }
00301
00302 void KGrGame::showHiddenLadders()
00303 {
00304 int i,j;
00305 for (i=1;i<21;i++)
00306 for (j=1;j<29;j++)
00307 if (playfield[j][i]->whatIam()==HLADDER)
00308 ((KGrHladder *)playfield[j][i])->showLadder();
00309 initSearchMatrix();
00310 }
00311
00312 void KGrGame::goUpOneLevel()
00313 {
00314 lives++;
00315 emit showLives (lives);
00316 incScore (1500);
00317
00318 if (level >= collection->nLevels) {
00319 freeze();
00320 KGrMessage::information (view, collection->name,
00321 i18n("<b>CONGRATULATIONS !!!!</b>"
00322 "<p>You have conquered the last level in the "
00323 "<b>\"%1\"</b> game !!</p>", collection->name));
00324 checkHighScore();
00325
00326 unfreeze();
00327 level = 0;
00328 }
00329 else {
00330 level++;
00331 emit showLevel (level);
00332 }
00333
00334 enemyCount = 0;
00335
00336 while (!enemies.isEmpty())
00337 delete enemies.takeFirst();
00338
00339 view->deleteEnemySprites();
00340 newLevel = true;
00341 loadLevel (level);
00342 showTutorialMessages (level);
00343 newLevel = false;
00344 }
00345
00346 void KGrGame::loseNugget()
00347 {
00348 hero->loseNugget();
00349 }
00350
00351 KGrHero * KGrGame::getHero()
00352 {
00353 return (hero);
00354 }
00355
00356 int KGrGame::getLevel()
00357 {
00358 return (level);
00359 }
00360
00361 bool KGrGame::inMouseMode()
00362 {
00363 return (mouseMode);
00364 }
00365
00366 bool KGrGame::inEditMode()
00367 {
00368 return (editMode);
00369 }
00370
00371 bool KGrGame::isLoading()
00372 {
00373 return (loading);
00374 }
00375
00376 void KGrGame::setMouseMode (bool on_off)
00377 {
00378 mouseMode = on_off;
00379 }
00380
00381 void KGrGame::freeze()
00382 {
00383 if ((! modalFreeze) && (! messageFreeze)) {
00384 emit gameFreeze (true);
00385 }
00386 KGrObject::frozen = true;
00387 }
00388
00389 void KGrGame::unfreeze()
00390 {
00391 if ((! modalFreeze) && (! messageFreeze)) {
00392 emit gameFreeze (false);
00393 }
00394 KGrObject::frozen = false;
00395 restart();
00396 }
00397
00398 void KGrGame::setMessageFreeze (bool on_off)
00399 {
00400 if (on_off) {
00401 messageFreeze = false;
00402 if (! KGrObject::frozen) {
00403 messageFreeze = true;
00404 freeze();
00405 }
00406 }
00407 else {
00408 if (messageFreeze) {
00409 unfreeze();
00410 messageFreeze = false;
00411 }
00412 }
00413 }
00414
00415 void KGrGame::setBlankLevel(bool playable)
00416 {
00417 for (int j=0;j<20;j++)
00418 for (int i=0;i<28;i++) {
00419 if (playable) {
00420
00421 playfield[i+1][j+1] = new KGrFree (FREE,i+1,j+1,view);
00422 }
00423 else {
00424
00425 playfield[i+1][j+1] = new KGrEditable (FREE);
00426 view->paintCell (i+1, j+1, FREE);
00427 }
00428 editObjArray[i+1][j+1] = FREE;
00429 }
00430 for (int j=0;j<30;j++) {
00431
00432 playfield[j][0]=new KGrObject (BETON);
00433 editObjArray[j][0] = BETON;
00434
00435 playfield[j][21]=new KGrObject (BETON);
00436 editObjArray[j][21] = BETON;
00437 }
00438 for (int i=0;i<22;i++) {
00439
00440 playfield[0][i]=new KGrObject (BETON);
00441 editObjArray[0][i] = BETON;
00442
00443 playfield[29][i]=new KGrObject (BETON);
00444 editObjArray[29][i] = BETON;
00445 }
00446
00447
00448
00449
00450 }
00451
00452 void KGrGame::newGame (const int lev, const int gameIndex)
00453 {
00454
00455 loading = true;
00456
00457 view->goToBlack();
00458 if (editMode) {
00459 emit setEditMenu (false);
00460
00461 editMode = false;
00462 paintEditObj = false;
00463 paintAltObj = false;
00464 editObj = BRICK;
00465
00466 view->setHeroVisible (true);
00467 }
00468
00469 newLevel = true;
00470
00471
00472
00473
00474 if (lev >= 0) {
00475 level = lev;
00476 collnIndex = gameIndex;
00477 }
00478 collection = collections.at (collnIndex);
00479 owner = collection->owner;
00480
00481 lives = 5;
00482 score = 0;
00483 startScore = 0;
00484
00485 emit showLives (lives);
00486 emit showScore (score);
00487 emit showLevel (level);
00488
00489 enemyCount = 0;
00490
00491
00492 while (!enemies.isEmpty())
00493 delete enemies.takeFirst();
00494
00495 view->deleteEnemySprites();
00496
00497 newLevel = true;;
00498 loadLevel (level);
00499 newLevel = false;
00500 }
00501
00502 void KGrGame::startTutorial()
00503 {
00504 if (! saveOK (false)) {
00505 return;
00506 }
00507
00508 int i, index;
00509 int imax = collections.count();
00510 bool found = false;
00511
00512 index = 0;
00513 for (i = 0; i < imax; i++) {
00514 index = i;
00515 if (collections.at(i)->prefix == "tute") {
00516 found = true;
00517 break;
00518 }
00519 }
00520 if (found) {
00521
00522 collection = collections.at (index);
00523 owner = collection->owner;
00524 emit markRuleType (collection->settings);
00525 collnIndex = index;
00526 level = 1;
00527 newGame (level, collnIndex);
00528 showTutorialMessages (level);
00529 }
00530 else {
00531 KGrMessage::information (view, i18n("Start Tutorial"),
00532 i18n("Cannot find the tutorial game (file-prefix '%1') in "
00533 "the '%2' files.",
00534 QString("tute"), QString("games.dat")));
00535 }
00536 }
00537
00538 void KGrGame::showHint()
00539 {
00540
00541 QString caption = i18n("Hint");
00542
00543 if (levelHint.length() > 0)
00544 myMessage (view, caption, levelHint);
00545 else
00546 myMessage (view, caption,
00547 i18n("Sorry, there is no hint for this level."));
00548 }
00549
00550 int KGrGame::loadLevel (int levelNo)
00551 {
00552
00553 loading = true;
00554
00555
00556 LevelData d;
00557 if (! readLevelData (levelNo, d)) {
00558 loading = false;
00559 return 0;
00560 }
00561
00562 view->setLevel(levelNo);
00563 view->fadeIn();
00564 nuggets = 0;
00565 enemyCount=0;
00566 startScore = score;
00567
00568 int i, j;
00569
00570 for (j = 1; j <= FIELDHEIGHT; j++) {
00571 for (i = 1; i <= FIELDWIDTH; i++) {
00572 changeObject (d.layout.at ((j-1)*FIELDWIDTH + (i-1)), i , j);
00573 }
00574 }
00575
00576
00577 levelName = (d.name.size() > 0) ? i18n((const char *) d.name) : "";
00578
00579
00580 int len = d.hint.length();
00581 emit hintAvailable (len > 0);
00582
00583
00584 levelHint = (len > 0) ? i18n((const char *) d.hint) : "";
00585
00586
00587 disconnect (view, SIGNAL (mouseClick(int)), 0, 0);
00588 disconnect (view, SIGNAL (mouseLetGo(int)), 0, 0);
00589
00590 if (newLevel) {
00591 hero->setEnemyList (&enemies);
00592 QListIterator<KGrEnemy *> i (enemies);
00593 while (i.hasNext()) {
00594 KGrEnemy * enemy = i.next();
00595 enemy->setEnemyList (&enemies);
00596 }
00597 }
00598
00599 hero->setNuggets (nuggets);
00600 setTimings();
00601
00602
00603 if (KGrFigure::reappearAtTop && (enemies.count() > 0)) {
00604 KGrEnemy::makeReappearanceSequence();
00605 }
00606
00607
00608 initSearchMatrix();
00609
00610
00611 view->setTitle (getTitle());
00612
00613
00614 if (mouseMode) {
00615 view->setMousePos (startI, startJ);
00616 }
00617
00618
00619 if (newLevel) {
00620 KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
00621 gameGroup.writeEntry ("GamePrefix", collection->prefix);
00622 gameGroup.writeEntry ("Level_" + collection->prefix, level);
00623 gameGroup.sync();
00624 }
00625
00626
00627 connect (view, SIGNAL(mouseClick(int)), SLOT(doDig(int)));
00628
00629
00630 loading = false;
00631
00632 return 1;
00633 }
00634
00635 void KGrGame::showTutorialMessages (int levelNo)
00636 {
00637
00638 setMessageFreeze (true);
00639
00640
00641 if ((collection->prefix.left(4) == "tute") && (levelNo != 0)) {
00642
00643
00644 if (levelNo == 1) {
00645 KGrMessage::information (view, collection->name,
00646 i18n(collection->about.toUtf8().constData()));
00647 }
00648
00649 KGrMessage::information (view, getTitle(), levelHint);
00650 }
00651
00652
00653 if (mouseMode) {
00654 view->setMousePos (startI, startJ);
00655 }
00656 setMessageFreeze (false);
00657 }
00658
00659 bool KGrGame::readLevelData (int levelNo, LevelData & d)
00660 {
00661 KGrGameIO io;
00662
00663 const QString dir = ((owner == SYSTEM) || (levelNo == 0)) ?
00664 systemDataDir : userDataDir;
00665 IOStatus stat = io.fetchLevelData (dir, collection->prefix, levelNo, d);
00666
00667 switch (stat) {
00668 case NotFound:
00669 KGrMessage::information (view, i18n("Read Level Data"),
00670 i18n("Cannot find file '%1'.", d.filePath));
00671 break;
00672 case NoRead:
00673 case NoWrite:
00674 KGrMessage::information (view, i18n("Read Level Data"),
00675 i18n("Cannot open file '%1' for read-only.", d.filePath));
00676 break;
00677 case UnexpectedEOF:
00678 KGrMessage::information (view, i18n("Read Level Data"),
00679 i18n("Reached end of file '%1' without finding level data.",
00680 d.filePath));
00681 break;
00682 case OK:
00683 break;
00684 }
00685
00686 return (stat == OK);
00687 }
00688
00689 void KGrGame::changeObject (unsigned char kind, int i, int j)
00690 {
00691 delete playfield[i][j];
00692 switch(kind) {
00693 case FREE: createObject(new KGrFree (FREE,i,j,view),FREE,i,j);break;
00694 case LADDER: createObject(new KGrObject (LADDER),LADDER,i,j);break;
00695 case HLADDER: createObject(new KGrHladder (HLADDER,i,j,view),FREE,i,j);break;
00696 case BRICK: createObject(new KGrBrick (BRICK,i,j,view),BRICK,i,j);break;
00697 case BETON: createObject(new KGrObject (BETON),BETON,i,j);break;
00698 case FBRICK: createObject(new KGrObject (FBRICK),BRICK,i,j);break;
00699 case POLE: createObject(new KGrObject (POLE),POLE,i,j);break;
00700 case NUGGET: createObject(new KGrFree (NUGGET,i,j,view),NUGGET,i,j);
00701 nuggets++;break;
00702 case HERO: createObject(new KGrFree (FREE,i,j,view),FREE,i,j);
00703 hero->init(i,j);
00704 startI = i; startJ = j;
00705 hero->started = false;
00706 hero->showFigure();
00707 break;
00708 case ENEMY: createObject(new KGrFree (FREE,i,j,view),FREE,i,j);
00709 if (newLevel){
00710
00711 enemy = new KGrEnemy (view, i, j);
00712 enemy->setPlayfield(&playfield);
00713 enemy->enemyId = enemyCount++;
00714 enemies.append(enemy);
00715 connect(enemy, SIGNAL(lostNugget()), SLOT(loseNugget()));
00716 connect(enemy, SIGNAL(trapped(int)), SLOT(incScore(int)));
00717 connect(enemy, SIGNAL(killed(int)), SLOT(incScore(int)));
00718 } else {
00719
00720 enemy=enemies.at(enemyCount);
00721 enemy->enemyId=enemyCount++;
00722 enemy->setNuggets(0);
00723 enemy->init(i,j);
00724 }
00725 enemy->showFigure();
00726 break;
00727 default : createObject(new KGrBrick(BRICK,i,j,view),BRICK,i,j);break;
00728 }
00729 }
00730
00731 void KGrGame::createObject (KGrObject *o, char picType, int x, int y)
00732 {
00733 playfield[x][y] = o;
00734 view->paintCell (x, y, picType);
00735 }
00736
00737 void KGrGame::setTimings ()
00738 {
00739 Timing * timing;
00740 int c = -1;
00741
00742 if (KGrFigure::variableTiming) {
00743 c = enemies.count();
00744 c = (c > 5) ? 5 : c;
00745 timing = &(KGrFigure::varTiming[c]);
00746 }
00747 else {
00748 timing = &(KGrFigure::fixedTiming);
00749 }
00750
00751 KGrHero::WALKDELAY = timing->hwalk;
00752 KGrHero::FALLDELAY = timing->hfall;
00753 KGrEnemy::WALKDELAY = timing->ewalk;
00754 KGrEnemy::FALLDELAY = timing->efall;
00755 KGrEnemy::CAPTIVEDELAY = timing->ecaptive;
00756 KGrBrick::HOLETIME = timing->hole;
00757 }
00758
00759 void KGrGame::initSearchMatrix()
00760 {
00761
00762 int i,j;
00763
00764 for (i=1;i<21;i++){
00765 for (j=1;j<29;j++)
00766 {
00767
00768 if (playfield[j][i]->whatIam()==LADDER)
00769 playfield[j][i]->searchValue = CANWALKLEFT + CANWALKRIGHT +
00770 CANWALKUP + CANWALKDOWN;
00771 else
00772
00773 if ((playfield[j][i+1]->whatIam()==BRICK)||
00774 (playfield[j][i+1]->whatIam()==HOLE)||
00775 (playfield[j][i+1]->whatIam()==USEDHOLE)||
00776 (playfield[j][i+1]->whatIam()==BETON))
00777 playfield[j][i]->searchValue=CANWALKLEFT+CANWALKRIGHT;
00778 else
00779
00780 if ((playfield[j][i]->whatIam()==POLE)||
00781 (playfield[j][i+1]->whatIam()==LADDER))
00782 playfield[j][i]->searchValue=CANWALKLEFT+CANWALKRIGHT+CANWALKDOWN;
00783 else
00784
00785 playfield[j][i]->searchValue=CANWALKDOWN;
00786
00787
00788 if(playfield[j][i-1]->blocker)
00789 playfield[j][i]->searchValue &= ~CANWALKUP;
00790 if(playfield[j-1][i]->blocker)
00791 playfield[j][i]->searchValue &= ~CANWALKLEFT;
00792 if(playfield[j+1][i]->blocker)
00793 playfield[j][i]->searchValue &= ~CANWALKRIGHT;
00794 if(playfield[j][i+1]->blocker)
00795 playfield[j][i]->searchValue &= ~CANWALKDOWN;
00796 }
00797 }
00798 }
00799
00800 void KGrGame::startPlaying () {
00801 if (! hero->started) {
00802
00803 for (--enemyCount; enemyCount>=0; --enemyCount) {
00804 enemy=enemies.at(enemyCount);
00805 enemy->startSearching();
00806 }
00807 hero->start();
00808 }
00809 }
00810
00811 QString KGrGame::getDirectory (Owner o)
00812 {
00813 return ((o == SYSTEM) ? systemDataDir : userDataDir);
00814 }
00815
00816 QString KGrGame::getFilePath (Owner o, KGrCollection * colln, int lev)
00817 {
00818 QString filePath;
00819
00820 if (lev == 0) {
00821
00822 o = SYSTEM;
00823 filePath = "level000.grl";
00824 }
00825 else {
00826 filePath.setNum (lev);
00827 filePath = filePath.rightJustified (3,'0');
00828 filePath.append (".grl");
00829 filePath.prepend (colln->prefix);
00830 }
00831
00832 filePath.prepend (((o == SYSTEM)? systemDataDir : userDataDir) + "levels/");
00833
00834 return (filePath);
00835 }
00836
00837 QString KGrGame::getTitle()
00838 {
00839 QString levelTitle;
00840 if (level == 0) {
00841
00842 if (! editMode)
00843 levelTitle = "E N D --- F I N --- E N D E";
00844 else
00845 levelTitle = i18n("New Level");
00846 }
00847 else {
00848
00849 levelTitle.setNum (level);
00850 levelTitle = levelTitle.rightJustified (3,'0');
00851 levelTitle = collection->name + " - " + levelTitle;
00852 if (levelName.length() > 0) {
00853 levelTitle = levelTitle + " - " + levelName;
00854 }
00855 }
00856 return (levelTitle);
00857 }
00858
00859 void KGrGame::readMousePos()
00860 {
00861 QPoint p;
00862 int i, j;
00863
00864
00865 if (loading) return;
00866
00867
00868 if ((! mouseMode) && (! editMode)) return;
00869
00870 p = view->getMousePos ();
00871 i = p.x(); j = p.y();
00872
00873 if (editMode) {
00874
00875 if (paintEditObj && ((i != oldI) || (j != oldJ))) {
00876 insertEditObj (i, j, editObj);
00877 oldI = i;
00878 oldJ = j;
00879 }
00880 if (paintAltObj && ((i != oldI) || (j != oldJ))) {
00881 insertEditObj (i, j, FREE);
00882 oldI = i;
00883 oldJ = j;
00884 }
00885
00886
00887 }
00888 else {
00889
00890 if (KGrObject::frozen) return;
00891
00892 hero->setDirection (i, j);
00893
00894
00895 if ((! hero->started) && ((i != startI) || (j != startJ))) {
00896 startPlaying();
00897 }
00898 }
00899 }
00900
00901 void KGrGame::doDig (int button) {
00902
00903
00904 if (editMode) return;
00905 if (! mouseMode) return;
00906
00907
00908 if ((! loading) && (! KGrObject::frozen)) {
00909 if (! hero->started) {
00910 startPlaying();
00911 }
00912 switch (button) {
00913 case Qt::LeftButton: hero->digLeft (); break;
00914 case Qt::RightButton: hero->digRight (); break;
00915 default: break;
00916 }
00917 }
00918 }
00919
00920 void KGrGame::heroAction (KBAction movement)
00921 {
00922 switch (movement) {
00923 case KB_UP: hero->setKey (UP); break;
00924 case KB_DOWN: hero->setKey (DOWN); break;
00925 case KB_LEFT: hero->setKey (LEFT); break;
00926 case KB_RIGHT: hero->setKey (RIGHT); break;
00927 case KB_STOP: hero->setKey (STAND); break;
00928 case KB_DIGLEFT: hero->setKey (STAND); hero->digLeft (); break;
00929 case KB_DIGRIGHT: hero->setKey (STAND); hero->digRight (); break;
00930 }
00931 }
00932
00933
00934
00935
00936
00937 void KGrGame::saveGame()
00938 {
00939 if (editMode) {myMessage (view, i18n("Save Game"),
00940 i18n("Sorry, you cannot save your game play while you are editing. "
00941 "Please try menu item \"%1\".",
00942 i18n("&Save Edits...")));
00943 return;
00944 }
00945 if (hero->started) {myMessage (view, i18n("Save Game"),
00946 i18n("Please note: for reasons of simplicity, your saved game "
00947 "position and score will be as they were at the start of this "
00948 "level, not as they are now."));
00949 }
00950
00951 QDate today = QDate::currentDate();
00952 QTime now = QTime::currentTime();
00953 QString saved;
00954 QString day;
00955 day = today.shortDayName(today.dayOfWeek());
00956 saved = saved.sprintf
00957 ("%-6s %03d %03ld %7ld %s %04d-%02d-%02d %02d:%02d\n",
00958 collection->prefix.myStr(), level, lives, startScore,
00959 day.myStr(),
00960 today.year(), today.month(), today.day(),
00961 now.hour(), now.minute());
00962
00963 QFile file1 (userDataDir + "savegame.dat");
00964 QFile file2 (userDataDir + "savegame.tmp");
00965
00966 if (! file2.open (QIODevice::WriteOnly)) {
00967 KGrMessage::information (view, i18n("Save Game"),
00968 i18n("Cannot open file '%1' for output.",
00969 userDataDir + "savegame.tmp"));
00970 return;
00971 }
00972 QTextStream text2 (&file2);
00973 text2 << saved;
00974
00975 if (file1.exists()) {
00976 if (! file1.open (QIODevice::ReadOnly)) {
00977 KGrMessage::information (view, i18n("Save Game"),
00978 i18n("Cannot open file '%1' for read-only.",
00979 userDataDir + "savegame.dat"));
00980 return;
00981 }
00982
00983 QTextStream text1 (&file1);
00984 int n = 30;
00985 while ((! text1.endData()) && (--n > 0)) {
00986 saved = text1.readLine() + '\n';
00987 text2 << saved;
00988 }
00989 file1.close();
00990 }
00991
00992 file2.close();
00993
00994 if (safeRename (userDataDir+"savegame.tmp", userDataDir+"savegame.dat")) {
00995 KGrMessage::information (view, i18n("Save Game"),
00996 i18n("Your game has been saved."));
00997 }
00998 else {
00999 KGrMessage::information (view, i18n("Save Game"),
01000 i18n("Error: Failed to save your game."));
01001 }
01002 }
01003
01004 bool KGrGame::safeRename (const QString & oldName, const QString & newName)
01005 {
01006 QFile newFile (newName);
01007 if (newFile.exists()) {
01008
01009
01010
01011
01012 if (! newFile.remove()) {
01013 KGrMessage::information (view, i18n("Rename File"),
01014 i18n("Cannot delete previous version of file '%1'.", newName));
01015 return false;
01016 }
01017 }
01018 QFile oldFile (oldName);
01019 if (! oldFile.rename (newName)) {
01020 KGrMessage::information (view, i18n("Rename File"),
01021 i18n("Cannot rename file '%1' to '%2'.", oldName, newName));
01022 return false;
01023 }
01024 return true;
01025 }
01026
01027 void KGrGame::loadGame()
01028 {
01029 if (! saveOK (false)) {
01030 return;
01031 }
01032
01033 QFile savedGames (userDataDir + "savegame.dat");
01034 if (! savedGames.exists()) {
01035
01036 myMessage (view, i18n("Load Game"),
01037 i18n("Sorry, there are no saved games."));
01038 return;
01039 }
01040
01041 if (! savedGames.open (QIODevice::ReadOnly)) {
01042 KGrMessage::information (view, i18n("Load Game"),
01043 i18n("Cannot open file '%1' for read-only.",
01044 userDataDir + "savegame.dat"));
01045 return;
01046 }
01047
01048
01049 modalFreeze = false;
01050 if (!KGrObject::frozen) {
01051 modalFreeze = true;
01052 freeze();
01053 }
01054
01055 QString s;
01056
01057 KGrLGDialog * lg = new KGrLGDialog (&savedGames, collections, view);
01058
01059 if (lg->exec() == QDialog::Accepted) {
01060 s = lg->getCurrentText();
01061 }
01062
01063 bool found = false;
01064 QString pr;
01065 int lev;
01066 int i;
01067 int imax = collections.count();
01068
01069 if (! s.isNull()) {
01070 pr = s.mid (21, 7);
01071 pr = pr.left (pr.indexOf (" ", 0, Qt::CaseInsensitive));
01072
01073 for (i = 0; i < imax; i++) {
01074 if (collections.at(i)->prefix == pr) {
01075 collection = collections.at(i);
01076 collnIndex = i;
01077 owner = collections.at(i)->owner;
01078 found = true;
01079 break;
01080 }
01081 }
01082 if (found) {
01083
01084 emit markRuleType (collection->settings);
01085 lev = s.mid (28, 3).toInt();
01086 newGame (lev, collnIndex);