!--------------------------------------------------------------------------
! Followable objects: how to allow the player to type "follow thief" when
! the thief has left the room.
!
! The "follow" verb needs a different scope definition.  You can try to
! follow anything that's ordinarily in scope, or any object that's
! followable and whose just_visited value equals your location.
!
! The routine MoveNPC(object,destination,direction) is used to maintain the
! just_visited and follow_direction properties.  When you try to follow
! something, the action <Go f> is generated, where f is the
! follow_direction property of the object.
!
! Finally, we need to cancel the just_visited property whenever the player
! moves from one location to another (I rule that you can only follow
! things that you saw leave, and only if neither you nor they has done any
! movement since).  The entry point NewRoom() is just right for this.
!
! Gareth Rees, 29/11/94
!--------------------------------------------------------------------------

Constant Story "FOLLOW MY LEADER";
Constant Headline "^An Interactive Skeleton^by Gareth Rees^";

Include "parser";
Include "verblib";

! If you're running out of properties you can probably alias just_visited
! and follow_direction as all the code checks that followable is set before
! querying or changing them.

Property just_visited;
Property follow_direction;
Attribute followable;

[ Initialise;
   location = RoomNW;
   StartDaemon(Roadrunner);
   print "^^^^^Now you see it, now you don't...^^";
];

[ NewRoom i;
   for (i = selfobj + 1: i <= top_object: i++) {
       if (i has followable)
           i.just_visited = 0;
   }
];

[ FollowScope i;
   if (scope_stage == 1) rfalse;
   if (scope_stage == 2) {
       for (i = selfobj + 1: i <= top_object: i++) {
           if (i has followable && i.just_visited == location)
               PlaceInScope(i);
       }
       rfalse;
   }
   "You've no idea where that is.";
];

[ FollowSub d;
   if (noun in location || noun hasnt followable) "No need!";
   if (noun.follow_direction == 0) {
       print "You start after ", (the) noun, " but as far as you're \
           concerned, ";
       if (noun hasnt animate) print "it";
       else { if (noun has female) print "she"; else print "he"; }
       " has vanished into thin air.";
   }
   d = noun.follow_direction;
   <Go d>;
];

[ NoFollowSub;
   if (noun == player) "You can't follow yourself.";
   print_ret (The) noun, " is right here.";
];

Include "grammar";

Verb "follow" "chase" "pursue" "trail"
   * scope=FollowScope          -> Follow
   * "after" scope=FollowScope  -> Follow
   * noun                       -> NoFollow
   * "after" noun               -> NoFollow;

[ MoveNPC n dest dir i;
   if (n has followable) {
       for (i = n: parent(i) ~= 0: i = parent(i)) {}
       n.just_visited = i;
   }
   n.follow_direction = dir;
   if (dest == 0) remove n;
   else move n to dest;
];

Class   FollowClass
has    followable,
with   just_visited 0,
       follow_direction 0;

Object  RoomNW "NW Room"
has    light
with   description "You can go east or south.",
       e_to RoomNE,
       s_to RoomSW;

Object  RoomNE "NE Room"
has    light
with   description "You can go west or south.",
       w_to RoomNW,
       s_to RoomSE;

Object  RoomSE "SE Room"
has    light
with   description "You can go west or north.",
       n_to RoomNE,
       w_to RoomSW;

Object  RoomSW "SW Room"
has    light
with   description "You can go east or north.",
       n_to RoomNW,
       e_to RoomSE;

Object  Roadrunner "roadrunner" RoomNW
class  FollowClass
has    animate
with   name "road" "runner" "roadrunner" "bird",
       description "A small bird of the species G. californiensis.",
       life [;
           Ask, Answer, Order: "~Meep! Meep!~";
       ],
       daemon [ d;
           if (self in RoomNW) d = e_obj;
           if (self in RoomNE) d = s_obj;
           if (self in RoomSE) d = w_obj;
           if (self in RoomSW) d = n_obj;
           if (self in location)
               print "^The roadrunner sprints away to the ",
                   (address) (d.&name)-->1, ".^";
           MoveNPC(self, (parent(self)).(d.door_dir), d);
           if (self in location)
               print "^A roadrunner comes sprinting up to you.^";
       ];

End;