!
! SMARTCANTGO.H
!  David Wagner
!  Version 3
!   8-Nov-1995
!  All rights given away.
!
!  Defines a routine that can be used for the cant_go property of rooms
!  to print the exits, instead of just "You can't go that way."  For
!  example, the following code
!
!      Object Crystal_Cave "Crystal Cave"
!        with s_to Narrow_Passage,
!             cant_go #r$SmartCantGo,
!
!  will produce the message "You can only go south." if the player goes
!  the wrong way.
!
!  This code can be stored in a file and included into a game with
!  'Include "smartcantgo"' sometime after the parser is included.
!
!  NOTES (far too many of them):
!
!  1. If the room is dark, it just prints "You can't go that way."
!     How could the player know where the exits are?
!
!  2. This routine ignores direction properties which point to concealed
!     doors or are strings.  Therefore this code won't work quite as
!     intended in the following room:
!
!       Object Library "Library"
!         with description "A small wood-panelled library.  An open \
!                     window to the west affords a stunning view of \
!                     the Tuscan coastline.",
!              w_to "Ouch! You discover that the ~window~ is really \
!                     in incredibly lifelike mural painted on the wall.",
!
!  3. This routine does include direction properties that are routines
!     on the assumption that the routine will return something sensible.
!     If your routine returns a concealed door, you will have to do
!     something different.
!
!  4. Due to a bug in the RunRoutines() function in version 5/12 of the
!     parser, you can't use "ChangeDefaults(cant_go,#r$SmartCantGo)" to
!     make this the default for all rooms.  Either explicitly say
!     "cant_go SmartCantGo" for every room (or make a class which does
!     this and subclass all rooms), or Replace RunRoutines() with a
!     modified version which calls indirect(obj.prop) when obj.#prop==0.
!
!  5. This routine is adequate for the rare occasions when the player
!     types the wrong direction.  One might be tempted to use this
!     routine to simplify room descriptions, as in:
!
!        Object Boring_Room "Boring Room"
!          with description
!               [; "A small room with white walls. ";
!                  SmartCantGo();
!               ];
!
!     Don't do this!  Part of the interest of a room is a good
!     description of the exits.
!
!     "To the west is a wooden door, above which is strange gothic
!     lettering."
!
!
[ SmartCantGo room i dest desttype ndir idir;
!
!  How would a player in darkness know where the exits are?
!
 if (location == thedark) "You can't go that way.";
!
!  Find what room the player is in.
!
 room = location;
 while (parent(room) ~= 0) room = parent(room);
!
!  Count the number of exits-- if a direction property is a string or
!  a concealed door, don't count it; if it is a routine, count it.
!
 objectloop (i in compass)
 {
   dest = room.(i.door_dir);
   if (dest ~= 0)
   {
     desttype = ZRegion(dest);
     if (desttype ~= 3 &&
         (desttype == 2 || dest hasnt door || dest hasnt concealed)) ndir++;
   }
 }
!
!  There might not be a (visible) exit
!
 if (ndir == 0) "There are no exits.";
 print "You can only go ";
!
!  Print the exits.  (Note that we rely on the fact that the full name of
!  the direction is stored as the second item in the list of name
!  properties for the direction objects; true for the standard directions
!  in version 5/9 of the Inform library.)
!
 objectloop (i in compass)
 {
   dest = room.(i.door_dir);
   if (dest ~= 0)
   {
     desttype = ZRegion(dest);
     if (desttype ~= 3 &&
         (desttype == 2 || dest hasnt door || dest hasnt concealed))
     {
       idir++;
       print_addr (i.&name)-->1;
       if (idir <= ndir-2) print ", ";
       if (idir == ndir-1) print " or ";
     }
   }
 }
 ".";
];