Exemplo n.º 1
0
    def __init__(self, surface, b_config, e_config):
        # UI stuff
        self.stfont = pygame.font.SysFont('Consolas', 15, bold=False)
        self.drawing = True
        self.surface = surface

        # neat-python variables
        self.b_conf = b_config
        self.e_conf = e_config
        self.b_pop = neat.Population(b_config)
        self.e_pop = neat.Population(e_config)
        self.b_brains = [
            neat.nn.FeedForwardNetwork.create(self.b_pop.population[i],
                                              b_config)
            for i in self.b_pop.population
        ]
        self.e_brains = [
            neat.nn.FeedForwardNetwork.create(self.e_pop.population[i],
                                              e_config)
            for i in self.e_pop.population
        ]

        # game objects
        self.bow_gen = [
            BowCreature(self.surface, GameObjects.Bow(self.surface))
            for i in range(0, len(self.b_pop.population))
        ]
        self.enemy_gen = [
            SquareCreature(self.surface, GameObjects.Enemy(self.surface, 100))
            for i in range(0, len(self.e_pop.population))
        ]
        self.managers = [
            GameObjects.WaveManager([self.enemy_gen[i].game_model],
                                    self.bow_gen[i].game_model)
            for i in range(0, len(self.bow_gen))
        ]
        self.timers = [0 for i in range(0, len(self.bow_gen))]

        # statistics
        self.generations = 1
        self.avg_b_fitness = []
        self.avg_e_fitness = []
        self.kills = []
        self.e_stdev = None
        self.b_stdev = None

        self.b_gen_fitness = []
        self.e_gen_fitness = []
Exemplo n.º 2
0
    def multicycle(self):
        """Runs and draws a game cycle on multiple enemies and bows.
        Restarts when all timers reach 100/all enemies die."""
        view_single = False
        mp = pygame.mouse.get_pos()
        mouse_ind = None

        # check if viewing a single bow-enemy pair
        if int(mp[1]) in range(12, 12 + 10 * len(self.bow_gen)) and int(
                mp[0]) in range(860, 990):
            mouse_ind = (mp[1] - 12) // 10
            view_single = True

        # game loop
        for i in range(0, len(self.bow_gen)):
            if self.timers[i] < 100:

                # updating game objects
                b = self.bow_gen[i].game_model
                e = self.enemy_gen[i].game_model
                self.managers[i].detectCollisions()
                self.enemy_gen[i].avoided = self.managers[i].missed

                # setting input for enemy neural networks
                e_inp = [
                    b.draw_dx, b.draw_dy, (e.pos[0] - 255), (e.pos[1] - 255)
                ]
                for q in e.quadstat:
                    if q:
                        e_inp.append(100)
                    else:
                        e_inp.append(0)
                self.e_brains[i].activate(e_inp)

                # setting input for bow neural networks
                b_inp = [b.draw_dx, b.draw_dy]
                b_inp.extend([(e.pos[0] - 255), (e.pos[1] - 255), e.vel[0] * 3,
                              e.vel[1] * 3])
                self.b_brains[i].activate(b_inp)

                # drawing game objects and timer bars
                time_rect = pygame.Rect(860, 12 + 10 * i,
                                        (100 - self.timers[i]) * 1.3, 5)

                # check for high bow fitness, highlight timer bars
                c = (0, 255, 0)
                if self.generations > 1 and self.bow_gen[i].set_fitness(
                        self.managers[i].avg_dist
                ) > self.avg_b_fitness[-1] + self.b_stdev * 1.2:
                    c = (255, 0, 0)
                pygame.draw.rect(self.surface, c, time_rect)

                # listening for NN interaction, and updating game models
                b_out = [self.b_brains[i].values[ind] for ind in range(0, 3)]
                e_out = [self.e_brains[i].values[ind] for ind in range(0, 4)]
                self.enemy_gen[i].move_model(e_out)
                arrow = self.bow_gen[i].move_model(b_out)
                if arrow is not None:
                    self.managers[i].add_arrow(arrow)

                # check if viewing a single bow-enemy pair, draw respective stats
                if (not view_single) or (i == mouse_ind):
                    self.managers[i].draw()
                    if view_single:
                        self.enemy_gen[i].set_fitness()
                        self.enemy_gen[i].draw_fitness(self.stfont, (600, 60))

                        self.bow_gen[i].set_fitness(self.managers[i].avg_dist)
                        self.bow_gen[i].draw_fitness(self.stfont, (600, 400))

                        self.draw_nn(i, b_out)
                        self.draw_nn(i, e_out, True)

                # countdown when stuck/unstuck, ending timer when enemy dies
                if len(self.managers[i].enemies) < 1:
                    self.timers[i] = 150
                    self.bow_gen[i].killed = True
                elif not e.is_moving() or self.managers[
                        i].failed_shots > 15 or b.arrows > 18 or b.time_between_shots > 300:
                    self.timers[i] += 0.2
                else:
                    self.timers[i] = 0
        self.drawstats()

        # checking all generations finished, select, breed, and mutate
        for i in self.timers:
            if i < 100:
                return None

        self.b_gen_fitness, self.e_gen_fitness = [], []
        self.b_pop.run(self.bow_ff, 1)
        self.e_pop.run(self.enemy_ff, 1)
        self.shuffle_pops()

        # update kill count for generation
        k = 0
        for m in self.managers:
            if len(m.enemies) < 1:
                k += 1
        self.kills.append(k)

        # reset timers and game models, brains
        self.bow_gen = [
            BowCreature(self.surface, GameObjects.Bow(self.surface))
            for i in range(0, len(self.b_pop.population))
        ]
        self.enemy_gen = [
            SquareCreature(self.surface, GameObjects.Enemy(self.surface, 100))
            for i in range(0, len(self.e_pop.population))
        ]
        self.managers = [
            GameObjects.WaveManager([self.enemy_gen[i].game_model],
                                    self.bow_gen[i].game_model)
            for i in range(0, len(self.bow_gen))
        ]
        self.timers = [0 for i in range(0, len(self.bow_gen))]
        self.b_brains = [
            neat.nn.FeedForwardNetwork.create(self.b_pop.population[i],
                                              self.b_conf)
            for i in self.b_pop.population
        ]
        self.e_brains = [
            neat.nn.FeedForwardNetwork.create(self.e_pop.population[i],
                                              self.e_conf)
            for i in self.e_pop.population
        ]
        self.generations += 1