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