==================================
Jeffs Supplementary TADS functions
==================================

This library consists of all the additional functions, classes and objects
that I have written over the last two years in order to make some of my
game projects possible.  Whilst doing so, I decided that it was important
to be able to carry any new functionallity along with later revs of TADS
and that I should be able to share it with the rest of the world.

Caveat:  Some of it is still under development and will most likely change
over time.  However, most of it is stable now and changes are likely to be
backward compatible anyway.

I have made the following changes to my copy of adv.t over the years.
These changes need to be applied every time a new revision arrives to
ensure compatibility with the library.

-       add default 'weight' and 'bulk' to class 'thing.
-       travelTo(room) should use moveInto() instead of manipulating the
       location.contents list directly.
-       remove basicMe.moveInto() method completely
-       set lookVerb.sdesc to "look at"
-       remove function 'goToSleep' - this is handled by bodyfunc.t

=== version.t ===

The most important problem to be solved (imho) in distributing a game
based on a large number of software components is that of keeping track of
versions that are released.  If a beta-tester reports that a particular
problem happens in a section of code that you have edited 5 times since,
how do you tell whether the problem was fixed already?

This module provides two basic facilities.  The first is that it defines a
class called 'versionTag' which is used to document the version number of
source files.  For example, the file 'heartbeat.t' has the following

       heartbeatVersion: versionTag
           id="$Id: heartbeat.t_v 1.3 1994/05/09 07:35:47 jeffl Exp jeffl $\n"
           author='Jeff Laing'
           func='heartbeat monitoring'
       ;

The verb 'sources' will automatically scan all objects of class 'versionTag'
and will perform the method "id", thus printing out whatever arbitrary
message is displayed there.  I use RCS to keep the field populated with the
latest checked-in version number.

The other fields 'author=' and 'func=' are used by the verb 'credits'.
This is used, primarily, to ensure that you give credit where credit is
due.  For example, one game in progress currently does this...

       >credits
       The following modules were provided by TADS developers
       who were prepared to share their work with others:

       Version & credit tracking, system verbs, utility
       functions, smarter floaters, bodypart support, look
       code, darkness support, enhanced travelling, heartbeat
       monitoring, real actors, actor dialog, organized
       violence and timer management were provided by Jeff
       Laing.

       Footnote support was provided by David Etherton
       ([email protected]).

       Scoring was provided by Jeff Laing with suggestions
       from Mike Roberts and Dave Baggett.

       If you are a TADS developer, please consider doing the
       same.  All the above mentioned modules should be
       available for ftp from the interactive-fiction archive
       maintained by Volker Blasius on ftp.gmd.de.

Most components of this output are actually user-configurable so that you
can make the text match the feel of your game.

=== sysfuncs.t ===

This module is largely a rewrite of std.t, incorporating some other
output changes from the net and providing some new, useful, features
for supporting modular libraries, etc.

Having lots of self-contained modular libraries creates havoc when
initialization is required.  Typically, the user has to edit their std.t to
include code in preinit() or init().  No longer!

The preinit() provided in this module scan the world for objects of class
"initialization".  If found, the method calls "preinit_phase()" for each of
them and arranges for "init_phase()" to be called at init() time.  This
allows a library module to define its own behaviour to be performed at compile
or startup time without editing standard libraries.  For example, sysverbs.t
contains the following

sysverbsTag: versionTag,initialization
   id="$Id: sysverbs.t_v 1.3 1994/05/09 03:29:30 jeffl Exp jeffl $\n"
   func='system verbs'
   author='Jeff Laing'

   /*
    * called by preinit()
    */
   preinit_phase={
       local o;
       global.scrambler_list := [];

       // search for scramblers and remember them
       for (o:=firstobj(game_scrambler);o<>nil;o:=nextobj(o,game_scrambler)) {
           global.scrambler_list += o;
       }
   }

   /*
    * called by init()
    */
   init_phase={
       if (global.restarting)
           notify_scramblers(#restartedGame);
   }
;

When preinit() runs, it performed sysverbsTag.preinit_phase (which builds
internal lists for later processing).  Similiarly for init_phase.

When init() is finished, it calls the function gameinit() which is where
the game specific initialization should go.  This allows a programmer to
have their own initialization that won't need to be re-written when the
next version of TADS comes along, requiring more in init().

I have used the "initialization" feature to move all of the standard init
sequence out of std.t and into seperate libraries.  The advantage of this
has been to remove the need for "eat/sleep" code if you don't want it.
Just don't include it at compile time!  Other optional features can
disappear in the same way.  Or, if you wish to write more complicated
code that will be reusable in more than one game (hint, hint, let others
use it as well), you can write it as an auto-initting module which can be
included into other games *without changing one line of code in them*.

=== score.t ===

Nothing is as important (in a *game*) as getting a score.  After all, how
do you tell how well you have done against the author of the game unless he
begrudgingly hands out points for achievement.

This module was based, very loosely, on code that has been around for ages.
Others have posted variations on this theme, and I have certainly learned
from them.

Scoring is loosely based on two different types of achievement.  The
preinit_phase() is responsible for collecting all scores and calculating
a possible maximum.

The first scorable just corresponds to getting somewhere difficult.
For example, it may be worth 10 points to reach the "Pinnacle of Human
Experience" room.  To provide this feature, merely modify the room
definition to include the 'room_value' method.  i.e.

       thePinnacle: room
               sdesc="Pinnacle of Human Experience"
               room_value = 10
       ;

The second scorable corresponds to the notion of a "treasure".  The module
provides one class called "treasure" and another called "repository".
Scoring is implemented as follows...

-       The first time that "treasure" moves into "Me.contents", the
       players score is increased by "treasure.find_score" and then
       "treasure.find_score" is set to zero.

-       Whenever a "treasure" moves into a "repository", the players score
       is increased by "treasure.keep_score".

-       Whenever a "treasure" moves out of a "repository", the players
       score is decreased by "treasure.keep_score".

The module provides the pseudo-standard "Your score just went up" messages
and allows the verb "NOTIFY" to turn this feature on/off.

To add your own scoring mechanism (i.e. something which doesn't use either of
the two schemes), just use the method "scoreobj.adjust(amount)" to change
the players score.

The scoring module is also responsible for kicking the random number
generator in my library.  The library then provides Dave Baggett's verb
"norandom" which allows scripted-walkthroughs to be recorded that can
actually be replayed.  This allows the scoring module to determine whether
the player deserves a real rating or not.  (At present, this information is
not used)

All features of the scoring module are attached to the object "scoreobj"
and are available as method calls, thus allowing programmers the flexibility
to define behaviour if required.

=== heartbeat.t ===

This module is intended to cut down on the number of individual daemons
which are required by a TADS game.

Every object which has a method called "heartbeat" will be collected into a
list (at preinit time).  Once per turn, the objects "wantheartbeat" method
will be tested; if it returns true, the objects "heartbeat" will be
called. Effectively, the code performs as follows.

       for all obj in heartbeatlist
               if (obj.wantheartbeat)
                       obj.heartbeat;

This can be used, for example, in candles & lights which would have the
wantheartbeat method just return (self.lit) and the heartbeat let the
candle melt down or the light's battery run down.  Wandering monsters can
be enabled based on the players location.  i.e.

       wantheartbeat=(isclass(Me.location, inmonstermaze))
       heartbeat={ ... code to move monster around ... }

This will call the monsters "heartbeat" method only while the player is in
a room which has been tagged as class "inmonstermaze".

=== utility.t ===

This module just contains a couple of useful utility functions which may or
may not be useful.  I use them for debugging and other common list
traversals that verbs need.

saylist(list)   - this will dump out a list of objects, by their sdesc
               method.  This is a debug macro only and should not be used
               in a finished game.

allwithprop(loc,prop)
               - look through loc.contents for all objects for which the
               specified property returns true.  The fight verbs uses this
               for defaulting -- ... := allwithprop(loc, isweapon);

=== timers.t ===

Keeping track of timed appearance and events can be a real pain.  Once upon
a time, TADS used to barf if you did an unnotify() without the corresponding
notify() - fortunately, this is no longer the case.

This module provides a number of entry points which correspond pretty
closely to the standard TADS functions but which take an extra argument
which can be used for diagnostic information.

Basically, the calling sequence is the same as the tads function but the
name is *all* uppercase and there is an extra string argument (which is
just descriptive text)

If you set "timer_info.debug := true", the timer routines will all announce
as they are being executed.

The routines will also catch the case where an unnotify has been called
without a corresponding notify and issue a warning message (since I
consider this to be a bug).

Since it is impossible to detect when a notify/fuse/daemon has triggered,
there are three extra routines which are used for the list management.
These are "FORGET_NOTIFY, FORGET_FUSE and FORGET_DAEMON".  Typical usage of
these functions is as follows.

       // Player will be fried 6 turns after entering this room
       enterRoom(a) = {
               inherited.enterRoom(a);
               if (a=Me) NOTIFY(self,&intruder_alarm,6,'entered vault');
       }

       // this method is called when the player has been in this room just a
       // bit too long...
       intruder_alarm  = {
               FORGET_NOTIFY(self,&intruder_alarm,'bank alarm triggered');

               if (Me.location = Vault) {
                       "\bA metallic voice says, \"Hello, Intruder!  Your
                       unauthorized presence in the vault area of the Bank
                       of Zork has set off all sorts of nasty surprises,
                       several of which seem to have been fatal.  This
                       message brought to you by the Frobozz Magic Alarm
                       Company.\"";
                       jigsup(true);
               }
       }

Caveat: At present the code for knowing about daemons and fuses in progress
does not work due to a bug in TADS concerning the storage of function
pointers in lists.  Mike Roberts is aware of the bug and it will hopefully
be repaired in an upcoming revision of TADS.  Until then, only the notify()
code is implemented in a useable fashion.

=== footnote.t ===

This module borrowed from the one previously provided by David Etherton
(and gives credit appropriately; see the versionTag) and built on his
work.  I made a number of changes to it from a look-and-feel perspective
and distribute it here only because it's now part of my standard library.

He wrote it originally.  I didn't.  He deserves the credit.  I am just a
satisfied user (who tweaked with it slightly)

Disclaimers aside, the differences I have added are...

- object names have been changed, to avoid namespace collisions
- wherever possible, functions are replaced by method calls to allow for
 easier overriding of behaviour.
- a help message is added (ala Adventions.  Thanx guys)
- an error message is displayed if the number is not specified
- reading footnotes doesn't cost turns.

Using David's example, the code should be used as follows...
       ...
       #include <footnote.t>
       ...
       gameinit: function
               footnote.helpmsg;               // give footnote intro
       ....
       desk: ....
            noun = 'desk'
            adjective = 'fine' 'oak'
            sdesc = "fine oak desk"
            ldesc = {
               "The desk is stained a deep brown color, and has that wonderful
               rustic appeal of a Norman Rockwell painting. ";
               footnote.new(  'In fact, this entire room looks like an
                               explosion at a Normal Rockwell factory.'
               );
            }
       ...
       > EXAMINE THE DESK
       The desk is stained a deep brown color, and has that wonderful
       rustic appeal of a Norman Rockwell painting.  [3]
       > FOOTNOTE 3
       [3]. In fact, this entire room looks like an explosion at a Norman
       Rockwell factory.

=== actor.t ===

This module is definitely not complete but represents the beginning of a
framework that supports actors that you can give things to and who will
respond to instructions.  For example, the following comes from a game in
progress.

       > LOOK
       Entrance
       You are standing in the entrance to a large building.
       Jane is here.
       John is here.  John seems to have a sword.
       > TAKE SWORD
       John is carrying the sword and won't let you have it.
       > JANE,TAKE SWORD
       John is carrying the sword and won't let her have it.
       > JOHN,GIVE SWORD TO JANE
       Jane accepts the sword gladly.
       > JANE,INVENTORY
       Jane has a sword.
       > JOHN,INVENTORY
       John is empty-handed.
       > JANE,HIT JOHN WITH SWORD
       John doesn't understand why Jane attacked.  Feeling foolish, Jane
       desists before any damage is done.
       >JOHN, NORTH THEN LOOK THEN SOUTH
          John leaves the area.
       Other room
          John is in the other room.  South leads back to the startroom
          John enters the area.
       >

and so on.  Its by no means complete nor is it without its bugs.  It does,
however open up a framework in which more complicated actions can be
experimented with.  For example, should you see the description that John
sees when he goes into the other room or should it be deferred until he
returns to you?

I use bits of it already and want to use more in the future so I will
continue to change/expand/etc. the whole thing.  In fact, as currently
distributed it has a bunch of debug messages which will need to be deleted
before it can be useful in any released software; I have left the messages
in because it helped me find problems in routing verb processing from
indirects to directs, etc and found the problem that "lookVerb" did not
have an "sdesc" property.

=== askme.t ===

This is a generalised question/answer module which only really works to
provide the framework for NPC information ability.  It should be able to be
tied in to other schemes that have been discussed on rec.arts.int-fiction.

The method used is based on the suggested technique in the TADS manual (did
I suggest you register?  You should!) but with an extra indirection added.

Each "actor" needs to have a property called "askme" which should be set to
a property pointer.  This pointer is then used to find information that
this actor knows about any other object.  For example, if our two actors
John and Jane are implemented, they would look like this ...

       John: maleactor
               askme=&askJohn
       ;
       Jane: femaleactor
               askme=&askJane
       ;

and then we add information to each of our other objects in the game.

       football: item
               askJohn='It\'s a present I got from my father'
               askJane="It smells!"
               askAnybody(askedactor)='You throw them.
                               Thats why they call it a football'
       ;

> ASK JOHN ABOUT FOOTBALL
John says "It's a present I got from my father"
> ASK JANE ABOUT FOOTBALL
"It smells!"
> ASK JEFF ABOUT FOOTBALL
Jeff says "You throw them.  Thats why they call it a football"

In this last case, an actor who didn't have the "askme" property defined,
or for whom there was no specific information recorded against the "football"
object, the "askAnybody(askedactor)" method is used.

The methods are also inspected to determine whether any special formatting
needs to be done.  If the "askXxxx" method is of type single-quoted-string
(as the examples above were), the response will be displayed as follows.

       <<askedactor.thedesc>> says "<<object.askXxxx>>"

If the method is of type double-quoted string or procedure, it is just
executed directly with no special formatting.  If it is any other type, a
vanilla "I don't know about that" message is displayed.

There are a couple of trivial exceptions that are also built into the
module as an aside.  Getting one actor to ask another about you (the player)
results in various gags of very low laugh-value.  Asking yourself questions
is bizarre as well.

=== sysverbs.t ===

This module provides support for what I consider the "smart-ass"
non-player character.  Suppose we have the classic "lady behind one door,
tiger behind the other" puzzle and we have given a reasonable number of
clues to the player but they haven't bothered to think and just use

       "OPEN DOOR 1. UNDO. OPEN DOOR 2"

To combat this, I have introduced the notion of a "game_scrambler".  This
object would be able to detect whether the player has opened the door
already and actually intercept the "undo".  For example, one game in
progress looks like this ...

       >undo
       [Undone 1 turn]

       Inside the Entrance
       You are standing just inside the entrance to the fun-park.  Outside (to
       the south) you can see orange mist that seems to surround this place.
       There is a carnival barker standing here.

       The barker leans over and says "If you use undo, we reserve the right
       to change the games!"

The same traps can be applied to save and restore

       >save "xxx"

       [Saved as "xxx"]

       As you finish saving, you notice that the barker has just given you a
       big wink as though he realised what you were doing.  You get an uneasy
       feeling that this might not be as easy as it looked!

       >restore "xxx"

       [Restored "xxx"]

       Inside the Entrance
       You are standing just inside the entrance to the fun-park.  Outside (to
       the south) you can see orange mist that seems to surround this place.
       There is a carnival barker standing here.

       The barker leans over and says "I hope you wern't hopin to cheat us
       honest carny folk by just guessing the answers.  We know about that
       stuff and we just mix things up again while you're away!"

You can even trap restart if you wish (which is getting a mite paranoid in
my opinion but hey, paranoids are right sometimes!).

At present, you can only trap *after* the verb has occurred.  I may allow
scramblers to actually disallow those verbs if the need arises.

The module also provides some other cosmetic niceties like "UNDO 5" which
will roll back 5 turns, and allowing a save at "quit".  i.e.

       >quit
       In 7 turn(s), your score is 0 out of a possible 1.  This gives you the
       rank of Beginner.

       If you wish, you can save before quitting.

       Do you really wish to quit now?  (Y=yes, N=no, S=save) >S
       File to save game in > XXX

One last function is jigsup() which can be called whenever the player has
"died".  This works in the same way as the standard die() but takes a
parameter which indicates whether undo should be allowed or not.

=== travel.t ===

The first big project I worked on (and in fact haven't finished yet) is a
port of Dungeon (Zork).  One of its neat features was a sword that glowed
when a bad-guy was "nearby".  Implementing "nearby" checking was impossible
with the current TADS structures and eventually I decided to change them as
little as possible but with as much flexibility.

To each motion vector (north, west, southeast, etc), you need to add an
extra parameter (actor).  If this parameter is 'Me', the method should
perform normal operation since it is the player actually travelling in that
direction.  If the parameter is 'nil', the method should just return the
actual room that can be reached (or nil) because this is being called by a
'probing' method.

The module also provides the ability to destroy a room completely (Dungeon
needed to be able to blow one up and to fill another with poison gas). The
following fragment ...

       loc.kaboom('The path ahead is blocked by rubble.');

.. will stop the location 'loc' from being entered and will display the
specified message instead.

The module provides a verb called 'exits' which will display a message that
shows all the exit directions that can be used from the current room.

       > EXITS
       [It would appear that you can go east, west, in or out]

However, in order to diffuse mazes, etc, there is a hook.  If you replace
the "room.roomexits" method with one which returns a message, that will be
displayed.  Thus..

       class mazeroom: room
               roomexits='Hey, its a maze.  I don\'t know any better than you'
       ;

       > EXITS
       [Hey, its a maze.  I don't know any better than you]

If the roomexits method returns anything other than a list, it will be fed
into "say()".

=== wallpaper.t ===

Floating items always seemed to confuse me so I sat down and tryed once and
for all to nail down exactly why they did/didn't work.  This module
includes the standard processing that I now apply to floaters.

Class 'wallpaper' is a subclass of 'fixedItem' and 'floatingItem'.  I make
the assumption that you can never 'take' the wallpaper.

Any room where wallpaper can exist should have a list property that
contains the wallpaper items that exist there.  For example, one game which
has a lot of orange mist scattered around in it defines it ...

       orange_mist: wallpaper
               noun='mist'
               adjective='orange'
               sdesc="mist"
               ldesc="The mist is orange.  Nothing more exciting that that."
       ;

and then the rooms where it is visible do this ...

       startroom: room
           sdesc="Orange mist"
           ldesc="     You seem to be standing in an orange mist.  There
                       appears to be a light to the north."

           floating_items=[orange_mist]
       ;

All verbs should now be able to refer to the "orange mist" in any of the
rooms which include it.

This module has also redefined a number of the low-level methods used in
object disambiguation and verification to be interceptable by other
modules.  Thus, darkness can be implemented in a more sensible fashion,
bodyparts can work, etc.

=== bodypart.t ===

Body parts are a little problematic in TADS.  Sure, most players have two
hands, two feet, etc.  However, no-one wants to see the following...

       > INVENTORY
       You have a left hand, a right hand, a head, a torso, a left foot, a
       right foot and a torch (providing light).

On the other hand, its annoying to see the following

       > OPEN JAR
       What do you want to open the jar with?
       > HANDS
       I don't know the word "hands"

This module implements body-parts as wallpaper that is located inside the
player.  All of the code related to "all" objects (inventory, doDefault
methods, etc) are adjusted to not return body parts unless they are
explicitly mentioned by the player.

There will still be the annoyance to the player that the above dialog will
now look like

       > OPEN JAR
       What do you want to open the jar with?
       > HAND
       Which hand do you mean, the left hand or the right hand?

but I think this can still be conquered if needed.  More work required.

=== look.t ===

This module mimics the existing "look" methods provided in TADS but allows
another variation.  At present, the default method will print ...

       > LOOK
       Play Pen.
               You are currently standing in the play pen.
               There is a dinosaur, an armchair and a pound of butter here.

In order to add to the "fiction" part of "interactive-fiction", we would
prefer to have

       > LOOK
       Play Pen.
               You are currently standing in the play pen.
               Over to one side is a small plastic dinosaur which has been
               gnawed on by the child who seems to be absent.
               There is a large armchair which looks quite comfortable and
               yet the bloodstains fail to make it look welcoming.
               On the ground is a pound of butter which seems to be melting.

This module allows objects to have an extra method called 'hdesc'.  The
code in look.t will automatically detect this method and will use it
instead of just constructing the list of objects.

However, in some circumstances, an object will decide that it doesn't want
to be listed specially.  For example, the first time you see this room, ...

       > LOOK
       The Stone Room
               ....
               Lying on the ground is the most magnificent sword you have
               ever seen.

However, once you have taken the sword, played with it a while, carried it
somewhere else, etc, the description should become

       > LOOK
       Play Pen
               ....
               There is a sword here.

In order to provide this flexibility, the method 'has_hdesc' is used.  By
default, this will return true if the method 'hdesc' exists.  Objects can
have custom versions which only return true when they require special
output.  A lot of my code looks like this ...

       sword: item
               hdesc="Lying on the ground <blah, blah>"
               has_hdesc=(self.istouched)
               moveInto(loc)=
                       inherited.moveInto(loc);
                       self.istouched:=true;
               }
       ;

so that the sword will maintain its long description until it is moved
somewhere other than its original location.

The look code understands about wallpaper and will not describe it by
accident.

=== darkness.t ===

The original implementation of darkness in TADS was pretty simple.  Either
a verb worked in the dark or it didn't.  Its quite apparent that "drop"
should definitely work, even in the dark, but it didn't!

This module adds a new method to each of the verbs called 'validDark'.
This method allows the verb to specify whether it operates in the dark or
not.

The module provides patches to three verbs as samples. "INSPECT X" will
work currently if X is held by the actor.  "TURN ON X" will also work if X
is held, thus allowing the "TURN ON TORCH" that sensible players do when
plunged into darkness.  "READ X" will not work but will report a customised
error message.

The module also patches into the "xxDefault" routines so that "EXAMINE ALL"
will not reveal objects in the darkness.

=== bodyfunc.t ===

This is just where I put all the standard eat/sleep code from std.t

At the moment, it gains you nothing to use this.  However, it does provide
a repository for code which I don't want to incorporate into normal games
all that often.

=== clothing.t ===

This is another module I have swiped from the net.  It was originally
written by Jonathan D. Feinberg.

He wrote it originally.  I didn't.  He deserves the credit.  I am just a
satisfied user (who tweaked with it slightly)

Disclaimers aside, the differences I have added are...

- I have integrated it with "look.t" so that it uses cleaner methods
- Sped it up by searching specific classes (in nextobj)
- Use actor so that other actors than the player can wear clothing

Look to his original documentation for information about this.  I actually
haven't ever used it except as a test to ensure that the version dumping
information was working and the credits verb handled different authors.

=== violence.t ===

The other thing that I hated about porting Dungeon was that there were a
zillion ways of attacking someone, not the least of which was "MUNG".

This module is intended to be a vocabulary mapper.  It defines two classes
(victim and weapon) and maps as many sentence structures as possible onto a
vanilla combat method.

All sentences which seem agressive directed at a victim will be caught and
redirected to either the weapon (if one was used) or to the victim if not.

In both cases, the method called is 'attack_with'.

The default behaviour of the weapon is to pass the call on to the victim so
the logic is (roughly) as follows.

       if a weapon was specified
               if weapon has custom method
                       weapon.attack_with(attacker,victim,severe)
               else
                       victim.attack_with(attacker,weapon,severe)
       else
               victim.attack_with(attacker,nil,severe)

The severe parameter is a flag which indicates how "agressive" the command
was.  For example, "POKE BOB WITH SCREWDRIVER" is taken to be an attack but
not severe so we pass 'nil'.  "ATTACK BOB WITH SCREWDRIVER" however is
considered to be severe and we pass 'true'.

The default behaviour for the victim is to shrug off the attack with a
'I don't understand why you are doing that' message.  If real combat is to
be implemented, the attack_with method(s) should be overridden.

Cursed weapons can be implemented by overriding the weapon.attack_with
method (I had to do this for Dungeon)

=== Versions ===

This document was written when the files were at the following revision levels.

actor.t:        $Id: actor.t_v 1.2 1994/04/13 09:20:13 jeffl Exp jeffl $
askme.t:        $Id: askme.t_v 1.4 1994/05/04 07:40:53 jeffl Exp jeffl $
bodyfunc.t:     $Id: bodyfunc.t_v 1.1 1994/05/04 06:49:35 jeffl Exp jeffl $
bodypart.t:     $Id: bodypart.t_v 1.7 1994/05/01 02:11:21 jeffl Exp jeffl $
clothing.t:     $Id: clothing.t_v 1.4 1994/04/22 00:53:40 jeffl Exp jeffl $
darkness.t:     $Id: darkness.t_v 1.9 1994/05/01 02:10:29 jeffl Exp jeffl $
footnote.t:     $Id: footnote.t_v 1.6 1994/04/26 06:23:30 jeffl Exp jeffl $
heartbeat.t:    $Id: heartbeat.t_v 1.3 1994/05/09 07:35:47 jeffl Exp jeffl $
instruct.t:     $Id: instruct.t_v 1.4 1994/05/04 07:44:19 jeffl Exp jeffl $
look.t:         $Id: look.t_v 1.9 1994/05/09 04:15:24 jeffl Exp jeffl $
score.t:        $Id: score.t_v 1.6 1994/05/03 07:59:52 jeffl Exp jeffl $
sysfuncs.t:     $Id: sysfuncs.t_v 1.3 1994/05/06 09:20:30 jeffl Exp jeffl $
sysverbs.t:     $Id: sysverbs.t_v 1.3 1994/05/09 03:29:30 jeffl Exp jeffl $
timers.t:       $Id: timers.t_v 1.3 1994/05/05 06:38:15 jeffl Exp jeffl $
travel.t:       $Id: travel.t_v 1.10 1994/05/09 04:15:03 jeffl Exp jeffl $
utility.t:      $Id: utility.t_v 1.2 1994/04/22 00:53:40 jeffl Exp jeffl $
version.t:      $Id: version.t_v 1.10 1994/04/22 00:53:40 jeffl Exp jeffl $
violence.t:     $Id: violence.t_v 1.3 1994/04/22 00:53:40 jeffl Exp jeffl $
wallpaper.t:    $Id: wallpaper.t_v 1.8 1994/05/01 02:08:26 jeffl Exp jeffl $

Jeff Laing <[email protected]>
--------------------------------------------------------------------------------
'I meant,' said Ipslore bitterly, 'what is there in this world that makes living
worth while?'  Death thought about it.  CATS, he said eventually. CATS ARE NICE
       -- Sourcery (Terry Pratchett)