[PYTHON] A story about competing with a friend in Othello AI Preparation

How many years ago did AlphaGo win the Go World Champion (three years ago ^ 1)? Nowadays, various methods have been developed, and it seems that AIs often fight each other.

So, this time, I'm going to fight the AI made by my friend N and my one (what is the hundreds of millions of brews?).

I will write it as a series like a diary, so thank you.

Tied up

I set up a bond when playing against a friend this time. that is

** Do not search at all **

AlphaZero, the successor to AlphaGo, has gained strength by a method ^ 1 that combines Monte Carlo tree search and deep learning, but half of it is intentionally discarded. The reason for this kind of binding is that my friends make AI using a method that focuses on searching. It is a composition of so-called search vs. deep learning.

Then, how to make AI is to play a game based on random numbers and generated models and let AI learn the musical score information. The model will do its best to pick up the features required to win.

Preparation

When making Othello AI, the first thing you need is rule-making and board information management means for Othello itself. So in this preparatory section, I would like to explain the situation when they were made.

First of all, I would like to say something.

** Save any means of speeding up other than the algorithm **

I didn't pay much attention to speeding up the Othello game itself (I thought it was an error level because it's an 8 * 8 board), but now that I've already started learning, the reading is sweet. Is echoing the current situation. I have a clear idea about speeding up, so I hope I can write about that article as well.

Initialize, move

othello.py


def othelloInit():
    board = np.zeros((8,8))
    board[4-1][4-1]=1
    board[5-1][5-1]=1
    board[4-1][5-1]=-1
    board[5-1][4-1]=-1
    board=board.astype(np.int32)
    return board

def othelloMove(board,move):
    if type(move)==int:
        return -1
    tempBoard=othelloMovable(board,move)
    if type(tempBoard) ==np.ndarray:
        return tempBoard
    else:   
        return 0



I will write all about Othello's game system in othello.py. othelloInit () returns the first board state of Othello (the state where black and white pieces are placed in the reversi state only in the middle) in numpy.ndarray format.

Also, since the board information is directly put into the model, it is not classified.

othelloMove () updates the board information based on the information of the move variable. Checks if it can be updated with othelloMovable (), returns 0 if not, and board information if possible.

Can you move?

othello.py


def othelloBlank(board,move):#0 if free, 1 if not free
    k=(board[move[0]][move[1]])*(board[move[0]][move[1]])

    return k
def othelloMovable(Board,Move):#Judge whether it is in move, if it can, return board information after placing, if not, return 0
    board=Board.copy()
    move=copy.deepcopy(Move)
    old_board=board.copy()
    if move[0]<0:
        move[0]=0
    elif move[0]>=8:
        move[0]=7
    if move[1]<0:
        move[1]=0
    elif move[1]>=8:
        move[1]=7
    if othelloBlank(board,move)==1:
        return 0
    for i in range(1,9):
        
        #print("ColorCheck:"+str(ColorCheck(board,move,i))+" i:"+str(i))
        if ColorCheck(board,move,i)==-1:
            if i==1:#Up
                #print("i:"+str(i))
                check=1
                for k in range(move[1],8):#Checking the mass including yourself
                    
                    if k==move[1]:#I have already checked, so pass
                        pass
                    else:
                        #print([move[0],k])
                        temp=ColorCheck(board,[move[0],k],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                        
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[move[0]][c+move[1]]=1
                        break
            elif i==2:#Upper right
                #print("i:"+str(i))
                temp_move=max(move)
                check=1
                for k in range(temp_move,8):#Checking the mass including yourself
                    
                    if k==temp_move:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[move[0]+k-temp_move,move[1]+k-temp_move],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[c+move[0]][c+move[1]]=1
                        break
            elif i==3:#right
                #print("i:"+str(i))
                check=1
                for k in range(move[0],8):#Checking the mass including yourself
                    
                    if k==move[0]:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[k,move[1]],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                          
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[move[0]+c][move[1]]=1
                        break
            elif i==4:#Lower right
                #print("i:"+str(i))
                temp_move=max(move[0],7-move[1])
                check=1
                for k in range(temp_move,8):#Checking the mass including yourself
                    
                    if k==temp_move:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[move[0]+k-temp_move,move[1]-k+temp_move],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[c+move[0]][-c+move[1]]=1
                        break
            elif i==5:#under
                #print("i:"+str(i))
                check=1
                for k in range(move[1],0,-1):#Checking the mass including yourself
                    
                    if k==move[1]:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[move[0],k],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[move[0]][-c+move[1]]=1
                        break
            elif i==6:#Lower left
                #print("i:"+str(i))
                temp_move=min(move)
                check=1
                for k in range(temp_move,0,-1):#Checking the mass including yourself
                    
                    if k==temp_move:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[move[0]+k-temp_move,move[1]+k-temp_move],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[-c+move[0]][-c+move[1]]=1
                        break
            elif i==7:#left
                #print("i:"+str(i))
                check=1
                for k in range(move[0],0,-1):#Checking the mass including yourself
                    
                    if k==move[0]:#I have already checked, so pass
                        pass
                    else:
                        temp=ColorCheck(board,[k,move[1]],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                           
                            break
                            
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[move[0]-c][move[1]]=1
                        break
            elif i==8:#upper left
                #print("i:"+str(i))
                temp_move=max(7-move[0],move[1])
                check=1
                for k in range(temp_move,8):#Checking the mass including yourself
                    
                    if k==temp_move:#I have already checked, so pass
                        pass
                    else:
                        
                        temp=ColorCheck(board,[move[0]-k+temp_move,move[1]+k-temp_move],i)#Mass check
                        #print("Check:"+str(check))
                        if temp==-1:#Increase the count if your opponent
                            check=check+1
                        elif temp==1 and check>0:#If you are yourself, reverse, except when the opponent's square never appeared
                            check=check*-1
                        else:#Exclude because it does not reverse
                            
                            break
                    if check<0:#Negative value can be left
                        for c in range(0,(check*-1)+1):#Determine the cell to be changed by referring to the count value.
                            board[-c+move[0]][c+move[1]]=1
                        break
    if np.allclose(board,old_board):
        #print("I can't put it")
        return 0
    return board

long... othelloBlank () checks if it is free on the board based on the move information. I didn't want to use branching, so I forcibly calculate and return it.

othelloMovable () checks whether it is in a rule (whether there is a piece to flip) based on move information. It's just long. I wrote it in the midnight tension, and I feel that I was still trying to improve it at that time, but it seems that this is the cause of the slowness.

Did you do it? And others

othello.py


def othelloEndCheck(board):#Find out if there is another place to go. Returns 1 if it can be placed, 0 if it cannot be placed.
    for i in range(0,8):
        for n in range(0,8):
            #print([i,n])
            if type(othelloMovable(board,[i,n]))==np.ndarray:
                #print("Nope")
                return 1
    return 0

def ColorCheck(board,axis,way):#Start 1 clockwise and reserve up to 8. 0 is omnidirectional. If off board-2,If the other party-Returns 1, 0 for blanks, 1 for itself.
    if way==1:
        if axis[1]>=7:
            return -2
        else:
            #print("ColorCheck")
            #print(board[axis[0]][axis[1]+1])
            return board[axis[0]][axis[1]+1]
    elif way==2:
        if axis[0]>=7 or axis[1]>=7:
            return -2
        else:
            return board[axis[0]+1][axis[1]+1]
    elif way==3:
        if axis[0]>=7:
            return -2
        else:
            return board[axis[0]+1][axis[1]]
    elif way==4:
        if axis[0]>=7 or axis[1]<=0:
            return -2
        else:
            return board[axis[0]+1][axis[1]-1]       
    elif way==5:
        if axis[1]<=0:
            return -2
        else:
            return board[axis[0]][axis[1]-1]
    elif way==6:
        if axis[1]<=0 or axis[0]<=0:
            return -2
        else:
            return board[axis[0]-1][axis[1]-1]
    elif way==7:
        if axis[0]<=0:
            return -2
        else:
            return board[axis[0]-1][axis[1]]
    elif way==8:
        if axis[0]<=0 or axis[1]>=7:
            return -2
        else:
            return board[axis[0]-1][axis[1]+1]


    return 0

This is also long ... othelloEndCheck () checks to see if there are any more moves. Returns 1 if you can hit it, 0 if you can't hit it.

ColorCheck () returns the color of the surrounding frames based on the move information (why only you don't have othello?). I didn't use all directions in the comment out, so I haven't implemented it yet.

The one who displays something

othello.py


def othelloReverse(Board):
    board=Board.copy()
    #print("reversing")
    board=board*-1
    return board

def othelloShow(board):
    for i in reversed(range(0,8)):#y
        #print("i:"+str(i))
        for k in range(0,8):#x
            if board[k][i]==-1:
                print("○",end=" ")
            elif board[k][i]==1:
                print("●",end=" ")
            elif board[k][i]==0:
                print("■",end=" ")
        print("")
        print("")
    #print(board[7])
    return 0

othelloReverse () flips the color of the board. In other words, the first and second attacks are replaced. As a result, the hitting side will always be 1 on the board data.

othelloShow () shows the status of the board. It's a bit annoying to make the bottom left (0,0). In the future, I would like to use the gui method using pygames for convenience.

Summary

** The one who is definitely on the net is faster. ** **

I'm not a person who can do competitive programming very much, and I'm not a programming enthusiast, so I can't think of an algorithm that can be done faster.

And I was shocked to know how to speed up after making all of these ...

I hope to see you next time in the model construction edition.

Recommended Posts

A story about competing with a friend in Othello AI Preparation
A story about machine learning with Kyasuket
A story about implementing a login screen with django
A story packed with absolute values in numpy.ndarray
A story about making 3D space recognition with Python
A story about using Resona's software token with 1Password
A story about predicting exchange rates with Deep Learning
A story about making Hanon-like sheet music with Python
A story about trying a (Golang +) Python monorepo with Bazel
A story about reflecting Discord activity in Slack Status
A story about how theano was moved with TSUBAME 2.0
A story about a Linux beginner passing LPIC101 in a week
A story about how to specify a relative path in python.
A story about installing matplotlib using pip with an error
A story about an amateur making a breakout with python (kivy) ②
[Note] A story about trying to override a class method with two underscores in Python 3 series.
A story about how to deal with the CORS problem
Machine learning A story about people who are not familiar with GBDT using GBDT in Python
A story about an amateur making a breakout with python (kivy) ①
A story about making a tanka by chance with Sudachi Py
[Django] A story about getting stuck in a swamp trying to validate a zip with form [TDD]
A story about trying to implement a private variable in Python.
A story about a tragedy happening by exchanging commands in chat
A story about a python beginner stuck with No module named'http.server'
A story about everything from data collection to AI development and Web application release in Python (3. AI development)
A story about adding a REST API to a daemon made with Python
A story about a build error in a shared library that references libusb
A story about developing a soft type with Firestore + Python + OpenAPI + Typescript
A refreshing story about Python's Slice
A note about get_scorer in sklearn
A sloppy story about Python's Slice
Let's make Othello AI with Chainer-Part 1-
A story about using Python's reduce
Let's make Othello AI with Chainer-Part 2-
The story of a Parking Sensor in 10 minutes with GrovePi + Starter Kit
[Small story] How to save matplotlib graphs in a batch with Jupyter
A story about a beginner making a VTuber notification bot from scratch in Python
A story about automating online mahjong (Mahjong Soul) with OpenCV and machine learning
[Memorandum] A story about trying OpenCV tutorial (face recognition) in a Windows environment
Spiral book in Python! Python with a spiral book! (Chapter 14 ~)
A story about remodeling Lubuntu into a Chromebook
Draw a heart in Ruby with PyCall
[Easy] AI automatic recognition with a webcam!
A story about Python pop and append
Let's make a tic-tac-toe AI with Pylearn 2
A story about a 503 error on Heroku open
A story about a programming beginner who made a business efficiency map application with GeoDjango
[Note] A story about not being able to break through a proxy with pip
A confusing story with two ways to implement XGBoost in Python + overall notes
A story about building an IDE environment with WinPython on an old Windows OS.
A story that turned light blue in 4 months after starting AtCoder with python
Escape from Python's virtual environment ~ A story about being trapped in a virtual environment I created ~
A story about making an x86 bootloader that can boot vmlinux with Rust