20090720

Socials and Pmotes

I've been busy lately... with life. And with a new feature (or couple features, I guess). Most MUDs have a few different kinds of commands. Most commands are used for doing something useful, like moving around, attacking stuff, examining your stats, and so on. One class of commands is used mainly for fun. These commands are called "socials," because they're used for socializing, I guess. Before now I had one social hard-coded in my MUD, but now I have a few. More importantly, I now have a way of adding more without making code changes.

Here's an example of a social in use. This is one of the new ones I put in.

<type commands for a list> blarg man
You blarg a man about.

<type commands for a list> blarg self
You really blarg yourself good.

<type commands for a list> order man blarg joint
A man blargs you good.

<type commands for a list> order man blarg guy
A man blargs a guy so much that he hurts himself.

<type commands for a list> order man blarg self
A man takes a good long blarg at himself.

Take note at the number of different pieces of text here (and these aren't all of the possible ones, as you'll see in a bit). For any given action, there are a number of different points of view. There is the possibility that the command takes a target to act upon. There's an option to see something different when the target is oneself.

Social Parameters

When writing socials, I tend to follow the model set forth already by Eventos. There are three points of view that matter: you are the originator of the action; you are the target of an action; or you are a bystander observing the action. Accordingly, when authoring a social you have to fill out text for these three points of view.

And I like to think of the status of the target in a few ways: the action has no target (is impersonal); the action has a target, and that target is yourself; the action has a target, and that target is someone else.

This represents the complete set of pieces of text that need to be defined. But we're not done. Notice in the output above that there is some other interpolation going on. "A man blargs a guy so much that he hurts himself." What happens if the actor here isn't "a man" but instead a female? It should read, "...she hurts herself," but I'd really rather avoid having separate canned text for all possible combinations of genders that can be imagined. So there's some interpolation taking place.

Dext

I'm trying to build up suspense for the punchline, but I just can't anymore. The text that you put in the social definition file isn't straight text, but instead text with embedded directives that are substituted at runtime. Text with directives - I call it "dext." If you think that's a crap name, you can tell Kirill about it, but you probably don't want to know what it was called before he helped me out with the naming.

At this point I'm ready to show the full definition of the "blarg" social.

<social kind="social" order="0">
    <string>blarg</string>
    <dextSource>You blarg about.</dextSource>
    <dextBystander>$1c blargs a lot.</dextBystander>
    <withTarget>
        <selfTarget>
            <dextSource>You really blarg yourself good.</dextSource>
            <dextBystander>$1c takes a good long blarg at $1r.</dextBystander>
        </selfTarget>
        <dextSource>You blarg $2 about.</dextSource>
        <dextTarget>$1c blargs you good.</dextTarget>
        <dextBystander>$1c blargs $2 so much that $1s hurts $1r.</dextBystander>
    </withTarget>
</social>

The astute reader will immediately see where $1 and $2 are being substituted for the actor and the target in some of the above examples. But even the astute reader can't possibly imagine what the trailing text on the directives stands for. If you can guess, then you're awesome in my book.

Another interesting observation you can tell from looking at this spectrum is that "I" is conspicuously absent. That's because the MUD is a second- and third-person only game. The system/world tells you things, so addresses you as "you." Sometimes it tells you things about other people, so refers to them as "he" and so on.

A little documentation

Here are all the flags currently supported, which you couldn't possibly have guessed.

FlagMeaning
cCapitalize - used for beginnings of sentences.
sSubjective case - i.e. subject of the sentence. E.g. "he/she/it"
oObjective case - i.e. target of an action. E.g. "him/her/it"
rReflective objective - third person target when the target is oneself. E.g. "himself/herself/itself"
pPossessive case, e.g. "his/her/its"
fShow Full Name - an override to force the system to show the full short description in this place. I'll try to show why this is useful later. Clearly, it's not being used here.

You're lucky I didn't use the Latin cases here (nominative, accusative, acc. again, genetive, respectively). At a glance, the reflective objective may seem out of place, but it's not. I may get disagreement from the hardcore grammar crowd, but I think the reflexive modifier only exists for the objective case in English. In the subjective and possessive cases, the closest you can get is usually termed "intensive": "he himself" and "his own", respectively. These serve functionally different purposes and are more adornments, so I haven't included them now. Also because it's a little hard to tell how to fit them into a simple system that works merely by substitution.

Some of these flags can be combined together, such as a case and capitalization. Others obviously can't, like two different cases.

The way the dext directives are used is that when a social command executes, it constructs an evento that is sent to everyone in the room. The various fields of the evento (source text, target text, and bystander text) are generated from the dext by passing in the source and (optionally) the target. The MUD makes a guarantee to social authors that $1 is always the originator and $2 is always the first target in the target-related text.

Finally, socials don't have to work with a target, and don't have to have separate text for a target when the target is oneself. It's up to the social author. This is one of those reminders that there are multiple audiences for the MUD. I'd say it's primarily about the player, but much thinking goes into making things painless for the various creative people that are inevitably involved, such as builders who create the areas, dealies, and nipics. From what I hear, real game studios make similar investments for the sake of their artists, level designers, etc..

Hey, what about this "pmote" thing?

Silly titles... right, you caught me. I alluded to something called a "pmote" in the title, so I'd better talk about it. Everyone knows what an emote is, right? Well, maybe not. It's a command that sends some output that is your name followed by arbitrary text. In case that sounds too vague, here's a concrete example.

<type commands for a list> emote does a little dance.
jointface does a little dance.

There you have it, instant socials. In IRC I think the format is "/me string". In IMs, people do *string*. It's pretty useful for ad-hoc acting, and if you enjoy role-playing, you might use emote even more than any other communication command. But it has shortcomings, like this.

<type commands for a list> order man emote hits jointface in the face.
a man hits jointface in the face.

He hit him in the face?! I bet that hurt! Hey wait, that's me! You get the point. It would be nice if by doing that action, instead of seeing your name as if you were in the third person, it said "you" to let you know he actually targeted you. This is exactly where pmote comes in.

I don't know what pmote stands for. I reckon it's probably "player emote" or something. It allows for the insertion of directives (hey, weren't we just talking about those before?) into the emote string for more effective acting. It works a little differently than regular socials, though.

As an aside, in looking up what pmote stands for, I found some documentation on other MUDs' pmote systems. I am compelled to admit that this one is more advanced than mine, based purely on the number of different directives it supports.

Directives and Pmotes

There are two criteria for the minimum effective use of pmotes: you can refer to things around you by name and you can refer later in the sentence to those things again. In my system currently, you can refer to a thing in the room by prefixing it with an @ symbol. Once you've done this, it assumes a position at the end of the list of known things and can be referred to using the usual $ syntax. I call this variation on dext "edext", as in dext with embedded directives. It's not a great name, but whatever.

<type commands for a list> pmote grins at @man.
jointface grins at a man.

<type commands for a list> order man pmote grins at @joint.
a man grins at you.

<type commands for a list> order man pmote grins at @guy.
a man grins at a guy.

Remember that "show full text" flag from above? You can see it at work here. I include that flag for @ directives to keep "pmote grins at @man" from becoming "jointface grins at him". Some more interesting examples:

<type commands for a list> pmote is really mad at @man because $1s is dumb.
jointface is really mad at a man because he is dumb.

<type commands for a list> order man pmote hates @guy and $1p dog.
a man hates a guy and his dog.

Notice in both these examples how I referred back to the assimilated target later on. The first time you point to a target, it always inserts their full short description (again, that "show full text" flag). This limits the sentence structure a little, but in practice I haven't noticed it as a big deficiency in the past. Here's another neat use of the possessive:

<type commands for a list> pmote pets @man 's cat.
jointface pets a man's cat.

<type commands for a list> order man pmote is jealous of @joint 's dog.
a man is jealous of your dog.

I opted for a natural syntax for the possessive here, where having the orphaned "'s" retroactively indicated to the parser that the previous directive was a possessive form. The reason the space is required is that the text immediately following the @ is a full target string, conferring the extent of its expressiveness. Check out this example, showing off a target string and why the apostrophe would be ambiguous if not separated.

<type commands for a list> pmote thinks @1.'man dude' 's bagel is cool.
jointface thinks a man's bagel is cool.

The @ syntax was pretty arbitrary. I was looking across the top of my keyboard for a piece of punctuation to use, and I just happened to feel like using it. Only later did I realize it happens to match the Twitter syntax for directing messages to specific people.

How it works in code

Dext and edext are handled by different functions. Here are their signatures.

def DextTools.textFromDext(dext, hearer, targets)

def DextTools.textFromEdext(edext, hearer, procLookupTarget)

In the case of dext, there is no assimilating of embedded directives. The set of known things (termed "targets" here) is known already, so the caller just passes in an array of them, where targets[0] is $1 and so on.

For edext, there is no predetermined list of targets; it's built up as the string is scanned. So instead, the caller passes in a function that maps target strings to targets. I like this design because it doesn't restrict the caller at all with how the lookups are done. They could be done in a static array, generated randomly, queried from some other source, etc.. Here's the fairly sensible code for pmote, which currently lets you target mobs in your current room. Check out them closures!

procLookupInRoom = lambda { |targetString|
    return room().bagMobsInRoom().searchByTargetString(targetString, self)
}

Not everything is perfect

There are some inevitable problems with trying to make everything work.

<type commands for a list> order man pmote thinks @joint is crazy.
a man thinks you is crazy.

Woops! This looks fine to everyone else, at the expense of you. Without making the system aware of the various verb forms of "to be" and making it dynamically rewrite that on the fly, I don't really see a good way to make this look correct to both the second and third person view.

This brings up an interesting point: the previous example might be considered an invalid input. Step back from the nitty gritty of the substitution and consider the overall goal. The pmote command lets you act out things with your character, potentially including others nearby in the text. In the previous example, the originator conveyed far more in an action than is really possible.

And here's the crux of the point. I think any such pmote that includes some other person being used in a subjective case (like the example above) is probably doing an invalid pmote. In contrast, objective is fine, since you can do actions to people, and possessive is fine, since it's essentially adjectival.

In the end, there are infinite ways that players can abuse emotes and pmotes, but precedent across many MUDs has given these particular powers to players despite the risk. As a formerly avid role-player, I like giving players good tools to express themselves, so I agree here. I had fun coding up this feature because I like coding, and I like grammar.

1 comments:

leah said...

O WOW O WOW.... you are so smart, what a smart guy i have married, o wow. who would have ever thought of how smart you are to write such a hugely long entry about something i have no idea about!

it looks complicated and i really enjoyed the parts about being jealous of dogs and blarging so much he hurts himself.

Post a Comment