phyver / GameShell

a game to learn (or teach) how to use standard commands in a Unix shell
GNU General Public License v3.0
2.18k stars 140 forks source link

Savegame and overwritting it (unintentionally) #92

Closed Aierbote closed 2 years ago

Aierbote commented 2 years ago

After completing 7 missions, I exit-ed and I tried to re run a second time the game (but I forgot I had to bash gameshell-save.sh 😅 )

So I would suggest a message to inform whoever repeats this kind of mistake before overwritting the previous checkpoint.

Lucky for me I realized right away and this was my workaround:

  1. DON'T PANIC 👍
    • Keep the game running (don't execute exit just yet)
  2. open a new Terminal window
    • cd into the folder GameShell is saved
  3. Backup the not-yet_overwritten save file with cp
    • cp gameshell-save.sh gameshell-save.sh.bckp
  4. Return to the Terminal window running Gameshell and exit
    • This will overwrite the first savegame, but there is a copy
  5. Remove the overwritten one
    • rm gameshell-save.sh
  6. Copy back the backup file into the original save format
    • cp gameshell-save.sh.bckp gameshell-save.sh

There could be a way to backup the data automatically (as save game slots) or even to warn the players of their previous gameshell-save.sh before they start again.

But depending on the player skill level or if they dare, they could decide to try this workaround

rlepigre commented 2 years ago

I agree this is a bit unfortunate. At the very least, we should make it so that the generated gameshell-save.sh file has a an attached date/time. Alternatively, we could place the generated scripts under a folder saved_games, and when running bash gameshell.sh again, ask the player if they want to resume any existing game (identified by time stamps, sorted from most recent) if the saved_games folder exists.

phyver commented 2 years ago

Lucky for me I realized right away and this was my workaround:

Good work!

I'm not entirely happy with the current way I handle save files.

I don't really want to usegameshell-save_001,sh, gameshell-save_002.sh, ... (or some timestamp) because you have to trust the user to run the last version. (And I don't like the idea of having a dozen save files cluttering my directory.)

I thus see 2 possible solutions:

  1. We could keep the saved game by rewriting gameshell.sh, as I initially wanted to do. That's the simplest and you can still run gameshell.sh -R to restart the game from scratch. One problem is that you cannot restart GameShell from scratch if you mess up with the internal folders. (There are safeguards, but it is still possible.)
  2. As Rodolphe suggested, we could put saves files in a directory and have gameshell.sh start the most recent one, with an option to choose another one by giving an appropriate flag. (We don't even need to keep all the save files: the last 10 is probably more than enough!)

That leaves us with the first or third solution. Simplicity vs features.

One thing I don't like about the second solution is that without adding some messy code the saved insances of GameShell will run from inside the save directory : . DIR/gameshell.sh will initially run in DIR/GameShell, . DIR/gameshell.sh will run in DIR/GameShell-savefiles/GameShell when there are savefiles.

What do you think?

rlepigre commented 2 years ago

Could we not save the saved game files in the self-extracting archive itself? (Maybe with two levels of self-extracting archives.) I mean, running gameshell.sh could first extract itself to obtain a bunch of saved sessions plus a version of the current gameshell.sh, and then we could run a script that prints a menu in case there are saved files, and let you choose which to run. This way we do not need any external files, and all games are played under a uniform file path.

phyver commented 2 years ago

I don't like the idea of having the self extracting archive grow in size. Currently, everything is included in all archives, making them self-contained. I could share GameShell's code between savefiles, but that would require changes I'm not sure are worth doing.

Here is one proposition:

That should only require changes in the file lib/header.sh.

rlepigre commented 2 years ago

OK, sounds good to me.

phyver commented 2 years ago

Ah! One thing I hadn't thought about is that translating the messages about existing savefiles will require unzipping the first archive, which I find rather inelegant. (This is what I do for dealing with bash gameshell.sh -h, but I don't like it.)

In this case, that would mean first unzipping the archive and if the player wants to change savefile, removing the directory (no need to zip it again), and unzip the other one. That's a little ugly...

Any thoughts on that?

BTW, I just realized that running

$ bash gameshell.sh -h

does create gameshell-save.sh file even though nothing was actually done! I should fix that.

rlepigre commented 2 years ago

That's annoying, but not really a big problem. We should probably care more about usability than elegance, at least if we cannot have both. I don't have any other idea at the moment, so I guess you can go with whatever option you like best!

phyver commented 2 years ago

@rlepigre I pushed several commits in the devel branch including some things to make savefiles more robust:

  1. by default, a savefile is created after each successful gsh check (always using the same file)
  2. by default, each time you run GameShell, the savefile uses a different filename (gameshell.sh, saved to gameshell-save.sh, saved to gameshell-save001.sh, etc.)
  3. on startup, GameShell checks if a savefile with greater index exists. If so, the user can choose between running the file she specified, running the latest savefile, aborting or restarting GameShell from the first mission.

Some changes I might make are:

  1. saving after unsuccessful gsh check as well and adding a flag to disable automatic saving,
  2. adding a flag for changing the choice of savefiles
  3. removing the option to reset GameShell

At the moment, the "menu" from point 3. cannot be translated. The reason is that it occurs before the archive is extracted. That could be changed but would require more work.

None of this has been very thoroughly tested, so if you have time, feel free to play with all that! Also, if you have ideas for different choices, I'm happy to hear them. For example, I'm not sure using the greatest index as a proof of later savefile is the best choice. I could use modification time, but this isn't completely robust. The best thing, but it requires more work, would be to recover the current mission from the archive, and / or the last completed mission.

Note that it is also possible to explicitly save from within GameShell with gsh save FILE (using a FILE outside GameShell).

phyver commented 2 years ago

commit 880cc7dd should solve this kind of problems.