コード例 #1
0
    def do(self, world: World, elapsed: float, location: Location, position: Position, ant: ModularAnt):
        try:
            # Get a list of ALL possible directions to move in.
                # Compile list into a list of pairs, where the first entry is a direction, and the second a weight.
            directions: Directions = Directions(world, position)

            # Bias the direction in terms of the origin position.
            if self.brood_position is not None:
                directions.bias(brood_direction_func(self.hold_chance, self.brood_position))

            # Bias the direction weights, by pheromone level (with respect to the bias amount).
            directions.bias(pheromone_bias_func(age_bias(self.pheromone_bias, self.age)))

            # Bias by brood pheromones, encouraging ants to adopt a nurse role.
            directions.bias(brood_pheromone_bias_func(self.age))

            # Make a random, weighted selection of these direction.
            self.facing = directions.get_random_direction()

            # Apply a wobble at random.
            d: Direction = self.facing.get_wobble(random.choice(array([0, -1, 1]), p=array([1 - self.wobble_chance,
                                self.wobble_chance/2, self.wobble_chance/2])))
            to: Location = world.get_location(position.x + d.get()[0], position.y + d.get()[1])
            world.move(location, to)
        except IndexError:
            # The ant can't move...
            pass
コード例 #2
0
def __populate_with_objects(world: World, objects_file: str) -> World:
    if objects_file is None or objects_file == "":
        return world
    with open(objects_file) as file:
        lines: [str] = file.readlines()
        for line in lines:
            name, x, y = line.split()[0], int(line.split()[1]), int(
                line.split()[2])
            world.add_object(factory.make_object(name), x, y)
    return world
コード例 #3
0
 def get_baked(world: World, position: Position) -> [(Direction, float)]:
     if world not in Directions.compiled_positions:
         Directions.compiled_positions[world] = {}
         for i in range(world.get_dimensions()[0]):
             for j in range(world.get_dimensions()[1]):
                 Directions.compiled_positions[world][(
                     i,
                     j)] = Directions.get_weighted_directions(world, i, j)
     return Directions.compiled_positions[world][(position.x,
                                                  position.y)].copy()
コード例 #4
0
def __generate_with_grounds(grounds_file: str) -> World:
    with open(grounds_file) as file:
        lines: [str] = file.readlines()
        width, height = int(lines[0].split()[0]), int(lines[0].split()[1])
        world = World(width, height)

        for y in range(height):
            strings = lines[y + 1].split()
            for x in range(width):
                world.set_location(Location(factory.make_ground(strings[x])),
                                   x, y)
        return world
コード例 #5
0
    def draw_world(world: World, *object_kinds: [Kind]):
        """\
    Draws a World in its current state.
        """
        colours: [[Colour]] = world.get_printable(*object_kinds)

        colour_list_of_list = []
        cmap = []
        colour_dict = {}
        for i in range(len(colours[0])):
            colour_list_of_list.append([])
            for j in range(len(colours)):
                if colours[j][i].get_rgba() not in colour_dict:
                    colour_dict[colours[j][i].get_rgba()] = len(colour_dict)
                    cmap.append(colours[j][i].get_rgba())
                colour_list_of_list[i].append(
                    colour_dict[colours[j][i].get_rgba()])
        cmap = mpl.colors.ListedColormap(cmap)
        plt.figure(figsize=(len(colour_list_of_list[0]),
                            len(colour_list_of_list)))
        plt.axis("off")
        plt.pcolor(colour_list_of_list[::-1], cmap=cmap)

        plt.get_current_fig_manager().window.state("zoomed")

        plt.show()
コード例 #6
0
 def change_dir_random(world: World, elapsed: float, location: Location, pos: Position):
     possible_free_locations = []
     # scan 1 range saving taking note of all available spots
     for i in range(-1, 2):
         for j in range(-1, 2):
             if i != 0 and j != 0:
                 if world.get_location(pos.get_coordinates()[0] + i, pos.get_coordinates()[1] + j).is_free():
                     possible_free_locations.append(
                         [pos.get_coordinates()[0] + i, pos.get_coordinates()[1] + j, i, j])
     # if at least 1 available spot in 1 range
     if len(possible_free_locations) > 0:
         # pick a random one and move there
         random_available_space = random.choice(possible_free_locations)
         WanderBehaviour.move(ant, world.get_location(pos.x, pos.y),
                              world.get_location(random_available_space[0], random_available_space[1]))
         ant.current_dir = [random_available_space[2], random_available_space[3]]
コード例 #7
0
    def tick(self, world: World, elapsed: float, location: Location, position: Position):
        self.age += elapsed * ModularAnt.AGE_SCALE
        self.current_wander_behaviour.set_age(self.age)
        self.current_wander_behaviour.set_seeking_food(not self.carrying_food)

        if random.random() > self.hold_position_chance * (1 + self.interacting_ticks):
            self.current_wander_behaviour.do(world, elapsed, location, position, self)

        if self.age < ModularAnt.FORAGING_AGE or random.random() < ModularAnt.\
                FORAGING_PHEROMONE_OVERRIDE_CHANCE:
            location.add_pheromones(ModularAnt.PHEROMONES_PER_TICK)
        else:
            if location.get_brood_pheromone_count() == 0 and location.get_pheromone_count() == 0:
                location.add_foraging_pheromones(ModularAnt.FORAGING_PHEROMONES_PER_TICK)

        # If this ant is in the foraging area, it will pick up food readily.
        if not self.carrying_food:
            if location.get_ground().get_id() == ForageGrounds.get_id() or \
                    random.random() < ModularAnt.ALT_PICKUP_CHANCE:
                foods: [Object] = location.get_objects(Kind.FOOD)
                if len(foods) > 0:
                    self.carrying_food = True
                    location.remove_object(foods[-1])
        elif location.get_ground().get_id() == Nest.get_id():
            if random.random() < ModularAnt.FOOD_DROP_CHANCE or sum(map(lambda l: len(l.get_objects(Kind.FOOD)),
                    world.get_adjacent_locations(position.x, position.y, 1, False))) > 0:
                location.add_object(Food())
                self.carrying_food = False


        # Measure interactions:
        others: [int] = []
        for loc in world.get_adjacent_locations(position.x, position.y, ModularAnt.INTERACTION_RADIUS, False):
            if loc.get_actor() is None:
                continue
            if isinstance(loc.get_actor(), ModularAnt):
                other: ModularAnt = loc.get_actor()
                if ModularAnt.can_interact(self, other):
                    others.append(other.get_ant_id())
        if self.interacting_with_id in others:
            self.interacting_ticks += 1
            if self.interacting_ticks > ModularAnt.INTERACTING_TICKS_THRESHOLD:
                self.interact(self.interacting_with_id)
        elif len(others) > 0:
            self.interacting_with_id = others[0]
            self.interacting_ticks = 0
コード例 #8
0
 def pheromone_bias(world: World, position: Position, direction: Direction,
                    weight: float) -> float:
     try:
         loc: Location = world.get_location(position.x + direction.get()[0],
                                            position.y + direction.get()[1])
         return weight + (bias * loc.get_pheromone_count()
                          if loc.is_free() and weight != 0 else 0)
     except IndexError:
         return 0
コード例 #9
0
 def tick(self, world: World, elapsed: float, location: Location, position: Position):
     if self.brood_position is None:
         self.brood_position = (position.x, position.y)
         self.current_wander_behaviour.set_brood_position(self.brood_position)
     # location.add_brood_pheromones(ModularQueen.BROOD_PHEROMONES_PER_TICK)
     for loc in world.get_adjacent_locations(position.x, position.y, 1, False):
         loc.add_brood_pheromones(ModularQueen.BROOD_PHEROMONES_PER_TICK)
     self.current_wander_behaviour.set_age(ModularQueen.QUEEN_LOGICAL_AGE)
     super().tick(world, elapsed, location, position)
コード例 #10
0
def __populate_with_actors(world: World, actors_file: str) -> World:
    if actors_file is None or actors_file == "":
        return world
    with open(actors_file) as file:
        lines: [str] = file.readlines()
        for line in lines:
            name, x, y = line.split()[0], int(line.split()[1]), int(
                line.split()[2])

            attributes: Union[Attributes, None]
            if len(line.split()) > 3:
                attributes = Attributes(
                    ast.literal_eval(''.join(line.split()[3:])))
            else:
                attributes = None

            world.add_actor(factory.make_actor(name, attributes), x, y)
    return world
コード例 #11
0
 def exploration_bias(world: World, position: Position,
                      direction: Direction, weight: float) -> float:
     try:
         loc: Location = world.get_location(position.x + direction.get()[0],
                                            position.y + direction.get()[1])
         return weight * (tanh((age - 130) / 10) + 2 # weight * 5 * (tanh((age - 130)/(10)) + 1.2 #
                                     ) if (loc.get_pheromone_count() <= FORAGING_PHEROMONE_THRESHOLD and
                                     loc.get_brood_pheromone_count() <= FORAGING_PHEROMONE_THRESHOLD) or \
                                     loc.get_foraging_pheromone_count() > FORAGING_PHEROMONE_THRESHOLD else weight
     except IndexError:
         return 0
コード例 #12
0
 def tick(self, world: World, elapsed: float, location: Location,
          position: Position):
     try:
         # COMPLETELY RANDOM CHOICES FOR WALKS (no preserving of direction).
         to: Location = Random().choice(
             world.get_adjacent_locations(position.x, position.y, 1, True))
         self.move(location, to)
         self.food_interaction(to, world, position)
     except IndexError:
         # The ant can't find anywhere to move...
         location.add_object(TestObject())
コード例 #13
0
 def get_weighted_directions(world: World, x: int,
                             y: int) -> [(Direction, float)]:
     directions: [(Directions, float)] = []
     for i in range(-1, 2):
         for j in range(-1, 2):
             if i == j:
                 continue
             weight: float
             try:
                 loc: Location = world.get_location(x + i, y + j)
                 weight = 1 if loc.is_free() else 0
             except (IndexError, InvalidLocationException):
                 weight = 0
             directions.append((Direction(i, j), weight))
     return directions
コード例 #14
0
 def food_interaction(self, loc: Location, world: World,
                      position: Position):
     if self.carrying is not None and Random().random(
     ) < StigmergyAnt.DROP_CHANCE:
         for l in world.get_adjacent_locations(position.x, position.y, 1,
                                               False):
             if len(l.get_objects(Kind.FOOD)) > 0:
                 loc.add_object(self.carrying)
                 self.carrying = None
                 break
     else:
         food_items: [Object] = loc.get_objects(Kind.FOOD)
         if len(food_items) > 0:
             self.carrying = food_items[0]
             loc.remove_object(self.carrying)
コード例 #15
0
    def change_dir_random_chance(self, world: World, elapsed: float, location: Location, pos: Position, chance: float):
        if  chance < random.random(): #90% of the time

            #if spot in same direction is free and passes a 33% chance, go there
            if world.get_location(pos.get_coordinates()[0] + self.current_dir[0], pos.get_coordinates()[1] + self.current_dir[1]).is_free() and random.random() < 1/3:
                self.move_ant(world, elapsed, pos, [pos.get_coordinates()[0] + self.current_dir[0], pos.get_coordinates()[1] + self.current_dir[1]])
            else:
                #with a 50% choose the adjacent spot e.g. if going north, pick north-east 50% of the time , north-west 50% of the time
                next_dirr = self.give_dir_next_to_current( self.current_dir[0], self.current_dir[1])

                #if the first picked adjacent spot is free go there
                if world.get_location(pos.get_coordinates()[0] + next_dirr[0][0],pos.get_coordinates()[1] + next_dirr[0][1]).is_free():
                    self.move_ant(world, elapsed, pos, [pos.get_coordinates()[0] + next_dirr[0][0], pos.get_coordinates()[1] + next_dirr[0][1]])

                # else if the second picked adjacent spot is free go there
                elif world.get_location(pos.get_coordinates()[0] + next_dirr[1][0],pos.get_coordinates()[1] + next_dirr[1][1]).is_free():
                    self.move_ant(world, elapsed, pos, [pos.get_coordinates()[0] + next_dirr[1][0], pos.get_coordinates()[1] + next_dirr[1][1]])

                #else go random available spot ... and if no spot available change_dir_random will make the ant stay still
                else:
                    self.change_dir_random(world,elapsed,location,pos)

        else: #10% of the time go random available spot ... and if no spot available change_dir_random will make the ant stay still
            self.change_dir_random(world,elapsed,location,pos)
コード例 #16
0
 def food_lure(world: World, position: Position, direction: Direction,
               weight: float) -> float:
     locations: [(Location, int, int)
                 ] = world.get_adjacent_locations_with_positions(
                     position.x, position.y, FOOD_LURE_RADIUS, True)
     return weight + sum(
         map(
             lambda lxy: FOOD_BIAS_FACTOR * len(lxy[0].get_objects(Kind.FOOD
                                                                   )),
             filter(
                 lambda lxy:
                 (sign(lxy[1] - position.x) == sign(direction.x) or
                  direction.x == 0) and (sign(lxy[2] - position.y) == sign(
                      direction.y) or direction.y == 0),
                 filter(
                     lambda lxy: lxy[0].get_ground().get_id() ==
                     ForageGrounds.get_id(), locations))))
コード例 #17
0
 def move_ant(self,world: World, elapsed: float, pos: Position, target:list):
     world.get_location(pos.get_coordinates()[0], pos.get_coordinates()[1]).remove_actor()
     world.get_location(target[0], target[1]).set_actor(self)
     world.get_location(target[0], target[1]).add_object(TestObject())
コード例 #18
0
def save(world: World):
    world.write_out()
    ModularAnt.save_interactions()
コード例 #19
0
 def tick(self, world: World, elapsed: float, location: Location, position: Position):
     if random.random() < FoodGenerator.CHANCE:
         for loc in world.get_adjacent_locations(position.x, position.y, FoodGenerator.RADIUS, False):
             if len(loc.get_objects(Kind.FOOD)) == 0:
                 loc.add_object(Food())
コード例 #20
0
    def change_dir_random_chance(self, world: World, elapsed: float, location: Location, pos: Position,
                                 variation_chance: float, wobble_chance: float, ant: BehaviourAnt):
        def give_dir_next_to_current(i, j):
            if i == -1 and j == 1:
                if random.random() > 0.5:
                    return ([[-1, 0], [0, 1]])
                return ([[0, 1], [-1, 0]])
            if i == -1 and j == 0:
                if random.random() > 0.5:
                    return ([[-1, 1], [-1, -1]])
                return ([[-1, -1], [-1, 1]])
            if i == -1 and j == -1:
                if random.random() > 0.5:
                    return ([[-1, 0], [0, -1]])
                return ([[0, -1], [-1, 0]])
            if i == 0 and j == 1:
                if random.random() > 0.5:
                    return ([[-1, 1], [1, 1]])
                return ([[1, 1], [-1, 1]])
            if i == 0 and j == -1:
                if random.random() > 0.5:
                    return ([[-1, -1], [1, -1]])
                return ([[1, -1], [-1, -1]])
            if i == 1 and j == 1:
                if random.random() > 0.5:
                    return ([[0, 1], [1, 0]])
                return ([[1, 0], [0, 1]])
            if i == 1 and j == 0:
                if random.random() > 0.5:
                    return ([[1, 1], [1, -1]])
                return ([[1, -1], [1, 1]])
            if i == 1 and j == -1:
                if random.random() > 0.5:
                    return ([[1, 0], [0, -1]])
                return ([[0, -1], [1, 0]])


        def change_dir_random(world: World, elapsed: float, location: Location, pos: Position):
            possible_free_locations = []
            # scan 1 range saving taking note of all available spots
            for i in range(-1, 2):
                for j in range(-1, 2):
                    if i != 0 and j != 0:
                        if world.get_location(pos.get_coordinates()[0] + i, pos.get_coordinates()[1] + j).is_free():
                            possible_free_locations.append(
                                [pos.get_coordinates()[0] + i, pos.get_coordinates()[1] + j, i, j])
            # if at least 1 available spot in 1 range
            if len(possible_free_locations) > 0:
                # pick a random one and move there
                random_available_space = random.choice(possible_free_locations)
                WanderBehaviour.move(ant, world.get_location(pos.x, pos.y),
                                     world.get_location(random_available_space[0], random_available_space[1]))
                ant.current_dir = [random_available_space[2], random_available_space[3]]


        if variation_chance < random.random():  # 90% of the time
            # if spot in same direction is free and passes a 33% chance, go there
            if world.get_location(pos.get_coordinates()[0] + ant.current_dir[0],
                                  pos.get_coordinates()[1] + ant.current_dir[
                                      1]).is_free() and random.random() < wobble_chance:
                WanderBehaviour.move(ant, world.get_location(pos.x, pos.y),
                                     world.get_location(pos.get_coordinates()[0] + ant.current_dir[0],
                                                        pos.get_coordinates()[1] + ant.current_dir[1]))
            else:
                # with a 50% choose the adjacent spot e.g. if going north, pick north-east 50% of the time , north-west 50% of the time
                next_dirr = give_dir_next_to_current(ant.current_dir[0], ant.current_dir[1])

                # if the first picked adjacent spot is free go there
                if world.get_location(pos.get_coordinates()[0] + next_dirr[0][0],
                                      pos.get_coordinates()[1] + next_dirr[0][1]).is_free():
                    WanderBehaviour.move(ant, world.get_location(pos.x, pos.y),
                                         world.get_location(pos.get_coordinates()[0] + next_dirr[0][0],
                                                            pos.get_coordinates()[1] + next_dirr[0][1]))

                # else if the second picked adjacent spot is free go there
                elif world.get_location(pos.get_coordinates()[0] + next_dirr[1][0],
                                        pos.get_coordinates()[1] + next_dirr[1][1]).is_free():
                    WanderBehaviour.move(ant, world.get_location(pos.x, pos.y),
                                         world.get_location(pos.get_coordinates()[0] + next_dirr[1][0],
                                                            pos.get_coordinates()[1] + next_dirr[1][1]))

                # else go random available spot ... and if no spot available change_dir_random will make the ant stay still
                else:
                    change_dir_random(world, elapsed, location, pos)

        else:  # 10% of the time go random available spot ... and if no spot available change_dir_random will make the ant stay still
            change_dir_random(world, elapsed, location, pos)