So instances aren’t as hard as you might imagine, but nor are they trivial. We now have two instances in the game, and I think we’ll leave it at that for now. The beginning area is an instance because it wouldn’t work if more than one person started a character around the same time. The other is the mansion quest that comes with the stock Dead Souls mud lib, mainly so I could test the instance-related code.
I was able to retrieve the area I had created a few years ago and work it into the current game. The boot drive had failed, but the data drive was intact. I created an Ubuntu CD and copied the old code off the drive to safety.
Now, if you start a new character, you find yourself in a padded cell that you have to escape. After getting out of that room, you’ll find yourself in a floor of a hospital. The staff are dead and you have to find your way out. The normal exits are blocked off since your floor is under quarantine. Once you find your way out, you’re out of the starting instance and in the game proper.
This wouldn’t work if two players started in the padded cell together, or if a second player started before the room had reset. The needed items wouldn’t be there. Instances mean that I don’t have to worry about that.
There’s a story telling reason for starting in the hospital. You’re sociopathic. You don’t see the world the same way the other characters in the game see it, so you have been committed. This explains why the world in the game feels different than the world you inhabit as the player outside the game. Since you provide the brains behind your character, the other characters in the game see you as a bit crazy.
How did I make instances work? In Dead Souls, there are a few points where I had to add some logic to get it right, so far. They deal with player movement and doors.
When a player or NPC moves, it uses code in /lib/props/move.c to manage moving to the destination room. There, I can check if the destination is an instance and, if it is, get the instance clone of the room. Then I go to the clone. There’s a daemon that tracks which clone is for which player or party. I also added some code to /lib/std/room.c to manage creating the clone so the player/NPC could just query the master room object for the appropriate clone and get it. When an NPC moves from one room to the next in an instance, it makes sure it gets the next room in the same instance as the room it’s in.
Doors need to be instanced as well because their state is specific to the path between two instanced rooms (this would be true for any objects that act like doors from a data management perspective). This is handled in /lib/exits.c with clone tracking provided by the same daemon as for rooms. In instanced rooms, you have to go through the GetDoor() method to get the right instance door.
The code for setting up the room in the create() function doesn’t change. Exits still reference the master copy, as do the door configurations. This makes it easy to make a room instanced or revert to the original non-instanced version.
I modified the update command to let me update the room and reclone the instance I was in. The hospital daemon also needed a slight modification (less than 20 LOC, I think) to handle NPCs that needed to be unique within an instance. The hospital code is based on the Discworld mud lib, not Dead Souls.
Future changes could allow multiple laser tag games on the same range, something still to be finished. I’m still thinking through what else might work with instances. I don’t want it to be a way to be lazy about content. I want there to be good reasons for doing them.
IC vs. OOC
I’ve been working on the help system and a new version of nroff. The goal is to have a common layout for all command/verb help while also cluing the command/verb object into some important information about how it is used. I’m working now and then on a new parser based on the Discworld parser.
Dead Souls divides commands (in the sense of “things you type to control the game”) into two major types: commands and verbs. There are also soul commands and a few other things thrown in, but commands and verbs are the two major types. Verbs have syntax that is used by the parser to determine what is being acted upon. Commands do all of their own parsing.
This division of things into commands and verbs had me considering some of the different ways we experience interacting with games. Every game can be divided into two realms: in character (IC) actions and out of character (OOC) actions. It doesn’t matter if you’re playing a board game, a LARP, or a MUD, there are things you do that are IC (e.g., buy a hotel in Monopoly) and things that are OOC (e.g., role the dice in Monopoly). IC actions are part of the narrative of the game while OOC actions are outside the narrative, even if they impact the narrative.
Another way to think of this is that OOC actions make you aware of the interface to the game, whether that’s a command line, a mouse, or talking about the game to other people. In a LARP, if you do rock, paper, scissors, such as was done in the old World of Darkness, you’re doing something outside the narrative because vampires aren’t really standing around seeing if paper beats rock. They’re running around shooting each other. The IC action is fighting, but it’s accomplished by an OOC mechanic.
On the other hand, social interactions in a LARP tend to be IC: the conversation is experienced as the players intend it to occur in the story.
Continue reading →