Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Script to play Winterbells (http://www.ferryhalim.com/orisinal/g3/bells.htm) based on pydroid:

    import pydroid
    
    INIT_COLOR = 473428
    BELL_COLORS = set([12702690, 8950940, 9016477, 9017249, 9018536, 12505567,
                       12505568, 11715538, 10862803, 12965603, 12439776, 12834019,
                       14411502, 8953000, 5401724])
    
    def find_init_color(screen, xr, yr):
        for x in xr:
            for y in yr:
                if screen.get_color(x, y) == INIT_COLOR:
                    return (x, y)
    
    def init():
        while True:
            screen = pydroid.bitmap.capture_screen()
            first = find_init_color(screen, xrange(0, screen.width), xrange(0, screen.height))
            last = find_init_color(screen, xrange(screen.width - 1, -1, -1), xrange(screen.height - 1, -1, -1))
            
            if first is not None and last is not None:
                return first, last
    
    def check(first, last):
        screen = pydroid.bitmap.capture_screen()
        
        for y in xrange(last[1] - 1, first[1], -1):
            for x in xrange(first[0] + 1, last[0]):
                if screen.get_color(x, y) in BELL_COLORS:
                    return pydroid.mouse.move(x, y)
    
    def main():
        print 'Searching for Winterbells...'
        first, last = init()
        
        print 'Found at %s, %s. Running.' % (first, last)
        while True:
            check(first, last)
    
    if __name__ == '__main__':
        main()
It's far from perfect, but it's a good start. To run it, execute the script, then open the game in a resolution large enough such that the whole game is visible.

All it does is find pixels with colors unique to the bells and moves the mouse there. I made the same script in C# a while ago. This script is faster (even though it's Python!) and far more concise. It was astonishingly easy to make too thanks to pydroid. The only time-consuming bit was finding the bell colors. Kudos for the nice library!



Very cool!


Significantly optimized:

    import pydroid, operator
    
    INIT_COLOR = 473428
    BELL_COLORS = set([12702690, 8950940, 9016477, 9017249, 9018536, 12505567,
                       12505568, 11715538, 10862803, 12965603, 12439776, 12834019,
                       14411502, 8953000, 5401724])
    CANVAS_WIDTH = 751
    CANVAS_HEIGHT = 501
    
    CHECK_WIDTH = CANVAS_WIDTH / 2 - 50
    
    def find_init_color(screen, xr, yr):
        for x in xr:
            for y in yr:
                if screen.get_color(x, y) == INIT_COLOR:
                    return (x, y)
    
    def init():
        while True:
            screen = pydroid.bitmap.capture_screen()
            first = find_init_color(screen, xrange(0, screen.width), xrange(0, screen.height))
            last = find_init_color(screen, xrange(screen.width - 1, -1, -1), xrange(screen.height - 1, -1, -1))
            
            if first is not None and last is not None and last[0] - first[0] >= CANVAS_WIDTH and last[1] - first[1] >= CANVAS_HEIGHT:
                return first, last
            
    def triangle(base, width, height, top_left, bottom_right):
        for i in xrange(0, height):
            y = base[1] - i
            diff = i * width / height
            
            if y > bottom_right[1]:
                continue
            if y < top_left[1]:
                break
            
            for x in xrange(base[0] - width + diff, base[0] + width - diff):
                if x > top_left[0] and x < bottom_right[0]:
                    yield (x, y)
    
    def check(first, last, prev):
        screen = pydroid.bitmap.capture_screen()
        
        if prev is not None:
            for y in xrange(prev[1] + 20, prev[1] - 20, -1):
                for x in xrange(prev[0] - 20, prev[0] + 20):
                    if screen.get_color(x, y) in BELL_COLORS:
                        pydroid.mouse.move(x, y)
                        return (x, y)
                            
            for point in triangle(prev, CHECK_WIDTH, 150, first, last):
                if screen.get_color(point[0], point[1]) in BELL_COLORS:
                    pydroid.mouse.move(point[0], point[1])
                    return point
                
        for y in xrange(last[1] - 100, first[1], -1):
            for x in xrange(first[0] + 1, last[0]):
                if screen.get_color(x, y) in BELL_COLORS:
                    pydroid.mouse.move(x, y)
                    return (x, y)
    
    def main():
        print 'Searching for Winterbells...'
        first, last = init()
        prev = None
        
        print 'Found at %s, %s. Running.' % (first, last)
        while True:
            prev = check(first, last, prev)
    
    if __name__ == '__main__':
        main()
It still only scores in the thousands because one of the bell colors sometimes maps to the rabbit, but it's at the point where it scores better than a newbie. Instead of looking from the bottom up for bell pixels, it tries to look in the following regions in order:

1) The area near where it last looked.

2) A triangular area above where it last looked, which is a heuristic guess of where the rabbit would be able to jump to.

If those fail, then it looks from the bottom up for a bell. Okay that was fun, but it made me realize I really need a day job.


Cool :)

Just a minor nitpick: you may want to try the library method bmp.find_color() instead of your find_init_color() (http://msanders.github.com/autopy/documentation/api-referenc...), it should be significantly faster.

Also, instead of iterating through the width & height manually, autopy offers this shortcut:

  for x, y in bitmap:
      do_something(bitmap, x, y)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: