The Making of A Night in Algiers

06/30/2021

Background

In junior year of high school I chose to write my independent thesis on Albert Camus' The Stranger. I may have picked it because it was the shortest book on the list, but I found it captivating and frustrating and was very pleased with my decision. I wrote my paper, and then I set out on the second part of the assignment: a creative companion to our thesis, dubbed the “June Project.” I decided I would make a little old-school text adventure where you play as Meursault in the world of the novel.

With no experience and a looming deadline, I threw together a python script that takes commands and reads an extremely convoluted JSON file to find the right response. It worked … enough. Thankfully, it didn't crash during my presentation and the class was reasonably entertained. It had some quirks that always bugged me, though, and I've wanted to return to the project and do it properly ever since. So after my string of fixing up and publishing my Unity remakes, I thought I'd try a new direction and rebuild the game from scratch. I'm really happy I finally returned to this project and I'm really happy with how it came out.

The Thesis

My goal for the game was for it to be an exercise in absurdism similar to the novel. The way I achieve that spoils the game, so read on at your own risk: The basic assumption of a game is that it has some sort of objective, but this one has none. The player is presented with items to inspect and rooms to explore, but no set of actions will lead to a satisfying conclusion. Many actions will lead to discoveries and to opportunities for more actions, but in the end none of the paths they can take will stop the prompts for another typed input. The only way to “beat” the game is to quit. It is meaningless, and can only truly be enjoyed once you accept that. I think this quite nicely encapsulates the absurdist idea that to find understanding and contentment, you must stop searching for them.

The Goal

So that's what I was going for. I wanted to do it with a black screen and some green text. I was pretty happy with the general structure of the original game and the way it used exact quotes from the book. The main thing I wanted to fix was that the old version wasn't very responsive to the player's actions. For example, say there's a key lying in on the street. Once the player takes the key, if the player looks at the street again, the part about the key being there would still appear. The responses were all “dumb” strings in a dictionary; they couldn't change based on the context. I figured the best way to fix that would be to use a platform designed for interactive fiction. So I started looking for one that would fit the project.

The Search

There are lots of really neat engines out there for writing interactive fiction which have been around for years and have active communities online still offering support and guidance for how to use their many powerful features. So of course I ended up making my own. I promise, I really tried to not make it myself. But Inform7 and TADS are just both so enormous. All I wanted was a simple little game without any score, carry limits, or underwater rooms, and I wanted it to look and behave exactly as I had pictured it. Those big engines are great, but they assumed too much about how I wanted the game to work. And their gargantuan manuals didn't help either. Back in junior year, my English teacher once wrote on an assignment of mine “Learn to dance with the partner standing in front of you, not the one you think might be better.” It appears I have yet to take his advice.

Right before I gave up on preexisting engines, though, I found one that just almost fit the bill. It's called TAME and it's very interesting, but development seems to have stopped a while ago and it's not quite fleshed out the way I'd like. I tried to fork it and make some changes myself but it's written in some very opaque java and I had to give up. I really liked the development flow it used, and it strongly influenced the way the game architecture turned out.

The Result

The main thing I took from TAME is the idea that every command word the player can use (look, take, use, etc.) corresponds to a method stored in a dictionary on a World object. Those methods can then use that command string to call another corresponding method stored in dictionaries on objects in the scene. This gives the developer complete control over what commands their game uses, and what each of them do. I also took my classifications of commands from TAME. Commands are either intransitive, transitive, or ditransitive. Intransitive commands (look, help, inv) are run just at the World level. Transitive commands (take, talk, examine) have targets, so the World method will find the target object and call the corresponding method stored on that object. Ditransitive commands (give, use) involve two items. The World method will find the first and call its corresponding method, passing the second as a parameter.

Classifying commands like this does limit the understanding of the game's parser, but that was just fine for the game I envisioned. It also made writing the parser way easier. All it really does is check that the first word is a valid command, and then based on the command type check the following words for valid, accessible, items or correct prepositions. They have to be exact and precise, but I think that just adds to the retro experience I'm trying to create.

My favorite thing about the system, though, is that it works. When the player takes the key, the key disappears from the description of the street. What the player does in one room affects what happens in another. I created the tools I needed to make what I wanted to make, and it actually works exactly as intended. That in itself makes me very happy.

Working with Dotnet

I chose to write this project in C# because I knew I would need the benefits of a statically typed language to keep everything organized and I didn't want to add learning a new language to the list of challenges I was taking on with this project. I had never worked with C# outside of Unity, though, so this was my first introduction to dotnet. It was a very new workflow for me and understanding how to actually get this thing running was probably the hardest part, especially when using Blazor. However, it was totally worth it to see the same code run in the terminal and on a web page. There's no way I could build anything myself to get this game running on the web short of rewriting it in JavaScript, so using dotnet was a good reminder that I really should be more open to learning how to use established, powerful, useful tools even if it seems intimidating to learn or if I want to make things from scratch.

Active vs Reactive

Another lesson I learned from this project is that planning is important. I'm not really one for making outlines – of papers, stories, games, etc. – I usually just dive in to it and see where my instincts take me. Sometimes this works out for me, and sometimes not. I think for a project like this where I have to make decisions at the beginning that will affect how everything else down the line will function, I should really think harder about those decisions. Building this system, I would constantly run into problems in the way I was implementing some feature, make a change, and then spend an hour dealing with the ramifications of that change. Then, most of that hour's work would need to be redone again the next time around. It left me feeling that I wasn't actively shaping the project, but rather constantly reacting to changes and problems that kept cropping up. Sitting down at the beginning and taking me time to plan out the framework of how this system would work would have saved me a lot of time and effort down the line.

The Future

I think the Algiers namespace actually has potential. It has good a good amount of built-in features, but extra functionality can be added in a few ways. You could directly add to the namespace, and hopefully I've written it to be clear and accessible enough for that to be a relatively painless thing to do. I think a lot of neat things can also be done just be wrapping functionality in classes that extend GameObject, in functions that store commonly used behavior, or in higher-order functions that take the world's, the player's, or an item's state as a parameter. Even just placing logic in a separate file can help to remind that the developer has the whole power of C# at their fingers. The Salamano class demonstrates a way that rooms and items can be built on the fly based on the player's progress, and escapes the formulaic patterns that crop up in the main game file. I will definitely be returning to this project at some point to really put the system through its paces.

Tags: Game Development, Algiers