
                                                             1. Introduction
                                                             == ============

   The mca.h is a replacement library for Inform. It allows authors to
create so-called "choose your own adventure" games in a somewhat convenient
way. This is a type of game in which the reader, insted of typing a command,
chooses one of several options after each passage of text. This could mean
anything from a basic CYOA book to a full-fledged adventure game -- mca.h
allows for both types and everything in between. The library was first
designed for the latter kind of game, which explains the acronym: "multiple
choice adventure".

   This manual, though a bit terse, should hopefully contain all the
information needed to make the mca.h work. It won't go into the Inform
language and its syntax, but "The Inform Designer's Manual" does that well
enough. There are sections on the following topics:

   1.  Introduction
   2.  Getting started
   3.  The Node object
   4.  Changing options
   5.  Adding new Node subclasses
   6.  Ending the story
   7.  Events
   8.  Useful routines
   9.  Inventory management
   10. Special commands
   11. The repeat command
   12. Customising output
   13. Entry points
   14. Other details

                                                          2. Getting started
                                                          == ===============

   Just like the Inform library, mca.h allows you to define the constants
Story and Headline, as well as a release number and a serial number. They
all work in the same way here.

   The Initialise() entry point also looks the same. It may set up initial
conditions and/or print some introductory text, but the one thing it MUST
do is to set the global variable curnode to the node where the story is
supposed to begin. The library then displays the usual banner and calls
MoveTo(), which displays the text of the starting node. After that, most of
the action is carried out by either nodes or events.

   If you want to delay the printing of the banner, return false from
Initialise(), then manually call Banner() to display it where appropriate.

   The library itself consists of three files. The first one, which is
simply called "mca.h", should be included after the above mentioned
constants, but preferably before anything else. The second file,
"mcastubs.h", can go anywhere as long as it is included after the
definitions of any of the special entry points covered in section 14. The
third file contains all the language specific bits of the library, and
doesn't have to be included by hand.

                                                          3. The Node object
                                                          == ===============

   A node is the main element of a story. It contains a text to be printed
when it is entered, as well as a range of options and their associated
actions. Each option is represented by a number, counting from zero. This
numbering is only internal, and the player will not see any of it, except
that active options will be displayed in the order of their option numbers,
from low to high.

   All nodes belong to the base class Node, which makes use of the following
properties:

         text
   A text which is displayed when this node is entered, or a routine to
print one. Staying in the same node for more than one turn will not cause
this text to show up again.

         initial
   An optional text to be displayed when the node is entered for the first
time, the other text being shown at subsequent visits.

         title
   The title, if provided, is printed in bold style before the node's text
or initial.

         prompt
   Another optional text to be displayed immediately before the listing of
the options. If you want an empty line between the prompt and the options,
you have to print one here.

         SayOpt
   This property can be either a function or an array. In the former case,
it is called with a numerical argument corresponding to an option that is to
be displayed. Simply look at the option number and print the appropriate
text (including a linefeed at the end). When using an array, it should
consist of pairs of entries. The first entry in each pair is an option
number, and the second entry will usually be a string to be printed, though
a function pointer is also allowed.

         ActOpt
   A property to carry out the action when the player has chosen an option.
Like SayOpt, it can be either a routine or an array. The workings are the
same, except that the array version can also contain a new node object to
continue to. To manually change nodes in an ActOpt method (or anywhere else
for that matter), use the MoveTo() routine mentioned below.

         Action
   An optional method that will be called on each turn that the story is in
this node. This happens after the ActOpt stage, but before anything else --
most notably before any Events get to fire. If the current node should
change in the middle of a turn, then the Action method of the new node is
always the one that gets called.

         InitOpts
   This method is used to turn on the options that should be on for this
node. Before it is called, all the options are turned off. How often this
happens depends on the initmode property, as explained in the following
paragraph.

         initmode
   A single value. If it equals 1, then InitOpts will be called before each
turn. If 2 (the default), it will be called every time the node is entered,
but not again if we remain in the same node for several consecutive turns.
If 3, then InitOpts is called only when the node is entered for the first
time, and then never again (unless you remove the node's visited attribute).

         numopts
   Often there is no need to turn on options individually, so the Node class
provides a default mechanism for InitOpts. If you set this property to an
option number, then all options from zero up to that number will be turned
on. Also note that InitOpts is an additive property, so it's possible to
both supply your own InitOpts AND use the default, but the former takes
precedence and will thus always be called first.

         opts
   This is the array in which the on/off states of the options are stored.
Each entry will allow for sixteen options, and by default, nodes have only
one entry. This is usually enough, but if you need more options (or, more
likely, higher option numbers), then you can override opts and add a few
more zeroes.

   Note that of these properties, only InitOpts and opts are defined in the
Node class itself. The others merely have default values, so unless you
explicitly define them, they can only be read from and not written to or
changed. E.G: to change a node's initmode during play, the node must have
the initmode property somewhere in its object definition.

   It is also worth saying a few more words about the two ways of defining
SayOpt and ActOpt. The array versions are more convenient when no special
effects are required, but they do consume more of that precious substance
called readable memory. Only in very large stories should this be a problem,
but it might be worth avoiding arrays at least in Node subclasses, since
every instance would receive a copy of the entire array.

                                                         4. Changing options
                                                         == ================

   Options can be turned on or off using a number of routines supplied by
the library. They all act on the current node unless you specify a different
one (and this node, being optional, is always the last argument in the
line).

         OptOn(option), OptOff(option)
   These routines turn a single option either on or off. The first argument
should be the number of the option in question.

         OptsOn(from, to), OptsOff(from, to)
   For convenience, these routines can turn on or off several options at
once. They both accept a lower number and a higher number, and all options
with numbers in this range will be affected.

         ClearOpts()
   For turning off all options, should you ever need to do that.

   Besides these functions, the library also offers a way of automatically
turning off an option when the player selects it. To enable this in a
specific node, give it the checkopts attribute.

                                               5. Adding new Node subclasses
                                               == ==========================

   Now and then you may want certain options to be available in several
nodes, but copying code around isn't a viable solution. Then you can take
advantage of the fact that the properties that deal with options are all
additive, and create a new subclass to Node.

   Creating a Node subclass is no different from creating a regular node.
Just supply the class definition with an InitOpts to turn on the needed
options, a SayOpt to display them, and an ActOpt to make them do something.
Options from both levels should work as expected. You only have to make
sure that the same option numbers aren't used on more that one place in the
hierarchy.

                                                         6. Ending the story
                                                         == ================

   The library defines a Node subclass named EndNode, which provides a
default way of ending a story. It has the noevents attribute set (see the
section on Events), and will give the player options for restarting,
restoring and quitting.

   Four default EndNode objects are defined by the library. They only differ
in their text properties. Here are the objects and what they say:

   TheEnd:    "The End"
   WonEnd:    "You have won!"
   DiedEnd:   "You have died!"
   FailedEnd: "You have failed!"

   As you can se, creating a new EndNode object for a different kind of
ending is a simple matter. It's also possible to add new options for things
like displaying credits or amusing things to try. The option to quit is
number 10 and the others 0 and 1 respectively, so any new ones can be put in
between. And since an EndNode is no different from a regular node, you can
even "escape" back into the story.

   Finally, if, at any time, there should be no options at all to choose
from, the library will assume that the story is over and jump to TheEnd, but
this is to be considered a safety net and not a feature.

                                                                   7. Events
                                                                   == ======

   Events are things that happen regardless of the current node. They occur
after an option has been chosen and ActOpt has done its job, but before the
options for the next turn are given. (By definition, this means that they
don't run on the first turn.) An event object can be either of class Daemon
or of class Timer. Both types must supply a method named Action, which is
called every time the event is invoked. If text is to be printed, you may
want to precede it with a linefeed.

   Daemons with the active attribute (which is not set by default) are
invoked every turn. Timers have a timeleft property. It keeps ticking down
until it reaches zero. The timer will then be invoked, and after that it
will remain dormant until further notice. Consequently, a daemon is turned
on by setting its active attribute, and a timer by setting its timeleft
property to anything higher than zero. A timeleft value of 1 means that it
will fire on the very same turn, 2 on the next turn, and so on.

   To control in which order events are fired, give them different priority
properties. Events with higher priority will always run first. The default
priority is zero.

   On the other hand, events may be completely inappropriate in some nodes.
Giving such nodes the noevents attribute will keep them all from running.
Timers won't even tick down in the usual manner.

   It may also be useful to know that the library, for efficiency reasons,
moves all event objects to a special mother object called EventHome during
initialisation. Removing an event from this object will keep it from ever
firing again, even if it should be activated at some other point in the
story.

   Finally, note that activating an event from within another event can be a
bad idea, since it may or may not have been checked by the library already.
Using different priorities is a crude solution to such problems.

                                                          8. Useful routines
                                                          == ===============

   The library provides a couple of routines which can be used in ActOpt
methods or in events.

         MoveTo(node, flag)
   Changes the current node. This normally involves printing the new node's
initial or text, but setting the flag argument to a non zero value will make
the move completely silent.

         Wait()
   Will halt and wait for the player to press either enter or the space bar.

         Cls()
   Clears the screen.

         GetNumber(min, max)
   Prompts the player to enter a number between min and max, inclusively. It
won't give up until a proper number has been entered.

                                                     9. Inventory management
                                                     == ====================

   Although mca.h doesn't contain anything resembling a world model, it does
provide rudimentary support for inventory and such. The system used here is
simply an array of key values, each representing some item in the inventory.
An item can be a dictionary word, an object -- anything that boils down to a
unique integer value. Using plain numbers is more memory efficient, of
course. One could, for instance, enumerate constants for all the items in
the story, then use these constants as item references.

   Two routines are used to manage the inventory. Calling Acquire() with an
item as the only argument will add that item to the inventory, returning
false if there were no slots left, true otherwise. If the item number is
negated, it is instead removed, and the return value is true unless the item
wasn't there to remove in the first place.

   The other routine is called Aquired(). It also expects an item, returning
true if it is currently in the inventory, false otherwise.

   This system is general enough that it can be used for almost any purpose.
Not every author will need it, however, so it will not be compiled by
default. To change this, define the constant InventorySize to the maximum
number of items in the inventory to be created.

   Note that no inventory command is provided the player. One could be coded
that goes through the inventory array (which is called simply "inventory"),
printing appropriate names for all the items. The first word in this array
holds the number of items, and the items themselves are stored in the
succeeding words.

                                                        10. Special commands
                                                        === ================

   Apart from choosing between the specified options, the player can also
type in one of a few meta commands, namely: repeat, undo, save, restore,
restart and quit. (More on the repeat command in the next section.)

   In addition to these, the author is allowed to add extra commands.
However, since mca.h is only supposed to be a multiple choice engine, it
tries to avoid anything that complicates the parsing process. In fact, it
will only accept single word commands.

   Now, to add a new command (which will always be a meta command, consuming
no game time), use the entry point UnknownCommand(). This routine is called
whenever the library doesn't recognise the player's input. The unknown
command itself is passed as an argument, and is either a dictionary word or
nothing. Return true if something was printed, false otherwise.

   When adding new commands, it is also useful to replace the library's
standard error message for unknown commands, since this lists the ones that
are actually understood. This is done by defining a constant called
UnknownCommandMsg, as further explained in section 12.

                                                      11. The repeat command
                                                      === ==================

   Since there usually isn't any way to "look around" in a multiple choice
story, and options vary from turn to turn, the player is offered a "repeat"
command (it can also be abbreviated to "r") which displays all text that was
printed since the last choice, including the list of options for the current
turn. This is also done automatically after every restore or undo, since
that is where one would normally issue such a command.

   To implement this feature, text needs to be buffered instead of printed
right away, but this method has a couple of side effects. Most notably, all
commands that affect the style of printed text will not have the desired
effect. Instead, mca.h defines a set of style codes that can be embedded in
strings. As it happens, using these codes can be a lot more convenient than
using the equivalent Inform directives. The following is a list of supported
style codes and the commands that they replace:

   #b    style bold
   #u    style underline
   #v    style reverse
   #r    style roman
   #f    font off
   #n    font on
   ##    (prints a single hash)

   Apart from these, custom style codes may be added through an entry point
named UnknownStyleCode(). This is called, if it exists, when a code is
printed which isn't in the above list. The single character after the hash
sign is the only argument. The return value is not significant. Unsupported
style codes are simply ignored.

   Another thing to note is that the buffer used to store text internally
has to have fixed size. By default, 1 kb (that is 1024 bytes, or characters)
is reserved for this purpose. If this isn't enough, then the constant
BufferSize can be set to a more appropriate value.

   Finally, text buffering needs to be interrupted whenever input is
expected from the player. The routines Wait() and GetNumber() will do so
automatically, but for all other purposes, the correct procedure is to first
call BufferOff(), then handle any interactivity, then call BufferOn() before
any subsequent text is printed.

                                                      12. Customising output
                                                      === ==================

   In a typical story, nearly all printed text comes straight from the
author, but the library has a few messages that are printed on occasion.
These are all contained in a separate file called "english.h". There are two
things one may want to do with regard to this.

   One the one hand, one may wish to replace some of these messages, E.G.
the one printed when the player issues an unknown command, or perhaps the
texts and options of the four EndNode objects. These are all defined as
constants, and can be overridden if they are defined before mca.h is
included. Take a look at english.h for a list of these constants and what
they mean.

   On the other hand, one may wish to translate mca.h into another language.
This could be done by redefining each and every constant from english.h, but
it would of course be easier just to create a new language file. Simply make
a copy of english.h, rename it as appropriate (E.G. to "lojban.h"), then go
through all the constants and give them new values. To use this new language
file in a story, the Inform compiler must be told so, and this is usually
done by entering "+language_name=lojban" at the command line, or by making
an equivalent selection in a graphical interface.

                                                            13. Entry points
                                                            === ============

   Entry points are routines that are (usually) optional, and which are
called by the library at certain times. Some have been mentioned before.
Here follows a complete list:

         AfterPrompt(flag)
   Is called right after a prompt has been printed, but before the player
has been given the chance to type anything. This is where you would display
a quote box or similar, since this would keep it from scrolling off the
screen. The flag argument is set to true if the prompt is a "special
prompt", which means anything except the main prompt asking for an option to
be selected.

         DrawStatusLine()
   This routine can be used to set up a status line for the story. If it
isn't provided, then no status line will appear. (The reason why there is no
status line by default is that there isn't anything meaningful to write
there anyway. There is no score, "moves" aren't defined well enough to be
counted, and nodes don't have to provide titles like rooms in a text
adventure.)

         Initialise()
   This is the only entry point that must be provided. It is called during
startup and is responsible for specifying the initial node, which is done by
setting the curnode global variable. Return false to delay printing of the
story's banner.

         UnknownCommand(word)
   Is called when the player has written a command that wasn't understood.
The argument is either a dictionary word or nothing. Return true if anything
was printed, or false to display the usual error message.

         UnknownStyleCode(code)
   Is called when a style code has been written by the story which isn't
recognised by mca.h. The argument is a single character. The return value is
not significant.

   Note that these entry points, if provided, must be defined before the
inclusion of mcastubs.h.

                                                           14. Other details
                                                           === =============

   As previously stated, you can get at the current node by checking the
global variable curnode, and the previous node is similarly stored in
oldnode. Some nodes might want to customize text or options depending on the
previous node, and there's also the useful "MoveTo(oldnode)" command.

   You can see if a certain node has been visited by checking if it has the
visited attribute.

   A general attribute and a number property are also provided for your
amusement.

