Tuesday, January 26, 2010

Story telling in role playing games

I play a lot of indie RPGs, like Spirit of the Century and Swashbucklers of the Seven Skies, but for the past couple months, we've been retrying D&D 4e (and I'll be using "DM" below a lot of times in the generic sense). I tried it for 5 months in 2008, running a Keep on the Shadowfell adventure. I have to say that I think that was a mistake for Wizards. It's a dungeon. A lot of the monsters aren't intelligent (rats, oozes, skeletons, zombies). Etc. It ran like a 5 month long miniatures game. Maybe it was me, I don't know.

Nevertheless, we're giving 4e another go (this time, I even get to be a player!) D&D 4e has some great ideas and it has great resources for DMs. Since 2005, I've used techniques described in the "Group Storytelling" in the DMG2. You can find a lot of helpful hints for DMs out there on the net and I haven't read nearly all of them, but maybe I use some novel techniques. Some of these techniques were new to the veteran DMs and RPG designers I've spoken with. I created/independently discovered/borrowed/stole several techniques specifically to prevent wasting the work I do as a DM/story writer.

A friend of mine ran an adventure for us a while back and after we failed a search check in one room, I noticed him file away a sheet on which he had written a LOT of text. I asked him later if we were supposed to see that only if we succeeded in that roll, thus wasting all of that work. He said "yes." I thought it was a shame that he did all of that work and we never got to see it.

Usually, I have a campaign story arc, with subarcs for sections of the story. For each subarc (i.e. adventure), I do something kind of like what the DMG2 describes in the "Branching" section. Rather than make a tree with possibly dead scenes, I write a LINEAR story line which is really just a list of scenes, usually using an outline format in a google spreadsheet (this is great for collaborative DMing, by the way). This list represents the order in which I THINK the players are going to experience the scenes. I almost never have any "dead" scenes in my stories -- I work too hard coming up with ideas and fleshing them out to allow them to be skipped :).

Players almost never make the decisions I'm expecting them to make, so the actual order of scenes usually ends up different from the way I wrote it, with from-the-hip scenes inserted in the list as well, along with alterations to the original scenes (I usually change the spreadsheet as I run the adventure). To prevent the players from skipping over scenes and information that I've worked so hard to produce, I use a few techniques that they didn't mention in the branching section.

First, a few observations to keep in mind:
  1. The players don't have a lot of information until the DM reveals it; they don't know what's behind every door or around every corner
  2. The DM can ask a player to make a roll without telling them why; "make a perception roll"
If the players skip over a scene, there are a few techniques I use to "reclaim" the scene so I can present it to them later on:
  1. if it is an appointment that they missed, make it a "chance meeting" later
  2. if it was with a particular person who is out of the story now, reassign it to another person or use a messenger to convey the information
  3. make a new scene on-the-fly that accomplishes the same goals
Sometimes the story requires a prerequisite before an event can happen, like searching, detecting an ambush, etc. Prerequisites can be a way to put a certain character in the spotlight, like requiring a certain ritual, a certain skill, a bloodline, a race, etc. Lock-and-key scenarios that require successful rolling can be a bit dicey (sorry :D). You don't want the players to blow a roll and fail to see the cool document with the burnt edges that you antiqued by heating up paper soaked with lemon juice! The "Avoiding Dead Branches" section in the DMG2 presents two alternatives for "fake" branches; i.e. situations that look like a branch, but where there is no actual chance of failure. The alternatives are setting the DC of the check to 1 and "dropping the pretense" by just telling the players they succeeded (i.e. no roll). Here are some techniques I use to make sure that the players get the information or have the experience that I put so much work into, but still "keep the pretense"...

Ball and cups
Ever see that magic trick, where the magician shuffles around 3 cups and you can't tell which cup has the ball under it? The first two cups you look at never have the ball; it's always in the third cup. That's because the magician has the ball in his hand.

When the players are searching for something which could be anywhere, sometimes I assign it to "the third place they check". So after they look in two empty rooms, the third room will have what they're looking for, regardless of what the map looks like.

Suppose the players are looking for clues. Prepare several clues for them to find and have them gain the clues on successful search rolls in a specific order, regardless of where they are when they actually do the searching. So they can search 5 rooms in a house, find two clues and then search the alley to find the third clue. If they succeed in each of the first 3 rooms in the house, they get the clues then. If they blow all of the rolls in the house and the alley, they can discover the clues in some other location entirely.

Well, aren't you clever!
Suppose you want to have the characters spot an ambush in a jungle way before it happens so they can ambush the ambushers. The D&D game mechanics represent keen senses as a high perception skill value. Call for a perception roll from the group and if they blow it, give them a "soft ball" random encounter. Wash-rinse-repeat until they get a successful roll. When they do succeed, run the "real" encounter where they get to surprise the ambushers as they are preparing the ambush. Instead of just declaring that the characters have surprised the ambushers, they surprise them "because" they succeeded on a perception roll.

Reality is how you perceive it
OK, this one is from Donjon. Sometimes, the players search for traps and none of the chests/doors/cabinets in the whole building actually have traps. If they ask to check for traps, sometimes you'll want to put a trap there anyway. If they blow the roll, it can explode, if they make it, they can disarm it. When the characters use their skills, the player is actually requesting some spot light time for their character. Give it to them.

Thursday, January 21, 2010

Use rsync with Xus file sharing?

I'm wondering if it would be a good thing to use a variant of the rsync algorithm with Xus file transfer. This would help save a lot of bandwidth for large files that only have small changes. One example is Sauerbraten maps, which can be 2M or more (after compression). When you move a tree, only a small part of the map file is changed, but without rsync behavior, pushing an update requires transferring the whole file.

At this point, Plexus breaks files into chunks that are 50K (if I remember correctly) and keys them by SHA-1 hashes. If we include rsync's rolling CRC with the chunk ID, that would be enough (I think) for a peer to determine whether it could reuse a chunk from its current file and avoid downloading a chunk. I'll have to check on rsync to see its default chunk size. We chose 50K based on tuning with Pastry and Xus' behavior will probably be very different.

Monday, January 18, 2010

Xus file sharing

It's been a long time since my last post; various RL intrusions encroached on Xus. Now I'm starting the file sharing piece. I'm basing it on what I did in Plexus, but starting right away with Git integration instead of putting it off, since that seems to be a better way to actually have Git integration :).

Xus has kind of a weird profile for a p2p system. It's made to handle a mass of small clusters, rather than a giant, monolithic cloud. It's really based on the needs of Plexus, but I suspect other systems out there can benefit from it. In a monolithic p2p storage system like bittorrent or FreePastry's PAST, the cloud can (theoretically) be so large that the data can "live in the cloud". In a game like Plexus (or Sauerbraten), however, the clusters are small and may often drop to 0 users (like when the players for a particular world are asleep), so there needs to be a way to restore cluster state (so a world with no players is still up-to-date when a player joins, even if they weren't around recently).

The most straightforward way I could think of to accomplish this is just to use a Git repository for the Xus file cache and mirror it to a remote Git repository for backup/restore. When a topic space master boots a topic space, it can pull from a remote git repository to restore the state. To avoid a single point of failure, the owners can push to more than one designated repository. The DHT portion of the repository is only useful for peers that are connected, since the DHT expands and contracts, causing chunks to be copied around over time.

Storage:
  1. each resource is tracked with a tag: an outer directory containing chunk-list file and a subdirectory with standard names
  2. creator sends packed delta to topic owner
  3. owner pushes delta to remote Git repository
  4. owner returns signatures for the chunks, etc. to creator
  5. creator stores chunks, etc. in the DHT.
  6. creator gets an event when storage process is complete
Retrieval:
  1. request tag from owner, which responds with ID of chunk-list file
  2. retrieve chunk-list from DHT (which delegates to owner if chunk not in cache)
  3. retrieve chunks from DHT (possibly delegating to owner to fill cache)
  4. requester gets an event when the retrieval process is complete
Several owners is a good thing in this model, since they back the DHT cache.


So, that's the idea. I decided I'm going to include the source to jgit and its dependencies (jsch and jzlib) with this. Requiring on a properly installed command-line Git is just too much work to make developers do (or force their users to do). Requiring developers to download, test, and package a compatible version of JGit wouldn't be nice either. So I have some bloat now. I really don't see the file sharing part as being quite so optional, anyway. From my experience, nontrivial p2p apps tend toward bit torrent the same way most apps tend toward email clients (that's someone's law; maybe I'll get a comment with a citation for it).