Skip to content

Instantly share code, notes, and snippets.

@amitn
Created December 18, 2014 07:39
Show Gist options
  • Save amitn/470909939c950f3fb99a to your computer and use it in GitHub Desktop.
Save amitn/470909939c950f3fb99a to your computer and use it in GitHub Desktop.
Threes solver using OpenCV and Python
#!/usr/bin/python
import cv2
import numpy as np
import glob
SAMPLES_SIZE = 2001
SAMPLES = np.empty((0, SAMPLES_SIZE))
RESPONSES = []
def learnCard(I, num):
global SAMPLES
global RESPONSES
sample = I.reshape((1, SAMPLES_SIZE))
SAMPLES = np.append(SAMPLES, sample, 0)
RESPONSES.append(int(num))
def readDir(num):
for fileName in glob.glob("./cards/" + str(num) + "/*.png"):
print fileName
I = cv2.imread(fileName)
learnCard(I, num)
if __name__ == "__main__":
global SAMPLES
global RESPONSES
for num in (0, 1, 2, 3, 6, 12, 24, 48, 96, 192, 384, 768):
readDir(num)
RESPONSES = np.array(RESPONSES, np.int32)
RESPONSES = RESPONSES.reshape((RESPONSES.size, 1))
np.savetxt("train_samples.data", SAMPLES)
np.savetxt("train_responses.data", RESPONSES)
#!/usr/bin/python
import cv2
import numpy as np
import glob
SAMPLES_SIZE = 288
SAMPLES = np.empty((0, SAMPLES_SIZE))
RESPONSES = []
def learnCard(I, num):
global SAMPLES
global RESPONSES
sample = I.reshape((1, SAMPLES_SIZE))
SAMPLES = np.append(SAMPLES, sample, 0)
RESPONSES.append(int(num))
def readDir(num):
for fileName in glob.glob("./next_card/" + str(num) + "/*.png"):
print fileName
I = cv2.imread(fileName)
learnCard(I, num)
if __name__ == "__main__":
global SAMPLES
global RESPONSES
for num in (1, 2, 3, 6):
readDir(num)
RESPONSES = np.array(RESPONSES, np.int32)
RESPONSES = RESPONSES.reshape((RESPONSES.size, 1))
np.savetxt("train_samples_next.data", SAMPLES)
np.savetxt("train_responses_next.data", RESPONSES)
#!/usr/bin/python
import cv2
import numpy as np
import random
import socket
import time
import ThreesSolver
CARD_H = 185
CARD_W = 135
CARD_H_SUB = 40
CARD_W_SUB = 20
CARD_NUM = 0
NUM = 0
SCALE = 0.2
SAMPLES_SIZE_CARD = 2001
SAMPLES_SIZE_NEXT = 288
MODEL = None
MODEL_NEXT = None
DEBUG = False
#DEBUG = True
def doModel(name):
SAMPLES = np.loadtxt("train_samples%s.data" % (name), np.float32)
RESPONSES = np.loadtxt("train_responses%s.data" % (name), np.int32)
RESPONSES = RESPONSES.reshape((RESPONSES.size, 1))
MODEL = cv2.KNearest()
MODEL.train(SAMPLES, RESPONSES)
return MODEL
def iview(I):
global NUM
s = "NUM%03d" % (NUM)
cv2.imshow(s, I)
NUM += 1
return s
class GameCard(object):
def __init__(self, I, debug=False):
global CARD_NUM
global SCALE
self.I = I[20:-20, 10:-10]
#self.G = cv2.cvtColor(self.I, cv2.COLOR_BGR2GRAY)
self.s = cv2.resize(self.I, None, fx=SCALE, fy=SCALE)
self.num = 0
if debug:
cv2.imwrite("cards/card_%03d.png" % (CARD_NUM), self.s)
CARD_NUM += 1
else:
self.findNum()
def findNum(self):
global MODEL
sample = self.s.reshape((1, SAMPLES_SIZE_CARD))
sample = np.float32(sample)
retval, results, neigh_resp, dists = MODEL.find_nearest(sample, k=1)
self.num = int(results[0][0])
def onMouseEvent(event, x, y, flags, param):
if (cv2.EVENT_LBUTTONDBLCLK == event):
print "(%d, %d)" % (x, y)
def cutCards(I, nCard):
global DEBUG
H = CARD_H
W = CARD_W
b = ThreesSolver.Board()
for i in range(4):
for j in range(4):
iT = I[i * H:(i + 1) * H, j * W:(j + 1) * W]
c = GameCard(iT, DEBUG)
b.board[i, j] = c.num
if DEBUG:
MOVES = ("LEFT", "RIGHT", "DOWN", "UP")
return "SCREEN"
return random.choice(MOVES)
return b.checkAllMoves(nCard)
class NextCard(object):
def __init__(self, I, debug):
global SCALE
self.I = I[125:185, 340:380]
self.s = cv2.resize(self.I, None, fx=SCALE, fy=SCALE)
self.num = 0
if debug:
self.saveImage()
else:
self.getNum()
def saveImage(self):
global CARD_NUM
cv2.imwrite("next_card/card_%03d.png" % (CARD_NUM), self.s)
CARD_NUM += 1
def getNum(self):
global MODEL_NEXT
sample = self.s.reshape((1, SAMPLES_SIZE_NEXT))
sample = np.float32(sample)
retval, results, neigh_resp, dists = MODEL_NEXT.find_nearest(sample, k=1)
self.num = int(results[0][0])
def cutBoard(I):
B = I[340:1080, 90:630]
return B
def ProssesGame():
global DEBUG
iSCR = cv2.imread("shot1.png")
cv2.imshow('Screen', iSCR)
nCard = NextCard(iSCR, DEBUG)
iBRD = cutBoard(iSCR)
#cv2.imshow('Board', iBRD)
#cv2.setMouseCallback('Screen', onMouseEvent)
nextMove = cutCards(iBRD, nCard.num)
cv2.destroyAllWindows()
return nextMove
def getScreen(s):
time.sleep(1)
s.send("SCREEN")
time.sleep(0.3)
s.recv(64)
def randomMove(s):
s.send("MOVE")
time.sleep(0.3)
s.recv(64)
def sendMove(s, m):
s.send(m)
s.recv(64)
if __name__ == "__main__":
global MODEL
global MODEL_NEXT
cSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cSocket.connect(("localhost", 4456))
MODEL = doModel("")
MODEL_NEXT = doModel("_next")
while True:
getScreen(cSocket)
nextMove = ProssesGame()
sendMove(cSocket, nextMove)
#randomMove(cSocket)
#!/usr/bin/env monkeyrunner
from com.android.monkeyrunner import MonkeyRunner
import random
import time
import socket
MOVES = ("LEFT", "RIGHT", "DOWN", "UP")
def doMove(device, c, move):
if move in "LEFT":
device.drag(c, (c[0] - 100, c[1]), 0.3, 15)
elif move in "RIGHT":
device.drag(c, (c[0] + 100, c[1]), 0.3, 15)
elif move in "DOWN":
device.drag(c, (c[0], c[1] + 100), 0.3, 15)
elif move in "UP":
device.drag(c, (c[0], c[1] - 100), 0.3, 15)
time.sleep(0.3)
def randomMove(device, c):
i = random.randint(0,3)
doMove(device, c, MOVES[i])
def takeSnapshot(device):
result = device.takeSnapshot()
## Writes the screenshot to a file
result.writeToFile('shot1.png', 'png')
if __name__ == "__main__":
device = MonkeyRunner.waitForConnection()
W = device.getProperty('display.width')
H = device.getProperty('display.height')
c = (int(W) / 2, int(H) / 2)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 4456))
server.listen(5)
while True:
cn, addr = server.accept()
while True:
buf = cn.recv(64)
if not buf:
break
if len(buf) > 0:
print buf
if "MOVE" in buf:
randomMove(device, c)
elif "SCREEN" in buf:
takeSnapshot(device)
elif buf in MOVES:
doMove(device, c, buf)
cn.send("OK")
#!/usr/bin/python
import numpy
import copy
import random
import sys
import string
BOARD_SIZE = 4
MOVE_UP = (-1, 0)
MOVE_DOWN = (1, 0)
MOVE_LEFT = (0, -1)
MOVE_RIGHT = (0, 1)
MOVES = (MOVE_UP, MOVE_DOWN, MOVE_LEFT, MOVE_RIGHT)
MOVES_STRING = ("UP", "DOWN", "LEFT", "RIGHT")
UP_DOWN_LEFT_RIGHT = ((MOVE_UP, MOVE_DOWN), (MOVE_LEFT, MOVE_RIGHT))
def isValidLocation(s):
if (s[0] < 0 or s[1] < 0 or s[0] >= BOARD_SIZE or s[1] >= BOARD_SIZE):
return False
return True
def addPoints(s, d):
return (s[0] + d[0], s[1] + d[1])
def mergeScore(v1, v2):
if v1 > 2 and v2 > 2 and v1 == v2:
return 2
if v1 != 0 and v2 != 0 and v1 + v2 == 3:
return 2
return 0
def canMerge(v1, v2):
if v1 > 2 and v2 > 2 and v1 == v2:
return True
if v1 != 0 and v2 != 0 and v1 + v2 == 3:
return True
return False
class Board(object):
def __init__(self):
self.board = numpy.zeros((BOARD_SIZE, BOARD_SIZE), dtype=numpy.uint16)
self.wasMoved = False
self.depth = 0
def getScore(self):
score = 0.0
for i in range(BOARD_SIZE):
for j in range(BOARD_SIZE):
s = (i, j)
if (self.board[s] == 0):
score += 4
score += self.checkAllMerges(s)
score += self.checkLock(s)
#score += self.checkNextMerges(s)
return score
def checkAllMerges(self, s):
score = 0
for m in (MOVE_DOWN, MOVE_RIGHT):
d = addPoints(s, m)
if isValidLocation(d):
score += mergeScore(self.board[s], self.board[d])
return score
def checkNextMerges(self, s):
score = 0
return 0
for m in (MOVE_DOWN, MOVE_RIGHT):
d = addPoints(s, m)
if isValidLocation(d) and self.board[s] > 0:
if self.board[s] * 2 == self.board[d]:
score += 1
if self.board[s] == self.board[d] * 2:
score += 1
return score
def checkLock(self, s):
return 0
score = 0
for (t1, t2) in UP_DOWN_LEFT_RIGHT:
d1 = addPoints(s, t1)
d2 = addPoints(s, t2)
if isValidLocation(d1) and isValidLocation(d2):
c = self.board[s]
v1 = self.board[d1]
v2 = self.board[d2]
if (c + v1 != 3 and c + v2 != 3 and c < v1 and c < v2):
score += -1
return score
def doMove(self, m):
self.wasMoved = False
movedLocation = []
for outer in range(BOARD_SIZE):
wasMoved = False
for inner in range(1, BOARD_SIZE):
if (m == MOVE_UP or m == MOVE_DOWN):
j = outer
if m == MOVE_UP:
i = inner
else:
i = BOARD_SIZE - 1 - inner
else:
i = outer
if m == MOVE_LEFT:
j = inner
else:
j = BOARD_SIZE - 1 - inner
s = (i, j)
d = addPoints(s, m)
if (self.board[d] == 0 and self.board[s] > 0):
self.board[d] = self.board[s]
self.board[s] = 0
wasMoved = True
elif canMerge(self.board[s], self.board[d]):
self.board[d] += self.board[s]
self.board[s] = 0
wasMoved = True
movedLocation.append(wasMoved)
nextIndex = -1
t = []
for nextIndex in range(4):
if (movedLocation[nextIndex]):
self.wasMoved = True
ml = (-1, -1)
if (m == MOVE_LEFT):
ml = (nextIndex, BOARD_SIZE - 1)
elif (m == MOVE_RIGHT):
ml = (nextIndex, 0)
elif (m == MOVE_DOWN):
ml = (0, nextIndex)
elif (m == MOVE_UP):
ml = (BOARD_SIZE - 1, nextIndex)
t.append(ml)
return t
def checkAllMoves(self, nV):
allScores = []
allBoards = []
allDir = []
mi = 0
for m in MOVES:
newBoard = copy.deepcopy(self)
nextCardLocations = newBoard.doMove(m)
if (newBoard.wasMoved):
score = 0
nscore = 0
for ncl in nextCardLocations:
newBoard.board[ncl] = nV
score += newBoard.getScore()
nscore += 1
for mm in MOVES:
newBoardNew = copy.deepcopy(newBoard)
newBoardNew.doMove(mm)
if (newBoardNew.wasMoved):
score += newBoardNew.getScore()
nscore += 1
newBoard.board[ncl] = 0
score = score / nscore
allScores.append(score)
allBoards.append(newBoard)
allDir.append(MOVES_STRING[mi])
mi += 1
#print allScores
#for b in allBoards:
print nV
print self.board
print allScores
i = allScores.index(max(allScores))
return allDir[i]
#return allBoards[i]
def ReadBoard(B):
for i in range(BOARD_SIZE):
print "Enter Line %d" % (i)
line = sys.stdin.readline()
sline = string.split(line, " ")
for j in range(BOARD_SIZE):
B.board[(i, j)] = int(sline[j])
if __name__ == "__main__":
B = Board()
ReadBoard(B)
while (True):
print B.getScore()
print "Enter next:"
line = sys.stdin.readline()
nV = int(line)
B = B.checkAllMoves(nV)
print B.board
for xx in range(2):
print "Fix Board i j v:"
line = sys.stdin.readline()
sline = string.split(line, " ")
i = int(sline[0])
j = int(sline[1])
v = int(sline[2])
B.board[(i, j)] = v
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment