My thought was this. If you can save world states to a table, could you have the player "name" an action, like let's say a magic spell, and have that name recorded into the table?
Like, let's say you capture an evil sprite in a bottle and you assert control by naming it. The player literally uses whatever name the want, which is saved into the table, and they can then summon the sprite to do their bidding at any point by using their name.
ArdiMaster
Perhaps I'm misunderstanding your intent here, but I feel like this should be covered by the "understanding things by their properties" mechanism...
pinkunz
But those properties are assigned by the author, not the player, no?
ArdiMaster
Not necessarily. You can put a text property and have some action that assigns it from the player's command and it will work
pinkunz
Is there an example of this in the Inform Recipe book?
Or anywhere, for that matter. I'm not picky.
Here you go @pinkunz (broken out into a forum thread for readability and for the benefit of anyone who might be interested:
"Testing Project" by Adrian
The lab is a room. "Bubbling retorts, that sort of thing."
The genie is in the lab.
The genie has some text called the given name.
Understand the given name property as describing the genie.
Genie-naming is a truth state that varies. Genie-naming is initially false.
When play begins:
now the command prompt is "What shall be the name of your genie? >";
now genie-naming is true.
After reading a command when genie-naming is true:
let N be the substituted form of "[the player's command]";
now the given name of the genie is N;
now genie-naming is false;
now the command prompt is ">";
say "The genie shall be known as [N].";
reject the player's command.
Produces:
lab
Bubbling retorts, that sort of thing.
You can see a genie here.
What shall be the name of your genie? >Bob
The genie shall be known as Bob.
A technique famously used by the featureless white cubes in Spellbreaker, which you can write names on to keep them distinct. (Though of course that wasnât in Inform 7.)
A cube is a kind of thing.
A cube has some text called the label.
Understand the label property as describing a cube.
And now you can label all your cubes differently if you like.
I actually took inspiration from the Spellbreaker approach and wrote up a take on this prompt that implemented a labeling action in some depth - cool that you did the asking-the-player approach!
Thank you, Adrian. I sincerely appreciate you writing that example for me. Would it be appropriate to ask a couple of questions?
Iâm assuming the standard save function will retain these names. If you were using a non-standard save function, similar to Ryan Veederâs custom save functions, how would this substitution of N best be saved?
Also, can you use this with a verb? Like letâs say you capture a water druid and gain power over it by naming it, meaning you can summon it by uttering itâs name, causing the focus of your attention to be inundated with water.
let N be the substituted form of â[the playerâs command]â;
now the given name of water-druid-summoning is N;
If youâre using an action applying to a topic (like WRITE BANANA ON CUBE), you can use [the topic understood] instead of [the playerâs command] to get the part matched by a [text] token.
Iâm assuming the standard save function will retain these names
Yes. The standard save function basically takes a snapshot of the VMâs memory, so this is included. (Thatâs also why regular save files are not at all portable between releases.)
If you were using a non-standard save function, similar to Ryan Veederâs custom save functions, how would this substitution of N best be saved?
If youâre using this sort of save functionality, you probably already have a table that saves key-value-pairs of text. So youâd just have to come up with a new key to store this under. At the time the genieâs name is set, you also set the corresponding entry in the save data table. When you load this data back, itâs just one more value to restore.
Saving custom texts with these external file-based save functions is covered in this blog post (but let me know if that post is missing anything important).
Letting the player name things is documented pretty wellâthereâs this example in the I7 documentation, thereâs @DeusIraeâs example in the other thread, thereâs the example in that blog post I already linked (which includes splitting up names so the parser will recognize individual words). But I find my brain to be very tickled by a sentence at the very beginning of this thread:
could you have the player ânameâ an action, like letâs say a magic spell, and have that name recorded into the table?
â @pinkunz
To me this implies a game that works like this:
As long as you hold this magic scroll, you can give a name to your signature spell.
>NAME SPELL SMARGUS
Okay, your signature spell is Smargus! Have fun!
>SMARGUS
You cast the mighty spell of Smargus! The enemy crumbles before you!
But I canât figure out how to name actions! I canât do An action has a text called the custom-name. because actions canât have properties. Is there a way around this? I donât know.
Maybe I could satisfy myself with a custom argument for the >CAST action. I could >NAME FIREBALL FANTASTIC FIREBLITZ, and then the parser would know when I >CAST FANTASTIC FIREBLITZ it should treat that as >CAST FIREBALL.
Well,
A spell is a kind of value.
Fireball is a spell.
A spell has text called the custom name.
Understand the custom name property as describing a spell.
This doesnât compile, because âa property can be understood as referring to a single object (or a kind of object) but not to something of any other kind.â So am I stuck?
(If I treat a spell as a kind of thingâwhich is not very satisfyingâassigning a custom name works okay, but then I run into an unrelated issue where I canât cast a spell that isnât physically present, despite defining Understand "cast [any thing]" as casting. Has [any thing] been nerfed?)
You may have defined the casting action as applying to âone thingâ, which actually means one touchable thing. You have to use âone visible thingâ to mean one thing thatâs not necessarily touchable. This is, in my opinion, the single biggest issue with Informâs terminology and the one I most hope gets fixed.
You can also make your spells be a special kind of object, if you donât want them to be treated as âthingsâ, but in practice this usually isnât an issue. Itâs mostly important if you need to avoid them getting caught up by [any thing] actions (say, if you have a lot of actions like GO TO and donât want to write special rules for each one to prevent using them on spells).
Thank you. I may have understood this âone visible thingâ nonsense at some point and it slipped my mind. But not once have I ever had to care about the distinction between âthingâ and âobjectâ!
This is indeed the implementation I was imagining from the moment it was brought up in chat. I would imagine this would be fun to flesh out as the core mechanic of a game if I understood how to make it work. Thank you for articulating my thoughts better than I did.
Note that âverbless grammarâ (i.e. 'Understand ... phrases that start with a [token in square brackets] rather than a verb word) is still not fully supported in Inform 10.1.2.
The bug in 9.3/6M62 that led to incorrect allocation of topic snippets after commands such as âDarcy, helloâ (see here) when a story included any verbless grammar has been fixed in 10.1.2, but it remains the case that if you have a word that is both a true recognised verb word and also a word that is recognised by your âverbless grammarâ token, the parser will try to parse it only as a true verb word and never as a match to the âverbless grammarâ token (see also here).
In this instance, if you name your spell as a word that is already a true recognised verb word, your spell will never fire because the parser gives up after having failed to match a correct grammar line to the recognised verb word without then going on to consider the possibility of matching to âverbless grammarâ.
e.g.
Lab
>name spell answer
You name your spell Answer.
>answer
I didn't understand that sentence.
OK, so weâll block existing command verbs and pseudo-verbs.
use DICT_WORD_SIZE of 15.
To say again-word: (- Glulx_PrintAnything(AGAIN1__WD); -).
To say again-alias: (- Glulx_PrintAnything(AGAIN2__WD); -).
To say oops-word: (- Glulx_PrintAnything(OOPS1__WD); -).
To say oops-alias: (- Glulx_PrintAnything(OOPS2__WD); -).
To say undo-word: (- Glulx_PrintAnything(UNDO1__WD); -).
Include (-
! 1-indexed for I7's convenience
[ printDictWord i;
print (address) #dictionary_table + WORDSIZE + ((i-1) * (DICT_WORD_SIZE + 7));
];
-)
To say dictionary entry (n - a number): (- printDictWord({n}); -)
To decide what number is the dictionary size: (- #dictionary_table-->0 -)
The dictionary list is a list of texts variable.
To build the dictionary list:
if the dictionary list is empty begin;
add the substituted form of "[again-word]" to dictionary list;
add the substituted form of "[again-alias]" to dictionary list;
add the substituted form of "[oops-word]" to dictionary list;
add the substituted form of "[oops-alias]" to dictionary list;
add the substituted form of "[undo-word]" to dictionary list;
repeat with i running from 1 to the dictionary size begin;
add the substituted form of "[dictionary entry i]" to dictionary list;
end repeat;
end if;
when play begins:
build the dictionary list;
Last check naming something:
if word number 1 in "[the topic understood]" is listed in the dictionary list, instead say "Try something a little more original and distinctive, wizard."
Itâs that easy! In 6M62, at least. In 10.1, for your convenience, you canât compile an inclusion using #dictionary_table and would have to write a kit.
Neat! I would have thought that you donât need to build a copy of and exclude the whole dictionary- only those words flagged in the dictionary as being verb words?
I suppose you donât. But Iâm still a bull in the parserâs china shop, so whatâs a good way to get just the command verbs? (And donât skimp on the directions and their abbreviations as pseudo-commands of interest!)
Include (-
[ PrintCommandWords wd i j dictlen entrylen entry;
dictlen = #dictionary_table-->0;
entrylen = DICT_WORD_SIZE + 7;
for (j=0 : j<dictlen: j++ ) {
wd = #dictionary_table + WORDSIZE + entrylen*j;
entry = DictionaryWordToVerbNum(wd);
if ((entry >= 0) && (entry < dictlen))
print (address) wd, "^";
}
];
-)
To say command words: (- PrintCommandWords(); -)
The dictionary list is a list of texts variable.
To decide what text is the expanded (T - a text) (this is expanded-text): decide on the substituted form of T.
To build the dictionary list:
if the dictionary list is empty begin;
now the dictionary list is { "[again-word]", "[again-alias]", "[oops-word]", "[oops-alias]", "[undo-word]" };
repeat with dir running through the directions begin;
add the substituted form of "[dir]" to dictionary list;
end repeat;
now dictionary list is expanded-text applied to dictionary list;
let wordlist be the substituted form of "[command words]";
repeat with i running from 1 to (the number of lines in wordlist) begin;
add line number i in wordlist to dictionary list;
end repeat;
sort the dictionary list;
end if;
lab is a room.
when play begins: build the dictionary list; say the dictionary list
A dictionary entry in Inform-generated code consists of the word itself, followed by three bytes of data. Bit 0 of byte 1 is set if the word can be used as a verb. Iâm not sure if thereâs a portable way to access this, though; you might have to write it differently for Z-machine and Glulx (since the word is stored differently in each).