The other day I was inspired by a story on Reddit about a guy who had created a Python script to automatically play the olympic hurdles Google Doodle. The Python script just passed the correct keyboard commands to the game so that the game was finished in 1.5 seconds, earning a gold medal. The problem was that his script was specifically for Windows, so I set about trying to create a Linux version that I could run on Kubuntu.
After a bit of research I found a decent plugin that sends keyboard commands through Python called uinput. To get this installed I had to add the following lines to /etc/apt/sources.list.
deb http://ppa.launchpad.net/tuomasjjrasanen/tjjr/ubuntu precise main deb-src http://ppa.launchpad.net/tuomasjjrasanen/tjjr/ubuntu precise main
uinput can then be deleted via the following commands.
sudo apt-get update sudo apt-get install python-uinput
The examples on the uinput site where quite straightforward, but the first thing I had to do was find out what constants applied to which keys. To do this I used some example code and pulled out the class definition using dir(). It was then a case of looping through all of the available names in the class and printing them out.
1 2 3 4 5 6 7 8 9 10
#! /usr/bin/env python import uinput events = (uinput.KEY_E) device = uinput.Device(events) methods = dir(device) for method in methods: print method
From this code I was able to see that the keys I needed where uinput.KEY_RIGHT for the right key, uinput.KEY_LEFT for the left key and uinput.KEY_SPACE for the space bar. I originally intended to have the script press left and right to run and space when I needed to jump a hurdle. During the initial tests of this script I realised that the left and right arrows get "pressed" so quickly that also pressing the space bar wasn't needed. The below script runs the Google doodle hurdles (using just the arrow keys) in 1.0 seconds, earning three stars.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
#! /usr/bin/env python # include uinput and time import uinput, time def run(): events = (uinput.KEY_RIGHT, uinput.KEY_LEFT, uinput.KEY_SPACE) device = uinput.Device(events) print '3' time.sleep(1) print '2' time.sleep(1) print '1' time.sleep(1) print 'go!' s = time.time() while time.time() - s < 1: device.emit(uinput.KEY_RIGHT, 1) # press the right key device.emit(uinput.KEY_RIGHT, 0) # release the right key device.emit(uinput.KEY_LEFT, 1) # press the left key device.emit(uinput.KEY_LEFT, 0) # release the left key run()
Notice that this script also uses the time package to make sure that there is a delay between running this script and making sure that the Google doogle has focus. When you run the script you should immediately click on the Google doodle. This is important because if you run the python script and do nothing all of the keyboard commands will just be dumped into the terminal.
As an extension this this I then tried to adapt the script to get a perfect score on the basketball Google doodle. This was slightly more difficult as the space bar needed to be pressed at just the right time to score a goal. Also, when the duration needed between key presses changes as the score increases.
After some experimentation I managed to come up with the following code, which produces a score of 38 (if all goes well). I found that for some reason the code only worked when the doodle was first loaded onto the page, but as this was only a throw away script for personal entertainment so I wasn't worried. I also noticed that a friend of mine posted a higher score than I was able to get with this script so the timings must be off slightly.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
#! /usr/bin/env python # include uinput and time import uinput, time def play(): events = (uinput.KEY_RIGHT, uinput.KEY_LEFT, uinput.KEY_SPACE) device = uinput.Device(events) print '3' time.sleep(1) print '2' time.sleep(1) print '1' time.sleep(1) print 'go!' timediff = 0 s = time.time() while timediff <= 28: if timediff < 5.5: sleep = 0.25 elif timediff >= 5.5 and timediff < 9.5: sleep = 0.4 elif timediff >= 9.5 and timediff < 12.5: sleep = 0.41 elif timediff >= 12.5 and timediff < 21: sleep = 0.74 else: sleep = 0.80 time.sleep(sleep) device.emit(uinput.KEY_SPACE, 1) device.emit(uinput.KEY_SPACE, 0) timediff = time.time() - s play()
I haven't looked at doing this for the other London 2012 Olympic Google doodles, but I leave that as an exercise for the reader. Post a comment and let me know how you got on :)