Skip to content

Instantly share code, notes, and snippets.

@MadLittleMods
Last active November 21, 2018 07:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MadLittleMods/9940341 to your computer and use it in GitHub Desktop.
Save MadLittleMods/9940341 to your computer and use it in GitHub Desktop.
StackExchange Unicoin Miner in Python, https://www.youtube.com/watch?v=B74NHzUbvYo
# Unicoin Miner
# By: Eric Eastwood (ericeastwood.com)
#
# ** Press the `P` key or `Space` to stop the program **
#
# Description:
# Looks for rocks and clicks them
# Unicoins were a April Fools Joke on all StackExchange sites
# Just wanted to try out some basic vision and input emulation
#
# See it in action:
# http://youtu.be/B74NHzUbvYo
#
# Made and Tested with Python 2.7 on Windows 8
#
# Dependencies:
# pyhk: https://github.com/schurpf/pyhk
# For global hotkey stopping
# Pillow: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pillow
# Screen capture
# pywin: http://www.lfd.uci.edu/~gohlke/pythonlibs/#pywin32
# Left click emulation
#
# Note:
# Only captures and works on the primary monitor. This is a limitation of pillow.
# Does not work perfectly...
import os
import time
import pyhk
import win32api, win32con
import PIL.ImageGrab as ImageGrab
# from PIL import Image
import pythoncom
from multiprocessing.pool import ThreadPool
from random import randrange
# we use for saving the image if you want to
BASE_DIR = os.path.realpath(os.path.dirname(__file__))
def leftClick(x, y):
# Emulate a left click as coordiate x, y
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
time.sleep(.002)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def getPixelFromIndex(im, index):
# Given a index from a sequence of pixels (ie. im.getdata()),
# give the x and y coordinate
width, height = im.size
x = index%width
y = index/width
return (x, y)
def clamp(n, minn, maxn):
# just a simple utility function to clamp
return max(min(maxn, n), minn)
def sampleArea(coord, color, numSamples, im):
# Sample the area to the left and down randomly
mylist = list(((clamp(x-randrange(10), 0, im.size[0]), clamp(x+randrange(10), 0, im.size[1])) for x in range(numSamples)))
mylist.append(coord)
found = False
for listcoord in mylist:
if im.getpixel(listcoord) == color:
found = True
return found
# This is variable that controls the main while loop
running = True
def stopLoop():
# function that stops the main while loop
# We use this for the global stop hotkeys
global running
print("stopping")
running = False
# Create pyhk class instance
hot = pyhk.pyhk()
# Add in the globabl stop hotkeys
# Find more hotkeys: http://schurpf.com/python/python-hotkey-module/pyhk-end-user-documentation/#hotkey-list
hot.addHotkey(['P'], stopLoop, isThread=True)
hot.addHotkey(['Space'], stopLoop, isThread=True)
# Set up our thread pool we use to capture the screen
pool = ThreadPool(processes=1)
# Define some colors of the rocks to look for
effectColor = (187, 187, 187) # The sqaure sparkle chipping effect color
mainRockColor = (220, 220, 220) # The light gray color of the rock
secondaryRockColor = (154, 154, 154) # The dark gray color of the rock
# Initially capture the screen
im = ImageGrab.grab()
# Simple main loop
count = 0;
lastTimeSinceSearch = 0
needNewRock = True
returnImageFromAsync = True
while running:
# Refesh the image every second
if time.time() - lastTimeSinceSearch > 1:
# fullscreen
#im = ImageGrab.grab()
# Spin off a thread pool that captures the screen
async_result = pool.apply_async(ImageGrab.grab)
# We are going to actually get the image at the end of the while loop
returnImageFromAsync = True
lastTimeSinceSearch = time.time()
# Find a new rock if we need it
if needNewRock:
print("Finding rocks")
# Uncomment to save the image we are looking at
#im.save(BASE_DIR + '\\full_snap__' + str(int(time.time())) + '.png', 'PNG')
#print(im)
#print(im.getpixel((0, 0)))
# Reset the coord
rockCoord = (-1, -1)
# there is aliasing on the rocks so we need to buffer the transition from light gray to dark gray
bufferMax = 2
bufferCount = 0;
# Loop through the whole image
for index, pixelColor in enumerate(list(im.getdata())):
# If we find the main rock color(light gray), then reset the buffer count
if(pixelColor == mainRockColor):
bufferCount = 0
# If we can find the secondary rock color(dark gray) within the buffer max
# This means we found a rock
if(bufferCount <= bufferMax and pixelColor == secondaryRockColor):
#print(im.getpixel(getPixelFromIndex(im, index)))
rockCoord = getPixelFromIndex(im, index)
print("found it: " + str(rockCoord))
# Stop loopin through the image
break;
bufferCount += 1
# Start clicking on the rock if there is a valid coord
if(rockCoord[0] > 0 and rockCoord[1] > 0):
# Offset the rock coord just to make it click more on the rock. Better for smaller rocks
clickCoord = (rockCoord[0]-bufferMax, rockCoord[1])
# Emulate click
leftClick(*clickCoord)
# If we destroyed a rock, we need to find another
if not (sampleArea(rockCoord, mainRockColor, 10, im) or sampleArea(rockCoord, secondaryRockColor, 10, im) or sampleArea(rockCoord, effectColor, 10, im)):
print("destroyed rock: " + str(im.getpixel(rockCoord)))
needNewRock = True
else:
needNewRock = False
else:
needNewRock = True
# If there is a image to update our variable with
if returnImageFromAsync:
# Load it in
im = async_result.get()
returnImageFromAsync = False
# Uncomment the block to break after a certain number of iterations
#count += 1
#if count > 100000:
# print("broke after count: " + str(count))
# break
# continue pumping hotkey events
# This is for pyhk.
pythoncom.PumpWaitingMessages()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment