A brief summary of A-code

## A brief summary of A-code, version 12 A-code is the adventure-writing language developed by Dave Platt for the adv550 superset of the original Adventure, and subsequently developed by Mike Arnautov, in working on the adv660 superset and later on the adv770 one. ## Contents Introduction A-code style and version numbering A note on conventions and notation Source file naming A-code program structure A-code lexicals Constants Variables Texts Procedures Places Objects Words (a.k.a. verbs, a.k.a. nouns) Types of declared elements Major A-code directives Pragmas Game info, a.k.a header directives Declarations Automatic and optional entities and flags Minor A-code directives (a.k.a. opcodes) Local variables Conditionals Logical operators Iteration Execution flow control Moving player and objects Generating and manipulating output Arithmetical operations Randomisation Refno manipulation Manipulating flags Communicating with the machine environment Saving and restoring (file, memory or command) Debugging tools Obsolete directives A-code history ## Introduction A-code is not intended to be a general purpose programming language and its strengths lie in being tailored specifically for programming purely text-based interactive fiction games. Each game created with the A-code system is a stand-alone package, requiring no separate game engine/interpreter. As an added bonus, with a little care it is possible to ensure that any game saves are upward compatible and thus can be used even after the game has been modified/extended (a feature of particular use in beta-testing!). The current implementation of the language has only been used for writing extensions of the original Adventure, and hence its parser is limited to dealing with commands which can be reduced to (a series of) verb/noun commands. (See a separate document on the current A-code parser.) On the positive side, that implementation is fully internationalised and allows games to be written in languages and character sets other than English/Latin. Technically, A-code is a Polish notation (i.e. "prefix", or "operator [argument [...]]") language, so its statements take the form of, e.g. "set door, oiled". The original version by Dave Platt was organised as a "munger", translating A-code source into tokenised pseudo-binary, and an interpreter, interpreting the pseudo-binary at run time. This was an economical arrangement, but as versions grew in size, its performance on a multi-user machine gradually became less satisfactory. (We are talking mid-80s here! :-)) This is why the current implementation of A-code takes a different route. It consists of an A-code to C translator (".acd -> .c" or just acdc!) and a C kernel which gets compiled and loaded with the translated code. The overall size of the program is larger, but the performance is very much better. Now that computer speeds have increased dramatically, it would probably make sense to replace this translation-based implementation with a virtual machine, akin to Platt's original implementation. ## A-code style and version numbering The current version of A-code departs in some significant ways from Platt's original version of the language, but maintains full backward compatibility with it. This is achieved by an optional explicit declaration via the STYLE directive of the major version number of A-code being use by game source. The significance of the major A-code version in save game compatibility. Style 1 is Dave Platt's original A-code of Adv550 Style 2 is Make Goetz's slightly different A-code of Adv580 Styles 3 to 9 were development stages of Mike Arnautov's Adv660 Style 10 is the A-code version of the finalised code of Adv660 Style 11 was for a while the A-code of Mike Arnautov's Adv770, until save game compatibility got broken by some technical developments. Style 12 is the current A-code of Adv770 If not explicitly declared, the default style is assumed to be the currently highest one supported by the A-code engine being used. ## A note on conventions and notation All A-code documentation uses the following notation: A-code statements are case insensitive. This documentation uses upper case except when providing code snippets – that is just to make such statements to stand out against other text. A-code lexical elements (tokens) are separated by spaces and/or commas. By convention, the operator (the first token) is separated from its arguments simply by a space (or several spaces), while its arguments are separated by commas followed by a space (or spaces). E.g. "APPORT BOTTLE, YLEM". Angled brackets (< and >) are used to denote a generic name or value, to be substituted for as appropriate. Thus, e.g., "SET <varname>, <value>" is a generic form of statements such as, e.g., "SET COUNT, 1". Square brackets ([ and ]) are used to indicate optional arguments. For example "LOCAL <varname1> [, <varname2> [...]] " indicates that more than one local variable can be declared in a single LOCAL statement. Ellipsis ([...] or just ...) as in the above example, is used to show that the preceding element can be repeated. Curly brackets ({ and }) are used to denote mandatory items permitting some alternatives, such as "SET <entity>, {<entity2>|<state>|<constant>}". The word "entity" is used as a collective noun for any declared elements, which are not mere synonyms for numerical constants. ## Source file naming. All A-code source file must have the mandatory suffix .acd. However, in using A-code tools or when using the A-code INCLUDE directive to include another source file, this suffix may be omitted – it will be automatically added by the software. ## A-code program structure. At the highest conceptual level, an A-code program falls into four distinct parts: Header statements giving game information, (optional) Declarations of game-specific constants, entities and procedures (also optional) Code to be executed once, on game's invocation (mandatory, but may be empty) The main code loop, usually prompting the player for commands, and processing those commands (mandatory) Thus the simplest A-code program looks like this:
    init    # There is actually no initial code
    repeat  # Main loop...
       stop # ... consisting simply of the instruction to terminate the game
And here is the obligatory Hello World code:
    init
       say "Hello world!"
    repeat
       stop
In practice it is often convenient to have more than one INIT and REPEAT sections, which are executed in the order of their declaration. Major (or declarative) directives fall into three categories: header ones, translator directives (or pragmas) and entity declarations. With a single exception, they can occur in any order. All major A-code directives (translator instructions and declarators) must start in column one. All other lines of A-code source must be offset from the beginning of the line by one or more tabs or spaces. Other source lines are either parts of declaration, or lines of code. The latter have the form of a minor directive (a.k.a. opcode), possibly followed by some arguments. Code line tokens are separated by commas and/or spaces. The convention of using comma-space separators is not mandatory. ## A-code lexical items A-code lexical items fall into three categories: Major directives (or opcodes) Minor directives (or opcodes) Ad hoc modifiers to minor directives Major directives come in three flavours: Header statements describing game name, author, date etc... Pragmas, which affect the way the game source is treated by any software processing it (e.g. an instruction to include a separate source file in place of the INCLUDE pragma). Declarations of game elements, such as location, objects, procedures etc. Forward declarations are allowed! That is, a game entity may be referenced before it is declared. Minor directives are, with one exception (the LOCAL opcode, declaring local variables of a procedure) instructions for performing some action (e.g. SET STATUS, 1) and are used to write A-code procedures. ## Types of declared elements Elements manipulated by A-code are variables, objects, places, texts, words, procedures, flags, states and constants. All declared elements are global in scope, except for local variables and procedure arguments, both of which are local to the relevant procedure. Some elements (specifically flags, states and constants) are merely synonyms for integer values. Procedures (or procs) are a category of their own. All other elements are entities in their own rights and are referred to collectively as entities in this document. In its current implementation, A-code makes no distinction between vocabulary verbs and nouns, allowing e.g. "cage" to be treated as either, depending on context. However, the basic form of a player command is verb optionally followed by a noun. Thus in the context of parsing player commands "verb" and "noun" will be used, referring respectively to the first and second words of player command. Any source line, which is not a part of a text or a place.object description is considered to be terminated by a hash (#) sign. Thus # can be used to provide comments, including in-line comments. (This convention holds for A-code version 10 and higher -- earlier versions had different convention for comments.) Declared element names are subject to these rules: All names are case-independent. Names may not contain blanks or other "white space" characters (such as tab, end-of-line etc.). Unless UTF8 encoding is being used, all names must start with an alpha character, a dot or a question mark. Unless UTF8 encoding is being used, The rest of the name characters may be any of: an alpha character, a digit, dot (.), dash (-), underscore (_) shriek (!), single quote ('), ampersand (&) and forward slash (/). All declared (or automatically declared) elements other than states, flags or constants are automatically assigned a "reference number", or refno for short. You do not need to worry about specific refnos, but it is useful to understand that (a) they exist and (b) how they are assigned. Refnos are assigned separately for each type of entity, consecutively in the order in which elements are declared in the source code. Thus e.g. objects will have consecutive refno value, even if their declaration is interspersed with declarations of other entities. Refnos can be thought of as "addresses" of relevant entities and, indeed, can be used as such. Unlike other entities, texts can be declared nameless. Such texts can be accessed and manipulated via refno offsets from the nearest preceding named text. (Note, however, that this feature is deprecated in favour of using text switches.) In-line texts are also permitted. See the A-code texts description later in this document. Entities other than vocabulary words also have attributes other than their assigned refnos. They have a value (a short integer) and a bit-screen of binary flags. Objects, places and texts have further attributes appropriate to their type. These will be covered when describing declarations of such entities. All entity values are automatically initialised to zero and all flags are automatically set to false on program start-up. Places and vocabulary words can have (and generally do) have procedures associated with them via the AT and ACTION major directives (see below). ### Flags Flags are binary yes/no properties (bits in entity bitscreen), referred to by symbolic names. A flag's value is simply a bit-screen offset. There are three separate categories of flags. One is defined for objects, one for places and one for variables. Each entity has its own instance of the appropriate kind of a flag set. There are no limits on the number of flags in a flag set. Even within a given set, each individual flag can have several different names, allowing for the greater legibility of the source. Since alternative names are usually required for variable flags, several different variable flag sets can be defined (as opposed to only one for each the object and the place flag sets). The actual variable flag set is simply the biggest of these, with individual flags having synonymous names as defined in different set definitions. Don't worry if this makes little sense - it will eventually. ### Constants A-code constants come in several flavours, but fall into two simple types: numerical (integer values only) and symbolic. Where a integer value has been given a symbolic name, this can be used interchangeably with the actual value it names. The various constant flavours are: Numerical integer values (signed short integers) Symbolic names of such values, declared as CONSTANT for ease of reading game sources. Some entities (places, objects, variables and texts) each have a state (a.k.a. value) associated with them. These can be named by using STATE declarations. The only difference between a state and a symbolic constant is that the former cannot be negative. Some entities (namely objects, places and variables), also carry a bitscreen of binary flags. Symbolic names should be given to individual flags via FLAGS declaration – these are effectively just symbolic names for bitscreen offsets (necessarily non-negative). Flag names differ from state names in some important ways. Firstly, there can be only one set of flags associated with locations, whereas a number of multiple flag sets can be declared for objects and variables. Secondly, the distinction between object, place and variable flag sets is used as part of syntax checks. Thirdly, the system uses flag declarations to work out sizes of bitscreen required respectively by objects, places and variables. Finally, there are compound constants. These are deprecated. See the deprecated features section for a brief explanation. ### Variables Variables are symbolically named entities, each with a state and an instance of the variable flag set. There are some mandatory variables (e.g. HERE, see below), but any number of additional variables can be declared by the programmer. Words entered on the command line are available through the special mandatory variables ARG1 and ARG2 (and ARG3, currently used for handling of EXCEPT, but available for a future parser use of holding command instrument). This generally restricts A-code to simple verb/noun commands, even though the parser makes this less then obvious, permitting apparently complex commands such as e.g. DROP ALL BUT LAMP AND ROD THEN EXIT (see a separate document for an explanation of the way player commands get parsed). It is important to understand that the ARGn variables are unlike any others. They have the appropriate player command word associated with them regardless of the actual variable value (unless the value is -1, meaning "no word"). This makes error handling possible, because variable value can be sat by the parser to an appropriate error code, while embedding the variable in a text to be displayed, actually embeds the corresponding command word. A special form of variable declaration is an array. In A-code this has a very limited, simple meaning: declaring an array of n elements declares a variable of the given name, followed by n-1 anonymous variables. (See below on handling of anonymous entities). An automatic indirection occurs for some A-code directives when manipulating variables into which "addresses" (refnos) of other entities have been loaded. Generally speaking this happens for non-arithmetical manipulation of variables. ### Texts Texts are named, nameless, or in-line entities representing a piece of text. Any amount of text can be associated with a text entity. Generally multi-line texts are considered to be unformatted, line wrapping and filling being done by the A-code kernel at run time. However, A-code texts are more than just textual strings. A separate document gives their full description. ### Procedures A-code procedures are unusual in that there can be any number of procedures sharing the same name. Such procedure groups are executed in the order of their occurrence in the source (i.e. in the order of their refnos). Procedures come in 5 varieties: Initialising ones, declared as INIT. These form a procedure group, which gets executed on game startup. Main loop, declared as REPEAT. These form a procedure group executed repeatedly after the INIT procedure group execution is completed. "Free-standing" declared as PROC (or PROCEDURE). These procedures are all named. Procedure arguments (if any) are specified on the declaration line after the procedure's name. If two or more form an identically named procedure group, they must all have the same number of arguments. Associated with a place and declared as AT (as in "at such-and-such-place"). Their names are in fact names of relevant locations. No arguments are allowed. Associated with a vocabulary word and declared as ACTION. The name of such a procedure is the vocabulary word in question (or equivalently, any of its synonyms). Arguments are allowed and, perhaps surprisingly, procedures in the same procedure group will have different arguments and even different number of arguments. See the minor directive ACTION below for details. ### Places Places are symbolically named entities, each with a state, an instance of the place flag set, up to three different unnamed texts (brief, long and detailed descriptions) and a "hook" for unnamed chunks of A-code to be associated with the place. By default symbolic place names are not available in the player vocabulary, but each such name can be specifically forced into the vocabulary by prefixing the name in the place declaration with a plus sign (+). Any number of synonyms can be defined for a place name, though of course, there is no point doing this unless such names are forced into the player vocabulary. All properties of texts (described above) apply to place descriptions. ### Objects Objects are also individually named (with any number of synonymous names) and once again, have to their name a state and an instance of the object flag set each, plus up to three different descriptions (inventory, long and detailed), but no A-code. Object descriptions also obey the rules common to any kind of text. Object names (and synonyms) do get entered into the player vocabulary by default, but it is possible to exclude any specific object name by prefixing the object name in its declaration with a minus sign (-). ### Words (a.k.a. verbs, a.k.a. nouns) Words have symbolic names (with synonyms) and each is associated with one or more chunks of A-code. By default, verb names are added to the vocabulary, but again, any specific name can be excluded. It is sometimes useful to have "dummy" verbs for internal house-keeping, but not available to the player. This is again achieved by prefixing the verb name with a -, in the verb declaration. As noted above, some of the entity names are automatically or selectively added to the player vocabulary. To summarise, vocabulary words consist of: all explicitly defined words/verbs/nouns and their synonyms, all object names and their synonyms not explicitly excluded and some those place names which are explicitly included. A separate document gives a full description of A-code vocabulary. ## Major A-code directives Major directives are either declarations or translator instructions. They must start in the first column of a line – that's how they are recognised in the first place, since everything else must be indented. The indentation depth is arbitrary – the convention of 9 leading spaces and subsequent indents of three spaces at a time is not mandatory. ### Pragmas Firstly, there are two major directives, which are in fact translator instructions: INCLUDE <file> read commands from indicated file until end of file, then revert to reading from the previous file. Include files may be nested down to 10 levels. INCLUDE? <file> conditional include – includes the file if it exists. If it does not exist, this directive is simply ignored. Given the fact that A-code permits forward declarations and supports procedure groups, this pragma can be used for optional addition of new commands or modification of existing commands – a feature used extensively by Adv770 to provide the optional Wizard (debug) mode. ### Game info, a.k.a header directives Secondly, there are six game information directives, all of them optional. NAME <game-name> names the game (a.g. adv770). If not specified, the game's name is taken to be the name of the file given to the acdc translator, less the .acd suffix. VERSION <version> specifies game's version. Traditionally this has the format of two numbers (major and minor versions) separated by a dot (.), however, this format is not enforced. If omitted, the current year is used as the game's version. DATE <date> gives a free-format specification of the date of this version of the game. AUTHOR <author-name> name the game's author (also free format). STYLE <style> specifies the A-code style, i.e. the major version number of A-code in which the game is written. If used, directive must precede any non-header directives. If omitted, style is set to the major version of the acdc translator used to convert the game's A-code source into ANSI C. Style 1 is reserved for Dave Platt's original code of Adv550. Style 2 is similarly reserved to Mike Goetz's Adv580 (an expansion of Adv550). Styles 3 to 9 are not in use. Style 10 is reserved for Adv660. UTF8 signals use of the UTF8 character encoding in the game's A-code source. This directive is only required if the game uses UTF8 characters in its entity names or vocabulary words. It is not (and never was) required if use of such characters is restricted to games texts and objects/place descriptions. (There are also a couple of header directives (GAMEID and DBNAME) which are obsolete and only supported in style 10, i.e. in Adv660.) ### Declarations The remaining major directives are all declarators. Other than the flags, states and constants, all declared entities are associated with a "reference number" (refno) and are internally referenced by A-code only by this number. The reference numbers of entities of the same kind (e.g. objects, places, texts, variables...) are guaranteed to be lumped together into an unbroken numerical interval, with their reference numbers incrementing by one in the order in which the entities are declared. To reiterate: within each declarative category (e.g. objects, places, texts) entities are stored sequentially in the order of declaration and hence can be referenced via refnos by numerical offsets from other entities. It is not necessary for the game author to be aware of the reference numbers of declared entities, but it is helpful to be aware of this arrangement in general terms. Reference numbers are used to achieve indirection in A-code. They can be loaded into variables, which are then recognised by most opcodes as "indirectors" so that the opcode is actually applied to the entity whose reference number the variable stores. This does not apply to arithmetical opcodes, making it possible to do "reference number arithmetic". This allows, for example, referencing nameless texts by offsets from other named texts, and has other uses too. It is not necessary to know the "reference number" of an entity, in order to load it into a variable. FLAGS {VARIABLE|OBJECT|PLACE} starts the declaration of a flag set of the appropriate kind (variable, object or place). It is followed by any number of indented lines, each declaring a symbolically named flag in the set, optionally followed on the same line by synonymous names. Only one object and place set declarations are permitted, but any number of variable set declarations are allowed. (They are equivalent to a single declaration with flags declared on corresponding lines being synonymous with each other). STATE [value] statename [...] is used to declare symbolic names for entity states. It makes "statename" synonymous with the value preceding it, or with zero, if the value is absent. A STATE directive can be followed by any number of indented lines of the format " [value] statename", which declare further state names to be synonymous with the corresponding value, if given, or with the value of "statename" defined on the preceding line plus 1. Note that the STATE directive deliberately does not specify which entities the defined statenames relate to, allowing for partial state sequences to be shared by different entities. "Value" can be a number, a previously declared constant, a previously declared entity (in which case the "reference number" of the entity is used) or several such, combined into a simple expressions with plus (+) and/or minus(-) signs, without any separating blanks. CONSTANT [value] constname [...] This directive is in fact exactly synonymous with the STATE directive. It is used simply to indicate that the symbolic constants being defined are general purpose constant and not entity state names. The two are completely interchangeable. TEXT [textname] declares a piece of text, which may be associated with a text name or be "anonymous" (available only by offset from some named text). The TEXT directive is followed by one or more lines of text, which must not start in column 1 (anything starting in column 1 is taken to be a major directive -- it follows, that all leading spaces are ignored). A-code texts are very rich entities. Please see a separate document for details. FRAGMENT textname Identical to the TEXT directive, except that the text is not terminated by a new line. I.e. it is a text fragment. PLACE [+]placename [...] declares a location. By default, "placename" is not entered into the player vocabulary, unless prefixed with a '+' (which does not count as a part of the name). Synonymous names can be declared on the same line. Each location declaration is optionally followed by a piece of text (following all the text rules described above), comprising up to three different descriptions – the brief one, the full one and the detailed one – and terminated by a major directive. Insofar as these three description components occur – they occur in that particular order. The brief description (if any) immediately follows the PLACE line and is terminated by a text line starting with a '%', '&' or a major directive. The full description (if any) starts with a line beginning with '%' and is terminated by a line beginning with a '&' or by the next major directive. The detailed description (if any) starts with a line beginning with a '&' and is terminated by the next major directive. If the full description is missing and the brief one is present, the full one defaults to the brief one. If the detailed description is missing, it defaults to the full one, if that is present, or to the brief one, if the full one is absent and the brief one present. It is possible for a location to have no description at all. The '%' and '&' delimiters are not themselves considered to be a part of the description. If a text switch is encountered in a description being displayed, the current state of the location is used as the switch qualifier. All special trickery described under the TEXT directive applies to place descriptions as well. OBJECT [-]objname [[=]objname ...] declares an object. By default, "objname" is entered into the player vocabulary, unless prefixed with a '-' (which does not count as a part of the name). Synonymous names can be declared on the same line. These can be prefixed with a '=', indicating their re-mapping to the last synonym not so prefixed. Each object declaration is optionally followed by a piece of text (following all the text rules described above), comprising up to three different descriptions – the inventory one, the full one and the detailed one - and terminated by a major directive. Insofar as these three description components occur – they occur in that particular order. The inventory description (if any) immediately follows the PLACE line and is terminated by a text line starting with a '%', '&' or a major directive. The full description (if any) starts with a line beginning with '%' and is terminated by a line beginning with a '&' or by the next major directive. The detailed description (if any) starts with a line beginning with a '&' and is terminated by the next major directive. If the full description is missing and the inventory one is present, the full one defaults to the inventory one. If the detailed description is missing, it defaults to the full one, if that is present, or to the inventory one, if the full one is absent and the inventory one present. It is possible for an object to have no description at all. The '%' and '&' delimiters are not themselves considered to be a part of the description. If a text switch is encountered in a description being displayed, the current state of the object is used as the switch qualifier. All special trickery described under the TEXT directive applies to object descriptions as well. NOISE word [...] NOISE declares words to be ignored when parsing player's input. VERB [-]verbname [synonyms] Declares a word "verbname" (optionally with synonyms), which is (by default) entered into the vocabulary available to the player. The optional minus sign prefixing the principal verb word stops the verb being available in the vocabulary – such dummy verbs are chiefly used for range checking within the vocabulary and bracket groups of verbs of a similar kind (e.g. movement directions). VERB is currently synonymous with NOUN and WORD. Adjectives and prepositions are not currently supported. Distinction between different word types are up to the game's code. ACTION verb [objname] The major directive ACTION is used to associate chunks of A-code (procedures) with individual verbs. More than one procedure can be assigned to the same verb and they are executed in the order of their declaration. If the optional object name is given, that particular action procedure is skipped, unless the object in question features in player's command. VARIABLE variable [...] defines one or more variables. Note that variables defined on one line like this are not synonymous. By convention, related variables tend to be defined in a single VARIABLE directive. ARRAY arrayname constant defines a consecutive block of variables of the size given by the constant. The first of these is named by the array name, the rest are anonymous – accessible only via refno offsets from the array's base PROC procname [arg ... ] defines a chunk of A-code (a set of executable code) called "procname". The procname can be followed by a list of arguments, which are passed by value when the procedure is called. The subsequent lines contain the code, terminated by the next major directive. AT placename defines code to be executed when the player is at the indicated place - the following lines contain the actual code. More than one AT procedure may be defined for a particular place – they are executed in the order in which they are declared in the A-code source. INITIAL defines once-only code to be executed at initialisation time. Multiple INITIAL commands may be used and are executed in the order encountered. REPEAT defines the main action-processing code that is executed during each player input. After the INITIAL code has been executed, the REPEAT statements are executed. Once the last REPEAT statement is executed, the program loops back and starts again with the first. Each of the above "major directives" must appear in column 1. A major directive embraces all following lines up to but not including the next major directive statement (i.e., all lines in which column 1 is blank) or the end of the source file in which it occurs. ## Special entities and flags Not all entities or flags need to be declared explicitly. Some are "automatic" and some are "optional" "Automatic" means that the entity is declared automatically. Automatic entities may be explicitly declared by the program, but if so, must be of the correct type. If an entity of that name is declared as some other type, this is treated as a compilation/translation error. "Optional" means that the entity may but need not be declared by the program. If declared, it has a special meaning. An entity of that name but of a different type is treated as a compilation/translation error. INHAND automatic location Use: contains all objects currently carried by the player; contents are maintained by the kernel but can be also accessed and modified by the game's code. STATUS – automatic variable Use: set by the kernel to indicate the number of words in the player's latest command. Can be set by the program to various values in order to pass information to the kernel. Possible values: BADSYNTAX – automatic state Use: set by the kernel if the current player command cannot be parsed. NO.MATCH – automatic state Use: set by the program to indicate that no abbreviation or approximate matching is to be performed on the next player command. NO.AMATCH – automatic state Use: set by the program to indicate that no approximate matching is to be performed on the next player command. value -1 Use: set by the kernel to signal game restore on start-up. Flags: MOVED – optional flag Use: set by the kernel whenever player's location changes. JUGGLED – optional flag Use: set by the kernel if player's inventory has changed. PLS.CLARIFY – optional flag Use: set by the game's code in order to trigger orphan processing of next player input; cleared by the kernel as a part of orphan processing. (See the description of the A-code parser for an explanation of orphan processing of commands.) HERE – automatic variable Use: set by the kernel to the refno of the player's current location. THERE – automatic variable Use: set by the kernel on a change to player's location to the refno of the location prior to the change. ARG1 – automatic variable Use: set by the kernel to the refno of the player command's verb Possible values: BADWORD – automatic state Use: set by the kernel if the word is not understood. AMBIGWORD – automatic state Use: set by the kernel if the player's word can be an abbreviation of more than one vocabulary word. AMBIGTYPO – automatic state Use: set by the kernel if the player's word can be matched as a typo in more than one way SCENEWORD – automatic state Use: set by the kernel if the player's word is not found in the vocabulary but matches a word (in excess of three characters) in the latest location description or in a text displayed since the last move. ARG2 – automatic variable Use: set by the kernel to the refno of the player's noun (if any) or zero otherwise. States: (as ARG1) ARG3 – automatic variable Use: At present used solely for EXCEPT processing. If player's command is of the form "<verb> ALL EXCEPT <list>", ARG3 may be set by the kernel to BADWORD, AMBIGWORD or AMBIGTYPO, if appropriate. CONTEXT – optional variable Use: avoid use of the QUERY minor directive in game builds which require single-turn operation (see a separate document on A-code game build modes). Value: If non-zero, indicates the current command to be a response to a query, the value (as set by the program) indicating the nature of the query. Flags: PROMPTED – automatic flag Use: set by the kernel if the player has been prompted. ENTNAME – optional variable Use: when processed by the SAY directive, shows the symbolic name of the entity to which ENTNAME is set to point. Value: a pointer to a named entity set by game's code. Use of ENTNAME has the side-effect of stopping the dot character ('.') acting as a command separator, permitting reference to entity names containing this character, The variable is intended for game debugging in the wizard mode. See a separate section on debugging A-code games. TYPO – optional text Use: enables single-typo matching of player commands against the games vocabulary. The TYPO text must contain a switch of 4 (or a multiple of four) components. It is used by the kernel to explain a typo match to the player. Regardless of the number of components, it must be declared as
    FRAGMENT CYCLE TYPO
The first three components in each foursome must contain one word holder (#). The four switch components (in any of the switch quads if there are more than 4 components) are used by the kernel as follows: Shows original player word that got typo-corrected Shows the typo-corrected version for what the player gave Shows the full non-abbreviated matched word if typo-corrected version is an abbreviation. States that the corrected version is assumed Here is an example from Adv770:
    FRAGMENT cycle TYPO
        [Sorry, the word "#" is not familiar to me./ I'll just assume you
        meant "#"/, i.e. "#"/./
        Regretfully, I don't have "#" in my dictionary./ But I do know
        "#"/, as in "#"/, so I'll assume you meant that./
        The word "#" is not one I know./ Let's assume you meant "#"/,
        meaning "#"/./
        I wonder what "#" might be.../ I guess it could be mistyped
        "#"/, i.e. "#"/, so I'll assume that was what you meant.]
UNDO and REDO optional verbs. Use: Their presence activates the A-code undo/redo facility, enabling players to undo a specified number of last commands and, if necessary, undo some or all of this undoing. This is described in a separate document dealing with undo/redo. UNDO.STATUS – optional variable Use: set by the kernel to indicate the number of commands undone or re-done, which need not be the number requested by the player. UNDO.INFO – automatic flag Use: Can be used by game code to note that player has been advised of rules for using undo; set to off by default and ignored by the kernel. UNDO.TRIM – automatic flag Use: maintained by the kernel: if set, the level of undo/redo was found to be excessive and had to be trimmed to match the existing undo history. UNDO.INV – automatic flag Use: maintained by the kernel: if set, the player's inventory has changed as the result of undo/redo. UNDO.BAD – automatic flag Use: maintained by the kernel: if set, undo/redo failed. DWARVEN – optional variable Use: If set to non-zero, all text output by the game is shifted circularly one position up in the alphabet and all player input is shifted one position down. If set to zero, any portion of game text delimited by % signs is output shifted one position up. PROMPT – reserved optional variable Use: none at present. Reserved for specifying non-standard prompt. SCHIZOID an automatic object flag Use: Indicates that the object is to be treated as present in its current location, and also in the immediately succeeding one (i.e. the one with the refno one higher). ## Minor A-code directives (a.k.a. opcodes) The actual A-code code consist of minor directives (or opcodes) followed by their arguments (if any). A line of code cannot have more than a single opcode line. The following is a list of the available opcodes and a quickie description of what they do. As noted previously, in some cases if an argument is a variable, it is automatically de-referenced – i.e. the operation indicated by the opcode is applied not to the argument but to the entity referenced by the argument. Any such opcode arguments are denoted by a trailing asterisk in the following summaries. ### Local variables LOCAL varname [varname...] Declares correspondingly named variables local to a procedure. It must immediately follow either the major directive declaring the procedure in question, or another LOCAL declaration. Local names pre-empt any identically named global variables. Local variables are dynamically initialised to zero value and zero bitscreen whenever the procedure is entered. They do not exist outside the procedure. Local variables are not a part of the data set saved/restored by saving or restoring a game image. Thus they can be used to preserve some values over a game restore, instead of using the (now obsolete) EXEC 6 and EXEC 7. ### Conditionals All conditional structures have the basic form of conditional, some code, FIN conditional, some code, ELSE, some code FIN where the immediately following block of code is executed if the conditional is true, and the block following ELSE (if present) is executed if it is false. In order to avoid deeply nested indentation in source code, A-code also features OTHERWISE, analogous to C's "else if" or Perl's elsif. Thus
       some condition
          some code
       ELSE
          some condition
             some code
          ELSE
             some condition
                some code
             FIN
          FIN
       FIN
can be equivalently written as
       some condition
          some code
       OTHERWISE
       some condition
          some code
       OTHERWISE
       some condition
          some code
       FIN
The following conditionals are available: (A quick reminder: the value of a place or an object, is its state; however, variables (local or global) can be "pointers", i.e. have the refno of some entity is loaded into them. In the below, variables, which are in fact pointers are represented as "varname*".) value of a variable is either just that value or (if indirection is indicated IFEQ {entname1|const1}, {entname2|const2} True if the value of the first argument is equal to the value of the second argument. IFNE {entname1|const1}, {entname2|const2} True if the value of the first argument is not equal to the value of the second argument. IFLT {entname1|const1}, {entname2|const2} True if the value of the first argument is less then the value of the second argument. IFLE {entname1|const1}, {entname2|const2} True if the value of the first argument is less then or equal to the value of the second argument. IFGT {entname1|const1}, {entname2|const2} True if the value of the first argument is greater than the value of the second argument. IFINRANGE {entname|constant} {entname|constant} {entname|constant} True if the value of the first argument is greater or equal to that of the second argument, but less or equal to the value of the third one. CHANCE {entname|constant} True with the probability of n%, where 'n' is the value of the argument. IFHAVE {objname|varname}* [{state|flagname}] True if the player is holding the specified object. If the second argument is supplied, the object also has to be in the specified state or have the specified flag set. e.g. if THING is a variable,
       LDA THING, BOTTLE
       IFHAVE THING
will be true if and only if the bottle is in the player's inventory. Of course,
       IFHAVE BOTTLE
  will have the same effect in this particular example. IFHERE {objname|varname*} [{state|flagname}] True if the specified object is at the same location as the player. If the second argument is supplied, the object also has to be in the specified state or have the specified flag set. IFNEAR {objname|varname}* [{state|flagname}] True if the specified object is held by the player or is in the same location as the player. If the second argument is supplied, the object also has to be in the specified state or have the specified flag set. IFFLAG {entname|varname*} flagname True if the specified entity has the corresponding flag set. If a flagless entity is specified, the test returns FALSE. IFAT {placename|varname*} [...] True if the player is currently at the one of the specified locations. IFLOC {objname|varname1}*, {placename|varname2*} [...] True if the object specified by the first argument is at one of the the specified locations. IFIS varname, {objname|placename|varname*} [...] True if the named variable is a pointer to one of the specified objects or locations. IFKEY word [word] True if all specified words appear in the player's command. IFANY word [word...] True if any of the nominated words appear in the player's command. QUERY {textname|varname*} Displays the nominated text, which should be a yes/no question, and gets player response. Set to true if the answer is yes and false otherwise. CAUTION this directive is incompatible with library and single-turn modes (and thus incompatible with the HTML/JavaScript build, which uses the library mode). If such modes are to be supported, use the CONTEXT variable mechanism instead. IFHTML True if the game is running in a mode in which its output is formatted as HTML. IFCGI True if the game is running in a cloud via a CGI interface. IFDOALL True if the game is processing a DOALL command loop. IFTYPED True if the player actually typed the string given as an argument, as one of the command words. Thus for example
         IFTYPED W
  will be true only if the player typed W rather than WEST, even though W is interpreted as WEST. IFNEEDCMD True if there are no more pending simple commands to process, i.e. the player is about to be prompted for a new command. This is useful e.g. to avoid interrupting processing of a compound command with a spontaneous offer of help. ### Logical operators Now for some logical operators, to string the tests together, creating "compound" conditions. Note that tests are executed in the order in which they are encountered, with no precedence rules for operators and no bracketing. So, conceptually, A and B or C and D is understood as ((A and B) or C) and D. This may be unusual, but is, in fact surprisingly natural (or at least I found it so :-)). AND "And" the test results so far with the following test. OR "Or" the test results so far with the following test. XOR "Xor" the test results so far with the following test. NOT Invert immediately following test. Logically enough, here are delimiters for conditional code. ELSE Execute the following code, up to the next FIN, if the latest (compound) condition returned false. OTHERWISE An equivalent of "else if" in C or elsif in Perl. Useful for avoiding deeply nested if-then-else constructs. FIN Delimits the code associated with the most recent (compound) condition. Can be used interchangeably with EOI. ### Iteration Next come the opcodes to do with iteration. ITOBJ varname [{placename|varname*}] [objflag] Execute the following code up to the matching FIN repeatedly, with the value of the nominated "loop variable" becoming a reference to objects satisfying the optional location and/of flag/state constraints (or all object, if no constraints specified) in the order of their declaration. ITPLACE varname [{placename1|varname1*}, {placename2|varname2*}] Execute the following code up to the matching FIN repeatedly, with the value of the nominated "loop variable" running through the specified range of locations (default all declared locations) in the order of their declaration. ITERATE varname, {entname1|varname1*|const1}, {entname2|varname2*|const2} Execute the following code up to the matching FIN repeatedly, with the value of the nominated "loop variable" running through all values from entname1 to entname2 inclusive. If either of the two range delimiting entnames is a variable, its value is used as the appropriate loop boundary (this may but need not be the reference number of some other entity). If either is a constant, the value of the constant is used. Otherwise the reference number of the nominated entity is used. NEXT CONTINUE Skip the rest of the iteration block and proceed with the next iteration loop. BREAK LAST Break out of the innermost iteration block. DOALL [{placename|varname*}] [objflag] DOALL starts off a do-all loop, in which the REPEAT cycle is repeated, but instead of querying the player for input, input is constructed out of the verb in ARG1 and the next object fitting the specified criteria. The loop is terminated either when no more objects fit the criteria or when the FLUSH directive is executed. FLUSH Abort the do-all loop if one executing and flush the command line buffer ### Execution flow control CALL {procname|placename|verbname|varname*} Execute code associated with the named entity, which may consist of one or more separate, identically named chunks of code. These are executed in the order of their declaration, until either none left or one of RETURN, QUIT or QUIT-implying opcodes is executed in one of them. PROCEED Terminate the execution of the current procedure. If the procedure is one of a group of procedures of the same name, the next procedure in the sequence (in the order of declaration) is executed. RETURN Terminates the execution of the current procedure and of all procedures within the group of procedures of the same name QUIT Abort execution of the current procedure and restart the REPEAT loop at the first REPEAT procedure. STOP Terminate the whole program immediately. ### Moving player and objects APPORT {objname|varname*} {placename|varname2*} Transport the indicated object to the indicated location. GET {objname|varname*} Transport the indicated object into the player's hands. Equivalent to "APPORT {objname|varname*}, INHAND". DROP objname* Transport the indicated object (presumed to be in player's hands (location INHAND) to the same location as the player). Equivalent to
         IFAT {objname|varname*}, INHAND
           APPORT {objname|varname*} HERE
         FIN
  GOTO {placename|varname*} Transport player to the indicated location. MOVE [word [...]] {placename|varname*} If no word list supplied or if any of the supplied words appear in the player's command, transport the player to the indicated location and restart the main loop (the REPEAT loop).Equivalent to (if a word list is present)
         IFANY [word [...]]
            GOTO {placename|varname*}
            QUIT
         FIN
  SMOVE [word [...]] {placename|varname1*} {textname|varname2*} If no word list supplied or if any of the supplied words appear in the player's command, transport the player to the indicated location and display the indicated text, then restart the main loop. If a word list is present, equivalent to
         IFANY [word [...]]
            SAY {textname|varname1*}
            GOTO {placename|varname2*}
            QUIT
         FIN
  ### Generating and manipulating output There are several directives for producing text output. All of them can be "qualified" for the purposes of "#" and "$" substitution and/or of the text switch mechanism. The VALUE qualifier is mandatory, but both SAY and QUIP can be used with a single argument. If the argument is an object or a place (possibly indirectly pointed to through a variable), the current state value of the object or place is used as the implicit qualifier. See a separate document for a full explanation of A-code texts. SAY {entname|varname*} [{entname|constant}] Display text associated with the specified entity (text, object, place or any of these indirected through a variable), possibly modifying the text with the value of the qualifying entity/constant; any embedded # signs are replaced by the name of the qualifying entity and embedded $ signs with its value, while text switches are governed by qualifier's value. RESAY {entname|varname*} [{entname|constant}] Just like SAY, except that any text accumulated but not yet displayed is discarded first. QUIP {entname|varname*} [{entname2|constant}] Like SAY, but perform a QUIT having output the text RESPOND word [word [...]] {entname|varname*} [{entname2|constant}] Like QUIP, but null effect unless one of the listed words is present in the player's command. APPEND {entname|varname*} [{entname|constant}] Like SAY, but it first eliminates any trailing line feeds (if any) in the output accumulated so far and replaces them with a single blank. That is, it appends its text to the preceding paragraph. DESCRIBE {placename|objname|varname*} Outputs the long description of the indicated object or location. VOCAB {objname|placename} [flagname] [textname] VOCAB word {objname|placename} flagname [textname] VOCAB [textname] Used for displaying context-sensitive vocabulary. The first of the above three formats displays either primary name of the object or place in question, or the text specified as the last argument, unless the flagname argument is present and the flag in question is not set for that object or place. For example:
         VOCAB CAGE, SEEN
         VOCAB DWARF, SEEN, DWARF.VOC
  The second format applies to words which are neither places nor objects, but their listing should be regulated by a flag setting of some object or place. For example:
         VOCAB CHASM, SW.OF.CHASM, BEEN.HERE
The display, if any, is prefixed with a comma and a space, except for the first word displayed. The count of words displayed is reset to zero by a VOCAB directive with no arguments or with just the textname argument. TIE textname [textname2...] [entname|textname] Ties the value of the text (or texts) to that of the indicated entity or text. (See the A-code texts documentation for an explanation of text values.) The effect is that the value(s) of text(s) being tied are automatically kept in step with the value of the entity or text given as the last argument. ### Arithmetical operations SET entname {entname|constant} Set the value of the entity given as the first argument, to the value of the constant or entity given as the second argument. Note that no indirection occurs with this opcode. If the first argument is an "indirector" variable, SETting it reverts it to an ordinary variable. Use the DEPOSIT opcode to SET with indirection. ADD entname {entname|constant} Increase the value of the entity supplied as the first argument, by the value of the constant or entity supplied as the second. Note, that no indirection takes place! SUB entname {entname|constant} Decrease the value of the entity supplied as the first argument, by the value of the constant or entity supplied as the second. Note, that no indirection takes place! MULTIPLY entname {entname|constant} Set the value of the nominated entity to its original value multiplied by the value of the second argument. Note, that no indirection takes place! DIVIDE entname {entname|constant} Set the value of the nominated entity to its original value divided by the value of the second argument. Note, that no indirection takes place! INTERSECT entname {entname|constant} Set the value of the nominated entity to the bit-wise "and" of its original value and the value of the second argument. Note that no indirection takes place! NEGATE entname Set the value of the nominated entity to its original value negated. Note, that no indirection takes place! ### Randomisation RANDOM entname {entname|constant} Set the value of the entity indicated by the first argument to an integer chosen randomly from the interval between zero (inclusive) and the value of the entity or constant given as the second argument (exclusive). E.g. RANDOM CLOCK 10 will set the value of CLOCK at random to an integer number from 0 to 9. Note that no indirection takes place. RANDSEL varname, entname1, entname2, [...] RANDSELECT varname, entname1, entname2, [...] Selects at random (i.e. with equal probability) one of the listed entities and makes its first argument into a pointer to that entity. CHOOSE entnam {entnam2|constant2} {entnam3|constant3} Set the value of the entity indicated by the first argument to a random integer from the interval indicated by the second and the third arguments. If these latter arguments are both constants or variables, their values are used to determine the interval boundaries. However, for any entities other than variables, the reference numbers of the two entities are used instead. The randomisation is inclusive of the interval boundary values. E.g. CHOOSE VAR1 20 29 will set the value of VAR1 to a random integer between 20 and 29 inclusive, while CHOOSE VAR1 FIRST.QUIP, LAST.QUIP (where the two "quips" are not variables but text names) will load into VAR1 the reference number of an entity (text in this case) randomly chosen from between FIRST.QUIP and LAST.QUIP inclusive (there may well be some unnamed texts between these two). RANDOMISE {objname|placename}, constant Set state of the object or place to a random value between the base lower bound indicated by the constant (usually 0), and the highest numbered text switch component in any of the object's or location's description. ### Refno manipulation LDA varname, entname Make the variable specified by the first argument "indirect" to to entity specified by the second. EVAL varname varname Set the value of the variable specified by the first argument to the value of the entity "indirected" through the second argument. Please note that no check is made to verify that the second argument "indirects" anything meaningful. DEPOSIT varname {varname|constant} Set the value of the entity "indirected" by the first argument to the value specified by the second. Note that no check is made whether the first argument truly indirects to some other entity. LOCATE varname objname* Make the indicated variable into an "indirector" for the location currently holding the indicated object. ### Manipulating flags FLAG entname flagname Switch on the flag identified by "flagname" in the instance of the appropriate flag set belonging to the indicated entity. UNFLAG entname flagname Switch off the flag identified by "flagname" in the instance of the appropriate flag set belonging to the indicated entity. ### Communicating with the machine environment EXEC {varname|constant}, varname Perform a special action, indicated by the value of the first argument, and return the result in the value of the variable given as the second argument. This opcode is to do awkward things, which are not allowed for in A-code opcode definitions or are far easier done in C than in A-code. All these special actions are performed in the adv00.c procedure special(). As supplied the following actions can be selected by the appropriate value of the first argument: the value dump game to disc (obsolete – use SAVE FILE instead) restore game from disc (obsolete – use RESTORE FILE) delete saved game(obsolete – use DELETE FILE) Obsolete – Adv550 legacy only (flush game cache) Obsolete – Adv550 legacy only (get prime time flag) save value of a variable (obsolete – use local variables instead) restore value of a variable (obsolete – use local variables instead) get number of minutes since restored game saved set the value (pointer!) of ARG1 set the value (pointer!) of ARG2 pretend player said "X X" instead of "X" check for end of player's (possibly compound) command (obsolete – use IFHAVECMD instead) (spare) retrieve a persistent data flag (should be part of IFFLAG?) store a persistent data flag (should be part of FLAG?) delete a persistent data flag (should be part of UNFLAG?) save current location of all objects (should be part of SAVE?) retrieve saved location of an object (should be part of RESTORE?) toggle output text justification set screen width (in fixed font characters) set page margin (in fixed font characters) set screen height (in lines) save player's command (obsolete – use SAVE COMMAND instead) restore player's command (obsolete – use RESTORE COMMAND instead) (spare) (spare) if player command is "SAY <word>", echo "OK - "word"" recover from failed restore swap ARG1 and ARG2 (spare) (spare) check object being on the exception list check existence of a memory save list available saved games Any number of other special action may be defined, but codes up to and including 100 are reserved for future use by the engine. Get and manipulate player input. INPUT [{textname|varname*}] Input and parse a command, setting the mandatory variables ARG1 and ARG2 to the supplied verb and noun respectively. If only a single word is given and the mandatory flag PLS.CLARIFY of the mandatory variable STATUS is set, the supplied word is combined with the last (incomplete) command. Note that the player is queried for input only if we have run out of the last command line. There are three circumstances under which the player is not prompted: He gave several commands separated by full stops or semicolons and we have not processed the last one yet. The last processed command consisted of a verb followed by several nouns and we haven't yet finished applying the verb to all the nouns. This case does not preclude case (a) also applying! We are in a doall loop, applying the verb of the last processed command to all objects satisfying the criteria of the DOALL opcode, which started the loop – and there is at least one more object to process. Again, this case does not preclude either of the two preceding cases applying simultaneously. If the optional argument is supplied, the nominated text is displayed, before accepting player's input. Whether or not this happens, if the last printed text was a "fragment", it is pushed out as the prompt and padded with a space, if required. If the last message was not a fragment, the player is prompted by the standard linefeed and question mark prompt. Note that this allows you to have any prompt you like, instead of the standard one. FAKEARG [{entname1|varname1*}] [{entname2|varname2*}] If player's command refers to an entity referenced (possibly indirectly) by the first argument, pretend that the reference was to the entity referenced by the second argument. This directive does not, however, alter the words of the command. FAKECOM [{entname1|varname1*}] [{entname2|varname2*}] Like FAKEARG, except that the relevant word in the player's command is also modified, in case it is echoed back at the player. VERBATIM {ARG1|ARG2} Replaces the word string associated with ARG1 or ARG2 respectively, with whatever the player actually used, which got interpreted as whatever word string that is to be replaced. UNDO If undo is permitted, undo the number of commands specified by player command's second word, which may be (a) a number to undo a specific number of commands, (b) ALL to undo all commands since the last restore, or (c) UNDO to undo the immediately preceding UNDO. The UNDO_TRIM flag of the UNDO_STATUS variable is set or cleared appropriately. REDO Only accepted immediately after an UNDO command. REDO reverts the undoing of the specified number of commands, which may be given as (a) a number or (b) ALL which is equivalent to UNDO UNDO. The UNDO_TRIM flag of the UNDO_STATUS variable is set or cleared appropriately. DEFAULT [{placename|varname*}] [objflag] If no object has been specified in the player's last command (i.e. if the value of STATUS is 1), check whether there is an object at the nominated location (default HERE) and, optionally, has the nominated flag set. If no such object exists, this directive has no effect. If only one object satisfies the criteria, ARG2 is set as if the player had explicitly nominated that object. If more than one object fits the criteria, ARG2 is set to AMBIGWORD. In either case, the value of STATUS is increased from 1 to 2. ### Saving and restoring (file, memory or command) SAVE {FILE|MEMORY|COMMAND} varname SAVE FILE saves the current state of the game in a file nominated by the command text string associated with ARG2. SAVE MEMORY creates or replaces an in -memory save image (this gets written off to disk in ADVLIB and CGI modes). SAVE COMMAND saves player's parsed command, so that the game can ask a yes/no (or other) question, without relying on the QUERY directive, since this directive is not compatible with ADVLIB or CGI modes. The variable specified by the <varname> argument returns zero on success. Non-zero return indicates failure. RESTORE {FILE|MEMORY|COMMAND} varname Restores file, memory image or player command saved by the SAVE directive. The variable specified by the <varname> argument returns zero on success. Non-zero return indicates failure. DELETE {FILE|MEMORY} varname Deletes respectively a saved file nominated by the second word of the player's command, or the saved memory image (which also can be a file, in an ADVLIB or CGI modes). The variable specified by the <varname> argument returns zero on success. Non-zero return indicates failure. ### Debugging tools. CHECKPOINT SAYs its location (file name and line number) in the A-code source. DUMP Dumps to STDOUT the contents of the game's data array. ## Obsolete and/or deprecated lexicals and directives These directives are still supported for compatibility with old versions of A-code. Some are supported only for style 1 of A-code (i.e. only for Platt's original source). Compound constants A compound constant is a text string with no spaces, where names of simple constants or entitynames are joined by plus and/or minus signs.E.g. LAST.DEFLECTOR-FIRST.DEFLECTOR+2 evaluates as the value of LAST.DEFLECTOR minus the value of FIRST.DEFLECTOR plus 2. For entity names the value used in the calculation is the refno of that entity. In this example from Adv550, the two symbolic names happen to be text names. SYNON {value|symbname}, synon [...] Used to define symbolic name for constants or synonyms for already defined symbols. BISET {entname|varname*}, flagname BIS {entname|varname*}, flagname Obsolete synonym of FLAG. BITST {entname|varname*}, flagname BIT {entname|varname*}, flagname Obsolete synonym of IFFLAG. BICLEAR {entname|varname*}, flagname BIC {entname|varname*}, flagname Obsolete synonym of UNFLAG. LABEL procname Synonymous with PROC. NAME entname, qualifier Synonym of SAY, except that the qualifier is mandatory. DEFINE placename Add the placename to player's vocabulary. The recommended way of doing this is by prefixing the placename with the + sign in its declaration EOI Closes an iteration loop. Use FIN instead! EOF Used in Platt's code as a short-hand for an arbitrary number of successive FINs. DBNAME database-name Defines the name of the data file. TITLE title Older synonym of DBNAME. KEYWORD word [...] If all indicated words (or their synonyms) appear in input, execute the following code, up to the next major directive; otherwise PROCEED. HAVE {objname|varname*} [...] If all indicated objects are held by player (at location INHAND), execute the following statements up to the next major directive; otherwise PROCEED. HERE {objname|varname*} [...] If all indicated objects are at the same location as the player (specified by the variable HERE), execute the following code, up to the next major directive; otherwise PROCEED. There was no corresponding opcode in the original A-code. NEAR {objname|varname*} [...] If all indicated objects are either held by the player (at location INHAND) or at the same location as the player (as specified by the variable HERE), execute the following code up to the next major directive; otherwise PROCEED. AT {placename|varname*} [...] If the player is at (any of) the indicated location(s), execute the following code, up to the next major directive; otherwise PROCEED. Don't worry about the name of this opcode clashing with the AT major directive – they exist in different name spaces, major directives being recognised by starting in column one. Note that the "place" may be an object! ANYOF word [...] If the player typed any of the indicated words in the command being processed, execute the following code, up to the next major directive; otherwise PROCEED. If successive lines have the ANYOF opcode, they are merged internally into a single ANYOF directive. If any of indicated words are in command do following; else PROCEED VALUE entname* [{entname|constant}] Like SAY, but replace '#' with value of the qualifier, rather than the qualifying entity name. SVAR {varname|constant}, varname Set value of the variable nominated in the second argument, according to the value of an environmental variable (or condition) indicated by the value of the first argument. Supported only for the sake of Platt's original code of Adv550, which uses SVAR 4 and SVAR 5 to regulate timing of game restores. ## A-code history The A-code language was created by Dave Platt in early 1980s for the purpose of writing his classic 550 expansion of the original Adventure. It was subsequently expanded by myself in mid 1980s when merging Platt's Adventure 3 (now known as Adv550 ) with Luckett's and Pike's AdventureII (now known as Adv440) into Adv660 (well... into Adventure4, upgraded to Adventure4+, now known as Adv660). I embarked on further expanding Adv660 into Adv770 in 1998, one of the purposes of the exercise being to explore further possibilities for improving A-code. The final result was the considerably improved Acode12. A separate document describes the history of the language in greater detail.