30 #include <libkdegames_capabilities.h>
31 #ifdef KGAUDIO_BACKEND_OPENAL
44 #include <QStringList>
48 #include <KRandomSequence>
49 #include <KPushButton>
50 #include <KStandardGuiItem>
51 #include <KStandardDirs>
52 #include <KApplication>
61 #ifdef USE_KSCOREDIALOG
62 #include <KScoreDialog>
66 #include <QTextStream>
68 #include <QVBoxLayout>
70 #include <QSpacerItem>
71 #include <QTreeWidget>
72 #include <QHeaderView>
73 #include <QTreeWidgetItem>
78 #define UserPause true
79 #define ProgramPause false
94 scene (view->gameScene()),
95 systemDataDir (theSystemDir),
96 userDataDir (theUserDir),
98 mainDemoName (
"demo"),
102 programFreeze (false),
113 dyingTimer =
new QTimer (
this);
114 connect (dyingTimer, SIGNAL (timeout()), SLOT (finalBreath()));
117 randomGen =
new KRandomSequence (time (0));
118 kDebug() <<
"RANDOM NUMBER GENERATOR INITIALISED";
125 qDeleteAll(gameList);
135 bool KGrGame::modeSwitch (
const int action,
136 int & selectedGame,
int & selectedLevel)
159 result = selectSavedGame (selectedGame, selectedLevel);
172 result = selectGame (slAction, selectedGame, selectedLevel);
174 if (playback && (result ==
true)) {
182 int selectedGame = gameIndex;
183 int selectedLevel = level;
184 if (! modeSwitch (action, selectedGame, selectedLevel)) {
189 newGame (selectedLevel, selectedGame);
190 showTutorialMessages (level);
193 if (level >= levelMax) {
195 i18n (
"There are no more levels in this game."));
199 kDebug() <<
"Game" << gameList.
at(gameIndex)->name <<
"level" << level;
200 newGame (level, gameIndex);
201 showTutorialMessages (level);
204 loadGame (selectedGame, selectedLevel);
219 if (levelPlayer && (! playback)) {
230 if (! startDemo (
SYSTEM, mainDemoName, 1)) {
235 runReplay (
SOLVE, selectedGame, selectedLevel);
239 startInstantReplay();
246 runReplay (
REPLAY_ANY, selectedGame, selectedLevel);
256 bool newEditor = (editor) ?
false :
true;
257 int editLevel = level;
258 dbk <<
"Level" << level << prefix << gameIndex;
262 i18n (
"Inappropriate action: you are not editing a level."));
268 editor =
new KGrEditor (view, systemDataDir, userDataDir, gameList);
277 editOK = editor->
updateLevel (gameIndex, editLevel);
292 editOK = editor->
editGame (gameIndex);
323 int game = gameIndex, lev = level;
326 if (((game != gameIndex) || (lev != level)) && (lev != 0)) {
328 prefix = gameList.
at (gameIndex)->prefix;
331 kDebug() <<
"Saving to KConfigGroup";
332 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
333 gameGroup.writeEntry (
"GamePrefix", prefix);
334 gameGroup.writeEntry (
"Level_" + prefix, level);
370 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
375 toggleSoundsOnOff (action);
379 onOff = (! gameGroup.readEntry (
"StartingDemo",
true));
380 gameGroup.writeEntry (
"StartingDemo", onOff);
385 setControlMode (action);
386 gameGroup.writeEntry (
"ControlMode", action);
391 setHoldKeyOption (action);
392 gameGroup.writeEntry (
"HoldKeyOption", action);
398 setTimeScale (action);
399 gameGroup.writeEntry (
"SpeedLevel", action);
400 gameGroup.writeEntry (
"ActualSpeed", timeScale);
404 setTimeScale (action);
405 gameGroup.writeEntry (
"ActualSpeed", timeScale);
415 initialThemeFilepath = themeFilepath;
420 #ifndef KGAUDIO_BACKEND_OPENAL
422 i18n (
"Warning: This copy of KGoldrunner has no sound.\n"
424 "This is because no development versions of the OpenAL and "
425 "SndFile libraries were present when it was compiled and built."),
428 kDebug() <<
"Entered, draw the initial graphics now ...";
432 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
433 QString prevGamePrefix = gameGroup.readEntry (
"GamePrefix",
"tute");
434 int prevLevel = gameGroup.readEntry (
"Level_" + prevGamePrefix, 1);
436 kDebug()<<
"Config() Game and Level" << prevGamePrefix << prevLevel;
443 dbk1 << gameIndex << level <<
"Search:" << prevGamePrefix << prevLevel;
446 if (gameData->
prefix == prevGamePrefix) {
449 dbk1 <<
"FOUND:" << gameIndex << prevGamePrefix << level;
457 emit
setToggle (((controlMode == MOUSE) ?
"mouse_mode" :
458 ((controlMode ==
KEYBOARD) ?
"keyboard_mode" :
459 "laptop_mode")),
true);
461 holdKeyOption = gameGroup.readEntry (
"HoldKeyOption", (
int)
CLICK_KEY);
462 emit
setToggle (((holdKeyOption == CLICK_KEY) ?
"click_key" :
465 int speedLevel = gameGroup.readEntry (
"SpeedLevel", (
int)
NORMAL_SPEED);
467 emit
setToggle ((speedLevel == NORMAL_SPEED) ?
"normal_speed" :
469 "champion_speed"),
true);
470 timeScale = gameGroup.readEntry (
"ActualSpeed", 10);
472 #ifdef KGAUDIO_BACKEND_OPENAL
474 soundOn = gameGroup.readEntry (
"Sound",
false);
475 kDebug() <<
"Sound" << soundOn;
480 emit
setToggle (
"options_sounds", soundOn);
482 stepsOn = gameGroup.readEntry (
"StepSounds",
false);
483 kDebug() <<
"StepSounds" << stepsOn;
484 emit
setToggle (
"options_steps", stepsOn);
487 dbk1 <<
"Owner" << gameList.
at (gameIndex)->owner
488 << gameList.
at (gameIndex)->name << level;
490 setPlayback (gameGroup.readEntry (
"StartingDemo",
true));
491 if (playback && (startDemo (
SYSTEM, mainDemoName, 1))) {
497 newGame (level, gameIndex);
500 emit
setToggle (
"options_demo", startupDemo);
508 bool KGrGame::startDemo (
const Owner demoOwner,
const QString & pPrefix,
512 QString dir = (demoOwner ==
SYSTEM) ? systemDataDir : userDataDir;
513 QString filepath = dir +
"rec_" + pPrefix +
".txt";
514 KConfig config (filepath, KConfig::SimpleConfig);
516 dbk1 <<
"DEMO LIST" << demoList.
count() << demoList;
520 int index = demoList.
indexOf (s) + 1;
521 dbk1 <<
"DEMO looking for" << s <<
"found at" << index;
524 kDebug() <<
"DEMO not found in" << filepath << s << pPrefix << levelNo;
529 if (playLevel (demoOwner, pPrefix, levelNo, (!
NewLevel))) {
530 playbackOwner = demoOwner;
531 playbackPrefix = pPrefix;
532 playbackIndex = levelNo;
535 playbackMax = (playbackPrefix == mainDemoName) ?
536 demoList.
count() : levelNo;
540 kDebug() <<
"DEMO started ..." << filepath << pPrefix << levelNo;
545 kDebug() <<
"DEMO failed ..." << filepath << pPrefix << levelNo;
550 void KGrGame::runNextDemoLevel()
552 dbk <<
"index" << playbackIndex <<
"max" << playbackMax << playbackPrefix
553 <<
"owner" << playbackOwner;
554 if (playbackIndex < playbackMax) {
556 if (playLevel (playbackOwner, playbackPrefix,
561 kDebug() <<
"DEMO continued ..." << playbackPrefix << playbackIndex;
568 void KGrGame::finishDemo()
571 newGame (level, gameIndex);
579 showTutorialMessages (level);
583 void KGrGame::interruptDemo()
585 kDebug() <<
"DEMO interrupted ...";
588 levelMax = gameList.
at (gameIndex)->nLevels;
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");
601 void KGrGame::startInstantReplay()
603 dbk <<
"Start INSTANT_REPLAY";
612 lives = recording->
lives;
614 score = recording->
score;
623 void KGrGame::replayLastLevel()
626 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
627 QString lastPrefix = gameGroup.readEntry (
"LastGamePrefix",
"");
628 int lastLevel = gameGroup.readEntry (
"LastLevel", -1);
633 if (! startDemo (
USER, lastPrefix, lastLevel)) {
636 i18n (
"ERROR: Could not find and replay a recording of "
637 "the last level you played."));
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."));
652 void KGrGame::quickStartDialog()
661 qs->setCaption (i18n(
"Quick Start"));
663 (KDialog::Ok | KDialog::Cancel | KDialog::User1 | KDialog::User2);
664 qs->setButtonFocus (KDialog::Ok);
665 qs->setButtonsOrientation (Qt::Vertical);
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"));
676 qs->setButtonText (KDialog::Cancel, i18n (
"&Quit"));
677 qs->setButtonToolTip (KDialog::Cancel, i18n (
"Close KGoldrunner"));
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"));
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"));
697 qs->setMainWidget (logo);
698 logo->
setPixmap (kapp->windowIcon().pixmap (240));
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()));
709 void KGrGame::quickStartPlay()
715 showTutorialMessages (level);
718 void KGrGame::quickStartNewGame()
723 int selectedGame = gameIndex;
724 int selectedLevel = level;
725 if (modeSwitch (
NEW, selectedGame, selectedLevel)) {
726 newGame (selectedLevel, selectedGame);
728 showTutorialMessages (selectedLevel);
731 void KGrGame::quickStartUseMenu()
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."));
745 void KGrGame::quickStartQuit()
755 int & selectedGame,
int & selectedLevel)
762 gameList, systemDataDir, userDataDir,
764 bool selected = sl->
selectLevel (selectedGame, selectedLevel);
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;
777 void KGrGame::runReplay (
const int action,
778 const int selectedGame,
const int selectedLevel)
780 if (action ==
SOLVE) {
784 (
SYSTEM, gameList.
at (selectedGame)->prefix, selectedLevel)) {
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");
795 (
USER, gameList.
at (selectedGame)->prefix, selectedLevel)) {
797 i18n (
"Sorry, you do not seem to have played and recorded "
798 "the selected level before."),
"Show_noReplay");
807 void KGrGame::newGame (
const int lev,
const int newGameIndex)
813 gameIndex = newGameIndex;
814 owner = gameData->
owner;
815 prefix = gameData->
prefix;
825 playLevel (owner, prefix, level,
NewLevel);
828 bool KGrGame::playLevel (
const Owner fileOwner,
const QString & prefix,
829 const int levelNo,
const bool newLevel)
848 if (! initRecordingData (fileOwner, prefix, levelNo)) {
860 levelHint = recording->
hint;
869 if (newLevel && (level != 0)) {
870 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
871 gameGroup.writeEntry (
"GamePrefix", prefix);
872 gameGroup.writeEntry (
"Level_" + prefix, level);
879 void KGrGame::setupLevelPlayer()
883 levelPlayer->
init (view, recording, playback, gameFrozen);
888 connect (levelPlayer, SIGNAL (endLevel(
int)),
889 this, SLOT (endLevel(
int)), Qt::QueuedConnection);
891 connect (levelPlayer, SIGNAL (interruptDemo()),
892 this, SLOT (interruptDemo()), Qt::QueuedConnection);
904 #ifdef KGAUDIO_BACKEND_OPENAL
908 static int fallToken = -1;
912 token = effects->
play (fx [n]);
919 else if ((n ==
FallSound) && (fallToken >= 0)) {
920 effects->
stop (fallToken);
926 void KGrGame::endLevel (
const int result)
928 dbk <<
"Return to KGrGame, result:" << result;
930 #ifdef KGAUDIO_BACKEND_OPENAL
950 dbk <<
"delete levelPlayer";
957 if ((! playback) && ((result ==
WON_LEVEL) || (result ==
DEAD))) {
958 dbk <<
"saveRecording()";
966 else if (result ==
DEAD) {
972 void KGrGame::herosDead()
974 if ((level < 1) || (lives <= 0)) {
979 if ((--lives > 0) || playback) {
988 dyingTimer->
start (1000);
1000 QString gameOver = i18n (
"<NOBR><B>GAME OVER !!!</B></NOBR><P>"
1001 "Would you like to try this level again?</P>");
1003 i18n (
"&Try Again"), i18n (
"&Finish"))) {
1006 newGame (level, gameIndex);
1007 showTutorialMessages (level);
1023 void KGrGame::finalBreath()
1025 dbk <<
"Connecting fadeFinished()";
1026 connect (scene, SIGNAL (fadeFinished()),
this, SLOT (repeatLevel()));
1027 dbk <<
"Calling scene->fadeOut()";
1031 void KGrGame::repeatLevel()
1033 disconnect (scene, SIGNAL (fadeFinished()),
this, SLOT (repeatLevel()));
1041 else if (playLevel (owner, prefix, level, (!
NewLevel))) {
1048 void KGrGame::levelCompleted()
1052 dbk <<
"Connecting fadeFinished()";
1053 connect (scene, SIGNAL (fadeFinished()),
this, SLOT (goUpOneLevel()));
1054 dbk <<
"Calling scene->fadeOut()";
1058 void KGrGame::goUpOneLevel()
1060 disconnect (scene, SIGNAL (fadeFinished()),
this, SLOT (goUpOneLevel()));
1071 if (level >= levelMax) {
1077 i18n (
"<b>CONGRATULATIONS !!!!</b>"
1078 "<p>You have conquered the last level in the "
1079 "<b>\"%1\"</b> game !!</p>", gameData->
name));
1089 if (playLevel (owner, prefix, level,
NewLevel)) {
1090 showTutorialMessages (level);
1094 void KGrGame::setControlMode (
const int mode)
1097 bool enableDisable = (mode ==
KEYBOARD);
1098 emit
setAvail (
"click_key", enableDisable);
1099 emit
setAvail (
"hold_key", enableDisable);
1102 if (levelPlayer && (! playback)) {
1108 void KGrGame::setHoldKeyOption (
const int option)
1110 holdKeyOption = option;
1111 if (levelPlayer && (! playback)) {
1117 void KGrGame::setTimeScale (
const int action)
1130 timeScale = (timeScale < 20) ? timeScale + 1 : 20;
1133 timeScale = (timeScale > 2) ? timeScale - 1 : 2;
1139 if (levelPlayer && (! playback)) {
1141 kDebug() <<
"setTimeScale" << (timeScale);
1148 return (editor != 0);
1151 void KGrGame::toggleSoundsOnOff (
const int action)
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);
1159 soundOn = soundOnOff;
1162 stepsOn = soundOnOff;
1165 #ifdef KGAUDIO_BACKEND_OPENAL
1167 if (soundOn && (effects == 0)) {
1175 void KGrGame::freeze (
const bool userAction,
const bool on_off)
1177 QString type = userAction ?
"UserAction" :
"ProgramAction";
1178 kDebug() <<
"PAUSE:" << type << on_off;
1179 kDebug() <<
"gameFrozen" << gameFrozen <<
"programFreeze" << programFreeze;
1181 #ifdef KGAUDIO_BACKEND_OPENAL
1182 if (on_off && effects) {
1191 if (programFreeze) {
1192 kDebug() <<
"P: The program has already frozen the game.";
1195 kDebug() <<
"P: The user has already frozen the game.";
1199 programFreeze =
false;
1201 else if (! programFreeze) {
1203 kDebug() <<
"P: The user will keep the game frozen.";
1206 kDebug() <<
"P: The game is NOT frozen.";
1211 programFreeze = on_off;
1213 else if (programFreeze) {
1215 kDebug() <<
"U: THE USER HAS BROKEN THROUGH SOMEHOW.";
1223 gameFrozen = on_off;
1225 levelPlayer->
pause (on_off);
1227 kDebug() <<
"RESULT: gameFrozen" << gameFrozen
1228 <<
"programFreeze" << programFreeze;
1231 void KGrGame::showHint()
1234 QString caption = i18n (
"Hint");
1236 if (levelHint.
length() > 0) {
1240 i18n (
"&OK"), i18n (
"&Show A Solution"))) {
1247 runReplay (
SOLVE, gameIndex, level);
1252 myMessage (view, caption,
1253 i18n (
"Sorry, there is no hint for this level."));
1256 void KGrGame::showTutorialMessages (
int levelNo)
1262 if ((prefix.
left (4) ==
"tute") && (levelNo != 0)) {
1267 i18n (gameList.
at (gameIndex)->about.constData()));
1279 void KGrGame::setPlayback (
const bool onOff)
1281 if (playback != onOff) {
1283 bool enableDisable = (! onOff);
1284 emit
setAvail (
"game_highscores", enableDisable);
1285 emit
setAvail (
"kill_hero", enableDisable);
1287 emit
setAvail (
"mouse_mode", enableDisable);
1288 emit
setAvail (
"keyboard_mode", enableDisable);
1289 emit
setAvail (
"laptop_mode", enableDisable);
1291 emit
setAvail (
"click_key", enableDisable);
1292 emit
setAvail (
"hold_key", enableDisable);
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);
1306 return ((o ==
SYSTEM) ? systemDataDir : userDataDir);
1311 int lev = (playback) ? recording->
level : level;
1315 return (i18n (
"T H E E N D"));
1324 i18nc (
"Game name - level number.",
1325 "%1 - %2", gameName, levelNumber)
1327 i18nc (
"Game name - level number - level name.",
1328 "%1 - %2 - %3", gameName, levelNumber, levelName);
1329 return (levelTitle);
1334 dbk2 <<
"Keystroke setting direction" << dirn <<
"pressed" << pressed;
1345 if (pressed && ((controlMode ==
MOUSE) ||
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")))
1361 case KMessageBox::Yes:
1365 case KMessageBox::No:
1387 void KGrGame::saveGame()
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...")));
1406 (
"%-6s %03d %03ld %7ld %s %04d-%02d-%02d %02d:%02d\n",
1407 qPrintable(prefix), level, lives, startScore,
1412 QFile file1 (userDataDir +
"savegame.dat");
1413 QFile file2 (userDataDir +
"savegame.tmp");
1415 if (! file2.open (QIODevice::WriteOnly)) {
1417 i18n (
"Cannot open file '%1' for output.",
1418 userDataDir +
"savegame.tmp"));
1424 if (file1.exists()) {
1425 if (! file1.open (QIODevice::ReadOnly)) {
1427 i18n (
"Cannot open file '%1' for read-only.",
1428 userDataDir +
"savegame.dat"));
1434 while ((! text1.atEnd()) && (--n > 0)) {
1435 saved = text1.readLine() +
'\n';
1444 userDataDir+
"savegame.dat")) {
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."));
1452 i18n (
"Error: Failed to save your game."));
1456 bool KGrGame::selectSavedGame (
int & selectedGame,
int & selectedLevel)
1461 QFile savedGames (userDataDir +
"savegame.dat");
1462 if (! savedGames.exists()) {
1464 myMessage (view, i18n (
"Load Game"),
1465 i18n (
"Sorry, there are no saved games."));
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"));
1479 bool result =
false;
1483 if (lg->exec() == QDialog::Accepted) {
1493 pr = loadedData.
mid (21, 7);
1494 pr = pr.
left (pr.
indexOf (
" ", 0, Qt::CaseInsensitive));
1496 for (
int i = 0; i < gameList.
count(); i++) {
1497 if (gameList.
at (i)->prefix == pr) {
1503 selectedGame = index;
1504 selectedLevel = loadedData.
mid (28, 3).
toInt();
1509 i18n (
"Cannot find the game with prefix '%1'.", pr));
1519 void KGrGame::loadGame (
const int game,
const int lev)
1521 newGame (lev, game);
1522 showTutorialMessages (level);
1523 lives = loadedData.
mid (32, 3).
toLong();
1525 score = loadedData.
mid (36, 7).
toLong();
1531 return (editor ? (editor->
saveOK()) :
true);
1538 void KGrGame::checkHighScore()
1541 if ((prefix.
left (4) ==
"tute") || (playback)) {
1549 #ifdef USE_KSCOREDIALOG
1550 KScoreDialog scoreDialog (
1551 KScoreDialog::Name | KScoreDialog::Level |
1552 KScoreDialog::Date | KScoreDialog::Score,
1554 scoreDialog.setConfigGroup (prefix);
1555 KScoreDialog::FieldInfo scoreInfo;
1556 scoreInfo[KScoreDialog::Level].setNum (level);
1557 scoreInfo[KScoreDialog::Score].setNum (score);
1559 scoreInfo[KScoreDialog::Date] = today.
toString (
"ddd yyyy MM dd");
1560 if (scoreDialog.addScore (scoreInfo)) {
1564 bool prevHigh =
true;
1565 qint16 prevLevel = 0;
1566 qint32 prevScore = 0;
1567 QString thisUser = i18n (
"Unknown");
1571 QFile high1 (userDataDir +
"hi_" + prefix +
".dat");
1574 if (! high1.exists()) {
1575 high1.setFileName (systemDataDir +
"hi_" + prefix +
".dat");
1576 if (! high1.exists()) {
1583 if (! high1.open (QIODevice::ReadOnly)) {
1584 QString high1_name = high1.fileName();
1586 i18n (
"Cannot open file '%1' for read-only.", high1_name));
1594 while (! s1.
atEnd()) {
1604 if (score > prevScore) {
1611 if ((! found) && (highCount >= 10)) {
1620 QFile high2 (userDataDir +
"hi_" + prefix +
".tmp");
1623 if (! high2.open (QIODevice::WriteOnly)) {
1625 i18n (
"Cannot open file '%1' for output.",
1626 userDataDir +
"hi_" + prefix +
".tmp"));
1632 Qt::WindowTitleHint);
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>"),
1648 QPushButton *
OK =
new KPushButton (KStandardGuiItem::ok(), hsn);
1650 mainLayout-> addWidget (hsnMessage);
1651 mainLayout-> addWidget (hsnUser);
1652 mainLayout-> addWidget (OK);
1654 hsn-> setWindowTitle (i18n (
"Save High Score"));
1659 OK-> setShortcut (Qt::Key_Return);
1660 hsnUser-> setFocus();
1662 connect (hsnUser, SIGNAL (returnPressed()), hsn, SLOT (accept()));
1663 connect (OK, SIGNAL (clicked()), hsn, SLOT (accept()));
1667 thisUser = hsnUser->
text();
1668 if (thisUser.
length() <= 0)
1669 thisUser =
QChar(
'-');
1676 (
"%s %04d-%02d-%02d",
1684 bool scoreRecorded =
false;
1686 while ((! s1.
atEnd()) && (highCount < 10)) {
1693 if ((! scoreRecorded) && (score > prevScore)) {
1698 s2 << (qint16) level;
1699 s2 << (qint32) score;
1700 s2 << qPrintable(hsDate);
1701 scoreRecorded =
true;
1703 if (highCount < 10) {
1713 if ((! scoreRecorded) && (highCount < 10)) {
1717 s2 << (qint16) level;
1718 s2 << (qint32) score;
1719 s2 << qPrintable(hsDate);
1727 s2 << (qint16) level;
1728 s2 << (qint32) score;
1729 s2 << qPrintable(hsDate);
1735 userDataDir +
"hi_" + prefix +
".dat")) {
1742 i18n (
"Error: Failed to save your high score."));
1750 void KGrGame::showHighScores()
1753 if (prefix.
left (4) ==
"tute") {
1755 i18n (
"Sorry, we do not keep high scores for tutorial games."));
1759 #ifdef USE_KSCOREDIALOG
1760 KScoreDialog scoreDialog (
1761 KScoreDialog::Name | KScoreDialog::Level |
1762 KScoreDialog::Date | KScoreDialog::Score,
1766 qint16 prevLevel = 0;
1767 qint32 prevScore = 0;
1771 QFile high1 (userDataDir +
"hi_" + prefix +
".dat");
1774 if (! high1.exists()) {
1775 high1.setFileName (systemDataDir +
"hi_" + prefix +
".dat");
1776 if (! high1.exists()) {
1778 i18n(
"Sorry, there are no high scores for the \"%1\" game yet.",
1779 gameList.
at (gameIndex)->name));
1784 if (! high1.open (QIODevice::ReadOnly)) {
1785 QString high1_name = high1.fileName();
1787 i18n (
"Cannot open file '%1' for read-only.", high1_name));
1792 Qt::WindowTitleHint);
1802 "<center><h2>KGoldrunner Hall of Fame</h2></center>"
1803 "<center><h3>\"%1\" Game</h3></center>",
1804 gameList.
at (gameIndex)->name),
1812 i18nc (
"1, 2, 3 etc.",
"Rank") <<
1813 i18nc (
"Person",
"Name") <<
1814 i18nc (
"Game level reached",
"Level") <<
1819 hs-> setWindowTitle (i18n (
"High Scores"));
1825 while ((! s1.
atEnd()) && (n < 10)) {
1847 if (prevScore > 0) {
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);
1880 mainLayout-> addLayout (hboxLayout1, 5);
1888 connect (OK, SIGNAL (clicked()), hs, SLOT (accept()));
1906 if (levelPlayer && gameFrozen) {
1920 if (! loadGameData (
SYSTEM))
1922 loadGameData (
USER);
1924 for (
int i = 0; i < gameList.
count(); i++) {
1925 dbk1 << i << gameList.
at(i)->prefix << gameList.
at(i)->name;
1930 bool KGrGame::loadGameData (
Owner o)
1935 IOStatus status = io.fetchGameListData
1936 (o, getDirectory (o), gList, filePath);
1938 bool result =
false;
1944 i18n (
"Cannot find game info file '%1'.", filePath));
1950 i18n (
"Cannot open file '%1' for read-only.", filePath));
1954 i18n (
"Reached end of file '%1' before finding end of game-data.",
1967 bool KGrGame::initRecordingData (
const Owner fileOwner,
const QString & prefix,
1977 const QString dir = ((fileOwner ==
SYSTEM) || (levelNo == 0)) ?
1978 systemDataDir : userDataDir;
1980 kDebug() <<
"loadRecording" << dir << prefix << levelNo;
1981 if (! loadRecording (dir, prefix, levelNo)) {
1990 if (! io.readLevelData (dir, prefix, levelNo, levelData)) {
1997 kDebug() <<
"Recording at" << recording->
dateTime;
2005 recording->
level = levelNo;
2016 recording->
lives = lives;
2017 recording->
score = score;
2018 recording->
speed = timeScale;
2021 recording->
content [0] = 0xff;
2026 void KGrGame::saveRecording()
2028 QString filename = userDataDir +
"rec_" + prefix +
".txt";
2030 kDebug() << filename << groupName;
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);
2054 for (
int i = 0; i < n; i++) {
2060 configGroup.writeEntry (
"Content", bytes);
2065 for (
int i = 0; i < n; i++) {
2066 ch = (uchar)(recording->
draws.
at(i));
2071 configGroup.writeEntry (
"Draws", bytes);
2076 KConfigGroup gameGroup (KGlobal::config(),
"KDEGame");
2077 gameGroup.writeEntry (
"LastGamePrefix", prefix);
2078 gameGroup.writeEntry (
"LastLevel", level);
2082 bool KGrGame::loadRecording (
const QString & dir,
const QString & prefix,
2085 kDebug() << prefix << levelNo;
2086 QString filename = dir +
"rec_" + prefix +
".txt";
2088 kDebug() << filename << groupName;
2090 KConfig config (filename, KConfig::SimpleConfig);
2091 if (! config.hasGroup (groupName)) {
2092 kDebug() <<
"Group" << groupName <<
"NOT FOUND";
2096 KConfigGroup configGroup = config.group (groupName);
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);
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);
2114 recording->
keyOption = configGroup.readEntry (
"KeyOption",
2119 if ((demoType ==
DEMO) || (demoType ==
SOLVE)) {
2121 for (
int i = 0; i < gameList.
count(); i++) {
2122 if (gameList.
at (i)->prefix == recording->
prefix) {
2129 recording->
gameName = gameList.
at (index)->name;
2135 if (io.readLevelData (dir, recording->
prefix, recording->
level,
2147 int n = bytes.
count();
2149 for (
int i = 0; i < n; i++) {
2154 bytes = configGroup.readEntry (
"Draws",
QList<int>());
2157 for (
int i = 0; i < n; i++) {
2158 recording->
draws [i] = bytes.
at (i);
2162 lives = recording->
lives;
2164 score = recording->
score;
2169 void KGrGame::loadSounds()
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};
2177 "themes/default/gold.ogg"));
2179 "themes/default/step.wav"));
2181 "themes/default/climb.wav"));
2183 "themes/default/falling.ogg"));
2185 "themes/default/dig.ogg"));
2187 "themes/default/ladder.ogg"));
2189 "themes/default/completed.ogg"));
2191 "themes/default/death.ogg"));
2193 "themes/default/gameover.ogg"));
2195 "themes/default/victory.ogg"));
2204 effects->
setVolume (fx [i], volumes [i]);
2224 #include "kgrgame.moc"
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.
void setToggle(const char *actionName, const bool onOff)
char rules
Rules that applied at time of recording.
QString toString(Qt::DateFormat format) const
QByteArray hint
Level hint (optional).
void editNameAndHint()
Run a dialog in which the name and hint of a level can be edited.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
int height
Height of grid, in cells.
The KGrGameIO class handles I/O for text-files containing KGoldrunner games and levels.
void showReplayMessage(bool onOff)
void setInitialTheme(const QString &themeFilepath)
void setReplayMessage(const QString &msg)
QString prefix
Game's filename prefix.
int level
Level number (at time of recording).
QString dateTime
Date+time of recording (UTC in ISO format).
int controlMode
Control mode during recording (mouse, etc).
QString toString(Qt::DateFormat format) const
Owner owner
Owner of the game: "System" or "User".
KGrGameData structure: contains attributes of a KGoldrunner game.
static int warning(QWidget *parent, const QString &caption, const QString &text, const QString &label0, const QString &label1, const QString &label2="")
Class to play, record and play back a level of a game.
QString hint
Hint (translated at recording time).
bool deleteLevelFile(int pGameIndex, int pLevel)
Delete a level from a game.
void setHoldKeyOption(const int option)
Change the keyboard click/hold option during play.
QByteArray & fill(char ch, int size)
void setEditObj(char newEditObj)
Set the next object for the editor to paint, e.g.
void setPixmap(const QPixmap &)
const T & at(int i) const
void setDevice(QIODevice *d)
long score
Score at start of level.
void stop(int token)
Stop playing the sound associated with the given token.
void setAlignment(QFlags< Qt::AlignmentFlag >)
bool editGame(int pGameIndex)
Create a new game (a collection point for levels) or load the details of an existing game...
const QString getCurrentText()
QByteArray layout
Codes for the level layout (mandatory).
void setFrameStyle(int style)
void setTitle(const QString &newTitle)
Set the text for the title of the current level.
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void pause(bool stop)
Pause or resume the gameplay in this level.
char rules
Game's rules: KGoldrunner or Traditional.
void playSound(const int n, const bool onOff=true)
void interruptPlayback()
Stop playback of a recorded level and adjust the content of the recording so that the user can contin...
void getGameAndLevel(int &game, int &lev)
QString number(int n, int base)
int count(const T &value) const
void append(const T &value)
QString fromUtf8(const char *str, int size)
QString levelName
Name of the level (translated at rec time).
bool moveLevelFile(int pGameIndex, int pLevel)
Move a level to another game or level number.
QString rightJustified(int width, QChar fill, bool truncate) const
int speed
Speed of game during recording (normal=10).
Owner owner
Original owner, at time of recording.
void dbgControl(int code)
Implement author's debugging aids, which are activated only if the level is paused and the KConfig fi...
int toInt(bool *ok, int base) const
virtual void addItem(QLayoutItem *item)
void setObjectName(const QString &name)
KGrRecording structure: contains a record of play in a KGoldrunner level.
const char * constData() const
void dbgControl(const int code)
static void information(QWidget *parent, const QString &caption, const QString &text, const QString &dontShowAgain=QString())
KGrLevelData structure: contains attributes of a KGoldrunner level.
int nLevels
Number of levels in the game.
void setDirectionByKey(const Direction dirn, const bool pressed)
Set a direction for the hero to move or dig when using keyboard control.
long lives
Number of lives at start of level.
void setTimeScale(const int timeScale)
Set the overall speed of gameplay.
void kbControl(const int dirn, const bool pressed=true)
QString shortDayName(int weekday)
void setMargin(int margin)
void setAvail(const char *actionName, const bool onOff)
QString prefix
Game's filename prefix.
int play(int effect)
Play a sound effect.
void setParent(QObject *parent)
This class is the game-editor for KGoldrunner.
long toLong(bool *ok, int base) const
void gameActions(const int action)
IOStatus
Return values from I/O operations.
void killHero()
If not in playback mode, add a code to the recording and kill the hero.
QByteArray draws
The random numbers used during play.
QDateTime currentDateTime()
QString mid(int position, int n) const
bool createLevel(int pGameIndex)
Set up a blank level-layout, ready for editing.
bool saveLevelFile()
Save an edited level in a text file (*.grl) in the user's area.
QString & setNum(short n, int base)
void stopAllSounds()
Stop all sounds currently playing.
QString & sprintf(const char *cformat,...)
int width
Width of grid, in cells (at rec time).
void setControlMode(const int mode)
Change the input-mode during play.
int keyOption
Click/hold option for keyboard mode.
int width
Width of grid, in cells.
bool selectLevel(int &selectedGame, int &selectedLevel)
QString gameName
Name of the game (translated at rec time).
bool updateLevel(int pGameIndex, int pLevel)
Load and display an existing level, ready for editing.
QString left(int n) const
void editToolbarActions(const int action)
void setTimedSound(int i)
Set up a sound to have its latest start-time recorded.
int indexOf(const QRegExp &rx, int from) const
void setTextAlignment(int column, int alignment)
void setLevel(unsigned int level)
Set the current level number.
bool saveOK()
Check if there are any unsaved edits and, if so, ask the user what to do.
KGrGame(KGrView *theView, const QString &theSystemDir, const QString &theUserDir)
void setRootIsDecorated(bool show)
void editActions(const int action)
QString name
Name of game (translated, if System game).
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
int height
Height of grid, in cells (at rec time).
int loadSound(const QString &fileName)
Load a sound sample.
QByteArray content
The encoded recording of play.
QByteArray layout
Codes for the level layout (at rec time).
void settings(const int action)
void setVolume(int effect, qreal volume)
Change the volume of one type of sound (e.g.
static bool safeRename(QWidget *theView, const QString &oldName, const QString &newName)
void incScore(const int n)
void setSpacing(int spacing)
void init(KGrView *view, KGrRecording *pRecording, const bool pPlayback, const bool gameFrozen)
The main initialisation of KGrLevelPlayer.
QByteArray name
Level name (optional).
QByteArray toUtf8() const