Last active
November 21, 2018 07:48
-
-
Save MadLittleMods/9940341 to your computer and use it in GitHub Desktop.
StackExchange Unicoin Miner in Python, https://www.youtube.com/watch?v=B74NHzUbvYo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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