Once upon a time, I played a game called SHENZHEN I/O. I wrote some blog posts about it (1, 2, 3, 4), but stopped after a while. This wasn’t due to me getting bored with the game. On the contrary. I was writing my posts as I went, but the game was so much fun that I didn’t want to take breaks in between puzzles in order to write about them for my blog. I have in fact long since completed the main storyline, but I just haven’t found the motivation to write about it.
So, enter TIS-100. Also developed by Zachtronics, this is essentially the predecessor to SHENZHEN I/O. I’ve been playing this game recently, and I figured this one would be interesting to write about as well. This time, however, I’m writing about it after the fact. Which hopefully means I’ll be seeing this one through to the end. I’m also taking a bit of a different approach: I won’t be explaining the game mechanics too much; rather, I’ll just present and discuss my solutions to the puzzles. If you’re looking for a tutorial on the TIS-100, I suggest you RTFM instead.
Enough rambling. Join me as I set out to repair the TIS-100, and uncover its dark secrets.
Segment 00150: self-test diagnostic
This is your super easy tutorial level to lure you in and boost your confidence, before you get crushed by the later puzzles. There’s absolutely nothing interesting going on here. All you do is use the MOV instruction to pass variables from one end to the other, unaltered.
There’s a silly achievement (“BUSY_LOOP”) that you can get for solving this in more than 100.000 cycles. For reference, the solution above runs in 83 cycles. The easiest way of doing this is to, well, simply create a loop. In my case, I’m having one of the nodes slowly count down from 250 to zero using a whole bunch of unnecessary instructions, before passing the next value along.
This gets me just above the needed 100.000 cycles. I suppose it’s quite easy to reach well into the millions, but I honestly have no intention of finding out.
Segment 10981: signal amplifier
Again, a tutorial puzzle, this time to introduce us to the ACC register, and how to manipulate it.
This solution runs in 160 cycles. There’s an achievement (“PARALLELIZE”) for getting it down below 100 cycles. I don’t normally go for these types of achievements, but in this case doing so is pretty trivial by exploiting the powerful ANY pseudo-port.
Doubling the number is the bottleneck in this little program, but we can speed the overall program up by having two different nodes work on this in parallel. The ANY pseudo-port in the last node means it will take the first available value available on any port, which in this case means the first value outputted by either doubling node. And even though we’re doing things in parallel here, there’s no need to worry about the values getting out-of-sequence, because the doubling nodes each take the same amount of time to do their work. As such, the first value that gets sent to either doubling node will also be the first value that gets sent back out.
This trick gets the solution down to 84 cycles, which is enough to earn the achievement. Yay!
Segment 20176: differential converter
Here we are introduced to the arcane art of subtracting numbers. The solution is pretty straightforward once you realize that B - A = -(A - B) and also there is a convenient NEG instruction.
Segment 21340: signal comparator
We simply pass the value along to the three nodes, and output one when their condition is met, and zero otherwise. For this we use (un)conditional JMP instructions.
Segment 22280: signal multiplexer
Another easy math puzzle. The trick to this one is realizing you can always output A + B, as long as you make sure to substitute zero for A or B under certain conditions. So here, the nodes reading A or B will output A or B respectively, or zero, depending on the value from S. All that remains after that point is to simply output A + B.