Only one challenge writeup this time, really tough multi-part questions and only had time to solve this one all the way through.
A Block and a Hard Place (28 Solves)
Description:
Are you the Far Lands because you're a Maze? Or are you a Maze because you're the Far Lands?
Solution:
We're given only a server to netcat to and nothing else. Once connected, we can move with either wasd or WASD to jump over walls.
β$ nc 13.201.224.182 30961 130 β¨―
Welcome to The Far Lands! You're free to explore.
You can move around using wasd (lowercase).
If you hit a wall, you can jump over them using WASD (uppercase).
You can't jump if there's no wall in front of you.
Lastly, you're placed in a random position in the maze.
Do your best to figure out it's secrets!
2000> w
Moved!
1999> w
You can't move there!
1998> W
Jumped over a wall!
1997> w
Moved!
...
Once we get to the boundary (at the top when trying w/W), neither option will work. To map out the entire maze, I wrote the following to go to the upper left corner, and then zig-zag right and left through the maze.
This will print out the rows, with a # for if there was a wall. Since we're going backwards every other row, I have * in the output to make a note to flip it. I did that by copy pasting the output to a text file, and in vim selecting the row (V) and then reversing it (:%!rev). Then find/replace * with # and deleting all characters other than # and space. See the final output below.
This looks like a QR code but not quite, and this is because this is just a representation of where the horizontal walls are. Picturing a black and white QR code, each horizontal wall should signify a switch from white to black, and vice versa. Therefore, every time a # is encountered, it's actually a toggle. The below code fixes this.
This gives us the fixed map, but it's in ASCII so one more program to convert it to a QR image.
import socket
import time
HOST = '13.201.224.182'
PORT = 32127
# Create a socket, connect to the server, and return the socket
def create_socket_and_connect(host, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
return s
# Send a command to the server and return the response
def send_command(sock, command):
ret = sock.recv(4096).decode('utf-8')
sock.sendall(f"{command}\n".encode('utf-8'))
ret = sock.recv(4096).decode('utf-8')
#print(command, ret) # print out command outputs for debugging
return ret
# Navigate to the upper-left corner of the maze
def navigate_to_upper_left_corner(sock):
while True:
response = send_command(sock, 'w')
if "can't move there" in response:
response = send_command(sock, 'W')
if "can't move there" in response:
break
while True:
response = send_command(sock, 'a')
if "can't move there" in response:
response = send_command(sock, 'A')
if "can't move there" in response:
break
# Move to the right until the boundary is hit
def explore_right(sock):
row = []
while True:
response = send_command(sock, 'd')
if "can't move there" in response:
response = send_command(sock, 'D')
if "can't move there" in response:
break
else:
row.append("#")
else:
row.append(".")
print(row)
# Move to the left until the boundary is hit
def explore_left(sock):
row = []
while True:
response = send_command(sock, 'a')
if "can't move there" in response:
response = send_command(sock, 'A')
if "can't move there" in response:
break
else:
row.append("*")
else:
row.append(".")
print(row)
def main():
with create_socket_and_connect(HOST, PORT) as sock:
# Receive and print the welcome message
print(sock.recv(4096).decode('utf-8'))
time.sleep(1)
# Navigate to the upper-left corner of the maze
navigate_to_upper_left_corner(sock)
# Skip a few rows that had no walls, found earlier
response = send_command(sock, 's')
response = send_command(sock, 's')
response = send_command(sock, 's')
# Go down one, move to the right, go down one, move to the left
while True:
response = send_command(sock, 's')
if "can't move there" in response:
break
explore_right(sock)
response = send_command(sock, 's')
if "can't move there" in response:
break
explore_left(sock)
if __name__ == "__main__":
main()