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")
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.