A-code vocabulary

A-code vocabulary structure and handling have some unusual features, motivated by my desire to make IF games more player-friendly and less 'mechanical' in their responses to player commands. This document deals specifically with vocabulary handling, rather than with the more general topic of player command parsing. See a separate document for parsing details.

There are four specific areas in which A-code vocabulary handling is unusual. These are:

Automatic abbreviations

By default, all vocabulary words are automatically abbreviated to the shortest unambiguous length. For example, if the vocabulary contains KICK and no other word beginning with K, then KICK is automatically abbreviable as any of K, KI and KIC. If, however, the vocabulary also contains KILL (and no other word beginning with KI), then KICK is only abbreviable to KIC, and KILL to KIL.

There are, of course, command words which must not be abbreviated: this is particularly true for any magic words. E.g. we do not want X to mean XYZZY! This is catered for in vocabulary declariations by prefixing the non-abbreviable word with an exclamation mark:

verb !xyzzy

This does not, however, eliminate all unwanted abbreviations. For example, a player may wish to save a game under some arbitrary name, which just happens to be a legitimate abbreviation of some vocabulary word. Clearly, the intended name should not be expanded to the vocabulary word in question.

This problem is solved by permitting some vocabulary verbs to be marked as "special" in that other words in the command are taken verbatim, as entered by the player (except for the case, which is always normalised to lower case). For historical reasons, instead of such special verbs being flagged individually, at present (A-code version 12) they are grouped in one block of verb declarations:

verb -first.special
[standard declarations of any special verbs]
verb -last.special

The '-' sign preceding "first.special" and "last.special" indicate that these are pseudo-verbs, not to be added to the game's vocabulary. This is an extention of the same convention in declaring object names.

To cater for any other instances in which abbreviation expansion is not wanted, setting the mandatory STATUS variable to the built-in value of NO.MATCH suppresses expansion for the duration of one command cycle.

As a further wrinkle, for object names, abbreviation matching is performed only if the object in question has been seen by the player. This prevents game secrets being inadvertently revealed by being too generous ni interpreting player's command.

See the document on command parsing for an explanation of A-code's response to ambiguous abbreviations.

Approximate matching

My typing is terrible. From seeing many player logs I know that I am not alone in this. That's why by default A-code features automatic approximate matching of words entered by the player against words in the game's vocabulary. If a single typo is sufficient to transform an unknown word type by the player into a unique (though possibly abbreviated) match in the vocabulary, that match is accepted as the player's command word. Here by a typo I mean a single character dropped, a single character interpolated, a single character substituted by another character or two adjacent characters swapped around. Thus, for example GET BOTTEL will be understood as GET BOTTLE.

Clearly enough, the same problems areise here as with abbreviation matchig. These are dealt with by the same mechanisms. No approximate matching in the following circumstances:

  • word declared as non-abbreviable
  • word accompanies a verb declared as "special"
  • word refers to an object not yet seen by the player
  • the STATUS variable is set to NO.MATCH or NO.AMATCH (duration one command cycle)

See the document on command parsing for a detailed explanation of A-code's responses to approximately matched commands.

Synonyms and sub-synonyms

Traditionally, IF game vocabulary is a 2D structure, consisting of list of lists of synonyms. Thus, for example, using A-code notation

verb get, take
verb drop, release

declares two vocabulary terms, both of which are denoted by two synonymous words. From version 10, A-code adds a third dimension: any individual word in the traditional structure may be associated with a list of sub-synonyms. For example, in Adv770 the full definitions of get and drop are as follows:

verb get, =g, =reach, carry, take, =t, pickup, keep, hold, catch, grab, =grip, clutch, steal, capture, tote, scoop
verb drop, =dr, =discard, =fall, =abandon, free, =release, =let

The '=' sign preceding a word indicates that word to be a sub-synonym of the last preceding word not prefixed with '='. So G and REACH are sub-synonyms of GET, but CARRY is not.

This additional vocabulary structure is motivated by my preference for responding to player commands rather more explicitly than is traditionally the case. Thus instead of the standard and rather mechanical "Taken." in response to GET CAGE, I like the game to respond with "You get the cage.". But there is a very obvious snag to this: G CAG should not result in "You g the cag."

While the expansion of "cag" to "cage" is handled by the abbreviation processing feature of the parser, "g" is declared explicitly as a vocabulary word, so does not get expanded as an abbreviation. If there were no other verbs beginning with g, it would not be necessary to include "g" as a verb synonym – the abbreviation processor would do the expanding, but that's not a realistic solution. Hence the declaration of "g" as a sub-synonym of "get", which instructs the A-code engine to echo the latter if the command verb is to be echoed.

Vocabulary listing

To my mind, one of the most irritating feature of many IF games is the need to guess what words may or may not be present in the game's vcabulary. A-code offers an intelligent way of making the vocabulary listing available to players, without revealing things players should not as yet know about. This is achieved by the minor directive VOCAB, which is a kind-of fancy wrapper around the SAY directive. In simple cases it is equivalent to

SAY "f:, #", {<OBJECT>|<PLACE>|<VERB>}

except that the leading comma and space are omitted for the first word in the list being produced. The full syntax of the VOCAB directive is as follows:

VOCAB {<OBJECT>|<PLACE>|<VERB>}, {<PLACE>}, {<FLAG>}, {<TEXT>}

The first argument is the vocabulary word to be conditionally included in a vocabulary listing. The second and the third arguments specify conditions under which the word is to bne included. The forth agrument specifies the text to be shown instead of the word given by the 1st argument.

Each of these arguments can be given as 0 (zero), in which case it is ignored.

As an example, here are some VOCAB commands from Adv770

vocab 0, 0, 0, voc.lead
A special form, signalling the beginning of a vocabulary listing in order to suppress the leading comma before the first word to be shown; in this example the 4th argment is not zero, so the voc.lead message will be also displayed.
vocab axe, 0, 0, 0
The word axe is shown unconditionally.
vocab alarm, 0, seen, 0
The word alarm is shown if the seen bit of the alarm object is set.
vocab bones, bones.room, been.here, 0
The word bones is shown if the player has been at the bones.room location. Note that the meaning of the 3rd argument is changed in this case to refer to a flag of the entity given by the 2nd argument.
vocab eggs, 0, seen, eggs.voc
The text eggs.voc (in this case "eggs (nest)") is shown if the object eggs has been seen.

In hind-sight, all this could be done more neatly and flexibly, and I may re-think the VOCAB syntax at some future time. The current syntax will, however, also remain supported.


To the A-code page
To the Mipmip home page
Feel free to leave a comment!
Mike Arnautov (25 December 2016)