TCommand

The TCommand module is basically designed to extend the functionality of the CommandTopic class. It does this in a number of ways:

·By modifying CommandTopic so that it can optionally match the direct and/or indirect object of the command, as well as the action commanded.  
·By adding two new methods to CommandTopic to facilitate the handling of commands.  
·By adding the obeyCommand property to CommandTopic to indicate whether or not the NPC should obey the command.  
·By modifying ActorState.obeyCommand to work better with CommandTopic and multiple direct objects.  
·By adding a new CommandHelper convenience mix-in class, and defining TCommandTopic, DefaultTCommandTopic and AltTCommandTopic to make use of it.  
·By modifying DefaultCommandTopic to work the same way as CommandTopic  
·By adding an AltCommandTopic class  
·By adding a SuggestedCommandTopic class  

The modied CommandTopic can match one or more direct objects and/or indirect objects as well as a specific action. While the library version of CommandTopic can only match specific actions such as TakeAction or DropAction, the modified CommandTopic can additionally match one or more direct objects as well, the object or objects specified in its matchDobj property. This may be specified as either a single object to match, a list of objects to match, a class of objects to match, or a list of classes of objects to match. It should also work perfectly well as a mixed list of classes and objects. In exactly the same way the matchIObj property can be used to match the indirect object of any command issued, CommandTopic also defines some additional methods primarily for convenience of access in the topicResponse method (to avoid the need to have to override handleTopic)

The following properties and methods have been added to CommandTopic:

·handleAction(fromActor, action) - This method is called before topicResponse, and contains any handling of the action you wish. Its main purpose is to provide a hook for CommandHelper to use, but it can also be used for your own handling.  
·actionResponse(fromActor, action) - this is called after topicResponse, and is basically intended as an alternative to topicResponse when the response needs access to the action that's being commanded.  
·obeyCommand - if this is set to true, then ActorState.obeyCommand will return true to allow the target actor to obey the command just as it was given.  
·matchDobj - the direct object, class of direct object (e.g. Food, Wearable), or list of direct objects/classes that you want this CommandTopic to match. If this is left at nil it will simply be ignored.  
·matchIobj - the indirect object, class of indirect object (e.g. Container, Surface), or list of indirect objects/classes that you want this CommandTopic to match. If this is left at nil it will simply be ignored.  

The new CommandHelper mix-in class overrides handleAction and provides the following additional properties:

·cmdDobj - the current direct object of the command that the CommandTopic matched on this occasion. For example,. if matchDobj is the list [brassCoin, goldCoin, silverCoin], and matchObj (which matches the action on a CommandTopic or TCommandTopic) is TakeAction, then if the TCommandTopic is responding to "bob, take silver coin", cmdDobj will be silverCoin.  
·cmdIobj - the current indirect object, if there is one. E.g. if the CommandTopic matched the command "Bob, put the coin in the slot", this will contain the slot object.  
·cmdAction - the current action that's being command. This simply makes it available to methods like topicResponse which otherwise wouldn't have access to it.  
·cmdTopic - if the action commanded is a TopicActionBase or subclass thereof (e.g. Bob, ask Fred about boots) then this holds the topic associated with the command (in this example, the 'boots' topic).  
·cmdPhrase - this is simply cmdAction.getInfinitivePhrase, e.g. if the command was "Bob, put the red book on the shelf" it will contain something like "put the red book on the shelf." This can be useful when the CommandTopic may have matched a number of different commands and we want to construct a sentence containing the command in topicResponse, e.g. "<q>Bob, <<cmdPhrase>>, will you?</q>". Note you might sometimes want the participle phrase, which you can get, for example, with "<q>Bob, would you mind terribly <<cmdAction.getParticiplePhrase>>?</q>", which might come out as "Bob, you mind terribly putting the red book on the shelf."  
·topicCmdPhrase() - this is a method that returns the command phrase (e.g. "ask Bob about boots") associated with a command to perform a TopicAction (e.g. "fred, ask bob about boots."). It it called by cmdPhrase when necessary, and was added to circumvent a run-time error that would otherwise occur. You probably won't need to use this method - you can just use cmdPhrase.  

In addition, two properties have been added to ActorState to enable trapping of commands that normally don't make much sense when directed to an NPC, along with two methods to explain why these commands are blocked:

·autoBlockSystemCommands - if true (the default) then any attempt to direct a system command to this actor when he's in this ActorState (e.g. Bob, Restore) will automatically be blocked, and the explainBlockSystemCommand() method called to explain why.  
·autoBlockTopicCommands - if true (the default) then any attempt to ask the actor who's in this ActorState to perform a conversational command (e.g. Bob, Ask Sally about lighthouse) will automatically be blocked, and the explainBlockTopicCommand() method called to explain why.  

For your convenience, TCommandTopic is now defined simply as

class TCommandTopic : CommandHelper, CommandTopic
;

For an example of a TCommandTopic, if you wanted Bob to respond to the commands TAKE THE DIAMOND or TAKE THE GOLD COIN by obeying these (but no other) take commands, you could code a TCommandTopic thus:

+ TCommandTopic @TakeAction
   matchDobj = [diamond, goldCoin]
   topicResponse
  {
     "<q>Bob, would you <<cmdPhrase>>, please?</q> you ask.\b
      <q>Certainly,</q> he replies. ";
      nestedActorAction(getActor, Take, cmdDobj);
  }
;

Note that you cannot necessarily assume that the command will succeed, however; in the above example, for instance, you'd probably want to test that Bob wasn't already holding the object in question before displaying an interchange that implies his willingness to take it. Again, you'd want to check that the nestedActorAction had succeeded (in this case, by testing that the currentDobj had changed location as a result of it) before displaying a message that implies that it has.

You can also use TCommandTopic with a command using two objects (direct and indirect). It's then up to you whether it matches on the action only, or also on either the direct object or the indirect object or both. You may, for example, want it to match only on the direct object: if Bob is willing to put the red book in the black bag but nowhere else, you'd want to give the player an indication that Bob might be willing to put the red book somewhere, rather than a generic message suggesting he's unwilling to do anything with it at all, so you might write:

+ TCommandTopic @PutInAction
   matchDobj = redBook
   topicResponse
   {
      "<q>Bob, be a good fellow and <<actionPhrase>>, would you?</q> you ask.\b";
      if(cmdIobj == blackBag)
      {
         "<q>Sure.</q> Bob agrees readily. ";
         nestedActorAction(getActor, PutIn, cmdDobj, blackBag);
      }
      else
         "<q>I don't think I should put it there.</q> he replies dubiously. ";
   }
;

Once again, it should be emphasized that the nestedActorAction may not succeed, so you may want to provide more sophisticated handling to allow for this possibility.

Commands with Multiple Direct Objects

It is possible that a player might enter a command such as:

>bob, take the brass coin, the small magnet, the large rifle, and the damp cucumber

Potentially, this could become quite difficult to handle in a CommandTopic. If you wanted Bob to accept commands to take the coin or the rifle, but not the magnet or the cucumber, simply matching this input in a CommandTopic would become problematic; proceeding to sort out Bob's response to being told to take all four objects could become even more so. It would be much easier to have one CommandTopic to handle the combination of action and direct object that Bob is willing to act upon, and another to handle those he isn't (this could either be a simple CommandTopic with a lower matchScore to pick up all other Take commands, or a DefaultCommandTopic).

To make this situation easier to handle, therefore, the TCommand module modifies ActorState.obeyCommand so that it splits any action on multiple direct objects into a sequence of actions on single direct objects. That way, any TCommandTopic (or CommandTopic or DefaultCommandTopic) can be certain that it only has to handle one direct object at a time.

At the same time, the overridden ActorState.obeyCommand sets each direct object in turn as the current direct object of the action object it passes to the CommandTopic.

Changes to DefaultCommandTopic

TCommand modified DefaultCommandTopic by adding the same handleAction(fromActor, action), actionResponse(fromActor, action) and obeyCommand methods/properties that have been added to CommandTopic. For your convenience the module also defines:

class DefaultTCommandTopic : CommandHelper, DefaultCommandTopic
;


This makes it easier to define a DefaultCommandTopic that displays a meaningful exchange between the player character and the target actor, such as:

+ DefaultTCommandTopic
   "<q>Would you <<cmdPhrase>> please, Bob?</q> you ask.\b
    <q>Actually, no, I won't.</q> he refuses. "
;

The purpose of this is mainly to gain a more elegant transcript where a conversation is started by addressing a command to an NPC, and the greeting protocols intervene between the command typed by the player and the message displayed bu the DefaultCommandTopic. Rather than have :

>bob, follow me
"Hello Bob, nice to see you again. How are you?" you greet him.

"I'm fine. It's good to see you too." he replies warmly.

"Actually, no, I won't." he refuses.

This allows us to have a transcript that reads:

>bob, follow me
"Hello Bob, nice to see you again. How are you?" you greet him.

"I'm fine. It's good to see you too." he replies warmly.

"Would you follow me please, Bob?" you ask.

"Actually, no, I won't." he refuses.


Which is an obvious improvement.

SuggestedCommandTopic
The new SuggestedCommandTopic is a SuggestedTopic class for use with CommandTopic or TCommandTopic. The name property should be set to something suitable to follow "You could tell her to ".



Finally, AltCommandTopic is simply a version of AltTopic for use with CommandTopic. It adds the same handleAction(fromActor, action), actionResponse(fromActor, action) and obeyCommand methods/properties that have been added to CommandTopic. Predictably, there is also an AltTCommandTopic defined as:

AltTCommandTopic : CommandHelper, AltCommandTopic
;