My Best Exapunks Solutions
I've been playing a lot of Exapunks recently and been enjoying it. I love the complex simplicity of Zachtronics games and this one is no exception - allowing you to program in an assembly-like language.
Some of these get pretty hard and require a certain insight to accomplish them but that makes solving them so much more satisfying.
In this post I'll be holding my solutions to all puzzles in Exapunks. Hopefully it helps you get unstuck or shares some new ways of solving things.
A few caveats:
- This is a best effort, work in progress so not all solutions may be up yet
- No guarantee that these are "optimal" though I'll try to share my best solutions anyway
Exapunks Puzzle Solutions
For this challenge, I decided to create 3 exas with their own job:
- DateReader - Navigates to Clock and reads / messages the date
- PayWriter - Navigates to the payment log (201) and listens for messages to write out the fake payment
- DebtReader - Navigates to the customer database to find, read, and void the debt to clear
NOTE DATEREADER LINK 800 LINK 801 COPY #DATE M HALT
NOTE PAYWRITER LINK 800 GRAB 201 SEEK 9999 COPY M F ; DATE MODE COPY M F ; USERID COPY M F ; DOLLARS COPY M F ; CENTS DROP HALT
NOTE DEBTREADER GRAB 300 COPY F X DROP LINK 800 GRAB 200 MARK SCANLOOP TEST F = X FJMP SCANLOOP COPY X M ; USERID COPY F M ; DOLLARS COPY F M ; CENTS SEEK -2 COPY 0 F COPY 0 F HALT
SFCTA Highway Sign #4902
For this solution, I split the process into two exas:
- Messagereader - Picks up the input file data and messages it out via M
- Signwriter - Keeps track of the rows / cols (3 rows of 9 cols) and writes out (row, col, char) to the sign's #data
- Keeping track of rows, cols - this is actually kinda hard using only a few registers. I decided to basically keep track of the number of grids we've used in total and then working back from there to determine the row / col we must be at.
- Row = RowColCount / 9
- Col = RowColCount - (9 * Row)
NOTE MESSAGEREADER GRAB 300 MARK READMESSAGE COPY F M TEST EOF FJMP READMESSAGE HALT
NOTE SIGNWRITER LINK 800 NOTE FILEWRITE NOTE ROW, COL, CHAR MARK FILEWRITE DIVI X 9 T ; T = ROW COPY T #DATA MULI 9 T T SUBI X T T ; T = COL COPY T #DATA COPY M #DATA ADDI X 1 X TEST X = 27 FJMP FILEWRITE HALT
Unknown Network 1
For this solution, we just use 1 exa that recursively spawns itself for a "tree-like" search:
- Searcher - For 4 levels (depth of tree), spawns a new exa to search right (801) and itself searches left (800). At 4 levels we are at a "leaf" where the target exa and file might live so we kill and grab the file (this kills off all incorrect exas due to no file error). Finally we return with the file.
- Kill - It took me awhile to realize this was a function. It's in the booklet but no hints lead you there.
- REPL - This is actually a really cool function and I'm betting we'll do some more complicated recursive stuff w it in the future.
- GRAB and Errors - It's interesting that here we actually use errors to help us destroy our unnecessary exas. I bet this will be a common tactic throughout the game.
NOTE SEARCHER LINK 800 NOTE SEARCH MARK SEARCH ADDI X 1 X TEST X = 4 TJMP KILLANDFETCH REPL SEARCHR MARK SEARCHL LINK 800 JUMP SEARCH MARK SEARCHR LINK 801 JUMP SEARCH MARK KILLANDFETCH KILL GRAB 276 LINK -1 LINK -1 LINK -1 LINK -1
For this solution, we use two exas:
- FileFinder - Finds and reads the target file and section of files
- HostSendWrite - This is a helper bot that both sends data to support FileFinder but also receives the target data to write out to our host
- Syncing messages between FileFinder and HostSendWrite - Ideally we'd be able to peek() messages in M in a non-destructive manner but I haven't found a way to do that. This means we need to basically set up comms between the two exas so they know how much data they're agreeing to process.
NOTE FILEFINDER GRAB 300 COPY F X DROP NOTE FINDHOST MARK FINDHOST LINK 800 HOST T TEST T = X FJMP FINDHOST NOTE HOSTFOUND-GETMETA NOTE META: NAME,OFF,LEN GRAB 200 COPY M X MARK FINDENTRY TEST F = X FJMP FINDENTRY NOTE ENTRYFOUND-SETLOOP COPY F T ; OFFSET COPY F X ; LEN NOTE SETTOOFFSET SEEK -9999 SEEK T COPY X M MARK READDATA COPY F M SUBI X 1 X TEST X = 0 FJMP READDATA DROP HALT
NOTE HOSTSENDWRITE NOOP NOOP NOOP NOTE SENDTARGETENTRY GRAB 300 SEEK 1 ; TO TARGETNAME COPY F X COPY X M DROP NOTE WRITEENTRIES MAKE COPY M X MARK WRITEDATA COPY M F SUBI X 1 X TEST X = 0 FJMP WRITEDATA HALT
For this solution, we use two Exas:
- FindUserDB - Finds the target username, then searches the user db to figure out which file contains its data, then pushes that to M
- OverwriteUserDB - Receives the target file, sums the transaction value, then writes out new transactions in max(75) increments until its written out the sum
NOTE FINDUSERDB GRAB 300 COPY F X DROP LINK 800 GRAB 199 MARK FINDUSERDB TEST F = X FJMP FINDUSERDB NOTE USERFILE TO M SEEK 1 COPY F M DROP HALT
NOTE OVERWRITEUSERDB LINK 800 LINK 799 COPY M X GRAB X COPY 0 X SEEK 2 MARK SUMALL ADDI X F X TEST EOF FJMP SUMALL SEEK -9999 SEEK 2 MARK WRITEALL TEST X > 75 TJMP WRITE75 JUMP WRITEREST MARK WRITE75 COPY 75 F SUBI X 75 X JUMP WRITEALL MARK WRITEREST COPY X F MARK END DROP HALT