cmdhelp.t

documentation
#charset "us-ascii"


/* include the library header */
#include "advlite.h"

/*---------------------------------------------------------------------------*/
/*
 *   cmdHelp Extension
 *.  by Eric Eve
 *
 *   Experimental extension to give help to players who enter a empty command.
 */


/* Modifications to Parser for CMDHELP EXTENSION */
modify Parser
    
    /* 
     *   Overridden for CMDHELP EXTENSION. If our autoHelp property is true then
     *   respond to an empty command by displaying a brief menu of command
     *   options.
     */
    emptyCommand()
    {
        if(autoHelp)
            CmdMenu.showOptions();
        else
            inherited();
    }
    
    /* 
     *   Flag: Do we want to show a menu of command options in response to an
     *   empty command? By default we do since that's the purpose of this
     *   CMDHELP EXTENSION.
     */
    autoHelp = true    
;

/ *[CMDHELP EXTENSION] */
DefineSystemAction(CmdMenu)
    showOptions()
    {
        DMsg(cmdhelp show options,
        'What would you like to do?\b
        <<aHref('1','1')>>. Go to another location\n
        <<aHref('2','2')>>. Investigate your surroundings\n
        <<aHref('3','3')>>. Relocate something\n
        <<aHref('4','4')>>. Manipulate something\n');
        
        if(defined(Actor))
        {
            for(local a = firstObj(Actor); a != nil ; a = nextObj(a, Actor))
            {
                if(a != gPlayerChar && Q.canTalkTo(gPlayerChar, a))
                {
                    DMsg(cmdhelp talk to someone, '<<aHref('5','5')>>. 
                        Talk to someone\n');
                    break;
                }
            }
        }
        // "6. Something else\b";        
        "<.p>";
    }
    
    /* 
     *   Show a list of possible actions, where cmd_str is the name of the
     *   action and lst a list of objects on which it might be tried.
	 *	[CMDHELP EXTENSION]
     */
    showList(lst, cmd_str)
    {       
        local cmdstr;
        
        /* 
         *   Replace any commonly abbreviated commands with their common
         *   abbreviations in the command we send to the command line, so that
         *   players get used to the common abbreviations.
         */
        switch(cmd_str)
        {
        case 'examine ':
            cmdstr = 'x ';
            break;
        default:
            cmdstr = cmd_str;
            break;
        }
        
        /*  
         *   Output a hyperlinked list of commands for each object in the list,
         *   but stop after at most maxObj objects, so we don't overwhelm the
         *   player with choices.
         */
        for(local cur in lst, local i = 1; i <= maxObjs; i++)
        {
            local str = cmd_str + cur.name;
            local str1 = cmdstr + cur.name;
            "<<aHref(str1, str)>>\ \ \ ";
        }
    }
    
    /* 
     *   Carry out this action. This is the response to the player entering a
     *   number at the command prompt. 
	 *   [CMDHELP EXTENSION]
     */
    execAction(cmd)
    {
        /* Get the number the player typed .*/        
        local num = cmd.dobj.numVal;
        
        /* Note the player character's current location. */
        local loc = gPlayerChar.getOutermostRoom();
        
        /* 
         *   If the player typed a number out of range, re-display the options
         *   and end there.
         */
        if(num < 1 || num > 6)
        {
            showOptions();
            return;
        }
        
        /* Option 1: The Player wants to go to another location. */
        if(num == 1)
        {
            /* Ask the player where s/he wants to go. */
            DMsg(cmdhelp where go, 'Where would you like to go?\n
            The possible exits are: ');
            
            /* 
             *   If we have an exit lister, use it to display the list of exits.
             */
            if(gExitLister)
                gExitLister.showExits(gPlayerChar);
            /*  Otherwise create our own list of exits. */
            else
            {
                /* Set up a flag to record if we actually found any exits. */
                local dirFound = nil;
                foreach(local dir in Direction.allDirections)
                {
                    /* 
                     *   Assume an exit exists if the corresponding direction
                     *   property points to a method or an object.
                     */
                    if(loc.propType(dir.dirProp) is in (TypeCode, TypeObject))
                    {
                        "<<aHref(dir.name, dir.name)>>\ \ ";
                        dirFound = true;
                    }
                }
                /* If we didn't find any exits, say so. */
                if(dirFound == nil)
                    DMsg(cmdhelp no exit, 'None ');
            }
            "<.p>";
            
            /* 
             *   If the routeFinder is present we can also offer the player of
             *   travelling to another location via the GO TO command.
             */
            if(defined(pcRouteFinder))
            {
                /* Get a list of rooms the player knows about. */
                local rmList = Q.knownScopeList.subset({o: o.ofKind(Room)});
                
                /* Remove the player's current location from the list. */
                rmList -= loc;
                
                /* Sort the list in alphabetical order. */
                rmList = rmList.sort(SortAsc, {a, b:
                                     a.name.compareIgnoreCase(b.name) });
                
                /* 
                 *   Don't offer the option unless there are any rooms to offer.
                 */
                if(rmList.length > 0)
                {
                    /* Introduce the list. */
                    DMsg(cmdhelp go to, 'Or you could: ');
                    
                    /* 
                     *   Display a hyperlinked GO TO ROOM command for every room
                     *   in the list.
                     */
                    foreach(local rm in rmList)
                    {
                        local str = 'go to ' + rm.name;
                        "<<aHref(str, str)>>\ \ ";
                    }
                }
                
            }         
            
            /* We're done. */
            return;
            
        }
        
        /* 
         *   If we reach this point the player may want to deal with specific
         *   objects, so we need to get a list of those in scope.
         */
        local scope_lst = World.scope.toList().subset({o:
            Q.canSee(gPlayerChar, o)});
        
        /*  Remove Unthings and Rooms from the list. */
        scope_lst = scope_lst.subset({o: !o.ofKind(Unthing) 
                                     && !o.ofKind(Room) });
        
        /* Option 2: the Player wants to investigate their environment. */
        if(num == 2)
        {
            /* First offer the basic set of intransitive commands. */
            DMsg(cmdhelp investigate, 'Here are some suggestions (other
                actions may also be possible):\n');
            "<<aHref('look', 'look', 'Look around the room')>>\ \ 
            <<aHref('listen', 'listen')>>\ \
            <<aHref('smell', 'smell')>>\ \ 
            <<aHref('I', 'inventory', 'See what you\'re carrying')>>\b"; 
            
           
            /* 
             *   Get a list of things that could be examined. In the first
             *   instance, sort them alphabetically.
             */
            local exa_lst = scope_lst.sort(SortAsc, 
                                           {a, b: a.name.compareIgnoreCase(b.name)});
            
            /* 
             *   If the list of things we could examine has too many items, sort
             *   the list in the order of the turn number on which the items
             *   were last examined, so that those that were examined longest
             *   ago come to the front of the list.
             */            
            if(exa_lst.length() > maxObjs)
                exa_lst = exa_lst.sort(SortAsc,{a, b: a.turnLastExamined -
                                       b.turnLastExamined});
            
            /* Show the list of EXAMINE suggestions. */                       
            showList(exa_lst, 'examine ');
                        
            "<.p>";
            
            /* 
             *   Get a list of READ suggestions by taking the subset of examine
             *   suggestions for items that have a non-nil readDesc.
             */
            local read_lst = exa_lst.subset({o: o.propType(&readDesc) !=
                                            TypeNil });
            
            /*  Show the list of READ suggestions. */
            showList(read_lst, 'read ');
            "<.p>";
            
            /* Get a list of thing we could look inside. */
            local li_lst = exa_lst.subset(
                {o: (o.contType == In && !o.isLocked)
                || (o.remapIn != nil && !o.remapIn.isLocked)});
            
            /*  
             *   Show a list of LOOK IN suggestions. Note we don't do the same
             *   for LOOK UNDER or LOOK BEHIND since these are much rarer, and
             *   handling them would either flood the player with useless
             *   suggestions (if we took a maximalist view of what to include)
             *   or create potential spoilers (if we took a minimalist view)
             */
            showList(li_lst,'look in ');
            
            "<.p>";
            
            /* 
             *   Get a list of things we could listen to; these are objects with
             *   a non-nil listenDesc.
             */
            local listen_lst = scope_lst.subset({o: o.propType(&listenDesc) !=
                                               TypeNil});
            
            /* Display the list of LISTEN TO suggestions. */
            showList(listen_lst, 'listen to ');
            
            
            /* 
             *   Get a list of things we could smell; these are objects with a
             *   non-nil smellDesc.
             */
            local smell_lst = scope_lst.subset({o: o.propType(&smellDesc) !=
                                               TypeNil});
            
            /*  Display the list of SMELL suggestions. */
            showList(smell_lst, 'smell ');
            
            /* We're done. */
            return;
        }
        
        /* 
         *   From this point on we're suggesting commands to manipulate objects
         *   in various ways, so we'll reduce the scope list to things the
         *   player character can actually touch.
         */
        
        scope_lst = scope_lst.subset({o:  Q.canReach(gPlayerChar, o)});
        
        /* Things can be moved if they're not fixed in place. */
        local move_lst = scope_lst.subset({o: !o.isFixed });
        
        /* Option 3: The player wants to move things around. */
        if(num == 3)
        {
            /* Display an introductory message. */         
            DMsg(cmdhelp relocate, 'Here are some suggestions (there may well
                be several other possibilities):\n');
            
            /* 
             *   First deal with things the player can TAKE. We need to set
             *   gAction since verify() routines will assume it has been set
             *   correctly.
             */                 
            gAction = Take;
            
            /*   
             *   Get a list of things than can be taken. This will be the subset
             *   of potentially moveable objects that pass verifyDobjTake().
             */
            local take_lst = move_lst.subset({o: Take.verify(o,
                DirectObject).allowAction});            
            
            /*   
             *   Also exlude any objects that would fail the TAKE action at the
             *   check() stage, if the excludeCheckFailures option is set.
             */
            if(excludeCheckFailures)
                take_lst = take_lst.subset({o: passCheck(Take, o) });
            
                       
            /*  
             *   If we have too many objects, sort them in the order in which they
             *   were last moved.
             */
            if(take_lst.length > maxObjs)
                take_lst = take_lst.sort(SortAsc, {a, b: a.turnLastMoved -
                                         b.turnLastMoved});
            
            /*  Display a list of TAKE suggestions */
            showList(take_lst, 'take ');            
            
            /*  
             *   If there's more than one thing that can be taken, also offer
             *   the TAKE ALL command.
             */
            if(take_lst.length > 1)
                "<<aHref('take all', 'take all')>>";
                        
            "<.p>";
            
            /*  
             *   Now suggest things that can be DROPped. Again we must set
             *   gAction for the sake of the verify method.
             */
            gAction = Drop;
            
            /*   
             *   Get a list of moveable objects directly located in the player
             *   character.
             */
            local drop_lst = move_lst.subset({o: o.isDirectlyIn(gPlayerChar)});
            
            /*  
             *   If we have too many objects, sort them in ascending order of
             *   the turn on which they were last moved.
             */
            if(drop_lst.length > maxObjs)
                 drop_lst = drop_lst.sort(SortAsc, {a, b: a.turnLastMoved -
                                         b.turnLastMoved});
            
            /* Display a list of DROP suggestions. */
            showList(drop_lst, 'drop ');            
            
            /* 
             *   If more than one object could be dropped, offer the DROP ALL
             *   option.
             */
            if(drop_lst.length > 1)
                "<<aHref('drop all', 'drop all')>>";
            
            "<.p>";
            
            /*   
             *   Now suggest PUT IN, PUT ON, PUT UNDER, PUT BEHIND. First set
             *   the list of objects that can be put anywhere to the list of
             *   moveable objects.
             */
            local put_lst = move_lst;
                        
            /*   
             *   If there are too many objects, sort them in ascending order of
             *   the turn on which they were last moved.
             */
            if(put_lst.length > maxObjs)
                 put_lst = drop_lst.sort(SortAsc, {a, b: a.turnLastMoved -
                                         b.turnLastMoved});
            
            
            /*  
             *   Set up PUT IN suggestions. First set gAction to PutIn so that
             *   any routines we call that depend on the value of gAction will
             *   work as expected.
             */
            gAction = PutIn;
            
            /*  
             *   Get the list of items into which things can be out. This is the
             *   list of unlocked objects with a contType of In plus the list of
             *   objects with an unlocked remapIn object.
             */
            local put_in_lst = scope_lst.subset({o: (o.contType == In &&
                !o.isLocked) || (o.remapIn != nil && !o.isLocked)});
            
            /*   
             *   Sort the resulting list into ascending order of the turn on
             *   which items last had anything inserted into them.
             */
            put_in_lst = put_in_lst.sort(SortAsc, {a, b: a.turnLastMovedInto -
                                         b.turnLastMovedInto });
            
            /*   
             *   Set up a counter to keep track of how many suggestions we've
             *   made.
             */
            local i = 1;
            
        in_loop:
            /* 
             *   Go through every item in our put_lst (potential direct objects
             *   of a PUT IN COMMAND).
             */
            for(local cur in put_lst)
            {
                /* 
                 *   For each potential direct object of a PUT IN command, go
                 *   through all the potential indirect objects of a PUT IN
                 *   command.
                 */
                foreach(local dest in put_in_lst)
                {
                    /* 
                     *   If the potential direct object is neither in the
                     *   potential indirect object nor identical to the
                     *   potential direct object, and if inserting the direct
                     *   object into the indirect object would pass the
                     *   checkInsert() test, then suggest putting this direct
                     *   object into this indirect object.
                     */
                    if(!cur.isOrIsIn(dest) 
                       && (!excludeCheckFailures || checkInsert(cur, dest,
                           PutIn)))
                    {
                        /* 
                         *   Create the relevant string version of the command
                         *   and output a hyperlinked version of it.
                         */
                        local str = 'put ' + cur.name + ' in ' + dest.name;
                        "<<aHref(str, str)>>\ \ ";
                        
                        /* 
                         *   Increment our number-of-suggestions counter. If it
                         *   exceeds maxObjs, break out of both loops.
                         */
                        if(++i > maxObjs)
                            break in_loop;
                    }
                }
            }
            "<.p>";
            
            /* 
             *   Now handle the PUT ON suggestions. The logic is the same as for
             *   PUT IN.
             */
            gAction = PutOn;
            put_in_lst =  scope_lst.subset({o: o.contType == On || 
                o.remapOn != nil});
            
            put_in_lst = put_in_lst.sort(SortAsc, {a, b: a.turnLastMovedInto -
                                         b.turnLastMovedInto });
            
            
            i = i;
        on_loop:
            for(local cur in put_lst)
            {
                foreach(local dest in put_in_lst)
                {
                    if(!cur.isOrIsIn(dest) 
                       && (!excludeCheckFailures || checkInsert(cur, dest,
                           PutOn)))
                    {
                        local str = 'put ' + cur.name + ' on ' + dest.name;
                        "<<aHref(str, str)>>\ \ ";
                        
                        if(++i > maxObjs)
                            break on_loop;
                    }
                }
            }                                    
            "<.p>"; 
            
            /* 
             *   Now handle the PUT UNDER suggestions. The logic is the same as
             *   for PUT IN.
             */
            gAction = PutUnder;
            put_in_lst =  scope_lst.subset({o: o.contType.canPutUnderMe || 
                (o.remapUnder != nil && o.remapUnder.canPutUnderMe) });
            
            put_in_lst = put_in_lst.sort(SortAsc, {a, b: a.turnLastMovedInto -
                                         b.turnLastMovedInto });
            
            
            i = 1;
        under_loop:
            foreach(local cur in put_lst)
            {
                foreach(local dest in put_in_lst)
                {
                    if(!cur.isOrIsIn(dest) 
                       && (!excludeCheckFailures || checkInsert(cur, dest,
                           PutUnder)))
                    {
                        local str = 'put ' + cur.name + ' under ' + dest.name;
                        "<<aHref(str, str)>>\ \ ";
                        
                        if(++i > maxObjs)
                            break under_loop;
                    }
                }
            } 
            "<.p>";                               
            
            /* 
             *   Now handle the PUT BEHIND suggestions. The logic is the same as
             *   for PUT IN.
             */
            gAction = PutBehind;
            put_in_lst =  scope_lst.subset({o: o.contType.canPutBehindMe || 
                (o.remapBehind != nil && o.remapBehind.canPutBehindMe) });
            
            put_in_lst = put_in_lst.sort(SortAsc, {a, b: a.turnLastMovedInto -
                                         b.turnLastMovedInto });
            
            i = 1;
            
        behind_loop:
            foreach(local cur in put_lst)
            {
                foreach(local dest in put_in_lst)
                {
                    if(!cur.isOrIsIn(dest) 
                       && (!excludeCheckFailures || checkInsert(cur, dest,
                           PutBehind)))
                    {
                        local str = 'put ' + cur.name + ' behind ' + dest.name;
                        "<<aHref(str, str)>>\ \ ";
                        
                         if(++i > maxObjs)
                            break behind_loop;
                    }
                }
            } 
            "<.p>";
        }
        
        /* 
         *   OPTION 4: The player wants to manipulate objects in their
         *   surroundings, which is a catch-all term for actions not covered
         *   above.
         */
        if(num == 4)
        {
            /* Display an introductory message. */
            DMsg(cmdhelp manipulate, 'Some things you could try include (there
                may be many other possibilities):\b');
            
            /* Go through every action in out manipulationActions list */
            foreach(local act in manipulationActions)
            {               
                /* 
                 *   Set gAction to the current action, so that routines such as
                 *   verify that depend on its value will work properly.
                 */
                gAction = act;
                
                /*   Set gActor to the player character for the same reason. */
                gActor = gPlayerChar;
                
                /*   
                 *   Get the list of objects in scope that would pass the verify
                 *   stage for this action.
                 */
                local lst = scope_lst.subset({o: act.verify(o,
                    DirectObject).allowAction});
                
                /*  
                 *   If we want to exclude objects that would fail at the check
                 *   stage, reduce our list to those objects that would pass
                 *   this action at the check stage.
                 */
                if(excludeCheckFailures)
                    lst = lst.subset({o: passCheck(act, o) });
                
                /*  
                 *   Get the name of the action from the grammarTemplates
                 *   property of the current action. This will be a string in
                 *   the form 'clean (dobj)', so we want to remove '(dobj)' from
                 *   the string to just leave the command name.
                 */
                local str = act.grammarTemplates[1].findReplace('(dobj)', '');
                
                /*  Display a list of commands for this action. */
                showList(lst, str);            
            }    
            
            /* 
             *   If the gadgets module is present the player could also try
             *   pushing and pulling buttons and levers. PUSH and PULL aren't
             *   included in manipulationActions as they would result in the
             *   suggestion of too many pointless commands.
             */
            if(defined(Button))
            {
                "<.p>";
                /* Get a list of all the buttons and levers in scope. */
                local lst = scope_lst.subset({o: o.ofKind(Button) ||
                                             o.ofKind(Lever)});
                
                /* Set gAction and gActor for the PUSH action. */
                gAction = Push;
                gActor = gPlayerChar;
                
                /* 
                 *   Restrict our list to actions that would pass the verify
                 *   stage of a PUSH action.
                 */
                lst = lst.subset({o: Push.verify(o, DirectObject).allowAction});
                
                /*   Display a list of suggested actions. */
                showList(lst, 'push ');
                
                /* Get a list of levers in scope. */
                lst = scope_lst.subset({o: o.ofKind(Lever) });
                
                /* Set gAction and gActor for the PULL action. */
                gAction = Pull;
                gActor = gPlayerChar;
                
                /* 
                 *   Get a subset of levers that would pass the verify stage for
                 *   PULL.
                 */
                lst = lst.subset({o: Pull.verify(o, DirectObject).allowAction});
                
                /*  Show a list of suggested PULL commands. */
                showList(lst, 'pull ');
                
            }
            
            /* LockWith and UnlockWith actions on lockableWithKey items */
            
            /* 
             *   Get a list of objects that can be locked or unlocked with a
             *   key, remembering to include those with lockable remapIn
             *   objects.
             */
            local lockLst = scope_lst.subset({o: o.lockability == lockableWithKey
                                            || (o.remapIn &&
                                                o.remapIn.lockability ==
                                                lockableWithKey)});
            
            /* Go through every object in our list. */
            foreach(local lock in lockLst)
            {
                /* 
                 *   Get a list of keys that might lock/unlock the current
                 *   object. These will be Keys in scope for which the current
                 *   object appears in the plausibleLockList.
                 */
                local key_lst = scope_lst.subset(
                    {o: o.ofKind(Key) &&
                    o.plausibleLockList.indexOf(lock) });
                
                /*  
                 *   Set the description of the suggested action to 'unlock' or
                 *   'lock' depending on whether the current object is locked or
                 *   unlocked.
                 */
                local actstr = lock.isLocked ? 'unlock ' : 'lock ';
                
                /* Go through every possibly usable key we found */
                foreach(local key in key_lst)
                {
                    /* 
                     *   Suggest locking or unlocking the current object with
                     *   that key.
                     */
                    local str = actstr + lock.name + ' with ' + key.name;
                    "<<aHref(str, str)>>\ \ ";
                }
                    
            }
            
            
        }
        
        /* OPTION 5: The player wants to talk with an NPC. */
        if(num == 5)
        {
            /* Set up a list of available actors. */
            local actor_lst = [];
            
            /* 
             *   We can only populate the list if the actor.t module is present.
             */
            if(defined(Actor))
            {
                /* 
                 *   Get a list of all the actors in scope who aren't the player
                 *   character.
                 */
                actor_lst = scope_lst.subset({o: o.ofKind(Actor) && o !=
                                             gPlayerChar});
            }
            
            /* If we didn't find any, say so. */
            if(actor_lst.length == 0)                  
                DMsg(cmdhelp no one to talk to, 'Sorry, but there\'s no one here 
                    to talk to right now.\b');
            /* 
             *   Otherwise, if we only found one and the player character is
             *   already talking to him or her, suggest the use of the TOPICS
             *   command.
             */
            else if(actor_lst.length == 1 && actor_lst[1] ==
                    gPlayerChar.currentInterlocutor)
                "<<aHref('topics', 'topics')>> ";
            /*  Otherwise display a list of actors to talk to. */
            else    
                showList(actor_lst, 'talk to ');
            
        }
        
        /* At the moment OPTION 6 isn't included in the suggestions menu */
        if(num == 6)
        {
            "Some other actions you could try include:\b
            <<aHref('JUMP', 'JUMP')>>\ \ <<aHref('THINK', 'THINK')>>
            \ \ <<aHref('WAIT', 'WAIT')>>, <<aHref('YELL', 'YELL')>>
            \ \ <<aHref('SLEEP', 'SLEEP')>>\b";
        }
        
        gAction = self;
    }
    
   
    
    
    /* 
     *   A list of the actions we'll potentially suggest for option 4,
     *   "Manipulate thing". Note that these must all be TActions.
     */
    manipulationActions = [Open, Close, Lock, Unlock, Break, Cut,
        SwitchOn, SwitchOff, Burn, Wear, Doff, Climb, ClimbUp, ClimbDown,
        Board, Enter, GetOff, GetOutOf, Light, Extinguish, Eat, Drink,
        Clean, Dig, Attach, Detach, Fasten, Unfasten, Unplug, JumpOff,
        JumpOver, Pour, Screw, Unscrew, GoThrough] 
 
    /* 
     *   We in any case rule out combinations of actions and objects that would
     *   fail at the verify stage; flag - should we also rule out combinations
     *   that fail at the check stage? By default we do.
     */
    excludeCheckFailures = true
    
    /*  Determine whether obj would pass the check stage of the act action. */
    passCheck(act, obj)
    {
        /* Set obj to the current direct object of act/ */
        act.curDobj = obj;
        
        /* See if running the check routine would output any text. */
        local str = gOutStream.captureOutput(
            {: act.check(obj, act.checkDobjProp)});
        
        /* 
         *   If any text would have been output, we failed the check stage;
         *   otherwise we passed.
         */
        return  str == '';
    }
    
    
    /* 
     *   Check whether obj can be inserted in cont with the action act (which
     *   will be one of PutIn, PutOn, PutUnder or PutBehind). 
     */
    checkInsert(obj, cont, act)
    {
        /* If the container has a remapIn object, use that instead */
        if(cont.remapIn != nil)
            cont = cont.remapIn;
         
        /* Set gAction to the appropriate action */
        gAction = act;
        gDobj = obj;
        
        /* 
         *   Get the property for running the check() method on the indirect
         *   object of prop,
         */
        local prop = act.checkIobjProp;
        
        /*   Capture the output from running this method. */
        local str = gOutStream.captureOutput( {: cont.(prop) });
        
        /* 
         *   If there was any output, we failed the check stage; otherwise we
         *   passed.
         */
        return str == '';
    }
    
    /* 
     *   The maximum number of objects in a list before we try to reduce that
     *   list.
     */
    maxObjs = 10   
;


/* [CMDHELP EXTENSION] */
VerbRule(CmdMenu)
    numericDobj
    : VerbProduction
    action = CmdMenu
    
    isActive = Parser.autoHelp
;
    

/* Modifications to Thing for the CMDHELP EXTENSION */
modify Thing
    turnLastMoved = 0
    turnLastMovedInto = 0
    
    /* 
     *   Modified for CMDHELP EXTENSION. Note the last turns on which this
     *   object was moved and on which something was moved into this object.
     */
    actionMoveInto(dest)
    {
        inherited(dest);
        turnLastMoved = gTurns;
        dest.turnLastMovedInto = gTurns;
        if(dest.ofKind(SubComponent) && dest.lexicalParent)
            dest.lexicalParent.turnLastMovedInto = gTurns;
    
    }
    
    turnLastExamined = 0
    
    /* 
     *   Modified for CMDHELP EXTENSION. Note the last turn on which this
     *   object was examined.
     */
    dobjFor(Examine)
    {
        action()
        {
            inherited();
            turnLastExamined = gTurns;
        }
    }
;

/* Modify suggestedTopicLister to hyperlink suggestions for the CMDHELP EXTENSION */
modify suggestedTopicLister
    
    /* 
     *   Turn on the topic suggestion hyperlinking if the Parser autoHelp is
     *   enabled.
     */
    hyperlinkSuggestions = Parser.autoHelp    
;
Adv3Lite Library Reference Manual
Generated on 01/03/2024 from adv3Lite version 1.6.2