from threading import Thread
from network import *
from genom import Genom
import pygame
# air # NEURO TYPE - 0
food = [] # list of food (x,y) positions in the maze # NEURO TYPE - 1
other_players = [] # list of other players (x,y) positions in the maze # NEURO TYPE - 2
kill_blocks = [] # list of kill blocks (x,y) positions in the maze # NEURO TYPE - 3
pop_size = 128
pop = []
x_size = 512
y_size = 512
view_size = 4
block_size = 4
# init pygame and create window and surface objects for drawing the maze and the players on it
pygame.init()
screen = pygame.display.set_mode((x_size, y_size))
'''
(up - 0, down - 1, left - 2, right - 3) - 0-3
(go - 0, nothing - 1, eat - 2, kill - 3, cross - 4) - 4-8
9
'''
def getBestGenom(pop) -> Genom:
best = pop[0]
for genom in pop:
if genom.fitnes > best.fitnes:
best = genom
return best
# Create a population of random networks.
for i in range(pop_size):
genom = Genom(NeuralNetwork([(((view_size*2)+1)**2), 9, 9], nmin=0, nmax=3), i)
pop.append(genom)
def getMaxOfArray(array: list) -> int:
return max(range(len(array)), key=lambda i: array[i])
def setPosGenom(pop):
for genom in pop:
genom.myPos = (randint(0, x_size), randint(0, y_size))
if genom.myPos in food:
genom.myPos = (randint(0, x_size), randint(0, y_size))
if genom.myPos in other_players:
genom.myPos = (randint(0, x_size), randint(0, y_size))
if genom.myPos in kill_blocks:
genom.myPos = (randint(0, x_size), randint(0, y_size))
other_players.append(genom.myPos)
def newPop(old_Genom: 'Genom'):
global pop
old_Genom.NN.save("NNs/nn_" + str(old_Genom.index) + ".pkl")
pop = []
for i in range(pop_size):
genom = Genom(None, i)
genom.NN = old_Genom.NN.clone()
# Mutate the genom with a random chance.
if random() < 0.25:
genom.NN.mutate(0.20)
pop.append(genom)
setPosGenom(pop)
setPosGenom(pop)
# Game logic
while True:
for i in range(1, 100000):
screen.fill((255, 255, 255))
print("Iteration: " + str(i))
# for genom in pop:
# if not genom.islife:
other_players = []
for genom in pop:
other_players.append(genom.myPos)
for genom in range(len(pop)):
genom = pop[genom]
if genom.islife:
if genom.hp <= 0:
genom.islife = False
genom.fitnes -= 25
other_players.remove(genom.myPos)
food.append(genom.myPos)
continue
input_array = []
for y in range(genom.myPos[1]-view_size, genom.myPos[1]+view_size+1):
for x in range(genom.myPos[0]-view_size, genom.myPos[0]+view_size+1):
if x >= 0 and x < x_size and y >= 0 and y < y_size:
if (x, y) in food:
input_array.append(1)
elif (x, y) in other_players:
input_array.append(2)
elif (x, y) in kill_blocks:
input_array.append(3)
else:
input_array.append(0)
else:
input_array.append(0)
output = genom.getOutput(input_array)
goTo = getMaxOfArray(output[:4])
doSome = getMaxOfArray(output[-5:])
if doSome == 0: # Go
if goTo == 0:
genom.myPos = (genom.myPos[0]-1, genom.myPos[1])
elif goTo == 1:
genom.myPos = (genom.myPos[0]+1, genom.myPos[1])
elif goTo == 2:
genom.myPos = (genom.myPos[0], genom.myPos[1]-1)
elif goTo == 3:
genom.myPos = (genom.myPos[0], genom.myPos[1]+1)
genom.fitnes += 1
elif doSome == 1: # Nothing
genom.fitnes -= 0.1
elif doSome == 2: # Eat
if (genom.myPos[0], genom.myPos[1]) in food:
food.remove((genom.myPos[0], genom.myPos[1]))
genom.hp += 50
genom.fitnes += 5
elif doSome == 3: # Kill
if (genom.myPos[0], genom.myPos[1]) in kill_blocks:
kill_blocks.remove((genom.myPos[0], genom.myPos[1]))
genom.hp -= 10
genom.fitnes -= 15
elif doSome == 4:
if goTo == 0:
cpos = (genom.myPos[0]-1, genom.myPos[1])
elif goTo == 1:
cpos = (genom.myPos[0]+1, genom.myPos[1])
elif goTo == 2:
cpos = (genom.myPos[0], genom.myPos[1]-1)
elif goTo == 3:
cpos = (genom.myPos[0], genom.myPos[1]+1)
if (genom.myPos[0], genom.myPos[1]) in other_players:
for genom2 in pop:
if genom2.myPos == cpos and genom2.islife:
genom2.hp -= 5
genom.fitnes += 100
new_genom = Genom(genom.cross(genom2.NN), len(pop))
print("New life: " + str(new_genom.index))
if random() < 0.25:
new_genom.NN.mutate(0.20)
pop.append(new_genom)
break
else:
genom.fitnes -= 15
genom.hp -= 1
if len(food) <= 512:
for i in range(512-len(food)):
food.append((randint(0, x_size), randint(0, y_size)))
if len(kill_blocks) <= 512:
for i in range(512-len(kill_blocks)):
kill_blocks.append((randint(0, x_size), randint(0, y_size)))
for genom in pop:
if genom.islife:
# Draw rect for genom position and hp bar and genom index and fitnes value on it.
if genom.myPos[0] >= 0 and genom.myPos[0] < x_size and genom.myPos[1] >= 0 and genom.myPos[1] < y_size:
pygame.draw.rect(screen, (255, 0, 0), (genom.myPos[0]*10, genom.myPos[1]*10, 10, 10), 0)
pygame.draw.rect(screen, (0, 255, 0), (genom.myPos[0]*10, genom.myPos[1]*10, 10, 10), int(10*genom.hp/150))
for food_pos in food:
# Daraw rect for food position and food index on it.
if food_pos[0] >= 0 and food_pos[0] < x_size and food_pos[1] >= 0 and food_pos[1] < y_size:
pygame.draw.rect(screen, (0, 255, 0), (food_pos[0]*10, food_pos[1]*10, 10, 10), 0)
for kill_pos in kill_blocks:
# Daraw rect for kill block position and kill block index on it.
if kill_pos[0] >= 0 and kill_pos[0] < x_size and kill_pos[1] >= 0 and kill_pos[1] < y_size:
pygame.draw.rect(screen, (255, 0, 0), (kill_pos[0]*10, kill_pos[1]*10, 10, 10), 0)
pygame.display.flip()
pygame.display.update()
if len(other_players) == 0:
print("No life")
break
newPop(getBestGenom(pop))