Solving the Challenge of Tiamat's Eye

Post Image

Last week at DerbyCon 5.0 the CircleCityCon folks had a booth with a challenge, the Challenge of Tiamat’s Eye.

The challenge consisted of the small chest pictured above containing an eye made up of blinking red LEDs. Every 30 seconds the pattern would reset. The content organizers hinted that we would need to record the eye at 60fps in order to capture all of the information we needed. We ended up using a coffee creamer cup as a diffuser over the LEDs to make the difference in the pixels clearer. This resulted in the following recording. Note: we recorded 30 seconds at 60fps, which resulted in a 60 second 30fps recording.

Next we extracted each frame from the video with the following command: (ffmpeg would have worked as well too)
avconv -i VID_20150926_175956.mp4 -r 30 frames/%5d.jpg

This resulted in the following 1800 frames.

frames

After viewing the image thumbnails we observed that the shortest amount of time the LED was either on or off was 3 frames. This means that every 3 frames represents a single bit. Since on some frames the LED was half-light we decided to sample every 3rd frame starting in the middle of each bit to get the best representation.

#! /usr/bin/env python

import os  
from PIL import Image  
import sys

def main():  
    i = 0
    # because os.walk is not sorted, and I'm lazy
    # ls frames/* > frames.list
    for l in open("frames.list"):
        i+=1
        if i % 3 == 0:
            im = Image.open(l.strip())
            # sample pixel location
            r,g,b = im.getpixel((1357,657))
            if (r>250):
                sys.stdout.write('1')
            else:
                sys.stdout.write('0')
    print ""

if __name__ == "__main__":  
    main()

The python script above reads every 3rd frame and prints out a 0 or 1 depending on the LED state. This gave us the following binary string.

0101010101111111111001100110100110100110011100101001110011100111010010011101001001101111100110110010011011111001100011100110000110011101001001100101100111010010011010001001100101100110100010011011111001110101100111001110011001011001101111100110011010011000101001100101100110000110011100101001101010100110010110011100111001110100100110010110011100101001110111100110100110011011101001110011100110000110011001101001110010100110010110011001011001100011100011001110011101001001101001100110001110011010111001100101100111010000000000000000000000000000000000000000000  

Our first guess was to convert it to ASCII, however that did not return anything intelligible. Another vague hint provided got us thinking it was 10 bit serial data. A quick search on Google led us to Asynchronous Serial Communication, which after removing the first 20 bits for the header, tells us that there is 8 data bits padded by a start and stop bit. Splitting the binary into 10 bit lines and then removing the first and last bit provided us with the following binary.

01100110  
01101001  
01110010  
01110011  
01110100  
01110100  
01101111  
01101100  
01101111  
01100011  
01100001  
01110100  
01100101  
01110100  
01101000  
01100101  
01101000  
01101111  
01110101  
01110011  
01100101  
01101111  
01100110  
...

Converting this to ASCII returns the following text.

firsttolocatethehouseofbearjesterwinsafreec3ticket  

After adding a few spaces says:
first to locate the house of bear jester wins a free c3 ticket

which was the magic phrase to say to the house of bear to solve the challenge and win CircleCityCon tickets.

The puzzle was fun and simple enough to solve in a few hours allowing us to enjoy the rest of DerbyCon. I would like to end by thanking CircleCityCon for creating the challenge and my teammates @SID_tracker and @ryatesm for assisting me in solving the challenge.

All of the data used can be found in This Gist.