Matching (Programming)

From HellWiki
Jump to: navigation, search

Matching

Whenever the MOO server receives a line of text, a number of things happen, as described [the manual]. Generally, input is divided into important parts, and prepositions; the server tries to match important parts after the first important part with objects; and then it tries to find a verb whose name matches the first important part.

However, it doesn't always work, or at least not the way one might like, so we have all sorts of other tools.

Failed Object Match

Often, a verb will be found and called, but the string a player used to refer to an object couldn't be matched with any object. In this case, you will have something like =dobjstr= set to some text that the player used to refer to an object, while =dobj= is set to an invalid object. This is where =$match_utils= comes in.

=$match_utils:match(*STR* string, *LIST* objects)= will try to return an object from the list given that matches =string=. It relies on a number of helper verbs on =$match_utils= and =$string_utils=.

If you need to do matching based on objects that aren't necessarily in the server's list of objects to match, then ignore =dobj= entirely and just use =$match_utils:match(dobjstr, objectlist)=.

Failed Verb Match

Far more annoying and complicated are failed verb matches. Sometimes, a player will type something that very little sense to the server, and a verb cannot be found at all. In this case, =player.location:huh= will be called with every word after the first word as =args=, and the first word as =verb=.

=#1:huh(args)= is rarely overriden, and passes directly to =$command_utils:do_huh(STR verb, LIST args)=, which does the following:

  • If =verb= is a blank string, return immediately and tell the player "I don't understand that."
  • Call =player:my_huh(verb, args)=, and stop if it returns true (nonzero).
  • Call =caller:here_huh(verb, args)= (remember, the caller would be =player.location=, so this will call =:here_huh= on the object containing the player.) Stop if it returns true.
  • Call =player:last_huh(verb, args)=, and stop if it returns true.
  • Check to see if =dobj= or =iobj= are =$ambiguous_match=, and let the player know if so, then stop.
  • If nothing else worked, tell the player "I don't understand that." and then call at most 3 verbs, stopping when one of them returns true:
    • =player:my_explain_syntax(caller, verb, args)=
    • =caller:here_explain_syntax(caller, verb, args)=
    • =this:explain_syntax(caller, verb, args)=

This is a lot of work, but the basic idea is that all the =*_huh= verbs take some input and do _last-chance matching_, that is, matching with things that aren't considered by the server automatically. This can be very handy if a programmer wants to work with input that is not a verb, e.g. if you'd like to send players through exits when they type the exit name (which is not a verb.) This is in fact done in =$room:here_huh=.

$player:my_huh

  • If =verb= is an integer, return.
  • Check every feature object in =this.features= for a verb that matches the input, and if found, call it and return 1 (success). (Also, if this task is about to run out of ticks, complain to the player and return 1.)

$room:here_huh

  • If there's only one word, check with =this:match_exit(verb)= to see if there is an exit that matches it.
  • If there's a single match, call =exit:invoke(player)= and return 1 (success).
  • If there's an ambiguous match, tell the player, and return 1.
  • Otherwise, return 0.

$player:last_huh

  • Do some extended checking with =$match_utils:match= (see above) to find all possible candidate objects that the server may have missed, and then try to find a verb to call using the candidates. Call it and return 1 on success.
  • If =verb= starts with "@" and =prepstr= is "is", call =$last_huh:(verb)(@args)= and return 1.
  • Otherwise, return 0.

$last_huh

=$last_huh= is an object that contains verbs that might be called as a last resort. This is where the verb is that is used to set messages using the "@<message-name> is <value>" syntax. Check =$last_huh:@*= for details.

$command_utils:explain_syntax

  • Check =player=, =caller=, =dobj= and =iobj= for verbs that the player might have meant to call. If one is found, show the player what they might have meant to type ("Try this instead"), and return 1; otherwise return 0.

Synopsis

That is a lot of screwing around just to figure out what the player meant to type. However, it can be harnessed to add functionality to the MOO that would not otherwise be there, e.g. the exit-matching. And now you know what all those huh verbs do.

(Note: there is no =$player:my_explain_syntax= nor a =$room:here_explain_syntax=, despite their being called in the code; also, there are three verbs on =$last_huh= that seem to never be called.)

-- Main.BlackLite - 28 Nov 2004