If you've used revision control much before, and/or worked on a project with a lot of people simultaneously, you have probably been exposed to branching. I reflected a little on how we use it at work and how I use it, and thought I'd write it down.

Revision control is when you get some sort of system to keep track of the entire history of a set of files. For example, all these blog entries are stored in an RCS on my computer at home. I don't feel pressure to make changes to them, because I know the system is remembering everything they ever said.

A "branch" is just a copy of the files, but it's a copy which the system knows originated from some earlier version, so that you can pinpoint a time where the branch split off and diverged from the "trunk", as it is sometimes called. Branches are useful for several things.

The two main uses I see branching used for at work are freezing a version of the code and separating risky features. When we ship a version of our product, as we near the release, we fork a branch off of the trunk where the code is meant to sit with relatively little disturbance until release. Any high-priority changes that absolutely must happen will take place in that branch, while the trunk of the code may continue with the normal rate of change for work beyond the upcoming release. When we ship, we freeze the branch, and that's that.

We also use branches for keeping risky features or large chunks of work a little removed from the trunk. The reason we do this is that we build the trunk nightly, so that every day there's a new installable product for the entire team to test out and use. If large, complicated changes are taking place in the code, the probability that a serious bug arises in the product is high. If this happens, then the bulk of the team suddenly doesn't have a new build that's usable that day. It can halt progress for a day, so it's worth taking precautionary measures.

What happens is that we create a branch of the code that is to be used for the development of one of these "risky features." Changes are added to that version and not to the trunk version, so while the major problems are being ironed out, only the few people working on that feature are affected, not the whole team. Approximately nightly, all the changes in the trunk are merged down into the feature branch, so that the code is still mainly in sync. Periodically (every several weeks), the code in the feature branches is merged up into the trunk if it is of high enough quality, i.e. it passes a bunch of tests. At this point, the trunk and the feature branch contain exactly the same contents.

An interesting idea that came up in our last development cycle was the namingof our team's feature branches. In the product cycle before that, feature branches were named after the features developed within. But in this one, the feature branches were named after colors. Red, green, yellow, etc.. I asked one of our development managers about it when the announcement was made, and one of the answers he gave me is so that we wouldn't have any problems putting any feature in any branch.

This didn't make much sense to me at the time. It felt kind of arbitrary, but now, over a year later, I think I kind of get it. As a programmer, naming is important to me. Sometimes I spend an inordinate amount of time agonizing over how to name something, because if I use a name I don't like, it continually irks me afterwards. Likewise, having neutral names for feature branches eliminates the part of the brain that says, "we can't do this work in that branch, because it's intended [due to its name] for this other kind of work."

I adopted this for my MUD. Even though I'm just a team of one, I have larger features and smaller changes. I like to keep a stable trunk build all the time, so I use a "feature branch" called "blue" for my bigger items. For instance, all the work on socials and pmotes went into blue first, then merged into the trunk. Meanwhile, I made bug fixes for things unrelated to that feature in the trunk and merged them down.

I almost think of this usage as a third way of using branches. If you consider that the trunk is all that really matters, and if you like the idea that the trunk is always stable, and if you like the thought that features are added to the trunk as a single revision, this use of branching kind of satisfies that. Even though the feature really is too big to add all at once, all of the little iterative pieces are added in this branch, kept out of the way of the trunk. Eventually, when it's all ready to go, it's added as a single big change to the trunk. You kind of get the best of both worlds: granular additions, and a nice clean view of the trunk. Plus, if you need to revert an entire feature, you have a single change (the merge) to undo, not a ton of little ones.

I use revision control for everything. I can't imagine getting along without it anymore.


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.


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">
    <dextSource>You blarg about.</dextSource>
    <dextBystander>$1c blargs a lot.</dextBystander>
            <dextSource>You really blarg yourself good.</dextSource>
            <dextBystander>$1c takes a good long blarg at $1r.</dextBystander>
        <dextSource>You blarg $2 about.</dextSource>
        <dextTarget>$1c blargs you good.</dextTarget>
        <dextBystander>$1c blargs $2 so much that $1s hurts $1r.</dextBystander>

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.

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.