I7 Glulx: Roguelike-style save & restore

Hi all,

I’ve put together a little extension that implements automated save and restore a la roguelike games. The main features are:

  1. Game saves automatically and silently every turn, just before reading in a command. There is no need for the player to issue any command to save.
  2. If the game finds an existing save file at startup, it automatically loads it.
  3. The standard SAVE and RESTORE commands are blocked to avoid confusion.
  4. The standard save and restore code is not, however, altered; if you want to use both roguelike mode and standard mode in your game, you can–just not at the same time. Use “Roguelike mode is false” to start the game with roguelike mode off, and “now roguelike mode is true/false” to change it over the course of the game.

There is no documentation. All that’s required to use the extension is to include it. If you want to alter behavior or default messages, though, you’ll need to read the code. You’ll also need to read the code if you want to understand how it works! :wink:

The extension works only with Glulx. It doesn’t seem to work with Quixe, and I’m not sure what it would take to get it working. (In fact, I’m not even sure how to properly test whether it’s working.)

I am not going to release this extension to the extensions library, as I already have a lot of extensions out there and I don’t want to have to support it–I see it more as a quick Sunday afternoon itch that I needed to scratch. If anyone wants to write some documentation, fix problems, modify as desired, etc. for submission to the library, you have my blessing. Feel free to give yourself authorship; if you want to credit my contribution, you can use the standard method for providing additional credit (see 25.4 in the manual).

The extension is attached to this post. You’ll need to change the extension from .txt to .i7x after downloading.

–Erik
Roguelike Save and Restore.txt (5.9 KB)

External-file stuff should work in Quixe, if you have a reasonably modern browser. However, I haven’t tried this code yet.

I can see how implementing this extension could be annoying to the player. If I saved before entering a room, then did three or four wrong things, then wanted to restore the saved game before I did those things, I would be annoyed if the wrong actions had overwritten my saved game.

On the other hand I know some game authors don’t really care for that behavior for players, and would like the behavior you’ve produced in an extension.

I’m guessing you’ve never played a roguelike such as nethack? Because that is exactly the point of this extension! :slight_smile: You can never save your position in order to experiment in such games – the only type of saving is that which occurs on exit.

And of course, this extension says it disables user-invoked saving, to avoid the sorts of problems you mention above.

Hm, interesting; quite a different approach than the one I use in my Permadeath extension. I think Permadeath is somewhat closer to how roguelikes generally work: e.g., if I understand it correctly your game only allows the player to have one active game at a time, whereas the roguelikes I played allow you to have as many as you wish.

However, your extension actually seems more useful for the project I’m currently working on, so I’m certainly going to take a closer look. :slight_smile:

It seems like the way that SLASH’EM worked on crash-override.net – you log in with a profile that has one game active at any given time, and it does constantly back up your game so you can restore if your connection drops or something.

Erik, if you use the extension as written, I think you should devise a way to communicate to the player that they must restart in order to “commit suicide”. In general, roguelikes implement save (“save the game and exit”) and quit (“kill the character and exit”); your extension effectively has quit (“save the game and exit”) and restart (“kill the character and start a new game”). Players who don’t realise this may get stuck in a game they don’t want to play any more. :slight_smile:

But I’m definitely going to steal… uh… adapt some of your code for Kerkerkruip. Part of the challenge there is to win several games in a row, which get more difficult as your winning streak becomes longer; and that means that having exactly one save game policed by the game itself is precisely what I want.

Unless I am completely mistaken, the extension contains a huge bug. There is no mechanism that removes the previous saved game, so you can never start a new game. You will always go back to the last turn of the previous game.

This is bad both because it means players cannot be killed (you can always “undo” by "restore"ing), and because it means that you can never start a new game (both “restart” and “quit + start” function effectively as “do nothing” if the game has not ended, and as “undo” if the game has ended).

This could best be solved by deleting the saved game on “restart” and on printing the player’s obituary. But I don’t know how to deleted a file, and based on the low-level I6 code of the extension, I’m not so sure I’d like to try and find out. Anyone who knows how to do this?

Really? My experience is pretty much limited to the classics, but all of the roguelikes I’ve spent any amount of time with have used the one-game-at-a-time model. Maybe it’s just the philosophy taken up in the Mac and/or iOS ports, but I’ve never seen any interface for keeping multiple games going at once. (My points of reference are Rogue, Nethack, Slash’Em, POWDER, and 100 Rogues.) Or maybe they do allow for multiple saved games and I’m just missing something in the interface…

Thanks for pointing out the missing restart feature. I knew I had to be missing something! (I wouldn’t call it a bug, though–just an unimplemented feature. :wink: ) The I6 for deleting a file is actually pretty simple, once you’ve had a look at the general parameters for handling files in FileIO.i6t. Here’s the code to add saved game file deletion (won’t work for any other type of file!). You would also need to add the instruction to delete at the appropriate point in the restart code, as well as after quitting. The former, at least, will require a bit of I6.

[code]To delete (filename - external file):
(- FileIO_DeleteSavedGame({filename}); -).

Include (-
[ FileIO_DeleteSavedGame extf struc fref res;
if ((extf < 1) || (extf > NO_EXTERNAL_FILES))
return FileIO_Error(extf, “tried to access a non-file”);
struc = TableOfExternalFiles–>extf;
fref = glk_fileref_create_by_name(fileusage_SavedGame + fileusage_BinaryMode, Glulx_ChangeAnyToCString(struc–>AUXF_FILENAME), 0);
if (fref == 0) rfalse;
if (glk_fileref_does_file_exist(fref)) {
res = glk_fileref_delete_file(fref);
if (res ~= 0)
CarryOutActivity( (+ failing to delete a saved game +) );
}
glk_fileref_destroy(fref);
];
-).[/code]

–Erik

I’m just testing with a local file. I make a couple of moves, then close the browser window, then reopen the game in Quixe (using link from the IDE release page). But Quixe doesn’t load the saved state. There aren’t any error messages–it appears that the interpreter just doesn’t detect the existing savegame file on startup.

–Erik

I don’t actually plan to use this particular roguelike save code at all. The idea really was to get the direct interface to the saved game files going: existence check, write, read, and now delete. Eventually, I’d like to have a full replacement for the command line save/restore interface, which I’ve always thought of as pretty annoying–not to mention way out of line with prevailing practice in other game genres. The saved game file command interface that this minimal roguelike implementation builds on (i.e., those four I6 routines) essentially lets you provide any game-controlled save interface that you like, e.g. the 3-slot system used in so many casual Flash games. The roguelike layer is just a simple frame to test them with, and is really only two rules on its own.

–Erik

What browser? It sort of matters. :slight_smile:

Also, testing Quixe on your local hard drive (file: URL) may differ in behavior from Quixe installed on a server (http: URL). The local storage system for Javascript isolates server domains from each other, rather like cookies.

Hm, I seem to recall that I could do this in Nethack… but I may be wrong. I know you can have multiple games going at once in Dungeon Crawl Stone Soup.

You call the ability to ever play more than one game a missing feature? :stuck_out_tongue:

Anyway, thanks for the code! You definitely posted all this at exactly the right time for me. (Also, I would be willing to wrap this up in an official extension and maintain it. Just let me know.)

In Dungeon Crawl Stone Soup, you can have multiple saves in order to have different characters, but each character only has the one save. I think most of the others are just one save file per user (though depending on the port, it may be possible to fake being a different user in order to get DCSS-like behavior – I think you could do this in the Windows port of Nethack by just entering a different name).

Anyway, this extension sounds interesting. I haven’t had a chance to look at it yet, but would it be possible to adapt it to save automatically at specific points? That is, what I’d like to do is define checkpoints throughout the game where it will quietly save for you. I don’t want to save every turn, just every time important progress is made so the player doesn’t have to worry about losing that progress if he screws up (thus allowing the author to be crueler to the player).

Actually, I don’t think it matters in this case–Firefox 5 and the latest Chrome on Mac OS X (at least I hope it doesn’t matter!) :wink:

I wondered if running Quixe from a file on my hard drive might make a difference. I will try to remember to test from an http URL tonight.

–Erik

Well, you can play more than one game. You just can’t delete the saved file from within the game. You have to delete it from the game’s folder instead. But I agree it’s one heck of a missing feature…

Please, run with it! I’m happy too that it will help with Kerkerkruip. (Tangential question–in English, “dungeon” comes from the political side, once having meant “castle” or “the lord’s tower/keep”. Is the Dutch word for dungeon really related to churches [kerk]?)

Sure! Just jettison the rule that saves every turn and insert the save-game instruction wherever you need it in your code.

–Erik

No, “kerker” comes from the Latin “carcer”, which means “prison”. This is also the root of the English “to incarcerate”. On the other hand, “kerk” (like “church” and “Kirch”, I assume) comes from the Greek “kuriakon” which means “(house) of the Lord”.

The Dutch also has “donjon”, which still means “keep” – this is not a commonly used word, as you can imagine.

Interesting. I’m not surprised to learn of the similar terms, given that English and Dutch both derive primarily from Old Low German. However, I would have guessed that “donjon” (later, dungeon) would have come to English from French (possibly reflecting the fact that, following the conquest, the Norman occupiers tended to be the lords) and would therefore not have expected to find a cognate term in Dutch. (Must be from all that contact with the Francophones in Belgium. :slight_smile:

Robert Rothman

On my Mac port of nethack, you can have multiple simultaneous games going by using different names for your characters. (Looks like the saved games I have lying around are Montana the archeologist, Percy the knight, and Name the valkyrie – I don’t always remember to type something in when I restart.) On the SLASH’EM server I’ve played on, I only have one saved game for my profile (I might be able to get simultaneous games going on the two different versions that server hosts), and I don’t choose my characters name; it’s always my username. Other nethack servers seem to me to work the same way.

I think the deal is that a lot of these games started out played on shared servers with terminal interfaces, so they just mapped one game to one account, and then for locally hosted versions they just mimicked this by basically treating different names for characters like different usernames. Basically what Scott just said. (Though I don’t know if the internal workings of this save system are anything like the server copy with multiple usernames, or whether it just kind of looks like that.)

OK, I was able to test from a server (i.e., over the web as opposed to locally), with the same results. On the plus side, I was able to use Firebug to see that the saved game data is being loaded into LocalStorage each turn, and it shows up in the DOM again when the page is reloaded. It seems that what is happening, then, is that the restore code is not actually restoring that data (a message should be printed on successful restore).

Here’s the link to the test:

dl.dropbox.com/u/947038/Test/play.html

I usually go north a couple of times and then reload the page.

–Erik