• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegames API Reference
  • KDE Home
  • Contact Us
 

kgoldrunner

  • sources
  • kde-4.14
  • kdegames
  • kgoldrunner
  • src
kgrgame.cpp
Go to the documentation of this file.
1 #include "kgrdebug.h"
2 
3 /****************************************************************************
4  * Copyright 2003 Marco Krüger <grisuji@gmx.de> *
5  * Copyright 2003 Ian Wadham <iandw.au@gmail.com> *
6  * Copyright 2009 Ian Wadham <iandw.au@gmail.com> *
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20  ****************************************************************************/
21 
22 #include "kgrgame.h"
23 
24 #include "kgrview.h"
25 #include "kgrscene.h"
26 #include "kgrselector.h"
27 
28 // KGoldrunner loads and plays .ogg files and requires OpenAL + SndFile > v0.21.
29 // Fallback to Phonon by the KgSound library does not give good results.
30 #include <libkdegames_capabilities.h>
31 #ifdef KGAUDIO_BACKEND_OPENAL
32  #include "kgrsounds.h"
33 #endif
34 
35 #include "kgreditor.h"
36 #include "kgrlevelplayer.h"
37 #include "kgrdialog.h"
38 #include "kgrgameio.h"
39 
40 #include <iostream>
41 #include <stdlib.h>
42 #include <time.h>
43 
44 #include <QStringList>
45 #include <QTimer>
46 #include <QDateTime>
47 
48 #include <KRandomSequence>
49 #include <KPushButton>
50 #include <KStandardGuiItem>
51 #include <KStandardDirs>
52 #include <KApplication>
53 #include <KDebug>
54 
55 // TODO - Can we change over to KScoreDialog?
56 
57 // Do NOT change KGoldrunner over to KScoreDialog until we have found a way
58 // to preserve high-score data pre-existing from the KGr high-score methods.
59 // #define USE_KSCOREDIALOG 1 // IDW - 11 Aug 07.
60 
61 #ifdef USE_KSCOREDIALOG
62 #include <KScoreDialog>
63 #else
64 
65 #include <QByteArray>
66 #include <QTextStream>
67 #include <QLabel>
68 #include <QVBoxLayout>
69 #include <QDate>
70 #include <QSpacerItem>
71 #include <QTreeWidget>
72 #include <QHeaderView>
73 #include <QTreeWidgetItem>
74 #include <QDir>
75 
76 #endif
77 
78 #define UserPause true
79 #define ProgramPause false
80 #define NewLevel true
81 
82 /******************************************************************************/
83 /*********************** KGOLDRUNNER GAME CLASS *************************/
84 /******************************************************************************/
85 
86 KGrGame::KGrGame (KGrView * theView,
87  const QString & theSystemDir, const QString & theUserDir)
88  :
89  QObject (theView), // Game is destroyed if view closes.
90  levelPlayer (0),
91  recording (0),
92  playback (false),
93  view (theView),
94  scene (view->gameScene()),
95  systemDataDir (theSystemDir),
96  userDataDir (theUserDir),
97  level (0),
98  mainDemoName ("demo"),
99  // mainDemoName ("CM"), // IDW test.
100  demoType (DEMO),
101  startupDemo (false),
102  programFreeze (false),
103  effects (0),
104  fx (NumSounds),
105  soundOn (false),
106  stepsOn (false),
107  editor (0)
108 {
109  dbgLevel = 0;
110 
111  gameFrozen = false;
112 
113  dyingTimer = new QTimer (this);
114  connect (dyingTimer, SIGNAL (timeout()), SLOT (finalBreath()));
115 
116  // Initialise random number generator.
117  randomGen = new KRandomSequence (time (0));
118  kDebug() << "RANDOM NUMBER GENERATOR INITIALISED";
119 
120  scene->setReplayMessage (i18n("Click anywhere to begin live play"));
121 }
122 
123 KGrGame::~KGrGame()
124 {
125  qDeleteAll(gameList);
126  delete randomGen;
127  delete levelPlayer;
128  delete recording;
129 }
130 
131 // Flags to control author's debugging aids.
132 bool KGrGame::bugFix = false; // Start game with dynamic bug-fix OFF.
133 bool KGrGame::logging = false; // Start game with dynamic logging OFF.
134 
135 bool KGrGame::modeSwitch (const int action,
136  int & selectedGame, int & selectedLevel)
137 {
138  // If editing, check that the user has saved changes.
139  // Note: KGoldrunner::setEditMenu disables/enables SAVE_GAME, PAUSE,
140  // HIGH_SCORE, KILL_HERO, HINT and INSTANT_REPLAY, so they are not relevant
141  // here. All the other GameActions require a save-check.
142  if (! saveOK()) {
143  return false; // The user needs to go on editing.
144  }
145  bool result = true;
146  SelectAction slAction = SL_NONE;
147  switch (action) {
148  case NEW:
149  slAction = SL_ANY;
150  break;
151  case SOLVE:
152  slAction = SL_SOLVE;
153  break;
154  case REPLAY_ANY:
155  slAction = SL_REPLAY;
156  break;
157  case LOAD:
158  // Run the Load Game dialog. Return false if failed or cancelled.
159  result = selectSavedGame (selectedGame, selectedLevel);
160  break;
161  case HIGH_SCORE: // (Disabled during demo/replay)
162  case KILL_HERO: // (Disabled during demo/replay)
163  case PAUSE:
164  case HINT:
165  return result; // If demo/replay, keep it going.
166  break;
167  default:
168  break;
169  }
170  if (slAction != SL_NONE) {
171  // Select game and level. Return false if failed or cancelled.
172  result = selectGame (slAction, selectedGame, selectedLevel);
173  }
174  if (playback && (result == true)) {
175  setPlayback (false); // If demo/replay, kill it.
176  }
177  return result;
178 }
179 
180 void KGrGame::gameActions (const int action)
181 {
182  int selectedGame = gameIndex;
183  int selectedLevel = level;
184  if (! modeSwitch (action, selectedGame, selectedLevel)) {
185  return;
186  }
187  switch (action) {
188  case NEW:
189  newGame (selectedLevel, selectedGame);
190  showTutorialMessages (level);
191  break;
192  case NEXT_LEVEL:
193  if (level >= levelMax) {
194  KGrMessage::information (view, i18n ("Play Next Level"),
195  i18n ("There are no more levels in this game."));
196  return;
197  }
198  level++;
199  kDebug() << "Game" << gameList.at(gameIndex)->name << "level" << level;
200  newGame (level, gameIndex);
201  showTutorialMessages (level);
202  break;
203  case LOAD:
204  loadGame (selectedGame, selectedLevel);
205  break;
206  case SAVE_GAME:
207  saveGame();
208  break;
209  case PAUSE:
210  freeze (UserPause, (! gameFrozen));
211  break;
212  case HIGH_SCORE:
213  // Stop the action during the high-scores dialog.
214  freeze (ProgramPause, true);
215  showHighScores();
216  freeze (ProgramPause, false);
217  break;
218  case KILL_HERO:
219  if (levelPlayer && (! playback)) {
220  // Record the KILL_HERO code, then emit signal endLevel (DEAD).
221  levelPlayer->killHero();
222  }
223  break;
224  case HINT:
225  showHint();
226  break;
227  case DEMO:
228  setPlayback (true);
229  demoType = DEMO;
230  if (! startDemo (SYSTEM, mainDemoName, 1)) {
231  setPlayback (false);
232  }
233  break;
234  case SOLVE:
235  runReplay (SOLVE, selectedGame, selectedLevel);
236  break;
237  case INSTANT_REPLAY:
238  if (levelPlayer) {
239  startInstantReplay();
240  }
241  break;
242  case REPLAY_LAST:
243  replayLastLevel();
244  break;
245  case REPLAY_ANY:
246  runReplay (REPLAY_ANY, selectedGame, selectedLevel);
247  break;
248  default:
249  break;
250  }
251 }
252 
253 void KGrGame::editActions (const int action)
254 {
255  bool editOK = true;
256  bool newEditor = (editor) ? false : true;
257  int editLevel = level;
258  dbk << "Level" << level << prefix << gameIndex;
259  if (newEditor) {
260  if (action == SAVE_EDITS) {
261  KGrMessage::information (view, i18n ("Save Level"),
262  i18n ("Inappropriate action: you are not editing a level."));
263  return;
264  }
265 
266  // If there is no editor running, start one.
267  freeze (ProgramPause, true);
268  editor = new KGrEditor (view, systemDataDir, userDataDir, gameList);
269  emit setEditMenu (true); // Enable edit menu items and toolbar.
270  }
271 
272  switch (action) {
273  case CREATE_LEVEL:
274  editOK = editor->createLevel (gameIndex);
275  break;
276  case EDIT_ANY:
277  editOK = editor->updateLevel (gameIndex, editLevel);
278  break;
279  case SAVE_EDITS:
280  editOK = editor->saveLevelFile ();
281  break;
282  case MOVE_LEVEL:
283  editOK = editor->moveLevelFile (gameIndex, editLevel);
284  break;
285  case DELETE_LEVEL:
286  editOK = editor->deleteLevelFile (gameIndex, editLevel);
287  break;
288  case CREATE_GAME:
289  editOK = editor->editGame (-1);
290  break;
291  case EDIT_GAME:
292  editOK = editor->editGame (gameIndex);
293  break;
294  default:
295  break;
296  }
297 
298  if (newEditor) {
299  if (editOK) {
300  // If a level or demo is running, close it, with no win/lose result.
301  setPlayback (false);
302  if (levelPlayer) {
303  endLevel (NORMAL);
304  scene->deleteAllSprites();
305  }
306 
307  emit showLives (0);
308  emit showScore (0);
309  }
310  else {
311  // Edit failed or was cancelled, so close the editor.
312  emit setEditMenu (false); // Disable edit menu items and toolbar.
313  delete editor;
314  editor = 0;
315  }
316  freeze (ProgramPause, false);
317  }
318 
319  if (! editOK) {
320  return; // Continue play, demo or previous edit.
321  }
322 
323  int game = gameIndex, lev = level;
324  editor->getGameAndLevel (game, lev);
325 
326  if (((game != gameIndex) || (lev != level)) && (lev != 0)) {
327  gameIndex = game;
328  prefix = gameList.at (gameIndex)->prefix;
329  level = lev;
330 
331  kDebug() << "Saving to KConfigGroup";
332  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
333  gameGroup.writeEntry ("GamePrefix", prefix);
334  gameGroup.writeEntry ("Level_" + prefix, level);
335  gameGroup.sync(); // Ensure that the entry goes to disk.
336  }
337 }
338 
339 void KGrGame::editToolbarActions (const int action)
340 {
341  // If game-editor is inactive or action-code is not recognised, do nothing.
342  if (editor) {
343  switch (action) {
344  case EDIT_HINT:
345  // Edit the level-name or hint.
346  editor->editNameAndHint();
347  break;
348  case FREE:
349  case ENEMY:
350  case HERO:
351  case CONCRETE:
352  case BRICK:
353  case FBRICK:
354  case HLADDER:
355  case LADDER:
356  case NUGGET:
357  case BAR:
358  // Set the next object to be painted in the level-layout.
359  editor->setEditObj (action);
360  break;
361  default:
362  break;
363  }
364  }
365 }
366 
367 void KGrGame::settings (const int action)
368 {
369  // TODO - Bad - Configure Keys does not pause a demo. IDW
370  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
371  bool onOff = false;
372  switch (action) {
373  case PLAY_SOUNDS:
374  case PLAY_STEPS:
375  toggleSoundsOnOff (action);
376  break;
377  case STARTUP_DEMO:
378  // Toggle the startup demo to be on or off.
379  onOff = (! gameGroup.readEntry ("StartingDemo", true));
380  gameGroup.writeEntry ("StartingDemo", onOff);
381  break;
382  case MOUSE:
383  case KEYBOARD:
384  case LAPTOP:
385  setControlMode (action);
386  gameGroup.writeEntry ("ControlMode", action);
387  break;
388  case CLICK_KEY:
389  case HOLD_KEY:
390  if (controlMode == KEYBOARD) {
391  setHoldKeyOption (action);
392  gameGroup.writeEntry ("HoldKeyOption", action);
393  }
394  break;
395  case NORMAL_SPEED:
396  case BEGINNER_SPEED:
397  case CHAMPION_SPEED:
398  setTimeScale (action);
399  gameGroup.writeEntry ("SpeedLevel", action);
400  gameGroup.writeEntry ("ActualSpeed", timeScale);
401  break;
402  case INC_SPEED:
403  case DEC_SPEED:
404  setTimeScale (action);
405  gameGroup.writeEntry ("ActualSpeed", timeScale);
406  break;
407  default:
408  break;
409  }
410  gameGroup.sync();
411 }
412 
413 void KGrGame::setInitialTheme (const QString & themeFilepath)
414 {
415  initialThemeFilepath = themeFilepath;
416 }
417 
418 void KGrGame::initGame()
419 {
420 #ifndef KGAUDIO_BACKEND_OPENAL
421  KGrMessage::information (view, i18n ("No Sound"),
422  i18n ("Warning: This copy of KGoldrunner has no sound.\n"
423  "\n"
424  "This is because no development versions of the OpenAL and "
425  "SndFile libraries were present when it was compiled and built."),
426  "WarningNoSound");
427 #endif
428  kDebug() << "Entered, draw the initial graphics now ...";
429 
430  // Get the most recent collection and level that was played by this user.
431  // If he/she has never played before, set it to Tutorial, level 1.
432  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
433  QString prevGamePrefix = gameGroup.readEntry ("GamePrefix", "tute");
434  int prevLevel = gameGroup.readEntry ("Level_" + prevGamePrefix, 1);
435 
436  kDebug()<< "Config() Game and Level" << prevGamePrefix << prevLevel;
437 
438  // Use that game and level, if it is among the current games.
439  // Otherwise, use the first game in the list and level 1.
440  gameIndex = 0;
441  level = 1;
442  int n = 0;
443  dbk1 << gameIndex << level << "Search:" << prevGamePrefix << prevLevel;
444  foreach (KGrGameData * gameData, gameList) {
445  dbk1 << "Trying:" << n << gameData->prefix;
446  if (gameData->prefix == prevGamePrefix) {
447  gameIndex = n;
448  level = prevLevel;
449  dbk1 << "FOUND:" << gameIndex << prevGamePrefix << level;
450  break;
451  }
452  n++;
453  }
454 
455  // Set control-mode, hold-key option (for when K/B is used) and game-speed.
456  settings (gameGroup.readEntry ("ControlMode", (int) MOUSE));
457  emit setToggle (((controlMode == MOUSE) ? "mouse_mode" :
458  ((controlMode == KEYBOARD) ? "keyboard_mode" :
459  "laptop_mode")), true);
460 
461  holdKeyOption = gameGroup.readEntry ("HoldKeyOption", (int) CLICK_KEY);
462  emit setToggle (((holdKeyOption == CLICK_KEY) ? "click_key" :
463  "hold_key"), true);
464 
465  int speedLevel = gameGroup.readEntry ("SpeedLevel", (int) NORMAL_SPEED);
466  settings (speedLevel);
467  emit setToggle ((speedLevel == NORMAL_SPEED) ? "normal_speed" :
468  ((speedLevel == BEGINNER_SPEED) ? "beginner_speed" :
469  "champion_speed"), true);
470  timeScale = gameGroup.readEntry ("ActualSpeed", 10);
471 
472 #ifdef KGAUDIO_BACKEND_OPENAL
473  // Set up sounds, if required in config.
474  soundOn = gameGroup.readEntry ("Sound", false);
475  kDebug() << "Sound" << soundOn;
476  if (soundOn) {
477  loadSounds();
478  effects->setMuted (false);
479  }
480  emit setToggle ("options_sounds", soundOn);
481 
482  stepsOn = gameGroup.readEntry ("StepSounds", false);
483  kDebug() << "StepSounds" << stepsOn;
484  emit setToggle ("options_steps", stepsOn);
485 #endif
486 
487  dbk1 << "Owner" << gameList.at (gameIndex)->owner
488  << gameList.at (gameIndex)->name << level;
489 
490  setPlayback (gameGroup.readEntry ("StartingDemo", true));
491  if (playback && (startDemo (SYSTEM, mainDemoName, 1))) {
492  startupDemo = true; // Demo is starting.
493  demoType = DEMO;
494  }
495  else {
496  setPlayback (false); // Load previous session's level.
497  newGame (level, gameIndex);
498  quickStartDialog();
499  }
500  emit setToggle ("options_demo", startupDemo);
501 
502  // Allow a short break, to display the graphics, then use the demo delay-time
503  // or the reaction-time to the quick-start dialog to do some more rendering.
504  QTimer::singleShot (10, scene, SLOT(preRenderSprites()));
505 
506 } // End KGrGame::initGame()
507 
508 bool KGrGame::startDemo (const Owner demoOwner, const QString & pPrefix,
509  const int levelNo)
510 {
511  // Find the relevant file and the list of levels it contains.
512  QString dir = (demoOwner == SYSTEM) ? systemDataDir : userDataDir;
513  QString filepath = dir + "rec_" + pPrefix + ".txt";
514  KConfig config (filepath, KConfig::SimpleConfig);
515  QStringList demoList = config.groupList();
516  dbk1 << "DEMO LIST" << demoList.count() << demoList;
517 
518  // Find the required level (e.g. CM007) in the list available on the file.
519  QString s = pPrefix + QString::number(levelNo).rightJustified(3,'0');
520  int index = demoList.indexOf (s) + 1;
521  dbk1 << "DEMO looking for" << s << "found at" << index;
522  if (index <= 0) {
523  setPlayback (false);
524  kDebug() << "DEMO not found in" << filepath << s << pPrefix << levelNo;
525  return false;
526  }
527 
528  // Load and run the recorded level(s).
529  if (playLevel (demoOwner, pPrefix, levelNo, (! NewLevel))) {
530  playbackOwner = demoOwner;
531  playbackPrefix = pPrefix;
532  playbackIndex = levelNo;
533 
534  // Play back all levels in Main Demo or just one level in other demos.
535  playbackMax = (playbackPrefix == mainDemoName) ?
536  demoList.count() : levelNo;
537  if (levelPlayer) {
538  levelPlayer->prepareToPlay();
539  }
540  kDebug() << "DEMO started ..." << filepath << pPrefix << levelNo;
541  return true;
542  }
543  else {
544  setPlayback (false);
545  kDebug() << "DEMO failed ..." << filepath << pPrefix << levelNo;
546  return false;
547  }
548 }
549 
550 void KGrGame::runNextDemoLevel()
551 {
552  dbk << "index" << playbackIndex << "max" << playbackMax << playbackPrefix
553  << "owner" << playbackOwner;
554  if (playbackIndex < playbackMax) {
555  playbackIndex++;
556  if (playLevel (playbackOwner, playbackPrefix,
557  playbackIndex, (! NewLevel))) {
558  if (levelPlayer) {
559  levelPlayer->prepareToPlay();
560  }
561  kDebug() << "DEMO continued ..." << playbackPrefix << playbackIndex;
562  return;
563  }
564  }
565  finishDemo();
566 }
567 
568 void KGrGame::finishDemo()
569 {
570  setPlayback (false);
571  newGame (level, gameIndex);
572  if (startupDemo) {
573  // The startup demo was running, so run the Quick Start Dialog now.
574  startupDemo = false;
575  quickStartDialog();
576  }
577  else {
578  // Otherwise, run the last level used.
579  showTutorialMessages (level);
580  }
581 }
582 
583 void KGrGame::interruptDemo()
584 {
585  kDebug() << "DEMO interrupted ...";
586  if ((demoType == INSTANT_REPLAY) || (demoType == REPLAY_LAST)) {
587  setPlayback (false);
588  levelMax = gameList.at (gameIndex)->nLevels;
589  freeze (UserPause, true);
590  KGrMessage::information (view, i18n ("Game Paused"),
591  i18n ("The replay has stopped and the game is pausing while you "
592  "prepare to go on playing. Please press the Pause key "
593  "(default P or Esc) when you are ready."),
594  "Show_interruptDemo");
595  }
596  else {
597  finishDemo(); // Initial DEMO, main DEMO or SOLVE.
598  }
599 }
600 
601 void KGrGame::startInstantReplay()
602 {
603  dbk << "Start INSTANT_REPLAY";
604  demoType = INSTANT_REPLAY;
605 
606  // Terminate current play.
607  delete levelPlayer;
608  levelPlayer = 0;
609  scene->deleteAllSprites();
610 
611  // Redisplay the starting score and lives.
612  lives = recording->lives;
613  emit showLives (lives);
614  score = recording->score;
615  emit showScore (score);
616 
617  // Restart the level in playback mode.
618  setPlayback (true);
619  setupLevelPlayer();
620  levelPlayer->prepareToPlay();
621 }
622 
623 void KGrGame::replayLastLevel()
624 {
625  // Replay the last game and level completed by the player.
626  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
627  QString lastPrefix = gameGroup.readEntry ("LastGamePrefix", "");
628  int lastLevel = gameGroup.readEntry ("LastLevel", -1);
629 
630  if (lastLevel > 0) {
631  setPlayback (true);
632  demoType = REPLAY_LAST;
633  if (! startDemo (USER, lastPrefix, lastLevel)) {
634  setPlayback (false);
635  KGrMessage::information (view, i18n ("Replay Last Level"),
636  i18n ("ERROR: Could not find and replay a recording of "
637  "the last level you played."));
638  }
639  }
640  else {
641  KGrMessage::information (view, i18n ("Replay Last Level"),
642  i18n ("There is no last level to replay. You need to play a "
643  "level to completion, win or lose, before you can use "
644  "the Replay Last Level action."));
645  }
646 }
647 
648 /******************************************************************************/
649 /********************** QUICK-START DIALOG AND SLOTS ************************/
650 /******************************************************************************/
651 
652 void KGrGame::quickStartDialog()
653 {
654  // Make sure the game does not start during the Quick Start dialog.
655  freeze (ProgramPause, true);
656 
657  qs = new KDialog (view);
658 
659  // Modal dialog, 4 buttons, vertically: the PLAY button has the focus.
660  qs->setModal (true);
661  qs->setCaption (i18n("Quick Start"));
662  qs->setButtons
663  (KDialog::Ok | KDialog::Cancel | KDialog::User1 | KDialog::User2);
664  qs->setButtonFocus (KDialog::Ok);
665  qs->setButtonsOrientation (Qt::Vertical);
666 
667  // Set up the PLAY button.
668  qs->setButtonText (KDialog::Ok,
669  i18nc ("Button text: start playing a game", "&PLAY"));
670  qs->setButtonToolTip (KDialog::Ok, i18n ("Start playing this level"));
671  qs->setButtonWhatsThis (KDialog::Ok,
672  i18n ("Set up to start playing the game and level being shown, "
673  "as soon as you click, move the mouse or press a key"));
674 
675  // Set up the Quit button.
676  qs->setButtonText (KDialog::Cancel, i18n ("&Quit"));
677  qs->setButtonToolTip (KDialog::Cancel, i18n ("Close KGoldrunner"));
678 
679  // Set up the New Game button.
680  qs->setButtonText (KDialog::User1, i18n ("&New Game..."));
681  qs->setButtonToolTip (KDialog::User1,
682  i18n ("Start a different game or level"));
683  qs->setButtonWhatsThis (KDialog::User1,
684  i18n ("Use the Select Game dialog box to choose a "
685  "different game or level and start playing it"));
686 
687  // Set up the Use Menu button.
688  qs->setButtonText (KDialog::User2, i18n ("&Use Menu"));
689  qs->setButtonToolTip (KDialog::User2,
690  i18n ("Use the menus to choose other actions"));
691  qs->setButtonWhatsThis (KDialog::User2,
692  i18n ("Before playing, use the menus to choose other actions, "
693  "such as loading a saved game or changing the theme"));
694 
695  // Add the KGoldrunner application icon to the dialog box.
696  QLabel * logo = new QLabel();
697  qs->setMainWidget (logo);
698  logo->setPixmap (kapp->windowIcon().pixmap (240));
699  logo->setAlignment (Qt::AlignTop | Qt::AlignHCenter);
700 
701  connect (qs, SIGNAL (okClicked()), this, SLOT (quickStartPlay()));
702  connect (qs, SIGNAL (user1Clicked()), this, SLOT (quickStartNewGame()));
703  connect (qs, SIGNAL (user2Clicked()), this, SLOT (quickStartUseMenu()));
704  connect (qs, SIGNAL (cancelClicked()), this, SLOT (quickStartQuit()));
705 
706  qs->show();
707 }
708 
709 void KGrGame::quickStartPlay()
710 {
711  // KDialog calls QDialog::accept() after the OK slot, so must hide it
712  // now, to avoid interference with any tutorial messages there may be.
713  qs->hide();
714  freeze (ProgramPause, false);
715  showTutorialMessages (level); // Level has already been loaded.
716 }
717 
718 void KGrGame::quickStartNewGame()
719 {
720  qs->accept();
721  freeze (ProgramPause, false);
722 
723  int selectedGame = gameIndex;
724  int selectedLevel = level;
725  if (modeSwitch (NEW, selectedGame, selectedLevel)) {
726  newGame (selectedLevel, selectedGame);
727  }
728  showTutorialMessages (selectedLevel);
729 }
730 
731 void KGrGame::quickStartUseMenu()
732 {
733  qs->accept();
734  freeze (ProgramPause, false);
735  freeze (UserPause, true);
736  KGrMessage::information (view, i18n ("Game Paused"),
737  i18n ("The game is halted. You will need to press the Pause key "
738  "(default P or Esc) when you are ready to play."));
739 
740  if (levelPlayer) {
741  levelPlayer->prepareToPlay();
742  }
743 }
744 
745 void KGrGame::quickStartQuit()
746 {
747  emit quitGame();
748 }
749 
750 /******************************************************************************/
751 /************************* LEVEL SELECTION PROCEDURE ************************/
752 /******************************************************************************/
753 
754 bool KGrGame::selectGame (const SelectAction slAction,
755  int & selectedGame, int & selectedLevel)
756 {
757  // Halt the game during the dialog.
758  freeze (ProgramPause, true);
759 
760  // Run the game and level selection dialog.
761  KGrSLDialog * sl = new KGrSLDialog (slAction, selectedLevel, selectedGame,
762  gameList, systemDataDir, userDataDir,
763  view);
764  bool selected = sl->selectLevel (selectedGame, selectedLevel);
765  delete sl;
766 
767  kDebug() << "After dialog - programFreeze" << programFreeze;
768  kDebug() << "selected" << selected << "gameFrozen" << gameFrozen;
769  kDebug() << "selectedGame" << selectedGame
770  << "prefix" << gameList.at(selectedGame)->prefix
771  << "selectedLevel" << selectedLevel;
772  // Unfreeze the game, but only if it was previously unfrozen.
773  freeze (ProgramPause, false);
774  return selected;
775 }
776 
777 void KGrGame::runReplay (const int action,
778  const int selectedGame, const int selectedLevel)
779 {
780  if (action == SOLVE) {
781  setPlayback (true);
782  demoType = SOLVE;
783  if (! startDemo
784  (SYSTEM, gameList.at (selectedGame)->prefix, selectedLevel)) {
785  KGrMessage::information (view, i18n ("Show A Solution"),
786  i18n ("Sorry, although all levels of KGoldrunner can be "
787  "solved, no solution has been recorded yet for the "
788  "level you selected."), "Show_noSolutionRecorded");
789  }
790  }
791  else if (action == REPLAY_ANY) {
792  setPlayback (true);
793  demoType = REPLAY_ANY;
794  if (! startDemo
795  (USER, gameList.at (selectedGame)->prefix, selectedLevel)) {
796  KGrMessage::information (view, i18n ("Replay Any Level"),
797  i18n ("Sorry, you do not seem to have played and recorded "
798  "the selected level before."), "Show_noReplay");
799  }
800  }
801 }
802 
803 /******************************************************************************/
804 /*************************** MAIN GAME PROCEDURES ***************************/
805 /******************************************************************************/
806 
807 void KGrGame::newGame (const int lev, const int newGameIndex)
808 {
809  scene->goToBlack();
810 
811  KGrGameData * gameData = gameList.at (newGameIndex);
812  level = lev;
813  gameIndex = newGameIndex;
814  owner = gameData->owner;
815  prefix = gameData->prefix;
816  levelMax = gameData->nLevels;
817 
818  lives = 5; // Start with 5 lives.
819  score = 0;
820  startScore = 0;
821 
822  emit showLives (lives);
823  emit showScore (score);
824 
825  playLevel (owner, prefix, level, NewLevel);
826 }
827 
828 bool KGrGame::playLevel (const Owner fileOwner, const QString & prefix,
829  const int levelNo, const bool newLevel)
830 {
831  // If the game-editor is active, terminate it.
832  if (editor) {
833  emit setEditMenu (false); // Disable edit menu items and toolbar.
834  delete editor;
835  editor = 0;
836  }
837 
838  // If there is a level being played, kill it, with no win/lose result.
839  if (levelPlayer) {
840  endLevel (NORMAL);
841  }
842 
843  // Clean up any sprites remaining from a previous level. This is done late,
844  // so that the player has a little time to observe how the level ended.
845  scene->deleteAllSprites();
846 
847  // Set up to record or play back: load either level-data or recording-data.
848  if (! initRecordingData (fileOwner, prefix, levelNo)) {
849  return false;
850  }
851 
852  scene->setLevel (levelNo); // Switch and render background if reqd.
853  scene->fadeIn (true); // Then run the fade-in animation.
854  startScore = score; // The score we will save, if asked.
855 
856  // Create a level player, initialised and ready for play or replay to start.
857  setupLevelPlayer();
858 
859  levelName = recording->levelName;
860  levelHint = recording->hint;
861 
862  // Indicate on the menus whether there is a hint for this level.
863  emit hintAvailable (levelHint.length() > 0);
864 
865  // Re-draw the playfield frame, level title and figures.
866  scene->setTitle (getTitle());
867 
868  // If we are starting a new level, save it in the player's config file.
869  if (newLevel && (level != 0)) { // But do not save the "ENDE" level.
870  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
871  gameGroup.writeEntry ("GamePrefix", prefix);
872  gameGroup.writeEntry ("Level_" + prefix, level);
873  gameGroup.sync(); // Ensure that the entry goes to disk.
874  }
875 
876  return true;
877 }
878 
879 void KGrGame::setupLevelPlayer()
880 {
881  levelPlayer = new KGrLevelPlayer (this, randomGen);
882 
883  levelPlayer->init (view, recording, playback, gameFrozen);
884  levelPlayer->setTimeScale (recording->speed);
885 
886  // Use queued connections here, to ensure that levelPlayer has finished
887  // executing and can be deleted when control goes to the relevant slot.
888  connect (levelPlayer, SIGNAL (endLevel(int)),
889  this, SLOT (endLevel(int)), Qt::QueuedConnection);
890  if (playback) {
891  connect (levelPlayer, SIGNAL (interruptDemo()),
892  this, SLOT (interruptDemo()), Qt::QueuedConnection);
893  }
894 }
895 
896 void KGrGame::incScore (const int n)
897 {
898  score = score + n; // SCORING: trap enemy 75, kill enemy 75,
899  emit showScore (score); // collect gold 250, complete the level 1500.
900 }
901 
902 void KGrGame::playSound (const int n, const bool onOff)
903 {
904 #ifdef KGAUDIO_BACKEND_OPENAL
905  if (! effects) {
906  return; // Sound is off and not yet loaded.
907  }
908  static int fallToken = -1;
909  if (onOff) {
910  int token = -1;
911  if (stepsOn || ((n != StepSound) && (n != ClimbSound))) {
912  token = effects->play (fx [n]);
913  }
914  if (n == FallSound) {
915  fallToken = token;
916  }
917  }
918  // Only the falling sound can get individually turned off.
919  else if ((n == FallSound) && (fallToken >= 0)) {
920  effects->stop (fallToken);
921  fallToken = -1;
922  }
923 #endif
924 }
925 
926 void KGrGame::endLevel (const int result)
927 {
928  dbk << "Return to KGrGame, result:" << result;
929 
930 #ifdef KGAUDIO_BACKEND_OPENAL
931  if (effects) { // If sounds have been loaded, cut off
932  effects->stopAllSounds(); // all sounds that are in progress.
933  }
934 #endif
935 
936  if (! levelPlayer) {
937  return; // Not playing a level.
938  }
939 
940  if (playback && (result == UNEXPECTED_END)) {
941  if (demoType == INSTANT_REPLAY) {
942  interruptDemo(); // Reached end of recording in instant replay.
943  }
944  else {
945  runNextDemoLevel(); // Finished replay unexpectedly. Error?
946  }
947  return;
948  }
949 
950  dbk << "delete levelPlayer";
951  // Delete the level-player, hero, enemies, grid, rule-book, etc.
952  // Delete sprites in the view later: the user may need to see them briefly.
953  delete levelPlayer;
954  levelPlayer = 0;
955 
956  // If the player finished the level (won or lost), save the recording.
957  if ((! playback) && ((result == WON_LEVEL) || (result == DEAD))) {
958  dbk << "saveRecording()";
959  saveRecording();
960  }
961 
962  if (result == WON_LEVEL) {
963  dbk << "Won level";
964  levelCompleted();
965  }
966  else if (result == DEAD) {
967  dbk << "Lost level";
968  herosDead();
969  }
970 }
971 
972 void KGrGame::herosDead()
973 {
974  if ((level < 1) || (lives <= 0)) {
975  return; // Game over: we are in the "ENDE" screen.
976  }
977 
978  // Lose a life.
979  if ((--lives > 0) || playback) {
980  // Demo mode or still some life left.
981  emit showLives (lives);
982 
983  // Freeze the animation and let the player see what happened.
984  freeze (ProgramPause, true);
985  playSound (DeathSound);
986 
987  dyingTimer->setSingleShot (true);
988  dyingTimer->start (1000);
989  }
990  else {
991  // Game over.
992  emit showLives (lives);
993 
994  freeze (ProgramPause, true);
995  playSound (GameOverSound);
996 
997  checkHighScore(); // Check if there is a high score for this game.
998 
999  // Offer the player a chance to start this level again with 5 new lives.
1000  QString gameOver = i18n ("<NOBR><B>GAME OVER !!!</B></NOBR><P>"
1001  "Would you like to try this level again?</P>");
1002  switch (KGrMessage::warning (view, i18n ("Game Over"), gameOver,
1003  i18n ("&Try Again"), i18n ("&Finish"))) {
1004  case 0:
1005  freeze (ProgramPause, false); // Offer accepted.
1006  newGame (level, gameIndex);
1007  showTutorialMessages (level);
1008  return;
1009  break;
1010  case 1:
1011  break; // Offer rejected.
1012  }
1013 
1014  // Game completely over.
1015  freeze (ProgramPause, false); // Unfreeze.
1016  level = 0; // Display the "ENDE" screen.
1017  if (playLevel (SYSTEM, "ende", level, (! NewLevel))) {
1018  levelPlayer->prepareToPlay(); // Activate the animation.
1019  }
1020  }
1021 }
1022 
1023 void KGrGame::finalBreath()
1024 {
1025  dbk << "Connecting fadeFinished()";
1026  connect (scene, SIGNAL (fadeFinished()), this, SLOT (repeatLevel()));
1027  dbk << "Calling scene->fadeOut()";
1028  scene->fadeIn (false);
1029 }
1030 
1031 void KGrGame::repeatLevel()
1032 {
1033  disconnect (scene, SIGNAL (fadeFinished()), this, SLOT (repeatLevel()));
1034  scene->goToBlack();
1035 
1036  // Avoid re-starting if the player selected edit before the time was up.
1037  if (! editor) {
1038  if (playback) {
1039  runNextDemoLevel();
1040  }
1041  else if (playLevel (owner, prefix, level, (! NewLevel))) {
1042  levelPlayer->prepareToPlay();
1043  }
1044  }
1045  freeze (ProgramPause, false); // Unfreeze, but don't move yet.
1046 }
1047 
1048 void KGrGame::levelCompleted()
1049 {
1050  playSound (CompletedSound);
1051 
1052  dbk << "Connecting fadeFinished()";
1053  connect (scene, SIGNAL (fadeFinished()), this, SLOT (goUpOneLevel()));
1054  dbk << "Calling scene->fadeOut()";
1055  scene->fadeIn (false);
1056 }
1057 
1058 void KGrGame::goUpOneLevel()
1059 {
1060  disconnect (scene, SIGNAL (fadeFinished()), this, SLOT (goUpOneLevel()));
1061  scene->goToBlack();
1062 
1063  lives++; // Level completed: gain another life.
1064  emit showLives (lives);
1065  incScore (1500);
1066 
1067  if (playback) {
1068  runNextDemoLevel();
1069  return;
1070  }
1071  if (level >= levelMax) {
1072  KGrGameData * gameData = gameList.at (gameIndex);
1073  freeze (ProgramPause, true);
1074  playSound (VictorySound);
1075 
1076  KGrMessage::information (view, gameData->name,
1077  i18n ("<b>CONGRATULATIONS !!!!</b>"
1078  "<p>You have conquered the last level in the "
1079  "<b>\"%1\"</b> game !!</p>", gameData->name));
1080  checkHighScore(); // Check if there is a high score for this game.
1081 
1082  freeze (ProgramPause, false);
1083  level = 0; // Game completed: display the "ENDE" screen.
1084  }
1085  else {
1086  level++; // Go up one level.
1087  }
1088 
1089  if (playLevel (owner, prefix, level, NewLevel)) {
1090  showTutorialMessages (level);
1091  }
1092 }
1093 
1094 void KGrGame::setControlMode (const int mode)
1095 {
1096  // Enable/disable keyboard-mode options.
1097  bool enableDisable = (mode == KEYBOARD);
1098  emit setAvail ("click_key", enableDisable);
1099  emit setAvail ("hold_key", enableDisable);
1100 
1101  controlMode = mode;
1102  if (levelPlayer && (! playback)) {
1103  // Change control during play, but not during a demo or replay.
1104  levelPlayer->setControlMode (mode);
1105  }
1106 }
1107 
1108 void KGrGame::setHoldKeyOption (const int option)
1109 {
1110  holdKeyOption = option;
1111  if (levelPlayer && (! playback)) {
1112  // Change key-option during play, but not during a demo or replay.
1113  levelPlayer->setHoldKeyOption (option);
1114  }
1115 }
1116 
1117 void KGrGame::setTimeScale (const int action)
1118 {
1119  switch (action) {
1120  case NORMAL_SPEED:
1121  timeScale = 10;
1122  break;
1123  case BEGINNER_SPEED:
1124  timeScale = 5;
1125  break;
1126  case CHAMPION_SPEED:
1127  timeScale = 15;
1128  break;
1129  case INC_SPEED:
1130  timeScale = (timeScale < 20) ? timeScale + 1 : 20;
1131  break;
1132  case DEC_SPEED:
1133  timeScale = (timeScale > 2) ? timeScale - 1 : 2;
1134  break;
1135  default:
1136  break;
1137  }
1138 
1139  if (levelPlayer && (! playback)) {
1140  // Change speed during play, but not during a demo or replay.
1141  kDebug() << "setTimeScale" << (timeScale);
1142  levelPlayer->setTimeScale (timeScale);
1143  }
1144 }
1145 
1146 bool KGrGame::inEditMode()
1147 {
1148  return (editor != 0); // Return true if the game-editor is active.
1149 }
1150 
1151 void KGrGame::toggleSoundsOnOff (const int action)
1152 {
1153  const char * setting = (action == PLAY_SOUNDS) ? "Sound" : "StepSounds";
1154  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
1155  bool soundOnOff = gameGroup.readEntry (setting, false);
1156  soundOnOff = (! soundOnOff);
1157  gameGroup.writeEntry (setting, soundOnOff);
1158  if (action == PLAY_SOUNDS) {
1159  soundOn = soundOnOff;
1160  }
1161  else {
1162  stepsOn = soundOnOff;
1163  }
1164 
1165 #ifdef KGAUDIO_BACKEND_OPENAL
1166  if (action == PLAY_SOUNDS) {
1167  if (soundOn && (effects == 0)) {
1168  loadSounds(); // Sounds were not loaded when the game started.
1169  }
1170  effects->setMuted (! soundOn);
1171  }
1172 #endif
1173 }
1174 
1175 void KGrGame::freeze (const bool userAction, const bool on_off)
1176 {
1177  QString type = userAction ? "UserAction" : "ProgramAction";
1178  kDebug() << "PAUSE:" << type << on_off;
1179  kDebug() << "gameFrozen" << gameFrozen << "programFreeze" << programFreeze;
1180 
1181 #ifdef KGAUDIO_BACKEND_OPENAL
1182  if (on_off && effects) { // If pausing and sounds are loaded, cut
1183  effects->stopAllSounds(); // off all sounds that are in progress.
1184  }
1185 #endif
1186 
1187  if (! userAction) {
1188  // The program needs to freeze the game during a message, dialog, etc.
1189  if (on_off) {
1190  if (gameFrozen) {
1191  if (programFreeze) {
1192  kDebug() << "P: The program has already frozen the game.";
1193  }
1194  else {
1195  kDebug() << "P: The user has already frozen the game.";
1196  }
1197  return; // The game is already frozen.
1198  }
1199  programFreeze = false;
1200  }
1201  else if (! programFreeze) {
1202  if (gameFrozen) {
1203  kDebug() << "P: The user will keep the game frozen.";
1204  }
1205  else {
1206  kDebug() << "P: The game is NOT frozen.";
1207  }
1208  return; // The user will keep the game frozen.
1209  }
1210  // The program will succeed in freezing or unfreezing the game.
1211  programFreeze = on_off;
1212  }
1213  else if (programFreeze) {
1214  // If the user breaks through a program freeze somehow, take no action.
1215  kDebug() << "U: THE USER HAS BROKEN THROUGH SOMEHOW.";
1216  return;
1217  }
1218  else {
1219  // The user is freezing or unfreezing the game. Do visual feedback.
1220  emit gameFreeze (on_off);
1221  }
1222 
1223  gameFrozen = on_off;
1224  if (levelPlayer) {
1225  levelPlayer->pause (on_off);
1226  }
1227  kDebug() << "RESULT: gameFrozen" << gameFrozen
1228  << "programFreeze" << programFreeze;
1229 }
1230 
1231 void KGrGame::showHint()
1232 {
1233  // Put out a hint for this level.
1234  QString caption = i18n ("Hint");
1235 
1236  if (levelHint.length() > 0) {
1237  freeze (ProgramPause, true);
1238  // TODO - IDW. Check if a solution exists BEFORE showing the extra button.
1239  switch (KGrMessage::warning (view, caption, levelHint,
1240  i18n ("&OK"), i18n ("&Show A Solution"))) {
1241  case 0:
1242  freeze (ProgramPause, false); // No replay requested.
1243  break;
1244  case 1:
1245  freeze (ProgramPause, false); // Replay a solution.
1246  // This deletes current KGrLevelPlayer and play, but no life is lost.
1247  runReplay (SOLVE, gameIndex, level);
1248  break;
1249  }
1250  }
1251  else
1252  myMessage (view, caption,
1253  i18n ("Sorry, there is no hint for this level."));
1254 }
1255 
1256 void KGrGame::showTutorialMessages (int levelNo)
1257 {
1258  // Halt the game during message displays and mouse pointer moves.
1259  freeze (ProgramPause, true);
1260 
1261  // Check if this is a tutorial collection and not on the "ENDE" screen.
1262  if ((prefix.left (4) == "tute") && (levelNo != 0)) {
1263 
1264  // At the start of a tutorial, put out an introduction.
1265  if (levelNo == 1) {
1266  KGrMessage::information (view, gameList.at (gameIndex)->name,
1267  i18n (gameList.at (gameIndex)->about.constData()));
1268  }
1269  // Put out an explanation of this level.
1270  KGrMessage::information (view, getTitle(), levelHint);
1271  }
1272 
1273  if (levelPlayer) {
1274  levelPlayer->prepareToPlay();
1275  }
1276  freeze (ProgramPause, false); // Let the level begin.
1277 }
1278 
1279 void KGrGame::setPlayback (const bool onOff)
1280 {
1281  if (playback != onOff) {
1282  // Disable high scores, kill hero and some settings during demo/replay.
1283  bool enableDisable = (! onOff);
1284  emit setAvail ("game_highscores", enableDisable);
1285  emit setAvail ("kill_hero", enableDisable);
1286 
1287  emit setAvail ("mouse_mode", enableDisable);
1288  emit setAvail ("keyboard_mode", enableDisable);
1289  emit setAvail ("laptop_mode", enableDisable);
1290 
1291  emit setAvail ("click_key", enableDisable);
1292  emit setAvail ("hold_key", enableDisable);
1293 
1294  emit setAvail ("normal_speed", enableDisable);
1295  emit setAvail ("beginner_speed", enableDisable);
1296  emit setAvail ("champion_speed", enableDisable);
1297  emit setAvail ("increase_speed", enableDisable);
1298  emit setAvail ("decrease_speed", enableDisable);
1299  }
1300  scene->showReplayMessage (onOff);
1301  playback = onOff;
1302 }
1303 
1304 QString KGrGame::getDirectory (Owner o)
1305 {
1306  return ((o == SYSTEM) ? systemDataDir : userDataDir);
1307 }
1308 
1309 QString KGrGame::getTitle()
1310 {
1311  int lev = (playback) ? recording->level : level;
1312  KGrGameData * gameData = gameList.at (gameIndex);
1313  if (lev == 0) {
1314  // Generate a special title for end of game.
1315  return (i18n ("T H E E N D"));
1316  }
1317 
1318  // Set title string to "Game-name - NNN" or "Game-name - NNN - Level-name".
1319  QString gameName = (playback) ? recording->gameName : gameData->name;
1320  QString levelNumber = QString::number(lev).rightJustified(3,'0');
1321 
1322  QString levelTitle = (levelName.length() <= 0)
1323  ?
1324  i18nc ("Game name - level number.",
1325  "%1 - %2", gameName, levelNumber)
1326  :
1327  i18nc ("Game name - level number - level name.",
1328  "%1 - %2 - %3", gameName, levelNumber, levelName);
1329  return (levelTitle);
1330 }
1331 
1332 void KGrGame::kbControl (const int dirn, const bool pressed)
1333 {
1334  dbk2 << "Keystroke setting direction" << dirn << "pressed" << pressed;
1335 
1336  if (editor) {
1337  return;
1338  }
1339  if (playback) {
1340  levelPlayer->interruptPlayback(); // Will emit interruptDemo().
1341  return;
1342  }
1343 
1344  // Using keyboard control can automatically disable mouse control.
1345  if (pressed && ((controlMode == MOUSE) ||
1346  ((controlMode == LAPTOP) && (dirn != DIG_RIGHT) && (dirn != DIG_LEFT))))
1347  {
1348  // Halt the game while a message is displayed.
1349  freeze (ProgramPause, true);
1350 
1351  switch (KMessageBox::questionYesNo (view,
1352  i18n ("You have pressed a key that can be used to control the "
1353  "Hero. Do you want to switch automatically to keyboard "
1354  "control? Pointer control is easier to use in the long term "
1355  "- like riding a bike rather than walking!"),
1356  i18n ("Switch to Keyboard Mode"),
1357  KGuiItem (i18n ("Switch to &Keyboard Mode")),
1358  KGuiItem (i18n ("Stay in &Mouse Mode")),
1359  i18n ("Keyboard Mode")))
1360  {
1361  case KMessageBox::Yes:
1362  settings (KEYBOARD);
1363  emit setToggle ("keyboard_mode", true); // Adjust Settings menu.
1364  break;
1365  case KMessageBox::No:
1366  break;
1367  }
1368 
1369  // Unfreeze the game, but only if it was previously unfrozen.
1370  freeze (ProgramPause, false);
1371 
1372  if (controlMode != KEYBOARD) {
1373  return; // Stay in Mouse or Laptop Mode.
1374  }
1375  }
1376 
1377  // Accept keystroke to set next direction, even when the game is frozen.
1378  if (levelPlayer) {
1379  levelPlayer->setDirectionByKey ((Direction) dirn, pressed);
1380  }
1381 }
1382 
1383 /******************************************************************************/
1384 /************************** SAVE AND RE-LOAD GAMES **************************/
1385 /******************************************************************************/
1386 
1387 void KGrGame::saveGame() // Save game ID, score and level.
1388 {
1389  if (editor) {
1390  myMessage (view, i18n ("Save Game"),
1391  i18n ("Sorry, you cannot save your game play while you are editing. "
1392  "Please try menu item \"%1\".",
1393  i18n ("&Save Edits...")));
1394  return;
1395  }
1396  if (playback) {
1397  return; // Avoid saving in playback mode.
1398  }
1399 
1400  QDate today = QDate::currentDate();
1401  QTime now = QTime::currentTime();
1402  QString saved;
1403  QString day;
1404  day = today.shortDayName (today.dayOfWeek());
1405  saved = saved.sprintf
1406  ("%-6s %03d %03ld %7ld %s %04d-%02d-%02d %02d:%02d\n",
1407  qPrintable(prefix), level, lives, startScore,
1408  qPrintable(day),
1409  today.year(), today.month(), today.day(),
1410  now.hour(), now.minute());
1411 
1412  QFile file1 (userDataDir + "savegame.dat");
1413  QFile file2 (userDataDir + "savegame.tmp");
1414 
1415  if (! file2.open (QIODevice::WriteOnly)) {
1416  KGrMessage::information (view, i18n ("Save Game"),
1417  i18n ("Cannot open file '%1' for output.",
1418  userDataDir + "savegame.tmp"));
1419  return;
1420  }
1421  QTextStream text2 (&file2);
1422  text2 << saved;
1423 
1424  if (file1.exists()) {
1425  if (! file1.open (QIODevice::ReadOnly)) {
1426  KGrMessage::information (view, i18n ("Save Game"),
1427  i18n ("Cannot open file '%1' for read-only.",
1428  userDataDir + "savegame.dat"));
1429  return;
1430  }
1431 
1432  QTextStream text1 (&file1);
1433  int n = 30; // Limit the file to the last 30 saves.
1434  while ((! text1.atEnd()) && (--n > 0)) {
1435  saved = text1.readLine() + '\n';
1436  text2 << saved;
1437  }
1438  file1.close();
1439  }
1440 
1441  file2.close();
1442 
1443  if (KGrGameIO::safeRename (view, userDataDir+"savegame.tmp",
1444  userDataDir+"savegame.dat")) {
1445  KGrMessage::information (view, i18n ("Save Game"),
1446  i18n ("Please note: for reasons of simplicity, your saved game "
1447  "position and score will be as they were at the start of this "
1448  "level, not as they are now."));
1449  }
1450  else {
1451  KGrMessage::information (view, i18n ("Save Game"),
1452  i18n ("Error: Failed to save your game."));
1453  }
1454 }
1455 
1456 bool KGrGame::selectSavedGame (int & selectedGame, int & selectedLevel)
1457 {
1458  selectedGame = 0;
1459  selectedLevel = 1;
1460 
1461  QFile savedGames (userDataDir + "savegame.dat");
1462  if (! savedGames.exists()) {
1463  // Use myMessage() because it stops the game while the message appears.
1464  myMessage (view, i18n ("Load Game"),
1465  i18n ("Sorry, there are no saved games."));
1466  return false;
1467  }
1468 
1469  if (! savedGames.open (QIODevice::ReadOnly)) {
1470  myMessage (view, i18n ("Load Game"),
1471  i18n ("Cannot open file '%1' for read-only.",
1472  userDataDir + "savegame.dat"));
1473  return false;
1474  }
1475 
1476  // Halt the game during the loadGame() dialog.
1477  freeze (ProgramPause, true);
1478 
1479  bool result = false;
1480 
1481  loadedData = "";
1482  KGrLGDialog * lg = new KGrLGDialog (&savedGames, gameList, view);
1483  if (lg->exec() == QDialog::Accepted) {
1484  loadedData = lg->getCurrentText();
1485  }
1486  delete lg;
1487 
1488  QString pr;
1489  int index = -1;
1490 
1491  selectedLevel = 0;
1492  if (! loadedData.isEmpty()) {
1493  pr = loadedData.mid (21, 7); // Get the game prefix.
1494  pr = pr.left (pr.indexOf (" ", 0, Qt::CaseInsensitive));
1495 
1496  for (int i = 0; i < gameList.count(); i++) { // Find the game.
1497  if (gameList.at (i)->prefix == pr) {
1498  index = i;
1499  break;
1500  }
1501  }
1502  if (index >= 0) {
1503  selectedGame = index;
1504  selectedLevel = loadedData.mid (28, 3).toInt();
1505  result = true;
1506  }
1507  else {
1508  KGrMessage::information (view, i18n ("Load Game"),
1509  i18n ("Cannot find the game with prefix '%1'.", pr));
1510  }
1511  }
1512 
1513  // Unfreeze the game, but only if it was previously unfrozen.
1514  freeze (ProgramPause, false);
1515 
1516  return result;
1517 }
1518 
1519 void KGrGame::loadGame (const int game, const int lev)
1520 {
1521  newGame (lev, game); // Re-start the selected game.
1522  showTutorialMessages (level);
1523  lives = loadedData.mid (32, 3).toLong(); // Update the lives.
1524  emit showLives (lives);
1525  score = loadedData.mid (36, 7).toLong(); // Update the score.
1526  emit showScore (score);
1527 }
1528 
1529 bool KGrGame::saveOK()
1530 {
1531  return (editor ? (editor->saveOK()) : true);
1532 }
1533 
1534 /******************************************************************************/
1535 /************************** HIGH-SCORE PROCEDURES ***************************/
1536 /******************************************************************************/
1537 
1538 void KGrGame::checkHighScore()
1539 {
1540  // Don't keep high scores for tutorial games.
1541  if ((prefix.left (4) == "tute") || (playback)) {
1542  return;
1543  }
1544 
1545  if (score <= 0) {
1546  return;
1547  }
1548 
1549 #ifdef USE_KSCOREDIALOG
1550  KScoreDialog scoreDialog (
1551  KScoreDialog::Name | KScoreDialog::Level |
1552  KScoreDialog::Date | KScoreDialog::Score,
1553  view);
1554  scoreDialog.setConfigGroup (prefix);
1555  KScoreDialog::FieldInfo scoreInfo;
1556  scoreInfo[KScoreDialog::Level].setNum (level);
1557  scoreInfo[KScoreDialog::Score].setNum (score);
1558  QDate today = QDate::currentDate();
1559  scoreInfo[KScoreDialog::Date] = today.toString ("ddd yyyy MM dd");
1560  if (scoreDialog.addScore (scoreInfo)) {
1561  scoreDialog.exec();
1562  }
1563 #else
1564  bool prevHigh = true;
1565  qint16 prevLevel = 0;
1566  qint32 prevScore = 0;
1567  QString thisUser = i18n ("Unknown");
1568  int highCount = 0;
1569 
1570  // Look for user's high-score file or for a released high-score file.
1571  QFile high1 (userDataDir + "hi_" + prefix + ".dat");
1572  QDataStream s1;
1573 
1574  if (! high1.exists()) {
1575  high1.setFileName (systemDataDir + "hi_" + prefix + ".dat");
1576  if (! high1.exists()) {
1577  prevHigh = false;
1578  }
1579  }
1580 
1581  // If a previous high score file exists, check the current score against it.
1582  if (prevHigh) {
1583  if (! high1.open (QIODevice::ReadOnly)) {
1584  QString high1_name = high1.fileName();
1585  KGrMessage::information (view, i18n ("Check for High Score"),
1586  i18n ("Cannot open file '%1' for read-only.", high1_name));
1587  return;
1588  }
1589 
1590  // Read previous users, levels and scores from the high score file.
1591  s1.setDevice (&high1);
1592  bool found = false;
1593  highCount = 0;
1594  while (! s1.atEnd()) {
1595  char * prevUser;
1596  char * prevDate;
1597  s1 >> prevUser;
1598  s1 >> prevLevel;
1599  s1 >> prevScore;
1600  s1 >> prevDate;
1601  delete prevUser;
1602  delete prevDate;
1603  highCount++;
1604  if (score > prevScore) {
1605  found = true; // We have a high score.
1606  break;
1607  }
1608  }
1609 
1610  // Check if higher than one on file or fewer than 10 previous scores.
1611  if ((! found) && (highCount >= 10)) {
1612  return; // We did not have a high score.
1613  }
1614  }
1615 
1616  /* ************************************************************* */
1617  /* If we have come this far, we have a new high score to record. */
1618  /* ************************************************************* */
1619 
1620  QFile high2 (userDataDir + "hi_" + prefix + ".tmp");
1621  QDataStream s2;
1622 
1623  if (! high2.open (QIODevice::WriteOnly)) {
1624  KGrMessage::information (view, i18n ("Check for High Score"),
1625  i18n ("Cannot open file '%1' for output.",
1626  userDataDir + "hi_" + prefix + ".tmp"));
1627  return;
1628  }
1629 
1630  // Dialog to ask the user to enter their name.
1631  QDialog * hsn = new QDialog (view,
1632  Qt::WindowTitleHint);
1633  hsn->setObjectName ( QLatin1String("hsNameDialog" ));
1634 
1635  int margin = 10;
1636  int spacing = 10;
1637  QVBoxLayout * mainLayout = new QVBoxLayout (hsn);
1638  mainLayout->setSpacing (spacing);
1639  mainLayout->setMargin (margin);
1640 
1641  QLabel * hsnMessage = new QLabel (
1642  i18n ("<html><b>Congratulations !!!</b><br>"
1643  "You have achieved a high score in this game.<br>"
1644  "Please enter your name so that it may be enshrined<br>"
1645  "in the KGoldrunner Hall of Fame.</html>"),
1646  hsn);
1647  QLineEdit * hsnUser = new QLineEdit (hsn);
1648  QPushButton * OK = new KPushButton (KStandardGuiItem::ok(), hsn);
1649 
1650  mainLayout-> addWidget (hsnMessage);
1651  mainLayout-> addWidget (hsnUser);
1652  mainLayout-> addWidget (OK);
1653 
1654  hsn-> setWindowTitle (i18n ("Save High Score"));
1655 
1656  // QPoint p = view->mapToGlobal (QPoint (0,0));
1657  // hsn-> move (p.x() + 50, p.y() + 50);
1658 
1659  OK-> setShortcut (Qt::Key_Return);
1660  hsnUser-> setFocus(); // Set the keyboard input on.
1661 
1662  connect (hsnUser, SIGNAL (returnPressed()), hsn, SLOT (accept()));
1663  connect (OK, SIGNAL (clicked()), hsn, SLOT (accept()));
1664 
1665  // Run the dialog to get the player's name. Use "-" if nothing is entered.
1666  hsn->exec();
1667  thisUser = hsnUser->text();
1668  if (thisUser.length() <= 0)
1669  thisUser = QChar('-');
1670  delete hsn;
1671 
1672  QDate today = QDate::currentDate();
1673  QString hsDate;
1674  QString day = today.shortDayName (today.dayOfWeek());
1675  hsDate = hsDate.sprintf
1676  ("%s %04d-%02d-%02d",
1677  qPrintable(day),
1678  today.year(), today.month(), today.day());
1679 
1680  s2.setDevice (&high2);
1681 
1682  if (prevHigh) {
1683  high1.reset();
1684  bool scoreRecorded = false;
1685  highCount = 0;
1686  while ((! s1.atEnd()) && (highCount < 10)) {
1687  char * prevUser;
1688  char * prevDate;
1689  s1 >> prevUser;
1690  s1 >> prevLevel;
1691  s1 >> prevScore;
1692  s1 >> prevDate;
1693  if ((! scoreRecorded) && (score > prevScore)) {
1694  highCount++;
1695  // Recode the user's name as UTF-8, in case it contains
1696  // non-ASCII chars (e.g. "Krüger" is encoded as "Krüger").
1697  s2 << thisUser.toUtf8().constData();
1698  s2 << (qint16) level;
1699  s2 << (qint32) score;
1700  s2 << qPrintable(hsDate);
1701  scoreRecorded = true;
1702  }
1703  if (highCount < 10) {
1704  highCount++;
1705  s2 << prevUser;
1706  s2 << prevLevel;
1707  s2 << prevScore;
1708  s2 << prevDate;
1709  }
1710  delete prevUser;
1711  delete prevDate;
1712  }
1713  if ((! scoreRecorded) && (highCount < 10)) {
1714  // Recode the user's name as UTF-8, in case it contains
1715  // non-ASCII chars (e.g. "Krüger" is encoded as "Krüger").
1716  s2 << thisUser.toUtf8().constData();
1717  s2 << (qint16) level;
1718  s2 << (qint32) score;
1719  s2 << qPrintable(hsDate);
1720  }
1721  high1.close();
1722  }
1723  else {
1724  // Recode the user's name as UTF-8, in case it contains
1725  // non-ASCII chars (e.g. "Krüger" is encoded as "Krüger").
1726  s2 << thisUser.toUtf8().constData();
1727  s2 << (qint16) level;
1728  s2 << (qint32) score;
1729  s2 << qPrintable(hsDate);
1730  }
1731 
1732  high2.close();
1733 
1734  if (KGrGameIO::safeRename (view, high2.fileName(),
1735  userDataDir + "hi_" + prefix + ".dat")) {
1736  // Remove a redundant popup message.
1737  // KGrMessage::information (view, i18n ("Save High Score"),
1738  // i18n ("Your high score has been saved."));
1739  }
1740  else {
1741  KGrMessage::information (view, i18n ("Save High Score"),
1742  i18n ("Error: Failed to save your high score."));
1743  }
1744 
1745  showHighScores();
1746  return;
1747 #endif
1748 }
1749 
1750 void KGrGame::showHighScores()
1751 {
1752  // Don't keep high scores for tutorial games.
1753  if (prefix.left (4) == "tute") {
1754  KGrMessage::information (view, i18n ("Show High Scores"),
1755  i18n ("Sorry, we do not keep high scores for tutorial games."));
1756  return;
1757  }
1758 
1759 #ifdef USE_KSCOREDIALOG
1760  KScoreDialog scoreDialog (
1761  KScoreDialog::Name | KScoreDialog::Level |
1762  KScoreDialog::Date | KScoreDialog::Score,
1763  view);
1764  scoreDialog.exec();
1765 #else
1766  qint16 prevLevel = 0;
1767  qint32 prevScore = 0;
1768  int n = 0;
1769 
1770  // Look for user's high-score file or for a released high-score file.
1771  QFile high1 (userDataDir + "hi_" + prefix + ".dat");
1772  QDataStream s1;
1773 
1774  if (! high1.exists()) {
1775  high1.setFileName (systemDataDir + "hi_" + prefix + ".dat");
1776  if (! high1.exists()) {
1777  KGrMessage::information (view, i18n ("Show High Scores"),
1778  i18n("Sorry, there are no high scores for the \"%1\" game yet.",
1779  gameList.at (gameIndex)->name));
1780  return;
1781  }
1782  }
1783 
1784  if (! high1.open (QIODevice::ReadOnly)) {
1785  QString high1_name = high1.fileName();
1786  KGrMessage::information (view, i18n ("Show High Scores"),
1787  i18n ("Cannot open file '%1' for read-only.", high1_name));
1788  return;
1789  }
1790 
1791  QDialog * hs = new QDialog (view,
1792  Qt::WindowTitleHint);
1793  hs->setObjectName ( QLatin1String("hsDialog" ));
1794 
1795  int margin = 10;
1796  int spacing = 10;
1797  QVBoxLayout * mainLayout = new QVBoxLayout (hs);
1798  mainLayout->setSpacing (spacing);
1799  mainLayout->setMargin (margin);
1800 
1801  QLabel * hsHeader = new QLabel (i18n (
1802  "<center><h2>KGoldrunner Hall of Fame</h2></center>"
1803  "<center><h3>\"%1\" Game</h3></center>",
1804  gameList.at (gameIndex)->name),
1805  hs);
1806  mainLayout->addWidget (hsHeader, 10);
1807 
1808  QTreeWidget * scores = new QTreeWidget (hs);
1809  mainLayout->addWidget (scores, 50);
1810  scores->setColumnCount (5);
1811  scores->setHeaderLabels (QStringList() <<
1812  i18nc ("1, 2, 3 etc.", "Rank") <<
1813  i18nc ("Person", "Name") <<
1814  i18nc ("Game level reached", "Level") <<
1815  i18n ("Score") <<
1816  i18n ("Date"));
1817  scores->setRootIsDecorated (false);
1818 
1819  hs-> setWindowTitle (i18n ("High Scores"));
1820 
1821  // Read and display the users, levels and scores from the high score file.
1822  scores->clear();
1823  s1.setDevice (&high1);
1824  n = 0;
1825  while ((! s1.atEnd()) && (n < 10)) {
1826  char * prevUser;
1827  char * prevDate;
1828  s1 >> prevUser;
1829  s1 >> prevLevel;
1830  s1 >> prevScore;
1831  s1 >> prevDate;
1832 
1833  // prevUser has been saved on file as UTF-8 to allow non=ASCII chars
1834  // in the user's name (e.g. "Krüger" is encoded as "Krüger" in UTF-8).
1835  QStringList data;
1836  data << QString().setNum (n+1)
1837  << QString().fromUtf8 (prevUser)
1838  << QString().setNum (prevLevel)
1839  << QString().setNum (prevScore)
1840  << QString().fromUtf8 (prevDate);
1841  QTreeWidgetItem * score = new QTreeWidgetItem (data);
1842  score->setTextAlignment (0, Qt::AlignRight); // Rank.
1843  score->setTextAlignment (1, Qt::AlignLeft); // Name.
1844  score->setTextAlignment (2, Qt::AlignRight); // Level.
1845  score->setTextAlignment (3, Qt::AlignRight); // Score.
1846  score->setTextAlignment (4, Qt::AlignLeft); // Date.
1847  if (prevScore > 0) { // Skip score 0 (bad file-data).
1848  scores->addTopLevelItem (score); // Show score > 0.
1849  if (n == 0) {
1850  scores->setCurrentItem (score); // Highlight the highest score.
1851  }
1852  n++;
1853  }
1854 
1855  delete prevUser;
1856  delete prevDate;
1857  }
1858 
1859  // Adjust the columns to fit the data.
1860  scores->header()->setResizeMode (0, QHeaderView::ResizeToContents);
1861  scores->header()->setResizeMode (1, QHeaderView::ResizeToContents);
1862  scores->header()->setResizeMode (2, QHeaderView::ResizeToContents);
1863  scores->header()->setResizeMode (3, QHeaderView::ResizeToContents);
1864  scores->header()->setResizeMode (4, QHeaderView::ResizeToContents);
1865  scores->header()->setMinimumSectionSize (-1); // Font metrics size.
1866 
1867  QFrame * separator = new QFrame (hs);
1868  separator->setFrameStyle (QFrame::HLine + QFrame::Sunken);
1869  mainLayout->addWidget (separator);
1870 
1871  QHBoxLayout *hboxLayout1 = new QHBoxLayout();
1872  hboxLayout1->setSpacing (spacing);
1873  QSpacerItem * spacerItem = new QSpacerItem (40, 20, QSizePolicy::Expanding,
1874  QSizePolicy::Minimum);
1875  hboxLayout1->addItem (spacerItem);
1876  QPushButton * OK = new KPushButton (KStandardGuiItem::close(), hs);
1877  OK-> setShortcut (Qt::Key_Return);
1878  OK-> setMaximumWidth (100);
1879  hboxLayout1->addWidget (OK);
1880  mainLayout-> addLayout (hboxLayout1, 5);
1881  // int w = (view->size().width()*4)/10;
1882  // hs-> setMinimumSize (w, w);
1883 
1884  // QPoint p = view->mapToGlobal (QPoint (0,0));
1885  // hs-> move (p.x() + 50, p.y() + 50);
1886 
1887  // Start up the dialog box.
1888  connect (OK, SIGNAL (clicked()), hs, SLOT (accept()));
1889  hs-> exec();
1890 
1891  delete hs;
1892 #endif
1893 }
1894 
1895 /******************************************************************************/
1896 /************************** AUTHORS' DEBUGGING AIDS **************************/
1897 /******************************************************************************/
1898 
1899 void KGrGame::dbgControl (const int code)
1900 {
1901  if (playback) {
1902  levelPlayer->interruptPlayback(); // Will emit interruptDemo().
1903  return;
1904  }
1905  // kDebug() << "Debug code =" << code;
1906  if (levelPlayer && gameFrozen) {
1907  levelPlayer->dbgControl (code);
1908  }
1909 }
1910 
1911 bool KGrGame::initGameLists()
1912 {
1913  // Initialise the lists of games (i.e. collections of levels).
1914 
1915  // System games are the ones distributed with KDE Games. They cannot be
1916  // edited or deleted, but they can be copied, edited and saved into a user's
1917  // game. Users' games and levels can be freely created, edited and deleted.
1918 
1919  owner = SYSTEM; // Use system levels initially.
1920  if (! loadGameData (SYSTEM)) // Load list of system games.
1921  return (false); // If no system games, abort.
1922  loadGameData (USER); // Load user's list of games.
1923  // If none, don't worry.
1924  for (int i = 0; i < gameList.count(); i++) {
1925  dbk1 << i << gameList.at(i)->prefix << gameList.at(i)->name;
1926  }
1927  return (true);
1928 }
1929 
1930 bool KGrGame::loadGameData (Owner o)
1931 {
1932  KGrGameIO io (view);
1933  QList<KGrGameData *> gList;
1934  QString filePath;
1935  IOStatus status = io.fetchGameListData
1936  (o, getDirectory (o), gList, filePath);
1937 
1938  bool result = false;
1939  switch (status) {
1940  case NotFound:
1941  // If the user has not yet created a collection, don't worry.
1942  if (o == SYSTEM) {
1943  KGrMessage::information (view, i18n ("Load Game Info"),
1944  i18n ("Cannot find game info file '%1'.", filePath));
1945  }
1946  break;
1947  case NoRead:
1948  case NoWrite:
1949  KGrMessage::information (view, i18n ("Load Game Info"),
1950  i18n ("Cannot open file '%1' for read-only.", filePath));
1951  break;
1952  case UnexpectedEOF:
1953  KGrMessage::information (view, i18n ("Load Game Info"),
1954  i18n ("Reached end of file '%1' before finding end of game-data.",
1955  filePath));
1956  break;
1957  case OK:
1958  // Append this owner's list of games to the main list.
1959  gameList += gList;
1960  result = true;
1961  break;
1962  }
1963 
1964  return (result);
1965 }
1966 
1967 bool KGrGame::initRecordingData (const Owner fileOwner, const QString & prefix,
1968  const int levelNo)
1969 {
1970  // Initialise the recording.
1971  delete recording;
1972  recording = new KGrRecording;
1973  recording->content.fill (0, 4000);
1974  recording->draws.fill (0, 400);
1975 
1976  // If system game or ENDE, choose system dir, else choose user dir.
1977  const QString dir = ((fileOwner == SYSTEM) || (levelNo == 0)) ?
1978  systemDataDir : userDataDir;
1979  if (playback) {
1980  kDebug() << "loadRecording" << dir << prefix << levelNo;
1981  if (! loadRecording (dir, prefix, levelNo)) {
1982  return false;
1983  }
1984  }
1985  else {
1986  KGrGameIO io (view);
1987  KGrLevelData levelData;
1988 
1989  // Read the level data.
1990  if (! io.readLevelData (dir, prefix, levelNo, levelData)) {
1991  return false;
1992  }
1993 
1994  recording->dateTime = QDateTime::currentDateTime()
1995  .toUTC()
1996  .toString (Qt::ISODate);
1997  kDebug() << "Recording at" << recording->dateTime;
1998 
1999  KGrGameData * gameData = gameList.at (gameIndex);
2000  recording->owner = gameData->owner;
2001  recording->rules = gameData->rules;
2002  recording->prefix = gameData->prefix;
2003  recording->gameName = gameData->name;
2004 
2005  recording->level = levelNo;
2006  recording->width = levelData.width;
2007  recording->height = levelData.height;
2008  recording->layout = levelData.layout;
2009 
2010  // If there is a name or hint, translate the UTF-8 code right now.
2011  recording->levelName = (levelData.name.size() > 0) ?
2012  i18n (levelData.name.constData()) : "";
2013  recording->hint = (levelData.hint.size() > 0) ?
2014  i18n (levelData.hint.constData()) : "";
2015 
2016  recording->lives = lives;
2017  recording->score = score;
2018  recording->speed = timeScale;
2019  recording->controlMode = controlMode;
2020  recording->keyOption = holdKeyOption;
2021  recording->content [0] = 0xff;
2022  }
2023  return true;
2024 }
2025 
2026 void KGrGame::saveRecording()
2027 {
2028  QString filename = userDataDir + "rec_" + prefix + ".txt";
2029  QString groupName = prefix + QString::number(level).rightJustified(3,'0');
2030  kDebug() << filename << groupName;
2031 
2032  KConfig config (filename, KConfig::SimpleConfig);
2033  KConfigGroup configGroup = config.group (groupName);
2034  configGroup.writeEntry ("DateTime", recording->dateTime);
2035  configGroup.writeEntry ("Owner", (int) recording->owner);
2036  configGroup.writeEntry ("Rules", (int) recording->rules);
2037  configGroup.writeEntry ("Prefix", recording->prefix);
2038  configGroup.writeEntry ("GameName", recording->gameName);
2039  configGroup.writeEntry ("Level", recording->level);
2040  configGroup.writeEntry ("Width", recording->width);
2041  configGroup.writeEntry ("Height", recording->height);
2042  configGroup.writeEntry ("Layout", recording->layout);
2043  configGroup.writeEntry ("Name", recording->levelName);
2044  configGroup.writeEntry ("Hint", recording->hint);
2045  configGroup.writeEntry ("Lives", (int) recording->lives);
2046  configGroup.writeEntry ("Score", (int) recording->score);
2047  configGroup.writeEntry ("Speed", (int) recording->speed);
2048  configGroup.writeEntry ("Mode", (int) recording->controlMode);
2049  configGroup.writeEntry ("KeyOption", (int)recording->keyOption);
2050 
2051  QList<int> bytes;
2052  int ch = 0;
2053  int n = recording->content.size();
2054  for (int i = 0; i < n; i++) {
2055  ch = (uchar)(recording->content.at(i));
2056  bytes.append (ch);
2057  if (ch == 0)
2058  break;
2059  }
2060  configGroup.writeEntry ("Content", bytes);
2061 
2062  bytes.clear();
2063  ch = 0;
2064  n = recording->draws.size();
2065  for (int i = 0; i < n; i++) {
2066  ch = (uchar)(recording->draws.at(i));
2067  bytes.append (ch);
2068  if (ch == 0)
2069  break;
2070  }
2071  configGroup.writeEntry ("Draws", bytes);
2072 
2073  configGroup.sync(); // Ensure that the entry goes to disk.
2074 
2075  // Save the game and level, for use in the REPLAY_LAST action.
2076  KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
2077  gameGroup.writeEntry ("LastGamePrefix", prefix);
2078  gameGroup.writeEntry ("LastLevel", level);
2079  gameGroup.sync(); // Ensure that the entry goes to disk.
2080 }
2081 
2082 bool KGrGame::loadRecording (const QString & dir, const QString & prefix,
2083  const int levelNo)
2084 {
2085  kDebug() << prefix << levelNo;
2086  QString filename = dir + "rec_" + prefix + ".txt";
2087  QString groupName = prefix + QString::number(levelNo).rightJustified(3,'0');
2088  kDebug() << filename << groupName;
2089 
2090  KConfig config (filename, KConfig::SimpleConfig);
2091  if (! config.hasGroup (groupName)) {
2092  kDebug() << "Group" << groupName << "NOT FOUND";
2093  return false;
2094  }
2095 
2096  KConfigGroup configGroup = config.group (groupName);
2097  QByteArray blank ("");
2098  recording->dateTime = configGroup.readEntry ("DateTime", "");
2099  recording->owner = (Owner)(configGroup.readEntry
2100  ("Owner", (int)(USER)));
2101  recording->rules = configGroup.readEntry ("Rules", (int)('T'));
2102  recording->prefix = configGroup.readEntry ("Prefix", "");
2103  recording->gameName = configGroup.readEntry ("GameName", blank);
2104  recording->level = configGroup.readEntry ("Level", 1);
2105  recording->width = configGroup.readEntry ("Width", FIELDWIDTH);
2106  recording->height = configGroup.readEntry ("Height", FIELDHEIGHT);
2107  recording->layout = configGroup.readEntry ("Layout", blank);
2108  recording->levelName = configGroup.readEntry ("Name", blank);
2109  recording->hint = configGroup.readEntry ("Hint", blank);
2110  recording->lives = configGroup.readEntry ("Lives", 5);
2111  recording->score = configGroup.readEntry ("Score", 0);
2112  recording->speed = configGroup.readEntry ("Speed", 10);
2113  recording->controlMode = configGroup.readEntry ("Mode", (int)MOUSE);
2114  recording->keyOption = configGroup.readEntry ("KeyOption",
2115  (int)CLICK_KEY);
2116 
2117  // If demoType is DEMO or SOLVE, get the TRANSLATED gameName, levelName and
2118  // hint from current data (other recordings have been translated already).
2119  if ((demoType == DEMO) || (demoType == SOLVE)) {
2120  int index = -1;
2121  for (int i = 0; i < gameList.count(); i++) { // Find the game.
2122  if (gameList.at (i)->prefix == recording->prefix) {
2123  index = i;
2124  break;
2125  }
2126  }
2127  if (index >= 0) {
2128  // Get the current translation of the name of the game.
2129  recording->gameName = gameList.at (index)->name;
2130 
2131  // Read the current level data.
2132  KGrGameIO io (view);
2133  KGrLevelData levelData;
2134 
2135  if (io.readLevelData (dir, recording->prefix, recording->level,
2136  levelData)) {
2137  // If there is a level name or hint, translate it.
2138  recording->levelName = (levelData.name.size() > 0) ?
2139  i18n (levelData.name.constData()) : "";
2140  recording->hint = (levelData.hint.size() > 0) ?
2141  i18n (levelData.hint.constData()) : "";
2142  }
2143  }
2144  }
2145 
2146  QList<int> bytes = configGroup.readEntry ("Content", QList<int>());
2147  int n = bytes.count();
2148  recording->content.fill (0, n + 1);
2149  for (int i = 0; i < n; i++) {
2150  recording->content [i] = bytes.at (i);
2151  }
2152 
2153  bytes.clear();
2154  bytes = configGroup.readEntry ("Draws", QList<int>());
2155  n = bytes.count();
2156  recording->draws.fill (0, n + 1);
2157  for (int i = 0; i < n; i++) {
2158  recording->draws [i] = bytes.at (i);
2159  }
2160 
2161  // Set up and display the starting score and lives.
2162  lives = recording->lives;
2163  emit showLives (lives);
2164  score = recording->score;
2165  emit showScore (score);
2166  return true;
2167 }
2168 
2169 void KGrGame::loadSounds()
2170 {
2171 #ifdef KGAUDIO_BACKEND_OPENAL
2172  const qreal volumes [NumSounds] = {0.6, 0.3, 0.3, 0.6, 0.6, 1.8, 1.0, 1.0, 1.0, 1.0};
2173  effects = new KGrSounds();
2174  effects->setParent (this); // Delete at end of KGrGame.
2175 
2176  fx[GoldSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2177  "themes/default/gold.ogg"));
2178  fx[StepSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2179  "themes/default/step.wav"));
2180  fx[ClimbSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2181  "themes/default/climb.wav"));
2182  fx[FallSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2183  "themes/default/falling.ogg"));
2184  fx[DigSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2185  "themes/default/dig.ogg"));
2186  fx[LadderSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2187  "themes/default/ladder.ogg"));
2188  fx[CompletedSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2189  "themes/default/completed.ogg"));
2190  fx[DeathSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2191  "themes/default/death.ogg"));
2192  fx[GameOverSound] = effects->loadSound (KStandardDirs::locate ("appdata",
2193  "themes/default/gameover.ogg"));
2194  fx[VictorySound] = effects->loadSound (KStandardDirs::locate ("appdata",
2195  "themes/default/victory.ogg"));
2196 
2197  // Gold and dig sounds are timed and are allowed to play for at least one
2198  // second, so that rapid sequences of those sounds are heard as overlapping.
2199  effects->setTimedSound (fx[GoldSound]);
2200  effects->setTimedSound (fx[DigSound]);
2201 
2202  // Adjust the relative volumes of sounds to improve the overall balance.
2203  for (int i = 0; i < NumSounds; i++) {
2204  effects->setVolume (fx [i], volumes [i]);
2205  }
2206 #endif
2207 }
2208 
2209 /******************************************************************************/
2210 /********************** MESSAGE BOX WITH FREEZE *************************/
2211 /******************************************************************************/
2212 
2213 void KGrGame::myMessage (QWidget * parent, const QString &title, const QString &contents)
2214 {
2215  // Halt the game while the message is displayed, if not already halted.
2216  freeze (ProgramPause, true);
2217 
2218  KGrMessage::information (parent, title, contents);
2219 
2220  // Unfreeze the game, but only if it was previously unfrozen.
2221  freeze (ProgramPause, false);
2222 }
2223 
2224 #include "kgrgame.moc"
2225 // vi: set sw=4 :
KGrLevelPlayer::prepareToPlay
void prepareToPlay()
Indicate that setup is complete and the human player can start playing at any time, by moving the pointer device or pressing a key.
Definition: kgrlevelplayer.cpp:360
QSpacerItem
SOLVE
Definition: kgrglobals.h:154
UNEXPECTED_END
Definition: kgrglobals.h:220
QTreeWidget::addTopLevelItem
void addTopLevelItem(QTreeWidgetItem *item)
QList::clear
void clear()
KGrGame::setToggle
void setToggle(const char *actionName, const bool onOff)
KGrRecording::rules
char rules
Rules that applied at time of recording.
Definition: kgrglobals.h:120
QDateTime::toString
QString toString(Qt::DateFormat format) const
KGrGame::logging
static bool logging
Definition: kgrgame.h:63
KGrLevelData::hint
QByteArray hint
Level hint (optional).
Definition: kgrglobals.h:111
QTime::minute
int minute() const
KGrEditor::editNameAndHint
void editNameAndHint()
Run a dialog in which the name and hint of a level can be edited.
Definition: kgreditor.cpp:200
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QWidget
kgrdebug.h
KGrLevelData::height
int height
Height of grid, in cells.
Definition: kgrglobals.h:108
UnexpectedEOF
Definition: kgrgameio.h:29
BAR
const char BAR
Definition: kgrglobals.h:39
kgreditor.h
KGrGameIO
The KGrGameIO class handles I/O for text-files containing KGoldrunner games and levels.
Definition: kgrgameio.h:58
QDateTime::toUTC
QDateTime toUTC() const
KGrScene::showReplayMessage
void showReplayMessage(bool onOff)
Definition: kgrscene.cpp:242
KGrGame::setInitialTheme
void setInitialTheme(const QString &themeFilepath)
Definition: kgrgame.cpp:413
NumSounds
Definition: kgrglobals.h:71
NotFound
Definition: kgrgameio.h:29
KGrScene::setReplayMessage
void setReplayMessage(const QString &msg)
Definition: kgrscene.cpp:237
DEMO
Definition: kgrglobals.h:154
KGrGameData::prefix
QString prefix
Game's filename prefix.
Definition: kgrglobals.h:94
EDIT_GAME
Definition: kgrglobals.h:157
KGrRecording::level
int level
Level number (at time of recording).
Definition: kgrglobals.h:123
KGrRecording::dateTime
QString dateTime
Date+time of recording (UTC in ISO format).
Definition: kgrglobals.h:118
KGrRecording::controlMode
int controlMode
Control mode during recording (mouse, etc).
Definition: kgrglobals.h:132
QDate::toString
QString toString(Qt::DateFormat format) const
KGrGameData::owner
Owner owner
Owner of the game: "System" or "User".
Definition: kgrglobals.h:91
SL_REPLAY
Definition: kgrglobals.h:62
KGrGameData
KGrGameData structure: contains attributes of a KGoldrunner game.
Definition: kgrglobals.h:88
KGrScene::fadeIn
void fadeIn(bool inOut)
Definition: kgrscene.cpp:320
QByteArray
QByteArray::at
char at(int i) const
KGrMessage::warning
static int warning(QWidget *parent, const QString &caption, const QString &text, const QString &label0, const QString &label1, const QString &label2="")
Definition: kgrdialog.cpp:314
KGrLevelPlayer
Class to play, record and play back a level of a game.
Definition: kgrlevelplayer.h:65
QLineEdit::text
text
ProgramPause
#define ProgramPause
Definition: kgrgame.cpp:79
KGrRecording::hint
QString hint
Hint (translated at recording time).
Definition: kgrglobals.h:128
KGrEditor::deleteLevelFile
bool deleteLevelFile(int pGameIndex, int pLevel)
Delete a level from a game.
Definition: kgreditor.cpp:425
HINT
Definition: kgrglobals.h:153
REPLAY_LAST
Definition: kgrglobals.h:154
QDataStream
QChar
HERO
const char HERO
Definition: kgrglobals.h:31
KGrLevelPlayer::setHoldKeyOption
void setHoldKeyOption(const int option)
Change the keyboard click/hold option during play.
Definition: kgrlevelplayer.cpp:1175
QByteArray::fill
QByteArray & fill(char ch, int size)
KGrEditor::setEditObj
void setEditObj(char newEditObj)
Set the next object for the editor to paint, e.g.
Definition: kgreditor.cpp:67
QLabel::setPixmap
void setPixmap(const QPixmap &)
QList::at
const T & at(int i) const
QDataStream::setDevice
void setDevice(QIODevice *d)
KGrGame::hintAvailable
void hintAvailable(bool)
KGrGame::inEditMode
bool inEditMode()
Definition: kgrgame.cpp:1146
KGrRecording::score
long score
Score at start of level.
Definition: kgrglobals.h:130
NORMAL
Definition: kgrglobals.h:220
KGrSounds::stop
void stop(int token)
Stop playing the sound associated with the given token.
Definition: kgrsounds.cpp:84
QHBoxLayout
QDialog::exec
int exec()
QLabel::setAlignment
void setAlignment(QFlags< Qt::AlignmentFlag >)
KGrEditor::editGame
bool editGame(int pGameIndex)
Create a new game (a collection point for levels) or load the details of an existing game...
Definition: kgreditor.cpp:496
KGrLGDialog::getCurrentText
const QString getCurrentText()
Definition: kgrdialog.h:113
SL_NONE
Definition: kgrglobals.h:62
SL_ANY
Definition: kgrglobals.h:60
DIG_LEFT
Definition: kgrglobals.h:175
KDialog
WON_LEVEL
Definition: kgrglobals.h:220
FIELDHEIGHT
const int FIELDHEIGHT
Definition: kgrglobals.h:49
KGrLevelData::layout
QByteArray layout
Codes for the level layout (mandatory).
Definition: kgrglobals.h:109
QFrame::setFrameStyle
void setFrameStyle(int style)
QDate::month
int month() const
KGrScene::setTitle
void setTitle(const QString &newTitle)
Set the text for the title of the current level.
Definition: kgrscene.cpp:227
SYSTEM
Definition: kgrglobals.h:26
QObject::disconnect
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
QTime
KGrLevelPlayer::pause
void pause(bool stop)
Pause or resume the gameplay in this level.
Definition: kgrlevelplayer.cpp:368
QFile
CHAMPION_SPEED
Definition: kgrglobals.h:164
NoWrite
Definition: kgrgameio.h:29
QTextStream
KGrGameData::rules
char rules
Game's rules: KGoldrunner or Traditional.
Definition: kgrglobals.h:93
KGrGame::playSound
void playSound(const int n, const bool onOff=true)
Definition: kgrgame.cpp:902
dbgLevel
static int dbgLevel
Definition: kgrdebug.h:21
QTreeWidget::clear
void clear()
KGrLevelPlayer::interruptPlayback
void interruptPlayback()
Stop playback of a recorded level and adjust the content of the recording so that the user can contin...
Definition: kgrlevelplayer.cpp:1065
LOAD
Definition: kgrglobals.h:152
QDate::dayOfWeek
int dayOfWeek() const
kgrdialog.h
LAPTOP
Definition: kgrglobals.h:161
KGrEditor::getGameAndLevel
void getGameAndLevel(int &game, int &lev)
Definition: kgreditor.h:166
KGrScene::deleteAllSprites
void deleteAllSprites()
Definition: kgrscene.cpp:589
kgrlevelplayer.h
QTreeWidget
CREATE_LEVEL
Definition: kgrglobals.h:156
Direction
Direction
Definition: kgrglobals.h:174
BEGINNER_SPEED
Definition: kgrglobals.h:163
QBoxLayout::addWidget
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
StepSound
Definition: kgrglobals.h:70
QList::append
void append(const T &value)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
PLAY_STEPS
Definition: kgrglobals.h:166
QHeaderView::setMinimumSectionSize
void setMinimumSectionSize(int size)
NUGGET
const char NUGGET
Definition: kgrglobals.h:37
KGrRecording::levelName
QString levelName
Name of the level (translated at rec time).
Definition: kgrglobals.h:127
KGrEditor::moveLevelFile
bool moveLevelFile(int pGameIndex, int pLevel)
Move a level to another game or level number.
Definition: kgreditor.cpp:326
QTimer
VictorySound
Definition: kgrglobals.h:71
QString::rightJustified
QString rightJustified(int width, QChar fill, bool truncate) const
KGrRecording::speed
int speed
Speed of game during recording (normal=10).
Definition: kgrglobals.h:131
KGrRecording::owner
Owner owner
Original owner, at time of recording.
Definition: kgrglobals.h:119
KGrGame::gameFreeze
void gameFreeze(bool)
QObject
KGrLevelPlayer::dbgControl
void dbgControl(int code)
Implement author's debugging aids, which are activated only if the level is paused and the KConfig fi...
Definition: kgrlevelplayer.cpp:1198
QString::toInt
int toInt(bool *ok, int base) const
MOVE_LEVEL
Definition: kgrglobals.h:156
QBoxLayout::addItem
virtual void addItem(QLayoutItem *item)
QObject::setObjectName
void setObjectName(const QString &name)
KGrRecording
KGrRecording structure: contains a record of play in a KGoldrunner level.
Definition: kgrglobals.h:115
FIELDWIDTH
const int FIELDWIDTH
Definition: kgrglobals.h:48
QString::isEmpty
bool isEmpty() const
FallSound
Definition: kgrglobals.h:70
QDate::day
int day() const
QByteArray::constData
const char * constData() const
KGrGame::dbgControl
void dbgControl(const int code)
Definition: kgrgame.cpp:1899
KGrMessage::information
static void information(QWidget *parent, const QString &caption, const QString &text, const QString &dontShowAgain=QString())
Definition: kgrdialog.cpp:306
KGrGame::showScore
void showScore(long)
KGrSounds
Definition: kgrsounds.h:28
LadderSound
Definition: kgrglobals.h:70
KGrLevelData
KGrLevelData structure: contains attributes of a KGoldrunner level.
Definition: kgrglobals.h:103
kgrsounds.h
QVBoxLayout
KGrGameData::nLevels
int nLevels
Number of levels in the game.
Definition: kgrglobals.h:92
KGrLevelPlayer::setDirectionByKey
void setDirectionByKey(const Direction dirn, const bool pressed)
Set a direction for the hero to move or dig when using keyboard control.
Definition: kgrlevelplayer.cpp:440
QDate
MOUSE
Definition: kgrglobals.h:161
KGrRecording::lives
long lives
Number of lives at start of level.
Definition: kgrglobals.h:129
QDate::year
int year() const
KGrScene::goToBlack
void goToBlack()
Definition: kgrscene.cpp:315
KGrLevelPlayer::setTimeScale
void setTimeScale(const int timeScale)
Set the overall speed of gameplay.
Definition: kgrlevelplayer.cpp:1185
KGrGame::kbControl
void kbControl(const int dirn, const bool pressed=true)
Definition: kgrgame.cpp:1332
QDate::shortDayName
QString shortDayName(int weekday)
QString
QList< KGrGameData * >
LADDER
const char LADDER
Definition: kgrglobals.h:36
HLADDER
const char HLADDER
Definition: kgrglobals.h:35
QLayout::setMargin
void setMargin(int margin)
HIGH_SCORE
Definition: kgrglobals.h:152
HOLD_KEY
Definition: kgrglobals.h:162
QDataStream::atEnd
bool atEnd() const
QTreeWidget::setColumnCount
void setColumnCount(int columns)
KGrGame::setAvail
void setAvail(const char *actionName, const bool onOff)
QStringList
KGrLGDialog
Definition: kgrdialog.h:107
KGrRecording::prefix
QString prefix
Game's filename prefix.
Definition: kgrglobals.h:121
NEW
Definition: kgrglobals.h:152
KGrGame::initGame
void initGame()
Definition: kgrgame.cpp:418
KGrGame::~KGrGame
~KGrGame()
Definition: kgrgame.cpp:123
QTime::hour
int hour() const
NewLevel
#define NewLevel
Definition: kgrgame.cpp:80
NoRead
Definition: kgrgameio.h:29
KGrGame::showLives
void showLives(long)
STARTUP_DEMO
Definition: kgrglobals.h:160
KGrSounds::play
int play(int effect)
Play a sound effect.
Definition: kgrsounds.cpp:60
QObject::setParent
void setParent(QObject *parent)
REPLAY_ANY
Definition: kgrglobals.h:154
KGrEditor
This class is the game-editor for KGoldrunner.
Definition: kgreditor.h:42
ENEMY
const char ENEMY
Definition: kgrglobals.h:29
QFrame
UserPause
#define UserPause
Definition: kgrgame.cpp:78
BRICK
const char BRICK
Definition: kgrglobals.h:33
KILL_HERO
Definition: kgrglobals.h:153
QTreeWidget::setCurrentItem
void setCurrentItem(QTreeWidgetItem *item)
kgrscene.h
QTime::currentTime
QTime currentTime()
QString::toLong
long toLong(bool *ok, int base) const
KGrGame::gameActions
void gameActions(const int action)
Definition: kgrgame.cpp:180
QTreeWidget::setHeaderLabels
void setHeaderLabels(const QStringList &labels)
dbk2
#define dbk2
Definition: kgrdebug.h:25
KGrSounds::setMuted
void setMuted(bool mute)
Definition: kgrsounds.cpp:91
IOStatus
IOStatus
Return values from I/O operations.
Definition: kgrgameio.h:29
KGrGame::setEditMenu
void setEditMenu(bool)
KGrLevelPlayer::killHero
void killHero()
If not in playback mode, add a code to the recording and kill the hero.
Definition: kgrlevelplayer.cpp:1154
kgrview.h
EDIT_ANY
Definition: kgrglobals.h:156
KGrRecording::draws
QByteArray draws
The random numbers used during play.
Definition: kgrglobals.h:135
GoldSound
Definition: kgrglobals.h:70
KGrSLDialog
Definition: kgrselector.h:50
DELETE_LEVEL
Definition: kgrglobals.h:157
QDateTime::currentDateTime
QDateTime currentDateTime()
QString::mid
QString mid(int position, int n) const
FBRICK
const char FBRICK
Definition: kgrglobals.h:34
KGrEditor::createLevel
bool createLevel(int pGameIndex)
Set up a blank level-layout, ready for editing.
Definition: kgreditor.cpp:72
KEYBOARD
Definition: kgrglobals.h:161
QTreeWidgetItem
QLatin1String
DeathSound
Definition: kgrglobals.h:71
INC_SPEED
Definition: kgrglobals.h:165
CompletedSound
Definition: kgrglobals.h:71
KGrEditor::saveLevelFile
bool saveLevelFile()
Save an edited level in a text file (*.grl) in the user's area.
Definition: kgreditor.cpp:214
QString::setNum
QString & setNum(short n, int base)
KGrGame::bugFix
static bool bugFix
Definition: kgrgame.h:62
NORMAL_SPEED
Definition: kgrglobals.h:163
KGrSounds::stopAllSounds
void stopAllSounds()
Stop all sounds currently playing.
Definition: kgrsounds.cpp:47
QString::sprintf
QString & sprintf(const char *cformat,...)
QHeaderView::setResizeMode
void setResizeMode(ResizeMode mode)
QDate::currentDate
QDate currentDate()
DigSound
Definition: kgrglobals.h:70
kgrselector.h
KGrView
Definition: kgrview.h:27
KGrRecording::width
int width
Width of grid, in cells (at rec time).
Definition: kgrglobals.h:124
KGrLevelPlayer::setControlMode
void setControlMode(const int mode)
Change the input-mode during play.
Definition: kgrlevelplayer.cpp:1165
KGrRecording::keyOption
int keyOption
Click/hold option for keyboard mode.
Definition: kgrglobals.h:133
CREATE_GAME
Definition: kgrglobals.h:157
KGrLevelData::width
int width
Width of grid, in cells.
Definition: kgrglobals.h:107
QString::length
int length() const
KGrSLDialog::selectLevel
bool selectLevel(int &selectedGame, int &selectedLevel)
Definition: kgrselector.cpp:72
KGrRecording::gameName
QString gameName
Name of the game (translated at rec time).
Definition: kgrglobals.h:122
USER
Definition: kgrglobals.h:26
KGrEditor::updateLevel
bool updateLevel(int pGameIndex, int pLevel)
Load and display an existing level, ready for editing.
Definition: kgreditor.cpp:120
QString::left
QString left(int n) const
DEAD
Definition: kgrglobals.h:220
KGrGame::editToolbarActions
void editToolbarActions(const int action)
Definition: kgrgame.cpp:339
QDialog
dbk
#define dbk
Definition: kgrdebug.h:23
GameOverSound
Definition: kgrglobals.h:71
KGrSounds::setTimedSound
void setTimedSound(int i)
Set up a sound to have its latest start-time recorded.
Definition: kgrsounds.cpp:42
QTimer::start
void start(int msec)
QPushButton
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
QTreeWidgetItem::setTextAlignment
void setTextAlignment(int column, int alignment)
QTreeView::header
QHeaderView * header() const
PLAY_SOUNDS
Definition: kgrglobals.h:159
QLineEdit
OK
Definition: kgrgameio.h:29
DEC_SPEED
Definition: kgrglobals.h:165
dbk1
#define dbk1
Definition: kgrdebug.h:24
KGrScene::setLevel
void setLevel(unsigned int level)
Set the current level number.
Definition: kgrscene.cpp:346
KGrEditor::saveOK
bool saveOK()
Check if there are any unsaved edits and, if so, ask the user what to do.
Definition: kgreditor.cpp:646
KGrGame::saveOK
bool saveOK()
Definition: kgrgame.cpp:1529
DIG_RIGHT
Definition: kgrglobals.h:175
NEXT_LEVEL
Definition: kgrglobals.h:152
KGrGame::KGrGame
KGrGame(KGrView *theView, const QString &theSystemDir, const QString &theUserDir)
Definition: kgrgame.cpp:86
QTreeView::setRootIsDecorated
void setRootIsDecorated(bool show)
INSTANT_REPLAY
Definition: kgrglobals.h:154
KGrGame::editActions
void editActions(const int action)
Definition: kgrgame.cpp:253
KGrGameData::name
QString name
Name of game (translated, if System game).
Definition: kgrglobals.h:98
SAVE_GAME
Definition: kgrglobals.h:152
QByteArray::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QLabel
KGrRecording::height
int height
Height of grid, in cells (at rec time).
Definition: kgrglobals.h:125
KGrSounds::loadSound
int loadSound(const QString &fileName)
Load a sound sample.
Definition: kgrsounds.cpp:34
KGrRecording::content
QByteArray content
The encoded recording of play.
Definition: kgrglobals.h:134
kgrgameio.h
kgrgame.h
KGrRecording::layout
QByteArray layout
Codes for the level layout (at rec time).
Definition: kgrglobals.h:126
KGrGame::settings
void settings(const int action)
Definition: kgrgame.cpp:367
KGrSounds::setVolume
void setVolume(int effect, qreal volume)
Change the volume of one type of sound (e.g.
Definition: kgrsounds.cpp:99
KGrGameIO::safeRename
static bool safeRename(QWidget *theView, const QString &oldName, const QString &newName)
Definition: kgrgameio.cpp:356
KGrGame::quitGame
void quitGame()
SelectAction
SelectAction
Definition: kgrglobals.h:60
CONCRETE
const char CONCRETE
Definition: kgrglobals.h:32
ClimbSound
Definition: kgrglobals.h:70
KGrGame::incScore
void incScore(const int n)
Definition: kgrgame.cpp:896
SAVE_EDITS
Definition: kgrglobals.h:156
KGrGame::initGameLists
bool initGameLists()
Definition: kgrgame.cpp:1911
QBoxLayout::setSpacing
void setSpacing(int spacing)
FREE
const char FREE
Definition: kgrglobals.h:28
PAUSE
Definition: kgrglobals.h:152
SL_SOLVE
Definition: kgrglobals.h:62
EDIT_HINT
const char EDIT_HINT
Definition: kgrglobals.h:45
Owner
Owner
Definition: kgrglobals.h:26
CLICK_KEY
Definition: kgrglobals.h:162
QTimer::singleShot
singleShot
KGrLevelPlayer::init
void init(KGrView *view, KGrRecording *pRecording, const bool pPlayback, const bool gameFrozen)
The main initialisation of KGrLevelPlayer.
Definition: kgrlevelplayer.cpp:100
KGrLevelData::name
QByteArray name
Level name (optional).
Definition: kgrglobals.h:110
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:18:24 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kgoldrunner

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

kdegames API Reference

Skip menu "kdegames API Reference"
  • granatier
  • kapman
  • kblackbox
  • kgoldrunner
  • kigo
  • kmahjongg
  • KShisen
  • ksquares
  • libkdegames
  •   highscore
  •   libkdegamesprivate
  •     kgame
  • libkmahjongg
  • palapeli
  •   libpala

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal