I’m wondering what it would take to put together a way to port old save games into new release versions of my WIP. Of course, I expect the first release to be totally perfect and bug-free, but on the off-chance that it’s not, it would be nice to be able to patch it without making everyone restart.
The obvious thing would be to make a text file and manually insert lines of code for each variable in the “write to text file”. But problem A: I’m working with Dynamic Objects, so importing a save would require object creation, and I’m not quite sure how that would work, and B: I’m not aware of anyone having done this before, and I’m bound to miss things that I’m supposed to initialize.
Has anyone done an extension like this for I7, or have shortcuts to suggest? There’s got to be an alternative to manually writing thousands of lines of code to write thousands of number and text variables into a text file, right?
I was hoping for everyone. There’s quite a bit of randomization, as well, which makes skeins a bit difficult to control - and it’s no small advantage to be able to “tweak” the import file as needed, but primarily it’s for general use between release versions.
It’s definitely not something I’m committed to, but since each save is gone forever, and it’s intended to be a fairly time consuming game, if there’s an easy-ish way to set up save porting, it would be kind.
If the game has several independent chuncks, you could make an external file that remembers which chunks have already been visited, and allow players to skip to any previously visited chunk immediately.
I was advocating this feature a number of years ago. It’s standard in many types of software – word processors and so on.
My impression (being no more than a ham-fisted amateur programmer) is that there are no technical problems standing in the way. There are, however, at least two roadblocks. First, the developers of the authoring system would have to spend time working out the optimum way to do it, and that’s not necessarily the best use of their time. Second, as each game is unique, each author who wanted to use the system would still have to work out how exactly to deal with incompatibilities between versions, which could be either trivial or complex.
Let’s suppose, for instance, that in your new version you’ve added an object in one of the rooms. Depending on how the authoring system produces a compiled game file, this change could cause the compiled game to renumber the object list, which could have disastrous consequences! In your saved game, maybe you picked up and were carrying the amethyst crystal, and when you load the game into the new version you might find that you’re carrying the stagecoach.
That said, I believe Inform lets the author create a system for saving and loading text files. If you parcel out every detail of what the player may or may not have done and save it in a text file, you could also write a routine that would load the text file and make whatever decisions you felt were appropriate in the case of conflicts between what the text file says and what is possible in the new version.
But do you really want to go to all that trouble?
A better alternative is to save and load play transcripts. The player who switches on ‘script’ (or its equivalent) before starting the first play session should be able to replay the transcript later in a new version – provided the author hasn’t done anything like add a lock to a door, which would break the transcript.
When I run across this issue, I intend to use the extension Totally Awesome Cross-Version Save Compatibility by Gravel.
…so for most games, I think Jim’s “save and load the transcript” would be a great idea. But even if you preserve the random seed, I’d guess that wouldn’t work very well for your game; tweak the probabilities and one thing may come out different, which sends the whole game gradually off the rails, until the player may as well just do a hard reset and see if they can play over again as their own ancestors. So you’re probably back into saving a bunch of state variables by hand in an external file and programming a way to load them all.
If I were you I would probably just break compatibility and adopt a Release Updates Only When Awesome policy, though if I were you I probably wouldn’t have started programming the game, because I’m lazy. So don’t take my advice.
Yeah, I’ll . . . get working on that. Oh, look, spreadsheets of fish masses. Man, if only I didn’t have that awesome opportunity waiting for me, I’m sure I would be all over that. Sad.
Yeah, that’s kind of what I anticipated, but it’s good to have confirmation. I’m not that motivated, I don’t think. I mean, part of the reason I’m using Inform is that I think writing save routines is dull and finicky.
Victor, there’s nothing quite like that, but it might be possible to expose some of the game states more directly to the player control. Something to think about, and far less intensive than a perfect save port.
The roadblocks you describe are what we programmers call “serious technical problems”.
Saving the transcript is the least dangerous way to approach this problem. I would still, in general, expect the result to be buggy and unreliable – unless you limit yourself solely to output changes. (Fixing typos in strings.) That makes it safe, obviously.
I’m sure it could get amazingly snarly. All I really meant was, it’s all 1’s and 0’s. In theory, therefore, anything is technically possible.
Looking at the roadblocks from a slightly higher angle, what I’m seeing is (a) implementing such a system in such a manner that it worked properly would require an enormous number of hours of labor; and (b) figuring out the optimum design for such a system would be a very non-trivial challenge because, for one thing, those who might want to use it would be unlikely to agree about what was needed and how it ought to work.
For instance, if the new version of a game changes the name of an object and also gives it a new property (a very normal type of revision), is it still the same object with respect to a saved game, or is it a different object? If it’s the same object, how does the author tell the compiler that? The compiler has no memory of previous versions unless the development system is altered in a fairly fundamental way (such as by allowing the author to give each object a unique ID – and now it’s up to the author to prevent the system from breaking).
The more I think about it, the more difficulties I can see. Transcripts of commands are really the only way to go … and of course those won’t work either in a game that includes randomness, or in which significant changes are made in any of a dozen areas.
Let’s suppose, for instance, that in the old version, the command ‘poke balloon with needle’ didn’t work. The response was “I don’t know the word ‘poke’.” But in the new version, ‘poke’ has been implemented, so that command pops the balloon, releasing the poison gas which kills the evil llama…
I wrote: “Saving the transcript is the least dangerous way to approach this problem.”
On second thought, here’s a safe way to approach the problem: put in safe checkpoints. Say your game is divided into chapters. You record a “version-portable save file” which really just says “the player has reached chapter 4”. Then, in the game, you have code that reads this and sets up everything at the beginning of chapter 4. (And ditto for every chapter.)
This is simplistic – you’re not even trying to record everything the player did to get there. But it’s testable and it won’t break.
I believe this is something that should be implemented in IF languages, not tacked on as an extension or hacked together for an individual project. In fact, I think it should be made a priority.
In the past, when IF almost always played on the desktop, it wasn’t such a big deal that save files weren’t compatible with new versions. It was your choice whether or not to upgrade to the new version of the game. But if you’re playing online through Parchment or some other web interpreter, that choice is no longer in your hands. If the author updates the game, your save is broken. And if you’re not already familiar with the way IF systems work, you may not even understand why the game is suddenly broken.
On the subject of replaying the transcript - didn’t Quest 4 do that? I remember a bit of a fuss during one IFComp because restoring a Quest game that had been entered was just so slow.
Let me be clear, because I been pussyfooting around this in previous posts:
Solving this at the system level, so that it works without any effort from the author, is impossible. We’re not avoiding the problem because we’re lazy or our priorities are elsewhere; we are avoiding the problem because we can’t solve it.
All the solutions proposed so far require the author to think carefully about each change made in an upgrade, and possibly write some code to manage “repairs” to an old save state. That is a tricky task for an experienced programmer. It is not practical to require I7 users to do that work, because most of them won’t bother and most of the ones who do will not do it very well. I am serious: I would not use such a system for my own IF – not even transcript-reloading. Too much work, too much danger of bugs slipping through anyway.
The “simplistic” solution I just posted is the best compromise I can come up with. It’s usable, in the sense that an IF author can get it right in a reasonable amount of time and testing. I don’t believe many games will adopt it, however.
Hm. Let me come at this another way: The problem per se is not “save files can’t be loaded in new release”, but rather “a new release comes out and the save files stop working.”
It would be easy enough for the new release to include the old release. (Just pack both game files into the same Blorb package.)
Then, when you type “restore”, you see all your save files – but some of them have asterisks. A footnote says “This save file is for release 1 of the game. If you load it, you may see bugs that have been fixed in release 2.” When you pick a save file, the interpreter picks the matching game file and loads you in.
When you type “restart”, the interpreter would of course jump to the current game file.
Implementing this is quite easy for the I7 language (add a “release along with previous game ‘foo’” statement and some blorb-hacking). It’s pretty simple for an interpreter to support it. It’s opt-in for the author, but the only effort is retaining your old game releases and remembering to import them. It makes the Blorb file bigger with every release, of course, but storage space is our cheapest resource these days.
From the player’s point of view it’s a half-assed solution, but it’s better than what we have now.
If people are to implement such a thing for their games, I guess the authoring system should at least provide streamable objects that can save and load their states, regardless of their bytecode representation.
The game programmer can take it from there and resolve conflicts. Whether he/she can do that correctly is anyone’s guess. Surely, not offering such features because of a “our users are too inexperienced” assumption sounds more like an excuse (there are some very talented people out there.) Better just say “it’s too much work to bother with this right now.”
Just as an additional clarification: This is not unique to IF. All games that allow saving at arbitrary times have to struggle with these exact same problems.
Undum’s compromise solution is to replay the transcript, but only if the version number hasn’t changed. This way the author can make minor changes that don’t break the saves, but if it’s necessary to change the story structure the author can increment the version and force readers to restart the game.
I agree that this is a lot bigger problem now than in the past. When games are hosted online by the authors, they can update the games and thus break the saves without the player’s consent. It must be frustrating that you can’t fix a single typo without wiping out everyone’s save games. If you offer the game as a download the player can decide whether they want to update or not.
On the other hand I agree with zarf in that transcript-replay-saves would probably bring a lot of extra headache to the authors which would be yet another unnecessary burden in already time-consuming development process, plus it would be extremely easy to make a single mistake that would break the whole system anyway. But it would be nice at least have an option available to go through that road if this is something you care about. So I don’t really know what kind of resources if any should be directed at adding the feature even as an external structure.
Multiple game files make no sense to me, because the people with an old save file don’t want the new version but need the old one which they already have, while people playing the game for the first time don’t need the old version.
It makes sense when the author pushes the update (online interpreters) or when the player doesn’t know that updating the game breaks the saves, which is contrary to how almost all other software works.
It also makes sense for iOS – which is where I came up with this notion in the first place. If I release a game file update, everybody will install it without thinking. So it makes sense to keep the old game file around, so the user’s old save files will continue to be usable.