EXAPUNKS Finished! Here’s my solutions…

Okay, I have been working on EXAPUNKS the last few weekends, and dreaming about it most nights. But I’m done with the main plot; got the achievement for proof, and I’m going to exorcise the game by writing down how I solved each puzzle.

First, some of my solutions are optimal, some are terrible, most fall somewhere in between. The first rule of programming is to get something working. Once you have an implementation, then you can go back and refactor; many times, your first pass is good enough. My boss used to tell me not to let the perfect be the enemy of the good; a good solution that produces the desired results is better than a perfect solution that is never finished. You’ll see what I mean by that when I get to some of my solutions.

Euclid’s Pizza (Order System)

After each puzzle, you can choose to make a GIF of your solution. It shows in a general way how your solution works, and how many cycles it took in the worst case (so, how fast your solution is), the size, in instructions, and the number of times an EXA crossed from one host to another. Most solutions won’t be perfect for every area. For instance, in this puzzle, I was able to get the cycles down to 13 by unrolling the two loops, but it increased the size slightly.

This solution used two EXAS, one to read the pizza order and the other to jump into the pizza shop’s mainframe and add what the first sent to the end of the list. It’s just copying five values.

There is an achievement for sending an EXA into host 805 and cycling the power.

Mitsuzen HDI-10 (Left Arm)

The framing plot for EXAPUNKS is that the main character, Moss, has been infected with a disease called “the Phage”, that slowly transforms nerves into digital circuits. This is always fatal. The Mitsuzen puzzles all deal with you writing programs to rebuild the connections between your bio parts and your new mech parts.

In this, XA stays home and bounds checks the values coming from the #NERV, and copies them to XB, which has traveled to the the destination and just copies what it receives to the destination nerve.

If only all the puzzles would be this easy…

Last Stop Snaxnet (Factory 11)

The repercussions of this hack will shake the world, as you go into the Peanut Blast ovens to remove the peanuts from their signature snacks.

This puzzle asks you to look for, and remove, the word “PEANUTS” in the ingredient list. Since the EXA language doesn’t have string literals, you have to read the word into the X register before moving into the assembly line. The GIF shows a solution using two EXAs, but it can be done with one. Not sure why I used two.

Zebros Copies (Point-of-Sale System)

This puzzle requires some careful communication between EXAS, and is the first time it’s become important to know if we’re sharing information globally, anyone can talk to anyone, or locally, only EXAS in the same host can talk.

One EXA runs immediately to the host with the #DATE and writes it to the global memory. One EXA reads the account number we are zeroing from the file in the main host, then jumps into the copy shop computer and searches for the outstanding balance for the user ID it just read. The third EXA opens the transaction log. The second and third EXA communicate LOCALLY the information about the account’s current balance. The second EXA then zeroes out the balance, while the third EXA reads the global date value the first EXA set up.

There is an achievement for making all the copy machines continually copy.

SFCTA Highway Sign #4902 (Remote Access Interface)

One EXA reads the characters, the second EXA writes them. The second EXA is iterating the characters in the X register, then used the SWIZ command to set the row and column to place the character. Usually, a programmer would use the DIV and MOD operators to get this information, but might as well get familiar with the SWIZ command (which extracts and reformats individual digits of a value). We’ll be using it more later.

Unknown Network 1 (Unknown Context)

This is our first adventure into hacking a Russian network. We’ll be seeing it again a few times. This puzzle uses replication to track down a file in the leaf node of this binary tree — the final puzzle of the main game is topologically similar to this. At each node, each EXA makes two copies of itself, one that will jump to link 800 and one to jump to link 801. It then attempts to kill a foreign EXA in its node, grab the file it was holding, then link backward to the starting host.

If any of the EXAs fail at linking or file grabbing, they terminate, so only the one EXA that can succeed at all those things lives until the end. EXAs that die drop whatever they’re holding, so there’s no need to explicitly drop the file in the home host.

UC Berkeley (EECS Department)

Universities really want games off their mainframes, and Berkeley is no exception. You’re sure you can hunt one down.

The name of the host to look for is the first record in the file in the host. The first EXA stays behind for later, while the second EXA travels from host to host looking for the correct tape drive. Since the EXA will always eventually find it, there’s no need to worry about infinitely looping forever.

Once found, it checks the tape for the location of the record named the second string in the host file. That given, the first drops the host file and makes a new file and copies all information sent by the second EXA into it. Since the data will never contain a 0, when that is sent by the second EXA, the first EXA knows it is done and exits.

Clearing this puzzle unlocks “пасьянс” — solitaire. There is an achievement for winning this once, and another for winning it a lot. I played it once. It’s just Freecell Solitaire.

WorkHouse (Work Management System)

WorkHouse is a Mechanical Turk-like job shop where people can do small tasks for small money. Your AI friend has been making some money on the side by doing these tasks, but has done too many, too fast, and your job is to run in there and make the pace seem more human-ish.

EXA #1 reads the AI’s “NORMALHUMAN” handle to the global channel. EXA #2 scans the user file for that ID and sends the file ID for the AI to EXA #3. EXA #3 sums up the values in the AI’s file, then while that sum is > 75, writes “75” to the file, subtracts 75, and loops, finally writing the remainder. There will always be more new entries than old, so no worries about truncating the file.

Equity First Bank (San Francisco)

Fairly straightforward. EXA jumps outside the ATM hosts, then replicates itself four times, and all five EXAs then go into their ATM, determine how many twenties the machine holds, then dispenses them all.

Mitsuzen HDI-10 (Heart)

We’re back in the body again, this time trying to keep the heart going. Things aren’t going well. Luckily, this is an easy one again. EXA #1 keeps reading from the CNS nerve. The 10s digit of this value is the number of rows to write, which is always at least 3. EXAs #2 and #3 head to their spots and write out the first two rows, which are always the same. Then they read, from the host, the number of additional rows to write, which again are always the same.

Trash World News (Unknown Context)

This puzzle replaces suspicious words in an e-mail with less-suspicious words. EXA #1 reads each old/new word pair and creates a new EXA to scan the e-mail and replace any match with the new word, and then exit. It goes through this process once for each word. EXA #1 then wipes its file and exits. A third EXA just carries a file from the central host to the outbox.

KGOG-TV (Programming Hub)

This is the first hacker battle we encounter. Mutex8021 isn’t a very formidable opponent; he just drops two tapes into two VCRs and exits. One of our EXAs replicates to carry our tapes into the channels, while the other carries mutex’s out again.

TEC RedShift (Development Kit)

This is a brute force password hack. It just keeps counting upward from zero, using this SWIZ command to break the count into three digits. After each try, it replicates a new EXA to try and link to the locked host, send the successful password and the devkit ID from the file it finds.

A second EXA is sitting waiting for a communication from a successful entry. When an EXA signals from the locked host, it grabs the current password, kills the first EXA, copies the password into the new file, copies the the devkit ID, then drops it back home.

This unlocks the RedShift Homebrew, which lets you make your own games if you are very, very patient. I made a Pong. It was painful. Actually it was just the paddles.

Digital Library Project (Patron Access System)

Fairly straightforward, again. Home EXA reads a list of codes that encode both the host that contains the desired book, and the file ID of that book. For each, it replicates a new EXA to go to that host. Once found, each of those EXAs replicates another EXA to make a new file containing the contents found. They talk a bit, all in LOCAL memory mode, then the copier EXA keeps linking back toward home until it can link no more, dropping its book at home.

TEC EXA-Blaster Modem (Radio Stations)

I went through a few iterations on this one. EXA #1 grabs the file with phone numbers and continually dials numbers. EXA #2 copies the song title and artist from the other file into its registers, drops that, then moves into the dialer, continually replicating new EXAs that will jump into any new connection immediately, and then replicates yet another EXA to rewrite the file it finds there.

Emerson’s Guide (StreetSmarts GIS Database)

This simple puzzle sets up a more complicated one later. The first EXA copies the name of a restaurant into the X register, then sends the relative grid coordinates of the file that contains the restaurant ratings to a second EXA. The second EXA travels to the location, scans to the correct entry, reads the string literal for a star (“*”) into a register, then writes that four more times into the file, turning a one star rating into a five star rating. All the EXAs then die.

Valhalla (=plastered)

This is the second hacker battle. All the hosts are simply connected, and the opponent has only a single EXA that just races through all the hosts, claiming ownership of each one. Since ten EXAs are available, we just replicate an EXA at each host that just sits there and takes control back in a loop. Easy win.

Mitsuzen HDI-10 (Left Hand)

Back to hacking our own body again. My solution was not optimal; too large, too much activity, but it worked. It’s a little frustrating because I can see from the leader board that there’s a better solution out there.

The problem is sending communications in a couple directions without crosstalk. I tried to synchronize things such that the global channel would always have the right EXA listening for the EXA that was sending, and it would just be calm and cool. And I believe the better solutions do just that.

My solution sends an EXA to the transmitting host and that replicates a carrier to bring the value to the receiving host, where it dies. This continues forever.

Sawayama WonderDisc (Drive Controller)

This one is a filter that takes data and replaces any non-numeric data it comes across with the value from the file in the home host.

The first EXA sends the authentication password to #AUTH (this value is in the Trash World News) and reads the desired region code into the X register. It then replicates an EXA to read the desired #TRAK and head into the locked area to retrieve it. A second EXA heads to the delivery area and creates a new file with the contents of the old track, replacing any non-numeric data it receives with the data in its X register (which it has from being replicated from the first EXA). Once the file is transferred, the delivery EXA drops off the file (which is gathered automatically by a processor-sent EXA), then returns to the central host to tell the main EXA to get the next track, and it continues from there.

There is an achievement for killing the processor-sent EXA when it pops out to grab the dropped track.

Completing this unlocks the Hack Match minigame, a matching block puzzle. The instructions are in Japanese, but it’s easy enough to figure it out from trial and error.

Alliance Power and Light (StreetSmarts GIS Database)

You’re looking for two hosts, the names of which are in the file in the base. The plan is to go to the upper left corner, and then replicate two EXAs, one for each host, that will self-replicate copies going east and south, then check to see if their host is the one they need. Turning off the power to that host immediately will prevent the other EXA from searching through it for the other host, so both EXAs, when they find their host, wait for a signal from the main that tells them it is okay to turn off the power.

Turning off the power of all cells triggers an achievement.

Deadlock’s Domain (deadlock)

The third hacker battle. The opponent, Deadlock, sends one EXA outside of their base that controls the rest of the fight. Kill that first, and then there is no competition to bringing the files back to your base host.

XTreme League Baseball (Player Database)

My solution was faster than average, but larger than average, too.

This is a three EXA solution. The first EXA stays at home, receiving player and score information and making sure to keep only the highest score. The second EXA jumps into the player directory and spawns copies of a third EXA that goes to the player file, calculates the score, and sends the results to the main EXA back at home.

Since there’s a lot of partial calculations, the calc bots store the partial calculations at the end of the player file, then clean them up as they finish the calculation. I’m not super sure how to improve on this, but it was at or above average on two-thirds of the metrics so not super worried.

Having an EXA continually run the bases gives an achievement.

King’s Ransom Online (US West Realm)

This won’t be the last time we will hack the King’s Ransom Online MMO. The task is to replace every occurrence of the player ID that is not the one given by the file in the base host, with that given player ID.

The first EXA just reads that file and sends out the player ID there six times — one for each realm host — through global memory.

The second EXA spawns the six malefactors that go to each realm, kill the player EXAs (maximum of three in a room), grabs the new player ID from global memory, and then, starting with file 200, changes the ownership of the item, and then spawns further EXAs to grab the files referenced at the end of the 200 file and change those ownerships too.

KGOG-TV (Satellite Uplink)

This was not an optimal solution. I think I was worse than average on every metric. You’ll probably do better.

I made two EXAs to go set the azimuth, elevation and frequency of the satellite dish, and then die. The main EXA then dropped the file with those values and picked up the file with the outgoing video data and spawned another EXA to go into the secure host and start getting ready to encode. A third EXA would sit in the broadcast host and get ready to send encoded data.

The data is added to the next encoding value, and if the sum is greater than or equal to 10,000, then 10,000 must be subtracted. This is made more difficult because adding two numbers that end with a sum over 9,999 is an error, and so I proactively subtract 10,000 from the data. If the result after adding the encoding is positive, then we’re good. Otherwise, I add the 10,000 back — in two steps, of 9,999 and 1, since you can’t specify a five digit value in EXAPUNKS.

Again, this solution was bad in all metrics, but… it worked.

Equity First Bank (San Francisco – ATMs Offline)

My solution here was below average by all metrics. Two EXAs just bring the new checking account (file 300) and the file containing the words CREDIT and DEBIT (file 301) to the checking account area. The third EXA reads through the file of customer IDs, and spawns one EXA to read the customer ID and record a transfer to the AI account, and another EXA to read that file and then mark a credit for that amount — one dollar — to the AI account file. Finally, after waiting for a time to make sure the child AIs are done with the file, the third EXA continues to the next ID, finally appending file ID 300 to the end of the file and cleaning up.

I probably should have implemented this with one EXA doing all the debits and one doing all the credits with no waiting around. Maybe next time.

Completing this unlocks the ability to write your own puzzles.

The Wormhole (x10x10x)

This hacker battle is just a race to see who can replicate bots fastest. I wrote seven bots that just slammed their way around the map in the fastest way possible — no loops — and once they had made their progeny, just sat there and replicated. That’s all it takes to win this battle.

TEC EXA-Blaster Modem (Dataphone Network)

My solution was slower than average, smaller than average, and made as many trips as average. So, it’s fine. I find that whenever I have to resort to adding NOOPs to my code to make the timings come out right, that means I have missed something important. I missed something important here. But it’s fine.

The graphic doesn’t reflect the current state of my solution. In the current state, the sole EXA grabs the 300 file containing the first number, jumps to the dialer, and for each entry in the file, dials that number and spawns an EXA that is to follow a valid connection into a destination host. If the number did not correspond to a valid host, then it fails to link and dies. The dialer waits a few cycles for a response from the spawned EXA, and if it gets one, it copies the phone numbers that EXA finds in the host to the end of the file it is holding. It then continues on until all is done.

I’m honestly unsure how I could make this faster.

Last Stop SnaxNet (Warehouse 27)

Fast food chains often find themselves having to purify nuclear fuel in order to build a bomb to tear a hole in reality. Super common.

My solution, which is average or better than average in all metrics, is to have an EXA go into the host with all the pressure sensors for the centrifuges, find which one is the maximum, then spawn an EXA to power that one down. This continues until the max pressure is zero, which happens when all the centrifuges have been powered down.

I originally thought I could just sort all of the values at once and then spawn an EXA to kill them all in the right order, but the order changes each time a centrifuge is powered down. I got a chance to use that sort later, though.

Mitsuzen HDI-10 (Visual Cortex)

Back into the body, this time fixing the eye. There’s a calculation that needs to be performed at each node, and since there is no concept of a procedure call in EXAPUNKS, I spawn a EXA at each node to do that calculation. Once done, it is transmitted via global memory to the EXA sitting at the output.

It would probably be faster to just transfer all the values to the receiver and let it do its own calculations. Actually, let me try that… okay that was faster, but larger.

Let’s try just sending out nine individual EXAs, one for each node. One of them will have to make the receiver, since we only have room for nine EXAs to start and we need ten total. Nope, don’t have enough code space. Moving on…

Holman Dynamics (Sales System)

Not sure why I didn’t make a graphic for this one. But it’s boring. My eventual solution of the three or so I tried hit the averages for size, cycles and activity.

One EXA stays behind to copy the valid credit card number to a file at home. One EXA links to the host just outside of the one containing the junk file, and one gets the junk file and drops it at the feet of the second EXA.

That EXA starts at 0 and increments the starting point for a newly spawned EXA to see if the 16 characters starting at that point represent a valid credit card number, according to the rules in the Trash World News. They send a success or failure message to their spawner and despawns. If this is a valid number, the spawner grabs the junk file, brings it back to its starting location, sends the digits back home in global memory, and then despawns.

Aberdeen

The last Hacker Battle. I didn’t find any good solutions to this one. Try to occupy the two safe hosts ASAP and then try to keep two EXAs on every host. This wins 70% of the time, but is pretty far from 100%, as for all the others.

U.S. Government (FEMA Genetic Database)

I took a long break between the previous puzzle and this one. I was just getting too obsessed; it wasn’t healthy.

In this one, we use a tape drive system to read genetic data about a politician and overwrite another politician’s data with that data to prove the second is a clone of the first. The data is scattered all over the place, and the game warns that the data you’re reading and the data you’re writing could be in the same file, so to make things simple, I spawn an EXA that knows how to find data, and as it finds data, it spawns a reader to copy the data to the file it carries, until it has a full record. Then the overseer does things in reverse for the next, sending the seeker out to find the data, but writing data from the file it holds instead.

It’s basic but not really elegant. These later puzzles, I didn’t spend much time figuring out the best way. I just wanted to finish, at this point.

Unknown Network 2 (Unknown Context)

We’re back in Russia again, attacking a rival AI. We need to kill all the enemy EXAs in the central area so that they drop their files, then iterate through all the possible file IDs from 200-299 and, if any are found, bring them back to the base host.

We must then kill all the remaining EXAs. Killing any EXA in a host blocks progress forward, so this must be done as the last step. Killing any EXA makes the remaining EXA in the pair start madly killing YOUR EXAs, so you can’t have an EXA do two KILLs and then skip out — it will be dead by then.

My solution was to leave a timed EXA behind in each host on the way out, It would wait two cycles, then do two KILLs and exit.

TEC EXA-Blaster Modem (Pager Network)

This GIF for this one won’t load into this post. Too big, I guess.

In this one, we’re given a list of page numbers and a message display on them, which is easy enough. The issue is that the pages must be sent on exactly the same cycle. I could figure out the timings if the messages for each run were the same length, but they are not.

My solution was to set everything up on a first pass, then do a second pass where I dialed up the pagers again and told them how many cycles to wait until sending the message they’d queued up, based on how many more pagers I had to contact. It took something like 26 cycles to contact each pager, and so that was the calculation. One cycle after I talked to the last pager, every pager rang. It was fun.

Mitsuzen HDI-10 (Cerebral Cortex)

The last puzzle in the main game. In this one, you have to sort all the inputs of nerves in a binary tree configuration by their host name, low to high. Sorting isn’t an issue; I’d already done a bubble sort earlier.

The problem was getting all the data in one file to sort. I’d always get crosstalk as multiple EXAs tried to talk at the same time. I finally made a one-way equation that would give wildly different delay times to each EXA so that there was no way they would ever collide. I had to fiddle with the timings bunches of times to get through the hundred test cases. My final solution was smaller than average — by a lot — the activity was average, but the cycles at the end were… 33,743, while the average seems to be somewhere around 1000.

I’m not happy with that. But it worked, in the end. It was hacky, but this is a game for hackers, right?

I wouldn’t show many of my solutions to these puzzles to my boss at work, though.

That finishes the main puzzle arc. There are four additional puzzles that are unlocked once you get through the main plot. I haven’t done those, yet, but they look fun.

If you want to compete against my scores, my Steam ID is “tipadaknife”. Good luck 🙂