Death on the Stormrider: A Postmortem

I finally accomplished it—my first IFComp entry! It’s something I’d always wanted to do, and a specific goal I’d set for myself this year. I got into interactive fiction a bit over a decade ago, made one big game, then spent the next several years providing technical help on the forums and never managing to release anything else. I had a sequel to Scroll Thief outlined, but its sheer size was suffocating it, and I ended up with a lot of cool puzzles but nothing holding them together.

I took a hiatus from the community during the pandemic, and when I came back, I wanted to actually finish and release some things. So I entered ECTOCOMP, and IntroComp, and had a lot of fun with it! But I really wanted to make something bigger than that, and actually enter the big competition, something I’d watched every year but never participated in. That was the main motivation behind all of this.

Separately, I’ve loved murder mysteries for a long time. The genre is such a fun blend of suspense, deduction, and excitement—all things I enjoy in IF as well. And the purest form of the murder mystery, in my opinion, is the “closed circle”, when some outside force keeps the mystery confined to a single location. Agatha Christie’s Murder on the Orient Express might be the most famous example; the whole story happens on a snowbound train, so the detective (and the reader) can be sure that all the suspects and all the evidence are confined to this one area. It cuts down the possibility space a lot!

So of course, I’ve always wanted to write one. The setting and the story were mostly derived from that goal, rather than the other way around. Return of the Obra Dinn inspired me to set it on a ship, and some conversations with my siblings inspired the airship specifically.

Of course, murder mysteries usually involve a lot of interviewing suspects, and conversation is the single hardest thing to implement in a parser game. There’s a limited number of things you can do with medium-sized dry goods, which means a parser world model can implement a lot of them, and give you a feeling of infinite options. But the number of possible things you can say in a conversation is so much more! Take any string of six or seven words from this review, and it’s likely that string has never been spoken before in the history of the English language. The number of possible English sentences is many times greater than the number of atoms in the observable universe. It’s difficult to convey how enormous the possibility space of conversation truly is.

On this front, inspiration came from my real-life work. My department at the university has a specific program for “less commonly taught languages”, that deals with languages like Lingála and Q’anjob’al that aren’t common enough to have resources widely available. But when I say “less common”, there are still hundreds of people just in this one city (right in the middle of the United States) who speak Q’anjob’al as their first language. And Q’anjob’al is just one of two dozen indigenous languages from Guatemala. There are plenty of cases where people aren’t able to find translators who understand them, since they don’t speak one of the dozen or so most common languages in the world. (In one recent case, a judge decided to handle immigration applications via Google Translate, and rejected several of them due to inconsistencies introduced by the translation.)

I’ve never been an especially literary IF author; I tend to focus more on puzzles than on themes and motifs. But I also think even genre fiction can have important ideas behind it. So that’s where the core of the story came from. The protagonist is effectively silenced by the lack of a common language. Everything else flowed from there. Why are you on a ship where nobody can understand you? Because you’re trying to get back home and this was the cheapest way you found. How did you make the arrangements if the crew can’t understand you? One person did speak your language and he was the murder victim. Why are you allowed to wander around the ship when a murder’s happened? Because you’re not the suspect, your brother is, and you need to get him free.

Other elements came from the needs of the gameplay. I need a lot of locations and not many crew members for the puzzles to be at all possible, so the ship is woefully understaffed. Why would that be? I went through some long brainstorming sessions on Discord with my partner and their roommates, figuring out what secrets each crewmate was trying to hide and why. The puzzles took shape slowly, over the course of months; I started by building the hiding and NPC autonomy mechanics, and then experimented with what I could do with them. My partner also provided the sketches of the crew members (aesthetically inspired by Obra Dinn) which I was absolutely elated with.

The endings were one of the last components added, and possibly one of the least successful. When the whole story has been shaped by the protagonist’s silence, the obvious way to end it is to undo that silence, let them speak freely and learn all the secrets of the ship. But I specifically didn’t want to do that. I didn’t want the core problem of the game to have an easy answer, or to go away as a reward for solving the mystery.

So my goal for the endings was to maintain the premise. You can’t talk to anyone, and that isn’t going to change. You don’t get to ask any questions, and you aren’t given any explanations. Even in the ending, you’re an outsider, not truly part of what’s happening; you see the fallout of your choices, but if you want to understand why that happens, you’ll need to find out for yourself.

In other words, the endings were written to be deliberately unsatisfying. And I’m not sure how successful that was. In the post-comp release, I’m going to modify the ending based on how many unfinished tasks are left on your list, hinting that there are explanations to find in the game—Zagin just needs to find them rather than being given them. We’ll see how well that works.

But for those of you who’ve read this far, I would like to explain the details here. This is the truth of what happened on the ship, as best Zagin can reconstruct it.


The Mekhe-Irakkab is a smuggling ship first and foremost. The empire has imposed debilitating tariffs on certain provinces to keep them in line, leading to a lot of discontent, and the crew is smuggling illegal spices and the seeds to grow more. They’re also using some of their ill-gotten profits to bribe customs inspectors not to report them.

However, not everyone is content with smuggling spices. Two members of the crew, Qarrad and Udan, are going a step further—a lot of people in the provinces are chafing against the empire’s control, and Qarrad and Udan are using the Mekhe-Irakkab to supply these groups with weapons. The rest of the crew knows nothing of this.

The original plan was to hire on more hands before launching, but a surprise visit from the authorities changed that. At the last minute, Udan spotted some Arali citizens looking for cheap passage home, and offered to get them back for free if they would help around the ship…and could be ready to launch in ten minutes. They agreed. The result is a dangerously under-staffed ship, straining the crew to the limits to get it to its destination—but that’s a better outcome than a surprise inspection!

During the voyage, the two Arali helped wherever they could around the ship, and one of them—Kiang—started getting very close with Udan. Eventually Udan gave him a key to his (Udan’s) cabin, where he (Kiang) was spending most of his off-duty time.

Meanwhile, the two engineers were profoundly overworked keeping the ship in the air. Bashti, the younger (and physically smaller) of the pair, ended up spending a lot of time in the rarely-used maintenance space between the decks, doing emergency repairs that normally wouldn’t be necessary. And in the process, he discovered what Qarrad and Udan were up to. He took the evidence to Udan’s cabin and confronted him about it.

Udan first offered him a cut of the profits to keep quiet, then resorted to threats, pulling out a personal sidearm (that, as the gunner’s mate, he was authorized to carry). In desperation Bashti grabbed for the weapon, and it went off; as Udan collapsed he fled back into the maintenance passages to dispose of the evidence. (His plan was to throw it overboard as soon as he saw an opportunity to get it through the cargo hold without Qarrad noticing, but he hasn’t gotten that chance yet.)

The crew eventually found Udan’s body in his locked cabin, and suspicion fell on the one other person with a key: Kiang, who (without Udan to translate) had no way to defend himself. And if the player doesn’t reveal one of the other crimes (the crew’s smuggling, Qarrad and Udan’s arming terrorists, or Bashti’s murder), he’ll be summarily sentenced as soon as the ship lands.

Thank you all for reading, and for playing! A post-comp release is coming soon, which will hopefully make it a bit more explicit that the tone of alienation is intentional, and humanize the relationship between Kiang and Zagin a bit more—I got some truly wonderful feedback from the reviews, and I think it’s going to improve the story quite a lot. So stay tuned for the improved version!


Oh, and while I’m revealing secrets:

  • The language the crew is speaking (“Kishadu”) is Old Babylonian; kishādû is Old Babylonian for “from the neck of the river”. The name of the protagonist’s province (“Arali” = “the plains”), as well as “Kiang” and “Zagin”, are Sumerian. The language of the Empire, only described in an easter egg, is Hittite. (And the language of one of the other provinces, only described in another easter egg, is Ugaritic.) The general aesthetic for the Kishadu characters is ancient Mesopotamian crossed with steampunk.
  • Since Old Babylonian is a Semitic language, a lot of verb forms are gendered. In particular, you can’t give orders to a specific person without specifying their gender. So while Zagin is never explicitly gendered in English (or Sumerian), the crew’s dialogue always refers to them as female.
  • This also means there’s an even mix of male and female crew members, which isn’t an accident—during development, the characters were first named A B C D E F X Y, and I alternated male and female when assigning placeholder names: Alice, Bob, Claire, Dave, Emma, Fred, Xavier, and…I forget what I had for Y. (Might have just been “You”.) Then those placeholder genders stuck when I assigned actual names.
  • The NPC autonomy system required me to rip out Inform’s default route-finding and replace it with a custom one, so that I could specify arbitrary edge weights. Specifically, I needed Bashti to prefer any number of normal rooms over a single crawlspace if he could, but still use them if necessary. Inform doesn’t provide a good way to do that.

Oh yeah, and one last secret to reveal: normally I try to work tester names into the game in some diagetic way, but given that a big theme of this game is not understanding anything that’s said or written, there was no real way to do that. With one exception.

According to the envelope in Shimat’s cabin, the corrupt customs inspector is named Meletz-Esun, “Joy of [the god] Esun”. Most of the Kishadu names are actual Old Babylonian ones, but this one I invented to sound like Mel Jason, the tester who figured out what language the Kishadu text was in, found a grammar of that language, analyzed the verb forms in Ishme’s dialogue, and realized that she was referring to Zagin in a feminine way. Which is so far above and beyond what I would ever expect of a tester that I needed to commemorate it somehow. (Mel Jason is also the reason there’s a “subtitles” option, for people who are curious about the language.)


Thanks for sharing! I love learning more about the author’s vision for the games. Hearing about how you had to write custom route-finding makes me even more impressed I didn’t have any problems with the crew going to the wrong places . . . and I really enjoyed the language notes, that’s fascinating.


It also helped with some mid-comp bugfixes! The solution to one issue was to add a special rule saying the edge from the Miscellany to Shimat’s Cabin had infinite weight when NPCs were planning their routes, so that Kasap couldn’t get trapped in there.

(It also made the pathfinding in Labyrinthine Library possible, so all in all I think the time invested in that code was well spent.)


Haha, see “the edge from the Miscellany to Shimat’s Cabin ha[s] infinite weight when NPCs [ar]e planning their routes” is the kind of patch note I love; it’s got that Dwarf-Fortress-“adjusted the value of bees” flavor.


See also “the lever in the boiler rooms is now fixed in place, not simply attached to the machinery”—previously you couldn’t take it because it was part of the machinery, but it was still flagged portable. Normally this wouldn’t be a problem, except that there are certain things in the game that you can’t interact with around NPCs, and the lever is one of those. Which means when you examine it, the game sees that it’s illegal and portable, and tells you that you could hide it in your pocket.

Patch notes are truly bizarre sometimes.