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.
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.
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.
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.
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.
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.
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.
** 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