Interview: Spring Villager
Using Python to help create The Last Tea Shop
I’ve recently had the wonderful opportunity to do some interviews with creators and game developers. Previously I spoke with M. Allen Hall about using code to help develop Unhallowed and Sprinkles is Missing.
After coordinating time zones between mine and theirs in Tāmaki Makaurau Auckland (New Zealand), we were able to sit down and have a chat.
We talked about game design, influences, and our shared love of Revenge of the Rainbow Dragons. I hope you enjoy it.
Thank you so much for taking the time to talk!
Let’s start with a little bit about you and your background. Tell me about how you ended up making games!
It's a pleasure!
I first dabbled with game development as a kid in the 1980s, making adventures for friends to play through. However, it's only been in the last couple of years that I actually sat down and tried to make a game. I was actually in the middle of making what I'd been thinking of as "a chill roguelike" in the Godot engine. I had made lots of progress on it, but realised that it would take at least a couple more years to finish working part-time on it.
I really wanted to make stuff for other people. I'd been away from TTRPGs for quite some time, and had never really been part of any online community around them. Then I discovered a few titles that blew my mind. It was the pre-Kickstarter version of Ultraviolet Grasslands and the initial PDF of Mausritter. Also, Maze Rats and Knave.
As a break from the digital game I was working on, I thought I'd participate in a Mausritter game jam. Over a weekend I made a tiny little pamphlet adventure: Maus Astrologus.
I pushed it up to Itch with no price and some people downloaded it. A few even paid money for it.
Oh!! The other big influence was Beyond the Wall. I've never got it to the table, but I really dig how its playbooks weave character creation and storytelling together. I also love the collaborative world building system in its Further Afield expansion and have used it to create a map with my players in an Old School Essentials game.
The thing that motivates me is trying to create these little spaces for people to have an experience they might not otherwise have and also to explore what's possible in games.
There are so many games with fighting and combat at their heart. That's cool, but I feel like that ground is covered. I'm interested in making things where people can touch something a little strange and unknowable, but without elements of horror or overt threat.
I’m curious what your background is related to programming languages. What’s the story of you becoming a coder?
I taught myself to code in the 1980s. Our school had five computers and a roll of 400 kids! These were old BBC Micros and were probably out of date even then. Me and a few other kids spent a winter in the computer room trying to programme a text adventure. We didn't get very far, but it introduced me to the idea of coding at a young age.
I didn't do much more programming until university, where I trained as a geographer. I was in an arts programme, but got into mapping and data visualisation. That was my entry into programming — mostly Matlab and some weird/dead proprietary languages
I picked up Python in the mid-2000s after leaving University. I'd heard about it for years, but never quite tried it. It turned out I really liked it! Its direct, clean syntax were really appealing. I had dabbled with Perl, but it never really stuck. So many ways to do the same thing. I found Python much more straightforward.
I work somewhere where R is the lingua franca. It makes sense as there is a lot of statistics and data visualisation, but I often find myself thinking, “This would be so much easier to write and maintain in Python!”
I have grown to like and respect R, but it's no Python.
I’m always curious about the workflows of other people. What does writing code look like for you?
For tabletop game development, I typically use Python with the built-in modules. While I've used packages like Pandas and Seaborn in the past, I stick with vanilla Python if possible. Instead of a visualisation library, I write results directly to the console.
Here's an output I've been working on for an in-development project where I am experimenting with rules for creating landscapes. I want each player to have a unique "valley", but for there to be some shared characteristics (e.g. higher elevations in the north):
M M M
M . F M
M t t t M
M . t t . M
t t . t t
t . . t
. . .
It's code that I write for myself, so it tends to be pretty light and throwaway. I work on a Mac with Visual Studio Code -- running the code in the standard terminal.
The Last Tea Shop is a journaling game that can be played either with one or two people. Can you tell me about the game?
The Last Tea Shop (LTS) came together because I wanted to make something for the One Page RPG Jam.
Believe it or not, it started as Lasers & Feelings hack. I really dig John Harper’s "small games" like L&F and Lady Blackbird. I love how tightly he connects mechanics and theme. (I'm sure his big games are great, but I've never played them.)
I started thinking about themes and stumbled on the idea of a tea shop on border of living and dead.
Since a kid, I've been interested in the spaces that exist between other places. Specifically, there's a scene in the 1980s gamebook Revenge of the Rainbow Dragons where the player can end up in limbo that I've never got out of my head.
Also, I kept thinking about a tea shop I once passed in the mountains outside Manali in India. I wanted to set something in a travelers' tea-shop — somewhere people might visit just once, but leaves an impression on them.
These ideas fused and The Last Tea Shop was born.
What do you think makes The Last Tea Shop special?
There are a few things that I think make LTS work:
There's a built in timer to the game in the form of the roll for days passing mechanic. This gives me the ability to influence the length of the experience in a way that's harder with systems based on drawing a specific card. (Key influence was Riverhorse's Labyrinth: The Adventure Game)
The visitor archetypes are specific enough to prompt a response in players, but vague enough to give them space to situate the narrative wherever suits them.
The sequence of visitors implies a story for many players. In the classic version, it starts with more humble professions before ending with royalty, and ultimately the Veiled One.
Asking the player to link each subsequent visitor's responses to the previous visitor's story creates an emergent overarching narrative. That's probably the most important element in the design.
The Veiled One is a distillation of what I'm trying to do with my game designs. Offer something evocative, but then hand it over to the player(s) to provide the meaning so that each Veiled One is different.
What’s the core game loop for The Last Tea Shop, and how is the end game triggered by the Veiled One?
You set up a tea shop using a series of random prompt tables. Then the game plays out over a series of days. Each day a different visitor comes to your tea shop. The tea shop owner and the visitor participate in a tea ritual, which involves asking 2 - 3 questions about the visitor's life and their relationship to other visitors. The game is designed so that on average about five people will come to the store before the final visitor arrives. This final visitor is always the Veiled One.
There are a few other things threaded through to provide variety and narrative prompts, including weather (which influences the emotional tone of the visitors), tea ingredients (which enable the owner to affect the mood of the visitor and conversation) and affinities (which are wildcard elements that players can use as much or as little as they want to tone the game).
So, under the hood it's a tracker/countdown timer controlled by dice rolls, calibrated to ensuring somewhere between 5 and 7 visitors.
Visitors arrive at your tea shop based on rolling a d6 but also on how many in-game days have passed. Can you explain how that works?
I wanted people to see the other visitors they might have had, and wonder about what it might be like to encounter them. Reducing the number of visitors helped achieve that.
In the original one-page version there is a list of 24 visitors, each keyed to a different day. To begin the game, the player rolls a d6 to see how many days have passed and looks up which visitor arrives on that day.
When that visitor leaves, the player rolls again to see how many more days pass. They add this result to the original dice roll and look up who the next visitor is. So, it's a cumulative system. Eventually you run out of numbers and the game's ending with Veiled One is triggered.
This is where the Python came in!
Can you talk about how you used Python to test the game, and what changes you made based on the results?
In my day-job I have to think a lot about edge cases. That thinking leaked into the LTS design. I started thinking, Well, what if a person just keeps rolling ones, twos and threes. The game may drag for them and I want them to have a better experience.
So, I coded up a simulation of the game -- not the whole game, just the days and the visitors. Specifically, I created a YAML file that holds the visitor data, and a small Python script that uses the random module to simulate many game runs.
I quickly realised that I needed a way to speed up progress through the game. That's where the boons/gifts came in.
Certain visitors will leave a gift. Some gift ingredients, which restock the owner's tea supplies. But the ones that help control pacing are the visitors who hasten the tea shop owner through the days.
I built the gifts into the simulation, then used them to distribute the hasten boons.
If you look, for example, at the distribution of the "dagger" symbols through the days/visitor list, four of the first six visitors speed up the game. This little cluster of hastens propels players deeper into the game, leaping them over where they otherwise would be with standard rolls.
I also used it to experiment with different rules for how the hasten boon worked.
Originally, the hasten rule was “roll 2d6 on the next DAYS and take the highest result."
The games were still taking a little too long, so I experimented with just adding +2 to the result of your next days roll. This both simplified the rule text, but also made games one visitor shorter on average.
Any other places that you used Python in the expanded edition?
The complete edition introduces the idea of paths. At the start of the game, the tea shop owner determines whether visitors arrive from the Dice Trail or the Lantern Path. In addition to the existing boons, some visitors make players do things like switch paths.
I wrote these things into the simulation, then experimented with them until the tuning felt right.
Aside from game length, I was checking how frequently each type of visitor would be reached depending on different start conditions (e.g. how often will a person starting on the Dice Trail encounter the mouse). I was also checking how often players would encounter events like a path switch or one of the hidden paths.
It was incredibly helpful for getting the design to a good place. I don't know how I could have done it otherwise!
What would this type of testing look like without using Python or coding?
I'm not sure how I would do this without Python (or a similar coding language). Playtesting is fantastic, but it's hard to do at scale. You don't get a good sense of how common an edge case is. You could try to simulate it in a spreadsheet with formulas, but it would be tricky to incorporate things like the boon effects.
I am currently working on a new game where the player creates a map of a landscape at the start of the game. They do this using some procedural rules. Python enables me to both articulate the rules and also to explore the variety and frequency of results
I'm still tuning the algorithm a bit, but each player will have their own little valley with its own peculiarities. Players will never see those ASCII outputs, but they're hiding underneath their (hopefully) hand-drawn maps.
Many Skeleton Code Machine readers who would love to do the kind of testing you do with Python. How can they get started?
My suggestion would be:
Figure out what aspect of they game you need help with (e.g. game length, simulating combat, supply depletion, economy)
Draft some clear, concise rules
Test the rules with dice, pen and paper
See if you can implement them in a spreadsheet with formulas -- if you can, great!
If you can't, try to translate them into Python code. You've done half of the hard stuff already by articulating the rules.
Nothing like writing down what you're trying to achieve to try and understand the problem better
Most important question: What’s your favorite dinosaur?
I think it's probably Diplodocus. There's something about how they're at once huge but also gentle that I really dig, and that graceful swoop of the body silhouette.
See you next week!
— E.P. 💀
Thanks for reading Skeleton Code Machine! Subscribe for free to receive new posts each week.