Happy backgammon aid

Worked hard technology is not possible in this life can not be a good practice. Techniques they learn not to go in, we only rely on assistance to sustain life like this.

Brief

Recently playing micro letter applet - Happy backgammon, the result is always abused, good gas ah. I hit upon some time ago a very popular jump jump online assistance. Simple thought for a moment to realize the idea of ​​aid, discovery tools currently required to have enough.

Required tools are divided into the following three categories:

  1. Yixin Yi heart engine, this engine is made by people, it can be said inside the non-commercial version of the strongest backgammon AI

    This is the official website https://www.aiexp.info/pages/yixin-cn.html

    At first I would like to use interface + engine Yi heart that paragraph, because customization is strong enough, and found that the program is not good Python interface to interact with the band, so we chose engine. However embarrassing is that I have official documents turned over and over use of the engine are not found. But later in the World Backgammon Championship https://gomocup.org/ found the AI two interfaces necessary to participate in the competition.

    http://petr.lastovicka.sweb.cz/protocl2en.htm using the input and output streams, herein is selected in this manner

    http://petr.lastovicka.sweb.cz/protocl1en.htm use file

  2. Python simple picture processing

  3. Python adb operate mobile phones

Thinking

The whole idea below, we follow the above order from simple to complex, began to introduce each module. The whole idea along down the procedure is actually better to write, that is, pre- need to manually match the pictures taken, see the corresponding pixel location .

achieve

Preparatory

The following area parameters to my phone 1920 * 1080, for example, different screen adaptation please yourself

class mVars:
    address='C:/Users/EA/Desktop/yixin/' # 使用到的文件所存放地址
    boradOne = 67 #一个相邻落子点的像素间隔
    borad = (65,480) #用来将图片像素坐标和棋盘坐标互转
    confirmBW = (820,1590,820+45,1590+60)#用来确定己方是黑棋还是白棋的区域
    confirmWin = (660,1780,660+46,1780+46)#用来确定是否胜利的区域

These are the need to pre-prepared picture, as to how to obtain these images, and so on back in time will have to add at the end of the text, in fact, do these preparations, the entire schedule is complete 30%

image-20200329105705796
Yixin engine

This engine can be downloaded from the official website Yixin http://gomocup.org/static/download-ai/YIXIN18.zip

Combined http://petr.lastovicka.sweb.cz/protocl2en.htm know how to interact with the engine

I use this module lets subprocess python interact with the engine

import subprocess as sub

class YiXin:
    mYixin = sub.Popen(mVars.address+"Yixin.exe", stdin=sub.PIPE, stdout=sub.PIPE, stderr=sub.PIPE)
    
    def __init__(self):
        self.input('START 15')
        self.input('INFO timeout_match 300000')
        self.input('INFO timeout_turn 10000')

        self.output()
        print("YiXin ready!!")

    def input(self,str): #向Yixin 输入对手落子指令
        print('Human: '+str)
        self.mYixin.stdin.write((str+'\n').encode())
        self.mYixin.stdin.flush()

    def output(self):   #获取Yixin 的输出
        #一直获取Yixin 输出,直到落子的指令或其它
        while True: 
            str = bytes.decode(self.mYixin.stdout.readline())
            print('YiXin: '+ str,end='')
            if ((',' in str) or ('OK' in str)):
                break;
        self.mYixin.stdout.flush()
        if(',' in str):
            return str

    def restart(self):
        self.input('RESTART 15')
        self.output()
Image processing

This module needs to be done is to deal with the picture-related, including comparative pictures, converting coordinates

At first, there are two ideas, one every once in a while get a cross-sectional diagram comparing two pictures of different places, to acquire rival placement position. 2. did not cut a picture from time to time, all have chess position on the map and identify the save, then by comparison, opponents get Lazi position. For efficiency reasons, I chose the first method.

class ImageProcess:
    #如果匹配成功,则返回中心像素点
    def matchImg(self,imgsrc,imgobj,confidence=0.8):
        coord = None
        res = ac.find_template(imgsrc,imgobj,confidence)
        if res != None:
            coord = (int(res['result'][0]),int(res['result'][1]))
        return coord
    
    #将像素坐标转化为棋盘坐标
    def transformBoard(self,coord):
        x = coord[0]
        y = coord[1]
        xcoord = ycoord = 0
        while x>=mVars.borad[0]:
            x-=mVars.boradOne
            xcoord+=1
        while y>=mVars.borad[1]:
            y-=mVars.boradOne
            ycoord+=1

        return xcoord-1,ycoord-1

    #将棋盘坐标转化为像素坐标
    def transfromScreen(self,coord):
        return (coord[0]*mVars.boradOne+mVars.borad[0],coord[1]*mVars.boradOne+mVars.borad[1])
    
    #对比两张图片的差异
    def difference(self,img1,img2):
        return img1-img2

ADB module

This module interacts with the phone, I use a piece of ADB wireless connection, of course, also be a wired connection, see the tutorial on ADB connection https://github.com/mzlogin/awesome-adb

import os
import time
class Adb:
    #无线连接手机
    def __init__(self):
        os.system('adb connect 1.1.1.1:5555')#ip 示例
        os.system('adb devices')
    #捕获截图
    def capture(self):
        os.system('adb exec-out screencap -p > '+mVars.address+'sc.jpg')
        return ac.imread(mVars.address+'sc.jpg')
    #点击特定位置
    def click(self,piexl):
        os.system('adb shell input tap %d %d'%(piexl[0],piexl[1]))
        time.sleep(0.1)
        os.system('adb shell input tap %d %d'%(piexl[0],piexl[1]))
Game System Module
class System:
    Yixin = YiXin() 
    ImageP = ImageProcess()
    Adb = Adb()
    imgobj = None #用来检测对手落子的图片
    certain = 0 #1表示己方为白,2表示己方为黑
    
    #确认是否胜利
    def confirmWin(self,imgsrc):
        x0,y0,x1,y1 = mVars.confirmWin
        imgsrc = imgsrc[y0:y1,x0:x1]
        imgobj = ac.imread(mVars.address+'confirmwin.jpg')
        return self.ImageP.matchImg(imgsrc,imgobj,0.9)
    
    #确认己方是黑棋还是白棋
    def confirmBW(self,imgsrc):
        x0,y0,x1,y1 = mVars.confirmBW
        imgsrc = imgsrc[y0:y1,x0:x1]

        imgobjw = ac.imread(mVars.address+'confirmw.jpg')
        imgobjb = ac.imread(mVars.address+'confirmb.jpg')
        
        if (self.ImageP.matchImg(imgsrc,imgobjw,0.8) != None):
            self.certain = 1
            self.imgobj=ac.imread(mVars.address+'objb.jpg')
        elif (self.ImageP.matchImg(imgsrc,imgobjb,0.8)!= None):
            self.certain = 2
            self.imgobj=ac.imread(mVars.address+'objw.jpg')
    
    #做好比赛前准备,
    def ready(self):
        while True:
            imgsrc = self.Adb.capture()
            self.confirmBW(imgsrc)
            if(self.certain != 0):
                break;
            print('UnCertain')
            time.sleep(1)
        
        if self.certain == 2:
            self.runCommand('BEGIN')
            return imgsrc
        elif self.certain == 1:
            return ac.imread(mVars.address+'None.jpg')
    
    #向Yixin 输入对方落点,获得Yixin 落点并点击屏幕
    def runCommand(self,COMMAND):
        self.Yixin.input(COMMAND)
        str = self.Yixin.output()
        a = str.find(',')
        b = str.find('\r')

        piexl = self.ImageP.transfromScreen((int(str[0:a]),int(str[a+1:b])))
        # print(piexl)
        self.Adb.click(piexl)
        
    #开始游戏
    def play(self,imgsrc):
        flag=False
        imagep = self.ImageP
        oldimg = newimg = imgsrc
        while self.confirmWin(newimg) == None:
            imgdif = imagep.difference(oldimg,newimg)
            ac.cv2.imwrite(mVars.address+'diff.jpg',imgdif)
            coord = imagep.matchImg(imgdif,self.imgobj)
            # print(coord)
            if(coord != None):
                x, y = imagep.transformBoard(coord)
                COMMAND = "TURN %d,%d"%(x,y)
                self.runCommand(COMMAND)
            
            oldimg,newimg = newimg,self.Adb.capture()
            time.sleep(0.8)
        
    #新一轮游戏
    def newGame(self):
        time.sleep(4)
        os.system('cls')
        os.system('adb shell input tap %d %d'%(100,1820))
        time.sleep(0.5)
        os.system('adb shell input tap %d %d'%(540,940))
        
        self.Yixin.restart()
        self.certain = 0
        self.imgobj = None

The main function
msys = System()
# n = input("请输入你想玩的局数:")
# for i in range(1,int(n)+1):
while True:
    imgBegin = msys.ready()
    msys.play(imgBegin)
    print("You Win !! Next Game Will Begin After 4sec")
    msys.newGame()

postscript

All code to the end here, will later be used to sort out the resources before uploading.
Has been successful on the highest level, winning is not 100%, because there is no joy backgammon ban on hand, so when the player using occasionally lose, but win Zhihei

Guess you like

Origin www.cnblogs.com/starrys/p/12591415.html
Aid