“Where buy chicken?” “Avocoda”

Brief Moments of Time

Before we go any further, let’s take a moment to talk about time in a text adventure game. Most games don’t play out in real time, they unfold in game time. In a game, what exactly marks the passage of time? In a single-player text adventure game, moves are the ticks that drive the clock: e.g. your wound will heal in 10 moves, or 3 moves until the bomb explodes.

When your UI is a ticking time bomb

Up until now, my game input had relied on Mix.Shell.IO.prompt/1 , the documentation for which consists of only two sentences, one of which was “Input will be consumed until Enter is pressed.” That humble sentence didn’t seem to foretell the complete rewriting of my codebase, but it did: I had to rethink my entire approach.

iex(world1@localhost)1> Xventure.new(:louise)
You are standing in a grassy clearing on the crest of a gentle hill. There is a gravel path leading to a red barn to the south.
Other people at this location: thelma
Exits: south

Raw Input Mode

What makes this article worth reading is the knowledge of how to transition from the predictable world of Mix.Shell.IO.prompt/1 and into the quantum singularity of the terminal’s “raw input mode”. Honestly, this was a bit of a struggle and it took some time for me to figure it out.

Player “bob” on the left, receives a message sent to him from the terminal window on the right

The Takeaways

Working with raw input mode is hard. As soon as I executed ExTermbox.Bindings.init/1 things in the terminal would get weird. If I had errors or I wanted to ctrl-c out, often I couldn’t, and I had to close the entire terminal window. I got really familiar with moving back into my project’s directory, over and over again.

def start(player_name) do
{:ok, pid} = Txtr.Player.start_link(%{name: player_name})
ref = Process.monitor(pid)
receive do
{:DOWN, ^ref, _, _, _} -> :ok

What we Have and What’s Next

I have spared you most of the coding details in this article in an effort to keep it shorter— you can review the source code for details. What we have now is the seed of a dynamic real-time terminal UI that will support multiple users and features like chats between players. This required adding a new kind of state: a “view state” dedicated to supporting a player’s terminal canvas and buffering keys, but it’s not yet clear how that will relate to the rest of the state in the game or what patterns might emerge from dealing with it.



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store