Beispiel #1
0
    def r2_procreate(self, abm, ca):
        neighborhood = ca.get_agent_neighborhood(self.x, self.y, 1)

        if self.is_fertile():
            free_cells = [v[0] for v in list(neighborhood.values())
                          if v[1] is False and (v[0].x != self.x and v[0].y != self.y)]
            mates = [v[1] for v in list(neighborhood.values()) if not v[1] is False]

            if mates:
                m = get_RNG().choice(mates)
                both_wealthy1 = (self.sugar >= self.init_sugar and m.sugar >= m.init_sugar)
                both_wealthy2 = (self.spice >= self.init_spice and m.spice >= m.init_spice)
                # All criteria is fulfilled to procreate!
                if free_cells and m.is_fertile() and m.gender != self.gender and both_wealthy1 and both_wealthy2:
                    # Take one free cell to place Junior there.
                    c = get_RNG().choice(free_cells)
                    n_x = c.x
                    n_y = c.y
                    # Give him / her initial resources
                    n_su = int(self.init_sugar / 2) + int(m.init_sugar / 2)
                    n_sp = int(self.init_spice / 2) + int(m.init_spice / 2)
                    self.sugar -= int(self.init_sugar / 2)
                    self.spice -= int(self.init_spice / 2)
                    m.sugar -= int(m.init_sugar / 2)
                    m.spice -= int(m.init_spice / 2)
                    # Fuse mommy's and daddy's chromosomes to create Juniors attributes.
                    # This is the actual creation of the baby. Behold the wonders of nature!
                    n_chromosome = self.chromosome.merge_with(m.chromosome)
                    child = SSAgent(n_x, n_y, self.gc, n_su, n_sp, 0, n_chromosome)
                    # Give the parents a reference to their newborn so they can,
                    # inherit their wealth to it before their inevitable demise.
                    self.children.append(child)
                    m.children.append(child)
                    # Update the abm that it has to schedule a new agent.
                    abm.add_agent(child)
Beispiel #2
0
    def get_cell_with_pheromone(self, target_ph, neighborhood):
        """
        Gets the cell with highest pheromone value (or random if no pheromones present)
        from the immediate neighborhood.
        :param: neighborhood is a dict of (x, y) -> cell mappings,
        where cell is a tuple of (ca_cell, [agent(s) on cell]).
        If no agent is on the cell then the list in the tuple is simply 'False'
        """
        result = None
        result_list = []
        backup_list = []
        best_cell = None
        max_ph = 0

        # Choose the possible directions the ants can currently look at.
        if self.current_dir == 5:
            possible_dirs = [4, 5, 0]
        elif self.current_dir == 0:
            possible_dirs = [5, 0, 1]
        else:
            possible_dirs = [self.current_dir - 1, self.current_dir, self.current_dir + 1]

        for i in possible_dirs:
            d = self.directions[i]
            _x = self.x + d[0]
            _y = self.y + d[1]
            if (_x, _y) in neighborhood:
                cell = neighborhood[_x, _y]
                if cell[0].pheromones[target_ph] > 0.00:  # and (not cell[1] or len(cell[1]) < 10):
                    ph = cell[0].pheromones[target_ph]
                    if ph > max_ph:
                        best_cell = cell
                        max_ph = ph
                        self.current_dir = i
                    result_list.append((cell, ph, i))
                # elif not cell[1] or len(cell[1]) < 10:
                else:
                    backup_list.append((cell, i))
        if result_list:
            if get_RNG().random() < 0.10:
                choice = AntAgent.weighted_choice(result_list)
                # choice = get_RNG().choice(result_list)
                result = choice[0]
                self.current_dir = choice[1]
            else:
                result = best_cell
        elif backup_list:
            choice = get_RNG().choice(backup_list)
            result = choice[0]
            self.current_dir = choice[1]
        else:
            # print('Ant Error: no cells found to move to!')
            self.current_dir = AntAgent.get_opposite_direction(self.current_dir)
            return self.get_cell_with_pheromone(target_ph, neighborhood)

        # Add a small random factor to the movement.
        return result
Beispiel #3
0
 def __init__(self, x, y, gc, team, min_density, power):
     super().__init__(x, y, gc)
     self.min_density = min_density
     self.strategy_walk = cab_rng.get_RNG().randint(0, 1)  # team.strategy_walk  # 0 - random, 1 - min-based
     self.strategy_seed = cab_rng.get_RNG().randint(0, 1)  # team.strategy_seed  # 0 - random, 1 - min-based
     self.score = 0
     self.power = power
     self.color = team.color
     self.team = team
Beispiel #4
0
    def get_island_landscape(self):
        l1 = {}
        l2 = {}
        last_rand = 0
        for j in range(self.height):
            for i in range(self.width):
                q = i - math.floor(j / 2)
                if get_RNG().randint(0, 100) < self.factor:
                    c = get_RNG().choice([True, False])
                    if c:
                        # last_rand = int(get_RNG().triangular(self.deepest, self.highest, self.water_level))
                        # l1[q, j] = last_rand
                        l1[q, j] = self.highest
                        for d in self.gc.HEX_DIRECTIONS:
                            l1[q + d[0], j + d[1]] = int(get_RNG().triangular(
                                self.water_level, self.highest,
                                self.highest * 0.75))
                            # try:
                            #     l1[q + d[0], j + d[1]] = self.highest * 2
                            # except KeyError:
                            #     pass
                    else:
                        l1[q, j] = self.deepest
                        for d in self.gc.HEX_DIRECTIONS:
                            l1[q + d[0], j + d[1]] = int(get_RNG().triangular(
                                self.deepest, self.water_level,
                                self.deepest * 0.75))
                else:
                    l1[q, j] = self.water_level

        for _ in range(self.smoothness):
            for j in range(self.height):
                for i in range(self.width):
                    n = 0
                    f = 0
                    q = i - math.floor(j / 2)
                    for d in self.gc.HEX_DIRECTIONS:
                        if not (d[0] == 0 and d[1] == 0):
                            try:
                                n += 1
                                f += l1[q + d[0], j + d[1]]
                            except KeyError:
                                pass
                    avg = f / n
                    if avg > l1[q, j]:
                        diff = avg - l1[q, j]
                        l2[q, j] = l1[q, j] + (diff * self.slope)
                    elif avg < l1[q, j]:
                        diff = l1[q, j] - avg
                        l2[q, j] = l1[q, j] - (diff * self.slope)
                    else:
                        l2[q, j] = l1[q, j]
            l1, l2 = l2, l1
        return l1
Beispiel #5
0
 def __init__(self, x, y, gc, team, min_density, power):
     super().__init__(x, y, gc)
     self.min_density = min_density
     self.strategy_walk = cab_rng.get_RNG().randint(
         0, 1)  # team.strategy_walk  # 0 - random, 1 - min-based
     self.strategy_seed = cab_rng.get_RNG().randint(
         0, 1)  # team.strategy_seed  # 0 - random, 1 - min-based
     self.score = 0
     self.power = power
     self.color = team.color
     self.team = team
    def get_island_landscape(self):
        l1 = {}
        l2 = {}
        last_rand = 0
        for j in range(self.height):
            for i in range(self.width):
                q = i - math.floor(j / 2)
                if get_RNG().randint(0, 100) < self.factor:
                    c = get_RNG().choice([True, False])
                    if c:
                        # last_rand = int(get_RNG().triangular(self.deepest, self.highest, self.water_level))
                    # l1[q, j] = last_rand
                        l1[q, j] = self.highest
                        for d in self.gc.HEX_DIRECTIONS:
                            l1[q + d[0], j + d[1]] = int(get_RNG().triangular(self.water_level, self.highest, self.highest * 0.75))
                            # try:
                            #     l1[q + d[0], j + d[1]] = self.highest * 2
                            # except KeyError:
                            #     pass
                    else:
                        l1[q, j] = self.deepest
                        for d in self.gc.HEX_DIRECTIONS:
                            l1[q + d[0], j + d[1]] = int(get_RNG().triangular(self.deepest, self.water_level, self.deepest * 0.75))
                else:
                    l1[q, j] = self.water_level

        for _ in range(self.smoothness):
            for j in range(self.height):
                for i in range(self.width):
                    n = 0
                    f = 0
                    q = i - math.floor(j / 2)
                    for d in self.gc.HEX_DIRECTIONS:
                        if not (d[0] == 0 and d[1] == 0):
                            try:
                                n += 1
                                f += l1[q + d[0], j + d[1]]
                            except KeyError:
                                pass
                    avg = f / n
                    if avg > l1[q, j]:
                        diff = avg - l1[q, j]
                        l2[q, j] = l1[q, j] + (diff * self.slope)
                    elif avg < l1[q, j]:
                        diff = l1[q, j] - avg
                        l2[q, j] = l1[q, j] - (diff * self.slope)
                    else:
                        l2[q, j] = l1[q, j]
            l1, l2 = l2, l1
        return l1
Beispiel #7
0
 def perceive_and_act(self, abm, ca):
     self.has_spawned_creepling_this_turn = False
     neighborhood = ca.get_empty_agent_neighborhood(self.x, self.y, 1)
     possible_cells = list(neighborhood.values())
     for c in possible_cells:
         if not c.team or c.team.number != self.team.number:
             self.dead = True
             break
         if self.current_creeplings < self.max_creeplings and not self.has_spawned_creepling_this_turn:
             density = cab_rng.get_RNG().randint(1, 15)
             power = cab_rng.get_RNG().randint(1, 10)
             abm.add_agent(CreeplingAgent(
                 c.x, c.y, self.gc, self.team, density, power))
             self.current_creeplings += 1
             self.has_spawned_creepling_this_turn = True
Beispiel #8
0
    def r4_diseases(self):
        """
        All diseases, the agent is currently infected with, are trying to spread to its neighbors.
        """
        #for n in neighbors:
        #    if n[1] and not n[1].dead and not self.dead:
        #        for _, d in self.diseases.items():
        #            d.spread(n[1])
        for _, d in self.diseases.items():
            targets = [
                agent for (cell, agent) in self.neighbors
                if agent is not None and not agent.dead and not self.dead
            ]
            if targets:
                victim = get_RNG().choice(targets)
                d.spread(victim)

        # Let the immune system build another instance
        # and then attempt to fight the diseases.
        self.im_create_antibodies()
        self.immune_reaction()
        # Reset the metabolism values of the agent to clear all past diseases.
        # That way, the diseases just fought off by the immune system are not longer
        # afflicting the body and possible new diseases can act on the agent.
        self.meta_sugar = self.chromosome.meta_sugar
        self.meta_spice = self.chromosome.meta_spice
        # Have the diseases affect the agent
        for _, d in self.diseases.items():
            d.affect(self)
Beispiel #9
0
 def im_create_antibodies(self):
     if self.fertility[0] < self.age < self.fertility[1] and len(self.immune_system) <= 10:
         is_copy = copy.deepcopy(self.chromosome.immune_system)
         length = len(is_copy)
         index = get_RNG().choice(range(length))
         is_copy[index] = 1 - is_copy[index]
         self.immune_system.append("".join(map(str, is_copy)))
Beispiel #10
0
    def get_coastal_landscape(self):
        l1 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        l2 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        for j in range(self.y_dim):
            for i in range(self.x_dim):
                # l1[i][j] = int(get_RNG().triangular(self.deepest, self.highest, 5))s
                mode = (((i + j) / 200) * 20) - 15
                l1[i][j] = int(cab_rng.get_RNG().triangular(
                    self.deepest + 2 * mode, self.highest + 2 * mode, mode))

        for _ in range(self.smoothness):
            for j in range(self.y_dim):
                for i in range(self.x_dim):
                    n = 0
                    f = 0
                    for cy in range(-1, 2):
                        for cx in range(-1, 2):
                            if not (cy == 0 and cx == 0):
                                try:
                                    n += 1
                                    f += l1[i + cx][j + cy]
                                except IndexError:
                                    pass
                    avg = f / n
                    if avg > l1[i][j]:
                        diff = avg - l1[i][j]
                        l2[i][j] = l1[i][j] + (diff * self.slope)
                    elif avg < l1[i][j]:
                        diff = l1[i][j] - avg
                        l2[i][j] = l1[i][j] - (diff * self.slope)
                    else:
                        l2[i][j] = l1[i][j]
            l1, l2 = l2, l1
        return l1
    def get_coastal_landscape(self):
        l1 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        l2 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        for j in range(self.y_dim):
            for i in range(self.x_dim):
                # l1[i][j] = int(get_RNG().triangular(self.deepest, self.highest, 5))s
                mode = (((i + j) / 200) * 20) - 15
                l1[i][j] = int(cab_rng.get_RNG().triangular(self.deepest + 2 * mode, self.highest + 2 * mode, mode))

        for _ in range(self.smoothness):
            for j in range(self.y_dim):
                for i in range(self.x_dim):
                    n = 0
                    f = 0
                    for cy in range(-1, 2):
                        for cx in range(-1, 2):
                            if not (cy == 0 and cx == 0):
                                try:
                                    n += 1
                                    f += l1[i + cx][j + cy]
                                except IndexError:
                                    pass
                    avg = f / n
                    if avg > l1[i][j]:
                        diff = avg - l1[i][j]
                        l2[i][j] = l1[i][j] + (diff * self.slope)
                    elif avg < l1[i][j]:
                        diff = l1[i][j] - avg
                        l2[i][j] = l1[i][j] - (diff * self.slope)
                    else:
                        l2[i][j] = l1[i][j]
            l1, l2 = l2, l1
        return l1
Beispiel #12
0
 def perceive_and_act(self, abm, ca):
     self.has_spawned_creepling_this_turn = False
     neighborhood = ca.get_empty_agent_neighborhood(self.x, self.y, 1)
     possible_cells = list(neighborhood.values())
     for c in possible_cells:
         if not c.team or c.team.number != self.team.number:
             self.dead = True
             break
         if self.current_creeplings < self.max_creeplings and not self.has_spawned_creepling_this_turn:
             density = cab_rng.get_RNG().randint(1, 15)
             power = cab_rng.get_RNG().randint(1, 10)
             abm.add_agent(
                 CreeplingAgent(c.x, c.y, self.gc, self.team, density,
                                power))
             self.current_creeplings += 1
             self.has_spawned_creepling_this_turn = True
Beispiel #13
0
    def r4_diseases(self):
        """
        All diseases, the agent is currently infected with, are trying to spread to its neighbors.
        """
        #for n in neighbors:
        #    if n[1] and not n[1].dead and not self.dead:
        #        for _, d in self.diseases.items():
        #            d.spread(n[1])
        for _, d in self.diseases.items():
            targets = [agent for (cell, agent) in self.neighbors if agent is not None and not agent.dead and not self.dead]
            if targets:
                victim = get_RNG().choice(targets)
                d.spread(victim)

        # Let the immune system build another instance
        # and then attempt to fight the diseases.
        self.im_create_antibodies()
        self.immune_reaction()
        # Reset the metabolism values of the agent to clear all past diseases.
        # That way, the diseases just fought off by the immune system are not longer
        # afflicting the body and possible new diseases can act on the agent.
        self.meta_sugar = self.chromosome.meta_sugar
        self.meta_spice = self.chromosome.meta_spice
        # Have the diseases affect the agent
        for _, d in self.diseases.items():
            d.affect(self)
    def get_coastal_landscape(self):
        l1 = {}
        l2 = {}
        for j in range(self.height):
            for i in range(self.width):
                # l1[i][j] = int(get_RNG().triangular(self.deepest, self.highest, 5))s
                q = i - math.floor(j / 2)
                mode = (((i + j) / 200) * 5) + self.water_level
                l1[q, j] = int(get_RNG().triangular(self.deepest + 2 * mode, self.highest + 2 * mode, mode))
                # l1[i][j] = int(get_RNG().triangular(self.deepest + 2 * mode, self.highest + 2 * mode, mode))

        for _ in range(self.smoothness):
            for j in range(self.height):
                for i in range(self.width):
                    q = i - math.floor(j / 2)
                    n = 0
                    f = 0
                    for d in self.gc.HEX_DIRECTIONS:
                        if not (d[0] == 0 and d[1] == 0):
                            try:
                                n += 1
                                f += l1[q + d[0], j + d[1]]
                            except KeyError:
                                pass
                    avg = f / n
                    if avg > l1[q, j]:
                        diff = avg - l1[q, j]
                        l2[q, j] = l1[q, j] + (diff * self.slope)
                    elif avg < l1[q, j]:
                        diff = l1[q, j] - avg
                        l2[q, j] = l1[q, j] - (diff * self.slope)
                    else:
                        l2[q, j] = l1[q, j]
            l1, l2 = l2, l1
        return l1
Beispiel #15
0
    def map_genome_to_attributes(self):
        """
        Decodes the genome and creates the attribute of the individual.
        """
        # The meta and init attributes cannot become smaller than 1,
        # even though that is possible by the encoding. We have to avoid that.
        meta_sugar = Chromosome.choose_dominant_gene(self.get_genome_substring('meta_sugar'))
        meta_spice = Chromosome.choose_dominant_gene(self.get_genome_substring('meta_spice'))
        init_sugar = Chromosome.choose_dominant_gene(self.get_genome_substring('init_sugar'))
        init_spice = Chromosome.choose_dominant_gene(self.get_genome_substring('init_spice'))
        vision = Chromosome.choose_dominant_gene(self.get_genome_substring('vision'))
        gender = get_RNG().choice(self.get_genome_substring('gender'))
        f1 = Chromosome.choose_dominant_gene(self.get_genome_substring('fertility_1'))
        f2 = Chromosome.choose_dominant_gene(self.get_genome_substring('fertility_2'))
        dying_age = Chromosome.choose_dominant_gene(self.get_genome_substring('dying_age'))

        self.meta_sugar = max(int(meta_sugar, 2), 1)
        self.meta_spice = max(int(meta_spice, 2), 1)
        self.init_sugar = max(int(init_sugar, 2), 1)
        self.init_spice = max(int(init_spice, 2), 1)
        self.vision = int(vision, 2)
        self.gender = int(gender, 2)
        self.dying_age = int(dying_age, 2)
        self.fertility = (int(f1, 2), int(f2, 2))

        dna = "".join((meta_sugar, meta_spice, init_sugar, init_spice, vision, gender, f1, f2, dying_age))
        self.dna_color = Chromosome.convert_to_color(dna)
Beispiel #16
0
 def im_create_antibodies(self):
     if self.fertility[0] < self.age < self.fertility[1] and len(
             self.immune_system) <= 10:
         is_copy = copy.deepcopy(self.chromosome.immune_system)
         length = len(is_copy)
         index = get_RNG().choice(range(length))
         is_copy[index] = 1 - is_copy[index]
         self.immune_system.append("".join(map(str, is_copy)))
Beispiel #17
0
 def weighted_choice(choices):
     total = sum(w for c, w, i in choices)
     r = get_RNG().uniform(0, total)
     up_to = 0
     for c, w, i in choices:
         if up_to + w > r:
             return c, i
         up_to += w
     assert False, "Shouldn't get here"
Beispiel #18
0
 def weighted_choice(choices):
     total = sum(w for c, w, i in choices)
     r = get_RNG().uniform(0, total)
     up_to = 0
     for c, w, i in choices:
         if up_to + w > r:
             return c, i
         up_to += w
     assert False, "Shouldn't get here"
Beispiel #19
0
    def r2_procreate(self, abm, ca):
        neighborhood = ca.get_agent_neighborhood(self.x, self.y, 1)

        if self.is_fertile():
            free_cells = [
                v[0] for v in list(neighborhood.values())
                if v[1] is False and (v[0].x != self.x and v[0].y != self.y)
            ]
            mates = [
                v[1] for v in list(neighborhood.values()) if not v[1] is False
            ]

            if mates:
                m = get_RNG().choice(mates)
                both_wealthy1 = (self.sugar >= self.init_sugar
                                 and m.sugar >= m.init_sugar)
                both_wealthy2 = (self.spice >= self.init_spice
                                 and m.spice >= m.init_spice)
                # All criteria is fulfilled to procreate!
                if free_cells and m.is_fertile(
                ) and m.gender != self.gender and both_wealthy1 and both_wealthy2:
                    # Take one free cell to place Junior there.
                    c = get_RNG().choice(free_cells)
                    n_x = c.x
                    n_y = c.y
                    # Give him / her initial resources
                    n_su = int(self.init_sugar / 2) + int(m.init_sugar / 2)
                    n_sp = int(self.init_spice / 2) + int(m.init_spice / 2)
                    self.sugar -= int(self.init_sugar / 2)
                    self.spice -= int(self.init_spice / 2)
                    m.sugar -= int(m.init_sugar / 2)
                    m.spice -= int(m.init_spice / 2)
                    # Fuse mommy's and daddy's chromosomes to create Juniors attributes.
                    # This is the actual creation of the baby. Behold the wonders of nature!
                    n_chromosome = self.chromosome.merge_with(m.chromosome)
                    child = SSAgent(n_x, n_y, self.gc, n_su, n_sp, 0,
                                    n_chromosome)
                    # Give the parents a reference to their newborn so they can,
                    # inherit their wealth to it before their inevitable demise.
                    self.children.append(child)
                    m.children.append(child)
                    # Update the abm that it has to schedule a new agent.
                    abm.add_agent(child)
Beispiel #20
0
 def create_gamete(genomes):
     """
     Creates and returns a gamete that consists of parts of
     both genomes in this chromosome.
     :return: Gamete in form of a single bitstring.
     """
     # 1) Generate a random number (gaussian distributed) of
     # random indices which are then used to split the genes at the respective points.
     genome_size = len(genomes[0])
     num_partitions = int(get_RNG().triangular(0, genome_size / 2, genome_size))
     partitions = get_RNG().sample(range(genome_size), num_partitions)
     partitions.sort()  # Now we have all our indices, and sorted.
     partitions.append(genome_size)  # Append the end of the string
     start = 0
     gamete = []
     for p in partitions:
         i = get_RNG().choice([0, 1])
         gamete.extend(genomes[i][start:p])
         start = p
     # 'gamete' is now a list of integers. Convert the ints to strings and join 'em all together.
     return gamete
Beispiel #21
0
    def mutate(self):
        """
        Has a chance of 0.5% to perform a random mutation in the dna,
        and a chance of 1% to flip a few bits in the cultural dna.
        :return:
        """
        # Flip bit in genome
        if get_RNG().random() < 0.005:
            length = len(self.genomes)
            index = get_RNG().randrange(length)
            l = list(self.genomes[0])
            l[index] = Chromosome.invert_bit(l[index])
            g1 = "".join(l)

            index = get_RNG().randrange(length)
            l = list(self.genomes[1])
            l[index] = Chromosome.invert_bit(l[index])
            g2 = "".join(l)
            self.genomes = (g1, g2)

        # Flip a bit in culture
        if get_RNG().random() < 0.01:
            length = len(self.culture)
            num_bits_changed = int(get_RNG().triangular(0, 1, length))
            index = get_RNG().sample(range(length), num_bits_changed)
            for i in index:
                self.culture[i] = 1 - self.culture[i]
Beispiel #22
0
 def spread_creep(self, neighborhood):
     cells = [c for c in list(neighborhood.values())]
     possible_cells = [
         c for c in cells if c.team and self.team.number == c.team.number
     ]
     if possible_cells:
         if self.strategy_seed == 0:
             cab_rng.get_RNG().shuffle(cells)
             cell = cab_rng.get_RNG().choice(cells)
         else:
             min_val = min(possible_cells, key=attrgetter('temperature'))
             c_list = [
                 c for c in possible_cells
                 if c.temperature == min_val.temperature
             ]
             c_list.extend([
                 c for c in cells
                 if not c.team or self.team.number != c.team.number
             ])
             cab_rng.get_RNG().shuffle(c_list)
             cell = cab_rng.get_RNG().choice(c_list)
         self.score += cell.inc_temperature(self.team, self.power)
     else:
         print("agent died: t{0} d{1} w{2} s{3} p{4}".format(
             self.team.number, self.min_density, self.strategy_seed,
             self.strategy_seed, self.power))
         self.dead = True
Beispiel #23
0
    def walk(self, neighborhood):
        possible_cells = [
            c for c in list(neighborhood.values())
            if c.team and self.team.number == c.team.number
            and c.temperature >= self.min_density
        ]
        self.prev_x = self.x
        self.prev_y = self.y
        if possible_cells:
            if self.strategy_walk == 0:
                cab_rng.get_RNG().shuffle(possible_cells)
                cell = cab_rng.get_RNG().choice(possible_cells)
            else:  # self.strategy_walk == 1:
                min_val = min(possible_cells, key=attrgetter('temperature'))
                c_list = [
                    c for c in possible_cells
                    if c.temperature == min_val.temperature
                ]
                cab_rng.get_RNG().shuffle(c_list)
                cell = cab_rng.get_RNG().choice(c_list)
            # Move to new cell

            self.x = cell.x
            self.y = cell.y
        else:
            print("agent died: t{0} d{1} w{2} s{3} p{4}".format(
                self.team.number, self.min_density, self.strategy_seed,
                self.strategy_seed, self.power))
            self.dead = True
Beispiel #24
0
    def mutate(self):
        """
        Has a chance of 0.5% to perform a random mutation in the dna,
        and a chance of 1% to flip a few bits in the cultural dna.
        :return:
        """
        # Flip bit in genome
        if get_RNG().random() < 0.005:
            length = len(self.genomes)
            index = get_RNG().randrange(length)
            l = list(self.genomes[0])
            l[index] = Chromosome.invert_bit(l[index])
            g1 = "".join(l)

            index = get_RNG().randrange(length)
            l = list(self.genomes[1])
            l[index] = Chromosome.invert_bit(l[index])
            g2 = "".join(l)
            self.genomes = (g1, g2)

        # Flip a bit in culture
        if get_RNG().random() < 0.01:
            length = len(self.culture)
            num_bits_changed = int(get_RNG().triangular(0, 1, length))
            index = get_RNG().sample(range(length), num_bits_changed)
            for i in index:
                self.culture[i] = 1 - self.culture[i]
Beispiel #25
0
 def create_gamete(genomes):
     """
     Creates and returns a gamete that consists of parts of
     both genomes in this chromosome.
     :return: Gamete in form of a single bitstring.
     """
     # 1) Generate a random number (gaussian distributed) of
     # random indices which are then used to split the genes at the respective points.
     genome_size = len(genomes[0])
     num_partitions = int(get_RNG().triangular(0, genome_size / 2,
                                               genome_size))
     partitions = get_RNG().sample(range(genome_size), num_partitions)
     partitions.sort()  # Now we have all our indices, and sorted.
     partitions.append(genome_size)  # Append the end of the string
     start = 0
     gamete = []
     for p in partitions:
         i = get_RNG().choice([0, 1])
         gamete.extend(genomes[i][start:p])
         start = p
     # 'gamete' is now a list of integers. Convert the ints to strings and join 'em all together.
     return gamete
Beispiel #26
0
 def __init__(self, x, y, gc):
     """
     Initializes an agent
     """
     super().__init__(x, y, gc)
     self.id = "ant"
     self.prev_x = x
     self.prev_y = y
     self.max_ph = gc.MAX_PHEROMONE
     self.food = 1
     self.has_food = False
     self.dead = False
     self.color = (0, 175, 200)
     self.directions = [(1,  0), (1, -1), ( 0, -1), (-1,  0), (-1, 1), ( 0, 1)]
     self.current_dir = get_RNG().randint(0, 5)
Beispiel #27
0
 def __init__(self, x, y, gc):
     """
     Initializes an agent
     """
     super().__init__(x, y, gc)
     self.id = "ant"
     self.prev_x = x
     self.prev_y = y
     self.max_ph = gc.MAX_PHEROMONE
     self.food = 1
     self.has_food = False
     self.dead = False
     self.color = (0, 175, 200)
     self.directions = [(1, 0), (1, -1), (0, -1), (-1, 0), (-1, 1), (0, 1)]
     self.current_dir = get_RNG().randint(0, 5)
Beispiel #28
0
 def choose_dominant_gene(strings):
     """
     Takes two gene strings and returns the dominant one,
     or random if both are dominant/ recessive
     :param strings: Two sub-genes of the chromosome
     :return: The more dominant/ luckier string of both.
     """
     # How do we determine dominance?
     # For now just by looking whether there is an even number of 'ones' in it.
     dominant0 = strings[0].count('1') % 2 == 0
     dominant1 = strings[1].count('1') % 2 == 0
     if (dominant0 and dominant1) or (not (dominant0 or dominant1)):
         return get_RNG().choice([strings[0], strings[1]])
     elif dominant1:
         return strings[0]
     else:
         return strings[1]
Beispiel #29
0
 def choose_dominant_gene(strings):
     """
     Takes two gene strings and returns the dominant one,
     or random if both are dominant/ recessive
     :param strings: Two sub-genes of the chromosome
     :return: The more dominant/ luckier string of both.
     """
     # How do we determine dominance?
     # For now just by looking whether there is an even number of 'ones' in it.
     dominant0 = strings[0].count('1') % 2 == 0
     dominant1 = strings[1].count('1') % 2 == 0
     if (dominant0 and dominant1) or (not (dominant0 or dominant1)):
         return get_RNG().choice([strings[0], strings[1]])
     elif dominant1:
         return strings[0]
     else:
         return strings[1]
Beispiel #30
0
 def update(self):
     """
     This method regulates the cell's state according to the state of its neighbors.
     """
     if self.zone.type == 'EMPTY':
         self.zone.update(self)
     else:
         if len(self.neighbor_zones) > 0:
             new_zone = get_RNG().choice(list(self.neighbor_zones))
             if new_zone.type == 'RESIDENTIAL':
                 self.zone = ResidentialZone()
             elif new_zone.type == 'COMMERCIAL':
                 self.zone = CommercialZone()
             elif new_zone.type == 'INDUSTRIAL':
                 self.zone = IndustrialZone()
             self.color = self.zone.color
     self.neighbor_zones.clear()
     print("self.color: ", self.color)
     self.update_color()
Beispiel #31
0
 def update(self):
     """
     This method regulates the cell's state according to the state of its neighbors.
     """
     if self.zone.type == 'EMPTY':
         self.zone.update(self)
     else:
         if len(self.neighbor_zones) > 0:
             new_zone = get_RNG().choice(list(self.neighbor_zones))
             if new_zone.type == 'RESIDENTIAL':
                 self.zone = ResidentialZone()
             elif new_zone.type == 'COMMERCIAL':
                 self.zone = CommercialZone()
             elif new_zone.type == 'INDUSTRIAL':
                 self.zone = IndustrialZone()
             self.color = self.zone.color
     self.neighbor_zones.clear()
     print("self.color: ", self.color)
     self.update_color()
Beispiel #32
0
    def r1_select_best_cell(self, ca):
        """
        Agent selects the best cell to move to, according to: its resources, occupier and tribal alignment.
        """
        neighborhood = ca.get_empty_agent_neighborhood(self.x, self.y,
                                                       self.vision)
        best_cells = list()
        max_dist = 0
        max_w = 0

        # Find cells with the highest possible reward.
        # TODO: check if distance calculation is correct for hex grids
        # print('neighborhood: {0}'.format(list(neighborhood.keys())))
        for cell in list(neighborhood.values()):
            if not best_cells:
                best_cells = [cell]
                max_w = self.welfare(cell.sugar, cell.spice)
                max_dist = (abs(cell.x - self.x) + abs(cell.y - self.y))
            else:
                dist = ca.hex_distance(self.x, self.y, cell.q, cell.r)
                welfare = self.welfare(cell.sugar, cell.spice)
                if welfare > max_w:
                    best_cells = [cell]
                    max_w = welfare
                    max_dist = dist
                elif welfare == max_w and dist < max_dist:
                    best_cells = [cell]
                    max_dist = dist
                elif welfare == max_w and dist == max_dist:
                    best_cells.append(cell)

        result_cell = get_RNG().choice(best_cells)

        # TODO: In case the target cell is not directly adjacent, find an adjacent cell that leads into its direction.
        # TODO: Make sure to pick one adjacent cell that is NOT currently occupied. Maybe calculate a path.
        # if self.vision > 1 and CAHex.cube_distance(ca.ca_grid[self.x, self.y], result_cell) > 1:
        #     next_in_direction = CAHex.get_cell_in_direction(ca.ca_grid[self.x, self.y], result_cell)
        #     result_cell = ca.ca_grid[next_in_direction]

        self.move_to(result_cell)
        self.eat_from(result_cell)
Beispiel #33
0
    def r1_select_best_cell(self, ca):
        """
        Agent selects the best cell to move to, according to: its resources, occupier and tribal alignment.
        """
        neighborhood = ca.get_empty_agent_neighborhood(self.x, self.y, self.vision)
        best_cells = list()
        max_dist = 0
        max_w = 0

        # Find cells with the highest possible reward.
        # TODO: check if distance calculation is correct for hex grids
        # print('neighborhood: {0}'.format(list(neighborhood.keys())))
        for cell in list(neighborhood.values()):
            if not best_cells:
                best_cells = [cell]
                max_w = self.welfare(cell.sugar, cell.spice)
                max_dist = (abs(cell.x - self.x) + abs(cell.y - self.y))
            else:
                dist = ca.hex_distance(self.x, self.y, cell.q, cell.r)
                welfare = self.welfare(cell.sugar, cell.spice)
                if welfare > max_w:
                    best_cells = [cell]
                    max_w = welfare
                    max_dist = dist
                elif welfare == max_w and dist < max_dist:
                    best_cells = [cell]
                    max_dist = dist
                elif welfare == max_w and dist == max_dist:
                    best_cells.append(cell)

        result_cell = get_RNG().choice(best_cells)

        # TODO: In case the target cell is not directly adjacent, find an adjacent cell that leads into its direction.
        # TODO: Make sure to pick one adjacent cell that is NOT currently occupied. Maybe calculate a path.
        # if self.vision > 1 and CAHex.cube_distance(ca.ca_grid[self.x, self.y], result_cell) > 1:
        #     next_in_direction = CAHex.get_cell_in_direction(ca.ca_grid[self.x, self.y], result_cell)
        #     result_cell = ca.ca_grid[next_in_direction]

        self.move_to(result_cell)
        self.eat_from(result_cell)
Beispiel #34
0
    def get_island_landscape(self):
        l1 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        l2 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        lower_limit = int((self.y_dim + self.x_dim) * 0.33)
        upper_limit = int((self.y_dim + self.x_dim) * 0.9)
        print(lower_limit, upper_limit)
        last_rand = 0
        for j in range(self.y_dim):
            for i in range(self.x_dim):
                if (i + j) % self.factor == 0:
                    last_rand = int(cab_rng.get_RNG().triangular(
                        self.deepest, self.highest, self.water_level))
                l1[i][j] = last_rand

        for _ in range(self.smoothness):
            for j in range(self.y_dim):
                for i in range(self.x_dim):
                    n = 0
                    f = 0
                    for cy in range(-1, 2):
                        for cx in range(-1, 2):
                            if not (cy == 0 and cx == 0):
                                try:
                                    n += 1
                                    f += l1[i + cx][j + cy]
                                except IndexError:
                                    pass
                    avg = f / n
                    if avg > l1[i][j]:
                        diff = avg - l1[i][j]
                        l2[i][j] = l1[i][j] + (diff * self.slope)
                    elif avg < l1[i][j]:
                        diff = l1[i][j] - avg
                        l2[i][j] = l1[i][j] - (diff * self.slope)
                    else:
                        l2[i][j] = l1[i][j]
            l1, l2 = l2, l1
        return l1
Beispiel #35
0
    def get_coastal_landscape(self):
        l1 = {}
        l2 = {}
        for j in range(self.height):
            for i in range(self.width):
                # l1[i][j] = int(get_RNG().triangular(self.deepest, self.highest, 5))s
                q = i - math.floor(j / 2)
                mode = (((i + j) / 200) * 5) + self.water_level
                l1[q, j] = int(get_RNG().triangular(self.deepest + 2 * mode,
                                                    self.highest + 2 * mode,
                                                    mode))
                # l1[i][j] = int(get_RNG().triangular(self.deepest + 2 * mode, self.highest + 2 * mode, mode))

        for _ in range(self.smoothness):
            for j in range(self.height):
                for i in range(self.width):
                    q = i - math.floor(j / 2)
                    n = 0
                    f = 0
                    for d in self.gc.HEX_DIRECTIONS:
                        if not (d[0] == 0 and d[1] == 0):
                            try:
                                n += 1
                                f += l1[q + d[0], j + d[1]]
                            except KeyError:
                                pass
                    avg = f / n
                    if avg > l1[q, j]:
                        diff = avg - l1[q, j]
                        l2[q, j] = l1[q, j] + (diff * self.slope)
                    elif avg < l1[q, j]:
                        diff = l1[q, j] - avg
                        l2[q, j] = l1[q, j] - (diff * self.slope)
                    else:
                        l2[q, j] = l1[q, j]
            l1, l2 = l2, l1
        return l1
    def get_island_landscape(self):
        l1 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        l2 = [[0 for _ in range(self.y_dim)] for _ in range(self.x_dim)]
        lower_limit  = int((self.y_dim + self.x_dim) * 0.33)
        upper_limit  = int((self.y_dim + self.x_dim) * 0.9)
        print(lower_limit, upper_limit)
        last_rand = 0
        for j in range(self.y_dim):
            for i in range(self.x_dim):
                if (i + j) % self.factor == 0:
                    last_rand = int(cab_rng.get_RNG().triangular(self.deepest, self.highest, self.water_level))
                l1[i][j] = last_rand

        for _ in range(self.smoothness):
            for j in range(self.y_dim):
                for i in range(self.x_dim):
                    n = 0
                    f = 0
                    for cy in range(-1, 2):
                        for cx in range(-1, 2):
                            if not (cy == 0 and cx == 0):
                                try:
                                    n += 1
                                    f += l1[i + cx][j + cy]
                                except IndexError:
                                    pass
                    avg = f / n
                    if avg > l1[i][j]:
                        diff = avg - l1[i][j]
                        l2[i][j] = l1[i][j] + (diff * self.slope)
                    elif avg < l1[i][j]:
                        diff = l1[i][j] - avg
                        l2[i][j] = l1[i][j] - (diff * self.slope)
                    else:
                        l2[i][j] = l1[i][j]
            l1, l2 = l2, l1
        return l1
Beispiel #37
0
    def map_genome_to_attributes(self):
        """
        Decodes the genome and creates the attribute of the individual.
        """
        # The meta and init attributes cannot become smaller than 1,
        # even though that is possible by the encoding. We have to avoid that.
        meta_sugar = Chromosome.choose_dominant_gene(
            self.get_genome_substring('meta_sugar'))
        meta_spice = Chromosome.choose_dominant_gene(
            self.get_genome_substring('meta_spice'))
        init_sugar = Chromosome.choose_dominant_gene(
            self.get_genome_substring('init_sugar'))
        init_spice = Chromosome.choose_dominant_gene(
            self.get_genome_substring('init_spice'))
        vision = Chromosome.choose_dominant_gene(
            self.get_genome_substring('vision'))
        gender = get_RNG().choice(self.get_genome_substring('gender'))
        f1 = Chromosome.choose_dominant_gene(
            self.get_genome_substring('fertility_1'))
        f2 = Chromosome.choose_dominant_gene(
            self.get_genome_substring('fertility_2'))
        dying_age = Chromosome.choose_dominant_gene(
            self.get_genome_substring('dying_age'))

        self.meta_sugar = max(int(meta_sugar, 2), 1)
        self.meta_spice = max(int(meta_spice, 2), 1)
        self.init_sugar = max(int(init_sugar, 2), 1)
        self.init_spice = max(int(init_spice, 2), 1)
        self.vision = int(vision, 2)
        self.gender = int(gender, 2)
        self.dying_age = int(dying_age, 2)
        self.fertility = (int(f1, 2), int(f2, 2))

        dna = "".join((meta_sugar, meta_spice, init_sugar, init_spice, vision,
                       gender, f1, f2, dying_age))
        self.dna_color = Chromosome.convert_to_color(dna)
Beispiel #38
0
 def spread_creep(self, neighborhood):
     cells = [c for c in list(neighborhood.values())]
     possible_cells = [
         c for c in cells if c.team and self.team.number == c.team.number]
     if possible_cells:
         if self.strategy_seed == 0:
             cab_rng.get_RNG().shuffle(cells)
             cell = cab_rng.get_RNG().choice(cells)
         else:
             min_val = min(possible_cells, key=attrgetter('temperature'))
             c_list = [c for c in possible_cells if c.temperature ==
                       min_val.temperature]
             c_list.extend(
                 [c for c in cells if not c.team or self.team.number != c.team.number])
             cab_rng.get_RNG().shuffle(c_list)
             cell = cab_rng.get_RNG().choice(c_list)
         self.score += cell.inc_temperature(self.team, self.power)
     else:
         print("agent died: t{0} d{1} w{2} s{3} p{4}".format(
             self.team.number, self.min_density, self.strategy_seed, self.strategy_seed, self.power))
         self.dead = True
Beispiel #39
0
    def walk(self, neighborhood):
        possible_cells = [c for c in list(neighborhood.values(
        )) if c.team and self.team.number == c.team.number and c.temperature >= self.min_density]
        self.prev_x = self.x
        self.prev_y = self.y
        if possible_cells:
            if self.strategy_walk == 0:
                cab_rng.get_RNG().shuffle(possible_cells)
                cell = cab_rng.get_RNG().choice(possible_cells)
            else:  # self.strategy_walk == 1:
                min_val = min(possible_cells, key=attrgetter('temperature'))
                c_list = [c for c in possible_cells if c.temperature ==
                          min_val.temperature]
                cab_rng.get_RNG().shuffle(c_list)
                cell = cab_rng.get_RNG().choice(c_list)
            # Move to new cell

            self.x = cell.x
            self.y = cell.y
        else:
            print("agent died: t{0} d{1} w{2} s{3} p{4}".format(
                self.team.number, self.min_density, self.strategy_seed, self.strategy_seed, self.power))
            self.dead = True
Beispiel #40
0
    def get_cell_with_pheromone(self, target_ph, neighborhood):
        """
        Gets the cell with highest pheromone value (or random if no pheromones present)
        from the immediate neighborhood.
        :param: neighborhood is a dict of (x, y) -> cell mappings,
        where cell is a tuple of (ca_cell, [agent(s) on cell]).
        If no agent is on the cell then the list in the tuple is simply 'False'
        """
        result = None
        result_list = []
        backup_list = []
        best_cell = None
        max_ph = 0

        # Choose the possible directions the ants can currently look at.
        if self.current_dir == 5:
            possible_dirs = [4, 5, 0]
        elif self.current_dir == 0:
            possible_dirs = [5, 0, 1]
        else:
            possible_dirs = [
                self.current_dir - 1, self.current_dir, self.current_dir + 1
            ]

        for i in possible_dirs:
            d = self.directions[i]
            _x = self.x + d[0]
            _y = self.y + d[1]
            if (_x, _y) in neighborhood:
                cell = neighborhood[_x, _y]
                if cell[0].pheromones[
                        target_ph] > 0.00:  # and (not cell[1] or len(cell[1]) < 10):
                    ph = cell[0].pheromones[target_ph]
                    if ph > max_ph:
                        best_cell = cell
                        max_ph = ph
                        self.current_dir = i
                    result_list.append((cell, ph, i))
                # elif not cell[1] or len(cell[1]) < 10:
                else:
                    backup_list.append((cell, i))
        if result_list:
            if get_RNG().random() < 0.10:
                choice = AntAgent.weighted_choice(result_list)
                # choice = get_RNG().choice(result_list)
                result = choice[0]
                self.current_dir = choice[1]
            else:
                result = best_cell
        elif backup_list:
            choice = get_RNG().choice(backup_list)
            result = choice[0]
            self.current_dir = choice[1]
        else:
            # print('Ant Error: no cells found to move to!')
            self.current_dir = AntAgent.get_opposite_direction(
                self.current_dir)
            return self.get_cell_with_pheromone(target_ph, neighborhood)

        # Add a small random factor to the movement.
        return result
Beispiel #41
0
 def get_random_valid_position(self) -> Tuple[int, int]:
     """
     Returns coordinates of a random cell position that is within the boundaries of the grid.
     :returns Coordinates in hex form.
     """
     return cab_rng.get_RNG().choice(list(self.ca_grid.keys()))
Beispiel #42
0
    def generate_agent(self, abm, ca):
        # x, y = ca.get_random_valid_position()
        # while (x, y) in abm.agent_locations:
        #     x, y = ca.get_random_valid_position()
        x, y = get_RNG().choice(self.possible_starting_locations)
        self.possible_starting_locations.remove((x, y))
        meta_sugar = get_RNG().randint(self.gc.MIN_METABOLISM, self.gc.MAX_METABOLISM)
        meta_spice = get_RNG().randint(self.gc.MIN_METABOLISM, self.gc.MAX_METABOLISM)
        vision = get_RNG().randint(1, self.gc.VISION + 1)
        g = get_RNG().choice([0, 1])
        if g == 1:
            f1 = get_RNG().randint(self.gc.F_FERTILITY_START[0], self.gc.F_FERTILITY_START[1])
            f2 = get_RNG().randint(self.gc.F_FERTILITY_END[0], self.gc.F_FERTILITY_END[1])
            f = (f1, f2)
        else:
            f1 = get_RNG().randint(self.gc.M_FERTILITY_START[0], self.gc.M_FERTILITY_START[1])
            f2 = get_RNG().randint(self.gc.M_FERTILITY_END[0], self.gc.M_FERTILITY_END[1])
            f = (f1, f2)
        su = get_RNG().randint(self.gc.STARTING_SUGAR[0], self.gc.STARTING_SUGAR[1])
        sp = get_RNG().randint(self.gc.STARTING_SUGAR[0], self.gc.STARTING_SUGAR[1])
        d = get_RNG().randint(f[1], self.gc.MAX_AGENT_LIFE)
        c = [get_RNG().randint(0, int((meta_sugar + meta_spice) / 2)) for _ in range(11)]
        # imm_sys = [get_RNG().getrandbits(self.gc.NUM_TRIBES - 1) for _ in range(self.gc.IMMUNE_SYSTEM_GENOME_LENGTH)]
        imm_sys = [get_RNG().getrandbits(int((meta_sugar + meta_spice) / 2)) for _ in range(self.gc.IMMUNE_SYSTEM_GENOME_LENGTH)]
        a = 0  # get_RNG().randint(0, int(self.gc.MAX_AGENT_LIFE / 2))
        gene_string = "{0:03b}".format(meta_sugar) + "{0:03b}".format(meta_spice)\
                      + "{0:06b}".format(su) + "{0:06b}".format(sp) \
                      + "{0:03b}".format(vision) + "{0:01b}".format(g)\
                      + "{0:06b}".format(f[0]) + "{0:06b}".format(f[1]) + "{0:07b}".format(d)
        # We use generation to keep track of how far an agent has walked down the evolutionary road.
        generation = (0, 0)
        genome = (gene_string, gene_string, c, imm_sys, generation)

        # Retrieve a spawn position from the position list belonging to its tribe.
        # tribe_id = max(set(c), key=c.count)
        # get_RNG().shuffle(position_list[tribe_id])
        # p = position_list[tribe_id].pop()
        # Create the new agent and add to both, dictionary and list.
        new_agent = SSAgent(x, y, self.gc, su, sp, a, genome)
        # self.agent_dict[x, y] = new_agent
        # self.agent_list.append(new_agent)
        # abm.add_agent(new_agent)
        return new_agent