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? Various programming-language-centric approaches to procedural generation. I've done a lot of these, and Potrero and Treant are two of the newest ones, but I'm using this to talk about the whole family of these tools.

My approach here is to build tools for procedural generation as programming languages, and usually specifically as functional or logical languages: the UI is fundamentally text-centric, based on writing bits of structured text, and the operations defined can be broken down into atomic units that can be understood and reasoned about in isolation without having to reason about broader state. Additionally, because they are ideally decidable—i.e. you can ensure that they don't loop forever, but instead will always complete in a finite amount of time—you get a lot of ability to statically analyze them.

I think there's a really interesting design space here, and different experiments have focused on exposing them in different ways. There are some thoughts in common between all of them:

  • I think (as mentioned) that decidability is important here, both because “this will never loop forever” is a nice property but also because it opens the way for some sophisticated static analysis, like, “Will this program ever produce output with such-and-such a property?”
  • I think mostly-pure functional programming is a useful way to think about these things, where the only side effect is non-determinism
  • I think there's some interesting inspiration to be taken from logic programming or answer-set programming (c.f. Smith & Mateas, Answer Set Programming for Procedural Content Generation: A Design Space Approach and also Karth & Smith, WaveFunctionCollapse is Constraint Solving in the Wild)
  • I think there's a lot of API work to be done around exposing common resources (like Darius Kazemi's corpora) as “standard libraries” to draw on
  • I think there's also a lot of API work to be done around the right primitives for structuring output either textually or non-textually (although I'll freely admit that there's research here that I'm not conversant with!)

So the goal of my various tools has been to chip away at this space and experiment with these various theses!

Why write it? The big tool in this space right now is Tracery. Tracery is a great tool and I love it. That said, I'm very picky about tools.

To give an example of what I mean, here's an example of a Tracery program which creates a brief description of meeting a person:

  "origin": ["#[#setNoun#]story#"],
  "setNoun": [
  "adj": ["familiar", "strange", "mysterious"],
  "adv": ["warmly", "cautiously", "profusely"],
  "story": ["You meet a #adj# #person#. You greet #them# #adv#."]

You'll notice that the syntax is all JSON, with all the advantages and disadvantages that brings: it's a universally available format, which is good, but it's also more finicky and particular, and also now important syntax is embedded in the string literals in a way that's not (for example) syntax-highlighted by default. Note also the "setNoun" rule above: what this does is actually create new rules effectively by injecting them into the set of rules, so depending on which choice is made, it'll define the rule "noun" as being either "man", "woman", or "person", and define "them" as being a corresponding pronoun.

Here's the same generator expressed in Matzo, a dynamically typed programming language for procedural generation that was also the very first tool I built along these lines:

person := "man" | "woman" | "person";
pronoun :=
  { "man"    => "him"
  ; "woman"  => "her"
  ; "person" => "them"
adj ::= familiar unfamiliar mysterious;
adv ::= warmly cautiously profusely;

n := person; fix n;
puts "You come across a " adj " " n ".";
puts "You greet " pronoun.n " " adv ".";

This has a lot of little convenience features, like the ::= taking a set of bare words that are implicitly understood to be a disjunction. (Indeed, you could rewrite the first line of the program to person ::= man woman person; and it would have the same meaning: I wrote it with := to showcase both approaches.) It also has functions—the value of pronoun is a function which branches on its argument—and the fix operation, which takes a rule which otherwise would be vary, evaluates it once, and modifies its value to be the result of that: i.e. after that line, person will still randomly be one of three values, but n will always deterministically be one of those three values.

After Matzo, I worked on a tool called Latka which was similar but with a light static type system. You'll notice this one relies more heavily on things like (structurally typed) algebraic data types and helper functions to assemble sentences, like pa for a paragraph or se for a sentence. You might also notice that fixed is no longer a thing which changes an existing rule, but a property of the binding site of the variable.

let gender = M | F | N
let noun M = "man"
  | noun F = "woman"
  | noun N = "person"
let them M = "him"
  | noun F = "her"
  | noun N = "them"
let adj = %{familiar unfamiliar mysterious}
let adv = %{warmly cautiously profusely}

let main =
  let fixed n = gender
    se.["You come across a", adj, noun.n],
    se.["You greet", them.n, adv],

These obviously have tradeoffs relative to Tracery, but they more closely match the way I think about these problems and the way I'd naturally gravitate towards solving them. That said, I also don't think they're competing: in fact, one thing I've wanted to do (but never finished a prototype of) is building cross-calling between them: I'd love to be able to directly include a Tracery program in a Latka program and vice versa.

As with other projects I've described, I think that the affordances of functional or expression-oriented programming have a lot of benefits, and I think decidable programming languages are really useful. And of course, one reason I want to write it is that I love random generation of things.

There's a reason this project is also the last backburner post: it's the project I most regret having left on the backburner, and the one I would love to spend more time on soon once I develop motivation to do so again.1

Why the name? Latka and Matzo were named together but otherwise chosen at random. I was originally gonna call another experimental language Mesa, which is Spanish for 'table' (by analogy with random tables you'd find in an RPG book) but there's already a graphics driver suite called mesa. So I decided to choose the name of a related geographical phenomenon, since a potrero is a kind of mesa. Similarly, the original version of Treant was designed around probabalistic tree rewriting, and treant is a name used in fantasy role-playing games to refer to a public-domain equivalent to Tolkien's Ents.

#backburner #tool #language #procedural

  1. Hell, I've even given a talk about these before—although a bad one which I'm thankful wasn't recorded, since I was feverish and recovering from a throad infection at the time—and I never did release Latka in a usable format afterwards, which is an ambient regret of mine. I would love to go back and release one of these properly instead!

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 inspired by classic hard-boiled detective stories.

My idea here is that this is pre-written, a hand-crafted world rather than a procedurally-generated one. My mental image of the setting is a sleeker-than-ever-really-existed fictionalized 1920's, borrowing heavily on the clichés of noir media: night more often than not, smoky with black shadows, Streamline Moderne in blue metals, but dingy as soon as you look past the surface. You'd interact with it as a old-style isometric RPG, talking to people and shuffling through drawers and trash-cans and so forth.

The interesting thing, I think, was how I planned to implement the mystery mechanic. When you're first given a case, you are also given a shape, a deeply irregular one with several crannies and protruding bits, areas of which are labeled: Culprit, Weapon, Motive, and so forth. As you acquire information by talking to witnesses, going to places, and so forth, those pieces of information also get represented as shapes, which can in turn be snapped onto the shape representing the case. The catch, of course, is that only one configuration will fit: the correct one. Sometimes also multiple shapes will snap onto the case, but will conflict with each other: a suspect fits, and a murder weapon fits, but they don't fit _together.

This does mean that it's possible to solve the mystery without thinking about its narrative content: by unthinkingly talking to everyone, casing every place, and then ignoring what the clues mean and simply snapping them together. I'm okay with that! The ideal way of playing is to approach it from both directions: using the narrative to inform how you approach the puzzle-pieces, and using the puzzle-pieces to help you approach the narrative. Ideally, too, the pieces would be designed to fit together in ways that match the story: for example, a given suspect and a given weapon both snap together with the shape of the case, then that suspect could have conceivably been the culprit and could conceivably have used that weapon, but if there's no matching motive, then you've got more work to do: either digging into a motive that fits, or figuring out if another suspect was the one that did it.

Why write it? Partly because I love the genre, and partly because I think the hard-boiled detective genre—despite being a perennial favorite for certain kinds of video games—have a ton of interest space for exploration.

I've had notes for this for a long time, and I recall back when I first saw trailers for L.A. Noire that I figured that maybe I had finally been scooped. I don't think it really succeeded at what I wanted to capture! Since the game's release, people have regularly made fun of the awkward interviews where the player must choose to believe, doubt, or disbelieve a suspect, but where choosing to doubt every question was always a safe strategy and lies were awkwardly telegraphed using exaggerated facial motion capture. (It was especially awkward since it wasn't clear which aspect of the story you were choosing to doubt: the player would notice a tiny discrepancy in a witness's story, choose to doubt the testimony, and the player's character would pound his fist on the table and shout, “You wanted him dead, just admit it!”) More than that, it was hampered by being a AAA action game: the grand climax of the whole affair was… an awkward, plodding shootout.

It's pretty common for games to borrow the trappings of noir but end up with yet more violence. (Not that I'm strictly opposed to video games that feature violence, but it's not a good fit for classic noir!) That said, there are games utilize the style and implement the mystery-solving a lot better. Grim Fandango is a spectacular example of the genre, leaning heavily on film noir iconography and using the affordances of a point-and-click adventure game to implement the mystery-solving. More recently, Disco Elysium does a spectacular job of building a deep and compelling mystery by building in the tradition of classic tabletop-inspired role-playing-games.

So I don't want to imply that this is unique or has never been attempted successfully: but that said, I still think there's space to play in this genre in a new and interesting way!

Why the name? I have notes covering the whole trilogy, each with a different protagonist, but each protagonist was going to be—predictably, given the genre—something of an outcast. The idea of the protagonists as “stray dogs” felt appropriate: more than a little cliché, sure, but given that I wanted to draw on the bombastic and cliché-filled movies of the Golden Age of Hollywood, I didn't necessarily think that was bad.

#backburner #videogame

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 tiny ML variant, designed for embedding.

It should of course have closures and anonymous functions and so forth. It should have algebraic data types—named sums, tuples, records for product types—and it should also be garbage-collected. It should have powerful pattern-matching constructs. It shouldn't be pure, in the same way that something like SML isn't pure: mutation would still need to use explicit ref types, but side-effectful functions should be allowed everywhere. It should have a basic exception system. It probably doesn't need a full module system, but some kind of namespacing would be nice.

I'm pretty neutral with respect to syntax, but I was imagining maybe borrowing some ideas from ReasonML. Over time I've become a fan of explicit delimiters for scope, but I also fully admit that syntax is probably the least interesting thing here.

Most importantly, it should be easily embeddable in any language, exposing a C API that makes it easy to initialize the runtime, call into it, and expose callbacks to it. PicoML wouldn't be for writing programs on its own: it would be for writing scripts in larger programs, which means making it accessible to larger programs should be as simple as possible.

Why write it? There are a number of language which are explicitly designed for embedding in a larger program: Lua is one of the most prominent, but there are certainly many others, my personal favorites being Wren and Io.

These embedded languages rarely have types, and the handful that do (like Pike or Mun) often don't embrace functional programming in the way that I wanted. Entertainingly, though, the closest language to what I wanted PicoML to be is Gluon, and my biggest complaint there is that it's too Haskell-ey: it's got monads and GADTs, which feels to me like it goes too far in the other direction. There's a middle ground—an impure functional language with strong SML influence—and that's where I want PicoML to sit.

Why the name? Not that surprising: I wanted to get across the idea that this would be “an extra-tiny ML variant”.

#backburner #software #language

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 tabletop game about fast cars, furious action, and family values.

This is of course inspired by that one series of films. Indeed, the original design goal was to build a game where every player had three core stats: Fast, Furious, and Family.

It's expanded and gone through a number of revisions, including a few that I still think are fascinating, but it's ended up being more or less an adaptation of Danger Patrol. Danger Patrol features an idea called the Action Area, which I like a lot: it's an explicit index-card based representation of the goals and major features of a session. For a lot of games, I think this might be overly restrictive and maybe even a little bland, but for broad-strokes genre storytelling—including both the 50's pulp adventure that Danger Patrol is drawing on and the modern action movies that Guns & Gasoline is drawing on—it feels kind of perfect.

I also put a lot of thought into the right way of representing vehicle chases and races, which are integral to the genre. Making sure that races aren't simply “who can roll the highest number first” but actually feel like moment-to-moment interesting things are happening is integral to the game I want to make. The system I'd been working with most recently involved a three-way distinction where you're always Leading, Tied, or Trailing, and those positions open up different options for actions you can take, including attempting to change your position to one or the other: sometimes that means accelerating to try to take the lead, but sometimes it also makes sense to deliberately let yourself trail behind because that's going to let you address the race in different ways.

Overall, it's not a game designed for long campaigns: it's for one-shots or maybe two or three session campaigns. It should be quick and exciting and ideally have lots of corny one-liners and over-the-top action beats. One guiding principle behind the game is that it should be true to the way a friend of mine once described the Fast & Furious movies: “Imagine a superhero movie, except everyone's superpower is 'car'.”

Why write it? Okay, this is a silly one, and one where I've actually struggled throughout several drafts to actually hit the tone and level of complexity I want: I keep coming up with interesting ideas and then realizing that they're far too elaborate for the goal here.

For example, one draft was a by-the-numbers Powered-by-the-Apocalypse game. I had a set of fighting moves that I liked a lot, including a distinction between Fight Hard (which you rolled with Furious) and Fight Smart (which you rolled with Fast) that not only had their own distinct effects but would interact with each other in a satisfying way. That was a fun idea, but the draft was too complicated.

Later on, I worked on a variation where, instead of using Powered-by-the-Apocalypse-style moves with three possible outcomes, I instead turned every move into a lits of “good outcomes” and “bad outcomes”, and dice rolls would give you points to either prevent bad outcomes or buy good outcomes: in effect, turning every move into a PbtA-style “choose things from a list” move. Because in this system dice would also explode—that is to say, if you rolled their maximum value, you'd keep that but also re-roll the die, possibly multiple times if you got the maximum value again—you could theoretically but rarely get a large number of points to buy outcomes, which could translate into e.g. a single roll letting you take down large numbers of opponents, acquire intelligence, and find useful objects, all at once. This was a fun system that was also far too finicky for the simple game I was trying to jam it into.

There's still a lot I like about the current draft, but I still struggle to make it a game suitable for one-shots. This is one project I deliberately left to the side for a while, because I wanted to come back to it with fresh eyes and figure out what I could cut down on.

Why the name? The working title was The Rapid & The Rageful, which was funny for about fifteen minutes before I found it tedious. Given that there's nice alliteration in both the movie that this game is inspired by and also in the name of the most famous tabletop role-playing game, it felt appropriate to choose an alliterative, so: Guns & Gasoline.

#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 “web framework”, but over SSH instead of HTTP.

What are web frameworks about, on a basic level? You're taking a protocol meant originally for serving simple documents in a hierarchical file system, and instead of serving those documents you're doing various computations and responding with dynamic data. Your web framework needn't interpret a GET /foo/bar as actually looking up a file bar in a directory foo: you could have code attached that does whatever you want!

Cube Cotillion follows the same basic idea except with a different protocol: SSH. Usually, when you establish an SSH connection, you get dropped to a shell and the stuff you type gets interpreted as command-like invocations. Cube Cotillion implements an SSH server, but instead of passing strings to a shell, it instead lets you write arbitrary computations keyed on the commands you've written. If someone writes ssh my-cc-server foo bar, then instead of trying to run the command foo with the argument bar, you can do, well, whatever you want!

Cube Cotillion is implemented as a Haskell library that does pattern-matching over the command passed in over SSH and can invoke callbacks as necessary. Here's a simple example: this server understands the command greet, with or without a parameter, and will respond with a greeting in kind, using the bs command to respond with a ByteString:

main :: IO ()
main = do
  key <- loadKey "server-keys"
  cubeCotillion 8080 key $ do
    cmd "greet" $ do
      bs "Hello, world!\n"
    cmd "greet :name" $ do
      name <- param "name"
      bs (mconcat ["Hello, ", name, "!\n"])

Like a web framework, we can now do whatever we want in response to these commands: there's no underlying shell we're passing commands to, and greet isn't dispatching to another executable, it's just a single process figuring out what to do with the strings and responding in kind. We could build applications on top of this that use structured data (e.g. responding with JSON blobs instead of simple lines) or keep various pieces of internal state. Why not?

Why write it? This is far more on the experimental side: I have no idea if this would be useful for anything at all!

The thing that I like about using SSH as a transport mechanism is that it necessarily has a notion of secure client identity. For certain applications, having a built-in mechanism for verifying client identity would be wonderful, since that's something that need to be built on top of HTTP applications again and again.

That said, I have no idea whether applications built on top of this system would be useful in practice or not. That was sort of the point: I wanted to experiment with using it as a tool for building personal server control, but would it be useful for anything else? Who knows!

I also never got around to designing the right API for doing anything with the client identity, or the ability to do interactive sessions at all. There's a whole design space there that might be fun to explore.

Why the name? I wrote this in Haskell, and there are multiple web frameworks in Haskell named after Star Trek characters, including Spock and Scotty. Given that this was an analogous but wrong project, I decided to choose a name from [Neil Cicierega's guide to the alien races in the Star Trek universe.

#backburner #software #experimental

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 about procedurally-generated under-equipped spy missions.

The player is a nameless spy with almost nothing on them: maybe a tiny amount of money, an object or two. They have an objective: a document to steal or replace, a photograph to take, a target to kill. They are in a randomly-generated city with a roughly 1980's level of technology: computers exist but are rare, mobile phones aren't practically obtainable, and only some sections of the city are accessible but within those sections you can (with some difficulty) get almost anywhere: apartments, offices, basements, and so forth. Go.

The intention is that there should be multiple ways of tackling the objective, but you need to be resourceful. You need to find your own disguises, hotwire cars or take trains, pickpocket money from people, do research in the handful of places where you can. You have no spy agency to rely on to bail you out or drop you resources: if you get caught, it's over, and all-out firefights are a failure condition. You're on your own, with only the infrastructure of the city to help you.

My mental image here was that this game would have the graphical sophistication of a roguelike: that is to say, very very simple grid-based graphics, no strong detail. The detail should instead be in the density of the simulated urban environment, ensuring that buildings do indeed have dozens of accessible and usable rooms (probably generated on-demand: after all, with that much detail, 95% of the map would never even get accessed!)

Why write it? I can pinpoint the exact blog post that inspired this game, which is this post about the “Bourne Infrastructure”. I read this around the same time that my brother and I had been discussing a very different kind of spy game—the James Bond-inspired kind of spy game, with massive explosions and firefights and stunts and whatnot—and it got me thinking, “What would a Jason Bourne game—one that really captured the feeling of the movies, not just a reskinned stealth game—look like?”

There's a lot of complexity here, and a big part would be managing to implement new and different ways of tackling the objectives. There's also an economy of detail that I don't off-hand know the right way to manage. I want players to be able to lockpick an apartment, sneak in, rummage through a drawer, steal a suit, and go off to blend in at an office, but that could easily grow and grow until there are unwieldy inventories and far too much stuff simulated. Finding out the right amount of fidelity here is key, and I don't yet have an instinct around how to do that.

Something I'm super interested in, though, is using stuff like shape grammars to create the world. It'd be a lot of fun to build the basic mechanics and then just keep revisiting new stuff to add to the world, making the city deeper and denser!

Why the name? It's a temporary name—I don't want to actually name it after a real place!—but it's named not for Schengen, Luxembourg itself, but rather for the Schengen Area since the setting is a roughly-defined European setting.

#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 reverse proxy and web server interface.

Aloysius was originally inspired by the old academic servers where a person could host static pages under their username. What I wondered was, how could I design a system like that for dynamic sites, where a given user account could run their own services via a reverse proxy but not conflict with any other service on the machine?

So the approach was based on directories and symlinks. The top-level configuration is a directory that contains zero or more subdirectories, each of which uses different files to describe both filters and forwarding logic. Filters are based on matching on either path (i.e. the HTTP requst path) or domain (i.e. the server) or both, and then they can forward in one of three ways—maybe more over time, too, but these were the first three I experimented with—as specified by a mode file: either http (which forwards the request to host host on port port), or redir (which uses HTTP response code resp and redirects to host host), or aloysius, where you specify another directory by the symlink conf, and then recursively check configuration there.

That last one is important, because it allows you to symlink to any readable directory. One idea here is that different subdomains can map to different users on the same machine. For example, let's say you're keeping your Aloysius configuration in $ALOYSIUSDIR, and you've got a user on the machine yan who doesn't have root access but wants to be able to run some dynamic sites. You can set up something like the following:

# create a dir to forward yan's config
$ mkdir -p $ALOYSIUSDIR/00-yan
# match against
$ echo >$ALOYSIUSDIR/00-yan/domain
# use a recursive aloysius config
$ echo aloysius >$ALOYSIUSDIR/00-yan/mode
# and forward it to yan's home directory
$ ln -s /home/yan/aloysius $ALOYSIUSDIR/00-yan/conf

Now yan can write their own configuration for whatever dynamic web services they want—at least, if supported by the ability for them to run user-level services—and it doesn't require giving them root access to change the other configuration for the reverse proxy. It falls directly out of Unix symlinks and permissions!

Why write it? Honestly, it's not terribly useful anymore: I run my own servers using mostly nginx and am pretty comfortable with configuration thereof. But I still think it's a cool idea, and I clearly think this directory-and-symlink-based system of configuration has legs (which I know I've written about before).

I still think it'd be convenient! After all, I have for a long time used a directory of files (along with a wildcard) to configure Nginx: this simply makes that the first-class way of doing configuration! But also, there's a lot of work that goes into writing a good web server, and this is also solving a problem which the tech world seems to no longer have: namely, how to shunt around requests to different web services all living on the same machine, since instead we abstract those away into their own containers and treat them like separate machines.

Why the name? The name Aloysius was chosen pretty much at random. I originally called it Melvil after Melvil Dewey due to a loose metaphor between the tiny scraps of information used in configuration and the card catalogues that Melvil Dewey had helped popularize, but only because at the time I didn't realize what an absolutely awful human being Melvil Dewey was.

#backburner #software #tool #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 map-drawing game about a village.

That is to say: it's a game for several players where you begin with a near-blank map. Over time, you take turns, where each turn involves developing the story of the place, filling in details, deciding on events that move the place forward. The place in particular is a rural village being rebuilt by a small community, and the game is otherwise neutral with respect to setting: maybe it's a little ancient village in the desert, or maybe it's a village in the snows of another planet in the far future, or maybe something else entirely!

There are many of these kinds of games now—something which I'll discuss in a bit—but the specific thing I want to do with Yan Tan Tethera is build a tiny, manageable-but-still-important resource economy into the game. Actions in the game will have two aspects: they move the story forward narratively but they also spend and gain resources, and losing too many resources will damage the village. I'm still torn on whether it's possible to straight-up lose, but I'm not taking it off the table. If losing is possible, then it should be unusual and difficult, but one reason I'm still open to losing is because it gives some weight and some bite to the resource economy.

Each player's turn is composed of two halves: one that's a random event, one that's an explicit action by the player. Random events might be windfalls, they might be problems, or they might be simply new things that add detail and color to the world. Actions can involve constructing buildings, making tools or resources, undertaking projects or journeys… they're somewhat free-form in terms of their effect on the story, but their effects are specified and play into the resource economy, helping you gather resources. And they can fail! There's an element of randomness, and players can help reinforce projects if they're important, but the randomness means that things might simply not go the way you want. Your village is growing, but it should regularly feel like it's growing against the odds.

Why write it? You've might have noticed that this description is heavily, heavily indebted to another game: Avery Alder's The Quiet Year, a game that I cannot understate my love for. The Quiet Year is a vaguely post-apocalyptic game, in that it specifies that the focus is a place being rebuilt after some kind of terrible catastrophe, but it's not well-specified what the apocalypse was or, indeed, any of the setting details. In the game, you draw cards to find out an event, and then you have various actions you can take.

I love The Quiet Year, but I'll also admit that I've had some weirdly directionless games of it in the past. A big part of it is that the game asks a lot of players. If the players are in the right mindset and have the right experience with improvisation, it can be supremely rewarding, because a player really has carte blanche to do just about anything they want. For example, they can start projects, which can be anything, and they can take about any amount of time and have any effects! They can discover anything! It's supremely flexible, but I've played games with players who have really struggled when given a full blank page. I distinctly remember one game of The Quiet Year where a friend of mine drew a card that told them to make up a second project, and they immediately became upset, because they were struggling to imagine up just one project, and now they had to imagine two.

So what I want is a game which tries to facilitate some of the tone and style of The Quiet Year but builds in a bit more restriction, which on one hand will limit the possibilities of the game, but on the other hand will provide more guidance and affordances to players. The biggest thing is that, instead of projects being free-form, I want projects to address specific resource problems and use specific resources, so that a player should never arrive at their turn and be unsure of what to do: there are problems, and they should be solving them! In this, it ends up borrowing from some of the other map-drawing games I've played, like Martin Nerurkar and Konstantinos Dimopoulos' Ex Novo and Everest Pipkin's The Ground Itself but also from more resource-management-focused games like Cecil Howe's Do Not Let Us Die In The Cold Night Of This Dark Winder. (Perhaps surprisingly, another game that's on my mind as an inspiration here is Matt Leacock's collaborative board game Pandemic, which is another resource-management board game in which you constantly feel like you're on the razor's edge!)

I also should be clear that this project is not a criticism of The Quiet Year. I'm not trying to “fix” it in any way, and I still love it dearly and encourage people to play it! It's especially worth noting that the game I'm describing here, in trying to address one specific design point, loses out on so much of what makes The Quiet Year such an effective and poignant game: in particular, you'll notice that I've glossed over the mechanics around community dynamics which make up such a central part of The Quiet Year, and that's because I legitimately am not sure how to build the game I want to build while preserving those. I'm playing around in the design space, but making something which tackles the issues I want to tackle ends up being a very different kind of game.

Why the name? The original name was Those Who Return, and it was part of a conscious (if somewhat lazy) attempt to avoid imbuing the game with difficult-to-avoid imperialist themes by reinforcing the idea that the protagonists of the game are native to the region and consequently not engaging in imperialism. In retrospect, I believe this was very naïve: after all, there' no shortage of imperialist projects—including ongoing ones—that use the idea of an “ancestral homeland” as an excuse to violently evict current inhabitants. It's an effort, but it's by no means sufficient.

The newer name, Yan Tan Tethera, comes from a system of sheep-counting in the northern parts of England: those three words specifically are the numbers “one, two, three” in the variation used in Lincolnshire. Many areas in Northern England once used a separate set of number words which were used by shepherds for counting sheep: these words were originally descended from the Celtic languages once spoken in those areas. There are some wildly different variants, as well, although it's pretty apparent that they all share a common root! I liked this name because it emphasized a kind of historical and agrarian tone to the game.

#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 protocol for writing RSS readers, heavily inspired by the maildir format.

The core idea of Lektor is that you separate out the typical operation of an RSS reader into two programs which can work concurrently over a specific directory. One program is called a fetcher, and its purpose is to read remote feeds (of any format) and write them into the lektordir format. The other program is called a viewer, and its purpose is to take the files inside the lektordir and view them.

I've got the full format specified elsewhere but the core idea is that you've got a specified directory called your lektordir, which in turn contains four directories: src, tmp, new, and cur. The src directory contains representations of feeds, new contains unread posts, and cur contains read posts. (The tmp directory is an explicit staging place: fetchers will create posts in there and then atomically move them to new, which means that it's impossible for a viewer to ever observe an incomplete post. Even if a fetcher crashes, it will only be able to leave garbage in tmp, and not in new.)

The representations of feeds and posts are themselves also directories, with files and file contents standing in for a key-value structure. That means a given feed is represented by a directory which contains at least an id (its URI) a name (its human-readable name), and a post is a directory which contains at least an id (its URI), a title (its human-readable name), a content file (which is its content represented as HTML), and a feed (a symlink to the feed that produced it.) In both cases, there are other optional files, and also ways of representing fetcher- or viewer-specific metadata.

The use of directories means that fetchers and viewers don't even need a specific data serialization or deserialization format: unlike maildir, you don't even need to “parse” the format of individual entries. This means fetchers need only a bare minimum of functionality in order to write feeds—I had test programs which used basic shell scripts that wouldn't have been able to safely serialize JSON, but were able to write this format trivially.

My intention is not just to design the format—which has already been pretty thoroughly specified, albeit in beta format and without having been subjected to much testing—but also to write the tools needed to write an RSS and maybe ActivityPub reader on top of this format.

Why write it? Well, I wanted to write an RSS reader, because none of the existing ones are exactly what I want, and this seemed like a good way of splitting up the implementation into bite-sized chunks.

There are some interesting features you get out of separating out the fetcher and viewer operation. For one, fetchers become ridiculously simple: they don't even need to be full services, even, they can just be cron jobs which hit an endpoint, grab some data, and toss it into the lektordir. Instead of a reader which needs to support multiple simultaneous versions (e.g. Atom, various versions of RSS, newer ActivityStreams-based formats) you can have a separate fetcher for each. For that matter, you can have fetchers which don't strictly correspond to a real “feed”: for example, you can have one which uses a weather API to include “posts” that are just sporadic weather updates, or one which chunks pieces of your system log and puts one in your feed every day to give you status updates, or whatnot.

Separating out viewers means that you can now have multiple views on the same data as well. Maybe one viewer only cares about webcomics, so you can pull it up and read webcomic pages but let it omit blog posts. Another gives you a digest of headlines and emails them to you, leaving them unread (but of course omits anything you happen to have read during the day.) Another does nothing but pop up a message if you let unread posts pile up too long. Hell, you could have one that takes your combined posts and… puts them together into an RSS feed. Why not?

The cool thing about lektordir to me is that it lowers the barrier to entry to writing RSS-reader-like applications. It takes the parts and splits them behind a well-defined interface. But there's a lot of cool stuff that you get from trying to apply a one-thing-well philosophy to problems like this!

Why the name? It's for reading, and lektor means “reader” in several languages. I'll probably change the name at some point, though, because there's also a plain-text CMS called Lektor.

#backburner #software #web #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? A video game about driving around an inscrutable world.

There's not much more to it: just a world, with a barebones (and probably slightly inscrutable) set of objective that ask you to go from unexplained place to unexplained place. Unlike the previous game ideas I've described like Albulaan and Tales, I didn't intend for this to be procedurally generated: just hand-created grand and unexplained places.

Why write it? This is actually a slightly newer incarnation of an older small idea I had: a walking simulator built around a series of bizarre atmospheric places, filled with surrealist imagery you might find in something like the Codex Seraphinianus or Le Garage hermétique. I like the idea of driving around even more, though, in part because I just enjoy games about driving, and in part because the idea of having somewhat inscrutable signage that still reads as signage sounds like a lot of fun.

Also it would be good Blender practice for me.

Why the name? I guess this is the post where having an obligatory “name explanation” section in every post becomes really really unnecessary, huh?

#backburner #videogame