Ejemplo n.º 1
0
    def test_commit(self):
        '''
        test local portion of commit operations (create env.to_remote)
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'block'
        self.args.action = 'block'
        self.args.match = 'exact'
        self.args.variable = None
        self.args.block_length = None

        # create a new environment, populate it with our list
        env = Environment(self.args)
        env.mock_remote = True
        Lists(self.args, env)

        # add items to the list
        self.args.add = True
        self.args.remove = False
        self.args.clean = False
        self.args.removeall = False
        self.args.item = ['!10.0.0.0/8']
        self.args.file = None
        Items(self.args, env)

        self.args.item = ['2a04:4e42:10::313/128']
        Items(self.args, env)

        # commit to 'remote' service
        State().commit(env, 'remote')

        # ensure SERVICEID is copied into env.to_remote
        self.assertEqual(env.to_remote['service_id'], 'SERVICEID')
        # ensure snippet contains config block and logic for our list
        self.assertRegex(
            env.to_remote['snippet']['content'],
            r'\n#fastlyblocklist_list {"name": "a_new_list".*"items": \[\]}\n')
        self.assertRegex(
            env.to_remote['snippet']['content'],
            r'\n\s*if \(var\.ip ~ fastlyblocklist_a_new_list\) {\n')
        # ensure our list is converted to ACL
        self.assertEqual(env.to_remote['acls'][0]['name'],
                         'fastlyblocklist_a_new_list')
        self.assertEqual(env.to_remote['acls'][0]['items'][0]['ip'],
                         '10.0.0.0')
        self.assertEqual(env.to_remote['acls'][0]['items'][0]['negated'], '1')
        self.assertEqual(env.to_remote['acls'][0]['items'][0]['subnet'], 8)
        self.assertEqual(env.to_remote['acls'][0]['items'][1]['ip'],
                         '2a04:4e42:10::313')
        self.assertEqual(env.to_remote['acls'][0]['items'][1]['negated'], '0')
        self.assertEqual(env.to_remote['acls'][0]['items'][1]['subnet'], 128)
Ejemplo n.º 2
0
 def draw_maps(self):
     # Render nutrientmap currently in view
     self.map_surface.fill(UI.BACKGROUND_COLOUR)
     for x in range(
             self.camera_offset[0],
             round(screen_dimensions_without_hud[0] /
                   Constants.ENVIRONMENT_ZONE_SIZE) +
             self.camera_offset[0]):
         for y in range(
                 self.camera_offset[1],
                 round(screen_dimensions_without_hud[1] /
                       Constants.ENVIRONMENT_ZONE_SIZE) +
                 self.camera_offset[1]):
             pygame.draw.rect(
                 self.map_surface,
                 Environment.get_colour(self.nutrientmap[x][y],
                                        self.heatmap[x][y],
                                        self.moisturemap[x][y]),
                 ((x - self.camera_offset[0]) *
                  Constants.ENVIRONMENT_ZONE_SIZE,
                  (y - self.camera_offset[1]) *
                  Constants.ENVIRONMENT_ZONE_SIZE,
                  Constants.ENVIRONMENT_ZONE_SIZE,
                  Constants.ENVIRONMENT_ZONE_SIZE))
             if self.toggle:
                 Text.draw_text((x - self.camera_offset[0]) *
                                Constants.ENVIRONMENT_ZONE_SIZE,
                                (y - self.camera_offset[1]) *
                                Constants.ENVIRONMENT_ZONE_SIZE,
                                str(round(self.heatmap[x][y])),
                                UI.TEXT_SIZE, (255, 90, 0),
                                self.map_surface)
Ejemplo n.º 3
0
    def test_new_list_none(self):
        '''
        try to create a valid new list with action none
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'block'
        self.args.action = 'none'
        self.args.match = None
        self.args.variable = None
        self.args.block_length = None

        # create a new environment
        env = Environment(self.args)

        # create a new list
        Lists(self.args, env)

        self.assertEqual(len(env.config['lists']), 1)
        self.assertEqual(env.config['lists'][0]['name'], 'a_new_list')
        self.assertEqual(env.config['lists'][0]['type'], 'block')
        self.assertEqual(env.config['lists'][0]['action_none'], True)
        self.assertEqual(env.config['lists'][0]['action_block'], False)
Ejemplo n.º 4
0
    def test_load_config(self):
        '''
        test init and load of a config file
        '''

        # create a new config file
        Environment(self.args)

        # load an existing config file
        self.args.init = False
        env = Environment(self.args)

        # ensure apikey and config are populated
        self.assertEqual(env.apikey, 'MYTESTAPIKEY')
        self.assertTrue(env.config['services'])
        self.assertFalse(env.config['lists'])
        self.assertEqual(env.config['log'], '')
Ejemplo n.º 5
0
    def test_load_config_override_services(self):
        '''
        test runtime override of args.services
        '''

        # create a new config file
        Environment(self.args)

        # load an existing config file and replace services in running config
        self.args.init = False
        self.args.service = ['SERVICE1', 'SERVICE2']
        env = Environment(self.args)

        # ensure override services are targeted
        self.assertEqual(
            len(env.config['services']),
            2
        )
Ejemplo n.º 6
0
    def test_init_service_defaults(self):
        '''
        ensure service config defaults are set during init
        '''

        # create a new environment
        env = Environment(self.args)

        # ensure service defaults
        self.assertEqual(env.config['services'][0]['type'], 'recv')
        self.assertEqual(env.config['services'][0]['priority'], '10')
        self.assertEqual(env.config['services'][0]['options']['edge_only'], True)
        self.assertEqual(env.config['services'][0]['options']['var_ip'], 'client.ip')
Ejemplo n.º 7
0
    def test_init(self):
        '''
        test init of a new config file
        '''

        # create a new environment
        env = Environment(self.args)

        # ensure apikey and config are populated
        self.assertEqual(env.apikey, 'MYTESTAPIKEY')
        self.assertTrue(env.config['services'])
        self.assertFalse(env.config['lists'])
        self.assertEqual(env.config['log'], '')
Ejemplo n.º 8
0
    def test_save_config(self):
        '''
        test saving a config file
        '''

        # create a new config file
        Environment(self.args)

        # load existing config file, change something, and save
        self.args.init = False
        self.args.service = ['SERVICE1', 'SERVICE2']
        Environment(self.args).save_config()

        # load the modified config file
        self.args.service = []
        env = Environment(self.args)

        # ensure updated config is loaded
        self.assertEqual(
            len(env.config['services']),
            2
        )
Ejemplo n.º 9
0
    def test_load_config_auto_generate(self):
        '''
        test init of a new config file where args.init is not provided
        '''

        # auto init a config file when one doesn't exist
        self.args.init = False
        env = Environment(self.args)

        # ensure apikey and config are populated
        self.assertEqual(env.apikey, 'MYTESTAPIKEY')
        self.assertTrue(env.config['services'])
        self.assertFalse(env.config['lists'])
        self.assertEqual(env.config['log'], '')
Ejemplo n.º 10
0
    def test_save(self):
        '''
        test create, save, and load of a config file
        '''

        # create a new config file
        Environment(self.args)

        # load existing config file, change something
        self.args.init = False
        self.args.save = True
        self.args.service = ['SERVICE1', 'SERVICE2']
        env = Environment(self.args)

        # save the changes using State().save()
        State().save(env)

        # load the modified config file
        self.args.service = []
        env = Environment(self.args)

        # ensure updated config is loaded
        self.assertEqual(len(env.config['services']), 2)
Ejemplo n.º 11
0
    def test_init_config_exists(self):
        '''
        test init of a new config file where another exists
        '''

        # create a 'valid' config file
        with open('tests.blocklist', 'w') as file_apikey:
            file_apikey.write('{}')

        # try to create a new config over existing
        self.args.force = False

        with self.assertRaisesRegex(
                SystemExit,
                "config file exists"
                ):
            Environment(self.args)
Ejemplo n.º 12
0
    def test_new_list_var_bad(self):
        '''
        try to create a new var list where no args.variable provided
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'var'
        self.args.action = 'block'
        self.args.match = 'exact'
        self.args.variable = None
        self.args.block_length = None

        # create a new environment
        env = Environment(self.args)

        with self.assertRaisesRegex(SystemExit, "no list variable defined"):
            Lists(self.args, env)
Ejemplo n.º 13
0
    def test_init_config_exists_force(self):
        '''
        test init of a new config file where another exists
        and args.force is provided
        '''

        # create a 'valid' config file
        with open('tests.blocklist', 'w') as file_apikey:
            file_apikey.write('{}')

        # force create a new config over existing
        self.args.force = True
        env = Environment(self.args)

        # ensure apikey and config are populated
        self.assertEqual(env.apikey, 'MYTESTAPIKEY')
        self.assertTrue(env.config['services'])
        self.assertFalse(env.config['lists'])
        self.assertEqual(env.config['log'], '')
Ejemplo n.º 14
0
    def test_new_list_temp(self):
        '''
        try to create a valid new temp list
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'temp'
        self.args.action = 'block'
        self.args.match = None
        self.args.variable = None
        self.args.block_length = 600

        # create a new environment
        env = Environment(self.args)
        Lists(self.args, env)

        self.assertEqual(len(env.config['lists']), 1)
        self.assertEqual(env.config['lists'][0]['type'], 'temp')
        self.assertEqual(env.config['lists'][0]['block_length'], 600)
Ejemplo n.º 15
0
    def test_new_list_var(self):
        '''
        try to create a valid new var list
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'var'
        self.args.action = 'block'
        self.args.match = 'exact'
        self.args.variable = 'req.whatever'
        self.args.block_length = None

        # create a new environment
        env = Environment(self.args)
        Lists(self.args, env)

        self.assertEqual(len(env.config['lists']), 1)
        self.assertEqual(env.config['lists'][0]['type'], 'var')
        self.assertEqual(env.config['lists'][0]['match'], 'exact')
        self.assertEqual(env.config['lists'][0]['variable'], 'req.whatever')
Ejemplo n.º 16
0
    def test_delete_list(self):
        '''
        try to create and delete a valid list
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'var'
        self.args.action = 'block'
        self.args.match = 'exact'
        self.args.variable = 'req.whatever'
        self.args.block_length = None

        # create a new environment
        env = Environment(self.args)
        Lists(self.args, env)

        self.args.new = False
        self.args.delete = True

        Lists(self.args, env)

        self.assertFalse(env.config['lists'])
Ejemplo n.º 17
0
    def test_delete_list_bad(self):
        '''
        try to delete a list where no args.list provided
        '''

        self.args.new = True
        self.args.delete = False
        self.args.list = ['a_new_list']
        self.args.type = 'var'
        self.args.action = 'block'
        self.args.match = 'exact'
        self.args.variable = 'req.whatever'
        self.args.block_length = None

        # create a new environment
        env = Environment(self.args)
        Lists(self.args, env)

        self.args.new = False
        self.args.delete = True
        self.args.list = []

        with self.assertRaisesRegex(SystemExit, r"no list name\(s\) defined"):
            Lists(self.args, env)
Ejemplo n.º 18
0
 def __init__(self, thread_name, thread_type, parameter_server, rhost):
     self.environment = Environment(
         thread_name, thread_type, parameter_server, rhost)
     self.thread_name = thread_name
     self.thread_type = thread_type
     self.util = Utilty()
Ejemplo n.º 19
0
class Worker_thread:
    def __init__(self, thread_name, thread_type, parameter_server, rhost):
        self.environment = Environment(
            thread_name, thread_type, parameter_server, rhost)
        self.thread_name = thread_name
        self.thread_type = thread_type
        self.util = Utilty()

    # Execute learning or testing.
    def run(self, exploit_tree, target_tree, saver=None, train_path=None):
        self.util.print_message(
            NOTE, 'Executing start: {}'.format(self.thread_name))
        while True:
            if self.thread_type == 'learning':
                # Execute learning thread.
                self.environment.run(exploit_tree, target_tree)

                # Stop learning thread.
                if isFinish:
                    self.util.print_message(
                        OK, 'Finish train: {}'.format(self.thread_name))
                    time.sleep(3.0)

                    # Finally save learned weights.
                    self.util.print_message(
                        OK, 'Save learned data: {}'.format(self.thread_name))
                    saver.save(SESS, train_path)

                    # Disconnection RPC Server.
                    self.environment.env.client.termination(
                        self.environment.env.client.console_id)

                    if self.thread_name == 'local_thread1':
                        # Create plot.
                        df_plot = pd.DataFrame({'exploitation': plot_count,
                                                'post-exploitation': plot_pcount})
                        df_plot.to_csv(os.path.join(
                            self.environment.env.data_path, 'experiment.csv'))
                        # df_plot.plot(kind='line', title='Training result.', legend=True)
                        # plt.savefig(self.environment.env.plot_file)
                        # plt.close('all')

                        # Create report.
                        report = CreateReport()
                        report.create_report('train', pd.to_datetime(
                            self.environment.env.scan_start_time))
                    break
            else:
                # Execute testing thread.
                self.environment.run(exploit_tree, target_tree)

                # Stop testing thread.
                if isFinish:
                    self.util.print_message(OK, 'Finish test.')
                    time.sleep(3.0)

                    # Disconnection RPC Server.
                    self.environment.env.client.termination(
                        self.environment.env.client.console_id)

                    # Create report.
                    report = CreateReport()
                    report.create_report('test', pd.to_datetime(
                        self.environment.env.scan_start_time))
                    break
Ejemplo n.º 20
0
    while action is None:
        try:
            action = input('what should I do? {} >>> '.format(actions))
            if action == 'quit':
                return True
            agent.step(action)
        except ValueError:
            action = None
    return False


if __name__ == '__main__':
    # define the gridworld environment
    env = Environment([
        [-10,0,0,50],
        [0,10,100, 0, -100, 500],
        [0,0, None, 10, None, -10, None],
        [None,0, 5, 10, None, 5, 0]
    ])

    # start at a random position
    pos = random.choice(env.positions)

    # simple reward function
    def reward(state):
        return env.value(state)

    # try discount=0.1 and discount=0.9
    DISCOUNT = 0.1
    LEARNING_RATE = 1
    agent = QLearner(pos, env, reward, discount=DISCOUNT, learning_rate=LEARNING_RATE)
    env.render(agent.state)
Ejemplo n.º 21
0
    def test_sync(self):
        '''
        test local portion of sync operations (env.from_remote to env.config)
        '''
        # create a new environment
        env = Environment(self.args)
        env.mock_remote = True
        # create an env.from_remote object
        env.from_remote = {
            'service_id':
            'REMOTESERVICEID',
            'version':
            1,
            'snippet': {
                'name':
                'REMOTE_SNIPPET_NAME',
                'type':
                'recv',
                'priority':
                10,
                'content':
                '#fastlyblocklist_list {"name": "my_test_list", '
                '"type": "block", "action_block": true, '
                '"action_log": true, "action_none": false, '
                '"match": "exact", "variable": null, '
                '"block_length": 600, "items": []}\n'
            },
            'acls': [{
                'name':
                'fastlyblocklist_my_test_list',
                'items': [{
                    'comment': '',
                    'subnet': 8,
                    'service_id': 'REMOTESERVICEID',
                    'negated': '1',
                    'deleted_at': None,
                    'ip': '10.0.0.0'
                }, {
                    'comment': '',
                    'subnet': None,
                    'service_id': 'REMOTESERVICEID',
                    'negated': '0',
                    'deleted_at': None,
                    'ip': '2a04:4e42:10::313'
                }]
            }],
            'dicts': []
        }

        # sync env.from_remote to local env.config
        State().sync(env, 'remote')

        # ensure remote made it into our local config
        self.assertEqual(env.config['services'][0]['id'], 'REMOTESERVICEID')
        self.assertEqual(env.config['services'][0]['snippet_name'],
                         'REMOTE_SNIPPET_NAME')
        self.assertEqual(env.config['lists'][0]['name'], 'my_test_list')
        self.assertEqual(env.config['lists'][0]['type'], 'block')
        self.assertTrue(env.config['lists'][0]['action_block'])
        self.assertEqual(env.config['lists'][0]['items'][0], '!10.0.0.0/8')
        self.assertEqual(env.config['lists'][0]['items'][1],
                         '2a04:4e42:10::313/128')
Ejemplo n.º 22
0
    action = None
    while action is None:
        try:
            action = input('what should I do? {} >>> '.format(actions))
            if action == 'quit':
                return True
            agent.step(action)
        except ValueError:
            action = None
    return False


if __name__ == '__main__':
    # define the gridworld environment
    env = Environment([[-10, 0, 0, 50], [0, 10, 100, 0, -100, 500],
                       [0, 0, None, 10, None, -10, None],
                       [None, 0, 5, 10, None, 5, 0]])

    # start at a random position
    pos = random.choice(env.positions)

    # simple reward function
    def reward(state):
        return env.value(state)

    # try discount=0.1 and discount=0.9
    DISCOUNT = 0.1
    LEARNING_RATE = 1
    agent = QLearner(pos,
                     env,
                     reward,
Ejemplo n.º 23
0
    def gameloop(self):
        while not self.done:
            while not self.done and Globals.titlescreen:  #For Multiple gameloops subsets. For example, a title screen and a pause screen
                title_events = pygame.event.get()

                for title_event in title_events:
                    #Event handling
                    if title_event.type == pygame.QUIT:
                        self.done = True
                    if title_event.type == pygame.KEYDOWN:
                        if title_event.key == K_x:
                            pass
                    if title_event.type == pygame.KEYUP:
                        if title_event.key == K_x:
                            pass
                    if title_event.type == pygame.MOUSEBUTTONDOWN:
                        if title_event.button == 1:
                            for button in self.buttons:
                                if button.hovered:
                                    button.activate()

                                    if button.__class__ == Button.NewButton:
                                        '''
										An important block of code! It is run ONCE when the "New Simulation" button is pressed.
										You will find environment generation, etc. here
										'''

                                        self.buttons.clear()

                                        print("Generating environment...")
                                        gen_hmap_start_time = time()

                                        self.nutrientmap = Environment.generate_noisemap(
                                            Constants.MAP_WIDTH,
                                            Constants.MAP_HEIGHT)
                                        self.heatmap = Environment.generate_noisemap(
                                            Constants.MAP_WIDTH,
                                            Constants.MAP_HEIGHT,
                                            Constants.HEATMAP_MULTIPLER
                                        )  # Less intense heatmap
                                        self.moisturemap = Environment.generate_noisemap(
                                            Constants.MAP_WIDTH,
                                            Constants.MAP_HEIGHT)
                                        self.regenmap = Environment.generate_noisemap(
                                            Constants.MAP_WIDTH,
                                            Constants.MAP_HEIGHT,
                                            1 / Constants.REPLENISH_DIVISOR)

                                        gen_hmap_end_time = time()
                                        print("Done. Took " +
                                              str(gen_hmap_end_time -
                                                  gen_hmap_start_time) +
                                              " seconds.")
                                        del gen_hmap_start_time, gen_hmap_end_time

                                        print("Rendering environment...")

                                        rend_hmap_start_time = time()
                                        self.draw_maps()

                                        rend_hmap_end_time = time()
                                        print("Done. Took " +
                                              str(rend_hmap_end_time -
                                                  rend_hmap_start_time) +
                                              " seconds.")
                                        del rend_hmap_start_time, rend_hmap_end_time

                                        for i in range(
                                                Constants.STARTING_POPULATION):
                                            self.organisms.append(
                                                self.generate_random_organism(
                                                ))
                                            self.organisms[-1].limit_position()

                                        mainscreen_timestamp = time()
                                        respawn_timestamp = time()

                #Titlescreen logic below
                screen.fill(UI.BACKGROUND_COLOUR)

                for button in self.buttons:
                    button.update()
                    button.draw()

                pygame.display.flip()  #Updates display
                clock.tick(60)

            while not self.done and not Globals.titlescreen and Globals.mainscreen:
                main_events = pygame.event.get()

                for main_event in main_events:
                    #Event handling
                    if main_event.type == pygame.QUIT:
                        self.done = True
                    if main_event.type == pygame.KEYDOWN:
                        if main_event.key == K_x:
                            pass

                        if main_event.key == K_UP:
                            # self.organisms[0].acceleration[0] = -1
                            pass

                        if main_event.key == K_DOWN:
                            # self.organisms[0].acceleration[0] = 1
                            pass

                        if main_event.key == K_RIGHT:
                            # self.organisms[0].rotational_acceleration = -1
                            pass

                        if main_event.key == K_LEFT:
                            # self.organisms[0].rotational_acceleration = 1
                            pass

                        if main_event.key == K_k:
                            self.toggle *= -1
                            self.toggle += 1

                        if main_event.key == K_w:
                            if self.camera_offset[1] > 0:
                                self.camera_offset[1] -= 1
                                self.draw_maps()

                        if main_event.key == K_a:
                            if self.camera_offset[0] > 0:
                                self.camera_offset[0] -= 1
                                self.draw_maps()

                        if main_event.key == K_s:
                            if self.camera_offset[
                                    1] < Constants.MAP_HEIGHT - round(
                                        screen_dimensions_without_hud[1] /
                                        Constants.ENVIRONMENT_ZONE_SIZE):
                                self.camera_offset[1] += 1
                                self.draw_maps()

                        if main_event.key == K_d:
                            if self.camera_offset[
                                    0] < Constants.MAP_WIDTH - round(
                                        screen_dimensions_without_hud[0] /
                                        Constants.ENVIRONMENT_ZONE_SIZE):
                                self.camera_offset[0] += 1
                                self.draw_maps()

                    if main_event.type == pygame.KEYUP:
                        if main_event.key == K_x:
                            pass
                    if main_event.type == pygame.MOUSEBUTTONDOWN:
                        if main_event.button == 1:
                            '''mousepom = self.position_to_map_position(pygame.mouse.get_pos(), True)
							print("mouse pom", mousepom)
							self.heatmap[mousepom[0]][mousepom[1]] = 1000000'''

                            for organism in self.organisms:
                                if pygame.Rect.colliderect(
                                        pygame.Rect(
                                            self.position_to_screen_position(
                                                organism.get_hitbox())),
                                    (pygame.mouse.get_pos()[0],
                                     pygame.mouse.get_pos()[1], 1, 1)):
                                    self.target_organism = organism

                            for button in self.buttons:
                                if button.hovered:
                                    button.activate()

                # Mainscreen logic below
                screen.fill(UI.BACKGROUND_COLOUR)
                screen.blit(self.map_surface, (0, 0))

                current_time = time()

                if len(
                        self.organisms
                ) < Constants.POPULATION_MINIMUM and current_time - respawn_timestamp >= Constants.RESPAWN_DELAY:
                    for i in range(Constants.POPULATION_MINIMUM -
                                   len(self.organisms)):
                        self.organisms.append(self.generate_random_organism())
                        self.organisms[-1].limit_position()
                        respawn_timestamp = time()

                if current_time - mainscreen_timestamp >= Constants.MAP_REFRESH_DELAY:
                    # Delete the dead organisms and re-render the map every few seconds
                    # Also give energy to the map so the organisms have an energy source
                    for organism in self.organisms[:]:
                        if organism.get_dead():
                            self.organisms.remove(organism)
                    mainscreen_timestamp = time()

                    for x in range(Constants.MAP_WIDTH):
                        for y in range(Constants.MAP_HEIGHT):
                            if self.nutrientmap[x][
                                    y] < Constants.ENVIRONMENT_SCALING:
                                self.nutrientmap[x][y] += self.regenmap[x][y]

                    self.draw_maps()

                for button in self.buttons:
                    button.update()
                    button.draw()

                qt_width = Constants.MAP_WIDTH * Constants.ENVIRONMENT_ZONE_SIZE
                qt_height = Constants.MAP_HEIGHT * Constants.ENVIRONMENT_ZONE_SIZE
                self.quadtree = Quadtree.Quadtree(
                    Quadtree.CentreRect(qt_width / 2, qt_height / 2, qt_width,
                                        qt_height),
                    Constants.QUADTREE_CAPACITY)
                del qt_width, qt_height

                for organism in self.organisms:
                    pom = self.position_to_map_position(organism.get_hitbox())
                    if not organism.get_dead():
                        organism.update(self.heatmap[pom[0]][pom[1]],
                                        self.moisturemap[pom[0]][pom[1]])

                        # Make the organism eat if in a neutral mood
                        if organism.get_mood_name() == "Neutral":
                            if self.nutrientmap[pom[0]][pom[1]] > 0:
                                organism.shift_energy(
                                    organism.get_size() *
                                    Constants.EAT_GAIN_MULTIPLIER)
                                self.nutrientmap[pom[0]][
                                    pom[1]] -= organism.get_size(
                                    )  #*Constants.EAT_GAIN_MULTIPLIER

                        organism_map_position = self.position_to_map_position(
                            organism.get_position())

                        organism.make_decision([], [
                            self.nutrientmap[organism_map_position[0]][
                                organism_map_position[1]],
                            self.heatmap[organism_map_position[0]][
                                organism_map_position[1]],
                            self.moisturemap[organism_map_position[0]][
                                organism_map_position[1]]
                        ])

                        organism.draw(screen, [
                            o * Constants.ENVIRONMENT_ZONE_SIZE
                            for o in self.camera_offset
                        ])
                        self.quadtree.insert(
                            (organism.get_position()[0],
                             organism.get_position()[1], organism))

                if self.toggle:
                    self.quadtree.draw(screen, [
                        o * Constants.ENVIRONMENT_ZONE_SIZE
                        for o in self.camera_offset
                    ])

                for organism in self.organisms:
                    vision_collide_points = self.quadtree.query(
                        Quadtree.NormalRect(
                            organism.get_vision_hitbox_points()))
                    organism_collide_points = self.quadtree.query(
                        Quadtree.NormalRect(organism.get_hitbox_points()))
                    colliding_organisms = [
                        o[2] for o in organism_collide_points
                    ]
                    seen_organisms = [o[2] for o in vision_collide_points]

                    for other_organism in colliding_organisms:
                        organism.bump(other_organism.get_velocity()[0])
                        if organism != other_organism:
                            if organism.get_aggression(
                            ) or other_organism.get_aggression():
                                # Attack
                                if organism.get_aggression(
                                ) and other_organism.get_aggression():
                                    # Both organisms take damage and gain energy
                                    organism.shift_fitness(
                                        -other_organism.get_attack())
                                    other_organism.shift_fitness(
                                        -organism.get_attack())
                                    organism.shift_energy(
                                        organism.get_attack())
                                    other_organism.shift_energy(
                                        other_organism.get_attack())

                                else:
                                    for o in [organism, other_organism]:
                                        if not o.get_aggression:
                                            # o takes damage, and the other gets energy
                                            o.fitness -= [
                                                organism, other_organism
                                            ][[organism, other_organism].index(
                                                o) - 1].get_attack()
                                            [[organism, other_organism
                                              ].index(o) - 1].shift_energy([
                                                  [organism, other_organism
                                                   ].index(o) - 1
                                              ].get_attack())

                            elif organism.get_mating(
                            ):  # and other_organism.get_mating():
                                # Reproduce
                                if len(self.organisms
                                       ) < Constants.POPULATION_LIMIT:
                                    organism.shift_energy(
                                        -organism.get_size() *
                                        Constants.REPRODUCTION_COST_MULTIPLIER)
                                    other_organism.shift_energy(
                                        -other_organism.get_size() *
                                        Constants.REPRODUCTION_COST_MULTIPLIER)
                                    average_energy_loss = (
                                        (organism.get_size() * Constants.
                                         REPRODUCTION_COST_MULTIPLIER) +
                                        (other_organism.get_size() * Constants.
                                         REPRODUCTION_COST_MULTIPLIER)) // 2

                                    average_position = [
                                        (p1 + p2) / 2 for p1, p2 in zip(
                                            organism.get_position(),
                                            other_organism.get_position())
                                    ]

                                    pc = (organism.get_point_count() +
                                          other_organism.get_point_count()
                                          ) // 2 + round(random() -
                                                         0.3) * randint(-1, 1)
                                    minpc = min(
                                        organism.get_point_count(),
                                        other_organism.get_point_count())
                                    if pc > minpc:
                                        # Need extra arm stats
                                        ac = [
                                            (organism.get_arm_chances()[i] +
                                             other_organism.get_arm_chances()
                                             [i]) / 2 for i in range(minpc)
                                        ]
                                        ac += [
                                            random() for i in range(pc - minpc)
                                        ]

                                    else:
                                        # We're good
                                        ac = [
                                            (organism.get_arm_chances()[i] +
                                             other_organism.get_arm_chances()
                                             [i]) / 2 for i in range(pc)
                                        ]

                                    minaco = min(
                                        len(organism.get_arms()),
                                        len(other_organism.get_arms()))
                                    astr = [
                                        (organism.get_arm_strengths()[i] +
                                         other_organism.get_arm_strengths()[i])
                                        / 2 for i in range(minaco)
                                    ]
                                    if pc > minaco:
                                        # Need extra arm strengths
                                        astr += [
                                            random()
                                            for i in range(pc - minaco)
                                        ]
                                    '''print("repro point count: ", pc)
									print("repro chances: ", len(ac))
									print("repro strengths: ", len(astr))'''

                                    average_gene_dict = {
                                        "colour":
                                        tuple([(c1 + c2) / 2 for c1, c2 in zip(
                                            organism.get_colour(),
                                            other_organism.get_colour())]),
                                        "point_count":
                                        pc,
                                        "arm_chances_per_point":
                                        ac,
                                        "arm_strength_per_arm":
                                        astr,
                                        "size":
                                        (organism.get_size() +
                                         other_organism.get_size()) // 2 +
                                        round(random() - 0.3) * randint(-1, 1),
                                        "behaviour_bias":
                                        (organism.get_behaviour_bias() +
                                         other_organism.get_behaviour_bias()) /
                                        2 + (random() * 2 - 1) / 8,
                                        "temp_regulator":
                                        (organism.get_temp_regulator() +
                                         other_organism.get_temp_regulator()) /
                                        2 + (random() * 2 - 1) / 8,
                                        "input_weights": [
                                            (iw1 + iw2) / 2 +
                                            (random() * 2 - 1) / 8
                                            for iw1, iw2 in zip(
                                                organism.get_input_weights(),
                                                other_organism.
                                                get_input_weights())
                                        ],
                                        "hidden_weights": [
                                            (hw1 + hw2) / 2 +
                                            (random() * 2 - 1) / 8
                                            for hw1, hw2 in zip(
                                                organism.get_hidden_weights(),
                                                other_organism.
                                                get_hidden_weights())
                                        ],
                                        "output_weights": [
                                            (ow1 + ow2) / 2 +
                                            (random() * 2 - 1) / 8
                                            for ow1, ow2 in zip(
                                                organism.get_input_weights(),
                                                other_organism.
                                                get_input_weights())
                                        ]
                                    }
                                    # (random()*2 - 1) / 8 is a weight mutation. This value should be studied closely, as it is the "step size" for the neural net

                                    average_generation = max([
                                        organism.get_generation(),
                                        other_organism.get_generation()
                                    ]) + 1

                                    average_id = min(
                                        organism.get_id(),
                                        other_organism.get_id()
                                    )  # Someone's id has to win out. I'll use the lower one
                                    #print("repro id: ", average_id)

                                    # Pick a polygon at random for the child.
                                    average_polygon = [
                                        organism.get_original_polygon(),
                                        other_organism.get_original_polygon()
                                    ][randint(0, 1)]

                                    # Finally, the offspring is created!
                                    self.organisms.append(
                                        Organism.Organism(
                                            average_position,
                                            average_gene_dict,
                                            average_generation, average_id,
                                            average_energy_loss,
                                            average_polygon))
                                    self.organisms[-1].limit_position(
                                    )  # Just in case

                                    organism.set_mating(False)
                                    other_organism.set_mating(False)

                                    organism.set_time_left_before_mating(
                                        organism.get_reproduction_wait_period(
                                        ))
                                    other_organism.set_time_left_before_mating(
                                        other_organism.
                                        get_reproduction_wait_period())

                    for seen_organism in seen_organisms:
                        if organism != seen_organism:

                            organism_map_position = self.position_to_map_position(
                                organism.get_position())
                            organism.make_decision([seen_organism], [
                                self.nutrientmap[organism_map_position[0]][
                                    organism_map_position[1]],
                                self.heatmap[organism_map_position[0]][
                                    organism_map_position[1]],
                                self.moisturemap[organism_map_position[0]][
                                    organism_map_position[1]]
                            ])

                            break

                # UI drawing
                pygame.draw.rect(
                    screen, (UI.UI_COLOUR),
                    (screen_dimensions_without_hud[0], 0,
                     screen_dimensions_without_hud[0], screen_dimensions[1]))

                if self.target_organism:
                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        0 + 1 * UI.PADDING, self.target_organism.get_name(),
                        UI.HEADER_TEXT_SIZE)

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        8 + 2 * UI.PADDING, "Generation: " +
                        str(self.target_organism.get_generation()))

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        8 + 3 * UI.PADDING,
                        "Origin ID: " + self.target_organism.get_id(),
                        UI.TEXT_SIZE)

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        8 + 4 * UI.PADDING, "Fitness: " +
                        str(self.target_organism.get_current_fitness()) + "/" +
                        str(self.target_organism.get_max_fitness()),
                        UI.TEXT_SIZE)

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        8 + 5 * UI.PADDING, "Energy: " +
                        str(self.target_organism.get_current_energy()) + "/" +
                        str(self.target_organism.get_max_energy()),
                        UI.TEXT_SIZE)

                    if self.target_organism.get_object_detected():
                        self.can_see_text = "Can see: " + self.target_organism.get_object_detected(
                        ).get_name()
                    else:
                        self.can_see_text = "Can see: none"
                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        8 + 6 * UI.PADDING, self.can_see_text, UI.TEXT_SIZE)

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + UI.PADDING,
                        8 + 7 * UI.PADDING, "Nodes: " +
                        str(self.target_organism.get_point_count()))

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + UI.PADDING,
                        8 + 8 * UI.PADDING,
                        "Mood: " + self.target_organism.get_mood_name())

                    Text.draw_text(
                        screen_dimensions_without_hud[0] + UI.PADDING,
                        8 + 9 * UI.PADDING, "Time left: " +
                        str(self.target_organism.get_time_left()) + "/" +
                        str(Constants.ORGANISM_LIFESPAN))

                    # Draw the organism's brain

                    # Draw the input layer
                    for n in range(len(self.target_organism.get_inputs())):
                        pygame.draw.circle(
                            screen, UI.NODE_DRAW_COLOUR,
                            (screen_dimensions_without_hud[0] + UI.PADDING,
                             2 * n * UI.NODE_DRAW_SIZE + 186),
                            UI.NODE_DRAW_SIZE)
                        Text.draw_text(
                            screen_dimensions_without_hud[0] + 6,
                            2 * n * UI.NODE_DRAW_SIZE + 186 - 5,
                            str(round(self.target_organism.get_inputs()[n],
                                      2)), UI.NODE_TEXT_SIZE, (255, 255, 255))
                        Text.draw_text(
                            screen_dimensions_without_hud[0] + 20,
                            2 * n * UI.NODE_DRAW_SIZE + 186 - 5,
                            self.target_organism.get_input_names()[n],
                            UI.NODE_TEXT_SIZE, (0, 0, 0))

                    # Draw the hidden layer
                    for n in range(len(
                            self.target_organism.get_hidden_layer())):
                        pygame.draw.circle(
                            screen, UI.NODE_DRAW_COLOUR,
                            (screen_dimensions_without_hud[0] + UI.PADDING +
                             50, 2 * n * UI.NODE_DRAW_SIZE + 186),
                            UI.NODE_DRAW_SIZE)
                        Text.draw_text(
                            screen_dimensions_without_hud[0] + 50 + 6,
                            2 * n * UI.NODE_DRAW_SIZE + 186 - 5,
                            str(
                                round(
                                    self.target_organism.get_hidden_layer()[n],
                                    2)), UI.NODE_TEXT_SIZE, (255, 255, 255))

                    # Draw the output layer
                    for n in range(len(self.target_organism.get_outputs())):
                        pygame.draw.circle(
                            screen, UI.NODE_DRAW_COLOUR,
                            (screen_dimensions_without_hud[0] + UI.PADDING +
                             100, 2 * n * UI.NODE_DRAW_SIZE + 186),
                            UI.NODE_DRAW_SIZE)
                        Text.draw_text(
                            screen_dimensions_without_hud[0] + 100 + 6,
                            2 * n * UI.NODE_DRAW_SIZE + 186 - 5,
                            str(round(self.target_organism.get_outputs()[n],
                                      2)), UI.NODE_TEXT_SIZE, (255, 255, 255))

                else:
                    Text.draw_text(
                        screen_dimensions_without_hud[0] + 1 * UI.PADDING,
                        0 + 1 * UI.PADDING,
                        "Click an organism for more info...",
                        UI.HEADER_TEXT_SIZE)

                Text.draw_text(
                    screen_dimensions_without_hud[0] + UI.PADDING,
                    screen_dimensions_without_hud[1] - 8 - 2 * UI.PADDING,
                    "Population: " + str(len(self.organisms)) + "/" +
                    str(Constants.POPULATION_LIMIT), UI.HEADER_TEXT_SIZE)

                pygame.display.flip()  #Updates display
                clock.tick(60)

        pygame.quit()  #Quits if all loops are exited