Hive/player algo.py
2024-01-11 18:29:56 +01:00

273 lines
No EOL
9.4 KiB
Python

import re
import base as Base
import copy, random, time, math
from PIL import Image, ImageDraw
# Player template for HIVE --- ALP semestral work
# Vojta Vonasek, 2023
r = [[0,-1],[1,-1],[1,0],[0,1],[-1,1],[-1,0]]
totalPieces = 18
def cn(graph,cell,visited):
n = 0
for i in graph[str(cell)][0]:
if(visited.get(str(i)) == None and graph[str(i)][1] == False):
visited[str(i)] = True
n += len(graph[str(i)][2])
n += cn(graph,i,visited)
return n
# PUT ALL YOUR IMPLEMENTATION INTO THIS FILE
class Player(Base.Board):
def __init__(self, playerName, myIsUpper, size, myPieces, rivalPieces): #do not change this line
Base.Board.__init__(self, myIsUpper, size, myPieces, rivalPieces) #do not change this line
self.playerName = playerName
self.algorithmName = "myGreatMethod"
def getCount(self):
n = 0
for i in self.myPieces.values():
n += i
for i in self.rivalPieces.values():
n += i
return totalPieces - n
def getMyCount(self):
n = 0
for i in self.myPieces.values():
n += i
return n
def connected(self,graph,cell):
for i in graph[str(cell)][0]:
if(graph[str(i)][1] == False):
break
return self.getCount()-1 == cn(graph, i, {str(cell): True, str(i): True}) + len(graph[str(i)][2])
def spider(self,graph,cell,n,visited):
n += 1
visited[str(cell)] = True
if(n == 4):
return [cell]
result = []
for i in graph[str(cell)][0]:
hive = False
empty = False
if(visited.get(str(i)) == None and graph[str(i)][1]):
for j in graph[str(i)][0]:
if(empty and hive):
break
if(j in graph[str(cell)][0]):
if(graph[str(j)][1] or visited.get(str(j))):
empty = True
else:
hive = True
if(empty and hive):
result += self.spider(graph,i,n,visited.copy())
return result
def bee(graph,cell):
result = []
for i in graph[str(cell)][0]:
if(graph[str(i)][1]):
hive = False
empty = False
for j in graph[str(i)][0]:
if(hive and empty):
break
if(j in graph[str(cell)][0]):
if(graph[str(j)][1]):
empty = True
else:
hive = True
if(hive and empty):
result.append(i)
return result
def grasshopper(graph,cell):
result = []
for i in r:
q = [cell[0]+i[0],cell[1]+i[1]]
if(graph.get(str(q))[1] == False):
while(True):
q = [q[0]+i[0],q[1]+i[1]]
if(graph.get(str(q)) != None):
if(graph.get(str(q))[1]):
result.append(q)
break
else:
break
return result
def bug(graph,cell):
if(len(graph[str(cell)][2]) > 1):
return graph[str(cell)][0]
result = []
for i in graph[str(cell)][0]:
if(graph[str(i)][1]):
for j in graph[str(i)][0]:
if(j[0] != cell[0] or j[1] != cell[1]):
if(graph[str(j)][1] == False):
result.append(i)
break
else:
result.append(i)
return result
def ant(self,graph,cell,visited):
visited[str(cell)] = True
result = []
for i in graph[str(cell)][0]:
hive = False
empty = False
if(visited.get(str(i)) == None and graph[str(i)][1]):
for j in graph[str(i)][0]:
if(empty and hive):
break
if(j in graph[str(cell)][0]):
if(graph[str(j)][1] or visited.get(str(j))):
empty = True
else:
hive = True
if(empty and hive):
result += [i]
result += self.ant(graph,i,visited)
return result
def move(self):
""" return [animal, oldP, oldQ, newP, newQ], or [animal, None, None, newP, newQ] or [] """
graph = {}
# [0] neighbours [1] empty [2] myFigure
myFigures = []
# GET GRAPH,MYFIGURES
for k,v in self.board.items():
for q,a in v.items():
ng = []
for i in r:
if(self.inBoard(k+i[0],q+i[1])):
ng.append([k+i[0],q+i[1]])
graph[str([k,q])] = [ng,a == "",self.myColorIsUpper == a.isupper()]
if(a != ""):
if(self.myColorIsUpper == a.isupper()):
myFigures.append([k,q])
# GET Movable,Empty
movableFigures = {}
emptyCells = []
for cell in myFigures:
# Get all empty cells
if(self.getMyCount() != 0):
for i in r:
q = [cell[0]+i[0],cell[1]+i[1]]
qs = str(q)
if(graph.get(qs) != None):
if(graph[qs][1] == True):
enemy = False
for j in r:
qq = [q[0]+j[0],q[1]+j[1]]
qqs = str(qq)
if(graph.get(qqs) != None):
if(graph[qqs][1] == False):
if(graph[qqs][2] == False):
enemy = True
break
if(not enemy):
emptyCells.append(q)
# Get all moves
if(self.myMove > 3):
if(self.connected(graph,cell)):
animal = graph[str(cell)][2][-1].lower()
arr = []
if(animal == 's'):
arr = self.spider(graph,cell,0,{})
elif(animal == 'b'):
arr = self.bug(graph,cell)
elif(animal == 'g'):
arr = self.grasshopper(graph,cell)
elif(animal == 'a'):
arr = self.ant(graph,cell,{})
else:
arr = self.bee(graph,cell)
if(len(arr) > 0):
movableFigures[str(cell)] = arr
# can't place or move
if(len(emptyCells) == 0 and len(movableFigures) == 0):
return []
# 0 - center or around
if(self.myMove == 0):
animal = random.choice(list(self.myPieces.keys()))
if(self.getCount() == 0):
return [animal,None,None,3,6]
else:
m = [[2,6],[4,6],[3,5],[4,5],[2,7],[3,7]]
n = random.randint(0,len(m)-1) # !
return [animal, None,None,m[n][0],m[n][1]]
# 1-3 - place figures
# 3 - must place queen
# 4+ - can move or place
# end
# - bee is surrounded - all neighbours arr full
# - move n > 80
# - both player can't play
return []
def updatePlayers(move, activePlayer, passivePlayer):
""" write move made by activePlayer player
this method assumes that all moves are correct, no checking is made
"""
if len(move) == 0:
return
animal, p,q, newp, newq = move
if p == None and q == None:
#placing new animal
activePlayer.myPieces[animal]-=1
passivePlayer.rivalPieces = activePlayer.myPieces.copy()
else:
#just moving animal
#delete its old position
activePlayer.board[p][q] = activePlayer.board[p][q][:-1]
passivePlayer.board[p][q] = passivePlayer.board[p][q][:-1]
activePlayer.board[newp][newq] += animal
passivePlayer.board[newp][newq] += animal
if __name__ == "__main__":
boardSize = 13
smallFigures = { "q":1, "a":2, "b":2, "s":2, "g":2 } #key is animal, value is how many is available for placing
bigFigures = { figure.upper(): smallFigures[figure] for figure in smallFigures } #same, but with upper case
P1 = Player("player1", False, 13, smallFigures, bigFigures)
P2 = Player("player2", True, 13, bigFigures, smallFigures)
filename = "begin.png"
P1.saveImage(filename)
moveIdx = 0
while True:
move = P1.move()
print("P1 returned", move)
updatePlayers(move, P1, P2) #update P1 and P2 according to the move
filename = "move-{:03d}-player1.png".format(moveIdx)
P1.saveImage(filename)
move = P2.move()
print("P2 returned", move)
updatePlayers(move, P2, P1) #update P2 and P1 according to the move
filename = "move-{:03d}-player2.png".format(moveIdx)
P1.saveImage(filename)
moveIdx += 1
P1.myMove = moveIdx
P2.myMove = moveIdx
if moveIdx > 50:
print("End of the test game")
break