This is Info file ifm, created by infoize v1.0 from ifm.inf

INFO-DIR-SECTION Gaming tools
START-INFO-DIR-ENTRY
* ifm: (ifm.info).		Interactive fiction mapper
END-INFO-DIR-ENTRY


File: ifm  Node: Top, Up: (dir)

IFM -- Interactive Fiction Mapper
*********************************

This Info file describes version 4.0 of IFM, a language and a program for
keeping track of your progress in an Interactive Fiction game.

* Menu::

* Introduction::               What is IFM?
* Operation::                  How to run IFM
* Making Maps::                How to create maps
* Solving the Game::           Creating a walkthrough
* Output Formats::             Available types of output
* Language::                   Language specification
* Diagnostics::                Errors and warnings
* Environment::                Environment variables
* Index::

 -- The Detailed Node Listing --

Making Maps

* Map Intro::                  Introduction to maps
* Adding Rooms::               How to add new rooms
* Adding Links::               How to add extra links
* Other Directions::           Setting non-compass directions
* Room Exits::                 Indicating unexplored directions
* Map Sections::               Splitting the map into pieces
* Adding Items::               Showing where items were found
* Conflicts::                  When things overlap each other

Solving the Game

* Task Intro::                 Introduction to tasks
* Requiring Tasks::            Tasks can depend on previous tasks
* Requiring Items::            Tasks often need items
* Obtaining Items::            Tasks often supply items
* Losing Items::               Tasks can destroy items too
* Dropping Items::             Tasks can cause items to be dropped
* Leaving Items::              Carrying items can block movement
* Limiting Movement::          Tasks often affect movement
* Movement Tasks::             Sometimes moving around is a task
* Scoring Points::             Getting credit for doing things
* Finishing the Game::         Certain things signal game end
* Finding a Solution::         What the game solver does
* Tweaking the Solution::      Helping the solver along
* Limitations::                What the game solver can't do

Output Formats

* Map Output::                 Creating game maps
* Item List Output::           Listing items in the game
* Task List Output::           Listing tasks needed to solve the game
* Customization::              Changing the appearance of things
* Output Variables::           Variables controlling output

Language

* Symbols::                    Symbols used in the language spec
* Format::                     General layout of the input
* Control::                    Titles and map sections
* Tags::                       Format of tags
* Commands::                   General command syntax
* Rooms::                      The 'room' command
* Items::                      The 'item' command
* Links::                      The 'link' command
* Joins::                      The 'join' command
* Tasks::                      The 'task' command
* Variables::                  Setting variables
* Styles::                     Display styles
* Expressions::                Arithmetic expressions
* Include Files::              Including other input files


File: ifm  Node: Introduction, Up: Top, Next: Operation

Description
***********

IFM is a language for keeping track of your progress through an
Interactive Fiction game, and a program for producing various different
sorts of output using it. You can record each room you visit and its
relation to other rooms, the initial locations of useful items you find,
and the tasks you need to perform in order to solve the game.

The IFM mapping commands are designed so that you can easily add to the
map as you explore the game. You type in the rooms you visit and the
directions you move in to reach other rooms, and IFM calculates the
position of each room in relation to the others. A map can consist of
several independent sections, allowing you to divide up the map however
you like. See *note Making Maps:: for an example of how to make a map.

The IFM task commands, if used, allow you to specify the order in which
game-solving tasks must be done. The IFM program can then calculate and
print a high-level 'walkthrough' of the game. See *note Solving the Game::
for examples of how to do this.

Several output formats are available, including PostScript and ASCII text
-- see *note Output Formats::. Some of the output formats have a set of
variables which control the appearance of the output -- see *note Output
Variables::.


File: ifm  Node: Operation, Prev: Introduction, Up: Top, Next: Making Maps

Operation
*********

On startup, IFM does the following. Firstly, the system initialization
file is read. This sets defaults used by everyone. This file is called
ifm-init.ifm, and is found by searching a standard set of directories. You
can override this search path by setting the environment variable IFMPATH
to be a colon-separated list of directories.

Then, if you have a personal initialization file, that is read. This file
is found in the directory specified by your HOME environment variable. On
Unix systems it is called .ifmrc, and on Win32 systems it is called
ifm.ini. You can use this file to customize the default variable settings
for different types of output.

Then input from the file(s) on the command-line is read. If no files were
specified, stdin is read. A filename equal to - also indicates that stdin
should be read at that point.

If any of the -map, -items, -tasks or -show options was specified, the
appropriate output is produced. If not, only a syntax check of the input
is done.

When producing output, the output format specified by the -format option
is used. If this was not specified, the first format in the list which
supports this type of output is chosen.

Some of the output formats use additional library files to do their work.
For example, the PostScript output format adds a standard "prolog" file to
all output. These files are found using the same search path as the system
initialization file (see above).

Here's a list of the command-line options (which can be abbreviated):

    -m, -map
	Draw a map of the game.

    -i, -items
	Print a list of items which appear in the game.

    -t, -tasks
	Print a list of tasks required to solve the game.

    -f, -format format
	Specify the output format (see *note Output Formats::).

    -o, -output file
	Write to the specified file, instead of stdout.

    -w, -nowarn
	Don't print warnings.

    -d, -debug
	Print debugging information.

    -s, -show type
	Show one of several types of information, and exit. See below for
	a list of valid arguments.

    -I, -include dir
	Prepend the specified directory to the library and include file
	search path. This option may be repeated.

    -noinit
	Don't read your personal init file.

    -version
	Print the program version.

    -help
	Just print some usage information.

Here's a list of the -show options (which can be abbreviated):

    path
	Show the directories that are searched for library and include
	files.

    vars
	Show a complete list of defined variables, in a format suitable
	for feeding back into IFM. See *note Variables::.


File: ifm  Node: Making Maps, Prev: Operation, Up: Top, Next: Solving the Game

Making Maps
***********

This section gives you a tour of the main commands for making maps. It's
not complete -- see *note Language:: for a full list of commands.

* Menu::

* Map Intro::                  Introduction to maps
* Adding Rooms::               How to add new rooms
* Adding Links::               How to add extra links
* Other Directions::           Setting non-compass directions
* Room Exits::                 Indicating unexplored directions
* Map Sections::               Splitting the map into pieces
* Adding Items::               Showing where items were found
* Conflicts::                  When things overlap each other


File: ifm  Node: Map Intro, Up: Making Maps, Next: Adding Rooms

Introduction to Maps
====================

The traditional Infocom-style way of drawing Interactive Fiction maps is
the 'boxes-and-lines' method. For example:

    +--------------+   +--------------+   +--------------+
    |              |   |              |   |              |
    |    Kitchen   |---|    Lounge    |   |     Study    |
    |              |   |              |   |              |
    +--------------+   +--------------+   +--------------+
            |       \          |                  |
            |        \         |                  |
            |         \        |                  |
    +--------------+   +--------------+           |
    |              |   |              |           |
    |    Garage    |   |  Dining Room |-----------+
    |              |   |              |
    +--------------+   +--------------+

This is the style of map that IFM produces. Rooms are represented as boxes
on a square grid, and links between the rooms are drawn as lines
connecting them. Links emanate from rooms in any of the eight standard
compass directions, and also follow the grid.

In the following sections, we'll introduce the IFM commands used to draw
the example map above.


File: ifm  Node: Adding Rooms, Prev: Map Intro, Up: Making Maps, Next: Adding Links

Adding Rooms
============

To draw the example map from the previous section, you first choose an
arbitrary start location: the kitchen (when mapping a real game, you'd
choose your actual start location). To add the kitchen, just type this:

    room "Kitchen";

Now you're in the kitchen. Suppose, if this were a real game, that you
first went south to explore the garage. That can be added to the map like
this:

    room "Garage" dir south;

Now you've said which way you went to get to the garage, and since you
were in the kitchen, IFM knows that the garage is south of the kitchen. By
the way, 'south' can be abbreviated 's' (and similarly for all other
directions), just like in the games.

Ok, you're in the garage. Unfortunately, that's a dead end and you have to
retrace your steps to the kitchen. You've already mapped that, so there's
no need to do anything. Now you head off east to the lounge. Now, you're
moving from the kitchen again but IFM thinks you're in the garage (IFM's
idea of 'where you are' is always the last room mentioned). You need a way
of referring to the kitchen again -- to do that, you add a 'tag' to it by
changing the 'kitchen' line like this:

    room "Kitchen" tag Kitchen;

The tag name can be any name you like. You might think that you could
refer to the kitchen by using the name in quotes, but that would mean you
could never have two distinct rooms with the same name. Another advantage
of tags is that they can be much shorter than the real room names. The tag
'K' would be just as valid in the example above (though not as readable).

Now you can refer to the kitchen by its tag, so you can move east from it
into the lounge like this:

    room "Lounge" dir e from Kitchen;

The 'from' clause tells IFM where you're moving from. If it's omitted, it
assumes you're moving from the last room mentioned.

Continuing your exploration, you move south into the dining room:

    room "Dining Room" dir s;

You exit the dining room to the east, and turn a corner north before
entering the study. How can you represent the corner faithfully on the
map? Like this:

    room "Study" dir e n;

This says that you move east, then north, to get to the study. Now, what
if someone locked the study door behind you and the only way out was
through the window? That's a one-way trip into the study, which you can
indicate using the 'oneway' attribute like this:

    room "Study" dir e n oneway;

This is indicated on the map by an arrow.


File: ifm  Node: Adding Links, Prev: Adding Rooms, Up: Making Maps, Next: Other Directions

Adding Links
============

The map as it stands is not complete -- the diagonal link between the
kitchen and the dining room is missing (because you didn't go that way in
visiting the kitchen or the dining room). To add it, you need to modify
the dining room command like this:

    room "Dining Room" dir s link Kitchen;

The 'link' clause creates a straight-line link between the current room
and the room with the specified tag name (in this case, the kitchen).

Note that if this link needed to turn corners, as in the study example
above, then that method of linking the rooms wouldn't have worked. In that
case, you'd have to use the stand-alone 'link' command. For example:

    link Diner to Kitchen dir n nw;

This assumes you've given the dining room the tag name 'Diner'. The link
starts off going north, then turns northwest, and finally goes toward the
kitchen. Note that in a 'link' command, if you omit the final direction
which leads to the linked room, it is added automatically.


File: ifm  Node: Other Directions, Prev: Adding Links, Up: Making Maps, Next: Room Exits

Other Directions
================

Suppose that there were steps down from the kitchen into the garage, and
that you wanted to indicate that you could up or down as well. You could
do that using the 'go' clause, like this:

    room "Garage" dir s go down;

This indicates that the actual direction travelled is downwards, but it is
still represented as south on the map. The 'go' clause accepts 'up',
'down', 'in' and 'out'. As with compass directions, 'up' and 'down' may be
abbreviated as 'u' and 'd'.


File: ifm  Node: Room Exits, Prev: Other Directions, Up: Making Maps, Next: Map Sections

Room Exits
==========

At various points in a game, you arrive in a room with many directions to
explore. It is useful to be able to mark some of these directions as
unexplored, so that you can come back and explore them later. You could
mark these by creating dummy rooms in those directions, but this is
tedious. Alternatively, you can use the 'exit' clause, like this:

    room "Dining Room" dir s exit nw e;

This says that there are two unexplored exits from this room, in the
northwest and east directions. When a map is drawn, this fact will be
displayed by a small line poking out of the room in those directions.

When you come to actually explore those directions, and add links to new
rooms, the corresponding room exit markers will no longer be drawn. So you
can leave the exit clauses in if you want.


File: ifm  Node: Map Sections, Prev: Room Exits, Up: Making Maps, Next: Adding Items

Map Sections
============

In IFM, rooms are divided into groups called 'map sections'. Each room in
a map section has an explicit spatial relationship to all the other rooms
in that section. A room which is obtained by moving via a 'dir' clause
from a previous room is on the same map section as the previous room,
since its co-ordinates can be calculated relative to it.

There are several reasons why it might be a good idea to split a game map
into different sections:

    *	Some maps can be very large, and may not look good on a single
	piece of paper.

    *	It might be awkward to put rooms in relation to each other because
	of, say, a lot of up/down connections which have to be 'flattened
	out'.

    *	The game might naturally divide into sections -- a prologue,
	middle-game and end-game, for example.

IFM manages independent map sections automatically, by deciding which
rooms are on which section. No special command is needed to start a new
map section -- simply define a room which has no connection to any
previous room, by leaving out the 'dir' clause (note that that's how the
kitchen starts out, in the example).

Rooms on different map sections are completely separate, and you may not
link them via the 'link' command. However, you can indicate where a room
on one section is connected to a room on another, using the 'join'
command:

    join Room1 to Room2;

As usual, 'Room1' and 'Room2' are tag names. You can also use 'join' as a
clause in a room command (usually done with the room starting in a new
section):

    room "Basement" join Ground_Floor;

The 'joined' status of the two rooms is indicated on the map, the exact
manner depending on the output format.

Each map section can be given a title using the 'map' command, like this:

    map "Kensington Gardens";

This names the next map section that hasn't been named. Note that you
should have as many 'map' commands as you have map sections, although this
isn't enforced -- any names that are missing will be assigned default
names, and extra names will be ignored. It's conventional to give a 'map'
command just before starting a new map section.

In rare circumstances (e.g. a three-dimensional maze) you may need to have
rooms on the same map section which are not connected to each other. The
room 'dir' clause creates an implicit link from the previous room by
default, but you can stop this from happening by using the 'nolink'
attribute. As a trivial example:

    room "One Side of Wall" tag this_side;
    room "Other Side of Wall" dir e nolink tag other_side;

    room "Underground Passage" tag passage_1;
    room "Underground Passage" tag passage_2 dir e;

    join this_side to passage_1 go down;
    join passage_2 to other_side go up;

In this example, there are two map sections: above ground, and below
ground. But the two above-ground rooms are not connected directly.


File: ifm  Node: Adding Items, Prev: Map Sections, Up: Making Maps, Next: Conflicts

Adding Items
============

As well as rooms, IFM can indicate the initial rooms of various items
found in the game. To add an item, use the 'item' command like this:

    item "Spoon" in Kitchen;

The 'in' clause can be omitted, and then the room defaults to the last
room mentioned. You can also add an arbitrary note to each item (e.g. to
remind you what it's for) using the 'note' attribute:

    item "Spoon" in Kitchen note "Stirs tea";

Here's the completed map description for the above example, with a few
other items thrown in:

    # Example map.

    room "Kitchen" tag Kitchen;
    item "spoon" note "Stirs tea";
    item "sink";
    item "monkey";

    room "Garage" dir s go down;
    item "monkey wrench" note "For wrenching monkey out of sink";

    room "Lounge" dir e from Kitchen;
    item "TV set";

    room "Dining Room" dir s link Kitchen;
    item "table";
    item "chair";

    room "Study" dir e n oneway;

See *note Map Output:: for how to display it.


File: ifm  Node: Conflicts, Prev: Adding Items, Up: Making Maps

Conflicts
=========

After creating a map from a real game and sending the results through IFM,
you may get warnings which talk about things overlapping. This is due to
two rooms, or a room and a link, wanting to occupy the same space on the
map. There are several ways that this could occur:

    *	The game designer made some room links longer than others, and you
	haven't taken that into account. To extend the length of a link,
	just add a length indicator after the direction in the 'dir'
	clause (e.g. 'dir e 2' instead of 'dir e').

    *	One of the links turned a corner, so that the direction you use to
	go back isn't the opposite of the one you used to get here. In
	that case, you need to add the corner-turn in the link (e.g. 'dir
	e s' instead of 'dir e').

    *	The map is multi-level, in which case it's probably best to split
	it into different map sections.

    *	The map is just weird. Colossal Cave is a good example,
	particularly the above-ground section and the mazes. There seems
	to be no logic tying the rooms together. You're on your own.


File: ifm  Node: Solving the Game, Prev: Making Maps, Up: Top, Next: Output Formats

Solving The Game
****************

As well as making a map of your game, IFM can be used to record the steps
you took to solve it. The IFM program can then calculate a (fairly)
optimal solution. This section is a guide to how to do it. Again, it's not
a complete specification -- see *note Language:: for that.

* Menu::

* Task Intro::                 Introduction to tasks
* Requiring Tasks::            Tasks can depend on previous tasks
* Requiring Items::            Tasks often need items
* Obtaining Items::            Tasks often supply items
* Losing Items::               Tasks can destroy items too
* Dropping Items::             Tasks can cause items to be dropped
* Leaving Items::              Carrying items can block movement
* Limiting Movement::          Tasks often affect movement
* Movement Tasks::             Sometimes moving around is a task
* Scoring Points::             Getting credit for doing things
* Finishing the Game::         Certain things signal game end
* Finding a Solution::         What the game solver does
* Tweaking the Solution::      Helping the solver along
* Limitations::                What the game solver can't do


File: ifm  Node: Task Intro, Up: Solving the Game, Next: Requiring Tasks

Introduction to Tasks
=====================

The basic game-solving action is called a task in IFM-speak. To introduce
a task, you use the 'task' command, like this:

    task "Put the fluffy bunny in the incinerator";

Most tasks need to be done in a certain room. The default is that a task
must be done in the last room mentioned. You can change that by using the
'in' clause, just as for items. Some tasks can be done anywhere -- you can
say 'in any' to indicate that. As usual, you can add tags to tasks in
order to refer to them later.

The game solver in IFM divides tasks into two fundamental types: 'safe'
and 'unsafe'. An unsafe task is one that, if done, might get you into a
position where solving the game is impossible. The game solver avoids
doing unsafe tasks until it really has to.


File: ifm  Node: Requiring Tasks, Prev: Task Intro, Up: Solving the Game, Next: Requiring Items

Requiring Tasks
===============

A lot of tasks require a previous task to be done first. To say this, you
use the 'after' clause:

    task "Press incinerator start switch" tag press_switch;
    ...
    task "Put the fluffy bunny in the incinerator" after press_switch;

As a shortcut, to avoid having to tag many tasks, you can say 'after last'
to indicate the last task mentioned. For example, if the two tasks above
could be done in the same room, you could say

    task "Press incinerator start switch" tag press_switch;
    task "Put the fluffy bunny in the incinerator" after last;

Alternatively, you could merge the two into a single task -- the
simplicity or complexity of tasks is up to you.

The 'after' clause only says that a task will come after another -- it
doesn't specify how soon after. But in some situations it is essential
that a task immediately follows a specific previous task, without
deviation. You can use the task 'follow' clause to specify this. For
example:

    room "Mission Control" ...;
    task "Activate launch sequence" tag activate;
    ...
    room "Rocket Cabin" ...;
    task "Fasten seat belt" follow activate;

The 'follow' clause creates a chain of tasks that must be done one after
the other. The game solver will not attempt the first task in the chain
until it knows that all the tasks are possible (i.e. all the prerequisites
for each task in the chain are satisfied). Also, if one of the tasks in
the chain is unsafe, then all previous tasks in the chain are also marked
unsafe.

Of course, you can only have a single task in a 'follow' clause -- the
immediately preceding task. It is an error for two or more tasks to try to
immediately follow the same task.


File: ifm  Node: Requiring Items, Prev: Requiring Tasks, Up: Solving the Game, Next: Obtaining Items

Requiring Items
===============

For a lot of tasks, you need to have one or more items in your possession.
You can indicate this by using the 'need' clause, like this:

    task "Put the fluffy bunny in the incinerator" need bunny;

Here, 'bunny' is the tag name of the corresponding item. You can list more
than one item tag -- e.g. 'need bunny asbestos_gloves'.

Note that you don't need to add tasks to get required items yourself --
the game solver does that automatically. It knows it has to get all the
items which appear in 'need' clauses.


File: ifm  Node: Obtaining Items, Prev: Requiring Items, Up: Solving the Game, Next: Losing Items

Obtaining Items
===============

Some tasks need to be done before you can get an item. One way to indicate
this is with the task 'get' clause:

    task "Put money in drinks machine" need coin get lemonade;

This naturally implies that all tasks which supply an item (via the 'get'
clause) must be done before any task which needs that item.

An alternate way to phrase this is with the item 'after' clause, which
says that the item can't be picked up until a specified task is done. This
is a common combination in IFM:

    task "Put money in drinks machine" need coin;
    item "lemonade" hidden after last;

Some items are only available *before* doing a certain task. You can use
the 'before' clause to say that:

    item "precious diamond" before trigger_alarm;

Some items can only be picked up if you're already carrying another -- use
the 'need' clause for that:

    item "hot coal" need tongs;

Sometimes, doing a task not only allows you to get an item, but also puts
it in your inventory. You can say that using the 'give' clause:

    task "Buy beer" need money give beer_mug;

Note that 'give' overrides all other restrictions placed on getting items.


File: ifm  Node: Losing Items, Prev: Obtaining Items, Up: Solving the Game, Next: Dropping Items

Losing Items
============

Some tasks cause items to be destroyed. You can say that with the 'lose'
clause:

    task "Light bonfire" need match lose match;

This naturally implies that all other tasks which need the item must be
done before the task that destroys it. A 'drop' task is never generated
for items that are lost in this way.

Incidentally, you can use the special tag 'it' to refer to the last room,
item or task tag name within a command. So the previous example could also
have been written

    task "Light bonfire" need match lose it;


File: ifm  Node: Dropping Items, Prev: Losing Items, Up: Solving the Game, Next: Leaving Items

Dropping Items
==============

Normally, you don't have to add explicit drop-item tasks -- IFM knows when
an item is no longer useful, and drops it automatically. But sometimes
items need to be dropped only temporarily. You can do that using the
'drop' clause:

    task "Throw spear at tree stump" need spear drop it tag target_practice;

In this example, the spear is dropped in the same room that the task was
done in. If you ever need the spear for anything else, it will be picked
up by the game solver. Note that an item will only be dropped if it is
being carried -- mentioning an item in a 'drop' clause does not imply that
it's needed to do the task.

Sometimes items must be dropped in a different room to the one you're in.
You can use the 'in' clause to modify things:

    room "Top of Chute";
    task "Put laundry in chute" need laundry drop it in Bottom_of_Chute;

In other cases, you need to drop all the items you're carrying, or all
except certain items. You can use 'drop all' and 'drop all except' to say
that.

Normally, if an item is dropped but is needed again for some other task,
there is nothing to stop the game solver picking it up again (provided
there's a path to the room the item was dropped in). But sometimes you
need to drop an item and not pick it up again until you've done something
else. You can use the 'until' clause to say that:

    task "Put coin in slot" give chocolate drop coin until open_machine;

A task which drops items will be marked unsafe if there is no path back to
the dropped items.


File: ifm  Node: Leaving Items, Prev: Dropping Items, Up: Solving the Game, Next: Limiting Movement

Leaving Items
=============

There are some situations where your movement is blocked if you are
carrying particular items. You can use the 'leave' attribute of rooms,
links and joins to specify a list of items that must be left behind before
using them. For example:

    room "Bottom of Canyon";
    item "heavy boulder" tag boulder;

    room "Top of Canyon" dir n go up leave boulder;

If the 'leave' clause appears before the 'dir' clause, that means the
items must be dropped before entering the room (from any direction). It is
generally the case that, if an attribute could apply to a room or its
implicit link with the previous one, its position relative to the 'dir'
clause is what decides it.

You can also say 'leave all', which means that you must leave all the
items you're currently carrying, and 'leave all except', which omits
certain items from being left behind.

When finding a solution, the game solver will carry items until it is
forced to drop them. If the dropped items are needed later, the game
solver will try to come back and get them. If it is trying to do a task
which requires items, it will choose a route to get to the task room which
doesn't involve dropping any of the needed items.


File: ifm  Node: Limiting Movement, Prev: Leaving Items, Up: Solving the Game, Next: Movement Tasks

Limiting Movement
=================

Sometimes an item is required, or a task needs to be done, before movement
in a certain direction is possible. To represent this, you can give 'need'
and 'after' clauses to rooms, links and joins. For example:

    ...
    room "Cemetery" dir s from winding_path;
    task "Unlock the iron door" need rusty_key;
    room "Crypt" dir s go down after last;
    ...

Here's another example:

    ...
    room "Dimly-lit Passage" dir e;
    room "Dark Passage" dir e need candle;
    ...

In this case it is the link between the two rooms that is blocked off
until the candle is obtained. If the 'dir' clause had appeared before the
'need' clause, the restriction would apply to the room itself (i.e. no
entering the room from *any* direction without the candle).

In some cases, doing a task closes off a room, link or join so that it
can't be used any more. You can use the 'before' clause to indicate this:

    room "Bank Vault" tag Vault;
    room "Bank Entrance" tag Entrance dir e before trigger_alarm;

All tasks which close things off like this are marked unsafe, since they
could block off a crucial path through the game.

Sometimes in a game there is the situation where a path is closed off and,
later on in the game, reopened again. A single link or join can't
represent this. However, there's nothing to stop you from using two or
more joins between the same rooms. If you mark them with the 'hidden'
attribute, they won't appear on the map either. For example, this line
could be added to the previous example to provide an escape route:

    join Vault to Entrance go e after disable_alarm hidden;


File: ifm  Node: Movement Tasks, Prev: Limiting Movement, Up: Solving the Game, Next: Scoring Points

Movement Tasks
==============

There are several different ways of moving around in a game. The usual way
is to say the direction you want to go in. Another way is to do something
else which results in movement. A good example is the magic word XYZZY
from Colossal Cave. It acts exactly like a movement command, in that you
can use it again and again and it moves you somewhere predictable. The
best way to represent this in IFM is to use a join to connect the two
rooms, and specify the command used to do the movement via the 'cmd'
clause, like this:

    join Debris_Room to Building after examine_wall cmd "XYZZY";

Yet another way of moving around is a one-off event that 'teleports' you
to a different room. You can indicate that this happens using the task
'goto' clause, and supplying the tag name of the destination room. For
example:

    task "Get captured by goblins" goto Dungeon;

As soon as the task is done, you 'teleport' to the new location -- no
intervening rooms are visited. Note that because each task is only done
once, this method of travel can only be used once. Note also that the
'drop' and 'leave' actions are done *before* teleporting you to the new
location (so if you drop items in the 'current room', you will be
teleported away from the dropped items).


File: ifm  Node: Scoring Points, Prev: Movement Tasks, Up: Solving the Game, Next: Finishing the Game

Scoring Points
==============

Many games have some sort of scoring system, whereby you get points for
doing various things. In IFM you can record this using the 'score
<integer>' clause, which can apply to rooms, items or tasks. For rooms,
it's the score you get when visiting it for the first time. For items,
it's the score for first picking it up. For tasks, it's the score for
doing that task.

If an item has a score, but is given to the player via a task 'give'
clause, then its score is added to the score for that task instead. If an
item has a score and also has the (obsolete) 'given' attribute, the score
won't be registered at all. So don't use 'given' -- use the task 'give'
clause instead.


File: ifm  Node: Finishing the Game, Prev: Scoring Points, Up: Solving the Game, Next: Finding a Solution

Finishing the Game
==================

Usually a game finishes when you complete some final task. You can
indicate which task this is using the 'finish' attribute. This attribute
can attach to rooms, items or tasks, giving three different types of
finish condition: entering a room, picking up an object or doing a task.
If the game solver ever manages to do something which is flagged with the
'finish' attribute, it considers the game solved and stops. Any extra
things left to do will not be done, even if they score points.


File: ifm  Node: Finding a Solution, Prev: Finishing the Game, Up: Solving the Game, Next: Tweaking the Solution

Finding a Solution
==================

Here's what the game solver does in order to come up with a solution to
the game. First, extra internal tasks are generated. These are tasks to
(a) get items which are scored, (b) get items which are required for
explicitly-mentioned tasks to be done, (c) get items which are needed to
go in certain directions, and (d) go to rooms which are scored.

Next, all the rooms are connected using their links and joins. This means
that for each room, a list is made of all other rooms reachable in one
move. Note that it is possible for some rooms to be unreachable -- for
example, all rooms in a section where there is no 'join' to rooms on other
sections.

Then the task dependencies are calculated. A dependency is where one task
must be done before another. The task dependencies are examined to see if
there are any cycles -- that is, chains of tasks where each one must be
done before the next, and the last must be done before the first. If there
are any, then the game is unsolvable, since none of the tasks in a cycle
can be done.

If there are no cyclic dependencies, the task list is 'traversed' to find
a sequence which solves the game while satisfying the task dependencies.
The start room is the room which was first mentioned in the input (but
this can be changed -- see *note Language::). While there are tasks left
in the task list, the following steps are performed:

    1.	The map is traversed to find the distances of all rooms from the
	current room. Then the task list is sorted in order of ascending
	distance of the rooms they must be done in. Tasks which can be
	done in any room count as having distance zero.

    2.	Scan the sorted task list to find the nearest possible task. For a
	task to be possible, the player must (a) have all required items,
	(b) have done all required previous tasks, and (c) be able to get
	from the current room to the task room via a path which doesn't
	require items not yet collected, or tasks not yet done, or which
	involves dropping needed items on the way.

	Priority is given to safe tasks. For a task to be safe, it must
	(a) not have previously been marked unsafe (e.g. because it closes
	off map connections) and (b) there must be a return path from the
	task room back to the current one. The second condition is to
	avoid taking a one-way trip before preparing properly.

	If there are any safe tasks, the nearest one will be done next
	regardless of how close an unsafe task is. If there are no safe
	task, the nearest unsafe task will be chosen.

    3.	If there was a possible task, do it and remove it from the list.
	Move to the room the task was done in (if any). If not, then the
	game is unsolvable. Give up.

The game solver automatically keeps track of which items the player is
carrying, and knows when an item will no longer be needed -- that's when
all tasks requiring that item have been done. When that happens, a 'drop'
task for the item is done. An exception is items which are needed to move
in a certain direction (see the last example above). In that case the item
is never dropped, since the game solver can't rule out having to go that
way again.

Some items, although they have no direct game-solving function, need to be
carried throughout the game -- e.g. some sort of container for carrying
other things. You can mark such items with the 'keep' attribute -- then
they will never be dropped.


File: ifm  Node: Tweaking the Solution, Prev: Finding a Solution, Up: Solving the Game, Next: Limitations

Tweaking the Solution
=====================

There will be some situations (quite a few, actually) where the game
solver doesn't do things the way you want it to. This section gives a few
tips, and some new keywords, for modifying things.

Making things safe

Firstly, the game solver is completely paranoid. It has to be, because it
doesn't do any lookahead past the current task. It won't do anything
unsafe (e.g. go to a room to do a task when there's no immediate return
journey) unless there's nothing safe left to do. It will quite happily
plod halfway across the map to pick something up rather than do something
a bit scary in the next room.

However, you can reassure it with the task 'safe' attribute. Adding this
to a task tells the solver that this task is safe, regardless of what it
thinks. So if you *know* that a one-way trip can eventually be returned
from, by doing other tasks, you can stop the solver from avoiding it. But
bear in mind that by doing this you are taking full responsibility if the
solver gets stuck.

Changing path lengths

Another thing the solver doesn't know about is how easy or difficult it is
to get from place to place on the map. Suppose you're in a game which is
on two levels separated by a tiresome set of access doors with ID cards.
The connection between the levels may only be two rooms on the map, but
it's a lot more in terms of typing. You can avoid unnecessary trips
through these doors by artificially changing the 'length' of the
connection between levels, by using the 'length' attribute of links and
joins:

    room "Level A" tag LA ...;
    room "Level B" tag LB dir e length 50;

In this way, by choosing an appropriate number for the length, you make it
appear to the solver that all the rooms in level A are closer to each
other than any of the rooms in level B. This means that priority will be
given to tasks in rooms in the same level as you are now, (hopefully)
minimizing the number of level changes. Note that the 'length' attribute
doesn't affect map drawing at all.

Closing off paths

There may be times when you want a map connection to appear on the map,
but not be used in solving the game -- for example, it may be certain
death to go that way. You can use the 'nopath' attribute of rooms, links
and joins to indicate this. It doesn't affect map output in any way.

Another use for this attribute is to force the game solver to do things in
a different order. This might be preferable to adding fake task
dependencies.

Keeping fixes together

It's probably best to keep all your 'game tweaks' together, separate from
the 'pure' game, and commented appropriately. You can do this by using
commands which just modify existing objects, instead of creating new ones,
by referring to their tags. As an example, suppose you have the following
situation:

    room "Top of Chute" ...;
    room "Bottom of Chute" dir s go down oneway;
    task "Do something weird" tag weird_task;
    ...

Suppose you're at the top of the chute, and that there's some stuff to be
done at the bottom, but no immediate way back up. As usual, the game
solver balks at taking a one-way trip and will do anything to avoid it.
But suppose you know that, as long as you have your giant inflatable
cheeseburger, you can get back out again. You can say:

    # Bottom of chute isn't that scary.
    task weird_task need burger safe;

which modifies the task at the bottom of the chute to (a) require the
burger (so that you won't go down there without it), and (b) be considered
safe by the game solver. So it will happily slide down the chute without
getting stuck at the bottom.

This way of modifying previous objects applies all types of object, even
links and joins -- these can be tagged too, in the normal way. The single
exception is the implicit link created by the room 'dir' clause. These
links automatically get tagged when the room does, and with the same name.
So the two-level example above could be split into:

    room "Level A" tag LA ...;
    room "Level B" tag LB dir e;

    ...

    # Stop gratuitous travel between levels.
    link LB length 50;

Debugging

Finally... you can gain an insight into what the game solver's up to by
using the -debug command-line option. This produces reams of output giving
details of the game solver's thoughts before it does anything. It's
supposed to be self-explanatory, but my view is slightly biased. Detailed
documentation may follow (a) if enough people ask for it, and (b) when I
get around to it.


File: ifm  Node: Limitations, Prev: Tweaking the Solution, Up: Solving the Game

Limitations
===========

Given the wild imaginations of today's IF authors, there are bound to be
some game solving situations that can't easily be dealt with using IFM.
Some of the things that IFM ignores are:

    *	Random events. For example, the Carousel room in Zork, and all the
	NPCs in Colossal Cave. There's no way to address this problem, but
	then again, hand-written walkthroughs have the same difficulty.
	However, if you're trying to tailor recording output so that it
	will play back properly in an interpreter, there is a workaround
	-- see *note Task List Output::.

    *	Carrying capacity. A solution may require you to carry more than
	you're allowed. This might be addressed in a future version, but
	inventory-juggling puzzles are out of fashion these days (if they
	were ever in) so this is not much of a problem. Some games provide
	you with an item that can carry stuff for you -- if so, a
	workaround is to add some special tasks that periodically put
	everything you're carrying into it.

There are some other limitations that are the result of certain keyword
combinations in the current implementation of IFM. These are fixable, and
hopefully will be in a later version. They are:

    *	If you have more than one link or join which connects the same two
	rooms, then if any of them set the 'length' attribute, they must
	*all* set it -- and to the same value. Otherwise IFM will give an
	error.

    *	Unsafe tasks in a 'follow' task chain normally cause all the
	previous tasks in the chain to be marked unsafe too (so the solver
	will avoid trying the first, knowing it'll be forced to do
	something distasteful later). However, some tasks are not known to
	be unsafe until just before they might be done -- specifically,
	those for which there is no return path. This is because whether
	there's a return path depends on where you are now. So a 'follow'
	chain could possibly lead to a game-solving dead end.

    *	There's a problem with the 'leave'/'need' attribute combination.
	The game solver could select a path from one room to another in
	which an item must be left behind at one point, but is needed for
	movement later on in the path. This sort of path should be
	invalid, but isn't.


File: ifm  Node: Output Formats, Prev: Solving the Game, Up: Top, Next: Language

Output Formats
**************

IFM has three different types of output (a map, a list of items, and a
list of tasks) and several different output formats. Not all types of
output are produced by each output format.

* Menu::

* Map Output::                 Creating game maps
* Item List Output::           Listing items in the game
* Task List Output::           Listing tasks needed to solve the game
* Customization::              Changing the appearance of things
* Output Variables::           Variables controlling output


File: ifm  Node: Map Output, Up: Output Formats, Next: Item List Output

Map Output
==========

Maps are drawn in the classic Infocom style. Rooms are drawn as boxes, and
links as are drawn as lines (oneway with an arrow). Joins are marked by
adding a 'join number' to the room text of the joined rooms. Non-hidden
items can be shown in their initial rooms.

The following output formats produce maps:

    PostScript (ps)
	Several map sections may be printed per page. Automatic packing is
	done to try to get a good fit on the page. Also, portrait or
	landscape is chosen depending on whichever gives the best fit.
	Fonts of room and item text are scaled to fit them in the room
	boxes, if required.

	To view the PostScript file on-screen, you'll need a PostScript
	previewer. I recommend Ghostview, which is free and is available
	for most systems. This can also print the map on your printer,
	even if the printer doesn't normally print PostScript files.

    Tk commands (tk)
	This produces commands for input to tkifm, a simple graphical
	interface to IFM. It isn't very useful to produce this output
	yourself -- tkifm does that internally to build its map pictures.
	But you can control its display by setting variables in the usual
	way.

        See *note Tkifm:(tkifm). for a description of B<tkifm>.

    Raw data (raw)
	This produces raw data intended for use by other programs. Each
	entry consists of a number of data lines, and is separated from
	other entries by a blank line. Each data line consists of an
	attribute, a colon, and its value. The attributes should be
	self-explanatory.


File: ifm  Node: Item List Output, Prev: Map Output, Up: Output Formats, Next: Task List Output

Item List Output
================

The following output formats produce item lists:

    ASCII text (text)
	This produces human-readable output. The output should be fairly
	self-explanatory.

    Raw data (raw)
	This produces raw data intended for use by other programs. Each
	entry consists of a number of data lines, and is separated from
	other entries by a blank line. Each data line consists of an
	attribute, a colon, and its value. The attributes should be
	self-explanatory.


File: ifm  Node: Task List Output, Prev: Item List Output, Up: Output Formats, Next: Customization

Task List Output
================

The following output formats produce task lists:

    ASCII text (text)
	This produces human-readable output. The output should be fairly
	self-explanatory.

    Recording commands (rec)
	This output produces a list of commands suitable for feeding to IF
	interpreters in playback mode. All the commands in the output are
	converted to uppercase.

	In order for this to work properly, you have to give commands that
	the game will understand. The 'cmd' attribute of rooms, links,
	joins and tasks can help with this. Currently there's no item
	'cmd' attribute, so you have to make sure that the item
	description is recognized by the game (for get and drop commands).
	Also, if a task is implicitly done in the game without you having
	to type any commands (e.g. visiting a room), you can indicate this
	by using 'cmd none'.

	Of course, a recording will only play back properly in an
	interpreter if it provides correct game commands. Random events
	can't be dealt with by IFM, and will probably cause playback to
	fail. But you can work around this with an interpreter that is
	able to fix the random seed at startup (e.g. dumb-frotz). This
	should eliminate most (but not all) of the problems of randomness.

    Raw data (raw)
	This produces raw data intended for use by other programs. Each
	entry consists of a number of data lines, and is separated from
	other entries by a blank line. Each data line consists of an
	attribute, a colon, and its value. The attributes should be
	self-explanatory.


File: ifm  Node: Customization, Prev: Task List Output, Up: Output Formats, Next: Output Variables

Customization
=============

You can change the appearance of many map features according to your
taste. You do this by setting the values of the variables that control
those features. This section tells you how to use variables -- for a
complete list of the customization variables available, see *note Output
Variables::.

As a first example, the background colour of rooms is determined by the
variable 'room_colour'. Its default value is "white". It can be changed
like this:

    room_colour = "beige";

Setting a variable like this will affect all output formats. But in some
cases you don't want to do that. A good example is the one above -- if you
don't have a colour printer, you may not want to have beige rooms printed
(they'll come out greyish). To get around that, you can set variables that
are specific to a particular output format:

    tk room_colour = "beige";

This says to set the variable to "beige" only if producing Tk output. The
default for all other formats is still "white".

You can also customize the appearance of individual rooms and links on the
map, by using different display styles. A display style is just a group of
variable settings with a given name. For example, suppose you're making a
map of Colossal Cave and want to mark rooms where you can refill your
water bottle. You can define a style called, say, Water, like this:

    style Water;
    room_colour = "light blue";
    endstyle;

The values of variables that are set between the 'style' and 'endstyle'
clauses only apply to things drawn in that style. Now, if you declare
rooms like this:

    room "At End Of Road";
    room "Inside Building" style Water dir e go in;

then the room "Inside Building" will be drawn with a light blue
background. You can customize individual links in a similar manner. Note
that here you must put the 'style' clause before the 'dir' clause, so that
the style applies to the room. If it appeared afterwards, it would apply
to the implicit link to the previous room instead.

An alternative way to define a variable in a particular style is to use
the 'in style' clause, like this:

    room_colour = "light blue" in style Water;

If a style only changes a single variable, this may be more convenient.

If you assign a style (say, called newstyle) to an object, but don't
define it anywhere in your input, then IFM will look for a file called
newstyle.ifm using the standard search path. If the file exists, it is
expected to define style newstyle. For example, you could put the "Water"
style definition above into a file called Water.ifm somewhere on the IFM
search path, and it would be read automatically. This is useful if, for
example, you want to use the same style in several different maps.


File: ifm  Node: Output Variables, Prev: Customization, Up: Output Formats

Output Variables
================

There are many variables available for customizing output. At the moment,
only map output can be customized.

The names, descriptions and default values of the customization variables
are all contained in the IFM initialization file. You can change this file
to set global defaults for everybody, or alternatively set your own
preferences in your personal init file.

Here's the original initialization file that came bundled with IFM.

    ##################################################################
    # System IFM init file
    ##################################################################

    # This file contains the default definitions for all variables
    # used by the output formats.  Changing these values will affect
    # all users.

    ##################################################################
    # General notes
    ##################################################################

    # At the moment, only map output is controlled by variables.  The
    # default values are designed to give nice results in all
    # formats.  The default for PostScript is to produce maps for
    # monochrome printing on A4 paper.

    # The map output formats differ in their treatment of fonts.  In
    # PostScript, the font and font size are specified separately,
    # via the *_font and *_fontsize variables.  In Tk, they are both
    # specified together, via the *_fontdef variables.

    # In PostScript output, a font size represents the maximum
    # desired size -- the actual size may be scaled down in order to
    # fit the text into an enclosing space (e.g. a room box).

    # In Tk output, all line width values are interpreted as integers.

    ##################################################################
    # General variables
    ##################################################################

    # Space allocated for each room, in cm.  In PostScript, this is
    # the maximum size -- the actual size may be reduced in order to
    # fit things on the page.
    room_size = 3;

    # Proportion of the room space that's taken up by the room
    # dimensions.  These values should be less than 1 or you'll have
    # no space left for link lines.
    room_width = 0.8;
    room_height = 0.65;

    ##################################################################
    # Room style variables
    ##################################################################

    # Default background colour of rooms.
    room_colour = "white";

    # Offset and colour of room 'shadows'.  This is a pseudo-3D
    # effect which makes rooms look raised off the page.  The offsets
    # are a proportion of the allocated room space.  Note that you
    # can change the direction of the room shadow by negating one or
    # both of the offsets.
    room_shadow_xoff = 0.05;
    room_shadow_yoff = 0.05;
    room_shadow_colour = "grey30";

    # Width and colour of the room box lines.
    room_border_width = 1;
    room_border_colour = "black";

    # Whether to draw dashed room borders (PostScript only).
    room_border_dashed = 0;

    # Width and colour of the room exit lines.
    room_exit_width = 1;
    room_exit_colour = "black";

    # Colour, font and fontsize of room description text.
    room_text_colour = "black";
    ps room_text_font = "Times-Bold";
    ps room_text_fontsize = 10;
    tk room_text_fontdef = "Times 10 bold";

    # Whether to append room tag names to room descriptions.  If so,
    # they are appended in square brackets, like [this].
    show_tags = 0;

    # Whether to show non-hidden item descriptions in rooms.
    show_items = 1;

    # Colour, font and fontsize of item description text (if shown).
    item_text_colour = "black";
    ps item_text_font = "Times-Italic";
    ps item_text_fontsize = 6;
    tk item_text_fontdef = "Times 8 italic";

    ##################################################################
    # Link style variables
    ##################################################################

    # Width and colour of link lines.
    link_line_width = 1;
    link_colour = "black";

    # Size of oneway link arrows, as a proportion of the allocated
    # room space.
    link_arrow_size = 0.08;

    # Whether to draw link lines as splines (Tk only).
    link_spline = 1;

    # Whether to draw dashed link lines (PostScript only).
    link_dashed = 0;

    # Appearance of text that's associated with link lines.  The Tk
    # default is to colour them differently for readability.
    ps link_text_font = "Times-Roman";
    ps link_text_fontsize = 6;
    ps link_text_colour = "black";
    tk link_text_fontdef = "Times 8 bold";
    tk link_text_colour = "red";

    # Text strings indicating up/down/in/out on links.
    link_updown_string = "U/D";
    link_inout_string = "I/O";

    ##################################################################
    # PostScript setup variables
    ##################################################################

    # Prolog file that gets prepended to all the PostScript output.
    # This defines all the procedures for drawing everything.
    prolog_file = "ifm-pro.ps";

    # File of colour definitions, which contains the RGB values of each
    # colour referred to below (and a good many more).  It's just the
    # rgb.txt file found on Unix/X11 systems.  See that file for a list
    # of available colours.  You can use the same colour names for the
    # Tk output, since it uses the standard X colours.
    colour_file = "ifm-rgb.txt";

    # Default page size.  Available page sizes are: A3, A4, A, B, C,
    # Legal, Letter.
    page_size = "A4";

    # If defined, these set a custom page size which overrides the
    # 'page_size' variable.  Units are in cm.
    page_width = undef;
    page_height = undef;

    # Whether to rotate each page to landscape.  If not defined, then
    # rotation is decided on a per-page basis in order to get the best
    # fit.
    page_rotate = undef;

    # Margin space to be left on each page, in cm.
    page_margin = 2;

    # Whether to show a border around each PostScript page.
    show_border = 0;

    # Colour of the page border (if drawn).
    page_border_colour = "black";

    # Colour of the page background.
    page_background_colour = "white";

    # Whether to show the main title on each page.
    show_title = 1;

    # Appearance of the main title (if shown).
    title_font = "Times-Bold";
    title_fontsize = 18;
    title_colour = "black";

    # Appearance of the title printed above each map section.
    map_text_font = "Times-Bold";
    map_text_fontsize = 14;
    map_text_colour = "black";

    # Scale factor which is applied to all PostScript fonts.  This is
    # a convenience variable to make font adjustments easier.
    font_scale = 1;

    ##################################################################
    # Tk setup variables
    ##################################################################

    # Maximum width and height of the map canvas window, in rooms.
    canvas_width = 8;
    canvas_height = 6;

    # Background colour of the map canvas.
    canvas_background_colour = "wheat";

    ##################################################################
    # Aliases
    ##################################################################

    # Alternate spellings for colour variables, for U.S. IFM fans.
    canvas_background_color => canvas_background_colour;
    color_file => colour_file;
    item_text_color => item_text_colour;
    link_color => link_colour;
    link_text_color => link_text_colour;
    map_text_color => map_text_colour;
    page_background_color => page_background_colour;
    page_border_color => page_border_colour;
    room_border_color => room_border_colour;
    room_color => room_colour;
    room_exit_color => room_exit_colour;
    room_shadow_color => room_shadow_colour;
    room_text_color => room_text_colour;
    title_color => title_colour;

    # Compatibility aliases for old versions of IFM.  If your maps
    # use any of these, you should replace them with the aliased
    # variable -- at some point in the future these aliases may go
    # away.
    exit_colour => room_exit_colour;
    exit_linewidth => room_exit_width;
    item_font => item_text_font;
    item_fontsize => item_text_fontsize;
    label_colour => link_text_colour;
    label_font => link_text_font;
    label_fontsize => link_text_fontsize;
    link_linewidth => link_line_width;
    room_font => room_text_font;
    room_fontsize => room_text_fontsize;
    room_linewidth => room_border_width;

Previous versions of IFM had two object attributes which are now
implemented as display styles: the room 'puzzle' attribute, and the link
'special' attribute. Here's the 'puzzle' style:

    # Room 'puzzle' style (was previously the 'puzzle' attribute).

    style puzzle;
      room_colour = "grey";
    endstyle puzzle;

And here's the 'special' style:

    # Link 'special' style (was previously the 'special' attribute).

    style special;
      ps link_dashed = 1;
      tk link_colour = "blue";
    endstyle special;


File: ifm  Node: Language, Prev: Output Formats, Up: Top, Next: Diagnostics

Language
********

This section gives a formal description of the IFM input language.

* Menu::

* Symbols::                    Symbols used in the language spec
* Format::                     General layout of the input
* Control::                    Titles and map sections
* Tags::                       Format of tags
* Commands::                   General command syntax
* Rooms::                      The 'room' command
* Items::                      The 'item' command
* Links::                      The 'link' command
* Joins::                      The 'join' command
* Tasks::                      The 'task' command
* Variables::                  Setting variables
* Styles::                     Display styles
* Expressions::                Arithmetic expressions
* Include Files::              Including other input files


File: ifm  Node: Symbols, Up: Language, Next: Format

Symbols
=======

In the following sections, these symbols are used:

    ID	      A name starting with a letter, followed by any combination
	      of upper- or lowercase letters or numbers or an underscore.
	      E.g. Dense_Forest. IDs are not allowed to clash with
	      reserved words (e.g. 'room', or 'tag'). One way to avoid
	      this is to capitalize all tags (reserved words are all in
	      lowercase).

    STRING    Any sequence of characters, in double-quotes. E.g. "Black
	      Rod". To get a double-quote inside a string, quote it by
	      using a backslash, like this: "Ground Floor, \"A\" Block".
	      To get a backslash inside a string, quote that too (\\). You
	      can continue strings on several lines -- a
	      newline-and-whitespace sequence is translated into a single
	      space, just like in TADS and Inform.

	      Note that dollars ($) are special inside strings -- they
	      mark the start of a variable substitution. See *note
	      Variables:: for details. If you want a literal dollar symbol
	      in a string, use $$.

    NUMBER    An number, or an arithmetic expression (see *note
	      Expressions::). If the context requires an integer, the
	      number is silently rounded to the largest integer not
	      greater than this value.

    COMPASS   A compass direction, which can be abbreviated or in full
	      (e.g. 'n', 'se', 'northwest', etc).

    OTHERDIR  One of 'up', 'down', 'in', or 'out'.

    [...]     An optional part.

    thing1 | thing2
	      A choice of several different things.


File: ifm  Node: Format, Prev: Symbols, Up: Language, Next: Control

Format
======

IFM generally has a free-format layout -- i.e. whitespace may be placed
anywhere to increase readability. The only exception is inside quoted
strings, where spaces are significant. Comments may be added, starting
with a hash (#) and continuing to the end of the line. All commands are
terminated with a semi-colon.


File: ifm  Node: Control, Prev: Format, Up: Language, Next: Tags

Control
=======

The overall title of the map may be set using the command

    title STRING;

If a map has several sections, you can set the title of each section using
the command

    map STRING;

This sets the title of the next map section. Also, any variables set after
this command are local to the next map section (see *note Variables::). If
you use this command at all, then the number of uses should be the same as
the actual number of map sections. But note that the map command doesn't
have to be near the room that starts a new map section, so you could (for
example) put all the map commands and their local variables at the start
of the input.


File: ifm  Node: Tags, Prev: Control, Up: Language, Next: Commands

Tags
====

All IFM objects may be given tag names, so that you can refer to them in
other commands. Tags for different types of object are independent -- for
example, you could have a room and an item with the same tag. However,
tags for similar objects must be unique.

In many cases, you are allowed to refer to a tag name anywhere, even
earlier in the file that you defined it (as long as the tag is defined
somewhere!). Exceptions are the room 'from ID' clause (see *note Rooms::),
and tags in commands that modify existing objects (see *note Commands::)
-- these tags must be defined before being used.

The special tag 'last' may be used to refer to the last object that was
defined (depending on the context). Also, within an individual command,
the special tag 'it' may be used to refer to the most recent object tag.


File: ifm  Node: Commands, Prev: Tags, Up: Language, Next: Rooms

Commands
========

There are 5 different types of object in IFM: rooms, items, links, joins
and tasks. Each is created using its own command, the general format of
which is:

    <type> <body> [attribute-list];

For rooms, items and tasks, body is just a string description. For links
and joins, body specifies two room tags to link or join together.

Many of the attributes of objects accept a list of tags as arguments. All
of these, if specified more than once in the same object, concatenate the
lists together.

Once an object has been declared with a tag name, its attributes can be
modified by later commands referring to that tag, like this:

    <type> ID [attribute-list];

where ID is the tag name of the object. Note that the tag must be defined
earlier in the file than it is used.


File: ifm  Node: Rooms, Prev: Commands, Up: Language, Next: Items

Rooms
=====

A new room is added using the command

    room STRING [attribute-list];

where STRING is a description of the room. Room attributes can be:

    tag ID    Give the room a tag name, so that you can refer to it
	      elsewhere.

    dir COMPASS [NUMBER] [COMPASS [NUMBER]...] [from ID]
	      Specify the position of the room relative to the room with
	      the given tag ID (which must be defined before it is used).
	      If no 'from' clause is specified, the last defined room is
	      used instead. There can be more than one direction given --
	      the new room is placed relative to the previous one using
	      them. Following a direction with a number means to repeat it
	      that many times.

	      The 'dir' clause creates an implicit link between this room
	      and the previous one. Some of the room attributes below
	      behave differently depending on whether they appear before
	      or after the 'dir' clause in the attribute list.

	      If the room is given a tag name, then the implicit link will
	      be given the same tag.

    link ID [ID...]
	      Specify other rooms that this room links to. Note that this
	      creates a link with no special attributes -- use the
	      standalone 'link' command for that (see *note Links::).

    join ID [ID...]
	      Specify rooms on other map sections that this room joins to.
	      Note that this creates a join with no special attributes --
	      use the standalone 'join' command for that (see *note
	      Joins::).

    exit COMPASS [COMPASS...]
	      Indicate which other directions the room has exits in. Room
	      exits in a particular direction are marked on the map only
	      if there is no link going to or from the room in that
	      direction.

    note STRING
	      Append a note to the room's note list.

    score NUMBER
	      Indicate that you score the specified number of points when
	      visiting this room for the first time.

    need ID [ID...]
	      If this appears before a 'dir' clause, indicate that you can
	      only enter this room after getting the specified items. If
	      it appears afterwards, it applies to the implicit link
	      instead.

    after ID [ID...]
	      If this appears before a 'dir' clause, indicate that you can
	      only enter this room after doing the specified tasks. If it
	      appears afterwards, it applies to the implicit link instead.

    before ID [ID...]
	      If this appears before a 'dir' clause, indicate that you can
	      only enter this room before doing the specified tasks. If it
	      appears afterwards, it applies to the implicit link instead.
	      Those tasks are marked unsafe.

    leave ID [ID...]
	      If this appears before a 'dir' clause, indicate that the
	      specified items, if carried, must be left behind when
	      entering the room. If it appears afterwards, it applies to
	      the implicit link instead.

    leave all [except ID [ID...]]
	      As above, except indicate that *all* items must be left
	      behind. The 'except' clause can be used to omit specific
	      items.

    go OTHERDIR
	      Indicate that the link to this room is in the specified
	      direction.

    cmd STRING
	      Specify the command you type to move to this room from the
	      previous one. If no 'cmd' clause is given, the command is
	      deduced from the 'go' clause. If that isn't specified, the
	      command will be deduced from the 'dir' clause.

    cmd from STRING
	      As above, but this specifies the command to go in the other
	      direction. This defaults to the 'cmd to' command, if
	      specified.

    cmd to STRING
	      This is identical to 'cmd' on its own, and only exists for
	      symmetry.

    oneway    Indicate that the return journey from this room to the
	      previous one is not possible.

    length NUMBER
	      Indicate that the direction link to this room has the
	      specified length (default 1). This only affects the
	      calculation of the 'nearest' task when solving the game --
	      see *note Tasks::.

    start     Indicate that this is the room the player starts in. Default
	      is for the first room mentioned to be the start room.

    finish    Indicate that entering this room finishes the game.

    nolink    Indicate that this room does not have an implicit link with
	      the previous one via the 'dir' clause.

    nopath    Indicate that the implicit link from this room should not be
	      used by the game solver.

    style ID [ID...]
	      Add a list of display styles to the room. See *note
	      Styles::.


File: ifm  Node: Items, Prev: Rooms, Up: Language, Next: Links

Items
=====

An item is introduced using the command

    item STRING [attribute-list];

where STRING is the item description. Item attributes can be:

    tag ID    Give the item a tag name, so you can refer to it elsewhere.

    in ID     Set the initial location of this item. Default is the last
	      defined room. If there is no last room (i.e. an item was
	      declared before any room was declared), then this item is
	      initially carried by the player.

    note STRING
	      Append a note to the item's note list.

    score NUMBER
	      Indicate that you get points the first time you pick this
	      item up.

    hidden    Indicate that this item is not immediately obvious when
	      entering the room.

    keep      Indicate that this item shouldn't be dropped (no 'drop' task
	      should be generated).

    given     Indicate that this item didn't have to be picked up when it
	      entered the inventory (no 'get' task should be generated).
	      This attribute is obsolete -- you should use the task 'give'
	      clause instead (see *note Tasks::).

    lost      Indicate that this item wasn't dropped when it left the
	      inventory (no 'drop' task should be generated). Normally you
	      should use the task 'drop' or 'lose' clauses instead (see
	      *note Tasks::). The only use for this attribute is for items
	      that are left behind due to a 'leave' clause.

    need ID [ID...]
	      Indicate that you can only pick this item up after getting
	      the specified items.

    after ID [ID...]
	      Indicate you can only pick this item up after the specified
	      tasks are done.

    before ID [ID...]
	      Indicate you can only pick this item up before the specified
	      tasks are done.

    finish    Indicate that getting this item finishes the game.

    style ID [ID...]
	      Add a list of display styles to the item. See *note
	      Styles::.


File: ifm  Node: Links, Prev: Items, Up: Language, Next: Joins

Links
=====

You can create extra room links using the command

    link ID to ID [attribute-list];

and the following attributes may be specified:

    tag ID    Give the link a tag name, so you can refer to it elsewhere.

    dir COMPASS [COMPASS...]
	      Set the intermediate directions that this link travels in,
	      in the same manner as for rooms. Note that if you omit the
	      final direction to the linked room, it is added
	      automatically.

    go OTHERDIR
	      Indicate that the link is in the specified direction.

    cmd STRING
	      Specify the command you type to go in this direction. If no
	      'cmd' clause is given, the command is deduced from the 'go'
	      clause. If that isn't specified, the command will be deduced
	      from the 'dir' clause.

    cmd from STRING
	      As above, but this specifies the command to go in the other
	      direction. This defaults to the 'cmd to' command, if
	      specified.

    cmd to STRING
	      This is identical to 'cmd' on its own, and only exists for
	      symmetry.

    oneway    Indicate that this is a one-way link, in a similar manner to
	      the room attribute of the same name.

    hidden    Indicate that this link should not be drawn on the map.
	      Hidden links are still used when solving the game.

    nopath    Indicate that this link should not be used by the game
	      solver.

    length NUMBER
	      Indicate that this link has the specified length (default
	      1). This only affects the calculation of the 'nearest' task
	      when solving the game -- see *note Tasks::.

    need ID [ID...]
	      Indicate that you can only go in this direction after
	      getting the specified items.

    after ID [ID...]
	      Indicate that you can only go in this direction after doing
	      the specified tasks.

    before ID [ID...]
	      Indicate that you can only go in this direction before doing
	      the specified tasks. These tasks are marked unsafe.

    leave ID [ID...]
	      Indicate that the specified items, if carried, must be left
	      behind when using this connection.

    leave all [except ID [ID...]]
	      As above, except indicate that *all* items must be left
	      behind. The 'except' clause can be used to omit specific
	      items.

    style ID [ID...]
	      Add a list of display styles to the link. See *note
	      Styles::.


File: ifm  Node: Joins, Prev: Links, Up: Language, Next: Tasks

Joins
=====

There is a standalone 'join' command which joins two rooms on different
map sections:

    join ID to ID [attribute-list];

The following attributes may be specified:

    tag ID    Give the join a tag name, so you can refer to it elsewhere.

    go COMPASS | OTHERDIR
	      Indicate that the join to this room is in the specified
	      direction.

    cmd STRING
	      Specify the command you type to go in this direction. If no
	      'cmd' clause is given, the command is deduced from the 'go'
	      clause. If that isn't specified, the command will be
	      undefined.

    cmd from STRING
	      As above, but this specifies the command to go in the other
	      direction. This defaults to the 'cmd to' command, if
	      specified.

    cmd to STRING
	      This is identical to 'cmd' on its own, and only exists for
	      symmetry.

    oneway    Indicate that this is a one-way join, in a similar manner to
	      the room attribute of the same name.

    hidden    Indicate that this join should not be drawn on the map.
	      Hidden joins are still used when solving the game.

    nopath    Indicate that this join should not be used by the game
	      solver.

    length NUMBER
	      Indicate that this join has the specified length (default
	      1). This only affects the calculation of the 'nearest' task
	      when solving the game -- see *note Tasks::.

    need ID [ID...]
	      Indicate that you can only go in this direction after
	      getting the specified items.

    after ID [ID...]
	      Indicate that you can only go in this direction after doing
	      the specified tasks.

    before ID [ID...]
	      Indicate that you can only go in this direction before doing
	      the specified tasks. These tasks are marked unsafe.

    leave ID [ID...]
	      Indicate that the specified items, if carried, must be left
	      behind when using this connection.

    leave all [except ID [ID...]]
	      As above, except indicate that *all* items must be left
	      behind. The 'except' clause can be used to omit specific
	      items.

    style ID [ID...]
	      Add a list of display styles to the join. See *note
	      Styles::.


File: ifm  Node: Tasks, Prev: Joins, Up: Language, Next: Variables

Tasks
=====

You can indicate tasks which need to be done in order to solve the game
using the 'task' command

    task STRING [attribute-list];

and these are the available attributes:

    tag ID    Give the task a tag name, so you can refer to it elsewhere.

    in ID     Specify the room the task must be done in. If this clause is
	      omitted, it defaults to the last defined room. You can use
	      the special word 'any' to indicate that the task may be
	      performed anywhere. A task declared before any room is
	      equivalent to saying 'in any'.

    need ID [ID...]
	      Indicate that the specified items are required before you
	      can do this task.

    after ID [ID...]
	      Indicate that this task can only be done after all the
	      specified tasks have been done.

    follow ID
	      Indicate that this task must be done immediately after the
	      specified one. Not even a 'drop item' task is allowed in
	      between.

    get ID [ID...]
	      Indicate that doing this task enables you to get the
	      specified items, and must be done before you can get them.

    give ID [ID...]
	      Indicate that doing this task puts the specified items
	      straight into your inventory, wherever they happen to be.

    lose ID [ID...]
	      Indicate that doing this task causes the specified items to
	      be lost. This implies that all tasks which need these items
	      must be done before this one.

    drop ID [ID...] [in ID] [until ID [ID...]]
	      Indicate that doing this task drops the specified items in
	      the current room (or the room indicated by the 'in' clause)
	      if you're carrying them. No 'drop' message is generated. If
	      there's an 'until' clause, you can't retrieve the items
	      until the specified tasks have been done.

    drop all [except ID [ID...]] [in ID] [until ID [ID...]]
	      As above, but drop everything you're carrying. The 'except'
	      clause can be used to omit specific items.

    goto ID   Indicate that you get 'teleported' to the specified room
	      when this task is done. This happens after 'give' and 'drop'
	      actions.

    safe      Mark this task as safe -- i.e. one that can't cause the game
	      solver to get stuck.

    finish    Indicate that doing this task finishes the game.

    score NUMBER
	      Indicate that you get the specified score for doing this
	      task.

    note STRING
	      Append a note to the task's note list.

    cmd STRING [NUMBER]
	      Specify the exact command you type to do the task. If a
	      number follows the command, do the command that many times.
	      Multiple 'cmd' clauses concatenate into a list of commands.

    cmd none  Indicate that no command is required to do this task.

    style ID [ID...]
	      Add a list of display styles to the task. See *note
	      Styles::.


File: ifm  Node: Variables, Prev: Tasks, Up: Language, Next: Styles

Variables
=========

Various aspects of output are controlled by variables. These are set using
the following syntax:

    [FORMAT] IDENT = NUMBER | STRING | undef [in style ID];

FORMAT, if specified, is the name of a specific output format -- the
variable then applies only to that output format. IDENT is the name of the
variable, and it can take a numeric or string value. Note that setting a
variable to the value 'undef' effectively removes it.

If the style clause is present, this means to only set the variable to
this value in the specified style (see *note Styles::).

You can use the value of a defined variable anywhere in the input where a
number or string is expected, by prefixing it with a dollar ($) symbol.

All strings that are printed by IFM output formats undergo variable
substitution -- that is, parts of the string which look like variable
references get the value of the variable inserted. If you want a literal $
inside a string, use $$. If you want substitution to be performed on a
variable that is cuddled up to other text that looks like part of the
variable name, you must surround it with twiddly brackets, like ${this}.
Note that variable substitution only happens when the string is output --
this happens after all other processing, so it is the final value of the
variable that will be substituted.

Variables can have 'aliases' -- that is, other names. A variable alias is
set using the syntax

    alias_name => var_name;

This has the effect that whenever variable 'alias_name' is set or
accessed, then variable 'var_name' is actually set or accessed instead.
Note that if a variable already exists with name 'alias_name', its value
is hidden while the alias is in force. Aliases can be removed by saying

    alias_name => undef;

Some output formats use variables so that you can customize them. They
expect certain variables to be defined, and give an error if they aren't.
The default values for these variables are set in the initialization file
-- see *note Output Variables::.


File: ifm  Node: Styles, Prev: Variables, Up: Language, Next: Expressions

Styles
======

Display styles change how individual things are shown when output.
Currently, only map output for rooms and links is affected by styles.

IFM keeps track of the currently active list of display styles, and there
are two commands which change this list. The command

    style ID;

pushes the specified style onto the style list. This style becomes the
current style. Any IFM objects declared while a style list is in force
will by default be output in those styles. Any variable setting is by
default in the current style (though you can specify a particular style
using the 'in style' clause -- see *note Variables::).

The command

    endstyle [ID];

pops the current style from the style list. The previous style on the list
(if any) becomes the current style. The ID, if specified, should match the
ID in the corresponding 'style' command, or a warning is given.

Each display style has its own set of values for customization variables.
On output, when the value of a variable is needed for displaying an
object, the style list for that object is searched in reverse order of
declaration. The value used is from the first style to define this
variable. If no style defines it, then the default value is used.

If a style is referenced by an object but not defined anywhere in the
input, then its definition is assumed to be in a separate file, which is
searched for using the standard search path. The name of this file is
formed by adding an .ifm suffix to the style name. If the file is not
found, or it does not define the required style, a warning is given.


File: ifm  Node: Expressions, Prev: Styles, Up: Language, Next: Include Files

Expressions
===========

Whenever a number is expected in IFM input, you can supply an arithmetic
expression. An expression can be a number or a variable value, or a
combination using the following constructs (in order of precedence):

    ( expr )            parentheses
    expr ^ expr         exponentiation
    + expr              unary plus
    - expr              unary minus
    expr * expr         times
    expr / expr         divide
    expr % expr         remainder
    expr + expr         plus
    expr - expr         minus

Note that in expressions, all variables are treated as numeric. If a
variable is set to be a string and is then used in an expression, its
numeric value will be read from the string. For most strings, this will be
zero. This means that if you want to set a string variable to be exactly
equal to another variable, you can't say something like

    string_var = $other_string_var;

because the right hand side is an expression, which is treated as numeric.
The way to do it is to use variable substitution in strings:

    string_var = "$other_string_var";


File: ifm  Node: Include Files, Prev: Expressions, Up: Language

Include Files
=============

Your IFM input can include other input files too, via the 'include'
directive. There are two forms:

    include "file"

and

    include <file>

The first form looks for the exact file name -- either absolute or
relative to the current directory. The second form does a directory search
to find the file, using the IFM search path (which can be set via the -I
command line option or the IFMPATH environment variable).

Note that to be recognized as such, the 'include' directive must be the
first thing on a line. Note also that no semicolon is required after it.


File: ifm  Node: Diagnostics, Prev: Language, Up: Top, Next: Environment

Diagnostics
***********

This section describes the possible error and warning messages which might
be produced by IFM, and what they mean. Note that individual output
formats may print their own errors and/or warnings. This list only covers
the standard ones.

Here's the list of error messages. If any errors occur, no output is
produced.

    error: invalid repeat count
	You've given a repeat count of zero or less for a string or
	direction, which doesn't make much sense.

    error: no last room
	You've given the very first room a 'dir' clause. See *note
	Rooms::.

    error: no [type] referred to by 'last'
	You've said 'last' to refer to the last room, item or task that
	was defined, but none of that type of object have been defined
	yet. See *note Tags::.

    error: no [type] referred to by 'it'
	You've said 'it' to refer to the last room, item or task tag that
	was mentioned in the current command, but no tags of that type of
	object have been mentioned. See *note Tags::.

    error: [type] tag [name] already defined
	You've given two similar objects the same tag name. See *note
	Tags::.

    error: [type] tag [name] not defined
	You've referred to a tag name that hasn't been defined anywhere in
	the input. See *note Tags::.

    error: [type] tag [name] not yet defined
	You're referring to a tag at a point where it hasn't yet been
	defined, in a situation where it must be (e.g. the room 'from'
	clause, or a command that modifies attributes of a
	previously-defined object). See *note Tags::.

    error: can't modify [name] attribute
	You're attempting to modify an attribute of an object which can't
	be changed once it's set (e.g. a tag name). This is because it
	would create inconsistencies between objects.

    error: can't link [name1] and [name2] -- different map sections
	The rooms you're trying to link are on different sections of the
	map, and have no spatial relation to one another. You might have
	forgotten to link a previous room in the list. Or you meant to use
	a 'join'.

    error: can't link [name] to itself without at least one direction
	To link a room to itself, you need to specify at least one
	direction. Otherwise, the link goes nowhere. See *note Links::.

    error: links between [name1] and [name2] have differing lengths
	You've defined more than one link or join between the given rooms,
	but given them different values for the 'length' attribute. This
	isn't allowed. See *note Limitations::.

    error: more than one task needs to follow [task] immediately
	You've given two or more tasks an identical 'follow' tag. Only one
	task can 'follow' a given task. See *note Tasks::.

    error: [num] cyclic task dependencies
	The game isn't solvable because there's one or more chains of
	tasks where each must be done before the next, but the last must
	be done before the first. See *note Finding a Solution::.

    error: variable [name] is not defined
	A customization variable needed by an output format is not
	defined. You should only see these errors if you have modified or
	overridden the system initialization file. The remedy is to define
	the variable somewhere.

Here's the list of warning messages. If only warnings occur, then output
is still produced.

    warning: attribute [attr] ignored -- no implicit link
	You've given a room with no 'dir' clause an attribute that is
	associated with that link (e.g. 'oneway', or 'special'). Most
	likely you're putting the attribute in the wrong place -- if you
	want, say, a join to have one of these attributes, you must define
	it using the standalone 'join' command instead. See *note Rooms::.

    warning: link from [name1] to [name2] outside grid
	The destination room for a link is not in a compass direction from
	the last specified position.

    warning: rooms [name1] and [name2] overlap
	The coordinates of the specified rooms are the same. See *note
	Conflicts::.

    warning: room [name] crossed by link line between [name] and [name]
	A link line passes through the coordinates of a room. See *note
	Conflicts::.

    warning: room [name] has multiple [dir] links
	More than one link connects to the specified room in a particular
	direction.

    warning: can't solve game ([num] tasks not done)
	The game is unsolvable according to the current set of tasks. This
	can be due to part of the map being inaccessible, or IFM stupidly
	choosing the wrong order of doing things. Hopefully the latter
	shouldn't happen very often. See *note Finding a Solution::.

    warning: no matching style command
	You've used 'endstyle' without a matching 'style'. You probably
	have too many 'endstyle' commands.

    warning: unexpected style: [name] (expected [name])
	You've used 'endstyle' with an argument that doesn't match the
	argument of the corresponding 'style'. You might have missed out
	another 'endstyle' somewhere, or have too many.

    warning: style [name] referenced but not defined
	An object in your input uses the specified style, but it isn't
	defined anywhere and the style definition file name.ifm doesn't
	exist in the search path (or if it does, it doesn't define the
	required style).

    warning: [keyword] is obsolete -- use [phrase] instead
	You've used an obsolete keyword. Consult the documentation and
	then try the suggested alternative instead. Note that multiple
	uses of an obsolete keyword only result in a single warning.


File: ifm  Node: Environment, Prev: Diagnostics, Up: Top, Next: Index

Environment
***********

These environment variables are used by IFM:

    HOME	Pathname of your home directory (used to find personal
		init file).

    IFMPATH	Colon-separated list of directories used to search for
		library files.


File: ifm  Node: Index, Prev: Environment, Up: Top

Index
*****

* Menu::

* 'after':                  Limiting Movement.
* 'after':                  Obtaining Items.
* 'after':                  Requiring Tasks.
* 'any':                    Tasks.
* 'before':                 Limiting Movement.
* 'before':                 Obtaining Items.
* 'cmd none':               Task List Output.
* 'cmd':                    Joins.
* 'cmd':                    Links.
* 'cmd':                    Movement Tasks.
* 'cmd':                    Rooms.
* 'cmd':                    Task List Output.
* 'cmd':                    Tasks.
* 'dir':                    Conflicts.
* 'dir':                    Customization.
* 'dir':                    Diagnostics.
* 'dir':                    Leaving Items.
* 'dir':                    Limiting Movement.
* 'dir':                    Links.
* 'dir':                    Map Sections.
* 'dir':                    Rooms.
* 'dir':                    Tweaking the Solution.
* 'drop all except':        Dropping Items.
* 'drop all':               Dropping Items.
* 'drop':                   Dropping Items.
* 'drop':                   Finding a Solution.
* 'drop':                   Items.
* 'drop':                   Losing Items.
* 'drop':                   Movement Tasks.
* 'drop':                   Tasks.
* 'endstyle':               Customization.
* 'endstyle':               Diagnostics.
* 'except':                 Joins.
* 'except':                 Links.
* 'except':                 Rooms.
* 'except':                 Tasks.
* 'exit':                   Room Exits.
* 'finish':                 Finishing the Game.
* 'follow':                 Diagnostics.
* 'follow':                 Limitations.
* 'follow':                 Requiring Tasks.
* 'from':                   Adding Rooms.
* 'from':                   Diagnostics.
* 'from':                   Rooms.
* 'get':                    Items.
* 'get':                    Obtaining Items.
* 'give':                   Items.
* 'give':                   Obtaining Items.
* 'give':                   Scoring Points.
* 'give':                   Tasks.
* 'go':                     Joins.
* 'go':                     Links.
* 'go':                     Other Directions.
* 'go':                     Rooms.
* 'goto':                   Movement Tasks.
* 'hidden':                 Limiting Movement.
* 'in any':                 Task Intro.
* 'in any':                 Tasks.
* 'in style':               Customization.
* 'in style':               Styles.
* 'in':                     Adding Items.
* 'in':                     Dropping Items.
* 'in':                     Other Directions.
* 'in':                     Symbols.
* 'in':                     Task Intro.
* 'in':                     Tasks.
* 'include':                Include Files.
* 'item':                   Adding Items.
* 'join':                   Diagnostics.
* 'join':                   Finding a Solution.
* 'join':                   Joins.
* 'join':                   Map Sections.
* 'join':                   Rooms.
* 'keep':                   Finding a Solution.
* 'leave all except':       Leaving Items.
* 'leave all':              Leaving Items.
* 'leave':                  Items.
* 'leave':                  Leaving Items.
* 'leave':                  Limitations.
* 'leave':                  Movement Tasks.
* 'length':                 Diagnostics.
* 'length':                 Limitations.
* 'length':                 Tweaking the Solution.
* 'link':                   Adding Links.
* 'link':                   Map Sections.
* 'link':                   Rooms.
* 'lose':                   Items.
* 'lose':                   Losing Items.
* 'map':                    Map Sections.
* 'need':                   Limitations.
* 'need':                   Limiting Movement.
* 'need':                   Obtaining Items.
* 'need':                   Requiring Items.
* 'nolink':                 Map Sections.
* 'nopath':                 Tweaking the Solution.
* 'note':                   Adding Items.
* 'oneway':                 Adding Rooms.
* 'oneway':                 Diagnostics.
* 'puzzle':                 Output Variables.
* 'room':                   Symbols.
* 'safe':                   Task Intro.
* 'safe':                   Tweaking the Solution.
* 'special':                Diagnostics.
* 'special':                Output Variables.
* 'style':                  Customization.
* 'style':                  Diagnostics.
* 'style':                  Styles.
* 'tag':                    Adding Rooms.
* 'tag':                    Symbols.
* 'task':                   Task Intro.
* 'task':                   Tasks.
* 'until':                  Dropping Items.
* 'until':                  Tasks.
* canvas_background_colour: Output Variables.
* canvas_height:            Output Variables.
* canvas_width:             Output Variables.
* colour_file:              Output Variables.
* display style:            Customization.
* display style:            Styles.
* environment:              Environment.
* environment:              Include Files.
* environment:              Operation.
* font_scale:               Output Variables.
* game solver:              Dropping Items.
* game solver:              Finding a Solution.
* game solver:              Finishing the Game.
* game solver:              Joins.
* game solver:              Leaving Items.
* game solver:              Limitations.
* game solver:              Links.
* game solver:              Requiring Items.
* game solver:              Requiring Tasks.
* game solver:              Rooms.
* game solver:              Task Intro.
* game solver:              Tasks.
* game solver:              Tweaking the Solution.
* IFMPATH:                  Environment.
* IFMPATH:                  Include Files.
* IFMPATH:                  Operation.
* initialization:           Diagnostics.
* initialization:           Operation.
* initialization:           Output Variables.
* initialization:           Variables.
* inventory:                Items.
* inventory:                Limitations.
* inventory:                Obtaining Items.
* inventory:                Tasks.
* item_text_colour:         Output Variables.
* item_text_font:           Output Variables.
* item_text_fontdef:        Output Variables.
* item_text_fontsize:       Output Variables.
* link_arrow_size:          Output Variables.
* link_colour:              Output Variables.
* link_dashed:              Output Variables.
* link_inout_string:        Output Variables.
* link_line_width:          Output Variables.
* link_spline:              Output Variables.
* link_text_colour:         Output Variables.
* link_text_font:           Output Variables.
* link_text_fontdef:        Output Variables.
* link_text_fontsize:       Output Variables.
* link_updown_string:       Output Variables.
* map section:              Control.
* map section:              Map Sections.
* map section:              Output Variables.
* map_text_colour:          Output Variables.
* map_text_font:            Output Variables.
* map_text_fontsize:        Output Variables.
* maze:                     Map Sections.
* options:                  Operation.
* overlap:                  Diagnostics.
* page_background_colour:   Output Variables.
* page_border_colour:       Output Variables.
* page_height:              Output Variables.
* page_margin:              Output Variables.
* page_rotate:              Output Variables.
* page_size:                Output Variables.
* page_width:               Output Variables.
* PostScript:               Introduction.
* PostScript:               Map Output.
* PostScript:               Operation.
* PostScript:               Output Variables.
* prolog_file:              Output Variables.
* recording:                Limitations.
* recording:                Task List Output.
* room_border_colour:       Output Variables.
* room_border_dashed:       Output Variables.
* room_border_width:        Output Variables.
* room_colour:              Customization.
* room_colour:              Output Variables.
* room_exit_colour:         Output Variables.
* room_exit_width:          Output Variables.
* room_height:              Output Variables.
* room_shadow_colour:       Output Variables.
* room_shadow_xoff:         Output Variables.
* room_shadow_yoff:         Output Variables.
* room_size:                Output Variables.
* room_text_colour:         Output Variables.
* room_text_font:           Output Variables.
* room_text_fontdef:        Output Variables.
* room_text_fontsize:       Output Variables.
* room_width:               Output Variables.
* show_border:              Output Variables.
* show_items:               Output Variables.
* show_tags:                Output Variables.
* show_title:               Output Variables.
* teleport:                 Movement Tasks.
* title_colour:             Output Variables.
* title_font:               Output Variables.
* title_fontsize:           Output Variables.
* Tk:                       Customization.
* Tk:                       Map Output.
* Tk:                       Output Variables.
* tkifm:                    Map Output.
* Unix:                     Operation.
* Unix:                     Output Variables.
* unsafe:                   Dropping Items.
* unsafe:                   Finding a Solution.
* unsafe:                   Joins.
* unsafe:                   Limitations.
* unsafe:                   Limiting Movement.
* unsafe:                   Links.
* unsafe:                   Requiring Tasks.
* unsafe:                   Rooms.
* unsafe:                   Task Intro.
* unsafe:                   Tweaking the Solution.
* variable:                 Customization.
* variable:                 Diagnostics.
* variable:                 Expressions.
* variable:                 Include Files.
* variable:                 Operation.
* variable:                 Output Variables.
* variable:                 Styles.
* variable:                 Symbols.
* variable:                 Variables.
* walkthrough:              Introduction.
* Win32:                    Operation.
