[MUD-Dev] Re: MUD Design doc (long)

Sunny Gulati sunnywiz at radiks.net
Fri Dec 18 11:18:55 CET 1998


Chris Gray wrote:
> 
> [Mik Clarke:]
> 
>  >  if target object not specified,
>  >    emote is in dire need of a bath
>  >  else
>  >    locate target object
>  >    if not found,
>  >      send_to_char "Sorry, can't find one of those."
>  >    else
>  >      if (!object->can_you_be(CMD_SNIFFED))
>  >        send_to_char "It smells of nothing in particular."
>  >      else
>  >        object->you_are(CMD_SNIFFED, char)
> 
> Big nod here.
> 
> This is what I do in my system, and it works fairly well. It is also
> possible to write generic code that will do this with lots of verbs,
> so the skeleton can be re-used via a function call.
> 
> You can get more complex, too:
> 
>     - there can be command pre-empts attached to the room and the
>         character, which may supercede any attached to the object.
> 
>     - to save effort, you can check for simple string responses as
>         alternatives to methods - just emit the string.
> 
>     - locating the target object can vary a bit. I have two variants, one
>         which searches only the character's inventory, and one which
>         searches that, then the room's contents. (So far, 'get' is the
>         only one that wants to search the room's contents before checking
>         in the inventory.)
> 
>     - another simplification is to have rooms able to have lists of
>         "scenery" words - if no matching object is found, check that
>         list of words, and if a match is found, just say something
>         generic like "You can't " + verbString + " the " + nounString.
> 
>     - there might be other places to sort-of check. For example, items
>         for sale in a store might be off-limits to some verbs until
>         you have purchased them.
> 
> --
> Don't design inefficiency in - it'll happen in the implementation. - me
> 
> Chris Gray     cg at ami-cg.GraySage.Edmonton.AB.CA
> 

Given my LP background, I thought it would be helpful to explain how
I've seen LP's do this stuff, for the benefit of those who are not
familiar with it.    If you're familiar with it, skip on :)

- Every player object has a list of "verbs" that are understood, with a
pointer to a function to call if that verb is "found". 

- Every object has an "apply"(?) (a function that is called back by the
driver, with a specific name.. like a implementation of an implicit
interface) called "init", which tells which verbs are understood by that
object. 

- Verbs that are understood implicitely by a living object are placed in
the living's init function like so: 
   void init() { 
     // note: liberty being taken with syntax.
     add_action("verb","function",flag); 
   }
The flag has to do with how many characters in the verb are significant. 

- As the driver moves objects into other objects and stuff like that, it
calls the init() function appropriately to add/modify the verblist of
various interactive-capable objects.   

For example, if a sword that has an
'add_action("wield","wield_func()")'  is moved into a room, which has
Boffo and Buffy in it, then the following happens: 

   +  Sword is moved
   +  Boffo's list is taken as context, and init() is called (adding
wield to Boffo's list)
   +  Buffy's list is taken as context, and init() is called (adding
wield to Buffy's list)

It is up to the sword to decide that Boffo and Buffy can't wield it
because he isn't holding it.  However, it could be smell'ed if it wanted
to be. 

- If the driver moves the object from the room into Buffy's inventory,
then the following happens:
 
   +  Boffo's list is taken as context, and init() is called (removing
wield from Boffo's list)
   +  Buffy's list is taken as context, and init() is called (removing
wield from Buffy's list)
   +  Sword is moved
   +  Buffy is a living environment, so Buffy's list is taken as
context, and init() is called 
      (adding wield to buffy's list). 

- Note that if there were two swords, one in the environment, one in
buffy's inventory, somehow the one in buffy's inventory ends up having a
preference.  I think its not just a list, but a list with built in
priorities (ie, inventory is always higher than environment, etc etc).  

- There are several optimizations to prevent stuff from happening twice
(ie, it wouldn't actually remove and then readd stuff as indicated
above; it would change the order for Buffy, and remove from Boffo, I
think). 

- When a player types a command, lookup is pretty much instantaneous (at
the cost of additional expenses during object moves.  Now, granted that
object moves happen as a result of player commands [usually], it could
be argued that players type commands more often than object moves,
making this useful.  I don't know. 

- Note that the init() function could be inherited from a standard
object, and/or redefined too.. ie, /obj/weapon.c could define the actual
wield();  /my/sword_of_lightning.c could inherit that, and state: 
    void init() { ::init(); add_action("lightning","dolightning"); } 
    int dolightning(string rest) { 
      if (this player is a magic user) { 
        perform lightning stuff
        return 1; 
      }
      return 0; 
    }
The return code is: 1 = command successful, 0 = command not successful,
keep looking for something else. 

- On a failed command, a command can set a "return message" using
notify_fail().  So, rather than the driver saying "bwah?", you could
tell smell to notify_fail to ("it doesn't smell like anything in
particular").   I think the point of this discussion was to get more
interesting results from this. 

- In the above example, you could also override the dolightning()
function call, or the do_wield function (whatever that is). 

- Another shortcut is used in the player object.  There's  a default
handler that is called for ANYTHING the player types.  Say, they typed
"bounce".  This handler (written in LPC) checks to see if /cmd/bounce.c
is available; if it is, then it calls there to get it handled.    This
means verbs can be added/removed from the game without recompiling the
player object (which would involve logging out and stuff).    [Add an
cache layer of previously loaded objects, and this gets pretty fast. 
Also lets you do command paths; for example on VH admins get /cmd/admin,
/cmd/wiz, /cmd/emote, and /cmd/std.  Wizards get ~/bin as well.  I tried
using a failed cache onceuponatime, but back then memory was NOT cheap,
and people mistyped.. a lot.   That has changed now.]


In a graphical context, I can see something similar.  Verbs might get a
radius in which they could be used; they will definitely be available in
someone's inventory.  

Anyway, hope this has been helpful/informative.  

Sunny




More information about the mud-dev-archive mailing list