Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

winner = p.run(eval_genomes,50) #25

Open
Piebee007 opened this issue Jan 21, 2021 · 1 comment
Open

winner = p.run(eval_genomes,50) #25

Piebee007 opened this issue Jan 21, 2021 · 1 comment

Comments

@Piebee007
Copy link

So, I've been using this tutorial to make a game of my own.
however, when using NEAT, I cannot make the program do more than one generation and I have no idea why.

import math
import pygame
import random
import os
import neat
import pickle
import time

pygame.init()
screenwidth = 1000
screenheight = 750

screen = pygame.display.set_mode((screenwidth,screenheight))

LunarLanderImage = pygame.image.load("LunarLanderImage.jpg")

class Lander(object):

    def __init__(self, x_pos, y_pos, angle, gravity):
        self.x_pos = x_pos
        self.y_pos = y_pos
        self.angle = angle
        self.gravity = gravity
        self.initial_mass = 1000
        self.fuel = 500
        self.mass = self.initial_mass + self.fuel
        self.thrust = 0
        self.weight = self.mass * self.gravity
        self.x_vel = 0
        self.y_vel = 0
        self.y_acceleration = 0
        self.x_acceleration = 0
        self.img = pygame.image.load("Lander.png")
        self.img = pygame.transform.scale(self.img, (50,50))
        self.img2 = pygame.image.load("Lander2.png")
        self.img2 = pygame.transform.scale(self.img2, (50,50))
        self.thrust_on = False
        self.rotatedImage = self.img
        self.rotatedImage2 = self.img2
        self.death = False
        self.score = 0
        self.start_time = time.time()
    def move(self):
        keys = pygame.key.get_pressed()
        
        if  keys[pygame.K_RIGHT] == True:
            self.angle -= 0.5
        elif keys[pygame.K_LEFT] == True:
            self.angle += 0.5
        elif keys[pygame.K_UP] == True:
            if self.fuel >0:
                self.fuel -= 0.5
                self.thrust = 1800
                self.thrust_on = True
        else:
            self.thrust = 0
            self.thrust_on = False

    def moveLeft(self):
        self.angle += 0.5
    def  moveRight(self):
        self.angle -= 0.5
    def thruster(self):
        if self.fuel >0:
            self.fuel -= 10
            self.thrust = 1800
            self.thrust_on = True

    def draw(self, screen):
        if self.thrust_on == False:
            self.rotatedImage = pygame.transform.rotate(self.img, self.angle)
            new_rect = self.rotatedImage.get_rect(center = self.img.get_rect(center = (self.x_pos,self.y_pos)).center)
            screen.blit(self.rotatedImage, new_rect)
        else:
            self.rotatedImage2 = pygame.transform.rotate(self.img2, self.angle)
            new_rect2 = self.rotatedImage2.get_rect(center = self.img.get_rect(center = (self.x_pos,self.y_pos)).center)
            screen.blit(self.rotatedImage2, new_rect2)

    def calculate(self):
        self.y_acceleration = ((self.weight - ((self.thrust*math.cos((self.angle%360)*( 3.1416/180)))))/self.mass)/50
        
        self.x_acceleration = ((self.thrust*math.sin(((self.angle%360)*(-1))*( 3.1416/180)))/self.mass)/50
        
        self.x_vel += self.x_acceleration
        self.y_vel += self.y_acceleration

        self.x_pos += self.x_vel
        self.y_pos += self.y_vel
        self.score +=1

        self.current_time = time.time()
        #print(self.current_time - self.start_time)
        
        if self.y_pos > 750:
            self.death = True
            self.y_pos = 0
            self.y_acceleration = 0
            self.y_vel = 0
            self.x_pos = 325
            self.x_acceleration = 0
            self.x_vel = 0
            self.fuel = 500
            self.angle = 0
        if self.x_pos > 750 or self.x_pos <0:
            self.death = True
            self.x_pos = 325
            self.x_acceleration = 0
            self.x_vel = 0
            self.y_pos = 0
            self.y_acceleration = 0
            self.y_vel = 0
            self.fuel = 500
            self.angle = 0

    def collision(self):
        self.momentum = self.mass * (math.sqrt((self.x_vel**2)+(self.y_vel**2)))
        if self.momentum > 750:
            self.death = True
        else:
            self.score = 100
        self.x_vel = 0
        self.y_vel = 0
        self.x_acceleration = 0
        self.y_acceletation = 0

class Planet (object):

    def __init__(self, backgroundImg,terrainImg, gravity, end_goal, atmosphere):
        self.backgroundImg = backgroundImg
        self.terrainImg = terrainImg
        self.gravity = gravity
        self.end_goal = end_goal
        self.atmosphere = atmosphere

    def draw(self, screen):
        screen.blit(self.backgroundImg, (0,0))
        screen.blit(self.terrainImg, (0, 420))

def collision(lander, terrain):
    
    if lander.thrust_on == False:
        lander_mask = pygame.mask.from_surface(lander.rotatedImage)
    else:
        lander_mask = pygame.mask.from_surface(lander.rotatedImage2)
    terrain_mask = pygame.mask.from_surface(terrain)

    offset = (int(lander.x_pos-5), int(lander.y_pos - 450))

    
    if terrain_mask.overlap(lander_mask, offset):
        #print("True")
        lander.collision()
        


def deathScreen(lander):
    pass


moon = Planet(pygame.image.load("MoonBackground.png"), pygame.image.load("MoonTerrain1.png"),0.8, [], False)
#lander = Lander(400,100, 0, 0.8)


def redraw():
    
    screen.fill((0,0,0))
    moon.draw(screen)
    font = pygame.font.SysFont('comicsans', 50)
    if len(landers) > 0:
        x_vel_text = font.render(("X Velocity:" + str(round(landers[0].x_vel,3))), 1, (255,255,255))
        y_vel_text = font.render(("Y Velocity:" + str(round(landers[0].y_vel,3))), 1, (255,255,255))
    ##    angle_text = font.render(("Angle:" + str(round(lander.angle))), 1, (255,255,255))
        screen.blit(x_vel_text, (600, 25))
        screen.blit(y_vel_text, (600, 75))
##    screen.blit(angle_text, (600, 125))
    for lander in landers:
        lander.draw(screen)
    pygame.display.update()


gen = 0
def eval_genomes(genomes,config):
    global landers, gen
    gen +=1
    run = True
    nets = []
    ge = []
    landers = []

    for genome_id,g in genomes:
        net = neat.nn.FeedForwardNetwork.create(g,config)
        nets.append(net)
        landers.append(Lander(random.randint(100,900),100, 0, 0.8))
        g.fitness = 0
        ge.append(g)

    clock = pygame.time.Clock()
    while run == True:
        clock.tick(60)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
        for x, lander in enumerate(landers):
            lander.calculate()
            ge[x].fitness += 0.1
            output = nets[x].activate((lander.x_pos, lander.y_pos, lander.angle, lander.x_vel, lander.y_vel))
            #print(output)

            if output[0] > 0.5 and lander.fuel > 0:
                lander.thruster()
            if output[1]>0.5:
                lander.moveLeft()
            if output[2] > 0.5:
                lander.moveRight()


        for x,lander in enumerate(landers):
            if lander.death == False:
                #lander.move()
                #lander.calculate()
                
                
                collision(lander, moon.terrainImg)
                for g in ge:
                    g.fitness += 1
            else:
                ge[x].fitness -=1
                landers.pop(x)
                nets.pop(x)
                ge.pop(x)

        redraw()

##        if len(landers) <= 0:
##            run = False
##            break

        



def run(config_file):
    config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
                         neat.DefaultSpeciesSet, neat.DefaultStagnation,
                         config_file)

    
    p = neat.Population(config)

    p.add_reporter(neat.StdOutReporter(True))
    stats = neat.StatisticsReporter()
    p.add_reporter(stats)

    winner = p.run(eval_genomes, 50)

    print('\nBest genome:\n{!s}'.format(winner))

        
        #winner = p.run(eval_genomes, 50)
        #print('\nBest genome:\n{!s}'.format(winner))
    

if __name__ == "__main__":
    #local_dir = os.path.dirname(__file__)
    config_path = os.path.join("LunarConfigFile.txt")
    run(config_path)

#pygame.quit()
@LeonardoZambranoL
Copy link

LeonardoZambranoL commented Jan 25, 2021

I think you are reaching the fitness_threshold after just 1 generation, thus neat decides that the model has trained enough.
Try adding "no_fitness_termination= True" in your neat configuration file under "reset_on_extinction" or try using a bigger number for fitness_threshold alternatively, try giving your model less fitness for surviving, you are giving each lander around 66 fitness per second for staying alive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants