In which we spend a weekend making something.
Solo and Scoped Down
As is my tradition, traveled to Cleveland Ohio to take part in their game jam gathering. It’s a great group; a little larger each year, which is good, but still very friendly and helpful.
Since I was acting as an organizer this time, I was unsure if I’d actually be able to contribute at all, so I turned down any invitations to join a team. Knowing that I’d be working by myself, I also kept the scope incredibly small.
One way to keep it simple was to eject graphics and sound entirely. One way to keep it interesting was to make it a multiplayer game. One of the GGJ 2017 Diversifiers, “Crowd Control”, called for an eight-player game; this piqued my interest, so I committed to that.
In the interest of being able to play around with some relatively unfamiliar tech, I decided to do a play-by-SMS game. Players would send text messages with their commands to a common phone number, and get responses the same way to let them know their current state.
The day job had led me to be familiar with a service called Twilio, which allows you to set up a phone number and have the messages sent to an HTTP endpoint, which can then be responded to via their API. They have many other services as well, but simple SMS response stuff is all I needed for this game.
A free account at Twilio would do most of what I needed, but would take up some of the text space with “Sent from a Twilio trial account”; so I made a paid account and threw $50 into it, hoping that would last long enough for the Jam.
Fight The Tide
After the theme (“Waves”) was announced, I pretty quickly came up with the premise: an eight-player brawl on the beach, with players chasing and kicking each other. As the waves recede, the players' feet are freed up to do more damage, but when the waves come crashing in they’ll knock over players who aren’t prepared for it.
Why are they just kicking? Maybe they’re in handcuffs; maybe it’s a prison break and there’s only room on the boat for one. Without needing art assets, the premise can be very flexible.
Running in the Cloud
I definitely didn’t want the game server running on my laptop; I couldn’t guarantee that it would be online all the time, let alone accessible from Twilio’s servers. So I spun up a free t2.micro instance on AWS to host the server. It had a clone of the GitLab repo, so I could do development either directly on the instance or on my laptop.
Interesting trade-offs always arise from cloud security. In the case of this game server, I opted for:
- SSH access from the IPs at the local GGJ site (and therefore me).
- Webserver running on a nonstandard port open to the world (and therefore Twilio and me).
Following some of Twilio’s examples, I set up Sinatra to handle the web requests, and pointed Twilio at the server.
In order to send messages, I would need to utilize my Twilio API keys, which needed to be kept secret (because they would give someone the ability to cost me money). In the code (which is in a public repository) I just call out to OS environment variables, which I set with a separate script that wasn’t in source control.
Beware. Ugly Ruby code ahead.
Phase One: One-player RPS
As a first step to prove out my integration with Twilio, I implemented a quick-and-dirty rock, paper, scissors game:
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
Phase Two: Two-player RPS
Now handling two players, differentiated by their phone numbers:
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
Phase Three: Fight on the Beach
Between my organizer duties and getting a little bit of sleep, I established the actual game.
Once the server is launched, it waits until it’s been contacted by at least eight players, then broadcasts the available commands to everyone.
134 135 136 137 138
The players are each placed into a blank space in the 2d grid (only one player may be in any square at a time).
Each turn, each player receives a description from their current point of view, e.g.
Each player enters their command; when all commands are received, the results are sent out to the affected players.
120 121 122 123 124 125 126 127 128 129 130 131 132 133
dummies_move, you ask? Since I didn’t have eight phones or enough teammates to help
constantly test the thing, I needed bots. No fancy AI, they just issue a move completely at
random each turn.
237 238 239 240 241 242 243
Phase Four: Map and Status Screens
I was playing with two phones most of the time to check my work, but it became clear that I needed a better way to see what was going on with all of the players. So I implemented a quick map using code I’m definitely not proud of:
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
etc etc etc
…to give me something like this:
1 2 3 4 5 6 7 8 9 10 11 12
To get a better way to demonstrate the game, I made a “status” page to display the last few lines of each player’s log as well as the map:
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
I was able to get at least that much done, so I had something to show off at the end of the Jam. I convinced eight people to text in and play for a few minutes, so I’ll call that success!
Code is unmaintainable.
One player can hold up the game indefinitely.
Once a game is over, it doesn’t restart.
Occasional delivery failures are not handled.
I’ll have to decide if it’s worth revisiting this game and addressing those issues. Tomorrow.