Hi there, I'm Howard Abrams. You may remember me
from past conference talks
as "Literate DevOps and the Temple of Doom"
and "Using Eshell for Fun and Profit".
I'm here to talk to you about my latest Emacs project:
playing games, solo role-playing games.
I started playing RPGs when I got my first copy
of Dungeons & Dragons when I was 12.
Yes, my original copy burned
in the Great Satanic Panic of the 1980s,
but that's another story.
I started playing other RPGs like GURPS.
These are some of my notes.
Back then, I was typing them in Emacs,
but I formatted them with LaTeX.
Later, when I was introducing my kids
to role-playing games,
I actually typed them up still in Emacs,
but now formatted them for a tablet.
I wrote a little JavaScript code
that allowed me to click on it, and it would roll dice,
generate random events, keep track of turn order,
you know, everything,
so I didn't have to slow down the action of the game.
Well, when my kids got older,
I still managed to sneak in a game of D&D
once a week at lunch.
This pastime came to a screeching halt with the pandemic.
I turned to playing role-playing games by myself
to get my fix. Playing these silly elf games in solo mode
has been part of the game for many years,
but with so many of us stuck at home,
solo role-playing games really expanded,
creative people releasing some amazing ideas.
What's a solo RPG like? Well, it's somewhere in the middle
of writing your own story, where anything's possible,
but you've got to do all the imaginative work;
or reading a choose-your-own-adventure book,
where the text is given to you,
and you have free, a few predetermined paths;
and tactical battle games,
where dice determines everything.
It kind of fits in the sweet spot between those.
While I started removing the Game Master
using the Mythic GM Emulator,
Ironsworn really captivated me.
I began with dice, pencils, notebooks, you know,
just like when I was a kid. But taking notes on paper?
Yeah, you know me. That's not my jam. Org mode is.
And, you know, notes have to be in Org,
well, why not write a little dice roller in Lisp?
Well, when Shawn Tomkin released his Ironsworn
under the Creative Commons, well,
I could just download the entire text.
I figured I could just render the entire game in Emacs.
All right, enough talk. Let's get some Emacs action here,
while I show you a bit of my game.
When playing a solo RPG,
I jot down the story notes in an Org file.
I mean, did you expect anything less from me?
I alternate between lengthy prose and short notes.
As I'm both the writer and the audience,
the goal is just enjoyment.
So, this document is both a record log of my game sessions,
as well as my character's character sheet.
In most RPGs, a player's focus is a character sheet
that lists all the attributes, the stats, equipment,
powers, you know, that sort of thing.
For my game, I wanted the focus to be the prose,
or at least the notes.
So, I put down all the stats as Org mode properties.
Now, I can collapse a property drawer
and have functions
that just grab values from these properties.
All right, let's play. While not important to my talk,
I'm in the middle of a game. My character, Tegan,
promised to help a village by tracking down
the son of a village chief. A less-than-stellar roll
meant I didn't catch him before he entered
the mysterious underground structure
of a relic of an ancient people.
I just finished playing out the journey,
and he's about to enter into the Catacombs of Svala's Blood.
Why that name? Well, that was actually what came up
from an extensive random number generator that I wrote.
As I wrote more and more functions
to help me play this game,
and since I don't play all the time,
I created hydra. I can roll dice,
I can roll dice challenges against the character stats,
I can adjust stats. Lots of random generators
come from this oracle section.
For instance, are footprints going through the door?
I press `c`, and I'm prompted with how likely.
Since the villagers gave Tegan vague directions,
and he didn't see any signs the contrary,
I chose "likely". And, well, it originally said yes,
and that's why I jotted this information down.
Now, this is different than my character's ability
to notice the prints. This is about generating the story,
something that the game master would do
in a typical role-playing game.
Now, if I wanted to name something,
or even the current weather,
I have random tables with the `C` keystroke.
Hmm, weather. Oh, it's summer, so hey,
it's nice and clear. All right, let's play.
The action in Ironsworn,
like other Powered by the Apocalypse games,
is driven by moves. So, I hit the `m` key,
and all the moves show up.
Now, I don't think I need to espouse
the virtues of completing-read enhancements like Ivy.
Here, I'm using orderless with vertico
to help me find my choices.
Since I've discovered a site, let's play that move.
I seldom remember the details for the moves,
so I figured, why not put the text of the book
in an Org file and show it in a side window?
The prompt at the bottom, asking for a name,
is driven by the content in the displayed Org file.
This allows me to enhance my game without
changing the original code. So, let's call this story arc,
Exploring the Catacombs of Svala's Blood.
Ooh, sounds epic.
Ironsworn tracks the beats of a narrative,
so major plot points take up more room in the fiction
than minor plot points.
Similar games like Blades in the Dark
use numbers to track these, so you can say something like,
we're three quarters of the way through this story arc.
Ironsworn just uses labels,
and while I want this particular story arc
to be significant, I really just want to get in,
find this person, and get out.
So, I'm going to call this "short".
Next, it's asking about an Org mode header placement.
While I originally wanted my Org files
to be completely flexible,
one thing I noticed in playing
is that a pattern always emerged.
The story became a tree. You see, story arcs
were just a series of montages or scenes,
and each of those were made of a series of events
and challenges to overcome.
So, each Org mode header has a track,
which often becomes the number of subheadings.
At any point, I can see how much track is being made.
So, for instance, this one seems to be
about a third of the way through.
So, let's dive into this ancient place.
Since I've been walking through a misty forest,
I can imagine vines hiding an immense door
and a humid, earthy smell as I peer inside.
But I don't have to write that stuff down,
or if I want to practice my writing, I can.
I can imagine the place is dark,
so Tegan lights a torch
before peering into this obscure world.
As this move mentions,
the next move to make is called Delve the Depths.
As soon as I select this move,
it shows up on the side window, and explains that,
depending on how you're moving through
this ancient catacombs,
is what kind of stat I roll against,
and those stats show up at the bottom.
You know, if I'm sneaking around, you roll against "shadow".
If you're trying to go as fast as you can, it's "edge".
But I kind of imagine that he's thinking through,
being very careful about it.
So, I'm going to select "wits".
And I don't have any modifiers.
Just about every one of my stats prompts me
if I want to add or subtract any values.
A miss. I should explain how the dice roll in this game.
The downside to Ironsworn is that
the dice mechanics are more cumbersome than other games.
You roll a 6-sided die, add to it your relevant stat,
plus any modifiers. Next, you roll two 10-sided die
and see how it compares.
Of course, I programmed this in Lisp,
but when I displayed it, I wanted to see all the dice.
And I also just wanted to see the end results.
So I colored it. I rolled a miss,
which means I need to reveal a danger.
Sure, I could imagine all sorts of dangers,
but this is a game.
I've already made a random generator for dangers.
In fact, I've made a random generator
for dangers in an ancient underkeep.
Discovery undermines or complicates the quest.
Hmm, a complication for finding the chief's son?
What about a labyrinth full of hallways and levels
with lots of choices and almost no way of finding them?
Yeah, that sounds like it fits pretty well.
Time for another move. This time, we're going to
gather information,
see if we can figure out which way to go.
A strong hit. Excellent.
I imagine Tegan noticing footprints in the dust
and knowing where to go.
The game suggests that when you get a strong success,
you can increase your momentum.
These game mechanics
come into play later, but this function here
allows me to adjust that stat +2.
I don't even have to scroll to the top of the buffer
and edit that value in my properties.
At any point, I can take a look at those stats
and see how they measure up.
Again, I don't have to scroll up
and take a look at my properties
at the top of the Org mode file.
That's how I play the game.
It's just a recursive loop of playing a move,
rolling some dice to see how it works,
trying to answer the question
based on your own imagination or random tables,
which the game calls oracles,
and play creatively until you decide to take a break
and pick it up another time.
I think you get the gist of how I play
this dice and pencil game in Org Mode.
However, I found more solo RPGs to play.
And of course, I want to render them in Emacs too.
This code for Ironsworn was a bit too specific,
so I decided to create a role-playing game toolkit.
This project is still in the early stages,
but I've created some functions
for mimicking rolling dice, including a mini-DSL for
making dice mechanics
typical of many role-playing game systems.
I've also ported over the random table system.
A text file can just list entries to be displayed at random.
I love that I can put dice expression
and word choices in the entries.
One type of random table allows you
to essentially copy and paste a table
from a published game into a text file.
A frequency table is what I'm calling
a list of random entries where some entries show up
more often than others. I'm working on generalizing
the character sheet attributes as Org properties,
so if you're interested, check out the project at Codeberg.
The point of my presentation is not to show off Ironsworn,
how I programmed it, or even this new toolkit.
You see, most engineers,
when they get an idea for a game like mine,
would make a web app. Nothing wrong with it.
More people can play it,
but web apps suffer from text entry.
And don't tell me you prefer the keyboard interface
to Google Docs. Oh, and the JavaScript framework du jour?
Oh, I mean, that's a huge barrier of entry
when all you want to do
is have a bit of fun prototyping a game.
What I'd like to impress upon you
is that hacking Emacs to make personal games is a trip.
Learning Lisp is, it's easy.
And more, Emacs Lisp has some, well sure,
it has some cruft. But really, some of those features
that I would hate at a distributed system at work,
like global variables, makes hacking easier
when you just want to have some fun in your own system.
So, grab your laptop, sink into your comfy chair,
pour yourself a glass of scotch,
and craft yourself an enjoyable evening.
Happy hacking, my friends.