Diamond Dash Bot: 1,000,000 points!

Update: My current high score is about 1.1 million, much more than the 480,000 reported earlier.

My wife is a hardcore casual gamer. Her Bejeweled Blitz scores routinely quadruple my best attempts. For a few short minutes, I had the leading score on Google Games' Diamond Dash, which lasted until my dear wife got a score that obliterated mine by a factor of 5. So, I made the logical decision: to write an automated Diamond Dash playing bot to beat my wife. At Diamond Dash.

DD is pretty similar to Bejeweled Blitz, except that instead of swapping pieces, you just click on a group of 3 or more contiguous pieces to eliminate them all. So, the logic is a little easier. Here's what I came up with.

I took a screenshot of the play area, and cropped off a little rectangle corresponding to the top left of the play area. This function searches, very inefficiently, for that exact set of pixels, to orient itself within the screenshot. It only has to find it once, then it saves that location for speed. So, no moving the window! It returns a cropped pixel array of just the play area.

# Get a point from 10,10 in a 40px square, which should be the right color

i_ind=int(i*factor+factor/4)

j_ind=int(j*factor+factor/4)

pixel=pixarray[i_ind][j_ind]

c=nearest_index_to_color(pixel)

counts[i][j]=c

returncounts

defnearest_index_to_color(color_tuple):

"Get the index in COLORS closest to color_tuple"

distances=[color_distance(c,color_tuple)forcinCOLORS]

returndistances.index(min(distances))

defnormalize_color(color_tuple):

"Get the color closest to color_tuple"

returnCOLORS[nearest_index_to_color(color_tuple)]

defcolor_distance(c1,c2):

"""Get the sum of squares of the difference between two colors"""

return(c1[0]-c2[0])**2+(c1[1]-c2[1])**2+(c1[2]-c2[2])**2

This bit of code takes that play area and reduces it to a single numeric matrix, where 0 is a diamond, and 1-5 are the various colors. This is what the rest of the program operates on. It does this by sampling every 40 pixels, with a 10x10px offset to get something within the color tile. This was chosen instead of the center because the colors are more consistent in the border between the tile bezel and the symbol.

This uses a recursive flood fill algorithm and modifies it to count instead.

A big difference between Diamond Dash and Bejeweled Blitz is that the latter penalizes you heavily for misses. Most issues seem to stem from the lag between when the screenshot is taken and when the action is processed; sometimes the board changes in between. Some possible improvements:

Alternating sides between picks, to ensure that information acquired in a screenshot is still valid

Building up multiple non-interfering picks from one screen and running them all (with a longer delay)

Running a faster computer

Improving the play-area-finding algorithm for speed

Porting the whole thing to C for performance.

A special message

This is where the affiliate links live, but hear me out! I use these
two services every day, and I wouldn't recommend them if I wasn't
satisfied.

DigitalOcean
- Purveyors of fine (and inexpensive) virtual servers. I use DigitalOcean to host
Address Bin
and a few others; it's my go-to host. Use this
referral link
for a $10 credit.

AirBnb
- I've been living in AirBnbs for a few months now, and plan to for many more.
If you've ever wanted to try them out, you can get a $25 discount from
this referral link.