Using Python To Beat The 2012 Olympic Google Doodles

Saturday, August 11, 2012 - 20:41

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.

1
2
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.

1
2
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 :)

Category: 
philipnorton42's picture

Philip Norton

Phil is the founder and administrator of #! code and is an IT professional working in the North West of the UK.
Google+ | Twitter

Comments

i used that script idea for getting spells accurately on pottermore
but for some reason the timing some times goes off . it maybe the website making some random timing changes to fight bots . or maybe something to do with os scheduling or even sth is slowing my pc randomly.
i manage to get the score of 142 on average . the max i got was 143 . and it can some times go as low as 134 . im still trying to improve it.

philipnorton42's picture
Submitted by philipnorton42 on Fri, 10/12/2012 - 10:02

I found the same thing on the basketball game, but I thought it was down to when the script was activated. Let me know if you find anything.

Add new comment