    The Verb

    Note: This page is for advanced coders who need to
    create new verbs, or modify existing ones. Newbie
    coders should not assume they need to know anything
    here.

    	The verb is like anything else. Exactly as
    good as you make it, no more and no less. Deconstructing
    a new verb for the first time can be confusing, but
    in doing so you will gain a better understanding of
    the parsing system Dead Souls uses.

    	Please note, if there's anything here hard to
    follow or understand, you need to review the Creator's
    Manual for key LPC concepts.

    The verb itself

    Rules and tokens

    can's and do's

    The object: direct_ and indirect_

    References

    The verb itself

    Let's take a look at the code for a verb, and dissect
    it for meaning.

    #include <lib.h>

    inherit LIB_VERB;

    static void create() {
        verb::create();
        SetVerb("buy");
        SetSynonyms("purchase");
        SetRules("STR from LIV");
        SetErrorMessage("Buy what from whom?");
        SetHelp("Syntax: <buy ITEM from VENDOR>\n\n"
          "Blah blah this is the help message.");
    }

    mixed can_buy_str_from_liv(string str) {
        if( this_player()->GetParalyzed() ) {
            return "You cannot do anything.";
        }
        return this_player()->CanManipulate();
    }

    mixed do_buy_str_from_liv(string str, object vendor) {
        return vendor->eventSell(this_player(), remove_article(lower_case(str)));
    }

    	If you never looked at a verb before, it can
    look rather alien and disgusting, like a dead facehugger.
    But like the facehugger, it's actually quite beautiful
    in its own way.
    	Let's dissect and comment it now:

    #include <lib.h>
    // This include statement allows us to use macros, or nicknames,
    // for certain things. Specifically, the lib include gives us
    // knowledge of what we mean by LIB_VERB.

    inherit LIB_VERB;
    // This line tells us that we will be inheriting all the
    // functions and variables defined in /lib/verb.c .

    static void create() {
    // The create function is like main() in C/C++. A function that
    // is *always* called when an object is loaded. Therefore,
    // anything important goes inside here.

        verb::create();
    // The :: operator is called the "scope resolution operator".
    // That's a fancy way of saying that we are trying to use
    // a function that exists somewhere in the inheritance tree, and
    // not in this individual file. The verb::create() line above
    // is saying "At this point, execute any directives in the
    // create() function of LIB_VERB". This is necessary because
    // the create() function we define here will override the create()
    // function we inherit, and that overridden function might have
    // had important stuff in it we need to have happen.
    //    If you didn't understand any of that, you should probably
    // stop reading this tutorial and get started on reading
    // the Creator's manual.

        SetVerb("buy");
    // This identifies what word the parser should associate
    // with this verb.

        SetSynonyms("purchase");
    // Self explanatory. This is where you specify words with a
    // similar meaning that should also be associated with this verb.

        SetRules("STR from LIV");
    // Here's one of the new and exotic features of verbs. Rules and tokens.
    // When the parser catches the "buy" word from the user's input,
    // it will check to see if the rest of the words in the
    // command line conform the the known set of rules for the verb.
    // if they don't, the parser will error. We'll go over the rules
    // a bit further on.

        SetErrorMessage("Buy what from whom?");
    // By default, the parser's error messages aren't terribly
    // descriptive or helpful...usually it's along the lines
    // of "You can't X the Y". The line above lets you provide the
    // user a clue as to how to better avail themselves of the
    // verb's functionality.

        SetHelp("Blah blah this is the help message.");
    // When the user types "help buy", this is what they get.

    // The create function ends here, with the close brace
    // below this line.
    }

    mixed can_buy_str_from_liv(string str) {
    // This function does some very rudimentary checks of
    // whether the user can use the verb. The can_* type
    // functions will be discussed in more detail a bit
    // further on.

        if( this_player()->GetParalyzed() ) {
            return "You cannot do anything.";
        }
    // Pretty self-explanatory. An obvious check.

        return this_player()->CanManipulate();
    // The player object has a CanManipulate() function. If
    // the player has no prehensile limbs (i.e. "wielding limbs",
    // like hands) then the  CanManipulate() function in their
    // object returns 0. Since the line above returns whatever
    // CanManipulate() returns, that means that if the player
    // is missing both hands, he can't sell anything. The verb
    // will fail.

    mixed do_buy_str_from_liv(string str, object vendor) {
    // Like the can_* functions, do_ functions will get more
    // treatment further on. This is generally where the actual
    // "doing" of the verb gets fired off, if appropriate.

        return vendor->eventSell(this_player(), remove_article(lower_case(str)));
    // Did you notice that this function is declared as type "mixed"?
    // This allows us to return weird stuff, like in this case where
    // we're returning the result of a function call. We're not
    // 100% sure what data type eventSell() in the vendor returns,
    // so mixed covers all the bases. Whatever eventSell() returns,
    // that's what gets returned here. If the parser got this far,
    // then the verb's execution was successful.
    //	That doesn't necessarily mean that the player successfully
    // sold anything. It may be he lacks enough quatloos for the
    // shizbat. But that is no concern of the verb. That is the
    // business of the eventSell() function it called on the vendor.
    }

    Rules and tokens

    	By a magic I do not fully understand myself, the
    parser (which lives in the compiled driver binary, meaning
    it was written in C and therefore inscrutable to me) can
    actually work out from your command line what object you meant
    to do what to with what.

    	For example, if you are in a room full of orcs,
    and you type:

    kill orcs

    	The parser actually susses out that orcs are objects
    in your environment, and that you intend to act on more than
    one of them. The parser will go on to check the attack verb
    for its known rules. The rules for "attack" look like this:

    SetRules("LVS", "only LVS","LVS only")

    	The parser sees that you meant two objects that
    are living, and sure enough, the attack verb will accept
    "multiple living things" as a rule. In this case, the
    matched rule is the first one, with the token LVS.

    	Hold on there, you say. What if I typed kill orc ,
    in the singular? This would still match the first rule,
    because LVS doesn't just stand for "multiple living things".
    It's rather more like "one or more living things".

    	If the first attack token were LIV instead, then
    killing a singular orc would succeed in the parser, but
    killing plural orcs would probably fail.

    	The second rule has two tokens. One is an object
    token, LVS, where object is meant in a semi-grammatical sense.
    The other is a prepositional token, which is also meant in
    a semi-grammatical sense.

    	The way "object" and "preposition" are handled in
    the parser's grammar is not the way they are handled in
    English grammar. For example, you may be feeling indignant
    at being told that "only" is a preposition. Obviously, in
    English, it isn't. However, the parser isn't as linguistically
    sophisticated as you. For the parser, anything used
    periverbally that isn't an object is a preposition. Please don't
    email me telling me I don't know my English grammar. When I
    talk subject, object, and preposition here, I am using
    the parser's simplified grammar.

    	As you might have guessed, an "object token" in this case
    is the noun that the verb will be working with. Note that the
    subject is assumed to be the caller, or player, that invoked the
    verb's execution, and does not have an explicit token identified.

    	So, back to our second rule. "only LVS" means that
    I can issue a command like this:

    kill only the second orc

    	And the parser will not reject it. However, failing
    to use the preposition token explicitly allowed in a rule
    will cause the parser to error. Trying to:

    kill merely the second orc

    will not bring joy.

    The known object tokens are:

    LIV - one living thing
    LVS - one or more living things
    OBJ - one object
    OBS - one or more objects
    STR - a string of characters
    WRD - a generic thing that may be a string, object, or living thing

    To get a list of known preposition tokens, type:

    eval return MASTER_D->parse_command_prepos_list()

    can's and do's

    	Following the create() fun you saw two types of functions:
    can_* and do_*. These are sometimes called "applies". When you see
    someone referring to an apply, they mean a function called by the driver.

    	Notionally, the can_ applies are meant to test the
    validity of the verb's execution, and the do_ applies are
    meant to perform the actions required.

    	In practice, this is only somewhat the case. Whether
    it's a bug or feature, the can_ applies tend to mangle the
    arguments they receive. Pretty much no matter what the
    argument is, it gets turned into a string. It's a peculiar
    "gotcha" that will have you spinning your wheels for a long time
    if you don't happen to know it.

    	That doesn't mean the can_ applies are useless. They are
    in fact necessary. If the can_ apply doesn't exist, or doesn't
    return a positive integer, the do_ apply won't happen, meaning your
    verb won't execute. Since the can_ applies are somewhat hobbled,
    use them for quick, obvious sanity checks, like "is this
    player dead" or "does she have hands to manipulate anything with".

    	If you need to do a check, for example, to ensure that
    the vendor is an elf, that means that you need to make a
    call to that vendor object. Since the can_ applies won't
    handle object arguments, this check will need to happen in the
    do_ function.

    Some examples of can_ and do_ verb applies:

    can_throw_obj()

    Pretty obvious. The command in question would be something
    like "throw switch" perhaps.

    can_throw_obj_word_obj()

    A little trickier. Now we're allowing for a wildcard prepositional token. Here
    the command might be "throw ball at benny", but because the token
    is not explicitly listed (that would be something like can_throw_obj_at_obj())
    and the target is not explicitly a living thing, this apply
    also matches "throw the sword in the lake". Note it won't match
    "throw the jacks on the floor".

    do_read_str_on_obj(string str, object ob)

    If your verb has a can_read_str_word_obj(string str, object ob) apply that
    returned 1, then this sweet baby gets called. Presumably here you'd
    have the verb call the object and tell it to do something with the
    arguments provided. Here is where the actual reading action begins.

    	Alas, the work of parser applies is not done. The object in
    question must have matching direct_ and indirect_ applies, otherwise,
    error occurs. These applies are discussed in the next section.

    The object: direct_ and indirect_

    	As you can see, the thing that gives a do_ apply
    its whammy is a call to an object. That's the point of a verb,
    is doing something, and in the case above, its:

    return vendor->eventSell(this_player(), remove_article(lower_case(str)));

    	However, if you make a verb like this, and then
    just try to use it, it'll fail. This is because the driver
    needs the objects it acts on to have applies that
    correspond to the do_ applies.

    	The corresponding applies are direct_ and indirect_ ,
    and the appropriate one must exist in the object.

    	Verb applies are usually added to the lib
    objects that are appropriate. For example, let's take
    the "press" verb. When you "push the button", the parser
    checks with the verb daemon, VERBS_D, to find out if
    "push" means anything. Sure enough, it's a synonym for
    "press", so the parser checks out the rules for press.

    	Eventually the parser decides all the t's are
    crossed and i's are dotted, and it's time to actually
    see whether the "button" you're talking about is
    pressable. It does this by calling the following apply
    in the button object:

    direct_press_obj(<the button object is the argument here>)

    	If the button does not have this function,
    or if the function returns 0, the parser errors, assuming
    that you're trying to press something that isn't
    supposed to be pressable. Therefore, if you're going to
    make a button somewhere, or a wall or anything that
    should do something when pushed, it will need to
    have that function in it. The way it looks is something
    like this:

    mixed direct_press_obj(object target) {
        return CanPress(this_player());
    }

    	Now, this gets complicated, because the CanPress()
    fun is a function that checks to see whether the
    relationship between the button, the presser, and the lib
    permits the pressing.

    	If you're going to have an object that is
    pressed, it's going to be a right pain in the butt to
    code all the necessary checks into that object. Fortunately,
    you don't need to. If you make a pressable thing, you don't
    need to code all that stuff yourself. Just have it
    inherit LIB_PRESS, which is a file that already
    contains the applies you need.

    	But, we're not done. You'll need to understand
    a couple more things to be able to construct your new verb.

    	direct and indirect refer to the relationship
    of two objects on a command line. If all you have is
    "throw ball", there's no need to worry about object relationship.
    But what if the command is "shoot nice guy eddy with pistol"?
    Or, suppose the player types "shoot pistol at eddy"?

    	The parser needs to differentiate between the two,
    but it isn't nearly sophisticated enough to understand the
    concept of who is acting on whom. The parser just needs to
    know which is first and which is second. therefore, in
    LIB_SELL you'll see:

    mixed direct_sell_obj_to_liv()

    where the direct object is obj and the indirect object
    is liv, and:

    mixed indirect_sell_liv_obj()

    where the direct object is liv and the indirect object is obj.
    Again, this is not English grammar, it's parser grammar.

    References

    	Though sparse, there are other sources of information
    on verbs and the parser. Some of it is quite thorough but
    incomprehensible. Some of it is crystal clear but not applicable
    to the current version of MudOS and/or Dead Souls.

    	You're encouraged to visit the following sites
    to gain more insight into the parser, but be warned that I
    cannot vouch for the intelligibility or applicability of
    their information.

    	Please let me know if you find others.

    http://www.dnd.utwente.nl/~krimud/Docs/NMAdmin/Parser/

    http://www.islandsofmyth.org/wiz/parser_guide.html

    	Within the mud, you should read and understand the
    parser related man page, specifically:

    man parse_command

    Dead Souls Homepage