Note on the packaging of the source code and accompanying files.
----------------------------------------------------------------

The Polyadv code (Polyadventure) supersedes the old AD551 game (Adventure
551), and is currently packaged in two parts:

1.  A zip archive in Windows format, containing the game source, walkthroughs,
README and license information.  Note that the filenames are no longer 
converted to upper case, but the end-of-line terminators are the
Windows type i.e. <cr> <lf>.  When unpacking the files to a Unix system,
you are advised to use the unzip command with the -a option (to convert the
line terminators to the Unix type i.e. just <lf>), e.g.

unzip -a polyadv310c.zip

2.  The machine-independent game file - polyadv.gam.   This should work
on any platform, provided that you have a recent TADS 2 interpreter.

License and Copyright Details
-----------------------------


                            Polyadv
                A TADS game with complete source code

                 Copyright (C) 1993 David M. Baggett
                       and (C) 1999-2005 David J. Picton
                       and (C) 1999, 2003 Bennett J. Standeven

   This source code is copylefted under the terms of the GNU Public
   License.  Essentially, this means that you are free to do whatever
   you wish with this source code, provided you do not charge any
   money for it or for any derivative works.  A copy of the GNU Public
   License should be included with this distribution.

   For information on how to play this and other TADS games, please refer
   to the file

   ftp://ftp.ifarchive.org/if-archive/games/playgame.FAQ

Contributors
------------

      Original 350-point TADS port (CCR):
      dmb     In real life:   David M. Baggett
              Internet:       <dmb@ai.mit.edu>
 
      551-point extensions, various bugfixes and enhancements,
      combined modes (701, 701+ points):
      djp     In real life:   David J. Picton
              Internet:       djpicton@gmail.com

      550, 580-point extensions
      bjs     In real life:   Bennett J. Standeven
              Internet:       berry@pop.networkusa.net
                           or bjstande@artsci.wustl.edu

Feedback on the game, including bug reports should be sent to David Picton.
Please note that we welcome ALL types of feedback on the game including 
suggestions for extensions and improvements to puzzles etc.

What Have We Here?
------------------

   This game is a remake of the first major adventure game ever written:
Colossal Cave, otherwise known as "Adventure."   The original Adventure
was written in FORTRAN by Willie Crowther and Don Woods, and was modelled
on a real cavern, called Bedquilt Cave, which is a part of Kentucky's Mammoth 
Cave system.   In its original form, it only had a simple two-word command 
parser.  Its descriptions were so vivid, however, that it captivated a 
generation of computer enthusiasts and quickly became part of the "hacker 
lore."  References to Adventure crop up even today in games and other software.

   Several extended versions of Adventure were subsequently produced, and
this port implements three of them - the 550-point, 551-point, and 580-point
versions - in addition to the original 350-point game.  A 701-point mode, 
which combines both versions, is also available, together with a 701+ point
mode with brand new extensions.  Special commands of the form GAME<vvv>, e.g. 
GAME550, allow you to select the version to play.

   The 550-point game was originally written in Fortran by David Platt in 1979.
It contains many new rooms, extensions and puzzles, and differs from the
original game in one important respect.   There is an element of game design;
a series of puzzles must be solved, each dependent on the last, in order to
explore some of new areas of the cave.  In contrast, the original game gives
you almost complete access to the whole cave once you've dealt with the
snake.

   The 551-point game derives from a 501-point version produced by David Long
at Stanford who rewrote portions of the program to provide a more sophisticated
parser, and greatly expanded the cave.  A castle problem was added in 1984 by
an anonymous writer, increasing the total number of points to 551 points.  Most
of the 'original' rooms are the same as in the 350-point version, but some
treasures have been changed or relocated, and a few directions have been
altered.  Like the 550-point game, the 551-point game requires that you solve
crucial puzzles in order to see certain parts of the cave.  However, it is much
less 'linear' - there is more freedom to choose the order in which the puzzles
are to be solved.

   The 580-point game was originally written by Mike Goetz in 1982, for the 
CP/M operating system. It expands slightly on the 550-point version, adding
one new area, with two treasures, and a few items to use in this area.

   Adventure was such a significant event in computerdom that it
spawned a whole genre of games, made even more popular by Infocom
in the 1980's.  The MIT hackers who formed Infocom took the Adventure
concept and added some powerful new technology to it: sentence parsing.
Their first game, Zork, was clearly very much inspired by Crowther and
Woods' original, but seemed more intelligent and was easier to play
because (like the 551-point version) it could accept simple sentences instead 
of just two-word directives.

   Eventually affordable computers got to be powerful enough to support
general text adventure authoring packages, and by 1992 there were already
nearly a dozen systems for would-be adventure authors to choose from.
This remake was written with TADS, one such adventure writing system, and
was developed from David Baggett's Colossal Cave Revisited.  It was first 
extended by David Picton to include the 551-point extensions (plus a few 
embellishments, e.g. more uses for the rod).  Bennett Standeven then 
implemented the extensions for the 550-point mode, and David Picton 
subsequently added the 701-point mode. Still later, Bennett Standeven ported
the 580-point mode, and David Picton released a new 701+ mode with 
completely new extensions, literally adding a new dimension to the game.  

   Thus Polyadv gives a new generation of adventurers an opportunity to 
play the various versions in a format they will feel comfortable with. Today's
text adventurers have been "spoiled" by the nice sentence parsing that most 
games have these days, and other useful features like the ability to examine 
objects.  It is the hope of the authors that this reimplementation will make 
the original Adventure games -- classics that still shine today -- accessible 
to a wider audience.


Implementation Details and Philosophy
-------------------------------------

   We have tried to be faithful to the spirit of the original games
throughout the project.  To start off on the right foot, David Baggett went 
back to Donald Ekman's excellent PC port of what seemed to be the original
DEC-10 FORTRAN source code.  Don told him he typed a significant
portion of that source in from a paper listing -- now that's
devotion!  In any case, few changes had to be made to get the game
running under DOS, so the source used for the original CCR was largely
"untainted."

   David Picton based the extensions for the 551-point game on the Fortran
sources by Doug McDonald.  The treasures and locations are almost completely
faithful to the original, except for the addition of a few new rooms in the
area of the East End of the Long Hall.  Several game extensions enhance the
gameplay; in particular, the sack is now a 'sack of holding' into which items 
are placed automatically when necessary.  New optional game features make it
possible to increase your weight limit, enhance the magic powers of the rod, 
and protect yourself against the dwarves' knives.  Look out for reading
material which might give clues to these features ...

   Bennett Standeven implemented the extensions for the 550-point game, based
on the UNIX C port by Ken Wellsch.  The treasures, locations and 
magic words etc. are all faithful to the original, and almost all of the
game features have been implemented.  For example, the troll will reject a
certain treasure if you use it as payment more than once.  There are a few 
minor additions to the original game.  For example, the vending machine has 
been upgraded to accept all coins, and (as with the 551-point version) you can
now protect yourself against the dwarves' attacks.

   David Picton subsequently developed the combined 701-point mode, which
contains all the treasures and rooms of the 550-point and 551-point games
(except the 551-point endgame).  It is interesting to note that there
are relatively few conflicts between the two versions, so little new coding was
needed to connect both sets of extended areas to the original 350-point rooms.
The areas of conflict were: the room NE of the Hall of the Mountain King 
(resolved by making the Morion Room lead on to the Throne Room), the 
north-of-reservoir room (different but reached by the same route, resolved
by combining the characteristics of the 550-point and 551-point rooms), 
the sword-in-the-stone puzzle (resolved by keeping both swords in the game) 
and the endgame (for which the combined game uses only the 550-point version).
Most of the work involved new coding to permit 550-point items to interact 
with 551-point NPCs, and vice versa.

   Note that the 701-point inventory handling follows the 551-point pattern 
(you are limited to seven items carried in hand, but containers are provided; 
strength-enhancing actions will increase the weight limit but not the total
bulk of items which may be carried.)  Note that some puzzles which are
optional in the 551-point game are compulsory in the 701-point version; in 
particular, you will need to enhance the powers of the rod to complete the
extensions from the 550-point game.

   The extensions for the 580-point game are based on Mike Goetz' original 
code.  Again, the treasures, locations, and magic words are highly faithful to
the original.

   The 701+ point mode is an extension of the 701-point mode by David Picton.
You play an adventurer with something extra - a sixth sense which allows you
to make crucial discoveries which previous adventurers have missed.  Note
that it is possible to finish the game with a declared 'maximum score' of
701 points, 781 points or even 793 points, depending on the discoveries which
you make.

   Retrofitting such old games onto a more sophisticated game engine
created a few philosophical problems.  Games these days are expected
to have "decorations;" little bits of scenery mentioned in the room
descriptions that you can't actually do anything with, but make
the setting feel more real.  The original 350-point Adventure didn't have many
decorations, and the two-word parser prevented players from trying
things like "look under y2 rock," "put the rod in the stream," etc.  Later
extended versions of Adventure did have more sophisticated partsers. In
particular, the 551-point game allowed commands like 'put axe in sack'
although some modern features were missing - in particular, most objects could
not be examined.   In other cases - particularly the 660- and 770-point
games - the parser has retained the verb-noun model (precluding commands like
'unlock grate with keys') but is modern in other respects; objects can be
examined, multiple objects (e.g. 'take axe and lamp', 'drop all') are
supported, and more scenery objects are provided.

   The approach we took was to add decorations in every reasonable place.
Where appropriate descriptions exist in the original game, we used them, even 
to the extent of making bits of room descriptions serve double duty.

   The new sentence parser created similar problems for game play.
Whereas in the original you had to say "throw axe" to attack something, you 
can now do things like "attack bear with lamp."  There is no analogue to this 
in the original 350-point game; "throw lamp" would be interpreted as a request
to drop the object.  An attempt has been made to stay consistent with the 
overall tone of the originals, but there are some differences; in particular,
"throw" is no longer synonymous with "drop" and an object must be thrown AT 
something; if this doesn't make sense, the command will be rejected.  However,
the old-style two-word commands will often work, because the parser can 
usually choose an appropriate default.  

   For example, "throw axe" will usually default to "at the dwarf" provided 
that you have the axe and there is at least one dwarf at your location, and 
"unlock grate" will default to "with the keys" if they are present at your
location.  Prompting for the indirect object will still occur if more than one 
possibility might be considered, e.g. if you say "throw axe" when a dwarf and 
the troll are both present.  From the beginning we wanted walkthroughs for the
originals to still work in the TADS implementation; this is largely true now, 
though there are a few exceptions.  Since the parser is no longer
limited to two-word commands, it now requires that certain actions (e.g.
opening the clam) be described more precisely to prevent accidental solving.
There are still a few unimplemented features.  For example, the 550-point
mode doesn't yet allow you to throw objects into fissures and chasms.

Hints to Programmers Who Want to Modify Polyadv
-----------------------------------------------

   Polyadv isn't meant to be an unchanging mass of archival source code.  On 
the contrary, we hope that people will add new features, objects and 
locations.  If you do add things, please let us know so we can incorporate 
the changes into the official distribution.

   Modifying any large program is daunting at first.  Fortunately, you 
shouldn't have to pay much attention to the grungy details of most of it, 
since we've tried our best to make it easy to modify.

   With this is mind, here are a few tips to make building and
changing Polyadv simpler:

   * Have a suitable compiler, preferably the latest version.   The current
     version has been compiled and tested using version 2.5.9 but should
     work with compilers/interpreters from 2.5.0 onwards.  Earlier versions
     of the TADS run-time won't support all the language and parser features
     used in the code.   A number of people have complained that Polyadv
     won't compile under the DOS version of the TADS compiler.  It does
     appear that the game is now too large to compile under the DOS version,
     so you're advised to use the Windows or Unix version instead.

   * Make new extensions optional.  This has been implemented in Polyadv
     using flags to the "global" object in ccr-std.t that enable or
     disable new code, objects and locations.  At present the code supports
     six game modes - the original 350-point mode, the 550-, 580- and 
     551-point extended modes, the combined 701-point mode, and a new
     extended version of the 701 point game (701+ point).

   * Use the 'modify' and 'replace' statements where appropriate.  The
     recommended practice - now used in Polyadv - is to use the standard adv.t
     file from the TADS distribution, then to apply user customizations using 
     replace and modify statements.  The separation of user modifications from
     standard code then makes it much easier to upgrade to a new version of
     adv.t.  A similar approach would be useful when extending the game, 
     allowing the new code to be separated completely from the original code. 

   * Use (or at least follow) the makefile.  Depending on the operating 
     system, some of the options in the Makefile are important and you may
     get mystifying error messages if you don't specify them.  Under MS-DOS,
     be sure to compile with the -mp option set large enough, and make sure 
     you make the cache small enough (with the -m option).

   * Use the existing classes whenever possible.  Classes are already
     defined to make your life easy, and Polyadv now makes more use of the
     standard classes as defined in the adv.t library. In particular, class 
     item is now used for portable non-treasure items, fixeditem for immovable
     objects, room for lighted rooms and darkroom for dark rooms.  For reasons
     of clarity, all rooms should be defined with either 'room' or 'darkroom' 
     as the first class in the list.  The CCR_item, CCR_room, lightroom and 
     CCR_decoration classes have been abolished. 

   * When defining new classes or puzzles, copy an existing similar
     implementation and then modify it to suit your needs.  Starting
     from scratch is always harder than updating already-working code.  

   * Note the following nonstandard features of the implementation.
     
     o Code should not assume that the actor is always Me.  This isn't true
       in Polyadv (for example, the bear responds to travel verbs, and
       locations of objects may sometimes have to be evaluated from the
       viewpoint of a dwarf or pirate). 
       
       Methods which don't receive the actor as an argument should obtain
       the current actor as follows:

       local actor := getActor(&prop);
       
       where &prop is the appropriate actor property in the global object:
                      &travelActor  (the actor currently being moved by 
                                    travelTo methods)
                      &currentActor (when determining the location of a 
                                    multiple-location object)
                      &verbActor    (for other purposes; indicates the
                                    actor for the current verb)

       Usually all three will be the same but there may be some exceptions;
       for example, a verb issued by the player might issue Bear.travelTo(...)
       which would change global.travelActor and global.currentActor to 
       Bear.

     o Note the extended argument list of the travelTo method.  In particular,
       the second argument represents a property to be executed within the
       travelTo method, instead of being evaluated beforehand.  The advantage
       of this approach is that the travelTo method can now set the relevant
       global variables, global.travelActor and global.currentActor, before
       the travel properties are evaluated.
       
       Thus the following form:

       actor.travelTo(actor.location, &east);

       is now preferred to:

       actor.travelTo(actor.location.east);
      
     The following classes are defined in Polyadv, in addition to the
     standard set:

     advmods.t
   
        class owntrans - a nestedroom which defines its own Transdindection 
        methods.  An example is the sandstone block.

     ccr-item.t

        class CCR_treasure_item (takepoints/depositpoints must be defined,
                         usually by a method, due to the varying scoring
                         schemes used in different game versions)
        class initmess   (items with a special initial description - these
                         use a heredesc until they have been moved, when
                         they become normal portable items.)
        class condlisted (items which have isListed set when they are carried
                         in hand or in a container, but use the heredesc
                         property when dropped in a room)
        class liquidcont (container for liquids)
        class contliquid (liquid in a container; if there are 'm' containers
                          and 'n' types of liquid, the number of contliquid
                          objects is 'm * n'.  However, they won't necessarily
                          appear in all game versions.  For example, wine
                          does not make an appearance in the 550-point game.)
        class canpick    (for items which the player may attempt to pick)
        class coinitem   (item which may be used in the vending machine)
        class unfixeditem (special class which will make an object portable
                          if given in the class list before any fixeditem
                          classes)
        class portable_chairitem (a portable item on which one could sit)
        class portable_beditem   (a portable item on which one could sit or
                                 lie)

     ccr-itm11.t
        
        class protect_ring - for an object which protects you against the
                             dwarves' knives.
        class pendantItem - for all Transindection pendants (excluding the 
                            discolored disk which cannot be worn)


     ccr-endg.t

        class objpile (pile of objects in endgame)
        class endgame_clone (subclass of CCR_item, object which appears in
                             an endgame pile)
        class endgame_liquidcont (subclass of liquidcont, see endgame_clone)

     ccr-npc.t, ccr-npc1.t etc:

        class NPC (for dwarves, pirate only)
        class Chaser (for NPC's which follow you in extended versions, e.g.
                     the Wumpus, the Gooseberry Goblins, and the Blob)
        class feedable (for NPC's which we might attempt to feed)

     ccr-room.t

        class CCR_doorway         - for non-lockable doors.
        class CCR_lockableDoorway - subclass for lockable doors.
        Special methods in the above classes handle all the special Polyadv
        customizations: different messages for different keys, doors which
        can't be unlocked during a security alert or cave closure condition,
        and sets of more than two doors which all represent the same object.

        class CCR_alike_maze_room (for 'all-alike' maze)
        class NoNPC (room where dwarves and pirate can't go)
        class CCR_dead_end_room (generic dead end)
        class Outside (i.e. outside the cave)
        class Indoor  (indoor locations outside the cave)
        class NotFarIn (inside cave but not far in)

        class makecontents - floating items (mostly of an omnipresent
        type, such as your hands) which can be added to contents lists at the 
        preinit stage.  See below.

        class floatingdecoration - objects which are present in more than
              one location, defined by a loclist.  If the current actor
              is in one of the listed rooms,  the location method returns the 
              relevant room.  Otherwise it returns the first element in the 
              loclist.

        class picklock - for items with locks which the player may attempt to
              pick.
        class roomliquid - a liquid which is available in a room.
        class Streamitem - subclass of roomliquid.  For bodies of water
                           (of which there are now several)

        class rfd (room feature decoration) - subclass of floatingdecoration
              (with a terse default ldesc)
        
        class unfixeditem - special class to override fixeditem, for 
              example when defining portable chairs and beds.  This class
              should appear at the end of the class list.  (N.B. this is
              a subset of fixeditem, so don't test for self.isclass(fixeditem)
              to determine whether an object is a fixed item.  Test the
              isfixed property instead.)

        class upclimable, downclimbable - for objects like stairs which you
        can climb up or down.

        class picklock - for objects (e.g. the chest, doors) with a lock.

        class Blueberries - for blueberry bushes (551-point game)

     ccr-rm1.t

        class Featurelesspit - for the (now-not-quite-so) featureless pits in
        the 551-point game.

        class CCR_boothitem - for phone booths
        class CCR_boothdoor
        class CCR_phoneitem

     ccr-rm2.t

        class CCR_ice_tunnel - for rooms in the ice tunnel maze


     ccr-verb.t
    
        class versionrestart - class for restart verbs.  If you add a new
        game version, you'll need to add one of these.

        class MagicWord - a magic word.  The omegapsical_order and
        omegaps701_order properties are for the Cylindrical Room puzzle in
        the 550-point and 701-point endgames.

        class magicTravelVerb - a travel word with a magic effect (Note that
        'plover' is regarded as magic by Polyadv but not by some other
        versions of Adventure, so its use in the Cylindrical Room puzzle has
        been made optional).

        class wizardVerb - a 'wizard mode' verb.  For game-testing.  These
        verbs only work when the game is compiled for debugging or with
        #define WIZARD; otherwise they are disallowed by the player 
        character's actorAction method.

        class numberedVerb - used by certain wizard mode verbs with
        a disambigDobj method, and (in some cases) the ability to specify
        a number to distinguish between objects e.g. 'gonear chasm number 2'.

        class VaultKeyVerb - a magic word used for opening the safe in the
        550-point game.

   * Note the following properties for rooms (N.B. there are other
       properties which are normally set by defining classes)

     analevel - the Transindection coordinate of a room.  Nonzero values are
        set for many of the rooms in the 701+ point extensions.

     brasskey - the version of the brass key item which is seen in a 
        particular location.  (small_key by default, large_key in rooms
        where the player is small, tiny_key in rooms where the player is
        large).

     contloc - for scoring objects, this is the location or object in which
         an object's container must be placed.  Unless the oldkeep property of
         the object is set to true, this property is ignored in the 
         350-, 550- and 580-point versions of the game.

     createloc - the location of dynamically-created objects.

     depositpoints - the points awarded when an item is deposited in the
        correct location and is no longer in the player's possession.  Due to 
        differing scoring systems, this is usually a method rather than a 
        simple value.

     floordesc - description of room's floor (if hasfloordesc is set)

     hasfloor  - if true, the floor will be called the 'floor'; if nil,
        the 'ground'.

     hasfloordesc - if true, the floordesc method will be used to describe
        the room's floor.

     isfissureroom - set to true at the locations of the fissure in 
        the Hall of Mists, where the rod can be used to create a bridge.
        (Not set at the Green-level fissure, where rods are used in a 
        different way.)

     isolated - set to true when a room with analevel=0 (Red level) can only
        be reached with the aid of Transindection movements.

     istoproom - set to true when a room is contained in another room (e.g.
        the pantry in the building) but is to be regarded as a top-level
        room when the player is inside.

     nofloor - true if the room has no floor.

     outercontloc - for a scoring object, this is the required location
         of an outer container (e.g. the wine must be placed in
         the cask (targloc=cask), the cask must be in the chest 
         (contloc=treasure_chest) and the chest must be in the building
         (outercontloc=Inside_Building).  Unless the oldkeep property of the
         object is set to true, this property is ignored in the 350-, 550- and
         580-point versions of the game.

     roomdroploc - location of room to which an object will fall (e.g.
        when objects fall down to a lower room)

     smashdrop - if true, fragile objects dropped in this room will break (used
        when objects will drop to a lower room; the vase will shatter and the 
        vial will release its contents.)

     softfloor - a room has a soft floor, so fragile items can be safely be
        dropped.

     takepoints - the points scored when an object is first taken.  Due to
        differing scoring systems this is usually a method rather than a simple
        value.

     targloc - for a scoring object, this is the room or container in which
         an object must be deposited before its full score is given.  Unless
         the oldkeep property of the object is set to true, this property is 
         ignored in the 350-, 550- and 580-point versions of the game (which
         hardcode the target location to the building).  

     transmove(prop) - where prop can be a destination room or a property
         pointer for a travel method (by default, evaluated relative to the
         top-level room).  Used in transindection travel and also size-changing
         travel outside the elfin door.  If a player is in a transportable
         vehicle (isfixed=nil or istransportable=true) the player will be
         conveyed in the vehicle.

     version_NoNPCs - optional method for a room, returning 'true' if
        the dwarves and pirates are to be excluded from the room in a
        particular game version.


   * Note also the following properties for actors

     roomMoveTravel(&moveprop,dest) or
     roomMoveTravel(&moveprop,dest,&prop)
     Move the actor to another room to another, along with any portable items
     in the room.  If the actor is in a nestedroom (e.g. standing on the rug),
     convey the actor in the nestedroom.  The moveprop argument should be one
     of &moveme (always convey the nestedroom) or &transmove (convey the
     nestedroom only if it is 'transportable': isfixed=nil or 
     istransportable=true).  The optional third argument is a travel property;
     if it is given, the destination room will be dest.&prop.

     vehicleTravel(&moveprop,dest) or
     vehicleTravel(&moveprop,dest,&prop)
     Move the player or convey the player in a nestedroom in which the player
     is located.  See roomMoveTravel.

     posture - set by the code to one of 'sitting', 'standing' or 'lying' to
     indicate the posture of a player when in a nestedroom.  


   * Note the following properties and methods, mainly for items
      
     accepts_item(dobj) - Method for containers, returning true if an
        object is suitable for the container, nil otherwise.  This
        method is required for 'sack of holding' objects so that items which
        won't go into the container can be silently excluded.  

     bothsides - for items, reachable from both sides of the dragon. 

     contname - the short name for a liquidcont item e.g. "bottle"

     emptydesc - sdesc to be used for an empty liquidcont item e.g.
        "small empty bottle"

     hasoil, haswater, haswine - for objects of type liquidcont, one of
        these properties can be set to true to indicate that the
        container is filled with the relevant liquid.

     isInside(location) - this evaluates to true if the item is inside
        'location', regardless of visibility.  (The standard isIn() method
        returns nil when the item is hidden inside a closed container.)

     islighted - returns true if the object is in a lighted room or
        container.  

     isListedinRoom - indicates that an object is to be listed in the 
        room description when it's in the room's contents list.  By 
        default this is the same as isListed, but certain special classes
        (initmess, condlisted) set isListedinRoom to nil and use a heredesc
        method instead.  See the description of the modified 
        nrmLkAround routine below.

     quickdest - for doors, returns the destination of the door, or nil
        if the player can't go through without explicitly opening the door
        beforehand.

     quickdest(loc) - evaluates the doordest as seen by an actor in the
        room defined by loc.

     doordestOK - for doors, indicates that a doordest method is safe for use
        by quickdest.

     list - when an object or class is used for dynamic object creation,
        this property will contain a list of the dynamically-created objects.

     mass - the weight of an object in the 551-point and 701-point game.
         The weight is set to 0 in the 350-point and 701-point games which
         only take into account the bulk of the objects which are
         carried.  

     misfit(io) - for lockable items, issues a message according to the key
         which the player has attempted to use.  For example, the set of
         keys produces a different message from a single key.

     moved - if true, indicates that an item has been moved from its initial
        position.  (Note that if an 'initmess' object has to be put in place
        during the game, its moved property should be set to nil so that
        it will display its initial description.)

     nosack - true if an object is not to be placed automatically into a 'sack
        of holding'

     objclass - in the construct method for dynamically-created items,
        this property is set to the class e.g. fresh_batteries.

     sdescbase - for liquidcont methods, this is the base for the sdesc
        when the bottle is full.  For example, if sdescbase is "small bottle"
        the sdesc (when the bottle contains water) evaluates to
        "small bottle of water"

     * Note the following functions
    
     asknum(prompt,errorstring) - function to prompt for a number

     addmass(list) - like addweight but includes items which are worn.

     droploc(location) - the room to which an object goes when dropped

     getActor(&prop) - retrieve the actor.  This function is useful in 
         methods for which the actor is not passed as an argument.

     nestcontents - lists the contents of an object including nested
         containers (used in score checking)

     obj_switch(oldkey,newkey) - switches two objects (used for the brass
         key which can be one of three objects)

     room_move(oldroom,newroom) - moves all nonfixed items from oldroom to
         newroom.


     sack_of_holding(actor, o, lftbulk) - implements a 'sack of holding' like
         the Curses rucksack.  Returns 'true' if the object 'o' could be
         placed in an appropriate container.  The optional lftbulk parameter
         is supplied as the bulk available to the player (see advmods.t for 
         examples).

     testtake(actor,object) - function to attempt to take an object during
         the processing of a command where an 'implied take' is appropriate.
         Returns true if the object could be taken, nil otherwise.  Takeable
         items with the noImpliedTake property return true without attempting
         to take the object.

     toplocation(item) - returns the 'top-level' room in which the item
     is situated.  The search for the top level will be terminated if a
     room has the istoproom property set to true.

     truetop(item) - returns the true top-level room in which item is situated.

     vertesttake(actor,object) - function to be called during verification
         to check that an object is capable of being taken.  Returns true
         for fixed items, nil for non-fixed.  The appropriate verDoTake 
         method is invoked except for objects for which noImpliedTake
         is true.  

   * Note that the handling of items with multiple locations has been
     improved.  For efficiency reasons, many items are no longer handled
     as floating objects - instead, they are installed in contents lists
     alongside objects with normal location properties:

    o Items in class floatingdecoration, in which the loclist property
     contains a list of rooms in which is the object is to be found.  If the
     loclist property needs to be changed, you are advised NOT to set
     the loclist property directly.  Instead, you should use the special
     moveLoclist method to ensure that all the rooms' contents lists will
     be updated. The loclist property should NOT be changed directly; instead,
     the special moveLoclist method should be invoked to update the rooms' 
     contents lists.  

     * Note that it is OK for loclist to include rooms which
     aren't in the game version being played.

     * Care must be taken if the player can enter the object.  (For an
     example, see the location method for In_Safe).

    o Other floating items in the makecontents class.  This is intended for
     objects which can sensibly be placed in the contents lists of rooms at
     the preinit stage.  The location method should return the player's
     location if the object is present at that location, or nil otherwise.
     The location method must not
        * depend on anything which might vary from one game to the next, 
          e.g. the game version or time of day
        * change during the execution of a game

     The list 'global.noall' specifies objects which are not to
     be included when you use ALL in a command.  This is mainly intended for
     omnipresent items like your hands, the floor and the air, which are
     now all included in the contents lists of rooms.

   * Take care when checking whether a room, container or surface is empty.  
     The contents list may contain invisible objects of class makecontents, so
     you may not get the right result if you check the length of the 
     contents list.  Instead, you should use the itemcnt function to check
     for listed items.

   * When coding new rooms, follow the convention that significant fixeditems
     will appear in the room description whether or not it is in 'brief'
     or 'verbose' mode.  To achieve this, give the object a 'heredesc' 
     property (which should normally start with P(); I();) instead of
     incorporating its description into the room's ldesc property.  The
     modified nrmLkAround method (see below) will then always list the 
     item.

   * Set global.debug to true to get extra information about room 
     connections and NPC movement at run-time.  The game will check
     its connections to make sure everything's OK at run-time.

     Add new debugging code enabled by this flag for your own
     extensions.

   * The room.nrmLkAround method has been customized in a number of ways.

     The order of printing is now:

     Room title

     Verbose room description (when listing is in 'verbose' mode e.g. when
     a room is first seen or the LOOK command is used)

     heredesc methods for fixed items (including floating items which don't
     appear in the room's contents list but whose location method evaluates
     to the room) and and for portable items which have the
     has_heredesc property set to true.  Each heredesc method should start 
     with P(); I(); so that the text will appear as a separate indented 
     paragraph.  In Polyadv these descriptions are always printed, even in
     'brief' mode.  

     Non-treasure items (except those with isListedinRoom= nil)
     Treasure items     (ditto)
     Contents lists of containers and surfaces
     
     actorDesc methods for actors, including 'floating' actors.   These 
     should also be methods starting with P(); I(); to ensure that each
     description starts a new paragraph.  If you want the actor description
     to appear earlier, set actorDesc to {} and define a heredesc instead.


Some Ideas
----------

   Here are a few things that we considered doing ourselves, but decided
to leave as exercises.  Some of the ideas for the original CCR (e.g. 
hints) have now been implemented, but others have been left as an exercise.
(Yeah, that's the ticket.)  They range from fairly trivial to incredibly 
time-consuming:

   * Make the NPC code more faithful to the original.  For example,
     dwarves should block your way when you try to return to your previous
     location.  (The trick here is to work out the player's intended
     destination without actually going there.  To avoid unwanted side effects,
     you wouldn't be able to evaluate the travel property e.g. &north when it's
     a method.  The exithints property might be useful here.)  The
     pirate code could also be made more like the original, in which the
     pirate would 'shadow' the player until a treasure was found, then pounce!

   * Make the NPC movement code faster.

   * Implement more "extended" versions of the game, e.g. the 430-point and/or
     440-point versions.  The complete source and database for the
     440-point game have recently been rediscovered - see vscheme.txt, and
     Mike Arnautov has recently released the 660-point game. 
     Note that old versions of Adventure generally came without copyright 
     statements and have in practice been regarded as 'public domain' 
     (although the legality of this view is questionable.)  However, more 
     recent versions usually do come with a copyright statement - please read
     it and contact the author if you are in any doubt.

   * Add your own NPC's, puzzles, or locations.   

   * Port TADS to new machines so that Polyadv has a wider audience.
     (Contact Mike Roberts for more info.)

Whatever you do, please send us your changes!

Special commands for game testing
---------------------------------

If your game is compiled for debugging, certain special 'wizard mode' commands
are made available to the player.  These include:

PURLOIN - obtain an item 'from thin air'

PURLOIN <item>  - obtain a given item.

PURLOIN <item> NUMBER <n> - obtain the nth object which matches the
noun phrase, e.g. PURLOIN RING NUMBER 3.

SUMMON <npc>
Make a dwarf, pirate or Chaser NPC appear at your location.  

BANISH <npc> - banish the NPC.

PIRLOC - show the locations of the pirate and dwarves.

GONEAR <item>  - go to the room containing <item>

GONEAR <item> NUMBER <n> - see PURLOIN.

LOCSEL <number>
This command only affects the next GONEAR command, and does nothing unless
the object has a loclist.  If it does, the <number> specifies the loclist 
element to use.  By default, the first loclist element is used.

Example:  LOCSEL 3. GONEAR JUNCTION

LAMPLIFE        - display the number of turns left in your lamp.
LAMPLIFE <n>    - set the lifetime of your lamp.

NUM-DWARVES <n> - set the number of dwarves to <n>.  This command is only
                  effective if it is issued early in the game, before the
                  dwarves have started in motion.

NUM-PIRATES <n> - as above, for the pirates.  (By default there is only one
                  but there is provision for larger numbers).

SCORETOTAL      - display the total score.

See also
--------

The file vscheme.txt has details about the game version handling and
numbering scheme.   This has been expanded to give advice about the
production of new versions which are extensions of existing ones (for
example, the 580-point version is an extension of the 550-point version, and
a few simple defaults allow the 580-point game to inherit all the 550-point
extensions automatically.)


