Mar 152014
 

I’ve gotten the Ruby version of Second Contract to the point where I can create a character and give it a position: sitting, standing, kneeling, crouching. Movement between and within scenes can be restricted to various positions depending on the character’s relationship with parts of the scene.

Let’s walk through what it takes to do this using the scripting language.

Continue Reading Positioning a Character

Feb 232014
 

A year ago, I talked about moving to DGD and building a persistent game. I managed to get enough code written that you could fire up the game, create a character, and look at the void in which you found yourself.

Since then, I’ve run into a wall. I love test driven development, but LPC environments don’t really have any good test libraries. I started writing one, but given how I would have to integrate it into the running game (or not, depending on some #defines), I decided to start over a bit with Ruby and EventMachine. The combination provides much of the core of an LPC driver, so it’s not as bad as it sounds.

So now, I’m developing Second Contract as a Ruby/EventMachine driver with some scripting. I’m keeping the LPC version in GitHub and created a new repo for the Ruby edition. I’m keeping the LPC version around for when anyone wants to take a look at it — it implements an HTTP REST service and some parsers. Development will focus on the Ruby side of things.

I’ve structured the Ruby version somewhat after the DGD version. I have parsers and compilers, archetypes and objects, player information separate from character information. What I won’t have is a web interface for editing domains, archetypes, or objects. Instead, I’m borrowing some ideas from the static build community: the game loads archetypes, traits, verbs, and other metadata from files. This makes it easier to manage game definitions in a source code control system, something that was difficult with a web interface.

Over the next few weeks, I’ll write posts talking about each aspect of this system. Along the way, we’ll see the scripting language used to respond to events and how the game manages data and objects.

Brief Overview

Game objects consist of data and an archetype. Archetypes consist of data, event handlers, and data calculations along with a potential archetype and traits. Traits consist of event handlers and data calculations. Archetypes may inherit from at most one archetype but as many traits as desired. Traits may inherit from as many traits as desired as well.

This means that archetypes and traits define code, and only archetypes and objects define data. Data follows single-inheritance rules while calculations and event handlers follow multi-inheritance rules. Data are things like object details and descriptions, exits, enters, flags, skills, stats. Things that make an object unique.

The game stores objects in a database, providing object persistence. The game loads archetypes and traits from files.

Hospitals (to borrow the term from the Discworld mudlib) will manage transient content. This includes wandering mobs, bosses, and gatherable resources, including loot tables for mobs. If scenes contain inventory, then the hospital data file defines inventory items as well.

Domains consist of a coherent set of scenes, paths, mobs, quests, etc. A domain or sub-domain may use a map file to define the starting set of scenes, but this is for convenience. The map file provides all the data for the objects making up the scenes, paths, and terrains, including guard objects (e.g., doors). Loading a map file will make sure that the objects named in the map have the specified data. It won’t remove objects from the domain that aren’t mentioned in the file.

By moving all scripting off to archetypes and traits, data files can describe the rest of the game, hopefully reducing the amount of time needed to code an area. Since most LPC-based rooms tend to be instances that set up some data and then rely on inherited functionality, this seems reasonable. For those rooms that need unique event handlers, it’s easy enough to create an archetype. Who knows, you might want a second room similar enough to the first somewhere else.

Sneak Preview

The following is the equivalent (at this point) of the basic character archetype in the LPC version of Second Contract:

---
flags:
  living: true
details:
  default:
    noun:
      - human
    adjective:
      - simple
---
based on std:item
is positional, movable

can scan:brief as actor
can scan:item as actor

can move:accept
can see

reacts to pre-move:accept with
  True

##
# msg:sight:env
# 
# Used to report on events around that can be seen.
#
reacts to msg:sight with
  Emit("narrative:sight", text)

##
# pre-scan:item
#
reacts to pre-scan:item as actor with do
  set flag:scan-item
  set flag:scanning
end

reacts to post-scan:item as actor with
  if flag:scan-item then
    :"<actor:name> <examine> <direct>."
    reset flag:scan-item
    reset flag:scanning

    Emit("env:sight", Describe(direct))
  end

##
# pre-scan:brief
#
# We set the flag that we'll be looking around.
# This lets other things react to this.
reacts to pre-scan:brief as actor with do
  set flag:brief-scan
  set flag:scanning
end

reacts to post-scan:brief as actor with
  if flag:brief-scan then
    :"<actor:name> <look> around."
    reset flag:brief-scan
    reset flag:scanning

    Emit("env:title", ( physical:environment.detail:default:name // "somewhere" ) )

    if physical:position then
      set $description to "You are " _ physical:position
    else
      set $description to "You are"
    end
    if physical:location.detail:default:name
      if physical:location:relation then
        set $description to $description _ " " _ physical:location:relation
      end
      if physical:location.detail:default:name then
        if physical:location.detail:default:article then
          set $description to $description _ " " _ physical:location.detail:default:article
        end
        set $description to $description _ " " _ physical:location.detail:default:name
      else
        set $description to $description _ " somewhere"
      end
    end
    if physical:location <> physical:environment then
      set $description to $description _ " in"
      if physical:environment.detail:default:article then
        set $description to $description _ " " _ physical:environment.detail:default:article
      end
      set $description to $description _ " " _ physical:environment.detail:default:name
    end

    Emit("env:sight", $description _ ". " _ Describe(physical:environment) )
    Emit("env:exits", ItemList(Keys(Exits(physical:location))))
    # now we can list items/mobs nearby/in the scene
  end

Note that the top of the file is YAML-formatted data. This allows you to set up the data without having to write a lot of code to do so. Archetypes can consist of just data if they don’t want to define new event handlers.

An example description of inside the inn:

> look

You look around.

Old Seadog

You are standing behind the bar in the Old Seadog. The inn radiates age and
charm with its oak beam roof and many seafaring mementos secured firmly 
around the walls. Even the bar is a single thick oak slab, worn and chipped 
with years of service to rowdy sailors. An old glass window lets in a little 
light from outside. A game room is to the south and a parlor is to the 
southeast. A party room is at the bottom of a flight of stairs.

Obvious exits: west

>

The rest of the files needed to get a two-room game up and running are in the game directory. The available verbs allow you to go west or east, enter the inn, stand behind the bar, on the bar, on the floor, crouch, kneel, and sit. You can look (at the scene) as well as details in the scene (the bar, the walls, floor, window, and ceiling in the inn).

Jul 062013
 

It’s been a while since my last post. I’ve done some traveling and other work: writing a chapter on Shared Canvas for a book coming out of a conference, working on a poster for an upcoming conference, and some other work-related things that aren’t as tied to narrative. In April, I spent a weekend in Munich at a workshop concerned with getting digital theater history projects working together. Theater history and architecture aren’t my areas of expertise. I was there representing the linked open data and REST api worlds as ways to get digital projects talking to each other. But theater stages led me to think about scene composition, so I also wandered around parts of the city center (within walking distance of the University) and the English Garden taking pictures with an eye at using them to compose scenes.

Continue Reading Describing Scenes, Paths, and Terrains

May 052013
 

I’ve put together a distribution of the Second Contract mudlib (SC-0.131250). It’s so basic that you can’t do much more than build it and see that it lets you create a minimal character in a single room with no details. I wanted to get something out at this point for several reasons: it gave me something to work towards, you don’t have to take my word that I’m making progress, and now I have a framework in place for making future releases.

The distribution consists of a checkout of the DGD github repo, the (networked) Kernel Lib github repo, and the Second Contract github repo all suitably arranged to allow easy bootstrapping. I’m using the network extensions now so I can make sure everything will work when I add intermud chat.

Mudlib versions are date based: M.yydddn where M is the major version number (0 for the foreseeable future), yy is the two-digit year (13 for 2013), ddd is the three-digit day of the year, and n is a minor version number used to distinguish releases on the same day. So any version which starts with 0.13 is from 2013, 0.14… is from 2014, etc. Higher numbers are newer releases. If I put out a test release, I’ll mark it as such with a sensible suffix.

What’s in this distribution?

This is just enough to illustrate a game that can boot and have a character floating in an empty scene. Multiple characters can log in, and they will see each other “looking”, but won’t otherwise see each other in the game unless they use the “%who” command to see which characters are active in the game. There’s even some debug output when you “look.”

The README has instructions for getting everything up and running, including which ports to log in to for which types of accounts and access.

Game accounts made through the telnet port are not visible to the Kernel lib as regular users that can be made creators or otherwise able to log in to the binary port. The two are completely separate. Game accounts may have up to five characters associated with them. You can choose which character to play when you log in, and you can only have one character in play at a time.

Note that you should not use this code as the base for a game yet. There’s a lot of unfinished stuff lying around and I’m not going to bother with writing upgrade functions for objects until I get closer to something that is workable as a game. If you play with this distribution, be ready to throw everything away and start over when I release a new distribution.

You should pass the web interface used to manage the game through a proxy of some kind that can wrap it in TLS/SSL for security. The http service in the game is good enough to work with a browser running on the same system, but I haven’t tried to make it handle all the malformed requests that can come in the wild. I depend on a proxy for that.

Next Steps

Besides getting more game systems up and running (such as quest generation), I need to flesh out the web interface to allow editing of details, placement of landmarks, paths, and scenes in terrains, verb handling (including multi-word verbs like “look at,” “turn on,” and “turn off”), and create verbs and actions for moving between scenes or scene details.

Apr 192013
 

One of the reasons I decided to start over a few months ago and develop a new mudlib on DGD was because I wanted to have quests that were built on the fly based on the situation of the player and the NPCs with which they were interacting. Instead of a fixed script that you had to follow, I want the game to be a bit of improv.

I’m sure this could be done using a mix of object clones and save files with FluffOS, but it seemed like it would be a lot easier if I didn’t have to worry about all of that with a persistent driver such as DGD. In the process, I’ve reworked a lot of how an LPC mudlib works. Based on what I’ve seen around in forums and in the free/open source/not-behind-an-NDA mudlibs, I’m producing a mudlib that isn’t just a rehash of old mudlibs. Whether or not it will be useful to anyone else is still up in the air.

Incorporating improv into the game engine means that when you meet an NPC that has a quest, it should somehow fit in with how you are playing the game. The game should be thinking, “Yes, and…” when constructing a quest plot. If the game can’t find a way to advance an NPC’s goals in a way that works with how you play the game, then it shouldn’t offer you the quest.

Continue Reading Improvising Plots

Mar 312013
 
Adverb

Adverb (Photo credit: Wikipedia)

I’ve spent more of the last week working on the web interface than working on the adverb system, but that doesn’t mean I haven’t been thinking about adverbs or doing any planning. Today, I want to walk through how I see adverbs working in the Second Contract mudlib. Adverbs here will be markedly different from adverbs in the Skotos system. You can use them with any verb, and they will affect the action in some way much of the time.

Adverbs serve a few different functions in a game: constraint modification (make something quickly instead of carefully), voice (shout mightily instead of loudly), or just atmosphere and emotion (bounce joyously or run crazily). Let’s look at each of these in turn.

Continue Reading Adverb Action

Mar 242013
 

This last week was our spring break, so I was able to spend a bit more time with the game. As a result, I can present a few screenshots to show where I am.

Screen shot of System dashboard

Screenshot of the System dashboard.

The primary means of managing the game and content is through a web interface. The first binary port is still available for emergencies, but nothing beyond the capabilities provided by the Kernel lib is available there. The first screenshot, then, is of the system dashboard.

You’ll notice that the Running Since time is more recent than the Started At time. The former is when the current DGD process began. The latter is when the game began.

You can also change the name of the game here. Changes will persist across restarts of the DGD process, but not across restarts of the game. This is the nature of persistent games with DGD.

For now, I’m building the administrative web application with sections for each major part of the mudlib: System, IFLib, and WorldLib. If there are any configurable things for ToolLib and DevLib, I’ll make sections for them, but they don’t have any now.

Continue Reading Screenshots!

Mar 182013
 
Pattern of nature and people

Pattern of nature and people (Photo credit: heritagefutures)

I’m making progress, though not quite far enough along to have something you can log into yet. I have the basics of things, a parser with a grammar and a binder (based in part on the Discworld code), an event handler installer, and a message renderer. I also have a user object that lets you use your email address and password to log in and then create or select a character.

I want to walk through what happens when you type in a command. Let’s use “grab the china from the table then quickly run through the door.” The parser will divide this into two commands and label the parts:

(
  (command
    (verb "grab")
    (direct-object "the china")
    (indirect-object "from" "the table")
  )
  (command
    (adverb "quickly")
    (verb "run")
    (indirect-object "through" "the door")
  )
)

I’m not settled yet on movement verbs taking an indirect object as indicating the point towards which the character moves, but that’s essentially how the commands would parse out with the current grammar if I defined the right verbs, adverbs, and prepositions. The grammar doesn’t support multi-word verbs yet, so no “look at” or “turn on” for now.

Continue Reading Verbs and Actions

Mar 122013
 

The last couple of weeks, I talked about proximity relationships, environment, and inventory. This week, I’ll explore what this means when we move objects around. Along the way, we’ll see where I’m considering tweaking the proximity system as I’ve coded it so far.

Placement

First, let’s review what we need in terms of placement in the game. We want to specify our relationship with other objects in the scene, landmarks, and where we are relative to other areas of the virtual world. We want to move towards and away from things within a scene. We want to move in ways that make narrative sense, not necessarily spatial sense (i.e., lean against the wall, not stand at position <x,y> with our shoulders touching a vertical surface at <u,v>).

This is easy to do if we have full objects for everything in a scene: each item we can manipulate, each detail we can look at, and each detail of each detail.

Continue Reading Proximity and Movement

Mar 022013
 

Last week, I talked a bit about the graph tracking object relationships with each other. This week, I want to continue by looking at what that graph means for the larger world.

One of the errors in designing text-based games is trying to shoe horn them into the expectations associated with a graphical game. Just as a movie has different affordances than a novel, a text game has different expectations and narrative conventions than a graphical game.

When writing a novel, you don’t specify the exact placement of everything in the scene. Instead, you take what you imagine as the scene and then put on paper only the things that have any significant impact on the story. If the choice of color doesn’t change the story, then leave it out. Same goes for the wallpaper pattern or any other detail. If a lamp is never thrown across the room in anger, then don’t tell the reader about it.

Continue Reading Scenes and Settings, Part 2