[I7] Writing a stored action table to a file

I need to record a stored action table in an external file.

I know I7 cannot record a table of rules into an external file. I assume actions fall into the same category.

Does anyone have a brilliant suggestion for working around this?

My current course of action involves associating all possible actions (and their nouns, second nouns, etc.) with numbers and converting the table right before writing to the file. It is not a pretty sight, so I’m hoping someone can assist.

Can I7 record action names into an external file? If it can (and I assume it can record things), then you could maybe use Ron Newcomb’s Editable Stored Actions* to break the stored actions into their components and write that.

If that doesn’t work, maybe you could associate things with text strings instead of numbers just to make it less ugly?

*I started typing Incredible Stored Actions because I love that extension SO MUCH.

This is a really bad idea, but you could potentially use my Verbal Conjugation extension to turn the actions into imperatives and write them as text, then feed them to the parser to get the actions back later. (You’d need to temporarily place everything in scope before parsing, so that the nouns would line up.)

[code]Chapter “Setup”

Include (-
[ STORED_ACTION_TY_Support task arg1 arg2 arg3;
switch(task) {
CREATE_KOVS: return STORED_ACTION_TY_Create();
CAST_KOVS: rfalse;
DESTROY_KOVS: return STORED_ACTION_TY_Destroy(arg1);
PRECOPY_KOVS: rfalse;
COPY_KOVS: return STORED_ACTION_TY_Copy(arg1, arg2);
COMPARE_KOVS: return STORED_ACTION_TY_Compare(arg1, arg2);
READ_FILE_KOVS: if (arg3 == -1) rtrue; return STORED_ACTION_TY_ReadFile(arg1, arg2, arg3);
WRITE_FILE_KOVS: return STORED_ACTION_TY_WriteFile(arg1);
HASH_KOVS: return STORED_ACTION_TY_Hash(arg1);
}
];
-) instead of “KOV Support” in “StoredAction.i6t”.

Include (-
[ STORED_ACTION_TY_WriteFile txb;
print “A”;
print BlkValueRead(txb, 0), “,”; ! action
print BlkValueRead(txb, 1), “,”; ! noun
print BlkValueRead(txb, 2), “,”; ! second noun
print BlkValueRead(txb, 3), “,”; ! actor
print BlkValueRead(txb, 4), “,”; ! request flag
if (BlkValueRead(txb, 5)) {
INDEXED_TEXT_TY_WriteFile(BlkValueRead(txb, 5));
} else {
print “;”;
}
];

[ STORED_ACTION_TY_ReadFile txb auxilary_file character
	index value;
	while (index ~= 5 && character ~= 32 or 9 or 10 or 13 or 0 or -1) {
		character = FileIO_GetC(auxilary_file);
		if (character == ',') {
			BlkValueWrite(txb, index++, value);
			value = 0;
		} else {
			value = value * 10 + (character - '0');
		}
	}
	character = FileIO_GetC(auxilary_file);
	if (character == 'S') {
		if (~~BlkValueRead(txb, 5)) {
			BlkValueWrite(txb, 5, INDEXED_TEXT_TY_Support(CREATE_KOVS));
		}
		INDEXED_TEXT_TY_ReadFile(BlkValueRead(txb, 5), auxilary_file, character);
	} else {
		if (BlkValueRead(txb, 5)) {
			BlkFree(BlkValueRead(txb, 5));
			BlkValueWrite(txb, 5, 0);
		}
	}
	return txb;
];

-) before “Involvement” in “StoredAction.i6t”.

Chapter “Demo”

There is a room.

The File of Memory is called “memory”.

Table of Memory
memory (stored action)

Before doing anything:
now the memory in row one of the Table of Memory is the current action.

Instead of jumping:
write the File of Memory from the Table of Memory;
say “Done.”

Instead of singing:
read the File of Memory into the Table of Memory.

Every turn:
showme the memory in row one of the Table of Memory.

Test me with “jump / z / sing”.[/code]
Note that this code breaks Inform’s rule about writing addresses to files; such a file can only be read by the same version of the story that wrote it.

This seems like the least kludgy solution… but if the file moves from one computer to another, will that also break it? (For example, if I have the file stored on Dropbox, and I boot the same version of the game from 2 different computers?)

I think that would be fine, as long as it’s the same version of the game (and thus has all the data in the right places in the file).

Yes, that will work.

You might want to include a version number in the save file. Check it against the game’s release number (or serial number, or checksum, or something) when you load it in. That way you can display a sensible error message instead of crashing.

I wonder what would happen when you read it into the wrong version. Would it die immediately when the memory addresses weren’t sensible? Would it die later when it couldn’t interpret the pointers as pointing to stored actions? Or would it be able to continue until dereferencing random areas of memory eventually caused something bad to happen?

As written, it wouldn’t die until you tried the stored actions or made use of their parts. It would be perfectly safe to check or otherwise compare values in the mis-loaded table, and also perfectly safe to overwrite all the stored actions with good values if the story decides it’s looking at data from a wrong version.

(The procedure could also be made robust enough to cross versions, but not without nailing down some corner cases. Like, what happens if one of the stored actions from version 1 is X FOO and the foo is removed in version 2?)

Fantastic! I’ll charge forward with this solution. Thank you very much for the help.