RemGlk autosave

Remember back, oh, about April – a million weeks ago – I said that I wanted to get autosave working in Glulxe+RemGlk?

It works now. See the bleeding-edge repositories:


This may be useful if you’re creating a bot or online game-playing service. It supports two slightly different use cases:

  • Hedging against the possibility of process termination

This is how the iOS interpreters work. (Or worked, since I’m not supporting them on current iOS.) The app starts and runs normally, but it could be killed at any time (when in the background). Therefore, we autosave every turn. At startup time, if autosave files exist, we restore them and continue play.

  • Single-turn operation

This allows you to run an ongoing game with no background process! Every time a user input arrives, you launch the interpreter and shove the input into stdin. The interpreter reads the autosave file, processes the input, generates a turn’s worth of output, updates the autosave, and exits.

See the README file at https://github.com/erkyrath/glulxe for more info on using the interpreter in these two modes.

3 Likes

I’ve run through a bunch of the Glulx unit tests with this interpreter (in single-turn mode). It seems to work, but there are undoubtedly bugs lurking. Keeping a stream open for several turns is a likely trouble spot. (I tested keeping a transcript file open, at least.)

In case you’re wondering: the Fizmo Z-code interpreter has support for the autosave API. However, it’s old (2012!) and is mostly written in ObjC, because I only ever used it on iOS. It could be updated to work with this new RemGlk, but I’m not sure when I’d get to it. Feel free to give it a shot…

2 Likes

So I’m in the process of changing how Emglken works: I am getting rid of my custom Glk library and incorporating the whole of Remglk, and so far it’s been surprisingly straightforward.

I have a couple of questions about the autosaving stuff:

  1. How graceful is it with autosaves produced from older versions or even entirely different autosaving systems? If we put an autosaving version of Glulxe in Lectrote will it be able to handle (ie, ignore) the autosaves from Quixe?

  2. If I want to build Glulxe without autosaving (or another terp that doesn’t have autosaving), will it work to just exclude unixautosave.c? I’m wondering will the dead code eliminator then clean up everything from the libremglk.a. Probably? But it looks somewhat closely integrated. I could comment out the GLKUNIX_AUTOSAVE_FEATURES definition, but I’m hoping for something that will work without me needing to maintain a fork.

Let’s see…

If I want to build Glulxe without autosaving (or another terp that doesn’t have autosaving), will it work to just exclude unixautosave.c?

You’re just trying to get the code size down? You can’t comment out GLKUNIX_AUTOSAVE_FEATURES in remglk (it won’t compile). You can add

#undef GLKUNIX_AUTOSAVE_FEATURES

after each #include “glkstart.h” line in unixstrt.c and unixautosave.c.

Autosave compatibility is not graceful at all. Lectrote’s assumption is that if the interpreter changes in any significant way, the autorestore will just fail and the game will start at the beginning. (The user might have to use the Reset menu option.)

This has never happened with Quixe. The advantage of slow development, I guess…

For supporting several interpreters, I’d say use the --autoname argument (or equivalent) and get each interpreter to use a different base filename.

Hmm, I’d prefer not to have to fork Glulxe, so I may just keep it in. It’s probably not too much code space compared with the whole.

I’m using a virtual filesystem and then passing the files to Dialog.js to handle, so the filenames don’t matter. But, I have just thought of a solution: I can add in a property to the JSON before giving it to Dialog, and then check if it’s there before giving it to the VM. That should work!

Yep, that’ll do it.

You can no longer compile Git with Remglk. Using the current code from each (and just changing Git’s Makefile to refer to remglk) it produces the following errors:

In file included from git_unix.c:9:
../remglk/glkstart.h:92:59: error: unknown type name ‘gidispatch_rock_t’
   92 | extern void glkunix_window_set_dispatch_rock(winid_t win, gidispatch_rock_t rock);
      |                                                           ^~~~~~~~~~~~~~~~~
../remglk/glkstart.h:95:59: error: unknown type name ‘gidispatch_rock_t’
   95 | extern void glkunix_stream_set_dispatch_rock(strid_t str, gidispatch_rock_t rock);
      |                                                           ^~~~~~~~~~~~~~~~~
../remglk/glkstart.h:98:62: error: unknown type name ‘gidispatch_rock_t’
   98 | extern void glkunix_fileref_set_dispatch_rock(frefid_t fref, gidispatch_rock_t rock);
      |                                                              ^~~~~~~~~~~~~~~~~
make: *** [<builtin>: git_unix.o] Error 1

Oh, hm. I think I messed up header dependencies.

If you want to get it built in a hurry, add #include "gi_dispa.h" to more .c files.

I pushed a fix for this. I hope.

1 Like