Review: TIS-100P29 Jan 2016 0
TIS-100P, from developer Zachtronics of SpaceChem fame, offers similarly neuron-stretching puzzles without the overly friendly graphical interface. This game simulates finding an old computer and becoming obsessed with teaching yourself to program in its assembly-like language with strict memory limits, right down to recommending you print out a physical copy of its manual. There’s a sort of video-gamey plot revealed through reading bugged sectors, involving a portal to another dimension or a cold-war era AI or something, but it’s about as important as the story in Destiny at launch, so don’t worry about it. What matters here are the puzzles, which deliver the joy of solving low-level coding problems without the annoyance of deadlines, grades, or co-workers.
If that sounds to you like something you might not be prepared to appreciate, your trepidation is justified. TIS-100P is far more accessible to those with programming experience than those without. I am not a programmer, though I did take introductory courses in C++ and Java years ago, so I’ll be reviewing it with a specific focus on its appeal to my fellow non-programmers. I also should admit that I want to love this game. I aspire to be the sort of patient, orderly thinker who embraces the explicit rejection of superficiality in favor of puzzles which actually communicate a new pattern of thought. As in so many other domains, I find myself almost adequate.
The central experience of TIS-100P is the assembly of useful chunks out of very simple primitive operations. The earliest example from my own experience was the development of a pattern of programming which approximated an if-then-else statement (yes, the language is low-level enough that it doesn’t even have a general if statement). It does have commands equivalent to “if the number is greater than zero, go to the line that starts like this:”, JGZ, and similarly for less than zero (JLZ) and equal to zero (JEZ). So the following code outputs a one if the number under consideration is zero, and a zero otherwise:
- MOV UP, ACC #Put the input into memory
- JEZ HIT #If the number is zero, go to the line that starts “HIT”
- MOV 0, DOWN #Output zero
- JRO -2 #Move up two lines, thereby checking for a new input and starting anew
- HIT: MOV 1, DOWN #Output one
For me, that was a great start. Once I’d used that basic practice enough, I could stop worrying about it and think in terms of the more comfortable if-then-else statements, knowing I could translate them into TIS-100P-ese once I’d figured out the rest of the problem. Gradually developing ways of thinking about how to program which allow you to make use of your limited cognitive resources to effectively represent processes you just don’t have the capacity to fully understand at the lowest level gives the game a tremendous sense of progression.
After you conceptualize a solution, or several parts of a possible solution you then try to fit together, comes debugging. Debugging is a lot like comforting a baby. On some level, you know the problem has to be simple. There are only a few kinds of things which can go wrong, and you basically just have to try to solve each of them in order. So you feed your program, burp your program, change your program’s diaper, bounce it, and swaddle it in its crib. Oh, crap, you forgot--maybe it needs its pacifier. Fine, try the pacifier. Nope, your program is still crying little red rows in the debugger. You know you fed it--did you check its diaper? You can’t remember, it’s 2am and you haven’t had a night’s sleep in months. Sing your program a song, maybe? Sigh. Okay, try feeding it again, and start the checklist over. On the other side of the analogy, you can step through an input, check that the manipulations are what you wanted and in the right order, and check agreement between high-level plans and low-level implementation. I am mortified by the frequency with which I’d discover my problem just by stepping through a sample input I know perfectly well I stepped through twice already. At least the program never has the problem that it’s so tired that it gets so mad it can’t sleep. Indeed, quite the opposite--TIS-100P is the only game I can remember during which, at the debugging phase, the screen would abruptly go dark as my iPad went to sleep, so intently had I been staring at my inoperative mess without daring to raise a finger.
But when it finally works, the sense of accomplishment rivals a Caribbean vacation in a hard winter. Right up until you see the screen which tells you how many cycles, instructions, and nodes it took other people to accomplish the same task, anyway. It doesn’t heckle you to be better, it just gives you enough information that you can nag yourself into becoming interested in optimization. Nothing hangs on it, but simply by keeping the concept of efficiency cognitively available, TIS-100P gives you just enough encouragement to look for ways to do things faster and simpler. That’s all it takes to help develop an aesthetic appreciation for good code, and the realization that you’ve learned to love a new kind of beauty brings as much satisfaction as solving the puzzles. Even if you’re able to solve everything on your own, there’s much to be gained from looking at the sorts of things others do with their programs, both to appreciate their cleverness and check that you aren’t falling into bad habits.
As heartwarming as it is to succeed, and to find my mind developing as a result of playing, possibly my favorite moment playing TIS-100P came from finding a bug in the game. If you paste without having copied, the game crashes right to the home screen. It felt so good to turn the tables on the app that had been telling me about my blunders so consistently! Didn’t even matter that it was completely unimportant. Other than that, my two concerns with the game are different ways that it commits too heavily to its premise. The interface is periodically aggravating in a way that seems appropriate to simulating an old computer--for example, you have to hold down a modifier key while typing to get numbers. Given that I’m often using the iPad one-handed, on a couch, that’s annoying, and Apple already has a perfectly good solution of letting the modifier key tap happen before the modified key. Similarly, the comma is one space off from the Apple keyboard, so those of us who actually type a lot have an unnecessary period of adjustment.
More serious and central to the game is a problem I had with its predecessor, as well, which is that all of the progression happens in your head. It would seem to me much more natural to have puzzles which consist of finding a way to do something, and then allowing you to effectively call your earlier function without having to rewrite it. This would let you focus on the abstraction rather than being concerned with memory limits and such, so it would make certain problems much easier, but would also open up more complicated problems. Because that isn’t the way this game works, later, more complicated tasks require much more complicated solutions which put an increasing drain on your working memory. It violates my (admittedly idiosyncratic) views on fair play to add a new kind of requirement partway through a game. Some day I should write a feature on my opposition to quick-time events on this basis, but my feelings on this issue are strong enough, and this review already long enough, that I’ll hold off on indulging that pet peeve.
I admire TIS-100P more than I like it, but only because I esteem it so highly. Teaching many of the basics of programming as a game, without adding frills to make that more palatable, is the sort of challenge most would regard as slightly mad. Zachtronics pulled it off; TIS-100P is a marvelously rewarding experience if you work at it enough. My recommendation to fellow non-programmers is to download the manual and give it a read--that should be your first step in playing the game, anyway. If that doesn't put you off, by all means, dive in and think hard. If you find yourself getting frustrated enough that you fear you might abandon it, check out the TIS-100 subreddit, and even go so far as to look at the solutions of others, but don't copy anything. Look at a program until you understand it; that should suffice to give you what you need to finish your own, while ensuring that you get the benefit of appreciating the elegance and complexity involved. Better yet, just start learning an actual programming language, like C# or Swift.