NB: this description is by now incomplete; I will try to find the time to add other features introduced during the development of adv770. Though to be honest, it really needs a complete re-write! In any case, the best way to learn A-code is to study A-code sources, as I did. MLA 18 Dec 2001.
A-code is the adventure-writing language developed by Dave Platt for the adv550 superset of the original Adventure, and subsequently developed by myself, in working on the adv660 superset.
A-code is not intended to be a programming language and hence as a programming language it is fairly primitive. Its strength are elsewhere - in supporting features such as text-switches or text-nesting. It also comes with a pre-programmed "skeleton" adventure template. This is written in A-code and implements lots of basic adventuring functionality, so that on the one hand you can get on with the meaty bits of your adventure straight away, while on the other if you want to give the standard parts a much more customised look, you can easily do that too. As a further bonus, each game created with the A-code system is a stand-alone package, requiring no separate game engine/interpreter.
Technically, A-code is a Polish notation (i.e. "prefix", i.e. "operator [argument [...]]") language. 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 Adventure4 grew in size, its performance on a multi-user machine gradually became less satisfactory. (We are talking mid-80s here! :-)
This is why this 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.
A-code is a deceptively simple language. Many of its features are quite primitive (e.g. global variables only, no procedure arguments...), but don't let this fool you. It is admirably suited to its purpose, making adventure development a much easier task than many other such tools. This is particularly true of this version, which comes with a pre-programmed "skeleton" adventure, already containing all generic adventure code for you to add to or modify.
A-code source consists of (surprise!) declarations and code - in that order! Forward references are not allowed. Declarations declare a variety of entities and code manipulates them. Entities manipulated by A-code are variables, verbs, objects, places, texts, procedures, flags, values and words. All entities have the global scope. I.e. there are NO local variables or procedure arguments. (No longer the case, A-code 11 now supports local variables and procedure arguments.)
Flags are binary yes/no properties, referred to by symbolic names. There are three separate sets of these. One set is defined for objects, one for places and one for verbs/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. Some flags are mandatory, (e.g. the object SCHIZOID flag, see below) but any number of additional ones can be declared in any of the three flag sets.
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.
Some entities (places, objects and variables) each have a state (a.k.a. value) associated with them. A state is simply a short signed integer. To enhance the legibility of A-code source, specific state values can be given symbolic names, e.g. making it possible to test a lamp against being "lit" instead of having the value of, say, 1).
More generally, numbers (signed short integers) can be used within A-code source interchangeably with symbolic constants. Compound symbolic constants, defined on the basis of numbers or previously defined constants, are also allowed for some special purposes.
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. Yes, you've spotted it! This restricts A-code to simple verb/noun commands. Which makes A-code adventures more difficult to devise, but easier to play. Not that expanding the syntax to verb/object [/instrument] would be very difficult.
Texts are named or nameless 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. Texts can contain text "switches" which allow them to be context dependent. A text switch cannot be nested in another switch (that would be meaningless!), but otherwise can occur anywhere within the text, and having components of any length. Its format is [string0/string1/string2...] and must contain not less than two strings (possibly empty). When displayed, text can be qualified by the value of a constant, a variable, an object or a place. If the qualifying value is n and the text contains text switches, only string-n of every switch is displayed. If the qualifier value is higher than the number of strings in the switch, the last string of the switch is printed. This allows texts (and for that matter object and place descriptions, which too are texts), to be context dependent.
Another feature of A-code text is the processing of the # symbol. In a text qualified by a value, each occurence of the # will be replaced either by the numerical value in question or, depending on the directive used to display the text, if the qualifier is a verb or an object, by the primary word associated with the verb or object.
As noted, A-code kernel does its own text formatting and filling at run- time. However, if a text line has a forward slash as it first non-blank character, the rest of the line will be displayed verbatim as a separate line of output.
Finally, text nesting. While braces on directive lines indicate comments, within text they signal inclusion of another previously defined piece of text, which in itself may have further nesting. The syntax is {text_name}, where text_name is either the symbolic name of a piece of text, or a variable referring to text. (See below for the A-code indirection mechanism.)
Chunks of A-code are just that - named or unnamed chunks of A-code. They can be separate procedures or can be associated with verbs or places.
You may be wondering how does one refer to nameless entities of any sort? A-code groups together all entities of one class in the order of their declaration, allowing one to reference nameless ones by offsets from named entities of the same class. Essentially, you can view a sequence of nameless entities as an "array" associated with the last declared named one.
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 +. 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 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 -.
Verbs 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.
There is no restriction on the length of symbolic names, but only the first 16 characters are significant. Names may include any "reasonable" printing ASCII characters.
As noted above, some of the entity names are automatically or selectively added to the player vocabulary. To summarise: all verb names and their synonyms (except if otherwise indicated), all object names and their synonyms (unless otherwise indicated) and some place names and their synonyms (where specifically requested).
Vocabulary words can be abbreviated by player to the minimal unambiguous length. Nevertheless, If a word used by the player is echoed via a text qualified by either the ARG1 or ARG2 variable, the full matching dictionary word is displayed. It is also possible to enforce remapping of vocabulary words. E.g. it may be kind to allow the player to refer to an object by several different synonyms, yet always echo back only one of these. E.g. a matchbox could be referenced as matchbox or just box, but you may wish "get box" to result in "You get the matchbox.". To do this, use the declaration
OBJECT MATCHBOX, =BOX
where the "equal" sign prefixing "BOX" is not a part of the synonym but specifies that if a player says "BOX", "MATCHBOX" should be assumed instead.
An automatic indirection occurs for some A-code directives when manipulating variables into which "addresses" of other entities have been loaded. Generally speaking this happens for non-arithmetical manipulation of variables.
Except within texts, casing is irrelevant - all keywords and opcodes are internally lowercased. The uppercasing of the A-code source is merely conventional.
All declarations must precede any executable code. Forward referencing is not allowed. Within these restrictions, major (declarative) directives 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. The convention of starting all "other" lines in column 10 is not mandatory.
Directive, symbolic names and numerical values can be separated by commas and or spaces. The convention of using comma-space separators is not mandatory.
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.
There are three translator instructions:
The remaining major directives are all declarators. Within each declarative category (e.g. objects, places, texts) entities are stored sequentially in the order of declaration and hence can be referenced by numerical offsets from other entities.
Other than the dbname, flags, states and constants, all declared
entities are associated with a "reference number" 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. It is not necessary for the
programmer 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.
New features at version 11.03 (these apply equally to object
and location descriptions):
All special trickery described under the TEXT
directive applies to place descriptions as well.
All special trickery described under the TEXT
directive applies to object descriptions as well.
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).
Any line with an asterisk in column 1 is considered to be a comment and
is ignored. Comments may be placed on major-command and opcode-control
lines (but not on text-string lines) by starting the comment portion of
the line with a left-brace ('{') - the closing of a comment with a right
brace ('}') is conventional but not mandatory.
From MLA A-code version 10 onwards these are not so much "mandatory" as
"reserved". If they are not defined, the acdc converter will define
them automatically. It will only complain if your A-code source defines
them to be of a wrong type.
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.
First, tests with the "if" group terminated by a major opcode
The next lot are also tests, but their "if" groups must be terminated by
the "FIN" opcode (or the deprecated "EOF" opcode).
Now for some logicals, 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.
Logically enough, here are delimiters for conditional code.
Next come the three iterative opcodes together with the iterative loop
terminator.
Other execution flow control opcodes.
There are three directives for producing text output. All three can be
"qualified" for the purposes of # substitution and/or 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 implied qualifier
These opcodes are used to alter values and flag settings.
Finally two opcodes for communication with the machine environment.
Any number of other special action may be defined, but
codes up to and including 100 are reserved for future use
by the engine.
Oh yes, as an afterthought, perhaps something to communicate with the
player.
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:
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.
That's it! Mind you, you won't understand A-code from this description
alone. Go and read the A-code source.
Just a quick word on the most common error one makes in using A-code.
It is dreadfully tempting to forget that ARG2 holds a pointer rather
than a value and to write "IFEQ ARG2, value", by analogy with "IFEQ
object, value". This is WRONG. The correct code would either refer
to ARG2 by its object name (we often know by that time which particular
object ARG2 points to) or use EVAL: "EVAL variable, ARG2" followed by
"IFEQ variable, value".
declares the dbs name of the adventure. If present, this must
be the first declarative directive. If the name is missing,
the old-style A-code is assumed and, for the purposes of
creating the encoded data file, the name ACODE is used.
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).
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 +es and -es without any separating
blanks.
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.
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. Line of text are
considered to be unformatted, end of line being (usually)
replaced by a space. There are two exceptions to this rule.
(a) A blank line is always displayed as a blank line and (b) if
the last character on a line is a text switch delimiter (/ or
]), the new line is simply ignored (unless followed by a blank
line). Line wrapping and filling is done at runtime. A /
character at the beginning of a line is used to (a) force a new
line and (b) optionally enforce leading spaces on the new line.
The / itself is converted to the line feed and any spaces
following it are honoured. This applies even within text
switches! By default, each text ends with a line feed, except
if any line of the text begins with !` - these characters are
not printed and the line feed at the end of the text is
suppressed. It is, however, recommended that the FRAGMENT
directive be used for this purpose instead.
Identical to the TEXT directive, except that the text is not
terminated by a new line. I.e. it is a text fragment.
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 '&' delimeters 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.
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.
NOISE declares words to be ignored when parsing player's input.
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).
The major directive ACTION is used to associate chunks of
A-code with individual verbs.
defines one or more variables. Note that variables defined on
one line like this are not synonymous. By convention,
related variable tend to be defined in a single VARIABLE
directive.
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.
defines a chunk of A-code (a set of executable code) called
"procname". The following lines contain the code, terminated
by the next major directive.
defines code to be executed when the player is at the indicated
place - the following lines contain the actual code. More than
one "AT" command may be defined for a particular place - they
are executed by a "CALL placename" instruction in the order
encountered during compilation.
defines code associated with a particular verb. The keywords
are optional - if used, the code will be executed iff all
keywords given were actually entered by the user on an input
command line (this is the same as if the keywords were entered
separately on a "KEYWORD" op-code directly following the
"ACTION" statement - "KEYWORD" for details). Note that it is
perfectly permissible to use the name of an object as a verb
(e.g., "WATER"). The code is executed via the "CALL verb"
instruction.
defines once-only code to be executed at initialization time.
Multiple INITIAL commands may be used and are executed in the
order encountered.
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. The REPEAT process may be cut short at any
time by the use of the "QUIT" opcode, which will restart
execution at the beginning of the REPEAT set.
Mandatory places, variables and flags
These three flags are common to all three kinds of flag sets. Their
values are maintained automatically and they are used to decide what
kind of entity one is dealing with.
This is the location of all objects the player is carrying.
Stores the reference number of the current location of the player.
Stores the reference number of the last location of the player.
The value of this variable indicates the number of words in the
players command being executed (not the whole command line!). As
things stand, this value can be only 1 or 2.
Variable set flag. Set automatically for the variable STATUS
whenever the player picks up or drops something.
Variable set flag. Set automatically for the variable STATUS
whenever the player changes his location.
Variable set flags. Changing their settings in the STATUS variable
changes the verbosity of descriptions.
Stores the verb part of the player's command.
Stores the object part of the player's command.
If set by the program, the object will appear in two places - its
current location and the place with the reference number one higher
than that of the current location. Handy for implementing objects
like doors, bridges etc...
If used on its own, repeats the previous (possibly compound) command
line. If embedded in a complex command line, causes the last atomic
command (other than AGAIN) to be re-executed.
Allows A-code program to understand commands like GET ALL and DROP ALL
Minor A-code directives (a.k.a. opcodes)
If all indicated words (or their synonyms) appear in input,
execute the following code, up to the next major directive;
otherwise PROCEED.
If all indicated objects are held by player (at location
INHAND), execute the following statements up to the next major
directive; otherwise PROCEED.
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.
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.
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!
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
Execute the following code up to the next ELSE or FIN (or EOF),
if the value (state, if object or place) of the first argument
is equal the value (state) of the second argument.
Execute the following code up to the next ELSE or FIN (or EOF),
if the value (state, if object or place) of the first argument
is less then the value (state) of the second argument.
Execute the following code up to the next ELSE or FIN (or EOF),
if the value (state, if object or place) of the first argument
is greater than the value (state) of the second argument.
Execute the following code up to the next ELSE or FIN (or EOF),
if the player is currently at the indicated location (which may
be in fact an object!).
Execute the following code up to the next ELSE or FIN (or EOF),
with the probability of n%, where 'n' is the value of the
argument.
Execute the following code up to the next ELSE or FIN (or EOF),
if the player is holding the indicated object. If the second
argument is supplied, the object has to be in the indicated
state or have the indicated flag set.
Execute the following code up to the next ELSE or FIN (or EOF),
if the indicated object is at the same location as the player.
If the second argument is supplied, the object has to be in the
indicated state or have the indicated flag set. This is a new
directive, not present in the original A-code.
Execute the following code up to the next ELSE or FIN (or EOF),
if the indicated object is held by the player or is in the same
location as the player. If the second argument is supplied,
the object has to be in the indicated state or have the
indicated flag set.
Execute the following code up to the next ELSE or FIN (or EOF),
if the indicated entity has the corresponding flag set.
Remember that only objects, places, verbs and variables have
flags to their names.
Execute the following code up to the next ELSE or FIN (or EOF),
if the nominated word appears in the player's command being
processed.
Display the indicated text and request a yes/no answer.
Execute the following code up to the next ELSE or FIN (or EOF)
if the answer is "yes". The answer is case insensitive and can
be abbreviated.
Execute the following code up to the next ELSE or FIN (or EOF),
if the first argument lies in the inclusive interval defined by
the second argument (lower bound) and the third argument
(upper bound). For the purposes of this opcode, if an argument
is a variable, the value of the variable is used, if it is a
constant, the constant value is used, otherwise the reference
number of the indicated entity is used.
Execute the following code up to the next ELSE or FIN (or EOF),
if the indicated variable references the indicated entity.
Execute the following code up to the next ELSE or FIN (or EOF),
if the object nominated by the first argument is located at the
place indicated by the second argument (which in itself may be
an object).
"And" the test results so far with the following test.
"Or" the test results so far with the following test.
"Xor" the test results so far with the following test.
Invert immediately following test.
Execute the following code, up to the next FIN (or EOF), if the
latest (compound) condition returned false.
Delimits the code associated with the most recent (compound)
condition. Can be used interchangeably with EOI.
Execute the following code up to the next EOI or EOF
repeatedly, with the value of the nominated "loop variable"
running through the specified range of objects (default all
declared objects) in the order of their declaration.
Execute the following code up to the next EOI or EOF
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.
Execute the following code up to the next EOI or EOF
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.
Delimits the code executed by the most recent iteration opcode
(ITPLACE, ITOBJECT, ITERATE). Can be used interchangeably with
FIN.
Execute code associated with the named entity, if there is any.
If there is more than one (doesn't apply to procedures, of
course), execute them in the order of their declaration, until
either none left or the QUIT opcode is executed in one of them
(be it explicitly or implicitly).
Terminate the execution of the current chunk of A-code.
Equivalent to returning from a procedure in C.
Terminate the execution of the current chunk of all current
chunks of A-code (they may be nested by various CALLs) and
restart the REPEAT loop at the first REPEAT procedure.
Terminate the whole program immediately.
Now for instructions to move objects and player.
Transport the indicated object to the indicated location (which
itself may be an object!).
Transport the indicated object into the player's hands.
Equivalent to "APPORT objname* INHAND".
Transport the indicated object (presumed to be in player's
hands (location INHAND) to the same location as the player.
indicated by the variable HERE). Equivalent to "APPORT
objname* HERE".
Transport player to the indicated location.
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 QUIT.
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 QUIT.
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, while text switches are governed by
qualifier's value.
Like SAY, but perform a QUIT having said the text
Like SAY, but replace '#' with value of the qualifier, rather
than the qualifying entity name.
Used for displaying context-sensitive vocabulary. The second
argument is not currently in use and must be supplied as 0.
If a flagname is specified and the corresponding flag of the
entity is not set, the directive is ignored. Otherwise the
first dictionary entry for the entity is displayed, or if a
textname is specified, the corresponding text is displayed
rather than the dictionary word. The display, if any, is
prefixed with ", ", except for the first word displayed.
The count of words displayed is reset to zero by a VOCAB
directive with 0 as the first argument, which has no other
effect.
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.
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!
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!
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!
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!
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!
Set the value of the nominated entity to its original value
negated. Note, that no indirection takes place!
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.
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, say 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).
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.
Make the variable specified by the first argument "indirect" to
to entity specified by the second.
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.
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.
Make the indicated variable into an "indirector" for the
location currently holding the indicated object.
Switch on the flag identified by "flagname" in the instance of
the appropriate flag set belonging to the indicated entity.
Switch off the flag identified by "flagname" in the instance of
the appropriate flag set belonging to the indicated entity.
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. The
mappings between the first argument value and the environmental
variable or condition required is quite arbitrary and is
performed by the code (if any) of the procedure svar() in
advcustom.c. The value returned through the second argument of
SVAR is equally arbitrarily decided upon by the same routine.
As supplied, A-code does not use the SVAR opcode. If you have
a need to - it's up to you.
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 advkernel.c procedure special().
As supplied the following actions can be selected by the
appropriate value of the first argument: the value
If no object specified set the object to the first one
satisfying supplied criteria - being at a specific location and
optionally having a specific object flag "on"; if no place
specified the current value of the mandatory variable HERE is
assumed as the place specification.
Just like DEFAULT, but instead of setting the command object,
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.
Abort the do-all loop if one executing and flush the command
line buffer
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 PLSCLARIFY of the
mandatory variable STATUS is set, the supplied word is combined
with the last (incomplete) command.
The most common A-code error
Obsolete directives
These obsolete directives are supported for compatibility with old
versions of A-code. They are honoured only in old-style A-code, i.e.
when the A-code source does not start with a DBNAME directive. (Well,
not strictly true, actually, but it's not safe to assume otherwise.)
Used to define symbolic name for constants or synonyms for
already defined symbols.
Synonymous with PROC.
Synonym of SAY, except that the qualifier is mandatory.
Add the placename to player's vocabulary. The recommended way
of doing this is by prefixing the placename with the + sign in
its declaration.
Delimits code associated with all pending (compound)
conditions and iterations. EOF is simply a shorthand for the
appropriate sequence of FINs and EOIs. Probably not supported
at all - old-style or no old-style! Jolly well replace it with
the explicit sequence of terminators whenever you find it, OK?
Older synonym of DBNAME.
| Back to A-code page Back to main page |
Mike Arnautov, Tuesday, 01-Jan-2008 05:17:33 MST |