I haven't looked into it too much but I know inform can store data in
external files (the "ghost" example in the recipe book that stores
"ghosts" of past sojourns, showing where the adventurer previously
died), so I was wondering if I could somehow silently force a save.
It doesn't have to be a very smart process. It could literally save
after every single thing the player types - even if it's a mistake. In
fact, it would be best if it worked that way, just to make sure it
captures everything the player does.
Best scenario: The game will save to a file after every command or
interaction between player and parser and load the file upon loading
the game (I suppose that would be during the "when the virtual machine
starts" event?).
Less optimal scenario: The game silently saves when the player quits.
This is less optimal because (a) the game will not save if the player
simply closes his or her interpreter and (b) it opens up an abusable
flaw. The player can play up to a point, quit, restart and then if the
player decides that he or she does not like the outcome of those turns
between the last "quit" and his current turn, he can simply close the
interpreter (or crash it, using task manager) and start from his last
save. This essentially would act as a de facto quicksave.
Least optimal scenario: I know I can (a) block saving throughout the
game and then (b) interject "Save your progress?" when the player
tries to quit, however this presents its own problems as the player
could conceivably play up to a certain point, decide he didn't like
the outcome, close the game without saving, and then resume from his
earlier save.
I know it sounds like I'm working hard for a feature that will likely
annoy the player, but I assure you it makes sense in the context of my
project (which would take too long to explain right now).
This certainly should be possible, though will require a bit of Inform 6
work. I wouldn't advise trying to save areas of memory: the easiest will be
to use the interpreter's built-in saving logic, but without asking the user
if they want to save.
When the user enters a save command the game ends up in the routine
SAVE_THE_GAME_R, which is in Glulx.i6t in the "Inform7/Extensions/Reserved"
directory of your Inform 7 installation.
The important point in this code is that the bit that asks the user where to
save is the call
fref = glk_fileref_create_by_prompt($01, $01, 0);
But the bit that actually does the save is
@save gg_savestr res;
If you write your own routine based on SAVE_THE_GAME_R, but instead of
calling glk_fileref_create_by_prompt() you call
glk_fileref_create_by_name(), with some appropriate arguments, you should
have a routine that silently saves the game's state, which you can then call
when you want to.
David
Excellent, that's exactly what I'm looking for - thank you very much!
I admit I'm almost entirely unfamiliar to I6 syntax, except for when
people have handed me code snippets. It seems fairly straightforward,
but I don't know enough to start writing my own I6 includes. Can you
recommend a document or place where I can read more about it, so I can
learn how to write a routine like this?
Also, is it possible for me to implement a routine where the game to
automatically loads this file? I assume so. Ideally I would have the
character type in a name (which has already been implemented) and then
after typing in the game, it would check if a save file for that
character exists and automatically load it. Kind of like how you log
into an MMORPG, or a Diablo-type games.
It would also be grand - though not actually necessary - if I could
write a routine allowing the player to "delete" a character file (at
his or her choosing, in this case).
Thanks again,
Roger
You could probably do this by having a separate text file (or binary
file, if you prefer that the player not be able to easily view the
contents) to which player profiles are saved. This would associate a
saved file's name with each character's name. You'd load that file at
startup, display a list of available characters, then load the
appropriate saved file based on the player's choice.
I assume (though I'm not certain) that Glulx Inform can delete as well
as create saved files silently. If so, you could use a similar method
to allow for profiles to be deleted as well.
--Erik
Erik Temple wrote:
> I assume (though I'm not certain) that Glulx Inform can delete as well
> as create saved files silently. If so, you could use a similar method
> to allow for profiles to be deleted as well.
I certainly hope that Glulx-interpreters cannot silently delete or
rename files! That would be a major security issue.
Regards,
Victor
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAksK37wACgkQoiOrMwvIZLyh+QCeOusEmju44NfrLHhO0akN0cqj
zqUAn30CmOwvBf636rFUgcu9WBUUueYQ
=FLr7
-----END PGP SIGNATURE-----
The file operations are supposed to be sandboxed to within an
interpreter-specific (or game-specific) directory. And yes, there is a
file-delete call.
--Z
--
"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the borogoves..."
*
You will fail to prevent this. If you save to disk files, players will
be able to copy them or back them up from outside the app.
Think of it in terms of "discouraging" players, rather than
"preventing" them, and you will at least be in a range that's not
logically impossible.
For that matter, nothing says that a Glulx interpreter can't support
hot-key undo/redo commands that bypass the game entirely. I don't
think they do at present -- not Mac Zoom or Spatterlight, at least --
but Z-code interpreters do.
> I admit I'm almost entirely unfamiliar to I6 syntax, except for when
> people have handed me code snippets. It seems fairly straightforward,
> but I don't know enough to start writing my own I6 includes. Can you
> recommend a document or place where I can read more about it, so I can
> learn how to write a routine like this?
The Inform (6) Designer's Manual would be the best place, I guess, or
maybe a Beginner's Guide to Inform (6). The former is more comprehensive,
but also assumes some familiarity with programming in similar languages.
Both are available here:
http://www.inform-fiction.org/manual/
But you probably won't need to become completely familiar with I6 to
accomplish this. David K. has already directed you to the most important
function names. You can find a useful summary of Glulx function calls here:
Zarf's site is also useful:
It's also quite useful to study extensions where people have hacked the I6
template layer. There are quite a few of these, but I don't know if any of
them target the
To get you started on the actual task, I've pasted below the code I used
to implement a very simple change to restoring the game in my WIP. I will
probably one day write an extension that hacks various entry points, such
as the report restoring the game rules below, into the library routines.
These would allow you to test conditions, set limits on the number of
saves, etc., as well as change the messages and other output associated
with saving and restoring (this is how the Undo Output Control extension
works; you might also take a look at that extension and Conditional Undo
for examples of how to incorporate I7 rules and activities into the flow
of I6 library routines). If I do this, I will probably include options to
allow the author to save/restore without prompting if desired. So, please
feel free to post what you come up with! Or wrap it up as an extension
yourself :)
--Erik
[Compare the I6 inclusions to their counterparts in Glulx.i6t to get a
sense of what was changed and what it allows.]
Section - Hacking game restore to offer customized restore message
The report restoring the game rules are a rulebook.
The last report restoring the game rule (this is the default restoring the
game rule):
rule fails.
Report restoring the game:
say "[bracket]Saved file successfully restored.[close bracket][paragraph
break]";
print startup text;[a phrase that prints appropriate situational text]
rule succeeds.
[GL__M(##Restore, 1) = "Restore failed"]
[GL__M(##Restore, 2) = "Ok."]
Include (-
[ RESTORE_THE_GAME_R res fref;
if (actor ~= player) rfalse;
fref = glk_fileref_create_by_prompt($01, $02, 0);
if (fref == 0) jump RFailed;
gg_savestr = glk_stream_open_file(fref, $02, GG_SAVESTR_ROCK);
glk_fileref_destroy(fref);
if (gg_savestr == 0) jump RFailed;
@restore gg_savestr res;
glk_stream_close(gg_savestr, 0);
gg_savestr = 0;
.RFailed;
GL__M(##Restore, 1);
];
-) instead of "Restore The Game Rule" in "Glulx.i6t".
Include (-
[ SAVE_THE_GAME_R res fref;
if (actor ~= player) rfalse;
fref = glk_fileref_create_by_prompt($01, $01, 0);
if (fref == 0) jump SFailed;
gg_savestr = glk_stream_open_file(fref, $01, GG_SAVESTR_ROCK);
glk_fileref_destroy(fref);
if (gg_savestr == 0) jump SFailed;
@save gg_savestr res;
if (res == -1) {
! The player actually just typed "restore". We're going to print
! a successful restore message; the Z-Code Inform library does this
correctly
! now. But first, we have to recover all the Glk objects; the values
! in our global variables are all wrong.
GGRecoverObjects();
glk_stream_close(gg_savestr, 0); ! stream_close
gg_savestr = 0;
if ( FollowRulebook( (+ report restoring the game rules +) ) &&
RulebookFailed())
{
return GL__M(##Restore, 2);
}
return;
}
glk_stream_close(gg_savestr, 0); ! stream_close
gg_savestr = 0;
if (res == 0) return GL__M(##Save, 2);
.SFailed;
GL__M(##Save, 1);
];
-) instead of "Save The Game Rule" in "Glulx.i6t".
> On Mon, 23 Nov 2009 12:20:29 -0600, Roger <roger.h...@gmail.com>
> wrote:
>
>> I admit I'm almost entirely unfamiliar to I6 syntax, except for when
>> people have handed me code snippets. It seems fairly straightforward,
>> but I don't know enough to start writing my own I6 includes. Can you
>> recommend a document or place where I can read more about it, so I can
>> learn how to write a routine like this?
Sorry, that last message was sent prematurely. Here it is with the links
in place:
The Inform (6) Designer's Manual would be the best place, I guess, or
maybe a Beginner's Guide to Inform (6). The former is more comprehensive,
but also assumes some familiarity with programming in similar languages.
Both are available here:
http://www.inform-fiction.org/manual/
But you probably won't need to become completely familiar with I6 to
accomplish this. David K. has already directed you to the most important
function names. You can find a useful summary of Glulx function calls here:
http://web.archive.org/web/20070606232237/members.aol.com/doepage/summary.txt
Zarf's site is also useful:
http://www.eblong.com/zarf/glk/
It's also quite useful to study extensions where people have hacked the I6
template layer. There are quite a few of these, but I don't know if any of
them target the save/restore mechanism. To get you started on the actual
task, I've pasted below the code I used to implement a very simple change
to restoring the game in my WIP. I will probably one day write an
extension that hacks various entry points, such as the report restoring
the game rules below, into the library routines. These would allow you to
test conditions, set limits on the number of saves, etc., as well as
change the messages and other output associated with saving and restoring
(this is how the Undo Output Control extension works; you might also take
a look at that extension and Conditional Undo for examples of how to
incorporate I7 rules and activities into the flow of I6 library routines).
If I do this, I will probably include options to allow the author to
save/restore without prompting if desired. So, please feel free to post
what you come up with! Or wrap it up as an extension yourself
--Erik
I think Erik's answer largely covers this. To some extent, though, you'll
have to dig into the code and figure out what's going on.
> Also, is it possible for me to implement a routine where the game to
> automatically loads this file? I assume so.
It should be doable, with a bit of hacking.
David
Quite right; my word choice was poor.
My opinion on allowing cheats and hacks is this: if a cheat is readily
available to the player, it potentially breaks the game for them. Of
course this depends on the psychology of the player more than anything
else, but sometimes it's best to protect the player from him or
herself. Of course, gamers that absolutely WANT to cheat will almost
always find a way to do so. I normally avoid cheats and especially
avoid hacks, but even I must admit that I have hex-edited a save game
once or twice in my years of gaming. And damned if I've ever played
the original Sim City without typing "SHIFT-F-U-N-D" a few hundred
times before embarking on my career as a mayor.
As to the player backing up his save files...well, there's only so
much I can prevent the player from doing. The correct word was the one
you used - discourage. That is precisely what I want to do. If the
player is resigned to circumvent the "rules" as I suggest them, then I
suppose he will do what he will do, but I can do what I can do to
discourage it, or at least design it to provide the experience I want
as a default. What the player does beyond that is up to him or her.
Thanks for the input!
On Nov 23, 5:21 pm, "Erik Temple" <ek.tem...@gmail.com> wrote:
> On Mon, 23 Nov 2009 16:17:36 -0600, Erik Temple <ek.tem...@gmail.com>
> wrote:
>
> > On Mon, 23 Nov 2009 12:20:29 -0600, Roger <roger.helge...@gmail.com>
> > wrote:
>
> >> I admit I'm almost entirely unfamiliar to I6 syntax, except for when
> >> people have handed me code snippets. It seems fairly straightforward,
> >> but I don't know enough to start writing my own I6 includes. Can you
> >> recommend a document or place where I can read more about it, so I can
> >> learn how to write a routine like this?
>
> Sorry, that last message was sent prematurely. Here it is with the links
> in place:
>
> The Inform (6) Designer's Manual would be the best place, I guess, or
> maybe a Beginner's Guide to Inform (6). The former is more comprehensive,
> but also assumes some familiarity with programming in similar languages.
> Both are available here:
>
> http://www.inform-fiction.org/manual/
>
> But you probably won't need to become completely familiar with I6 to
> accomplish this. David K. has already directed you to the most important
> function names. You can find a useful summary of Glulx function calls here:
>
> http://web.archive.org/web/20070606232237/members.aol.com/doepage/sum...
Erik, thank you very much! I will look into this and dig into the I6
designer's manual.
Thanks - it looks like I have some research ahead of me.
Of course, maybe you can create a culture in which this is
nigh-universally considered a Vile Thing. E.g. Nethack and
"savescumming."
Adam