Adapting whatever verb the player has used in descriptive text - cleaning, rubbing, wiping etc

I read all the relevant documentation about text alterations but didn’t see anything that would help me with this specific issue. Also searched the forum.

What I want to do is this:

Instead of rubbing the plate, say "It's no use [rubbing] this gunk off, the stuff's stuck on there pretty well."

So if the player typed “wipe plate” it would say “It’s no use wiping this gunk off,” or if they typed “clean plate” it would say “It’s no use cleaning this gunk off.”

Inform won’t let me use [rubbing] this way. Is there a built in way to achieve this kind of text substitution?

Ultimately I know this doesn’t matter, I could word it a different way or go to some lengths with the code to achieve the same thing, but I thought Inform had this sort of functionality buried in there.

There isn’t a built-in way to do it, exactly, although it’s not too hard to arrange with a bit of effort.

This is the best way that I found to do this sort of thing in my own work (and yes, you need to add every verb you want to support into this table):

Include Snippetage by Dave Robinson.


To rub is a verb.  To clean is a verb.

Table of Verb Translation
topic	verb
"rub"	verb rub
"clean"	verb clean

To decide which verb is the current verb:
	let v be the verb word;
	repeat through Table of Verb Translation:
		if v matches topic entry:
			decide on verb entry;
	decide on verb pass.


Instead of rubbing the player:
	say "Trying to [present participle of current verb] [ourselves] would be silly."

Instead of rubbing:
	say "Trying to [infinitive of current verb] [regarding the noun][them] would be unwise."

It usually makes more sense to do this sort of thing only in very generic contexts, or where you have a lot of verbs aliased to the same action but they don’t always imply the same thing in the player’s mind. (In my case I was doing something with “cut” vs. “attack”.) Otherwise it’s a lot simpler to just write the word you want directly in the specific rule.

For the curious, this is based on the basic form (using a fixed verb):

To rub is a verb.

[...]	say "You try [present participle of verb rub] [the lamp]."

But this is of course still a lot more verbose than just writing it directly, so again it typically only makes sense to do it when there’s something variable about the verb choice.

1 Like

Ah ok, thanks. I guess after seeing all the built-in substitutions I thought Inform would be smart enough to be able to handle this on its own. Oh well. Still a very useful way to implement this that you posted, thank you!

@UncleSporky, here’s the background on this, as I understand it.

First, every word that is recognizable by the parser’s built-in machinery goes into a big memory table called the dictionary. This table has the (first 9, usually) characters of the word, plus assorted internal flags to indicate certain functional features of the word in the context of parsing. One of these flags indicates whether the word is valid as a “verb” (in the Inform 6 sense).

In the world of Inform 6, a dictionary word is flagged as a verb if it is used to define the first word in a grammar line for an action. The word ‘take’ is marked as a verb to recognize commands like >TAKE LAMP, as is the word ‘pick’ for commands like >PICK UP LAMP. (The word ‘up’ is considered a “preposition” in that command, even though it’s not grammatically a preposition, and it’s not marked as a verb. A command like >UP is handled by special parser code for handling directions, so it’s not marked as a verb for that case, either.) As these examples show, it’s possible for different I6 verbs to trigger the same action, because, while a specific verb word is needed to get the parser to look at a given grammar line, it’s the end of that grammar line that indicates which action is to be generated upon successful parsing. (In this case, the action in either case is ##Take in the I6 notation. The equivalent in I7 is called an action name, and the action ##Take would be designated “the taking action”. See WWI 12.20 “Stored actions” for more on this.)

In the world of Inform 7, a “verb” has a special new meaning in the context of I7’s adaptive text system (see WWI 14 “Adaptive Text and Responses”), and it takes a special declaration to set up a word as a “verb” in the I7 sense (see WWI 14.3 “More on adapting verbs”). I think this creates an actual routine for the declared verb, and that routine can be asked to spit back the text for a given conjugation, tense, etc.

In I7, not every word that is recognized as an I6 verb by the parser gets a corresponding I7 verb. (I don’t know why. Perhaps space considerations? Fortunately, new verbs are very easy to declare, as mirality showed.) For your special message, you would want an I7 verb for each I6 verb that can trigger the message so that you can ask for its present participle. I7 verbs are only created at compile time, so it is necessary to declare in advance any of them that might be used for the message.

Hopefully that’s all correct. If not, someone will probably come along shortly to point out errors.

EDIT: @UncleSporky, just to add: Daniel Stelzer’s Subcommands extension is pretty great for similar functionality with respect to noun words typed by the player.

1 Like

In I7-speak, things typed by the player are “understand” phrases, which may or may not be verbs in the English sense but are never verbs in the I7 sense (unless explicitly declared so separately). While these usually correspond to English verbs and nouns in the story, they don’t have to, and they exist in a separate “space”. (Which is mostly the dictionary, but there are some special cases.)

I7 “verbs” are by default only the things required to make relational assertions in the source text (i.e. “carry” already exists as a verb because I7 knows that it’s associated with the carrying relation), plus a handful of additional verbs “for saying” defined either because the Standard Library responses needed them, or for historic reasons, or just because. But like otistdog suggested, I suspect it doesn’t define everything by default to avoid making you pay in code size for things you don’t actually use.

WI14.3 covers how to add more adaptive verbs; it’s fairly straightforward. You can see the list of verbs that have already been defined (and whether they’re only for saying or have been linked to a relation) under Index -> Phrasebook -> Verbs.

TBH, this association between source text verbs and printable verb adaptation is highly peculiar, and I strongly suspect (without evidence) that this was a “happy coincidence” – the compiler already needed to be able to adapt verbs in the source text and this was simply lifted into the runtime layer for the fancy new adaptable-text system, with the source verbs simply along for the ride. (Which is not intended to disparage the system or the implementation effort that went into it – it is indeed fancy and powerful and no doubt did take a lot of work. And it can be abused in highly fun ways.)

1 Like

I’d used this approach, but just today realized there’s a straightforward way to go from text to verb:

To decide what verb is the null verb: (- nothing -).

To decide what verb is (T - a text) as a verb:
    let t be T in lower case;
    repeat with v running through verbs begin;
      if "verb [t]" is "[v]", decide on v;
    end repeat;
    decide on the null verb.

To decide which snippet is the verb-snippet:
  (- ((verb_wordnum * 100) + 1) -)

every turn:
    let v be "[the verb-snippet]" as a verb;
    unless v is the null verb, say "She [adapt v from third person singular]."

I think that, rather than needing to hook into every verb you want to track, you should be able to do something like:

The pending player action is an action name that varies.

Before doing something:
    Now the pending player action is the action name of the current action.

(disclaimer: typing from memory, not at computer right now)

Then you can have the first column be an index of action names, instead of text. I did something similar when creating a system where NPCs can witness others taking actions and react accordingly (although in my case I used an “after” hook because I only wanted them to react if the action succeeded).