Text Adventures in iOS Shortcuts

Like a lot of people, I was aware of Workflow as an iOS app that seemed to be a slightly more robust version of IFTTT, but didn’t see an immediate use for it until iOS 12 was released, and the app was re-branded as Apple’s official Shortcuts app.

Only problem was, by that time, I had very little left in my life that I really cared to automate. Something about being sad and unemployed? I don’t know, it sounds vaguely familiar. Anyway.

For Android users, or at least people who don’t care, Shortcuts is a tool that allows you to use a drag-and-drop programming interface to put a limited amount of functions together. The end result of this being a new app, which harnesses the power of other apps on your phone. This can range from things like, polling the Weather app to see whether you will need an umbrella today, and giving you a push notification letting you know when and where the rain will fall. Or, for the smart-homed, curating intricately-choreographed “scenes” far beyond what the Home app is capable of; perhaps texting your entire home an emoji, and watching as the lights, temperature, entertainment center, and coffee machine all work in unison to fit a certain mood.

You could also, if you’re a true Portlander and are so inclined, use it to brag about how many coffee shops are within walking distance.

Though the new tool, with the ability to run programs that brought apps together using Siri, Home Screen buttons, or even the Widgets panel, was designed for those with a will to capital-O Optimize their everyday life, I saw in it a very different potential.

This started with the discovery of Space Alert, a “crappy text adventure” that takes advantage of the branching “Choose from Menu” function. While it’s a short game all told, it proffered a revelation: While the functions provided within are small, they contain all of the necessary elements of a variety of text and turn-based games. And so I set to work.

What unfolded over the last month has been an exploration, of sorts, into the practicalities of building games within a program that is all but explicitly not decided for making games in. Many of them are still a work-in-progress, but it’s proving to be a deeper well of experimentation than I anticipated. Below are two of the methods that I’ve been exploring, with some detailed reference for trying it out yourself.

If neither of them interest you, I’ve also figured out how to make a roguelike with Shortcuts, but that’s… a much longer post. Stay tuned.


Choose-Your-Own-Adventure

Starting with the example set forth from Space Alert, you can use a combination of the Show Alert and Choose from Menu functions to create a narrative with branching paths. Because of the visual nature of the Shortcuts interface, the results of a choice get “nested” inside the choice in the code, so it may be wise to create “routes” that diverge based on choice, then eventually come back together.

Roughly, that looks like this:

Show Alert: “Hello! Welcome to the game. You are in a room with two doors.”

Choose From Menu: “Do you want to go Left, or Right?”

Left

Show Alert: “You have chosen the left path.”

Right

Show Alert: “You have chosen the right path.”

Show Alert “You win!”

Reading that back, you’ll first see an alert saying “Hello! Welcome to the game. You are in a room with two doors.” You will then be presented a menu, allowing you to choose left or right, resulting in the respective alert shown. Then, regardless of choice, you’ll be shown the alert “You win!”

Of course, this can get more complicated as you go deeper and deeper into the branches. You can place a “Choose From Menu” inside a “Choose From Menu”, for example, or even list the result of a previous choice as an option for a new menu to list. Space Alert does a great example showing this off, so I won’t try to provide my own reference outside of that.


MUD-Style Text Adventure

Example: Simple Text Adventure Framework

One of my earliest and most important memories of playing videogames with my dad involves playing my first “MUD”, or “Multi-User Dungeon". A precursor to MMOs and MMORPGs, a MUD allowed a bunch of users to connect to the same server, and play a simple text adventure game together. Typically, this would follow a stereotypical ZORK-like pattern: “You are in a very dark room. You are likely to be eaten by a grue. Exits are NORTH, SOUTH, and WEST.”

You would then have to type commands like, “go NORTH”, or, “attack GRUE” and see how the world responded.

The reason this particular memory stuck with me, however, is that the game we played took place over a large expanse of “rooms” with various descriptions. Sprawling mansions, open marketplaces, creepy dungeons, all of which rendered only in text, without a map to keep them all organized. If you wanted to remember which way you’d turned previously, so that you can make your way back out of the labyrinth before the minotaur catches you, you had better keep track of that somehow. So, we would spend hours together, drawing out each action and movement onto a large sheet (and quickly several large sheets) of graph paper. The game, just a virtual fantasy, soon had a weighty physical counterpart, that we had built ourselves.

In Shortcuts, it’s possible to recreate this same sort of game on a smaller scale by replicating the core conceit of the text adventure above, but adding a few more functions from the Shortcuts arsenal, namely List, Variables, Calculate, and Repeat. All very simple ideas unto themselves, but can be combined powerfully.

Let’s start with how we want the game to look, and work backwards from there. I would like to have the game described to me a fictional room that I’m in, and provide a list of directions, which I can then use to move to the next room, which will then be described to me, and so on…

This is the core “loop” of the game, and since Shortcuts applications are only designed to be run all the way through once, this is achieved through the Repeat function. As of yet, there isn’t a “repeat infinitely” option, however we can set a Repeat of something like 1,000,000,000,000 times, which is basically the same thing. Inside that “loop”, we will do four things:

  1. Calculate what room the player is in

  2. Show that room’s description

  3. Allow the player to choose from a list of available exits

  4. Update the player’s position accordingly

If, like me, you’re prone to draw out maps on graph paper, you’re probably used to thinking about locations and positions in terms of X and Y coordinates. Picturing the top-left corner of the page as the origin, subtracting from a player’s Y value moves them “up” the page, whereas adding to it moves them “down”. Same for the X value with left and right. Once you have the X and Y position of the player, all you have to do is return the room that matches that value, and you’re off to the races.

Well, almost.

Shortcuts, not being an app that’s designed for such purposes, doesn’t allow us an easy method for creating two-dimensional arrays, which is what we typically want for X/Y coordinates. So, we have to get creative (“yaaaaaay,” I hear you saying).

What we’re going to do instead, is take advantage of the List function: a one-dimensional array that we can trick into becoming a two-dimensional array.

To do this, let’s take a look at the total amount of space you’re looking to create. How many rooms wide and how many rooms tall will it be? For the purposes of example, I stuck with three rooms wide, and three rooms high, for a total of nine spaces altogether in our “map”. We then specify the Map Width and Map Height as variables, like this:

Number: 3

Set Variable: Map Width

Set Variable: Map Height

Note that we only have to set the Number once here, as the Set Variable function passes its input on to the next action. If we wanted the height to be different from the width, we would place another Number in-between the two Set Variable commands.

With those numbers in mind, we’ll now create a List of our rooms, with the idea that we will be listing 9 rooms, in imaginary rows of 3. You could conceivably picture them as columns of 3, as well, but I prefer rows, so there. In my example, the list looks roughly like this:

List: “Northwest Room”

“North Center Room”

“Northeast Room”

“West Room”

“Center Room”

“East Room”

“Southwest Room”

“South Center Room”

“Southeast Room”

Set Variable: Room Title

Using the three-by-three layout works well enough for these purposes, but remember that you can adjust this to fit any width or height that you need. You can then use the Set Variable command to save this list for easy use later.

If you want to get more detailed, as I did in the example Shortcut provided above, you can create multiple lists that all correspond to the same rooms. For example, you could have a list of Room Titles, another list of Room Descriptions, and another list of Room Items, just making sure that the order of each list lines up with the order of the others. To determine what item in our lists to return, we will use not X and Y, but the player’s “Position”, a gestalt of the two dimensions.

“Position” will represent the player’s current spot in our many lists, and moving the position up or down will affect what room is display. This is where knowing the width of your map ahead of time is important, because that allows us to fool the list into thinking that it has more dimensions than it really does. To move the player to the right or left, we simply add or subtract 1 from the player position as needed. To move the player “up”, or “down”, we will add or subtract the Map Width variable. This will have the effect of simulating vertical movement in our imaginary map.

In the example we’ve laid out so far, let’s say that we set the Player Position to 5, like so:

Number: 5

Set Variable: Player Position

We can use that number to then return the information that we have about the room at that position, using the Get Item From List function, like this:

Get Variable: Room Title

Get Item From List: Item at Index: Player Position

Show Alert: Get Item From List

When you create the Show Alert, you can use the Select Magic Variable option to pull the result of the Get Item From List directly, rather than having to set/get more variables. When this is all run together, we’ll see an alert telling us that we are currently in the “Center Room”.

With our map and our initial positions set, we must now find a way to move around, which we’ll accomplish by returning to our old friend Choose From Menu. First, we’ll create a menu giving us four options, which we’ll name “North”, “South”, “East”, and “West”, to keep with tradition. Inside each option, we will get, adjust, and set the “Player Position” accordingly:

Choose From Menu: “What direction would you like to go?”

North

Get Variable: Player Position

Calculate: Subtract “Map Width”

South

Get Variable: Player Position

Calculate: Add “Map Width”

East

Get Variable: Player Position

Calculate: Add 1

West

Get Variable: Player Position

Calculate: Subtract 1

End Menu

Set Variable: Player Position

Note that while we Get Variable in each option, to ensure that we really are dealing with the Player Position, we only Set Variable once at the end. Since the Choose From Menu function passes any result to the next action, we can rely on the correct calculation being applied to our variable in the end. If you’re a fan of redundancy, though, feel free to add Set Variable to the end of each choice (like I did in the example I linked above).

With the Player Position updated, we will now loop back around to the beginning of this diatribe, get the correct room from the list, display it, and start all over. In the briefest possible outline, here is how all of that looks within your Shortcuts program:

List: “Northwest Room”

“North Center Room”

“Northeast Room”

“West Room”

“Center Room”

“East Room”

“Southwest Room”

“South Center Room”

“Southeast Room”

Set Variable: Room Title

Number: 5

Set Variable: Player Position

Repeat: 9999999999999999 times

Get Variable: Room Title

Get Item From List: Item at Index: Player Position

Show Alert: Get Item From List

Choose From Menu: “What direction would you like to go?”

North

Get Variable: Player Position

Calculate: Subtract “Map Width”

South

Get Variable: Player Position

Calculate: Add “Map Width”

East

Get Variable: Player Position

Calculate: Add 1

West

Get Variable: Player Position

Calculate: Subtract 1

End Menu

Set Variable: Player Position

End Repeat

And that, as they say, is that. Every time you select a direction, the loop will reset, grab the new Player Position, and return the relevant room.

Now, obviously, that isn’t the whole story, but you’ve read enough! There are a number of remaining questions that I’ve attempted to answer in the example I linked to at the start of this, and invite you to try and answer in your own version of this:

  1. How do you keep the player from moving out of bounds?

  2. Can you make the limited number of Repeats interesting?

  3. Can you update the exits dynamically, forcing the player into corridors and such?

  4. Can you add elements of interactivity, such as items, puzzles, or enemies?

  5. Can you add graphics?

Happy hunting, my friends. As always, if you have questions or comments about any of this, please reach out! The amount of research being done into this avenue of using Shortcuts seems relatively limited, so I’m curious to hear what thoughts are out there.

Like I said at the start, I’ve also been working on a roguelike game, following similar principles to those outlined above, just… much more complex. I’ll work up a new post about that soon.

GamesTylerShortcuts