Backburner Month 06: Parley and Beholder

This is an entry from a list of projects I hope to some day finish. Return to the backburnered projects index.

What is it? The digital tabletop I want for the tabletop games I play, scripted the way I want to script it. My original notes on the topic called this system Beholder, but more recently I've taken to calling it Parley.

The information display part is maybe a little bit less interesting, but fundamentally this is because of how I play tabletop games: what I want is first and foremost something wiki-like, and secondarily a mapping system. Many of the games I play don't care about fine-grained maps, but instead are concerned with characters and factions and whatnot: I want to bring that information front-and-center. I want a digital tabletop to function as a shared dossier, including the ability for players to add their own pieces of information (e.g. descriptions of NPCs or items) that are stored tagged with the player/character who wrote them. Maps should still be present, but they're not always the star of the show.

The scripting component is the more interesting part: I want the ability to express game rules using a total, decidable language with reusable components. I know that “this should use a decidable language” is a thing I've talked about before in these project posts—both Virgil and Van de Graaff include such a language, and won't be the last ones—but I really am interested in systems that do decidable computation in a domain-specific way. The intention here is that I can support a new tabletop game or system by chaining together an appropriately-designed set of computational primitives.

Say I want to describe the rules of the game Apocalypse World. In particular, let's look at the Apocalypse World rule for Do Something Under Fire, which is described like this:

When you do something under fire, or dig in to endure fire, roll+cool. On a 10+, you do it. On a 7–9, you flinch, hesitate, or stall: the MC can offer you a worse outcome, a hard bargain, or an ugly choice. On a miss, be prepared for the worst.

I might begin (using handwavey, ML-inspired syntax here—I hadn't made any syntax choices before) by writing a macro which can be used to describe the way all dice rolls in Apocalypse World have three fixed outcomes:

let aw_roll(modifier:, success:, partial:, failure:) =
  match 2d6 + modifier {
    | n when n >= 10 => success
    | n when n <= 6  => failure
    | otherwise      => partial
  }

I can then express a specific move by instantiating this macro, using constructs to express that the modifier will be filled in with the character's relevant stat and the various outcomes will result in specific pieces of informative text.

let do_something_under_fire = aw_roll
  ( modifier: @char.cool,
    success:
      say("You do it."),
    partial:
      say("You flinch, hesitate, or stall: the MC can offer
           you a worse outcome, hard bargain, or ugly choice."),
    failure:
      say("Be prepared for the worst."),
  )

Finally, this and other macros will be assembled into a single set of rules which can be exposed to the player in a clean way, which gives the player a palette of the abilities at their disposal. Importantly, despite looking like an imperative program, the above code would actually be purely declarative: the result of do_something_under_fire is an abstract tree of possibilities, so the Parley system would be able to understand not just how to “run” it with a particular random roll, but also how to, for example, express that rule in prose, since it understands expressions like 2d6 + modifier symbolically and abstractly.

Why write it? Well, for one, basically every digital tabletop service I've used (like Roll20) assumes that you're playing Dungeons and Dragons or at least a game significantly like it. That means they build first and foremost around maps, and usually grid-based maps of the kind usable for D&D combat.

While I'm not against D&D, it's also not my favorite kind of tabletop game. As I mentioned before, I mostly prefer games that aren't focused on tactical grid-based combat. My usual games of Blades in the Dark or Apocalypse World are far more about the history and interactions of NPCs and factions, and maps tend to be sketchy and collaborative instead of the rigorous structuring principle of the whole game. I've mostly been using Roll20 for my games, but a bunch of the UI around shared notes feels like an afterthought, and I think designing for shared notes up-front (maybe borrowing some ideas from Notion, a tool which I love) would yield some great benefits.

I also am fascinated by the language design necessary to describe tabletop games, and I think that's the most appealing part of this project to me. You can certainly express the rules for a new tabletop game using Roll20's system… but that system is just, “Program it with JavaScript.” I don't think that's a bad design, to be clear! But I think there's a lot you can do if you sat down and designed a language specifically for the task of describing and implementing tabletop game rules, especially from the point of view of being able to statically analyze the game structure.

For example, I can imagine using the same underlying “programming language” to build out not just a web interface for Parley but also a kind of rigorous rule-book: the same declarative description could just as easily be analyzed and serialized as it could be run. That sort of interface could even allow for a game designer to start doing an abstract analysis of the patterns and possibilities inherent in the rules. There's also some really fascinating ideas to be borrowed from Chris Martens' linear-logic-based Ceptre language which I haven't even scratched the surface of.

Why the name? The original name, Beholder, was because it was fundamentally an information-display application, but also referenced the famous D&D monster of the same name. The newer name, Parley, is because it's also a chat-like application featuring a feed of dice rolls and results, and because Parley is a Dungeon World move used to talk to people.

#backburner