Librarian of Alexandria

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

What is it? A language for expressing recipes in graph form.

The usual presentation of a recipe is as a snippet of prose, doing things step-by-step. However, actual recipes aren't strictly linear: there are often parallel preparations that need to be done, like making a roux while the sauce simmers elsewhere. Prose is certainly capable of capturing this—prose is, after all, a default way of representing information for a good reason—but I'm also fond of notation and alternative ways of representing information. What if we could make the various branches of a recipe more explicit?

Apicius is a way of writing recipes that encodes explicit parallel paths. It looks more like a programming language:

eggplant rougail {
  [2] eggplants
    -> scoop flesh, discard skin
    -> mash
    -> $combine
    -> mix & [4bsp] oil
    -> DONE;
  [2] white onions or shallots -> mince -> $combine;
  [2] hot peppers -> mince -> $combine;
}

How do we read this? Well, the bit before the curly braces is the name of the recipe: eggplant rougail. Inside the curly braces, we have a set of paths, each of which ends with a semicolon. The beginning of every path starts with one or more raw ingredients, with the amount set apart with square brackets. Once you're in a path, there are two things you can write: steps, which look like plain text, or join points, which start with a dollar sign.

What is a join point? It's a place where you combine multiple previously-separate preparations. In the above example, you have three different basic ingredients: eggplants, peppers, and onions or shallots. Each is prepared separately, and then later on mixed together: the join point indicates where the ingredients are combined.

There's also a fourth ingredient at one point above: at any given step or join point, you can add extra ingredients with &. The intention is that these are staples which require no initial preparation or processing: it's where you'd specify salt or pepper or oil in most recipes, ingredients which sometimes might not even make it onto the initial ingredients list because they're so simple and obvious.

Finally, there's a special step called DONE, which is always the last step.

In the above example, there's a relatively simple pattern happening: three ingredients are prepared and then joined. But with different uses of join points, you can express recipes that have multiple separate preparations that come together in a specific way, and that parallelism is now apparent in the writing. Here is a different recipe:

egg curry {
  [8] eggs -> boil 10m -> $a;
  [2] onions -> mince -> brown &oil -> stir -> $b;
  [2] garlic cloves + [1] piece ginger + [1] hot pepper + salt + pepper -> grind -> $b;
  [4] ripe tomatoes -> chop -> $c;
  $b -> stir &thyme -> $c;
  $c -> simmer 5m &saffron -> $a;
  $a -> stir 10m -> simmer 5m &water -> halve -> DONE;
}

This is rather more complicated! In particular, we now have three different join points, and a larger number of basic ingredients (combined with +). In parallel, we can boil the eggs, mince and brown the onions, grind seasonings together, and chop the tomatoes. The first two disparate sequences to join are actually the browned onions and the garlic/ginger/pepper/&c mixture: those are combined with some thyme, and afterwards the tomatoes are mixed in; after simmering with saffron, the boiled eggs are added, then all paths are joined.

I don't think this is terribly easy to follow in this format, especially when using non-descriptive join point names like $a. However, an advantage of this format is that it's machine-readable: this format can be ingested and turned into a graphic, like this:

The above recipe for egg curry, represented as a graph with certain steps leading to others

or a table, like this:

The above recipe for egg curry, represented as a table with cumulative preparations combined

or possibly even into a prose description, using natural language generation techniques to turn this into a more typical recipe. Marking the amounts in square brackets might also allow for automatic resizing of the recipe (although how to do this correctly for baking recipes—where linearly scaling the ingredients can result in an incorrect and non-working recipe—is a can of worms I haven't even considered opening yet.)

Why write it? Well, I love the presentation of recipes as graphs. I've actually got a whole web site of cocktail recipes in this form, which you can find at the domain cocktail.graphics, and I would love to get to the point that I could semi-automatically generate these diagrams from a snippet of Apicius:

A chart-based recipe for the Last Word cocktail

But I think—as I mentioned when I described the language for Parley—that there are many cool things you can do if you have generic data that can be re-interpreted and revisualized. As mentioned above, there are lots of ways you can take this format and use it to represent various structures. What I'd like to do, once I have the tooling to do so, is take a bunch of my favorite recipes (like sundubu-jjigae or ševid polow or jalapeño cream sauce) and convert them into Apicius, and then have some kind of front-end which can be used to view the same recipes using many different rendered formats.

Why the name? One of the few Latin-language cookbooks we have remaining copies of is usually called Apicius, although it's also referred to as De re coquinaria, which boringly translates to “On the topic of cooking.” It's not clear who Apicius was or if the Apicius referenced by the book was a single person who really existed: it may have been written by an otherwise-unattested person named Caelius Apicius, or it may have been named in honor of the 1st-century gourmet Marcus Gavius Apicius, or perhaps it was even authored by a group of people. (It doesn't help that the remaining copies we have are from much later and were probably copied down in the 5th century.)

#backburner #software #tool

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 #software #web

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

What is it? A video game: a scifi sandbox farming-sim game after my own tastes, one I've had kicking around in the back of my head for a long time.

The premise of the game is that you're a farmer who has moved to a new, uninhabited-by-sentient-life planet: there's a little settlement, and you get only sporadic contact with the core worlds for supply drops. Your primary job is to start building and maintaining your farm, and for that matter, understanding how and what to farm: the native plants and wild creatures are alien and unfamiliar—and procedurally generated for that save file—and you'll have to use a combination of laboratory analysis and practical experimentation to figure out which plants are edible, which plants are usable for medicine, which plants are usable for building materials, and so forth.

This will involve a combination of infrastructure-building and exploration. Infrastructure-building means, more or less, building out and maintaining a farm, but also expanding the little settlement to support more people, building homes and ensuring there's enough food and supplies for the sporadic new arrivals. Exploration would let you find new plants, new creatures, maybe even new places for settlements. Ideally, exploration will be slow and intentional and a bit difficult but not punishingly so: I plan to eschew any kind of combat, so the challenges would be around exploration and juggling resources like food and shelter, along with dangers like traversing rapids and bouldering up mountains. The world would be finite and exploration won't be a solution to all the problems a player would face: instead, you'll eventually develop the ability to do selective breeding of plants to come up with new, more-useful variants: cross-breeding varieties to select for larger yield or more resistance to climate variation and so forth.

Visually—at least subject to my own ability to implement it—my plan was to create a world inspired loosely by the paintings of Eyvind Earle, with lots of stark geometric shapes and sharp blocks of striking color. The look of the buildings would borrow heavily from the great concept artist Syd Mead and also from the building ideas of the futurist Buckminster Fuller. Of course, this graphical style was more than a bit aspirational, and I confess in my prototypes I never actually got to the point that it looked like it did in my head: I've since considered whether this game would be better served with a Roguelike-inspired grid of simple pixel art tiles, like Caves of Qud or the Oryx tiles for Brogue.

Why write it? My original ideas here actually far predated the survival sandbox games of the present day. When I first entertained ideas about it—in the mid-2000's, when I first wrote the name Albulaan in a notebook—my major inspiration was Harvest Moon: my original desire was to have a Harvest Moon-style farming sim game with procedural and exploration elements, a game where you couldn't simply look up in a wiki (or, at the time, a strategy guide) which crops were the best or where to go to find resources, because those crops and resources were unique to your own save file.

At this point, there are many more games in the genre that actually get closer to the game I want, although not quite bringing the same focus I'd want. There are plenty of more mechanical, infrastructure-based games like Factorio, plenty of more combat-focused survival sandbox games like Minecraft, plenty of expansive procedural worlds like No Man's Sky. I should be clear that the Albulaan of my dreams is not actually like any of these: I'm not interested in Factorio-style factory optimization, Minecraft-style resource extraction, or No Man's Sky-style tech trees. The gameplay of Albulaan should feel a little bit more like a Stardew Valley: daily farm maintenance coupled with some side activities and cheerful chats with settlement NPCs, with a bigger world and a set of traveling mechanics taking the place of Stardew's combat-focused mine levels.

Admittedly, one personal pet peeve I have about many of the games in this same space is that they try too hard to include every possible mechanic and end up with an awkward and subpar version of many of them—like Stardew Valley's clunky and static combat system, or Animal Crossing: New Horizons' tedious attempts at crafting mechanics—and that's one reason why I explicitly described Albulaan above as lacking things like combat mechanics: I genuinely believe there should be more games that don't try to tack on every possible way of interacting with the world, which is why my goal for Albulaan is to do farming and exploring and world-generating well, and that's about it.

Anyway, I do think several of my ideas for Albulaan are still distinctive—like the selective breeding of procedural plants—even if they're less unique than they would have been in 2005. If nothing else, it's still a game that, if someone else created it independently, I would want to play.

That said, I'm also not 100% sure which aspects of this idea will remain intact when I return to it. For one, I've gotten more and more uncomfortable with the colonialist and extractive aspects of some of these games, and I'd love to figure out a way to design Albulaan in a way that can mitigate some of these concerns. The fact that the world is necessarily finite—and consequently certain resources are also finite, and the player must think about conservation and renewable resources—might help here, but it's not a silver bullet that handles all (or even most) of the work of removing the colonialist underpinnings from a game like this.

Why the name? The word al-bulaʽān (ألبولعان), which literally means “the two swallowers”, is the Arabic name for two stars in the constellation Aquarius: specifically Nu Aquarii and Mu Aquarii. My first notes about Albulaan date back to my high school years, when I did some Flash experiments with the intention of creating procedural animals for it: at the time, I chose the name arbitrarily from a list of star names, and I've used it as my working title since.

#backburner #videogame #procedural

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

What is it? A very simple library and engine for writing storylet-based narratives.

“Storylets” are an approach to writing procedural, interactive narratives. There are a lot of different ways you can approach storylets, but the core idea is that you've got some kind of world state, and based on that world state, you choose a piece of “content”—in Rakonteto's case, a fragment of prose—that you can present to the player. The player can then make choices which change the world state, and that in turn allows the game to present another piece of content to the user.

Probably the simplest way to contrast this to other interactive narrative systems is by comparing it to a Choose-Your-Own-Adventure-like branching narrative system. Imagine that you want to write a story in which the player must go to two different places (A and B) in either order, and only after that can they return to a third, final place (Z). In a pure CYOA-style game, you effectively must have two branches, one corresponding to the sequence A → B → Z, the other B → A → Z, which implies that you must duplicate the content for A and B even if there are otherwise no changes to the visit to A and the visit to B. (And that's just for two places: if we have three places to visit in any order, we'd have to duplicate the content for each of the six possible visit orders!)

In contrast, a storylet-based system would let you represent A and B separately, and each one would end with modifying the world state with information indicating that the location had been visited. Finally, Z would include as precondition that A and B had both been visited. Many storylet systems allow for selecting the most salient next fragment, as well: that means that A and B can also include special content which will be surfaced in the specific situation that they're being visited first or second, but without having to duplicate all the content associated with A and B.

My implementation—Rakonteto—is designed as a textual language for producing interactive prose, loosely inspired by Ink. A given fragment of a story would look sort of like this:

=== [var: expr, var: expr, ...] ===

A fragment of text, to be shown to the player.

+ A choice. -> [var: new_expr, ...]
+ A different choice. -> [...]

The stuff in square brackets at the top is a set of “variables”—properties of the world, so to speak—with their current values. When the underlying story engine needs to choose a new story fragment to show to the user, it looks at each fragment to find whether the declared variables match the current state of the world, and then (using a handful of heuristics) choose a matching fragment to show to the player.

The bits at the bottom introduced with + are choices the use can make, and the stuff in brackets afterwards describes how to change the world-state so that a different fragment can be chosen next. A more “realistic” example might look like this:

=== [has_sword: false, in_location: forge] ===

As you walk into the forge, smoke stings your eyes. A
towering, muscular man with a singed beard is staring
pensively at the embers: as you approach, he is roused
from his thoughts and nods. Without a word, he turns,
walks to the back of the forge, and returns with a
beautiful and freshly polished sword, its surface only
marred by the man's sooty fingerprints.

+ Take the sword. -> [refused_sword: false, has_sword: true]
+ Decline the sword. -> [refused_sword: true]

The world state can include far more variables than are listed, and only the variables mentioned in the choices get updated: the others persist. One thing I hadn't figured out was the correct heuristics for handling selection among multiple different fragments that match to the same degree of “salience”. Another was how to provide tools to make certain common patterns more convenient: for example, I planned to have syntax in which you could include or swap out individual phrases or sentences based on parts of the world state, so that certain bits of customization didn't need an entirely new fragment. I also planned to have some choices “gated” by aspects of the world state, and also syntactic sugar for small branching scenes (so that you don't need to introduce new variables for situations like singular yes/no decisions that only matter within a single fragment.)

The original version was constrained entirely to finite sets of “world state” variables which could range over atomic strings, but I planned to also experiment with constrained integer arithmetic and eventually maybe even composite values like lists or sets.

Why write it? Mostly for experimentation! There were a few specific features I wanted to experiment with.

One such feature was that I wanted to have an engine for storylets which could be quickly and easily turned into something which can be played, sort of like the interfaces provided by Twine or Ink. My goal was that you could write a game and then “compile” it to a standalone HTML document that includes all the JavaScript necessary to run an interactive version of the game. For early playtesting, I also created a tiny command-line driver, which allowed you to choose from a list in order to move forward.

Another feature was an embeddable API. I wanted to be able to take this and link it in to other programs which could interact with it: for example, exposing it as a library so I could integrate it into a Unity or Unreal game (although I'd likely have started by writing bindings in something much simpler, like Löve.) The previous compile-to-HTML feature would let you get stories in front of people quickly, but I wanted to design the system such that you could use it as the “story backend” to a different kind of game, as well.

Finally, I wanted to experiment with debugging and modeling tools. With the state space constrained sufficiently, you could start throwing various solver techniques at a narrative. One reason you might want to do this is reachability: “I have these variables which have different states, and can change in this way. Can I actually ever get to this specific state?” Another is as a kind of automated play-testing. When your story is complicated enough, it might be possible for a player to “sequence break”: that is, to experience the story in a way that you didn't anticipate. I imagined addressing this with a solver as well: you could query your story model and ask questions like, “Is it possible that the player could experience fragment X before fragment Y?” and the tool could either confirm that it's impossible, or show that it is and give you an example of such a play-through.

Why the name? The word rakonteto is Esperanto: it's a diminutive form of rakonto “story”, so it means something like “little tale”.

#backburner #software #language #procedural

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

What is it? A grid-maps-and-tactics tabletop game, designed for one-offs and short campaigns and optimized for getting players sat down and into the game as quickly as possible.

The core of the rules is derived from Hero Kids, a simple but surprisingly robust tabletop game designed for children. One feature borrowed from Hero Kids is that all character-specific abilities (which by and large are represented as equipment: weapons, staffs, and so forth) are little cards which describe the ability in its entirety. That means that character creation amounts to doing rudimentary skill point allocation and then choosing some cards. If you wanted to get going immediately, you could even pick cards randomly and then allocate your points based on whatever you picked.

There are also features cribbed from 4th edition Dungeons & Dragons, specifically many of the monsters. D&D 4E distinguishes itself from other editions by building the game with a laser focus on tactical combat, and one great result of this is that monsters in 4E have meaningfully different ways they behave in fights. Encounters in 4E tend to be dynamic with lots of careful movement and positioning in order to gain advantages, and going up against a band of goblins is mechanically and tactically distinct from going up against a band of orcs or a pack of wolves or whatnot. I used those as a jumping-off point to try to build tactically distinct monsters and villains for this game, as well.

The end result is a game that can be picked up by players quickly, but can still support the kind of dungeon hijinks that games like D&D are known for.

Why write it? This game actually goes against my usual predilections in tabletop role-playing games. My personal tastes tend away from dungeon-crawling and tactical combat: I usually prefer games where combat is much more zoomed out (e.g. rolling a die to resolve an whole bout of combat or even an entire encounter, rather than tracking a whole fight blow-by-blow) and where the focus is broader than simply traversing dungeons.

But even though it's not always my favorite kind of RPG, I still sometimes want to sit down with some friends, trawl through a maze, sneak past some traps, and fight some monsters. When I first found Hero Kids, I realized that I found a game which would facilitate that but without the depth of rules that a D&D game offers: no flipping back and forth between four parts of a $45 book to build a character, no obscure rule interactions across three optional books, no hour-long character creation session. Not that I never want those things, but I also don't always want those things.

In a way, my goal was to build a game that sat between a board game and a tabletop RPG. The rules don't necessarily encourage you to role-play all that much or provide much support for doing anything that's not trawling through a dungeon (although you can still roll persuasion checks and there's some support for stuff to do in town.) Instead, the game puts a sword in your hand and tosses you into a dungeon filled with monsters and treasure. With a small dungeon prepared, you could run a session, complete with character creation, entirely during an hour-long lunch break. I think that's a worthy design goal.

Also, I love things that use little cards and slips of paper, and have kinda wanted to write a game around them for ages.

Why the name? I actually want to change this name—in part because there's already a spectacular RPG product out there called Delve—but I originally wanted to call it Delve partly for the typical fantasy-dungeon-crawling meaning, and partly because it meant I could quote Rosencrantz & Guildenstern Are Dead on the back cover.

I was waiting for you to delve. “When is he going to start delving?” I asked myself.

#backburner #tabletop

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

What is it? A typed, non-Turing-complete configuration language that is otherwise identical to JSON. The goal is that all valid JSON files will also be valid Virgil files.

{
  "name": "Ash",
  "age": 44,
  "pets": [
    {"name": "Spot", "species": "Dog"},
    {"name": "Henry David Thoreau", "species": "Dog"}
  ]
}

However, in addition to the usual JSON extensions like comments and trailing commas, it would also allow “splices”, which would allow for snippets of code to be included that would evaluate to other JSON expressions.

{
  "name": "Ash",
  "age": `(22 * 2),
  "pets": `[ {"name": n, "species": "Dog"}
           | n <- ["Spot", "Henry David Thoreau"]
           ],
}

It would also include a type system built largely around structural types, so that you can enforce that your functions are used correctly, but with the types inferred from use instead of explicitly written:

`let double(obj) {obj["n"] * 2}
[ `double({"n": 5}),      # okay
  `double({"n": false}),  # error, because `obj["n"]` is a boolean
  `double({"x": 0}),      # error, because no key `"n"` exists
]

The definable functions would also be limited to strongly normalizing (i.e. non-Turing-complete) ones, so recursion would be entirely disallowed:

`let fact(n) {
  if n == 0 { 1 }
  else { fact(n-1) }  # error: recursion
}
`[ fact(i) | i <- range(10) ]

Importantly, the goal of this project would be not simply to implement the Virgil language, but to implement the libraries in a way that has an API indistinguishable from existing JSON libraries. The goal would be that a project could decide to use Virgil by simply swapping an import: no other change would be necessary.

Why write it? It's worth noting that there are now two other major contenders in this space: one of them is Dhall, the other is Jsonnet. My original notes on Virgil actually predated Dhall itself (although they were indeed inspired by this tweet by Gabriella Gonzales, who would go on to create Dhall) but the end goal was a language that would in some ways sit exactly between the space occupied by Dhall and Jsonnet. Unlike Dhall and like Jsonnet, it would restrict itself to only expressing data that could be expressed in JSON (and therefore the final output could not include e.g. functions) and could exist as a near-drop-in replacement to any program that already used JSON. Unlike Jsonnet and like Dhall, it would include a static type system and would be Turing-complete.

In theory, had I written it when I first considered the idea, it might have tackled some of the use-cases that Dhall and Jsonnet have now cornered. At this point, I don't think it necessarily brings enough to the table to unseat either of them in their intended use-cases, but I still think it'd be a fun project to write.

Why the name? Like the historical Virgil, it takes the story of J(a)SON and adds a bunch of extra stuff to it.

#backburner #software #tool

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

What is it? Van de Graaff is a static site generator built around declarative pipelines. The original design used a vaguely Lisp-like format which could describe how to take various source files and produce downstream files from them, with the goal of being unreasonably flexible in terms of the format and interpretation of input data. A small fragment of a site configuration looked like this:

# `every` produces a single output file for each input file
(every "posts/%.md" {
  # the output filename is a function of the input one
  produce: "posts/%.html"
  # these are the arguments passed to the standard page
  # template, defined elsewhere in the config file
  with: {
    # the template here is invoked with `content` set to
    # the result of rendering the file contents with markdown
    content: (render markdown _)
    # this pulls out of the front matter at the beginning of
    # the Markdown file
    title: (front-matter "title" _)
  }
})

The above example is pretty simple: take every Markdown file in one directory, produce a corresponding HTML page to each in another directory by rendering the Markdown and pulling metadata out of the front matter. But the goal of Van de Graaff is also that the underlying set of “functions” should allow for a massive amount of customizability. For example, maybe we don't want to use front-matter in a Markdown file: maybe each post should be contained in its own directory, with metadata living in a separate file from the source itself, and indeed with the source file's location and markup format defined in the metadata file. The goal of Van de Graaff was to be flexible enough to accomodate nearly any kind of data organization you wanted while remaining fundamentally declarative:

(every {meta: "posts/%/metadata.json" source: (json-elem "content" meta)} {
  produce: "posts/%.html"
  with: {
    content: (render (if (== (json-elem "format" meta) "rst")
                         rst
                         markdown)
                     source)
    title: (json-elem "title" meta)
  }
})

Notice some of what's going on here: our “input” file has become a pair of named files, one of which depends on the content of another. There's now conditional logic to decide how to actually render the input file, and which renderer to use depends on the other file. This is certainly a kind of data organization that'd be harder to express in most existing static site generators.

The original goal was to build Van de Graaff as a tool with a decidable (i.e. non-Turing-complete) language, hence the Lisp-inspired-but-clearly-data-driven formatting system. Whenever I return to this project, my current plan is to reconsider this decision and instead write the pipelines in something like Lua or Wren, but still keep the core idea intact: the script itself would not actually load and process any files, but rather define a set of declarative pipelines, and those pipelines would be used to process the files, allowing reuse of intermediate outputs as well as cached computation of inputs known to be identical.

Why write it? There are two custom static site generators that I've written which I still use: one of them generates my sadly-languishing random-topic blog What Happens When Computer, and the other generates my prose and quote-collection site. They're rather different in almost every way: the former is written in Scheme (complete with an S-expression based templating mechanism) and ingests a custom-designed markup format, while the latter is written in an unholy combination of Mustache, Python, Bash, and Make, and ingests a combination of Markdown and YAML.

Despite being radically different from one another, they do have features in common: they both care about taking collections of things (posts, snippets of text, specific pages, &s) which they read, process, and munge into several different output files. A blog like What Happens When Computer would be generally well-supported by an off-the-shelf solution like Hugo, but I'd have to do a little bit more tweaking for my prose-and-quotes site. On the other hand, I could easily port the prose-and-quotes site to use a CMS-like solution like Python's Lektor, but at the cost of abandoning my own data organization: I'd have to convert my existing data to use such a new format, which would break other tools I've already written that use this data in other ways.

Van de Graaff was my attempt to write a flexible-but-still-constrained system which could accommodate them both as well as anything else I'd like to write, replacing not just static site generators but any system where I write shell scripts or Makefiles to ran Pandoc for me. It's rather overengineered, and it's a terrible effort-to-reward ratio, but I still like many of the underlying ideas.

Why the name? It's a static generator, so I immediately thought of a Van de Graaff generator. (According to old notes and repos, I also at one point called it TMS but literally cannot remember what that was supposed to stand for.)

#backburner #software #tool

I am an inveterate project-starter.

I just can't stop. I'm awful at finishing projects (which I've mentioned before) but my brain finds the novelty of new ideas too tempting to stay away from. And it's rare for me to fully abandon a project: I'll stop thinking about it for years, and then suddenly decide to open it up and work on it a bit more, pushing it slowly but inexorably towards a completed state like Zeno's Issue Tracker.

Such projects are my backburnered projects. I do still think about them, and I do want to return to them—some day, although not any specific day—but they're not at the top of my priorities at any given point. And I was recently considering how to give them a bit more love, how to bring them back into mind, how to push them along by at least tracking them or giving them a rough plan.

So here's what I'm gonna do this month: every day, I will post a short blog post about a backburnered project. I've got far more than can fit in a month, so I've formulated some specific requirements for what sorts of projects I'm going to write about:

  • They must be things I haven't tried picking up and working on for a few months. If it's something that I was working on earlier in 2021, even if I haven't touched it in the last few weeks, then it's not really backburnered in my head. For example, I've been working off-and-on on a small and very silly project I'm calling Buckminsterfullerene, which is a source code display tool inspired by Carbon. I haven't worked on this since July and I'm not planning on picking it up in the next few days, but July wasn't that long ago, so I'm not counting it as backburnered.
  • They must be things that I'm not opposed to picking up again. There are some projects that I have decided I am never going to resuscitate: those projects aren't backburnered, those are simply abandoned. For example, at one point I was working on a drawing program and associated vector format: the former was driven by the desire to recapture the novel way I felt about drawing in the Flash authoring environment (which remains one of my favorite programming environments) and the latter by the still-relevant concern that there are no good standard vector formats. I do not believe I will ever revisit this project: not because it's a bad idea, but because it's a massive undertaking that doesn't actually match my strengths or interests right now.
  • They must be things that are, in some little way, novel: a little more than, “a tool which does this in a slightly different way,” or, “a library for X in language Y.” For example, at one point I was working on an alternative HTTP client library for Haskell which I planned to call shelob (although I also considered the name vriska, on the grounds that both are related to webs.) I was trying to solve a genuine problem using shelob: the existing Haskell HTTP client libraries tended to make assumptions about the underlying sockets, and having a backend-agnostic library which would work over any stream-like abstraction would have made some tasks significantly easier in something like the now-defunct HaLVM project. But frankly, “an HTTP library with a slightly different interface” isn't that novel. I want to focus on projects that have a little more to talk about.
  • They must be something that someone else might theoretically be interested in using, playing, or reading. This means I'm sticking to talking about plans for software and media objects. I've definitely got backburnered projects which are, like, art or functional objects I want to make for myself—for example, streamlined shogi sets or conlang projects—but I'm not sure that those are worth giving a few paragraphs to in a blog post. Consequently, I've mostly stuck to software and game-ish projects, with a few little fiction projects scattered in.
  • They must be something I am comfortable talking about publicly. (I am not giving an example of a project I'm not comfortable talking about because… well, obviously.)

Each backburnered project will be given a few paragraphs: the what, the why, how far I've gotten, and of course why I chose the insufferable and impossible-to-remember name I gave it. (If I ever go back and finish any of these projects, I'll also edit the relevant posts to point to them, but I wouldn't hold my breath if I were you!)

Backburnered projects index

  1. Van De Graaff: a static site generator (software)
  2. Virgil: a computable configuration language (software)
  3. Delve: a lightweight dungeon-crawling game (tabletop game)
  4. Rakonteto: a storylet writing format (software)
  5. Albulaan: a procedural scifi farming game (video game)
  6. Parley and Beholder: a digital tabletop for less-grid-map-focused games (software)
  7. Apicius: a graph recipe format (software)
  8. The Last Alliance of Men and Elves: an asynchronous letter-writing strategy game (tabletop game)
  9. Endsay: a debuggable PostScript implementation (software)
  10. Tales: a casual procedural quest game (video game)
  11. Palladio: a grid-based shape-grammar authoring tool (software)
  12. Morphosyntactic Trek: an episodic linguistic scifi story (fiction)
  13. Petri: an experimental dynamically typed programming language (software)
  14. The Emissaries of Guenashk: a thinky-talky scifi game (tabletop game)
  15. Hypsibius: a microtonal music tracker (software)
  16. Alien Truck Simulator: an alien truck simulator (video game)
  17. Lektor: a standard for feed reading software (software)
  18. Yan Tan Tethera, or Those Who Return: a map-drawing game (tabletop game)
  19. Aloysius: a flexible reverse HTTP proxy (software)
  20. Shengen: a procedural hard-scrabble spy game (video game)
  21. Cube Cotillion: an experimental SSH-based service framework (software)
  22. Guns & Gasoline: a fast-cars-and-deadly-fights one-shot game (tabletop game)
  23. PicoML: a tiny embeddable functional language (software)
  24. The Stray Dog Trilogy: a gritty noir mystery game (video game)
  25. Potrero and Treant and the rest: a suite of languages for procedural text generation (software)

Projects by type

Software

Tabletop games

Video games

Other

#backburner

My New Year's resolution for 2020 was this: “Finish a project a month,” for some arbitrary definition of “project” and some arbitrary definition of “finish”.

…I did not do this.

In my defense—and I do think this is a robust defense—the world went completely and utterly to shit in 2020, even moreso than it had been doing for the rest of the past half-decade, so I don't blame myself for this! But still, there are a ton of things I want to do and I really want to finish some of them!

What did I actually do during 2020?

There are a few things! Here's a big one: just a few weeks ago I finally completed the first draft of a novel, a fantasy novel with the working title The Necromancer's Daughter. I've written a fair bit of short fiction before, including a collection of surrealist flash fiction, a few pieces of poetry I'm reasonably-not-ashamed of, and some short stories that I haven't put online, but I had never completed a full novel, despite a few very bad attempts at writing science fiction novels during high school.

I'm proud of having finished it, but it's a first draft of a first novel: the writing is clunky, the plotting is awkward, &c &c. I'm stepping away from it for a little bit but I'm planning on taking time this year to edit it into a second draft and then see about publishing it. I have no idea what this process looks like, much less how it works in a time of COVID when I'm also working an unrelated full-time job, but I'm excited to find out!

Another thing I have arguably “finished” is Lament Configuration, a self-hosted Pinboard-like bookmarking service. Both my web design sensibilities and my web design tools live firmly in the past, so Lament Configuration is a bit of a throwback in terms of how it works and is implemented, but I'm proud of where it is and I've fully switched over to it for storing links on my own self-hosted instance. It's not necessarily completed, but it's usable for myself and a small group of friends, and that's not nothing!

I've also been honing a few other skills in anticipation of not-yet-finished projects. For one, I've been working on page layout, both for personal prose projects and for tabletop-related projects. Earlier I mentioned my surrealist short fiction: I'm going to be putting together a tiny chapbook of all of those, and I've already got the layout all done, which means I just need to take the time to find a printer for chapbooks. I'm also working on some small (chapbook-sized) tabletop projects. Both of them are letting me get more familiar with the tools for doing these layouts and experiment with what works and what doesn't. For example, here are two pages from different projects: a title page from my short fiction chapbook on the left, and a page from a tabletop project on the right:

Another skill I've been honing is 3D modeling. I've tried learning Blender before, but this year it's really started to stick in a way it hasn't before. My specific focus is wanting to learn 3D modeling for video games, so I've been sticking to styles which will work for the kinds of video games I could theoretically make on my own, without a massive team of artists and while also doing the design and programming myself (to say nothing of music and sound and writing and so forth.) For example, I've been working on flat-shaded low-poly modeling, which has been great for figuring out how to build the shapes I want without worrying about texturing:

A kitchen scene, modeled in 3D with flat colors and few polygons.

I've also been working on a style of blocky low-poly model that uses pixel art for textures, which is yet another style that's accessible to an individual trying to build entire scenes without a team:

A market stall with boxes of food and signs, modeled in 3D and textured with giant chunky pixels.

Neither my typographical work nor my 3D work have yet resulted in “finished” projects, but I'm not disappointed in that: I'm happy I've flexed those muscles further, and I'll have those skills around for when I need them!

What do I want to do in 2021?

I've already mentioned a big one: I'd like to publish my novel! I've gotten some early positive feedback on it from people close to me, but they are, after all, people close to me. I do think there's something there in this draft, and I hope to find out what it'll take to bring it from awkward draft to a published novel.

I'd also like to write some more this year. By this, I mean writing more fiction—finishing some unfinished short stories, maybe starting another novel—as well as some lightly technical non-fiction. In particular, I've found that when blogging on my programming blog I really like to discuss ideas for a technical-but-not-specialist audience, and I also like doing technical history (e.g. this post of mine on the history of algebraic data types) and I'd like to combine those goals into a piece of long-form writing. We'll see where that goes, but I've got ideas as well as a potential collaborator who might be able to keep me on track!

And on a technical note, I've got some programming I want to do as well, but honestly less of it than before. That isn't to say that I won't program: I expect I'll do plenty of it, and I've got a number of small projects (compilers and libraries and tools) that I will poke at, but many of those feel more like ongoing concerns or means to an end than “projects” I am pushing myself to finish. Still, a smattering of programming projects I'll likely work on include a graph grammar authoring tool I'm calling palladio, a barebones storylet engine I'm calling rakonteto, and a wiki I'm calling baba-yaga.

However, that's not the only programming I'm going to do, because in 2021 I'd like to finish at least one small video game. I have a bad habit of gradually dreaming up grander and grander ideas, so I need to really limit myself: even ideas I've come up with tend to get too big for me to finish, honestly. Still, if I get even a tiny game-jam-sized project done, I'll be happy. (And to be clear, “finish” here means something like, “Get playable and put it on itch.io,” rather than trying to find a big publisher or even necessarily find an audience. I'd be totally happy creating a tiny weird game that four people ever play and nobody ever gives me a cent for!)

And I've got two or three tabletop projects I want to finish, as well. I had a screenshot of one of them above: a fantasy bio-punk Blades in the Dark hack about an arboreal city where people use plant-magic to grow their surroundings. I've got a few other ones that are small-sized and can at least get to playtest stage, like a Megaman-inspired party game called Get Equipped and a Silmarillion-inspired asynchronous storytelling game called The Last Alliance of Men and Elves, and maybe a few more: we'll see!

A few thoughts on projects

I'm still disappointed I finished fewer projects than I wanted to last year, but the reason for my resolution—”finish a project a month”—was not about actually being done with any specific thing. I don't mind having several projects in flight, and I don't think I'll ever stop doing that to some degree. The inventory above was mostly projects I think I can finish this year: I've got several more on backburner with varying levels of intention to finish, and I'm well aware that I won't finish half of them. That's okay!

The thing I want to address is not that any particular project isn't done, but rather that I'm not used to finishing projects in general. I've got more than a small measure of anxiety about finishing projects because a finished project has a kind of finality to it. An unfinished project is a dream: maybe it's great, maybe it's awful, but I can imagine it being as great as I want. A finished project, by contrast, is no more than what it is, and maybe it's disappointing or awkward or clunky and it will never be better than that.

But also a finished project exists and can be shared with others. And getting to the point that I can finish projects, both by being comfortable with the finality of a finished project and by being capable of the planning and legwork to finish the boring parts, is the only way I'll be able to share the things I want to share.

So I'm not gonna put a specific schedule on project-finishing this year, and anyway, the pandemic is still on, so any specific plans are ripe for skewering by our distressing present moment. But still, I'm going to keep learning to finish projects, and hopefully next year I'll be able to point to things I've completed and shared.

I tend to pursue too many projects at once. It's been a problem my whole life. But I'm trying to focus and finish them one-at-a-time recently while still brainstorming about future ones, so here are a handful of projects that I'm currently working on:

A Tool: Lament Configuration

I've used Pinboard for several years to store various links: it's one of very few proprietary online services that I genuinely like using, in part because of how it bucks the trends that many web services follow: there's no feature sunsetting, no “redesigns” that break existing workflows, no ad-driven engagement metrics. That said, I still prefer hosting my own services with my own data if I can, and there are a number of features I've wanted out of a bookmarking service that Pinboard doesn't have, including some slightly fancier tagging systems (e.g. hierarchical tags that can express subset-like relationships) and an alternate way of displaying links with rich content (e.g. preview photos for recipes).

So, I'm working on Lament Configuration, a self-hosted Pinboard-like system. I've got a running test instance at remember.when.computer which I'll eventually stabilize and open up to close friends as well, but it's designed as human-scale software so I don't believe I'll ever design it to host more than a small handful of people. I've been working on it with the help of my friend Trevor, and we'll probably put a bow on a “release” some time soon, but I've got several more features that I want to add over time.

Other tools on my backburner: a wiki inspired by Andy Matuschak's notes tentatively called baba-yaga, a Roll20 clone with an emphasis on note-taking and wikis for less-map-focused games tentatively called beholder, a tool for designing and using grid-based shape grammars tentatively called palladio.

A Tabletop Game: Guns & Gasoline

Okay, the original idea for this game was perfunctory and silly, and I've spent far too much time thinking about it considering what it is, but the core idea is: a tabletop game about street racing, gunfights, and saving the day, built specifically around three stats: Fast, Furious, and Family.

Yeah, it's corny, but that's what those movies are all about.

It's gone through at least three major revisions: the original version was a more-intricate-than-necessary Powered-by-the-Apocalypse game. That draft had a few ideas I liked—in particular, it had three different combat movies, Fight Smart, Fight Hard, and Fight For What You Love, each built around a different stat but with different narrative and mechanical consequences—but that draft of game never felt like it was really cohering in the way that I wanted.

The second revision was heavily inspired by a brief perusal of the second edition of 7th Sea, but was still largely Powered-by-the-Apocalypse in its bones: you'd roll to find out how many 'hits' you got, and then trade those for 'outcomes', both stopping bad outcomes and initiating good outcomes. The cool part here was that really high rolls (which were possible through exploding dice) could give you a large number of hits, allowing you to dispatch dozens of enemies in a single conceptual “action”, but the bad part was that listing a half-dozen outcomes to choose from for every roll felt super fiddly and annoying. I might revisit the idea at some point—it's got some cool promise, I think—but I was never satisfied with it for this concept.

The most recent revision is probably closest in its rough shape to Danger Patrol, a probably-never-going-to-be-finalized John Harper playtest draft, although the specific dice mechanic is different, incorporating the theoretically-unbounded-successes of the last version. It has an explicit “threat layout” where you use index cards to indicate what's on the table, like user-visible clocks, and it borrows the split playbook approach of Danger Patrol as well, so your character is created from an Origin (like “the feds” or “the streets”) and a Role (like “tech” or “hitter”). It also involves a lot of dice pool moving and trading: certain abilities let you roll more dice, but they might also let you temporarily move one of your dice to a different pool, or to a teammate's pool, or rearrange your pools on the fly. I still need to playtest, but I've gotten character sheets written and plan to write a lot more over the coming week or so, so it's ready for both personal and public playtesting.

Other games on my backburner: a scifi Dogs in the Vineyard hack tentatively called Wardens of Sirius, an Animal Crossing-inspired daily-life-in-a-village game playable via Slack or Discord tentatively called Yan Tan Tethera, a weird Americana Zelda-style dungeon crawler currently code-named Wenaglia.

A Creative Project: Cocktail Graphics

a diagrammatic recipe for the Last Word cocktail

I started making these diagrammatic cocktail recipes a while back, temporarily lost momentum on them, and have recently started picking them back up. The core idea is that they show you the steps split up so you can see which ingredients are necessary for each step, letting you plan by glancing at the recipe, which would be great for planning when making complicated multi-stage recipes. Unfortunately, this idea isn't terribly useful for cocktails: most of them involve one or two basic steps steps (mix, pour, garnish) so in practice I make these diagrams because they're pretty and fun, not because they make the act of cocktail-making significantly easier.

I'd like to do at least a set of “classic cocktails” (probably starting with the David Embury set) and a set of “personal cocktails”, but once I have a bigger library of vector graphic bottles to pick from I can probably put them together a lot more quickly and easily whenever I get a new idea. We'll see: drawing little vector graphic ingredients is pretty fun. I need to start looking into the best way to get them printed, as well!

Other creative projects on my backburner: a worldbuilding fiction project called Tir-Bhahat, a nearly-finished fantasy novel and drafts of a couple of short stories, and lots more linocut prints than I've done in the past month.