COMMANDS documentation
======================

BabbleMUD server.

Author:  Nick Gammon 
          http://www.gammon.com.au/ 

Written: 13th August 2004.

(C) Copyright Nick Gammon 2004. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears
in all copies. 


Introduction
------------

Command processing is a fundamental part of processing player input. Once the initial phase (identifying an existing player, or creating a new player) has been done, everything the player types will be sent to the function ProcessCommand. Also, some commands may be internally initiated (eg. "look" when you enter a new room), or a command may be forced on another character by the use of the "force" command. Mobs may also automatically generate commands as part of mob processing.

A lot of the preliminary work is processed by the command handler, to simplify writing individual commands. Indeed, some simple commands (like "say") may not need a hard-coded command handler at all.

Command files
-------------

You can supply any number of command files, which are files ending in ".xml" in the commands folder. These are processed in alphabetic order (by file name), so that you can control the order in which they are processed. 

For speed of evaluation, frequently-used commands should be placed in a file with a low collating sequence name (eg. "aaaCommon.xml"), and infrequent commands should be placed in a file with a high collating sequence name (eg. "zzzBuildling.xml").

Within a particular file, each command is processed in the sequence in which it appears. 

Command handlers
----------------

Some commands may required hard-coded (ie. C++) instructions, in which case you can place them into the server codebase. Command handlers are written in a standard way, as they must be built into a "map" of command handlers. Their prototype is:

    void DoLook (CommandInfo & info)
    {
    
    // do processing here
    
    } // end of DoLook

Each command handler is passed down a CommandInfo structure, which identifies various things discovered by the command processor during initial parsing of the command. Such things are:

* what they actually typed
* the current player (the person who typed the command)
* the target of command - if any - (eg. for "poke Nick", then "Nick" would be the target)
* the player's current room 
* the spell used, if a spell was present
* wildcards discovered during command parsing (see below)
* message substitutions (see below)


Command file format
-------------------

Each command file should start with a 3-line prologue, as below, then one or more command (between <command> and </command>, finally ending with the </commands> line. A simple example follows ...

  <?xml version="1.0" encoding="iso-8859-1"?>
  <!DOCTYPE commands>
  <commands>
  
  <command>
    <string 
      match="^say (?P<what>.+)$"
      success_room="%<player> says, '%<what>'."
      success_self="You say, '%<what>'."
      handler="DoSay"
    />
  </command>
  
  </commands>

Each command can have four types of data:

* string: any alphanumeric data, including newlines. 
    These can be things like the match text, the name of the command handler, help text, and so on.

* number: any integral number (eg. -30, +45678). 
    Their range is presently 2,147,483,648 to +2,147,483,647.

* float:  any floating-point number (eg. -0.04, +56.456). 
    Their range is presently 2.2250738585072014e-308 to 1.7976931348623158e+308.

* flag:   any "true or false" field. 
    You would normally write true as "1" and false as "0".

Every field must be given as a field name, followed by the "=" sign, followed by its value, in quotes.

eg.

  <string  name="Nick Gammon" />
  <number  hit_points="456" />
  <float   percentage="0.455" />
  <flag    can_fight="1" />
  
Multiple entries in a group should be all in the same group, eg.

  <number 
    str="10"
    dex="42"
    wis="88"
  />
  
The only character which cannot appear as itself in a field value is the quote symbol ("), because that is used to end a value. If you need to use it, use the HTML equivalent: &quot;

eg.  <string  description="A sword named &quot;George&quot; "  />


Regular Expressions and wildcards
---------------------------------

The command parser relies heavily on regular expressions, in particular the PCRE (Perl Compatible Regular Expression) syntax. You should consult its documentation for more details, a copy is available at:

  http://mushclient.com/pcre/pcrepattern.html

An important feature used in the command parser is the concept of "named wildcards". These are used to identify things like the target of an action, name of a spell, and so on. These are much more convenient than positional wildcards (like wildcard 5) because, for one thing it is tedious to work out which wildcard is number 5, and for another when commands are translated into different languages the wildcard positions may change.

To illustrate named wildcards, consider this match text:

      match="^say (?P<what>.+)$"

There is a single wildcard there, and it is named "what". The syntax "(?P<name> blah blah)" is used in PCRE to name the sequence of characters inside the brackets.

All of the named wildcards found by the command parser are placed in the "wildcards_" field of the info structure, so you could conceivably write a command handler like this:

   void DoSay (CommandInfo & info)
    {
    
    if (info.wildcards_ ["what"] == "fish")
       info.player () << "Don't mention fish to me!\n";
       
    } // end of DoSay


Other features of regular expressions
-------------------------------------

Use your regular expressions to do:

* alternatives, eg.  "(say|speak)"
   - would let you use either "say" or "speak" as the command

* optional words, eg. "give (?P<thing>.+) (to )?(%<target>\w+)
   - makes the word "to" optional
   
* validation, eg. "give (?P<coins>\d+) coins to (%<target>\w+)
   - this ensures that the number of coins is a decimal number
   
* enforce size limits, eg. "create spell (?P<spell>\w{4,20})
   - enforces that the spell name consists of "word" characters,
   - enforces that the spell name is between 4 and 20 characters long
  

Throwing exceptions
-------------------

If something "goes wrong" when processing a command, simply throw a runtime_error exception. This will be caught by the server and sent to the player. Also, wildcard substitution will take place automatically for you on exceptions. For example:

   void DoSay (CommandInfo & info)
    {
    
    if (info.wildcards_ ["what"].find ('x') != string::npos)
       throw runtime_error ("You cannot use the word %<what> as it has an 'x' in it");
       
    } // end of DoSay

Any text in the error message in the form %<word> will have "%<word>" replaced by the equivalent text from what the player typed, thus letting you write general error messages.

If you throw an exception then the "success" messages, decribed below, will not be shown.


Outputting to the player
------------------------

The info structure contains a function player (), which returns a reference to the current player. By using the << operator you can send text to him or her.

  void DoSomething (CommandInfo & info)
    {
    Character & p (info.player ());
    
    p << "Hi there!\n";
    p << "Have fun today.\n";
     
    } // end of DoSomething


Outputting to the target
------------------------

The info structure contains a function target (), which returns a reference to the target of the current action (if any). By using the << operator you can send text to him or her. If no target exists an exception will be thrown.

  void DoSomething (CommandInfo & info)
    {
    Character & t (info.target ());
    
    t << "Look out!\n";
     
    } // end of DoSomething


Automatic target processing
---------------------------

If your command "match" regular expression contains a named wildcard "target" then the server will automatically attempt to locate the command target for you. If the flag "target_in_room" is true, then that target must be in the room with the player. eg.

  <command>
    <string 
      match="^tell (?P<target>\w+?) (?P<what>.+)$"
      success_self="You tell %<target>, '%<what>'."
      success_target="%<player> tells you, '%<what>'."
    />
    <flag
      target_not_self="1"
      target_in_room="1"
    />
  </command>
      
In the example above, the target must be in the same room, and cannot be yourself (that, is you cannot "tell self hi"). You can see that this particular command does not even need a command handler, as it cannot fail, and thus the "success" messages suffice to carry out the command's action.

The target can be specified as "me" or "self", in which case the target is the enactor of the command. The check for "target_not_self" is correctly applied regardless of which form you use. Thus, if Nick types a command, which is "target_not_self", then he will be shown an error regardless of whether the target is given as "me", "self" or "Nick".

You can specify a field "no_target_message" which will be the message to be shwon if there is no target, eg.

  no_target_message="Tell that to who?"


Message substitution
--------------------

The success messages, and exceptions thrown, automatically have message substitution carried out on them (eg. replacing %<player> with the player name, %<target> with the target name, and indeed any wildcard in the command match text is available in the substitution text). If you wish to output to the player directly then you can use FixMessage to do the substitution.

eg.

  void DoSomething (CommandInfo & info)
    {
    info.player ()<< FixMessage ("Have fun today %<player>.\n, info)";
    } // end of DoSomething

You need to pass the info structure to FixMessage so it can look up the wildcards (such as the player name).


Defining your own substitutions
-------------------------------

You can add your own substitutions to the info structure, so they can be used in error messages, success messages or other messages. Here is an example:

  void DoSomething (CommandInfo & info)
    {
    info.sub_ ["foo"] = "bar";
    info.player () << FixMessage ("Have fun using %<foo> today, %<player>.\n, info)";
    } // end of DoSomething

In this example %<foo> will be replaced by "bar" as that has been defined in the command handler as the substitution text.


Pronoun substitutions
---------------------

Also automatically available, based on the gender of the player and the target, if any, are the following words:

Player:

  %<he>:   Subjective pronoun          - he/she/it/they 
  %<his>:  Possessive pronoun          - his/her/its/their 
  %<him>:  Objective pronoun           - him/her/it/them 
  %<hims>: Absolute possessive pronoun - his/hers/its/theirs 

Target:

  %<t_he>:   Subjective pronoun          - he/she/it/they 
  %<t_his>:  Possessive pronoun          - his/her/its/their 
  %<t_him>:  Objective pronoun           - him/her/it/them 
  %<t_hims>: Absolute possessive pronoun - his/hers/its/theirs 

Thus you might say:

  SendToAll (FixMessage ("%<player> takes %<his> sword.\n", info));

This would send "Nick takes his sword", "Margaret takes her sword" and so on, depending on the name and gender of the player.


Permission flags
----------------

You can control commands so that a player *must have* a flag set (on the player), or *must not have* a flag. The "must have" flag would be for unusual cases (eg. you cannot build without the "builder" flag). The "must not have" flag is for cases where you want to suppress commands in certain cases, eg. nuisance players.

Example of flag to be set:

  <command>
    <string 
      match="^create spell (?P<spell>.+?)$"
      handler="DoCreateSpell"
      needflag="can_create_spell"
      needflag_failure="Nice attempt."
    />
  </command>
  
In this case you cannot use the "create spell" command unless the can_create_spell flag is set on the enacting player. You can supply an optional "needflag_failure" text, otherwise the default "not permitted" text will be shown. 

Example of flag not to be set:
  
  <command>
    <string 
      match="^say (?P<what>.+)$"
      neednoflag="gagged"
      neednoflag_failure="You cannot speak."
      success_room="%<player> says, '%<what>'."
      success_self="You say, '%<what>'."
    />
  </command>

In this case you must *not* have the gagged flag set, or you cannot use the command. You can supply an optional "neednoflag_failure" text, otherwise the default "not permitted" text will be shown.


Handling partly-typed commands
------------------------------

To match on incomplete commands (eg. "say" without anything to be said) you simply define a second command *after* the one which matches the one with the correct syntax. Since the correct syntax hasn't been supplied, it will not match, and will "fall through" to match on the partial version. For example, for a "say" command:

  <command>
    <string 
      match="^say$"
      usage="Say what?"
    />
  </command>
  
In this case the "say" regular expression would match on simple "say" and the "usage" text will be sent to the player. You could also have used:

  success_self="Say what?"
  
However, there are subtle differences between the two when you start using command aliases, described below.


Command aliases
---------------

Aliased commands are designed for situations where you have two very similar commands, so that by using the "alias" mechanism you don't have to repeat the relevant details (permissions, success message etc.) for both versions.

For example, you might want to have two commands that do the same thing:

  give sword to John
  To John give sword

Now a single regular expression can't match that, because of the different word order, and you can only have a named wildcard (eg. "target") once in a regular expression. Here is how you might do it:

   <command>
    <string 
      match="^give (?P<what>.+) to (?<target>\w+)$"
      handler="DoGive"
      name="give"
      summary="Give something to somebody"
      needflag="can_give"
    />
   </command>

   <command>
    <string 
      match="^To (?<target>\w+) give (?P<what>.+)$"
      alias="give"
    />
   </command>

The second version simply aliases to the command named "give". The checks for the flags, command handler, summary etc. are all done on the first version.

Using a similar idea, we can do "usage" commands like this:

   <command>
    <string 
      match="^give"
      alias="give"
      usage="Give (thing) to (somebody)"
    />
   </command>

The alias here defers the checking of the command flags (ie. the "can_give" flag) to the main command, however it has the "usage" text to be echoed to the player. This is so that the command syntax is not echoed to a player who is not allowed to use it in the first place.


Command help
------------

Commands should be self-documenting. By placing a "name" and "summary" field into a command, it will automatically appear when the player types "help", thus they can see what commands are available. The help list is restricted to commands they can actually use, so in the example below it would not be shown to gagged players.

Below is the current version of the "say" command, in full. It matches on "say" or the double-quote symbol, requires the player to be not gagged, has a name and summary, and shows to the player, and others in the same room, what is said ...

  <command>
    <string 
    match="^(say |&quot;)(?P<what>.+)$"
    neednoflag="gagged"
    name="say"
    summary="Say something to people in the room"
    neednoflag_failure="You cannot speak."
    success_room="%<player> says, '%<what>'."
    success_self="You say, '%<what>'."
    />
  </command>
  
In this case, no hard-coded command handler was required, as everthing is done by default command processing.


Exact sequence for command processing
-------------------------------------

Having explained the various fields, here is what happens when you type a command:

* Leading and trailing spaces are discarded

* Empty commands are discarded

* Multiple spaces between words are discarded (thus "drop...book" and "drop.book" are considered the same, assuming that the period represents a space).

* The "colour escape" character (`) is doubled up, so that attempts to do colour says, tells etc. will not succeed.

* A check is made to see if the same command has been repeated more than "command_count_maximum" times (which is in the control file). This is currently 20. Thus, players who try to "spam" by using their client to do something many times will be disconnected.

* The current room is located in the rooms map (this will cause an exception if there is no current room).

* The current player's name (the command enactor) is placed into the info.sub_ field as "player".

* The gender of the player is established by consulting the attribute "sex" for the player. If it starts with "m" they are considered male, "f" or "w" are female, "p" is plural, "n" or anything else is neutral. No entry at all is considered to be male. This is used to set up the substitution fields "he", "his", "him" and "hims".

* All room exits are now scanned to see if the command matches the "match" text for the exit. This allows room-based local commands (an obvious example being a room exit). However other examples would be things that only work in a particular room (eg. "touch stone", "enter cave" and so on).

* If no matching room exit is found, then all commands in the command table are scanned in sequence for a match on the "match" text.

* If no match is found (neither exit nor command) then the default "huh?" text is displayed and processing terminates.

* The command "usage" field is saved in case they have entered a partial command.

* If the command has an "alias" field, then the alias is looked up, and substituted for the looked-up command.

* If the command has a named wildcard "target" then the MUD (or room) is scanned for a matching target. If not found, an error message is shown to the player.

* The gender of the target (if any) is established using similar rules to that for the player.

* If the command has a named wildcard "spell" then the spell list is scanned for a matching target. If not found, an error message is shown to the player.

* If the command has a non-empty "needflag" field then the player is checked to see if that flag is set. If not, either the "needflag_failure" message, or the default "permission denied" message is shown.

* If the command has a non-empty "neednoflag" field then the player is checked to see if that flag is *not* set. If set, either the "neednoflag_failure" message, or the default "permission denied" message is shown.

* If there was a non-empty "usage" field this is shown to the player as an error. The difference between an error and a "success" affects the way that commands are logged, and also in the case of who sees the message when you force one player to do a command.

* If the command has a handler in the "handler" field (that is, the name of a C++ routine in the server source) then that is called. This may throw an exception in case of an error.

* Exceptions are caught and passed through the FixMessage function to have argument substitution done on them, and re-thrown. If the "log_failures" flag is set on the control file then this command is logged to the "failures" log file. This is intended for debugging the MUD in the early phases, to see which commands are frequently mis-used.

<----- At this point, the command is considered to be a "success" ----->

* If the "notify_admin" flag is set on the command, any connected player with the "notify_admin" flag set is notified that the command was entered. This might be used for major commands (like kicking off players, adding spells etc.).

* If the "log" flag is set on the command, the command is logged to the game log file.

* If the target of the command is the enactor then the "target" name is changed to "yourself". Thus, something like "bop me" would be echoed to you as "You bop yourself".

* If the command has a "success_self" message, it is shown to the command enactor.

* If the command has a "success_target" message, and there was a command target, and the target was not yourself, then the target is shown that message.

* If the target of the command is the enactor then the "target" name is changed to "himself". Thus, something like "bop me" would be echoed to others as "Nick bops himself" (rather than "Nick bops Nick"). The word "himself" is itself changed to reflect the gender of the command enactor (eg. it might be "herself").

* If the command has a "success_all" message, it is shown to all players.

* If the command has a "success_room" message, it is shown to all players in the room with the enactor.

* The "success_target", "success_all", and "success_room" are partially suppressed depending on whether there was also a "success_self" or "success_target" message. Or, for room movement, a "depart_self" or "depart_target" message. This is so that you generally will only see a single "success" message.

  Example: You have a "shutdown" command. It sends:
      
      success_all="%<player> shuts down the MUD"
    
  This would be sent to every player, including the enactor.
  
  However if you had:
  
      success_self="You shut down the MUD"
      success_all="%<player> shuts down the MUD"
  
  Then, the message "%<player> shuts down the MUD" is sent to everyone *except* you, as you have already received your personalised message.

* If the command has the "do_look" flag set, the enactor then does a "look" command. This is intended for moving from room to room, where you want to see the success message first, then finally look around the new room.


Writing new command handlers
----------------------------

The small code segment below illustrates all that is needed to start writing your own command handlers. The single include below should include most of the needed files, and the three prototype command handlers show the general required syntax. The function LoadCommandsMap will be called at server initialisation (by the final line in the file), which will insert the commands into the global command handler map.

Then, all that is needed is to add appropriate commands into the commands ".xml" file which will be placed into the commands directory.


---------------------------------------------------------

#include "commands.h"

  void DoDodge (CommandInfo & info)
    {
    // dodge things
    
    throw runtime_error ("not implemented yet");
    } // end of DoDodge

 void DoBurn (CommandInfo & info)
    {
    // burn things
    throw runtime_error ("not implemented yet");
    } // end of DoBurn

 void DoFly (CommandInfo & info)
    // fly
    throw runtime_error ("not implemented yet");
    } // end of DoFly

static int LoadCommandsMap ()
  {
static CommandHandlerMap & commandmap = getCommandHandlerMap ();

  cout << "Loading command handlers in " __FILE__ << endl;
    
  COMMAND (DoDodge);
  COMMAND (DoBurn); 
  COMMAND (DoFly); 

  return 0;
  } // end of LoadCommands

static int loadThemUp = LoadCommandsMap ();

---------------------------------------------------------


Summary of recognised command fields
------------------------------------

(Strings)

match             - regular expression to match command (must be present)
usage             - summary of command usage (for incompletely entered commands)
alias             - which (name of) command to be used as an alias for this one
name              - the name of this command (should be unique) - shown in help
no_target_message - message to be shown if there is no target
needflag          - name of flag that enactor needs set to do this command
needflag_failure  - message to be shown if they dont have that flag
neednoflag        - name of flag that enactor needs to be clear to do this command
neednoflag_failure- message to be shown if they have that flag
handler           - name of command handler (C++ routine)
depart_self       - message to be shown to enactor on leaving a room
success_self      - message to be shown to enactor on success
depart_target     - message to be shown to target on leaving a room
success_target    - message to be shown to target on success
success_all       - message to be shown to all connected players on success
success_room      - message to be shown to all players in the current room on success
summary           - summary of command purpose (for help listing)

(Flags)

target_not_self   - target cannot be the enactor
target_in_room    - target must be in the same room as the enactor
no_force          - this command cannot be forced
notify_admin      - notify any person connected with "notify_admin" flag set when completed
log               - log this command to log file when completed
do_look           - force enactor to do a "look" on command completion


Note - the various message texts can have imbedded colour codes, see colours.txt for more details.
