summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Wadham <[email protected]>2015-09-19 16:16:54 +1000
committerIan Wadham <[email protected]>2015-09-19 16:16:54 +1000
commite42d0ed8d6e69aa2e69e9fb6adf049e43fe107da (patch)
tree9322499182dfbd18a367c4618a59defc354688d7
parent97925311fba4f1cb7bb9115d07ec4fa89f2795b5 (diff)
Add a feature to save a solution on a user-file and replay it.
-rw-r--r--src/kgoldrunner.cpp10
-rw-r--r--src/kgoldrunnerui.rc3
-rw-r--r--src/kgrgame.cpp96
-rw-r--r--src/kgrgame.h7
-rw-r--r--src/kgrglobals.h5
-rw-r--r--src/kgrselector.cpp4
6 files changed, 107 insertions, 18 deletions
diff --git a/src/kgoldrunner.cpp b/src/kgoldrunner.cpp
index 0994fe0..3c200bd 100644
--- a/src/kgoldrunner.cpp
+++ b/src/kgoldrunner.cpp
@@ -220,7 +220,7 @@ void KGoldrunner::setupActions()
a->setText (i18n ("&Load Saved Game..."));
// Save Game...
- // Save Edits... (extra copy)
+ // Save Solution...
// --------------------------
saveGame = KStandardGameAction::save (gameMapper, SLOT(map()), this);
@@ -229,6 +229,14 @@ void KGoldrunner::setupActions()
saveGame->setText (i18n ("&Save Game..."));
saveGame->setShortcut (Qt::Key_S); // Alternate key.
+ a = gameAction ("save_solution", SAVE_SOLUTION,
+ i18n ("Save A Solution..."),
+ i18n ("Save A Solution..."),
+ i18n ("Save a solution for a level into a file "
+ "called 'sol_<prefix>.txt' in your user's "
+ "data directory..."),
+ Qt::ShiftModifier + Qt::Key_S);
+
// Pause
// Show High Scores
// Get a Hint
diff --git a/src/kgoldrunnerui.rc b/src/kgoldrunnerui.rc
index 9325365..49621a9 100644
--- a/src/kgoldrunnerui.rc
+++ b/src/kgoldrunnerui.rc
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gui name="kgoldrunner"
- version="16"
+ version="17"
xmlns="http://www.kde.org/standards/kxmlgui/1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.kde.org/standards/kxmlgui/1.0
@@ -9,6 +9,7 @@
<Menu name="game" >
<Action append="new_merge" name="next_level" />
<Action append="save_merge" name="save_edits" />
+ <Action append="save_merge" name="save_solution" />
<Action append="misc_merge" name="kill_hero" />
</Menu>
<Menu name="move" >
diff --git a/src/kgrgame.cpp b/src/kgrgame.cpp
index 3113ef7..e6ce805 100644
--- a/src/kgrgame.cpp
+++ b/src/kgrgame.cpp
@@ -151,6 +151,9 @@ bool KGrGame::modeSwitch (const int action,
case SOLVE:
slAction = SL_SOLVE;
break;
+ case SAVE_SOLUTION:
+ slAction = SL_SAVE_SOLUTION;
+ break;
case REPLAY_ANY:
slAction = SL_REPLAY;
break;
@@ -181,6 +184,7 @@ void KGrGame::gameActions (const int action)
{
int selectedGame = gameIndex;
int selectedLevel = level;
+ // For some actions, modeSwitch() calls the game and level selection dialog.
if (! modeSwitch (action, selectedGame, selectedLevel)) {
return;
}
@@ -234,6 +238,9 @@ void KGrGame::gameActions (const int action)
case SOLVE:
runReplay (SOLVE, selectedGame, selectedLevel);
break;
+ case SAVE_SOLUTION:
+ saveSolution (gameList.at (selectedGame)->prefix, selectedLevel);
+ break;
case INSTANT_REPLAY:
if (levelPlayer) {
startInstantReplay();
@@ -505,12 +512,48 @@ void KGrGame::initGame()
} // End KGrGame::initGame()
+bool KGrGame::getRecordingName (const QString & dir, const QString & pPrefix,
+ QString & filename)
+{
+ QString recFile = dir + "rec_" + pPrefix + ".txt";
+ QFileInfo fileInfo (recFile);
+ bool recOK = fileInfo.exists() && fileInfo.isReadable();
+ filename = QString ("");
+
+ if (demoType == SOLVE) {
+ // Look for a solution-file name in User or System area.
+ QString solFile = dir + "sol_" + pPrefix + ".txt";
+ fileInfo.setFile (solFile);
+ bool solOK = fileInfo.exists() && fileInfo.isReadable();
+ if (solOK) {
+ filename = solFile; // Accept sol_* in User or System area.
+ return true;
+ }
+ else if (recOK && (dir == systemDataDir)) {
+ filename = recFile; // Accept rec_* (old name) in System area only.
+ return true;
+ }
+ }
+ else if (recOK) {
+ filename = recFile; // Accept rec_* name for demo or recording.
+ return true;
+ }
+ // File not found or not readable.
+ return false;
+}
+
bool KGrGame::startDemo (const Owner demoOwner, const QString & pPrefix,
const int levelNo)
{
// Find the relevant file and the list of levels it contains.
QString dir = (demoOwner == SYSTEM) ? systemDataDir : userDataDir;
- QString filepath = dir + "rec_" + pPrefix + ".txt";
+ QString filepath;
+ if (! getRecordingName (dir, pPrefix, filepath)) {
+ kDebug() << "No file found by getRecordingName() for" << dir << pPrefix;
+ return false;
+ }
+ dbk1 << "Owner" << demoOwner << "type" << demoType
+ << pPrefix << levelNo << "filepath" << filepath;
KConfig config (filepath, KConfig::SimpleConfig);
QStringList demoList = config.groupList();
dbk1 << "DEMO LIST" << demoList.count() << demoList;
@@ -780,7 +823,10 @@ void KGrGame::runReplay (const int action,
if (action == SOLVE) {
setPlayback (true);
demoType = SOLVE;
- if (! startDemo
+ if (startDemo // Has the user saved a solution to this level?
+ (USER, gameList.at (selectedGame)->prefix, selectedLevel)) {
+ }
+ else if (! startDemo // If not, look for a released solution.
(SYSTEM, gameList.at (selectedGame)->prefix, selectedLevel)) {
KGrMessage::information (view, i18n ("Show A Solution"),
i18n ("Sorry, although all levels of KGoldrunner can be "
@@ -845,7 +891,7 @@ bool KGrGame::playLevel (const Owner fileOwner, const QString & prefix,
scene->deleteAllSprites();
// Set up to record or play back: load either level-data or recording-data.
- if (! initRecordingData (fileOwner, prefix, levelNo)) {
+ if (! initRecordingData (fileOwner, prefix, levelNo, playback)) {
return false;
}
@@ -955,8 +1001,8 @@ void KGrGame::endLevel (const int result)
// If the player finished the level (won or lost), save the recording.
if ((! playback) && ((result == WON_LEVEL) || (result == DEAD))) {
- // dbk << "saveRecording()";
- saveRecording();
+ // dbk << "saveRecording (QString ("rec_"))";
+ saveRecording (QString ("rec_"));
}
if (result == WON_LEVEL) {
@@ -1964,8 +2010,27 @@ bool KGrGame::loadGameData (Owner o)
return (result);
}
+void KGrGame::saveSolution (const QString & prefix, const int levelNo)
+{
+ demoType = REPLAY_ANY; // Must load a "rec_" file, not "sol_".
+
+ // Proceed as if we are going to replay the selected level.
+ if (initRecordingData (USER, prefix, levelNo, true)) {
+ // But instead just save the recording data on a solution file.
+ saveRecording (QString ("sol_"));
+ KGrMessage::information (view, i18n ("Save A Solution"),
+ i18n ("Your solution to level %1 has been saved on file %2",
+ levelNo, userDataDir + "sol_" + prefix + ".txt"));
+ }
+ else {
+ KGrMessage::information (view, i18n ("Save A Solution"),
+ i18n ("Sorry, you do not seem to have played and recorded "
+ "the selected level before."), "Show_noRecording");
+ }
+}
+
bool KGrGame::initRecordingData (const Owner fileOwner, const QString & prefix,
- const int levelNo)
+ const int levelNo, const bool pPlayback)
{
// Initialise the recording.
delete recording;
@@ -1976,7 +2041,7 @@ bool KGrGame::initRecordingData (const Owner fileOwner, const QString & prefix,
// If system game or ENDE, choose system dir, else choose user dir.
const QString dir = ((fileOwner == SYSTEM) || (levelNo == 0)) ?
systemDataDir : userDataDir;
- if (playback) {
+ if (pPlayback) {
kDebug() << "loadRecording" << dir << prefix << levelNo;
if (! loadRecording (dir, prefix, levelNo)) {
return false;
@@ -2023,10 +2088,11 @@ bool KGrGame::initRecordingData (const Owner fileOwner, const QString & prefix,
return true;
}
-void KGrGame::saveRecording()
+void KGrGame::saveRecording (const QString & filetype)
{
- QString filename = userDataDir + "rec_" + prefix + ".txt";
- QString groupName = prefix + QString::number(level).rightJustified(3,'0');
+ QString filename = userDataDir + filetype + prefix + ".txt";
+ QString groupName = prefix +
+ QString::number(recording->level).rightJustified(3,'0');
// kDebug() << filename << groupName;
KConfig config (filename, KConfig::SimpleConfig);
@@ -2083,7 +2149,11 @@ bool KGrGame::loadRecording (const QString & dir, const QString & prefix,
const int levelNo)
{
// kDebug() << prefix << levelNo;
- QString filename = dir + "rec_" + prefix + ".txt";
+ QString filename;
+ if (! getRecordingName (dir, prefix, filename)) {
+ kDebug() << "No file found by getRecordingName() for" << dir << prefix;
+ return false;
+ }
QString groupName = prefix + QString::number(levelNo).rightJustified(3,'0');
// kDebug() << filename << groupName;
@@ -2132,7 +2202,9 @@ bool KGrGame::loadRecording (const QString & dir, const QString & prefix,
KGrGameIO io (view);
KGrLevelData levelData;
- if (io.readLevelData (dir, recording->prefix, recording->level,
+ QString levelDir = (gameList.at (index)->owner == USER) ?
+ userDataDir : systemDataDir;
+ if (io.readLevelData (levelDir, recording->prefix, recording->level,
levelData)) {
// If there is a level name or hint, translate it.
recording->levelName = (levelData.name.size() > 0) ?
diff --git a/src/kgrgame.h b/src/kgrgame.h
index e11c1fa..c272a01 100644
--- a/src/kgrgame.h
+++ b/src/kgrgame.h
@@ -95,6 +95,8 @@ private:
void newGame (const int lev, const int gameIndex);
void runReplay (const int action,
const int selectedGame, const int selectedLevel);
+ bool getRecordingName (const QString & dir, const QString & pPrefix,
+ QString & filename);
bool startDemo (const Owner demoOwner, const QString & pPrefix,
const int levelNo);
void runNextDemoLevel();
@@ -244,9 +246,10 @@ private:
/******************************************************************************/
bool loadGameData (Owner);
+ void saveSolution (const QString & prefix, const int levelNo);
bool initRecordingData (const Owner fileOwner, const QString & prefix,
- const int levelNo);
- void saveRecording();
+ const int levelNo, const bool pPlayback);
+ void saveRecording (const QString & filetype); // Type "rec_" or "sol_".
bool loadRecording (const QString & dir, const QString & prefix,
const int levelNo);
void loadSounds();
diff --git a/src/kgrglobals.h b/src/kgrglobals.h
index 9c0157c..92a12e3 100644
--- a/src/kgrglobals.h
+++ b/src/kgrglobals.h
@@ -59,7 +59,7 @@ enum KBAction {KB_UP, KB_DOWN, KB_LEFT, KB_RIGHT,
// Action codes when selecting a level or game for play, editing or replay.
enum SelectAction {SL_START, SL_ANY, SL_CREATE, SL_UPDATE, SL_SAVE,
SL_MOVE, SL_DELETE, SL_CR_GAME, SL_UPD_GAME,
- SL_REPLAY, SL_SOLVE, SL_NONE};
+ SL_REPLAY, SL_SOLVE, SL_SAVE_SOLUTION, SL_NONE};
/// Codes for the rules of the selected game and level.
const char TraditionalRules = 'T';
@@ -151,7 +151,8 @@ public:
enum GameAction {NEW, NEXT_LEVEL, LOAD, SAVE_GAME, PAUSE, HIGH_SCORE,
KILL_HERO, HINT,
- DEMO, SOLVE, INSTANT_REPLAY, REPLAY_LAST, REPLAY_ANY};
+ DEMO, SOLVE, SAVE_SOLUTION,
+ INSTANT_REPLAY, REPLAY_LAST, REPLAY_ANY};
enum EditAction {CREATE_LEVEL, EDIT_ANY, SAVE_EDITS, MOVE_LEVEL,
DELETE_LEVEL, CREATE_GAME, EDIT_GAME};
diff --git a/src/kgrselector.cpp b/src/kgrselector.cpp
index ec3d702..5873ac6 100644
--- a/src/kgrselector.cpp
+++ b/src/kgrselector.cpp
@@ -262,6 +262,9 @@ void KGrSLDialog::setupWidgets()
case SL_SOLVE: // Can ask to see a solution of any level in any game.
OKText = i18n ("Show Solution");
break;
+ case SL_SAVE_SOLUTION: // Can ask to save a recording on a solution-file.
+ OKText = i18n ("Save A Solution");
+ break;
case SL_UPDATE: // Can use any level in any game as edit input.
OKText = i18n ("Edit Level");
break;
@@ -432,6 +435,7 @@ void KGrSLDialog::slGame()
case SL_ANY:
case SL_REPLAY:
case SL_SOLVE:
+ case SL_SAVE_SOLUTION:
case SL_UPDATE:
case SL_DELETE:
case SL_UPD_GAME: