Sunday, 6 February 2011

Better article support

There are too many interesting things to work on, and too little time to do them in. I use this as justification for why I haven't worked on the Christmas requests from a user of my MUD framework until now.

Anyway, the task at hand is allowing use of articles in the commands they give, and displaying more correct messages in response to those commands by using articles in them. This transcript shows the current user experience.

> look
A room
This is a room.
It contains: brown pants, green pants, chest, you.
Exits: south
> take pants
Which pants?
> take the pants
You cannot find any the pants.
> take brown pants
You take brown pants.
As it shows, articles are treated as unrecognised adjectives in user commands. And when a sentence is constructed to describe an action (like the successful taking of pants), the lack of an article leaves it looking clunky.

It has been years since I last thought about how to do this sort of thing. I seem to recall some complex series of rules where a bystander and the actor see different things. The actor would see a description qualified by "the" when it is the only object which matches the command they gave, and qualified by "a" or "an" when it is one of two or more objects which match the command they gave. Meanwhile the bystander would always see "a" or "an". Or something like that. Thinking about it a little, I decided I would rather go with something simpler and worry about complexities later on. So taking a simpler approach when dealing with single objects, the actor would alway sees "the" and the bystander always see "a".
X takes an apple.
You take the apple.
Or in Python..
#   If the object is a body, use their short description directly.
text = self._object.shortDescription
if isinstance(self._object, Body):
    return text
#   If the viewer is the actor, use the description with "the" article.
if self._viewer is self._actor:
    return "the "+ text
#   If the viewer is not the actor, use the description with "a"/"an" article.
if text[0] in ("a", "e", "i", "o", "u"):
    return "an "+ text
return "a "+ text
Looking at the simplistic "vowel as a first character" check, I can obviously find some standard list of special cases to ensure as much correctness as possible. I also seem to recall some script on MudBytes that someone ran which located special cases of words, although maybe that wasn't related to articles. I can look into that at some later time.

Anyway, moving on.. the parser already supports stripping adjectives from a command and identifying the name of the object being referred to. Adding the articles to the list of these standard grammatical adjectives (determiners) does the trick.
articleDeterminers = set([ "a", "an", "the" ])
determiners = distributiveDeterminers | cardinalNumberDeterminers | articleDeterminers
And then the stripping ensures they are not factored into identifying the referred objects.
words = [ s.strip().lower() for s in string.split(" ") ]
noun = words.pop()
allAdjectives = set(words)
adjectives = allAdjectives.difference(determiners)
Now I have basic article support. Hmm. It is rather basic. But now that I can see articles in object descriptions in game output, I can see that I should be using the same point of view based logic in all description generation. For instance, displaying the room contents in a 'look' command.

No comments:

Post a Comment