My Best Exapunks Solutions
Date: 2023-06-21 | create | ctech | exapunks |
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
Zebros Copies
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
datereader
NOTE DATEREADER
LINK 800
LINK 801
COPY #DATE M
HALT
paywriter
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
debtreader
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
Highlights:
- 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)
messagereader
NOTE MESSAGEREADER
GRAB 300
MARK READMESSAGE
COPY F M
TEST EOF
FJMP READMESSAGE
HALT
signwriter
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.
Highlights:
- 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.
searcher
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
UC Berkeley
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
Highlights:
- 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.
FileFinder
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
HostSendWrite
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
Workhouse
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
FindUserDB
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
OverwriteUserDb
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
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.