TypeError: not supported between instances of 'NoneType' and 'float'

920 Views Asked by At

I am doing flappyBird game with neat from Tech with Tim tutorial and I created self.type inside Bird Class which means that bird is controllable by keyboard input or neat class, but I am getting this error after finish last generation:

     C:/Users/papadi166/Documents/MEGAsync/AppDev/FlappyBird/main.py:185: DeprecationWarning: an integer is required (got type float).  Implicit conversion to integers using __int__ is deprecated, and may be removed in a future version of Python.
  new_rect = rotated_image.get_rect(center = image.get_rect(topleft = topleft).center)
Traceback (most recent call last):
  File "C:/Users/papadi166/Documents/MEGAsync/AppDev/FlappyBird/main.py", line 393, in <module>
    run(config_path, genome_path="dict.pickle")
  File "C:/Users/papadi166/Documents/MEGAsync/AppDev/FlappyBird/main.py", line 364, in run
    winner = p.run(main, 2)
  File "C:\Users\papadi166\PycharmProjects\FlappyBird\venv\lib\site-packages\neat\population.py", line 99, in run
    if best is None or g.fitness > best.fitness:
TypeError: '>' not supported between instances of 'NoneType' and 'float'

Process finished with exit code 1

before i added this code to population.py:

        self.population = fitness_function(list(iteritems(self.population)), self.config)
        self.species.species[1].members = self.population

I got this error after finish one generation: if best is None or g.fitness > best.fitness: TypeError: '>' not supported between instances of 'NoneType' and 'float'

I understand that there is something wrong with loaded winner object, but I dont' know how to fix that in my code..

class Bird:
    IMGS = BIRD_IMGS
    P_IMGS = PLAYER_BIRD_IMGS
    MAX_ROTATION = 25
    ROT_VEL = 20
    ANIMATION_TIME = 5
    
    
    def __init__(self, x, y, t):
        self.x = x
        self.y = y
        self.tilt = 0
        self.tick_count = 0
        self.vel = 0
        self.height = self.y
        self.img_count = 0
        self.p_img = self.P_IMGS[0]
        self.img = self.IMGS[0]
        self.type = t
        
    def jump(self):
        self.vel = -10.5
        self.tick_count = 0
        self.height = self.y
    
    def move(self):
        self.tick_count +=1
        
        d = self.vel * (self.tick_count) + 0.5 * (3) * (self.tick_count)**2
        
        if d >= 16:
            d = (d/abs(d)) * 16
        if d < 0:
            d -= 2
        
        self.y = self.y + d
        
        if d < 0 or self.y < self.height + 50:
            if self.tilt < self.MAX_ROTATION:
                self.tilt = self.MAX_ROTATION
        else:
            if self.tilt > -90:
                self.tilt -= self.ROT_VEL
                
    def draw(self, win):
        self.img_count += 1

        if self.type == 0:
            if self.img_count < self.ANIMATION_TIME:
                self.img = self.IMGS[0]
            elif self.img_count < self.ANIMATION_TIME*2:
                self.img = self.IMGS[1]
            elif self.img_count < self.ANIMATION_TIME*3:
                self.img = self.IMGS[2]
            elif self.img_count < self.ANIMATION_TIME*4:
                self.img = self.IMGS[1]
            elif self.img_count < self.ANIMATION_TIME*4 + 1:
                self.img = self.IMGS[0]
                self.img_count = 0

            if self.tilt <= -80:
                self.img = self.IMGS[1]
                self.img_count = self.ANIMATION_TIME*2

            blitRotateCenter(win, self.img, (self.x, self.y), self.tilt)


        if self.type == 1:
            if self.img_count < self.ANIMATION_TIME:
                self.img = self.P_IMGS[0]
            elif self.img_count < self.ANIMATION_TIME * 2:
                self.img = self.P_IMGS[1]
            elif self.img_count < self.ANIMATION_TIME * 3:
                self.img = self.P_IMGS[2]
            elif self.img_count < self.ANIMATION_TIME * 4:
                self.img = self.P_IMGS[1]
            elif self.img_count < self.ANIMATION_TIME * 4 + 1:
                self.img = self.P_IMGS[0]
                self.img_count = 0

            if self.tilt <= -80:
                self.img = self.P_IMGS[1]
                self.img_count = self.ANIMATION_TIME * 2

            blitRotateCenter(win, self.p_img, (self.x, self.y), self.tilt)

    def get_mask(self):
        if self.type == 0:
            return pygame.mask.from_surface(self.img)
        elif self.type == 1:
            return pygame.mask.from_surface(self.p_img)

def main(genomes, config):

    """
    We need to keep track of neural network that controls each bird, because these genomes when they come in
    are really just a bunch of neural networks that are gonna control each of our birds, I need to keep track of the bird
    that that neural networks controlling so where that position is in the screen and I need to keep track of our genomes so
    that I actually change their fitness based on you know for they move or if they hit a pipe or if they do all this stuff
    so i do three lists to do this maybe not the most efficient way but should work fine
    """
    global GEN
    GEN += 1
    nets = []
    birds = []
    ge = []
    # Change bird = Bird(230, 350) to

    x = 0
    for _, g in genomes:
        if (x < len(genomes) -1) :
            net = neat.nn.FeedForwardNetwork.create(g, config)
            nets.append(net)
            birds.append(Bird(230, 350, 0))
            g.fitness = 0
            ge.append(g)
            x += 1
        if (x == len(genomes) -1):
            net = neat.nn.FeedForwardNetwork.create(g, config)
            nets.append(net)
            birds.append(Bird(230, 350, 1))
            g.fitness = 0
            ge.append(g)
            x += 1

    base = Base(730)
    pipes = [Pipe(600)]
    win = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
    run = True
    clock = pygame.time.Clock()

    score = 0

    while run:
        clock.tick(30)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.quit()
                quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    for bird in birds:
                        if bird.type == 1:
                            bird.jump()


        pipe_ind = 0
        if len(birds) > 0:
            if len(pipes) > 1 and birds[0].x > pipes[0].x + pipes[0].PIPE_TOP.get_width():
                pipe_ind = 1
        else:
            run = False
            break

        for x, bird in enumerate(birds):
            bird.move()
            ge[x].fitness += 0.1

            output = nets[x].activate((bird.y, abs(bird.y - pipes[pipe_ind].height), abs(bird.y - pipes[pipe_ind].bottom)))

            if output[0] > 0.5:
                if bird.type != 1:
                    bird.jump()

        #bird.move()
        add_pipe = False
        rem = []
        
        for pipe in pipes:
            for x, bird in enumerate(birds):
                # indent only this collision if becouse the rest of code don't have to be running at this for loop.
                if pipe.collide(bird):
                    ge[x].fitness -= 1 # Every time a bird hits a pipe is gonna have one removed from its fitness score
                    birds.pop(x)
                    nets.pop(x)
                    ge.pop(x)


                #Change bird.x to birds[0]... OR NOT..  better put that function into this for loop, because mian will runs 50 times so caling birds[0] 50 times isn't.. IDK. Efficient?
                if not pipe.passed and pipe.x < bird.x:
                    pipe.passed = True
                    add_pipe = True

            if pipe.x + pipe.PIPE_TOP.get_width() < 0:
                rem.append(pipe)

            pipe.move()

        if add_pipe:
            score += 1
            for g in ge:
                g.fitness += 5
            pipes.append(Pipe(700))

        for r in rem:
            pipes.remove(r)
        for x, bird in enumerate(birds):
            if bird.y + bird.img.get_height() >= 730 or bird.y < 0:
                birds.pop(x)
                nets.pop(x)
                ge.pop(x)

        base.move()
        draw_window(win, birds, pipes, base, score, GEN)

        if score >= 50:
            for x, bird in enumerate(birds):
                # indent only this collision if becouse the rest of code don't have to be running at this for loop.
                ge[x].fitness -= 1  # Every time a bird hits a pipe is gonna have one removed from its fitness score
                birds.pop(x)
                nets.pop(x)
                ge.pop(x)

def run(config_path, genome_path="dict.pickle"):
    import pickle
    genomes = []
    # Load the configuration
    config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
                                neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path)
    # Setup population
    p = neat.Population(config)

    #Set the output that we gonna see
    p.add_reporter(neat.StdOutReporter(True))
    stats = neat.StatisticsReporter()
    p.add_reporter(stats)

    # Set the fitness funnction ( This func. runs main func. 50 times and pass it all of the genoms so                                                                                   like that population current generation populations  )


    winner = p.run(main, 2)

    with open("dict.pickle", "wb") as infile:
        pickle.dump(winner, infile)
        infile.close()

    # Unpickle saved winner
    with open(genome_path, "rb") as infile:
        genome = pickle.load(infile)

    # Convert loaded genome into required data structure
    genomes = [(1, genome)]
    type = "test"
    # Call game with only the loaded genome
    main(genomes, config)
    print("LOL")
  
if __name__ == '__main__':
    local_dir = os.path.dirname(__file__)
    config_path = os.path.join(local_dir, "config-feedforward.txt")
    run(config_path, genome_path="dict.pickle")
2

There are 2 best solutions below

0
On

I don't know the exact reason but for me it caused by number of hidden neurons. I have 4 inputs and 5 output neurons. The number of my hidden neurons are 3 and it works. But when I change it to 10 it gives the same error. So you might want to change the number of your hidden neurons from config file.

0
On

For me, Declaring ge[x].fitness in a for loop before worked.

# put this above the other for loops
for x, bird in enumerate(birds):
    ge[x].fitness = 0