diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..73f69e0 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/NNCars.iml b/.idea/NNCars.iml new file mode 100644 index 0000000..9377184 --- /dev/null +++ b/.idea/NNCars.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/sevenchords.xml b/.idea/dictionaries/sevenchords.xml new file mode 100644 index 0000000..a5af36f --- /dev/null +++ b/.idea/dictionaries/sevenchords.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..dd4c951 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..8836c5c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..e432a6e --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/other.xml b/.idea/other.xml new file mode 100644 index 0000000..a708ec7 --- /dev/null +++ b/.idea/other.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/mapGen.py b/mapGen.py index 65e02f9..ceb18b3 100644 --- a/mapGen.py +++ b/mapGen.py @@ -1,11 +1,9 @@ import pygame import sys import random -import time -import math -import numpy as np from PIL import Image + class Cell: # A wall separates a pair of cells in the N-S or W-E directions. wall_pairs = {'N': 'S', 'S': 'N', 'E': 'W', 'W': 'E'} @@ -24,14 +22,17 @@ def knock_down_wall(self, other, wall): self.walls[wall] = False other.walls[Cell.wall_pairs[wall]] = False + class Maze: """A Maze, represented as a grid of cells.""" def __init__(self, nx, ny, ix=0, iy=0): self.nx, self.ny = nx, ny self.ix, self.iy = ix, iy self.maze_map = [[Cell(x, y) for y in range(ny)] for x in range(nx)] + def cell_at(self, x, y): return self.maze_map[x][y] + def find_valid_neighbours(self, cell): """Return a list of unvisited neighbours to cell.""" @@ -48,177 +49,184 @@ def find_valid_neighbours(self, cell): neighbours.append((direction, neighbour)) return neighbours + pygame.init() SCREEN = pygame.display.set_mode((1600, 900)) CLOCK = pygame.time.Clock() + def generateRandomMap(): - BLACK = (0, 0, 0) - WHITE = (255, 255, 255) + # BLACK = (0, 0, 0) + # WHITE = (255, 255, 255) GREEN = (0, 255, 128) WINDOW_HEIGHT = 730 - WINDOW_WIDTH = 1460 #These are for the maze/grid, not for the pygame window size + WINDOW_WIDTH = 1460 + # These are for the maze/grid, not for the pygame window size - blockSize = 146 #Set the size of the grid block + blockSize = 146 + # Set the size of the grid block rows, cols = (int(WINDOW_WIDTH/blockSize), int(WINDOW_HEIGHT/blockSize)) - maze = Maze(rows,cols,0,0) + maze = Maze(rows, cols, 0, 0) - trackLenght = 1 - movex = 70 - movey = 85 + trackLength = 1 + moveX = 70 + moveY = 85 - startx, starty = 0, 3 - currentCell = maze.cell_at(startx, starty) + startX, startY = 0, 3 + currentCell = maze.cell_at(startX, startY) - straight1 = pygame.image.load('Images\TracksMapGen\Straight1.png') + straight1 = pygame.image.load('Images/TracksMapGen/Straight1.png') straight1Rect = straight1.get_rect() - straight2 = pygame.image.load('Images\TracksMapGen\Straight2.png') + straight2 = pygame.image.load('Images/TracksMapGen/Straight2.png') straight2Rect = straight2.get_rect() - curve1 = pygame.image.load('Images\TracksMapGen\Curve1.png') + curve1 = pygame.image.load('Images/TracksMapGen/Curve1.png') curve1Rect = curve1.get_rect() - curve2 = pygame.image.load('Images\TracksMapGen\Curve2.png') + curve2 = pygame.image.load('Images/TracksMapGen/Curve2.png') curve2Rect = curve2.get_rect() - curve3 = pygame.image.load('Images\TracksMapGen\Curve3.png') + curve3 = pygame.image.load('Images/TracksMapGen/Curve3.png') curve3Rect = curve3.get_rect() - curve4 = pygame.image.load('Images\TracksMapGen\Curve4.png') + curve4 = pygame.image.load('Images/TracksMapGen/Curve4.png') curve4Rect = curve4.get_rect() - straight1Top = pygame.image.load('Images\TracksMapGen\Straight1Top.png') + straight1Top = pygame.image.load('Images/TracksMapGen/Straight1Top.png') straight1RectTop = straight1Top.get_rect() - straight2Top = pygame.image.load('Images\TracksMapGen\Straight2Top.png') + straight2Top = pygame.image.load('Images/TracksMapGen/Straight2Top.png') straight2RectTop = straight2Top.get_rect() - curve1Top = pygame.image.load('Images\TracksMapGen\Curve1Top.png') + curve1Top = pygame.image.load('Images/TracksMapGen/Curve1Top.png') curve1RectTop = curve1Top.get_rect() - curve2Top = pygame.image.load('Images\TracksMapGen\Curve2Top.png') + curve2Top = pygame.image.load('Images/TracksMapGen/Curve2Top.png') curve2RectTop = curve2Top.get_rect() - curve3Top = pygame.image.load('Images\TracksMapGen\Curve3Top.png') + curve3Top = pygame.image.load('Images/TracksMapGen/Curve3Top.png') curve3RectTop = curve3Top.get_rect() - curve4Top = pygame.image.load('Images\TracksMapGen\Curve4Top.png') + curve4Top = pygame.image.load('Images/TracksMapGen/Curve4Top.png') curve4RectTop = curve4Top.get_rect() - bg = pygame.image.load('Images\TracksMapGen\Background.png') + bg = pygame.image.load('Images/TracksMapGen/Background.png') while True: - #CurrentCell is the one at (0,3) position, im gonna look if there are unvisited cells from there + # CurrentCell is the one at (0,3) position, im gonna look if there are unvisited cells from there if len(maze.find_valid_neighbours(currentCell)) > 0: - if currentCell.x == 0 and currentCell.y == 3: #Second cell is always the one on top of first cell bc first cell is always a straight vertical track + + # Second cell is always the one on top of first cell bc first cell is always a straight vertical track + if currentCell.x == 0 and currentCell.y == 3: oldCell = currentCell - currentCell = maze.cell_at(oldCell.x,oldCell.y-1) + currentCell = maze.cell_at(oldCell.x, oldCell.y-1) currentCell.color = GREEN oldCell.knock_down_wall(currentCell, "N") - trackLenght += 1 #Keep track of length so to discard very short generated tracks + trackLength += 1 # Keep track of length so to discard very short generated tracks else: - random_unvisited_direction = random.choice(maze.find_valid_neighbours(currentCell))[0] #Pick a random direction to move + + # Pick a random direction to move + random_unvisited_direction = random.choice(maze.find_valid_neighbours(currentCell))[0] oldCell = currentCell - if random_unvisited_direction == "N": #Move according to the direction picked - currentCell = maze.cell_at(oldCell.x,oldCell.y-1) + if random_unvisited_direction == "N": # Move according to the direction picked + currentCell = maze.cell_at(oldCell.x, oldCell.y-1) elif random_unvisited_direction == "S": - currentCell = maze.cell_at(oldCell.x,oldCell.y+1) + currentCell = maze.cell_at(oldCell.x, oldCell.y+1) elif random_unvisited_direction == "E": - currentCell = maze.cell_at(oldCell.x+1,oldCell.y) + currentCell = maze.cell_at(oldCell.x+1, oldCell.y) elif random_unvisited_direction == "W": - currentCell = maze.cell_at(oldCell.x-1,oldCell.y) + currentCell = maze.cell_at(oldCell.x-1, oldCell.y) oldCell.knock_down_wall(currentCell, random_unvisited_direction) - trackLenght += 1 + trackLength += 1 else: - #Track is ready (back in initial position)! lets check if its long enough - if currentCell.x == 0 and currentCell.y == 4 and trackLenght > 40: - currentCell.knock_down_wall(maze.cell_at(0,3), "N") + # Track is ready (back in initial position)! lets check if its long enough + if currentCell.x == 0 and currentCell.y == 4 and trackLength > 40: + currentCell.knock_down_wall(maze.cell_at(0, 3), "N") for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) - currentCell.color = (0,0,1,255) + currentCell = maze.cell_at(int(x/blockSize), int(y/blockSize)) + currentCell.color = (0, 0, 1, 255) for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) + currentCell = maze.cell_at(int(x/blockSize), int(y/blockSize)) - if currentCell.walls["N"] == False and currentCell.walls["S"] == False: - SCREEN.blit(straight2, straight2Rect.move(x+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["W"] == False: - SCREEN.blit(straight1, straight1Rect.move(x+movex,y+movey)) - elif currentCell.walls["N"] == False and currentCell.walls["W"] == False: - SCREEN.blit(curve3, curve3Rect.move(x+movex,y+movey)) - elif currentCell.walls["W"] == False and currentCell.walls["S"] == False: - SCREEN.blit(curve2, curve2Rect.move(x+movex,y+movey)) - elif currentCell.walls["S"] == False and currentCell.walls["E"] == False: - SCREEN.blit(curve1, curve1Rect.move(x+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["N"] == False: - SCREEN.blit(curve4, curve4Rect.move(x+movex,y+movey)) + if not currentCell.walls["N"] and not currentCell.walls["S"]: + SCREEN.blit(straight2, straight2Rect.move(x+moveX, y+moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["W"]: + SCREEN.blit(straight1, straight1Rect.move(x+moveX, y+moveY)) + elif not currentCell.walls["N"] and not currentCell.walls["W"]: + SCREEN.blit(curve3, curve3Rect.move(x+moveX, y+moveY)) + elif not currentCell.walls["W"] and not currentCell.walls["S"]: + SCREEN.blit(curve2, curve2Rect.move(x+moveX, y+moveY)) + elif not currentCell.walls["S"] and not currentCell.walls["E"]: + SCREEN.blit(curve1, curve1Rect.move(x+moveX, y+moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["N"]: + SCREEN.blit(curve4, curve4Rect.move(x+moveX, y+moveY)) - #Save track and change background to transparent because that is how the main program needs the track image to be - #You can leave the black background if you change the collision condition on the main program + # Save track and change background to transparent because + # that is how the main program needs the track image to be + # You can leave the black background if you change the collision condition on the main program pygame.image.save(SCREEN, "randomGeneratedTrackBack.png") img = Image.open("randomGeneratedTrackBack.png") img = img.convert("RGBA") - pixdata = img.load() + pixData = img.load() for y in range(img.size[1]): for x in range(img.size[0]): - if pixdata[x, y] == (0, 0, 0, 255) or pixdata[x, y] == (0, 0, 1, 255): - pixdata[x, y] = (0, 0, 0, 0) + if pixData[x, y] == (0, 0, 0, 255) or pixData[x, y] == (0, 0, 1, 255): + pixData[x, y] = (0, 0, 0, 0) img.save("randomGeneratedTrackBack.png") - SCREEN.blit(bg, (0,0)) + SCREEN.blit(bg, (0, 0)) for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) - if currentCell.walls["N"] == False and currentCell.walls["S"] == False: - SCREEN.blit(straight2Top, straight2RectTop.move(x-20+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["W"] == False: - SCREEN.blit(straight1Top, straight1RectTop.move(x+movex,y-20+movey)) - elif currentCell.walls["N"] == False and currentCell.walls["W"] == False: - SCREEN.blit(curve3Top, curve3RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["W"] == False and currentCell.walls["S"] == False: - SCREEN.blit(curve2Top, curve2RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["N"] == False: - SCREEN.blit(curve4Top, curve4RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["S"] == False and currentCell.walls["E"] == False: - SCREEN.blit(curve1Top, curve1RectTop.move(x-15+movex,y-15+movey)) + currentCell = maze.cell_at(int(x/blockSize), int(y/blockSize)) + if not currentCell.walls["N"] and not currentCell.walls["S"]: + SCREEN.blit(straight2Top, straight2RectTop.move(x-20+moveX, y+moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["W"]: + SCREEN.blit(straight1Top, straight1RectTop.move(x+moveX, y-20+moveY)) + elif not currentCell.walls["N"] and not currentCell.walls["W"]: + SCREEN.blit(curve3Top, curve3RectTop.move(x-15+moveX, y-15+moveY)) + elif not currentCell.walls["W"] and not currentCell.walls["S"]: + SCREEN.blit(curve2Top, curve2RectTop.move(x-15+moveX, y-15+moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["N"]: + SCREEN.blit(curve4Top, curve4RectTop.move(x-15+moveX, y-15+moveY)) + elif not currentCell.walls["S"] and not currentCell.walls["E"]: + SCREEN.blit(curve1Top, curve1RectTop.move(x-15+moveX, y-15+moveY)) pygame.image.save(SCREEN, "randomGeneratedTrackFront.png") - break - else: - #It wasnt long enough so we start again - trackLenght = 0 + # It wasn't long enough so we start again + trackLength = 0 for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["N"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["S"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["E"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["W"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).color = 0, 0, 0 + maze.cell_at(int(x/blockSize), int(y/blockSize)).walls["N"] = True + maze.cell_at(int(x/blockSize), int(y/blockSize)).walls["S"] = True + maze.cell_at(int(x/blockSize), int(y/blockSize)).walls["E"] = True + maze.cell_at(int(x/blockSize), int(y/blockSize)).walls["W"] = True + maze.cell_at(int(x/blockSize), int(y/blockSize)).color = 0, 0, 0 - #Force occupied cells - maze.cell_at(3,3).walls["N"] = False - maze.cell_at(4,3).walls["N"] = False - maze.cell_at(5,3).walls["N"] = False - maze.cell_at(6,3).walls["N"] = False + # Force occupied cells + maze.cell_at(3, 3).walls["N"] = False + maze.cell_at(4, 3).walls["N"] = False + maze.cell_at(5, 3).walls["N"] = False + maze.cell_at(6, 3).walls["N"] = False - currentCell = maze.cell_at(startx, starty) + currentCell = maze.cell_at(startX, startY) return + generateRandomMap() pygame.quit() -sys.exit() - \ No newline at end of file +sys.exit() diff --git a/nnCarGame.py b/nnCarGame.py index 00ca89d..677ab2a 100644 --- a/nnCarGame.py +++ b/nnCarGame.py @@ -1,232 +1,235 @@ import pygame import random -import os import math import numpy as np -import time -import sys -from datetime import datetime from shapely.geometry import Point from shapely.geometry.polygon import Polygon from PIL import Image -from operator import attrgetter - -pygame.init() #Initialize pygame -#Some variables initializations -img = 0 #This one is used when recording frames -size = width,height = 1600, 900 #Size to use when creating pygame window - -#Colors -white = (255,255,255) -green = (0, 255, 0) -blue = (0, 0, 128) -black = (0,0,0) + +pygame.init() # Initialize pygame +# Some variables initializations +img = 0 # This one is used when recording frames +size = width, height = 1600, 900 # Size to use when creating pygame window + +# Colors +white = (255, 255, 255) +green = (0, 255, 0) +blue = (0, 0, 128) +black = (0, 0, 0) gray = pygame.Color('gray12') -Color_line = (255,0,0) +Color_line = (255, 0, 0) generation = 1 mutationRate = 90 FPS = 30 selectedCars = [] selected = 0 -lines = True #If true then lines of player are shown -player = True #If true then player is shown -display_info = True #If true then display info is shown +lines = True # If true then lines of player are shown +player = True # If true then player is shown +display_info = True # If true then display info is shown frames = 0 -maxspeed = 10 +maxSpeed = 10 number_track = 1 -white_small_car = pygame.image.load('Images\Sprites\white_small.png') -white_big_car = pygame.image.load('Images\Sprites\white_big.png') -green_small_car = pygame.image.load('Images\Sprites\green_small.png') -green_big_car = pygame.image.load('Images\Sprites\green_big.png') +white_small_car = pygame.image.load('Images/Sprites/white_small.png') +white_big_car = pygame.image.load('Images/Sprites/white_big.png') +green_small_car = pygame.image.load('Images/Sprites/green_small.png') +green_big_car = pygame.image.load('Images/Sprites/green_big.png') bg = pygame.image.load('bg7.png') bg4 = pygame.image.load('bg4.png') -def calculateDistance(x1,y1,x2,y2): #Used to calculate distance between points - dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2) +def calculateDistance(x1, y1, x2, y2): # Used to calculate distance between points + dist = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) return dist -def rotation(origin, point, angle): #Used to rotate points #rotate(origin, point, math.radians(10)) - ox, oy = origin - px, py = point +def rotation(origin, tempPoint, angle): # Used to rotate points #rotate(origin, point, math.radians(10)) + ox, oy = origin + px, py = tempPoint + qx = ox + math.cos(angle) * (px - ox) - math.sin(angle) * (py - oy) qy = oy + math.sin(angle) * (px - ox) + math.cos(angle) * (py - oy) return qx, qy + + +def move(tempPoint, angle, unit): # Translate a point in a given direction + x = tempPoint[0] + y = tempPoint[1] + rad = math.radians(-angle % 360) + + x += unit * math.sin(rad) + y += unit * math.cos(rad) -def move(point, angle, unit): #Translate a point in a given direction - x = point[0] - y = point[1] - rad = math.radians(-angle % 360) + return x, y + - x += unit*math.sin(rad) - y += unit*math.cos(rad) +def sigmoid(z): # Sigmoid function, used as the neurons activation function + return 1.0 / (1.0 + np.exp(-z)) - return x, y - -def sigmoid(z): #Sigmoid function, used as the neurons activation function - return 1.0/(1.0+np.exp(-z)) def mutateOneWeightGene(parent1, child1): - sizenn = len(child1.sizes) + sizeNN = len(child1.sizes) - #Copy parent weights into child weights - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + # Copy parent weights into child weights + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): - child1.weights[i][j][k] = parent1.weights[i][j][k] - - #Copy parent biases into child biases - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): - child1.biases[i][j] = parent1.biases[i][j] - - genomeWeights = [] #This will be a list containing all weights, easier to modify this way + child1.weights[i][j][k] = parent1.weights[i][j][k] + + # Copy parent biases into child biases + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): + child1.biases[i][j] = parent1.biases[i][j] + + genomeWeights = [] # This will be a list containing all weights, easier to modify this way - for i in range(sizenn-1): #i=0,1 - for j in range(child1.sizes[i]*child1.sizes[i+1]): + for i in range(sizeNN - 1): # i=0,1 + for j in range(child1.sizes[i] * child1.sizes[i + 1]): genomeWeights.append(child1.weights[i].item(j)) - #Modify a random gene by a random amount - r1 = random.randint(0, len(genomeWeights)-1) - genomeWeights[r1] = genomeWeights[r1]*random.uniform(0.8, 1.2) + # Modify a random gene by a random amount + r1 = random.randint(0, len(genomeWeights) - 1) + genomeWeights[r1] = genomeWeights[r1] * random.uniform(0.8, 1.2) count = 0 - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child1.weights[i][j][k] = genomeWeights[count] count += 1 return + def mutateOneBiasesGene(parent1, child1): - sizenn = len(child1.sizes) + sizeNN = len(child1.sizes) - - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): - child1.weights[i][j][k] = parent1.weights[i][j][k] - - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): - child1.biases[i][j] = parent1.biases[i][j] - + child1.weights[i][j][k] = parent1.weights[i][j][k] + + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): + child1.biases[i][j] = parent1.biases[i][j] + genomeBiases = [] - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): genomeBiases.append(child1.biases[i].item(j)) - - r1 = random.randint(0, len(genomeBiases)-1) - genomeBiases[r1] = genomeBiases[r1]*random.uniform(0.8, 1.2) - count = 0 - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): - child1.biases[i][j] = genomeBiases[count] - count += 1 + r1 = random.randint(0, len(genomeBiases) - 1) + genomeBiases[r1] = genomeBiases[r1] * random.uniform(0.8, 1.2) + + count = 0 + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): + child1.biases[i][j] = genomeBiases[count] + count += 1 return -def uniformCrossOverWeights(parent1, parent2, child1, child2): #Given two parent car objects, it modifies the children car objects weights - sizenn = len(child1.sizes) #3 si car1=Car([2, 4, 3]) + +def uniformCrossOverWeights(parent1, parent2, child1, child2): # Given two parent car objects, it modifies the + # children car objects weights + sizeNN = len(child1.sizes) # 3 si car1=Car([2, 4, 3]) - #Copy parent weights into child weights - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + # Copy parent weights into child weights + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child1.weights[i][j][k] = parent1.weights[i][j][k] - - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child2.weights[i][j][k] = parent2.weights[i][j][k] - - #Copy parent biases into child biases - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): - child1.biases[i][j] = parent1.biases[i][j] - - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): - child2.biases[i][j] = parent2.biases[i][j] - - genome1 = [] #This will be a list containing all weights of child1 - genome2 = [] #This will be a list containing all weights of child2 - - for i in range(sizenn-1): #i=0,1 - for j in range(child1.sizes[i]*child1.sizes[i+1]): + + # Copy parent biases into child biases + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): + child1.biases[i][j] = parent1.biases[i][j] + + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): + child2.biases[i][j] = parent2.biases[i][j] + + genome1 = [] # This will be a list containing all weights of child1 + genome2 = [] # This will be a list containing all weights of child2 + + for i in range(sizeNN - 1): # i=0,1 + for j in range(child1.sizes[i] * child1.sizes[i + 1]): genome1.append(child1.weights[i].item(j)) - - for i in range(sizenn-1): #i=0,1 - for j in range(child2.sizes[i]*child2.sizes[i+1]): + + for i in range(sizeNN - 1): # i=0,1 + for j in range(child2.sizes[i] * child2.sizes[i + 1]): genome2.append(child2.weights[i].item(j)) - - #Crossover weights - alter = True + + # Crossover weights + alter = True for i in range(len(genome1)): - if alter == True: + if alter: aux = genome1[i] genome1[i] = genome2[i] genome2[i] = aux alter = False else: alter = True - - #Go back from genome list to weights numpy array on child object + + # Go back from genome list to weights numpy array on child object count = 0 - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child1.weights[i][j][k] = genome1[count] count += 1 - + count = 0 - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): for k in range(child2.sizes[i]): child2.weights[i][j][k] = genome2[count] - count += 1 - return + count += 1 + return + -def uniformCrossOverBiases(parent1, parent2, child1, child2): #Given two parent car objects, it modifies the children car objects biases - sizenn = len(parent1.sizes) +def uniformCrossOverBiases(parent1, parent2, child1, child2): # Given two parent car objects, it modifies the + # children car objects biases + sizeNN = len(parent1.sizes) - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child1.weights[i][j][k] = parent1.weights[i][j][k] - - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): for k in range(child1.sizes[i]): child2.weights[i][j][k] = parent2.weights[i][j][k] - - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): - child1.biases[i][j] = parent1.biases[i][j] - - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): - child2.biases[i][j] = parent2.biases[i][j] - + + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): + child1.biases[i][j] = parent1.biases[i][j] + + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): + child2.biases[i][j] = parent2.biases[i][j] + genome1 = [] genome2 = [] - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): genome1.append(child1.biases[i].item(j)) - - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): + + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): genome2.append(child2.biases[i].item(j)) - - alter = True + + alter = True for i in range(len(genome1)): - if alter == True: + if alter: aux = genome1[i] genome1[i] = genome2[i] genome2[i] = aux @@ -234,196 +237,199 @@ def uniformCrossOverBiases(parent1, parent2, child1, child2): #Given two parent else: alter = True - count = 0 - for i in range(sizenn-1): - for j in range(child1.sizes[i+1]): - child1.biases[i][j] = genome1[count] - count += 1 - - count = 0 - for i in range(sizenn-1): - for j in range(child2.sizes[i+1]): - child2.biases[i][j] = genome2[count] - count += 1 - return + count = 0 + for i in range(sizeNN - 1): + for j in range(child1.sizes[i + 1]): + child1.biases[i][j] = genome1[count] + count += 1 + + count = 0 + for i in range(sizeNN - 1): + for j in range(child2.sizes[i + 1]): + child2.biases[i][j] = genome2[count] + count += 1 + return + def generateRandomMap(screen): SCREEN = screen - BLACK = (0, 0, 0) - WHITE = (255, 255, 255) + # BLACK = (0, 0, 0) + # WHITE = (255, 255, 255) GREEN = (0, 255, 128) WINDOW_HEIGHT = 730 - WINDOW_WIDTH = 1460 #These are for the maze/grid, not for the pygame window size - - blockSize = 146 #Set the size of the grid block - rows, cols = (int(WINDOW_WIDTH/blockSize), int(WINDOW_HEIGHT/blockSize)) - maze = Maze(rows,cols,0,0) + WINDOW_WIDTH = 1460 # These are for the maze/grid, not for the pygame window size + + blockSize = 146 # Set the size of the grid block + rows, cols = (int(WINDOW_WIDTH / blockSize), int(WINDOW_HEIGHT / blockSize)) + maze = Maze(rows, cols, 0, 0) - trackLenght = 1 - movex = 70 - movey = 85 + trackLength = 1 + moveX = 70 + moveY = 85 - #Choose a start cell - startx, starty = 0, 3 - currentCell = maze.cell_at(startx, starty) + # Choose a start cell + startX, startY = 0, 3 + currentCell = maze.cell_at(startX, startY) - #Load track images! - straight1 = pygame.image.load('Images\TracksMapGen\Straight1.png') + # Load track images! + straight1 = pygame.image.load('Images/TracksMapGen/Straight1.png') straight1Rect = straight1.get_rect() - - straight2 = pygame.image.load('Images\TracksMapGen\Straight2.png') + + straight2 = pygame.image.load('Images/TracksMapGen/Straight2.png') straight2Rect = straight2.get_rect() - - curve1 = pygame.image.load('Images\TracksMapGen\Curve1.png') + + curve1 = pygame.image.load('Images/TracksMapGen/Curve1.png') curve1Rect = curve1.get_rect() - - curve2 = pygame.image.load('Images\TracksMapGen\Curve2.png') + + curve2 = pygame.image.load('Images/TracksMapGen/Curve2.png') curve2Rect = curve2.get_rect() - - curve3 = pygame.image.load('Images\TracksMapGen\Curve3.png') + + curve3 = pygame.image.load('Images/TracksMapGen/Curve3.png') curve3Rect = curve3.get_rect() - - curve4 = pygame.image.load('Images\TracksMapGen\Curve4.png') + + curve4 = pygame.image.load('Images/TracksMapGen/Curve4.png') curve4Rect = curve4.get_rect() - - straight1Top = pygame.image.load('Images\TracksMapGen\Straight1Top.png') + + straight1Top = pygame.image.load('Images/TracksMapGen/Straight1Top.png') straight1RectTop = straight1Top.get_rect() - - straight2Top = pygame.image.load('Images\TracksMapGen\Straight2Top.png') + + straight2Top = pygame.image.load('Images/TracksMapGen/Straight2Top.png') straight2RectTop = straight2Top.get_rect() - - curve1Top = pygame.image.load('Images\TracksMapGen\Curve1Top.png') + + curve1Top = pygame.image.load('Images/TracksMapGen/Curve1Top.png') curve1RectTop = curve1Top.get_rect() - - curve2Top = pygame.image.load('Images\TracksMapGen\Curve2Top.png') + + curve2Top = pygame.image.load('Images/TracksMapGen/Curve2Top.png') curve2RectTop = curve2Top.get_rect() - - curve3Top = pygame.image.load('Images\TracksMapGen\Curve3Top.png') + + curve3Top = pygame.image.load('Images/TracksMapGen/Curve3Top.png') curve3RectTop = curve3Top.get_rect() - - curve4Top = pygame.image.load('Images\TracksMapGen\Curve4Top.png') + + curve4Top = pygame.image.load('Images/TracksMapGen/Curve4Top.png') curve4RectTop = curve4Top.get_rect() - initialTop = pygame.image.load('Images\TracksMapGen\Initial.png') + initialTop = pygame.image.load('Images/TracksMapGen/Initial.png') initialRectTop = initialTop.get_rect() - - bg = pygame.image.load('Images\TracksMapGen\Background.png') - + + bg = pygame.image.load('Images/TracksMapGen/Background.png') + while True: - - #CurrentCell is the one at (0,3) position, im gonna look if there are unvisited cells from there + + # CurrentCell is the one at (0,3) position, im gonna look if there are unvisited cells from there if len(maze.find_valid_neighbours(currentCell)) > 0: - if currentCell.x == 0 and currentCell.y == 3: #Second cell is always the one on top of first cell bc first cell is always a straight vertical track + if currentCell.x == 0 and currentCell.y == 3: # Second cell is always the one on top of first cell bc + # first cell is always a straight vertical track oldCell = currentCell - currentCell = maze.cell_at(oldCell.x,oldCell.y-1) + currentCell = maze.cell_at(oldCell.x, oldCell.y - 1) currentCell.color = GREEN oldCell.knock_down_wall(currentCell, "N") - trackLenght += 1 #Keep track of length so to discard very short generated tracks + trackLength += 1 # Keep track of length so to discard very short generated tracks else: - random_unvisited_direction = random.choice(maze.find_valid_neighbours(currentCell))[0] #Pick a random direction to move + random_unvisited_direction = random.choice(maze.find_valid_neighbours(currentCell))[ + 0] # Pick a random direction to move oldCell = currentCell - if random_unvisited_direction == "N": #Move according to the direction picked - currentCell = maze.cell_at(oldCell.x,oldCell.y-1) + if random_unvisited_direction == "N": # Move according to the direction picked + currentCell = maze.cell_at(oldCell.x, oldCell.y - 1) elif random_unvisited_direction == "S": - currentCell = maze.cell_at(oldCell.x,oldCell.y+1) + currentCell = maze.cell_at(oldCell.x, oldCell.y + 1) elif random_unvisited_direction == "E": - currentCell = maze.cell_at(oldCell.x+1,oldCell.y) + currentCell = maze.cell_at(oldCell.x + 1, oldCell.y) elif random_unvisited_direction == "W": - currentCell = maze.cell_at(oldCell.x-1,oldCell.y) + currentCell = maze.cell_at(oldCell.x - 1, oldCell.y) oldCell.knock_down_wall(currentCell, random_unvisited_direction) - trackLenght += 1 - + trackLength += 1 + else: - #Track is ready (back in initial position)! lets check if its long enough - if currentCell.x == 0 and currentCell.y == 4 and trackLenght > 40: - SCREEN.fill((0,0,0)) - currentCell.knock_down_wall(maze.cell_at(0,3), "N") + # Track is ready (back in initial position)! lets check if its long enough + if currentCell.x == 0 and currentCell.y == 4 and trackLength > 40: + SCREEN.fill((0, 0, 0)) + currentCell.knock_down_wall(maze.cell_at(0, 3), "N") for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) - currentCell.color = (0,0,1,255) + currentCell = maze.cell_at(int(x / blockSize), int(y / blockSize)) + currentCell.color = (0, 0, 1, 255) for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) + currentCell = maze.cell_at(int(x / blockSize), int(y / blockSize)) - if currentCell.walls["N"] == False and currentCell.walls["S"] == False: - SCREEN.blit(straight2, straight2Rect.move(x+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["W"] == False: - SCREEN.blit(straight1, straight1Rect.move(x+movex,y+movey)) - elif currentCell.walls["N"] == False and currentCell.walls["W"] == False: - SCREEN.blit(curve3, curve3Rect.move(x+movex,y+movey)) - elif currentCell.walls["W"] == False and currentCell.walls["S"] == False: - SCREEN.blit(curve2, curve2Rect.move(x+movex,y+movey)) - elif currentCell.walls["S"] == False and currentCell.walls["E"] == False: - SCREEN.blit(curve1, curve1Rect.move(x+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["N"] == False: - SCREEN.blit(curve4, curve4Rect.move(x+movex,y+movey)) - - #Save track and change background to transparent because that is how the main program needs the track image to be - #You can leave the black background if you change the collision condition on the main program + if not currentCell.walls["N"] and not currentCell.walls["S"]: + SCREEN.blit(straight2, straight2Rect.move(x + moveX, y + moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["W"]: + SCREEN.blit(straight1, straight1Rect.move(x + moveX, y + moveY)) + elif not currentCell.walls["N"] and not currentCell.walls["W"]: + SCREEN.blit(curve3, curve3Rect.move(x + moveX, y + moveY)) + elif not currentCell.walls["W"] and not currentCell.walls["S"]: + SCREEN.blit(curve2, curve2Rect.move(x + moveX, y + moveY)) + elif not currentCell.walls["S"] and not currentCell.walls["E"]: + SCREEN.blit(curve1, curve1Rect.move(x + moveX, y + moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["N"]: + SCREEN.blit(curve4, curve4Rect.move(x + moveX, y + moveY)) + + # Save track and change background to transparent because that is how the main program needs + # the track image to be + # You can leave the black background if you change the collision condition on the main program pygame.image.save(SCREEN, "randomGeneratedTrackBack.png") img = Image.open("randomGeneratedTrackBack.png") img = img.convert("RGBA") - pixdata = img.load() + pixData = img.load() for y in range(img.size[1]): for x in range(img.size[0]): - if pixdata[x, y] == (0, 0, 0, 255) or pixdata[x, y] == (0, 0, 1, 255): - pixdata[x, y] = (0, 0, 0, 0) + if pixData[x, y] == (0, 0, 0, 255) or pixData[x, y] == (0, 0, 1, 255): + pixData[x, y] = (0, 0, 0, 0) img.save("randomGeneratedTrackBack.png") - - SCREEN.blit(bg, (0,0)) + + SCREEN.blit(bg, (0, 0)) for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - if x == 0 and y == 3*blockSize: - SCREEN.blit(initialTop, initialRectTop.move(x-20+movex,y+movey)) + if x == 0 and y == 3 * blockSize: + SCREEN.blit(initialTop, initialRectTop.move(x - 20 + moveX, y + moveY)) else: - currentCell = maze.cell_at(int(x/blockSize),int(y/blockSize)) - if currentCell.walls["N"] == False and currentCell.walls["S"] == False: - SCREEN.blit(straight2Top, straight2RectTop.move(x-20+movex,y+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["W"] == False: - SCREEN.blit(straight1Top, straight1RectTop.move(x+movex,y-20+movey)) - elif currentCell.walls["N"] == False and currentCell.walls["W"] == False: - SCREEN.blit(curve3Top, curve3RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["W"] == False and currentCell.walls["S"] == False: - SCREEN.blit(curve2Top, curve2RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["E"] == False and currentCell.walls["N"] == False: - SCREEN.blit(curve4Top, curve4RectTop.move(x-15+movex,y-15+movey)) - elif currentCell.walls["S"] == False and currentCell.walls["E"] == False: - SCREEN.blit(curve1Top, curve1RectTop.move(x-15+movex,y-15+movey)) - + currentCell = maze.cell_at(int(x / blockSize), int(y / blockSize)) + if not currentCell.walls["N"] and not currentCell.walls["S"]: + SCREEN.blit(straight2Top, straight2RectTop.move(x - 20 + moveX, y + moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["W"]: + SCREEN.blit(straight1Top, straight1RectTop.move(x + moveX, y - 20 + moveY)) + elif not currentCell.walls["N"] and not currentCell.walls["W"]: + SCREEN.blit(curve3Top, curve3RectTop.move(x - 15 + moveX, y - 15 + moveY)) + elif not currentCell.walls["W"] and not currentCell.walls["S"]: + SCREEN.blit(curve2Top, curve2RectTop.move(x - 15 + moveX, y - 15 + moveY)) + elif not currentCell.walls["E"] and not currentCell.walls["N"]: + SCREEN.blit(curve4Top, curve4RectTop.move(x - 15 + moveX, y - 15 + moveY)) + elif not currentCell.walls["S"] and not currentCell.walls["E"]: + SCREEN.blit(curve1Top, curve1RectTop.move(x - 15 + moveX, y - 15 + moveY)) + pygame.image.save(SCREEN, "randomGeneratedTrackFront.png") - break - else: - #It wasnt long enough so we start again - trackLenght = 0 + # It wasn't long enough so we start again + trackLength = 0 for x in range(0, WINDOW_WIDTH, blockSize): for y in range(0, WINDOW_HEIGHT, blockSize): - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["N"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["S"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["E"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).walls["W"] = True - maze.cell_at(int(x/blockSize),int(y/blockSize)).color = 0, 0, 0 + maze.cell_at(int(x / blockSize), int(y / blockSize)).walls["N"] = True + maze.cell_at(int(x / blockSize), int(y / blockSize)).walls["S"] = True + maze.cell_at(int(x / blockSize), int(y / blockSize)).walls["E"] = True + maze.cell_at(int(x / blockSize), int(y / blockSize)).walls["W"] = True + maze.cell_at(int(x / blockSize), int(y / blockSize)).color = 0, 0, 0 - #Force occupied cells - maze.cell_at(3,3).walls["N"] = False - maze.cell_at(4,3).walls["N"] = False - maze.cell_at(5,3).walls["N"] = False - maze.cell_at(6,3).walls["N"] = False - - currentCell = maze.cell_at(startx, starty) + # Force occupied cells + maze.cell_at(3, 3).walls["N"] = False + maze.cell_at(4, 3).walls["N"] = False + maze.cell_at(5, 3).walls["N"] = False + maze.cell_at(6, 3).walls["N"] = False + + currentCell = maze.cell_at(startX, startY) return + class Cell: - #A wall separates a pair of cells in the N-S or W-E directions. + # A wall separates a pair of cells in the N-S or W-E directions. wall_pairs = {'N': 'S', 'S': 'N', 'E': 'W', 'W': 'E'} def __init__(self, x, y): @@ -436,20 +442,23 @@ def has_all_walls(self): return all(self.walls.values()) def knock_down_wall(self, other, wall): - #Knock down the wall between cells self and other + # Knock down the wall between cells self and other self.walls[wall] = False other.walls[Cell.wall_pairs[wall]] = False + class Maze: - #A Maze, represented as a grid of cells. - def __init__(self, nx, ny, ix=0, iy=0): + # A Maze, represented as a grid of cells. + def __init__(self, nx, ny, ix = 0, iy = 0): self.nx, self.ny = nx, ny self.ix, self.iy = ix, iy self.maze_map = [[Cell(x, y) for y in range(ny)] for x in range(nx)] + def cell_at(self, x, y): return self.maze_map[x][y] + def find_valid_neighbours(self, cell): - #Return a list of unvisited neighbours to cell. + # Return a list of unvisited neighbours to cell. delta = [('W', (-1, 0)), ('E', (1, 0)), ('S', (0, 1)), @@ -463,182 +472,194 @@ def find_valid_neighbours(self, cell): neighbours.append((direction, neighbour)) return neighbours + class Car: - def __init__(self, sizes): - self.score = 0 - self.num_layers = len(sizes) #Number of nn layers - self.sizes = sizes #List with number of neurons per layer - self.biases = [np.random.randn(y, 1) for y in sizes[1:]] #Biases - self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] #Weights - #c1, c2, c3, c4, c5 are five 2D points where the car could collided, updated in every frame - self.c1 = 0,0 - self.c2 = 0,0 - self.c3 = 0,0 - self.c4 = 0,0 - self.c5 = 0,0 - #d1, d2, d3, d4, d5 are distances from the car to those points, updated every frame too and used as the input for the NN - self.d1 = 0 - self.d2 = 0 - self.d3 = 0 - self.d4 = 0 - self.d5 = 0 - self.yaReste = False - #The input and output of the NN must be in a numpy array format - self.inp = np.array([[self.d1],[self.d2],[self.d3],[self.d4],[self.d5]]) - self.outp = np.array([[0],[0],[0],[0]]) - #Boolean used for toggling distance lines - self.showlines = False - #Initial location of the car - self.x = 120 - self.y = 480 - self.center = self.x, self.y - #Height and width of the car - self.height = 35 #45 - self.width = 17 #25 - #These are the four corners of the car, using polygon instead of rectangle object, when rotating or moving the car, we rotate or move these - self.d = self.x-(self.width/2),self.y-(self.height/2) - self.c = self.x + self.width-(self.width/2), self.y-(self.height/2) - self.b = self.x + self.width-(self.width/2), self.y + self.height-(self.height/2) #El rectangulo está centrado en (x,y) - self.a = self.x-(self.width/2), self.y + self.height-(self.height/2) #(a), (b), (c), (d) son los vertices - #Velocity, acceleration and direction of the car - self.velocity = 0 - self.acceleration = 0 - self.angle = 180 - #Boolean which goes true when car collides - self.collided = False - #Car color and image - self.color = white - self.car_image = white_small_car - def set_accel(self, accel): - self.acceleration = accel - def rotate(self, rot): - self.angle += rot - if self.angle > 360: - self.angle = 0 - if self.angle < 0: - self.angle = 360 + self.angle - def update(self): #En cada frame actualizo los vertices (traslacion y rotacion) y los puntos de colision - self.score += self.velocity - if self.acceleration != 0: - self.velocity += self.acceleration - if self.velocity > maxspeed: - self.velocity = maxspeed - elif self.velocity < 0: - self.velocity = 0 - else: - self.velocity *= 0.92 - - self.x, self.y = move((self.x, self.y), self.angle, self.velocity) - self.center = self.x, self.y + def __init__(self, sizes): + self.score = 0 + self.num_layers = len(sizes) # Number of nn layers + self.sizes = sizes # List with number of neurons per layer + self.biases = [np.random.randn(y, 1) for y in sizes[1:]] # Biases + self.weights = [np.random.randn(y, x) for x, y in zip(sizes[:-1], sizes[1:])] # Weights + # c1, c2, c3, c4, c5 are five 2D points where the car could collided, updated in every frame + self.c1 = 0, 0 + self.c2 = 0, 0 + self.c3 = 0, 0 + self.c4 = 0, 0 + self.c5 = 0, 0 + # d1, d2, d3, d4, d5 are distances from the car to those points, updated every frame too and used as the + # input for the NN + self.d1 = 0 + self.d2 = 0 + self.d3 = 0 + self.d4 = 0 + self.d5 = 0 + self.yaReste = False + # The input and output of the NN must be in a numpy array format + self.inp = np.array([[self.d1], [self.d2], [self.d3], [self.d4], [self.d5]]) + self.outp = np.array([[0], [0], [0], [0]]) + # Boolean used for toggling distance lines + self.showLinesBool = False + # Initial location of the car + self.x = 120 + self.y = 480 + self.center = self.x, self.y + # Height and width of the car + self.height = 35 # 45 + self.width = 17 # 25 + # These are the four corners of the car, using polygon instead of rectangle object, when rotating or moving + # the car, we rotate or move these + self.d = self.x - (self.width / 2), self.y - (self.height / 2) + self.c = self.x + self.width - (self.width / 2), self.y - (self.height / 2) + self.b = self.x + self.width - (self.width / 2), self.y + self.height - ( + self.height / 2) + self.a = self.x - (self.width / 2), self.y + self.height - ( + self.height / 2) # (a), (b), (c), (d) son los vertices + # Velocity, acceleration and direction of the car + self.velocity = 0 + self.acceleration = 0 + self.angle = 180 + # Boolean which goes true when car collides + self.collided = False + # Car color and image + self.color = white + self.car_image = white_small_car + + def set_accel(self, accel): + self.acceleration = accel + + def rotate(self, rot): + self.angle += rot + if self.angle > 360: + self.angle = 0 + if self.angle < 0: + self.angle = 360 + self.angle - self.d = self.x-(self.width/2),self.y-(self.height/2) - self.c = self.x + self.width-(self.width/2), self.y-(self.height/2) - self.b = self.x + self.width-(self.width/2), self.y + self.height-(self.height/2) #El rectangulo está centrado en (x,y) - self.a = self.x-(self.width/2), self.y + self.height-(self.height/2) #(a), (b), (c), (d) son los vertices + def update(self): + self.score += self.velocity + if self.acceleration != 0: + self.velocity += self.acceleration + if self.velocity > maxSpeed: + self.velocity = maxSpeed + elif self.velocity < 0: + self.velocity = 0 + else: + self.velocity *= 0.92 - self.a = rotation((self.x,self.y), self.a, math.radians(self.angle)) - self.b = rotation((self.x,self.y), self.b, math.radians(self.angle)) - self.c = rotation((self.x,self.y), self.c, math.radians(self.angle)) - self.d = rotation((self.x,self.y), self.d, math.radians(self.angle)) - - self.c1 = move((self.x,self.y),self.angle,10) - while bg4.get_at((int(self.c1[0]),int(self.c1[1]))).a!=0: - self.c1 = move((self.c1[0],self.c1[1]),self.angle,10) - while bg4.get_at((int(self.c1[0]),int(self.c1[1]))).a==0: - self.c1 = move((self.c1[0],self.c1[1]),self.angle,-1) - - self.c2 = move((self.x,self.y),self.angle+45,10) - while bg4.get_at((int(self.c2[0]),int(self.c2[1]))).a!=0: - self.c2 = move((self.c2[0],self.c2[1]),self.angle+45,10) - while bg4.get_at((int(self.c2[0]),int(self.c2[1]))).a==0: - self.c2 = move((self.c2[0],self.c2[1]),self.angle+45,-1) - - self.c3 = move((self.x,self.y),self.angle-45,10) - while bg4.get_at((int(self.c3[0]),int(self.c3[1]))).a!=0: - self.c3 = move((self.c3[0],self.c3[1]),self.angle-45,10) - while bg4.get_at((int(self.c3[0]),int(self.c3[1]))).a==0: - self.c3 = move((self.c3[0],self.c3[1]),self.angle-45,-1) + self.x, self.y = move((self.x, self.y), self.angle, self.velocity) + self.center = self.x, self.y - self.c4 = move((self.x,self.y),self.angle+90,10) - while bg4.get_at((int(self.c4[0]),int(self.c4[1]))).a!=0: - self.c4 = move((self.c4[0],self.c4[1]),self.angle+90,10) - while bg4.get_at((int(self.c4[0]),int(self.c4[1]))).a==0: - self.c4 = move((self.c4[0],self.c4[1]),self.angle+90,-1) + self.d = self.x - (self.width / 2), self.y - (self.height / 2) + self.c = self.x + self.width - (self.width / 2), self.y - (self.height / 2) + self.b = self.x + self.width - (self.width / 2), self.y + self.height - ( + self.height / 2) + self.a = self.x - (self.width / 2), self.y + self.height - ( + self.height / 2) - self.c5 = move((self.x,self.y),self.angle-90,10) - while bg4.get_at((int(self.c5[0]),int(self.c5[1]))).a!=0: - self.c5 = move((self.c5[0],self.c5[1]),self.angle-90,10) - while bg4.get_at((int(self.c5[0]),int(self.c5[1]))).a==0: - self.c5 = move((self.c5[0],self.c5[1]),self.angle-90,-1) + self.a = rotation((self.x, self.y), self.a, math.radians(self.angle)) + self.b = rotation((self.x, self.y), self.b, math.radians(self.angle)) + self.c = rotation((self.x, self.y), self.c, math.radians(self.angle)) + self.d = rotation((self.x, self.y), self.d, math.radians(self.angle)) - self.d1 = int(calculateDistance(self.center[0], self.center[1], self.c1[0], self.c1[1])) - self.d2 = int(calculateDistance(self.center[0], self.center[1], self.c2[0], self.c2[1])) - self.d3 = int(calculateDistance(self.center[0], self.center[1], self.c3[0], self.c3[1])) - self.d4 = int(calculateDistance(self.center[0], self.center[1], self.c4[0], self.c4[1])) - self.d5 = int(calculateDistance(self.center[0], self.center[1], self.c5[0], self.c5[1])) - - - - def draw(self,display): - rotated_image = pygame.transform.rotate(self.car_image, -self.angle-180) - rect_rotated_image = rotated_image.get_rect() - rect_rotated_image.center = self.x, self.y - gameDisplay.blit(rotated_image, rect_rotated_image) - - center = self.x, self.y - if self.showlines: - pygame.draw.line(gameDisplay,Color_line,(self.x,self.y),self.c1,2) - pygame.draw.line(gameDisplay,Color_line,(self.x,self.y),self.c2,2) - pygame.draw.line(gameDisplay,Color_line,(self.x,self.y),self.c3,2) - pygame.draw.line(gameDisplay,Color_line,(self.x,self.y),self.c4,2) - pygame.draw.line(gameDisplay,Color_line,(self.x,self.y),self.c5,2) - - def showLines(self): - self.showlines = not self.showlines - - def feedforward(self): - #Return the output of the network - self.inp = np.array([[self.d1],[self.d2],[self.d3],[self.d4],[self.d5],[self.velocity]]) - for b, w in zip(self.biases, self.weights): - self.inp = sigmoid(np.dot(w, self.inp)+b) - self.outp = self.inp - return self.outp - - def collision(self): - if (bg4.get_at((int(self.a[0]),int(self.a[1]))).a==0) or (bg4.get_at((int(self.b[0]),int(self.b[1]))).a==0) or (bg4.get_at((int(self.c[0]),int(self.c[1]))).a==0) or (bg4.get_at((int(self.d[0]),int(self.d[1]))).a==0): - return True - else: - return False - - def resetPosition(self): - self.x = 120 - self.y = 480 - self.angle = 180 - return - - def takeAction(self): - if self.outp.item(0) > 0.5: #Accelerate - self.set_accel(0.2) - else: - self.set_accel(0) - if self.outp.item(1) > 0.5: #Brake - self.set_accel(-0.2) - if self.outp.item(2) > 0.5: #Turn right - self.rotate(-5) - if self.outp.item(3) > 0.5: #Turn left - self.rotate(5) - return - -nnCars = [] #List of neural network cars -num_of_nnCars = 50 #Number of neural network cars -alive = num_of_nnCars #Number of not collided (alive) cars -collidedCars = [] #List containing collided cars - -#These is just the text being displayed on pygame window + self.c1 = move((self.x, self.y), self.angle, 10) + while bg4.get_at((int(self.c1[0]), int(self.c1[1]))).a != 0: + self.c1 = move((self.c1[0], self.c1[1]), self.angle, 10) + while bg4.get_at((int(self.c1[0]), int(self.c1[1]))).a == 0: + self.c1 = move((self.c1[0], self.c1[1]), self.angle, -1) + + self.c2 = move((self.x, self.y), self.angle + 45, 10) + while bg4.get_at((int(self.c2[0]), int(self.c2[1]))).a != 0: + self.c2 = move((self.c2[0], self.c2[1]), self.angle + 45, 10) + while bg4.get_at((int(self.c2[0]), int(self.c2[1]))).a == 0: + self.c2 = move((self.c2[0], self.c2[1]), self.angle + 45, -1) + + self.c3 = move((self.x, self.y), self.angle - 45, 10) + while bg4.get_at((int(self.c3[0]), int(self.c3[1]))).a != 0: + self.c3 = move((self.c3[0], self.c3[1]), self.angle - 45, 10) + while bg4.get_at((int(self.c3[0]), int(self.c3[1]))).a == 0: + self.c3 = move((self.c3[0], self.c3[1]), self.angle - 45, -1) + + self.c4 = move((self.x, self.y), self.angle + 90, 10) + while bg4.get_at((int(self.c4[0]), int(self.c4[1]))).a != 0: + self.c4 = move((self.c4[0], self.c4[1]), self.angle + 90, 10) + while bg4.get_at((int(self.c4[0]), int(self.c4[1]))).a == 0: + self.c4 = move((self.c4[0], self.c4[1]), self.angle + 90, -1) + + self.c5 = move((self.x, self.y), self.angle - 90, 10) + while bg4.get_at((int(self.c5[0]), int(self.c5[1]))).a != 0: + self.c5 = move((self.c5[0], self.c5[1]), self.angle - 90, 10) + while bg4.get_at((int(self.c5[0]), int(self.c5[1]))).a == 0: + self.c5 = move((self.c5[0], self.c5[1]), self.angle - 90, -1) + + self.d1 = int(calculateDistance(self.center[0], self.center[1], self.c1[0], self.c1[1])) + self.d2 = int(calculateDistance(self.center[0], self.center[1], self.c2[0], self.c2[1])) + self.d3 = int(calculateDistance(self.center[0], self.center[1], self.c3[0], self.c3[1])) + self.d4 = int(calculateDistance(self.center[0], self.center[1], self.c4[0], self.c4[1])) + self.d5 = int(calculateDistance(self.center[0], self.center[1], self.c5[0], self.c5[1])) + + def draw(self, display): + rotated_image = pygame.transform.rotate(self.car_image, -self.angle - 180) + rect_rotated_image = rotated_image.get_rect() + rect_rotated_image.center = self.x, self.y + gameDisplay.blit(rotated_image, rect_rotated_image) + + center = self.x, self.y + if self.showLinesBool: + pygame.draw.line(gameDisplay, Color_line, (self.x, self.y), self.c1, 2) + pygame.draw.line(gameDisplay, Color_line, (self.x, self.y), self.c2, 2) + pygame.draw.line(gameDisplay, Color_line, (self.x, self.y), self.c3, 2) + pygame.draw.line(gameDisplay, Color_line, (self.x, self.y), self.c4, 2) + pygame.draw.line(gameDisplay, Color_line, (self.x, self.y), self.c5, 2) + + def showLines(self): + self.showLinesBool = not self.showLinesBool + + def feedforward(self): + # Return the output of the network + self.inp = np.array([[self.d1], [self.d2], [self.d3], [self.d4], [self.d5], [self.velocity]]) + for b, w in zip(self.biases, self.weights): + self.inp = sigmoid(np.dot(w, self.inp) + b) + self.outp = self.inp + return self.outp + + def collision(self): + if (bg4.get_at((int(self.a[0]), int(self.a[1]))).a == 0) or ( + bg4.get_at((int(self.b[0]), int(self.b[1]))).a == 0) or ( + bg4.get_at((int(self.c[0]), int(self.c[1]))).a == 0) or ( + bg4.get_at((int(self.d[0]), int(self.d[1]))).a == 0): + return True + else: + return False + + def resetPosition(self): + self.x = 120 + self.y = 480 + self.angle = 180 + return + + def takeAction(self): + if self.outp.item(0) > 0.5: # Accelerate + self.set_accel(0.2) + else: + self.set_accel(0) + if self.outp.item(1) > 0.5: # Brake + self.set_accel(-0.2) + if self.outp.item(2) > 0.5: # Turn right + self.rotate(-5) + if self.outp.item(3) > 0.5: # Turn left + self.rotate(5) + return + + +nnCars = [] # List of neural network cars +num_of_nnCars = 50 # Number of neural network cars +alive = num_of_nnCars # Number of not collided (alive) cars +collidedCars = [] # List containing collided cars + +# These is just the text being displayed on pygame window infoX = 1365 -infoY = 600 -font = pygame.font.Font('freesansbold.ttf', 18) -text1 = font.render('0..9 - Change Mutation', True, white) +infoY = 600 +font = pygame.font.Font('freesansbold.ttf', 18) +text1 = font.render('0..9 - Change Mutation', True, white) text2 = font.render('LMB - Select/Unselect', True, white) text3 = font.render('RMB - Delete', True, white) text4 = font.render('L - Show/Hide Lines', True, white) @@ -649,73 +670,72 @@ def takeAction(self): text9 = font.render('A - Toggle Player', True, white) text10 = font.render('D - Toggle Info', True, white) text11 = font.render('M - Breed and Next Track', True, white) -text1Rect = text1.get_rect().move(infoX,infoY) -text2Rect = text2.get_rect().move(infoX,infoY+text1Rect.height) -text3Rect = text3.get_rect().move(infoX,infoY+2*text1Rect.height) -text4Rect = text4.get_rect().move(infoX,infoY+3*text1Rect.height) -text5Rect = text5.get_rect().move(infoX,infoY+4*text1Rect.height) -text6Rect = text6.get_rect().move(infoX,infoY+5*text1Rect.height) -text7Rect = text7.get_rect().move(infoX,infoY+6*text1Rect.height) -text8Rect = text8.get_rect().move(infoX,infoY+7*text1Rect.height) -text9Rect = text9.get_rect().move(infoX,infoY+8*text1Rect.height) -text10Rect = text10.get_rect().move(infoX,infoY+9*text1Rect.height) -text11Rect = text11.get_rect().move(infoX,infoY+10*text1Rect.height) - -def displayTexts(): - infotextX = 20 - infotextY = 600 - infotext1 = font.render('Gen ' + str(generation), True, white) - infotext2 = font.render('Cars: ' + str(num_of_nnCars), True, white) - infotext3 = font.render('Alive: ' + str(alive), True, white) - infotext4 = font.render('Selected: ' + str(selected), True, white) - if lines == True: - infotext5 = font.render('Lines ON', True, white) +text1Rect = text1.get_rect().move(infoX, infoY) +text2Rect = text2.get_rect().move(infoX, infoY + text1Rect.height) +text3Rect = text3.get_rect().move(infoX, infoY + 2 * text1Rect.height) +text4Rect = text4.get_rect().move(infoX, infoY + 3 * text1Rect.height) +text5Rect = text5.get_rect().move(infoX, infoY + 4 * text1Rect.height) +text6Rect = text6.get_rect().move(infoX, infoY + 5 * text1Rect.height) +text7Rect = text7.get_rect().move(infoX, infoY + 6 * text1Rect.height) +text8Rect = text8.get_rect().move(infoX, infoY + 7 * text1Rect.height) +text9Rect = text9.get_rect().move(infoX, infoY + 8 * text1Rect.height) +text10Rect = text10.get_rect().move(infoX, infoY + 9 * text1Rect.height) +text11Rect = text11.get_rect().move(infoX, infoY + 10 * text1Rect.height) + + +def displayTexts(): + infoTextX = 20 + infoTextY = 600 + infoText1 = font.render('Gen ' + str(generation), True, white) + infoText2 = font.render('Cars: ' + str(num_of_nnCars), True, white) + infoText3 = font.render('Alive: ' + str(alive), True, white) + infoText4 = font.render('Selected: ' + str(selected), True, white) + if lines: + infoText5 = font.render('Lines ON', True, white) else: - infotext5 = font.render('Lines OFF', True, white) - if player == True: - infotext6 = font.render('Player ON', True, white) + infoText5 = font.render('Lines OFF', True, white) + if player: + infoText6 = font.render('Player ON', True, white) else: - infotext6 = font.render('Player OFF', True, white) - #infotext7 = font.render('Mutation: '+ str(2*mutationRate), True, white) - #infotext8 = font.render('Frames: ' + str(frames), True, white) - infotext9 = font.render('FPS: 30', True, white) - infotext1Rect = infotext1.get_rect().move(infotextX,infotextY) - infotext2Rect = infotext2.get_rect().move(infotextX,infotextY+infotext1Rect.height) - infotext3Rect = infotext3.get_rect().move(infotextX,infotextY+2*infotext1Rect.height) - infotext4Rect = infotext4.get_rect().move(infotextX,infotextY+3*infotext1Rect.height) - infotext5Rect = infotext5.get_rect().move(infotextX,infotextY+4*infotext1Rect.height) - infotext6Rect = infotext6.get_rect().move(infotextX,infotextY+5*infotext1Rect.height) - #infotext7Rect = infotext7.get_rect().move(infotextX,infotextY+6*infotext1Rect.height) - #infotext8Rect = infotext8.get_rect().move(infotextX,infotextY+7*infotext1Rect.height) - infotext9Rect = infotext9.get_rect().move(infotextX,infotextY+6*infotext1Rect.height) - - gameDisplay.blit(text1, text1Rect) - gameDisplay.blit(text2, text2Rect) - gameDisplay.blit(text3, text3Rect) - gameDisplay.blit(text4, text4Rect) - gameDisplay.blit(text5, text5Rect) + infoText6 = font.render('Player OFF', True, white) + # infoText7 = font.render('Mutation: '+ str(2*mutationRate), True, white) + # infoText8 = font.render('Frames: ' + str(frames), True, white) + infoText9 = font.render('FPS: 30', True, white) + infoText1Rect = infoText1.get_rect().move(infoTextX, infoTextY) + infoText2Rect = infoText2.get_rect().move(infoTextX, infoTextY + infoText1Rect.height) + infoText3Rect = infoText3.get_rect().move(infoTextX, infoTextY + 2 * infoText1Rect.height) + infoText4Rect = infoText4.get_rect().move(infoTextX, infoTextY + 3 * infoText1Rect.height) + infoText5Rect = infoText5.get_rect().move(infoTextX, infoTextY + 4 * infoText1Rect.height) + infoText6Rect = infoText6.get_rect().move(infoTextX, infoTextY + 5 * infoText1Rect.height) + # infoText7Rect = infoText7.get_rect().move(infoTextX,infoTextY+6*infoText1Rect.height) + # infoText8Rect = infoText8.get_rect().move(infoTextX,infoTextY+7*infoText1Rect.height) + infoText9Rect = infoText9.get_rect().move(infoTextX, infoTextY + 6 * infoText1Rect.height) + + gameDisplay.blit(text1, text1Rect) + gameDisplay.blit(text2, text2Rect) + gameDisplay.blit(text3, text3Rect) + gameDisplay.blit(text4, text4Rect) + gameDisplay.blit(text5, text5Rect) gameDisplay.blit(text6, text6Rect) - gameDisplay.blit(text7, text7Rect) - gameDisplay.blit(text8, text8Rect) - gameDisplay.blit(text9, text9Rect) - gameDisplay.blit(text10, text10Rect) - gameDisplay.blit(text11, text11Rect) - - gameDisplay.blit(infotext1, infotext1Rect) - gameDisplay.blit(infotext2, infotext2Rect) - gameDisplay.blit(infotext3, infotext3Rect) - gameDisplay.blit(infotext4, infotext4Rect) - gameDisplay.blit(infotext5, infotext5Rect) - gameDisplay.blit(infotext6, infotext6Rect) - #gameDisplay.blit(infotext7, infotext7Rect) - #gameDisplay.blit(infotext8, infotext8Rect) - gameDisplay.blit(infotext9, infotext9Rect) + gameDisplay.blit(text7, text7Rect) + gameDisplay.blit(text8, text8Rect) + gameDisplay.blit(text9, text9Rect) + gameDisplay.blit(text10, text10Rect) + gameDisplay.blit(text11, text11Rect) + + gameDisplay.blit(infoText1, infoText1Rect) + gameDisplay.blit(infoText2, infoText2Rect) + gameDisplay.blit(infoText3, infoText3Rect) + gameDisplay.blit(infoText4, infoText4Rect) + gameDisplay.blit(infoText5, infoText5Rect) + gameDisplay.blit(infoText6, infoText6Rect) + # gameDisplay.blit(infoText7, infoText7Rect) + # gameDisplay.blit(infoText8, infoText8Rect) + gameDisplay.blit(infoText9, infoText9Rect) return - - -gameDisplay = pygame.display.set_mode(size) #creates screen +gameDisplay = pygame.display.set_mode(size) # creates screen clock = pygame.time.Clock() inputLayer = 6 @@ -725,72 +745,76 @@ def displayTexts(): auxcar = Car([inputLayer, hiddenLayer, outputLayer]) for i in range(num_of_nnCars): - nnCars.append(Car([inputLayer, hiddenLayer, outputLayer])) - -def redrawGameWindow(): #Called on very frame + nnCars.append(Car([inputLayer, hiddenLayer, outputLayer])) + - global alive +def redrawGameWindow(): # Called on very frame + + global alive global frames global img frames += 1 - - gameD = gameDisplay.blit(bg, (0,0)) - - #NN cars + + gameD = gameDisplay.blit(bg, (0, 0)) + + # NN cars for nncar in nnCars: if not nncar.collided: - nncar.update() #Update: Every car center coord, corners, directions, collision points and collision distances + nncar.update() + # Update: Every car center coord, corners, directions, collision points and collision + # distances - if nncar.collision(): #Check which car collided - nncar.collided = True #If collided then change collided attribute to true - if nncar.yaReste == False: + if nncar.collision(): # Check which car collided + nncar.collided = True # If collided then change collided attribute to true + if not nncar.yaReste: alive -= 1 nncar.yaReste = True - - else: #If not collided then feedforward the input and take an action + + else: # If not collided then feedforward the input and take an action nncar.feedforward() nncar.takeAction() nncar.draw(gameDisplay) - - #Same but for player + # Same but for player if player: car.update() if car.collision(): car.resetPosition() car.update() - car.draw(gameDisplay) - if display_info: - displayTexts() - pygame.display.update() #updates the screen - #Take a screenshot of every frame - #pygame.image.save(gameDisplay, "pygameVideo/screenshot" + str(img) + ".jpeg") - #img += 1 - + car.draw(gameDisplay) + if display_info: + displayTexts() + pygame.display.update() # updates the screen + + +# Take a screenshot of every frame +# pygame.image.save(gameDisplay, "pygameVideo/screenshot" + str(img) + ".jpeg") +# img += 1 + while True: - #now1 = time.time() - - for event in pygame.event.get(): #Check for events + # now1 = time.time() + + for event in pygame.event.get(): # Check for events if event.type == pygame.QUIT: - pygame.quit() #quits + pygame.quit() # quits quit() - - if event.type == pygame.KEYDOWN: #If user uses the keyboard - if event.key == ord ( "l" ): #If that key is l + + if event.type == pygame.KEYDOWN: # If user uses the keyboard + if event.key == ord("l"): # If that key is l car.showLines() lines = not lines - if event.key == ord ( "c" ): #If that key is c + if event.key == ord("c"): # If that key is c for nncar in nnCars: - if nncar.collided == True: + if nncar.collided: nnCars.remove(nncar) - if nncar.yaReste == False: + if not nncar.yaReste: alive -= 1 - if event.key == ord ( "a" ): #If that key is a + if event.key == ord("a"): # If that key is a player = not player - if event.key == ord ( "d" ): #If that key is d + if event.key == ord("d"): # If that key is d display_info = not display_info - if event.key == ord ( "n" ): #If that key is n + if event.key == ord("n"): # If that key is n number_track = 2 for nncar in nnCars: nncar.velocity = 0 @@ -802,37 +826,37 @@ def redrawGameWindow(): #Called on very frame generateRandomMap(gameDisplay) bg = pygame.image.load('randomGeneratedTrackFront.png') bg4 = pygame.image.load('randomGeneratedTrackBack.png') - - if event.key == ord ( "b" ): - if (len(selectedCars) == 2): + + if event.key == ord("b"): + if len(selectedCars) == 2: for nncar in nnCars: nncar.score = 0 - + alive = num_of_nnCars generation += 1 selected = 0 - nnCars.clear() + nnCars.clear() for i in range(num_of_nnCars): nnCars.append(Car([inputLayer, hiddenLayer, outputLayer])) - - for i in range(0,num_of_nnCars-2,2): - uniformCrossOverWeights(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i+1]) - uniformCrossOverBiases(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i+1]) - nnCars[num_of_nnCars-2] = selectedCars[0] - nnCars[num_of_nnCars-1] = selectedCars[1] + for i in range(0, num_of_nnCars - 2, 2): + uniformCrossOverWeights(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i + 1]) + uniformCrossOverBiases(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i + 1]) - nnCars[num_of_nnCars-2].car_image = green_small_car - nnCars[num_of_nnCars-1].car_image = green_small_car + nnCars[num_of_nnCars - 2] = selectedCars[0] + nnCars[num_of_nnCars - 1] = selectedCars[1] - nnCars[num_of_nnCars-2].resetPosition() - nnCars[num_of_nnCars-1].resetPosition() + nnCars[num_of_nnCars - 2].car_image = green_small_car + nnCars[num_of_nnCars - 1].car_image = green_small_car - nnCars[num_of_nnCars-2].collided = False - nnCars[num_of_nnCars-1].collided = False - - for i in range(num_of_nnCars-2): + nnCars[num_of_nnCars - 2].resetPosition() + nnCars[num_of_nnCars - 1].resetPosition() + + nnCars[num_of_nnCars - 2].collided = False + nnCars[num_of_nnCars - 1].collided = False + + for i in range(num_of_nnCars - 2): for j in range(mutationRate): mutateOneWeightGene(nnCars[i], auxcar) mutateOneWeightGene(auxcar, nnCars[i]) @@ -841,53 +865,50 @@ def redrawGameWindow(): #Called on very frame if number_track != 1: for nncar in nnCars: nncar.x = 140 - nncar.y = 610 - - selectedCars.clear() - - + nncar.y = 610 - - if event.key == ord ( "m" ): - if (len(selectedCars) == 2): + selectedCars.clear() + + if event.key == ord("m"): + if len(selectedCars) == 2: for nncar in nnCars: nncar.score = 0 - + alive = num_of_nnCars generation += 1 selected = 0 - nnCars.clear() + nnCars.clear() for i in range(num_of_nnCars): nnCars.append(Car([inputLayer, hiddenLayer, outputLayer])) - - for i in range(0,num_of_nnCars-2,2): - uniformCrossOverWeights(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i+1]) - uniformCrossOverBiases(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i+1]) - nnCars[num_of_nnCars-2] = selectedCars[0] - nnCars[num_of_nnCars-1] = selectedCars[1] + for i in range(0, num_of_nnCars - 2, 2): + uniformCrossOverWeights(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i + 1]) + uniformCrossOverBiases(selectedCars[0], selectedCars[1], nnCars[i], nnCars[i + 1]) + + nnCars[num_of_nnCars - 2] = selectedCars[0] + nnCars[num_of_nnCars - 1] = selectedCars[1] - nnCars[num_of_nnCars-2].car_image = green_small_car - nnCars[num_of_nnCars-1].car_image = green_small_car + nnCars[num_of_nnCars - 2].car_image = green_small_car + nnCars[num_of_nnCars - 1].car_image = green_small_car - nnCars[num_of_nnCars-2].resetPosition() - nnCars[num_of_nnCars-1].resetPosition() + nnCars[num_of_nnCars - 2].resetPosition() + nnCars[num_of_nnCars - 1].resetPosition() - nnCars[num_of_nnCars-2].collided = False - nnCars[num_of_nnCars-1].collided = False - - for i in range(num_of_nnCars-2): + nnCars[num_of_nnCars - 2].collided = False + nnCars[num_of_nnCars - 1].collided = False + + for i in range(num_of_nnCars - 2): for j in range(mutationRate): mutateOneWeightGene(nnCars[i], auxcar) mutateOneWeightGene(auxcar, nnCars[i]) mutateOneBiasesGene(nnCars[i], auxcar) mutateOneBiasesGene(auxcar, nnCars[i]) - + for nncar in nnCars: nncar.x = 140 - nncar.y = 610 - + nncar.y = 610 + selectedCars.clear() number_track = 2 @@ -901,10 +922,10 @@ def redrawGameWindow(): #Called on very frame generateRandomMap(gameDisplay) bg = pygame.image.load('randomGeneratedTrackFront.png') bg4 = pygame.image.load('randomGeneratedTrackBack.png') - if event.key == ord ( "r" ): + if event.key == ord("r"): generation = 1 alive = num_of_nnCars - nnCars.clear() + nnCars.clear() selectedCars.clear() for i in range(num_of_nnCars): nnCars.append(Car([inputLayer, hiddenLayer, outputLayer])) @@ -915,45 +936,43 @@ def redrawGameWindow(): #Called on very frame elif number_track == 2: nncar.x = 100 nncar.y = 300 - if event.key == ord ( "0" ): + if event.key == ord("0"): mutationRate = 0 - if event.key == ord ( "1" ): + if event.key == ord("1"): mutationRate = 10 - if event.key == ord ( "2" ): + if event.key == ord("2"): mutationRate = 20 - if event.key == ord ( "3" ): + if event.key == ord("3"): mutationRate = 30 - if event.key == ord ( "4" ): + if event.key == ord("4"): mutationRate = 40 - if event.key == ord ( "5" ): + if event.key == ord("5"): mutationRate = 50 - if event.key == ord ( "6" ): + if event.key == ord("6"): mutationRate = 60 - if event.key == ord ( "7" ): + if event.key == ord("7"): mutationRate = 70 - if event.key == ord ( "8" ): + if event.key == ord("8"): mutationRate = 80 - if event.key == ord ( "9" ): + if event.key == ord("9"): mutationRate = 90 - if event.type == pygame.MOUSEBUTTONDOWN: - #This returns a tuple: - #(leftclick, middleclick, rightclick) - #Each one is a boolean integer representing button up/down. - mouses = pygame.mouse.get_pressed() + # This returns a tuple: + # (leftClick, middleClick, rightClick) + # Each one is a boolean integer representing button up/down. + mouses = pygame.mouse.get_pressed(num_buttons = 3) if mouses[0]: pos = pygame.mouse.get_pos() point = Point(pos[0], pos[1]) - #Revisar la lista de autos y ver cual estaba ahi - for nncar in nnCars: + for nncar in nnCars: polygon = Polygon([nncar.a, nncar.b, nncar.c, nncar.d]) - if (polygon.contains(point)): + if polygon.contains(point): if nncar in selectedCars: selectedCars.remove(nncar) selected -= 1 if nncar.car_image == white_big_car: - nncar.car_image = white_small_car + nncar.car_image = white_small_car if nncar.car_image == green_big_car: nncar.car_image = green_small_car if nncar.collided: @@ -963,29 +982,28 @@ def redrawGameWindow(): #Called on very frame else: if len(selectedCars) < 2: selectedCars.append(nncar) - selected +=1 + selected += 1 if nncar.car_image == white_small_car: - nncar.car_image = white_big_car + nncar.car_image = white_big_car if nncar.car_image == green_small_car: - nncar.car_image = green_big_car + nncar.car_image = green_big_car if nncar.collided: nncar.velocity = 0 nncar.acceleration = 0 nncar.update() break - if mouses[2]: pos = pygame.mouse.get_pos() point = Point(pos[0], pos[1]) - for nncar in nnCars: + for nncar in nnCars: polygon = Polygon([nncar.a, nncar.b, nncar.c, nncar.d]) - if (polygon.contains(point)): + if polygon.contains(point): if nncar not in selectedCars: nnCars.remove(nncar) alive -= 1 break - + keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: car.rotate(-5) @@ -997,12 +1015,7 @@ def redrawGameWindow(): #Called on very frame car.set_accel(0) if keys[pygame.K_DOWN]: car.set_accel(-0.2) - - redrawGameWindow() + + redrawGameWindow() clock.tick(FPS) - - - - - \ No newline at end of file