Пример #1
0
 def _spawn(self):
     """
     function to create the grid by spawning fishes and sharks initially (and only at start)
     :return:
     """
     # get simulation elements
     simulation_params = self.get_simulation_parameters(self._sid)
     grid_size = simulation_params.grid_size
     coord_array = [(x, y) for x in range(grid_size)
                    for y in range(grid_size)]
     random.shuffle(coord_array)
     # spawn fish and Sharks
     fishes = 0
     sharks = 0
     for coord in coord_array:
         if fishes < simulation_params.init_nb_fish:
             self._persistence.init_animal(
                 sim_id=self._sid,
                 current_turn=0,
                 animal_type=Animal.Fish,
                 coordinate=SquareGridCoordinate(*coord))
             fishes += 1
         elif sharks < simulation_params.init_nb_shark:
             self._persistence.init_animal(
                 sim_id=self._sid,
                 current_turn=0,
                 animal_type=Animal.Shark,
                 coordinate=SquareGridCoordinate(*coord))
             sharks += 1
         else:
             break
     return
Пример #2
0
 def _spawn(self):
     """
     function to create the grid by spawning fishes and sharks initially (and only at start)
     :return:
     """
     # get simulation elements
     simulation_params = self.simulation_params
     grid_size = simulation_params.grid_size
     coord_array = [(x, y) for x in range(grid_size) for y in range(grid_size)]
     random.shuffle(coord_array)
     # spawn fish and Sharks
     fishes = 0
     sharks = 0
     for coord in coord_array:
         if fishes < simulation_params.init_nb_fish:
             # since animal at start can be able to breed, last breed can be negative
             spawn_turn = -random.randint(0, simulation_params.fish_breed_maturity)
             self._persistence.init_animal(sim_id=self._sid, current_turn=spawn_turn, animal_type=Animal.Fish,
                                           coordinate=SquareGridCoordinate(*coord),
                                           last_breed=spawn_turn)
             fishes += 1
         elif sharks < simulation_params.init_nb_shark:
             spawn_turn = -random.randint(0, simulation_params.shark_breed_maturity)
             self._persistence.init_animal(sim_id=self._sid, current_turn=spawn_turn, animal_type=Animal.Shark,
                                           coordinate=SquareGridCoordinate(*coord),
                                           last_breed=spawn_turn)
             sharks += 1
         else:
             break
     return
Пример #3
0
 def test_neighbour_function(self):
     # full neighborhood
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(1, 1))
     assert len(neigh_list) == 8
     # corner
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(9, 9))
     assert len(neigh_list) == 3
     # line
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(0, 5))
     assert len(neigh_list) == 5
Пример #4
0
 def test_valid_coordinate(self):
     assert square_grid_valid(10, SquareGridCoordinate(1, 2))
     # raise if invalid
     with pytest.raises(TopologyError):
         square_grid_valid(10, SquareGridCoordinate(10, 2))
     # invalid not raised
     assert not square_grid_valid(
         10, SquareGridCoordinate(-1, 2), raise_err=False)
     assert not square_grid_valid(
         10, SquareGridCoordinate(1, -1), raise_err=False)
     assert not square_grid_valid(
         10, SquareGridCoordinate(1, 10), raise_err=False)
Пример #5
0
    def test_square_grid_coordinate(self):
        coord = SquareGridCoordinate(1, 2)
        assert coord.x == 1
        assert coord.y == 2
        moved = coord.move(1, 1)
        assert moved.x == 2
        assert moved.y == 3

        coord_2 = SquareGridCoordinate(1, 3)
        coord_3 = SquareGridCoordinate(1, 2)
        assert not coord == coord_2
        assert coord == coord_3
Пример #6
0
    def test_square_grid_coordinate(self):
        coord = SquareGridCoordinate(1, 2)
        assert coord.x == 1
        assert coord.y == 2
        moved = coord.move(1, 1,
                           grid_size=10)  # AM: add grid_size as new argument
        assert moved.x == 2
        assert moved.y == 3

        coord_2 = SquareGridCoordinate(1, 3)
        coord_3 = SquareGridCoordinate(1, 2)
        assert not coord == coord_2
        assert coord == coord_3
Пример #7
0
 def test_neighbour_function(self):
     # full neighborhood
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(1, 1))
     assert len(neigh_list) == 8
     # corner
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(9, 9))
     assert len(
         neigh_list
     ) == 8  # Used to work fine. Changed from 3, since now we have 'infinite' grid
     # line
     neigh_list = square_grid_neighbours(10, SquareGridCoordinate(0, 5))
     assert len(
         neigh_list
     ) == 8  # Used to work fine. Changed from 5, since now we have 'infinite' grid
Пример #8
0
 def test_topology_agnostic_eating(self):
     '''
     Check the topology-agnostic behavior, i.e. that the shark from one corner
     will eat the fish from the opposite corner
     '''
     # set fish breeding probability to 0
     sim_config_empty_local = copy.deepcopy(sim_config_empty)
     sim_config_empty_local['fish_breed_probability'] = 0
     client = SimulationClient('sqlite:///:memory:')
     grid = SimulationGrid(persistence=client,
                           simulation_parameters=sim_config_empty_local)
     a_list = [(Animal.Fish, SquareGridCoordinate(x=0, y=0)),
               (Animal.Shark, SquareGridCoordinate(x=9, y=9))]
     # adding some food and a shark
     for t, c in a_list:
         client.init_animal(sim_id=grid._sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     # updating grid turn
     grid._sim_turn = 6
     # AM: the latest two rows to allow optimized 'occupied coordinates' check
     grid.animals = grid.get_simulation_grid_data()
     grid.occupied_coord = set(
         zip(grid.animals.coord_x, grid.animals.coord_y))
     shark_update = grid._eat()
     # shark has eaten
     shark = grid._persistence.get_animals_by_type(
         sim_id=grid._sid, animal_type=Animal.Shark).iloc[0]
     # the shark is in update list
     assert len(
         shark_update) == 1, 'There should be one shark in update list'
     assert shark.last_fed == 6, 'Shark last fed value should have updated'
     assert shark_update[shark.oid] == SquareGridCoordinate(
         x=9, y=9), 'Shark previous coordinate in shark update'
     # Fish is dead
     animal_in_square = client.get_animal_in_position(
         sim_id=grid._sid,
         coordinate=SquareGridCoordinate(int(shark.coord_x),
                                         int(shark.coord_y)),
         live_only=False)
     assert len(
         animal_in_square) == 2, 'there shoud be two animals in that square'
     # check that there is no fish
     fish = grid._persistence.get_animals_by_type(sim_id=grid._sid,
                                                  animal_type=Animal.Fish)
     assert len(
         fish
     ) == 0, 'there should be no fish alive'  # there is no fish (since we put 0 breeding probability)
Пример #9
0
 def test_position_functions(self):
     client = SimulationClient('sqlite:///:memory:')
     # init DB
     sid = client.init_simulation(**sim_config)
     # add a bunch of animals
     for t, c in animal_list:
         client.init_animal(sim_id=sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     # check animal in square
     coord = SquareGridCoordinate(x=1, y=3)
     animals_in_square = client.get_animal_in_position(sim_id=sid,
                                                       coordinate=coord)
     assert len(animals_in_square) == 1
     # kill that animal
     client.kill_animal(sim_id=sid, animal_ids=[animals_in_square[0].oid])
     animals_in_square = client.get_animal_in_position(sim_id=sid,
                                                       coordinate=coord)
     assert len(animals_in_square) == 0
     # adding a live one in coord
     client.init_animal(sim_id=sid,
                        current_turn=0,
                        animal_type=Animal.Fish,
                        coordinate=coord)
     animals_in_square = client.get_animal_in_position(sim_id=sid,
                                                       coordinate=coord,
                                                       live_only=False)
     assert len(animals_in_square) == 2
Пример #10
0
 def test_check_if_occupied(self):
     '''
     Test the modified function
     '''
     client = SimulationClient('sqlite:///:memory:')
     grid = SimulationGrid(persistence=client,
                           simulation_parameters=sim_config_empty)
     a_list = [(Animal.Fish, SquareGridCoordinate(x=1, y=1)),
               (Animal.Shark, SquareGridCoordinate(x=2, y=2))]
     # adding some food and a shark
     for t, c in a_list:
         client.init_animal(sim_id=grid._sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     grid.animals = grid.get_simulation_grid_data()
     grid.occupied_coord = set(
         zip(grid.animals.coord_x, grid.animals.coord_y))
     assert grid.check_if_occupied(SquareGridCoordinate(
         x=1, y=1)) == True, 'should be occupied'
     assert grid.check_if_occupied(SquareGridCoordinate(
         x=2, y=2)) == True, 'should be occupied'
     assert grid.check_if_occupied(SquareGridCoordinate(
         x=1, y=2)) == False, 'should be spare'
     # repeat the same for 1x1 case with initialization of 1 Fish
     del client, grid, a_list
     sim_config_empty_local = copy.deepcopy(sim_config_empty)
     sim_config_empty_local['init_nb_fish'] = 1
     sim_config_empty_local['grid_size'] = 1
     client = SimulationClient('sqlite:///:memory:')
     grid = SimulationGrid(persistence=client,
                           simulation_parameters=sim_config_empty_local)
     assert grid.check_if_occupied(SquareGridCoordinate(
         x=0, y=0)) == True, 'should be occupied'
Пример #11
0
 def test_breed(self):
     client = SimulationClient('sqlite:///:memory:')
     grid = SimulationGrid(persistence=client,
                           simulation_parameters=sim_config_empty)
     a_list = [(Animal.Fish, SquareGridCoordinate(x=1, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=2, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=3, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=1, y=3)),
               (Animal.Fish, SquareGridCoordinate(x=3, y=2)),
               (Animal.Shark, SquareGridCoordinate(x=2, y=2))]
     # adding some food and a shark
     for t, c in a_list:
         client.init_animal(sim_id=grid._sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     # updating grid turn
     grid._sim_turn = 4
     shark_update = grid._eat()
     assert len(shark_update) == 1, 'Shark should have fed'
     breed_moved = grid._breed_and_move(fed_sharks=shark_update)
     assert len(
         breed_moved
     ) == 5, '4 fishes and one shark should have moved due to breeding'
     assert len(breed_moved) == (len(a_list) - 1)
     grid_df = grid.get_simulation_grid_data()
     assert len(grid_df[grid_df['animal_type'] ==
                        Animal.Shark]) == 2, 'Should be 2 Sharks'
     assert len(grid_df[grid_df['animal_type'] ==
                        Animal.Fish]) == 8, 'Should be 8 fishes'
Пример #12
0
 def has_fish_in_square(self, sim_id: int, coordinates: List[SquareGridCoordinate]) -> List[SquareGridCoordinate]:
     """
     Return a list of coordinate where fish are present
     :param sim_id:
     :param coordinates:
     :return:
     """
     fish_df = self.get_animals_by_type(sim_id=sim_id, animal_type=Animal.Fish)
     has_fish = []
     for coord in coordinates:
         fta = fish_df[(fish_df.coord_x == coord.x) & (fish_df.coord_y == coord.y)]
         if len(fta) > 0:
             has_fish.append(SquareGridCoordinate(int(fta.iloc[0].coord_x), int(fta.iloc[0].coord_y)))
     return has_fish
Пример #13
0
 def _eat(self) -> Dict[int, SquareGridCoordinate]:
     """
     Sharks that are adjacent to a Fish square eat and move into fish square (and do not move after)
     :return: list[(oid, prev_coordinate)]
     """
     _debug = 'Turn: {:<3} - Eat - '.format(self._sim_turn)
     simulation_params = self.get_simulation_parameters(self._sid)
     # get a randomized df of all sharks
     sharks = self._persistence.get_animals_by_type(
         sim_id=self._sid, animal_type=Animal.Shark).sample(frac=1)
     sharks_eating = dict()
     shark_update = dict()
     for idx, shark in sharks.iterrows():
         # get shark neighbour square
         shark_position = SquareGridCoordinate(shark.coord_x, shark.coord_y)
         shark_neighbour = square_grid_neighbours(
             simulation_params.grid_size, shark_position)
         # try to find fish
         has_fish = self._persistence.has_fish_in_square(
             sim_id=self._sid, coordinates=shark_neighbour)
         if len(has_fish) > 0:
             # Shark is eating
             random.shuffle(has_fish)
             eating_coord = has_fish[0]
             if self._persistence.eat_animal_in_square(
                     sim_id=self._sid, coordinate=eating_coord):
                 _logger.debug('{}Shark {} {} eat Fish {} and move'.format(
                     _debug, shark.oid, shark_position, eating_coord))
                 # keep shark ref and position
                 sharks_eating[shark.oid] = shark_position
                 # move shark to eating position
                 self._persistence.move_animal(sim_id=self._sid,
                                               animal_id=shark.oid,
                                               new_position=eating_coord)
                 # add to update dictionary
                 shark_update[shark.oid] = {'last_fed': self._sim_turn}
             else:
                 raise ImpossibleAction(
                     'Something went wrong in Shark: {} feeding in {}'.
                     format(shark, has_fish[0]))
         else:
             _logger.debug('{}turn: {}, No fish to eat for shark {}'.format(
                 _debug, self._sim_turn, shark.oid))
     self._persistence.update_animals(sim_id=self._sid,
                                      update_dict=shark_update)
     _logger.debug('{}{} sharks have eaten'.format(_debug,
                                                   len(sharks_eating)))
     return sharks_eating
Пример #14
0
 def test_animal_functions(self):
     client = SimulationClient('sqlite:///:memory:')
     # init DB
     sid = client.init_simulation(**sim_config)
     # add a bunch of animals
     for t, c in animal_list:
         client.init_animal(sim_id=sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     # retrieve animals
     animals_df = client.get_animals_df(sim_id=1)
     assert isinstance(animals_df, pd.DataFrame), 'results is a DataFrame'
     assert len(animals_df) == 8, 'should be only 9 animals'
     # update animals
     # create update dict
     update_dict = {
         oid: {
             'breed_count': 1,
             'last_breed': 5,
             'last_fed': 4
         }
         for oid in animals_df.oid.values
     }
     client.update_animals(sim_id=sid, update_dict=update_dict)
     animals_df = client.get_animals_df(sim_id=1)
     assert animals_df.breed_count.unique(
     )[0] == 1, 'Breed count should be one now'
     client.update_animals(sim_id=sid, update_dict={1: {'alive': False}})
     # this update should not work
     animal = client.get_animal(sim_id=sid, animal_id=1)
     assert animal.alive, 'Animal should still be alive'
     # but this should work
     client.kill_animal(sim_id=sid, animal_ids=[1, 2, 3])
     animal = client.get_animal(sim_id=sid, animal_id=1)
     assert not animal.alive, 'This time alive was updates'
     # a dead animal does not occupy a square
     assert not client.coordinate_is_occupied(
         sim_id=sid, coordinate=SquareGridCoordinate(1, 3))
     # test get animal by types
     shark_df = client.get_animals_by_type(sim_id=sid,
                                           animal_type=Animal.Shark)
     assert shark_df.animal_type.unique()[0] == Animal.Shark
Пример #15
0
 def test_eating(self):
     client = SimulationClient('sqlite:///:memory:')
     grid = SimulationGrid(persistence=client,
                           simulation_parameters=sim_config_empty)
     a_list = [(Animal.Fish, SquareGridCoordinate(x=1, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=2, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=3, y=1)),
               (Animal.Fish, SquareGridCoordinate(x=1, y=3)),
               (Animal.Fish, SquareGridCoordinate(x=3, y=2)),
               (Animal.Shark, SquareGridCoordinate(x=2, y=2))]
     # adding some food and a shark
     for t, c in a_list:
         client.init_animal(sim_id=grid._sid,
                            current_turn=0,
                            animal_type=t,
                            coordinate=c)
     # updating grid turn
     grid._sim_turn = 4
     # AM: the next two rows are to allow optimized 'occupied coordinates' check
     grid.animals = grid.get_simulation_grid_data()
     grid.occupied_coord = set(
         zip(grid.animals.coord_x, grid.animals.coord_y))
     shark_update = grid._eat()
     # shark has eaten
     shark = grid._persistence.get_animals_by_type(
         sim_id=grid._sid, animal_type=Animal.Shark).iloc[0]
     # the shark is in update list
     assert len(
         shark_update) == 1, 'There should be one shark in update list'
     assert shark.last_fed == 4, 'Shark last fed value should have updated'
     assert shark_update[shark.oid] == SquareGridCoordinate(
         x=2, y=2), 'Shark previous coordinate in shark update'
     # Fish is dead
     animal_in_square = client.get_animal_in_position(
         sim_id=grid._sid,
         coordinate=SquareGridCoordinate(int(shark.coord_x),
                                         int(shark.coord_y)),
         live_only=False)
     assert len(
         animal_in_square) == 2, 'there shoud be two animals in that square'
Пример #16
0
 def test_moving_animals(self):
     client = SimulationClient('sqlite:///:memory:')
     # init DB
     sid = client.init_simulation(**sim_config)
     # add a bunch of animals
     for v in animal_list:
         client.init_animal(sim_id=sid,
                            current_turn=0,
                            animal_type=v[0],
                            coordinate=v[1])
     # test move
     assert not client.coordinate_is_occupied(
         sim_id=sid, coordinate=SquareGridCoordinate(5, 3))
     client.move_animal(sim_id=sid,
                        animal_id=4,
                        new_position=SquareGridCoordinate(5, 3))
     assert client.coordinate_is_occupied(sim_id=sid,
                                          coordinate=SquareGridCoordinate(
                                              5, 3))
     # trying to move dead animal
     client.kill_animal(sim_id=sid, animal_ids=[3])
     with pytest.raises(ImpossibleAction):
         client.move_animal(sim_id=sid,
                            animal_id=3,
                            new_position=SquareGridCoordinate(3, 3))
     # trying to move to an already occupied square
     with pytest.raises(NonEmptyCoordinate):
         client.move_animal(sim_id=sid,
                            animal_id=5,
                            new_position=SquareGridCoordinate(5, 3))
     # but moving to a square occupied by a dead animal is possible
     assert not client.coordinate_is_occupied(
         sim_id=sid, coordinate=SquareGridCoordinate(3, 2))
     client.move_animal(sim_id=sid,
                        animal_id=1,
                        new_position=SquareGridCoordinate(3, 2))
     assert client.coordinate_is_occupied(sim_id=sid,
                                          coordinate=SquareGridCoordinate(
                                              3, 2))
Пример #17
0
    def test_fish_only(self):
        '''
        Test if non-empty, but fish only: the simulation should end
        Make two cases:
            (1) add manually the fish to empty grid
            (2) use the config with updated value for corresponding key
        '''
        # No. 1
        client = SimulationClient('sqlite:///:memory:')
        grid = SimulationGrid(persistence=client,
                              simulation_parameters=sim_config_empty)
        a_list = [
            (Animal.Fish, SquareGridCoordinate(x=1, y=1)),
        ]

        for t, c in a_list:
            client.init_animal(sim_id=grid._sid,
                               current_turn=0,
                               animal_type=t,
                               coordinate=c)

        with pytest.raises(EndOfSimulatioError):
            grid._check_deads()

        with pytest.raises(EndOfSimulatioError):
            grid.play_turn()

        # repeat the same for No. 2
        del client, grid, a_list

        sim_config_empty_local = copy.deepcopy(sim_config_empty)
        sim_config_empty_local['init_nb_fish'] = 1

        client = SimulationClient('sqlite:///:memory:')
        grid = SimulationGrid(persistence=client,
                              simulation_parameters=sim_config_empty_local)
        with pytest.raises(EndOfSimulatioError):
            grid._check_deads()

        with pytest.raises(EndOfSimulatioError):
            grid.play_turn()
Пример #18
0
    def _move_animal_type(self, animal_type: Animal, already_moved: List[int]):
        """
        Perform move action for a type of animal
        :param animal_type:
        :param already_moved:
        :return:
        """
        _debug = 'Turn: {:<3} - Move - '.format(self._sim_turn)
        simulation_params = self.simulation_params
        animals = self._persistence.get_animals_by_type(sim_id=self._sid, animal_type=animal_type).sample(frac=1)
        for _, animal in animals.iterrows():
            if animal.oid in already_moved:
                # this one has already moved so not moving
                _logger.debug('{}{} already moved'.format(_debug, animal.oid))
                continue
            elif animal.spawn_turn == self._sim_turn:
                # fish was just spawn, not moving
                _logger.debug('{}{} just spawned'.format(_debug, animal.oid))
                continue
            else:
                neighbors = square_grid_neighbours(simulation_params.grid_size, SquareGridCoordinate(animal.coord_x,
                                                                                                     animal.coord_y))
                for neigh in neighbors:
                    if not self.check_if_occupied(neigh):
                        # move animal to this slot
                        # set occupation flag to False
                        occupation_flag = False
                        _logger.debug('{}{} moved to {}'.format(_debug, animal_type.name, neigh))
                        coord_to_remove = self._persistence.move_animal(sim_id=self._sid, animal_id=animal.oid,
                                                      new_position=neigh, occupied=occupation_flag)

                        self.update_occupied_coord(old_coord=coord_to_remove, new_coord=(neigh.x, neigh.y))

                        # set back to None
                        occupation_flag = None
                        # break # AM: why we don't have break here?! Seems like we are making unnecessary operations
                    else:
                        _logger.debug('{}{}: {} had no space to move to'.format(_debug, animal_type.name, animal.oid))
        return
Пример #19
0
 def _move_animal_type(self, animal_type: Animal, already_moved: List[int]):
     """
     Perform move action for a type of animal
     :param animal_type:
     :param already_moved:
     :return:
     """
     _debug = 'Turn: {:<3} - Move - '.format(self._sim_turn)
     simulation_params = self.get_simulation_parameters(self._sid)
     animals = self._persistence.get_animals_by_type(
         sim_id=self._sid, animal_type=animal_type).sample(frac=1)
     for _, animal in animals.iterrows():
         _logger.debug(animal)
         if animal.oid in already_moved:
             # this one has already moved so not moving
             _logger.debug('{}{} already moved'.format(_debug, animal.oid))
             continue
         elif animal.spawn_turn == self._sim_turn:
             # fish was just spawn, not moving
             _logger.debug('{}{} just spawned'.format(_debug, animal.oid))
             continue
         else:
             neighbors = square_grid_neighbours(
                 simulation_params.grid_size,
                 SquareGridCoordinate(animal.coord_x, animal.coord_y))
             for neigh in neighbors:
                 if not self._persistence.coordinate_is_occupied(
                         self._sid, neigh):
                     # move animal to this slot
                     _logger.debug('{}{} oid[{}] moved to {}'.format(
                         _debug, animal_type.name, animal.oid, neigh))
                     self._persistence.move_animal(sim_id=self._sid,
                                                   animal_id=animal.oid,
                                                   new_position=neigh)
                 else:
                     _logger.debug(
                         '{}{}: {} had no space to move to'.format(
                             _debug, animal_type.name, animal.oid))
     return
Пример #20
0
    def test_database_init(self):
        client = SimulationClient('sqlite:///:memory:')
        # init DB
        sid = client.init_simulation(**sim_config)
        assert len(
            client.get_all_simulations()) == 1, 'Should be only one simulation'
        assert isinstance(client.get_simulation(sid), Simulation)

        # check exception raised in init when adding animal on non-existent sim
        with pytest.raises(ValueError):
            client.init_animal(sim_id=10,
                               current_turn=0,
                               animal_type=Animal.Fish,
                               coordinate=SquareGridCoordinate(x=0, y=1))
        # init some animals
        client.init_animal(sim_id=sid,
                           current_turn=0,
                           animal_type=Animal.Fish,
                           coordinate=SquareGridCoordinate(x=0, y=1))
        assert client.coordinate_is_occupied(sim_id=sid,
                                             coordinate=SquareGridCoordinate(
                                                 x=0, y=1))

        # check exception for adding animal to an already occupied square
        with pytest.raises(NonEmptyCoordinate):
            client.init_animal(sim_id=sid,
                               current_turn=0,
                               animal_type=Animal.Fish,
                               coordinate=SquareGridCoordinate(x=0, y=1))
        # but should be fine in a new simulation
        sid_2 = client.init_simulation(**sim_config)
        client.init_animal(sim_id=sid_2,
                           current_turn=0,
                           animal_type=Animal.Fish,
                           coordinate=SquareGridCoordinate(x=0, y=1))

        # spawn outside the grid
        with pytest.raises(TopologyError):
            client.init_animal(sim_id=sid_2,
                               current_turn=0,
                               animal_type=Animal.Fish,
                               coordinate=SquareGridCoordinate(x=10, y=1))
Пример #21
0
    def test_animal_function(self):
        client = SimulationClient('sqlite:///:memory:')
        # init DB
        sid = client.init_simulation(**sim_config)
        # add a bunch of animals
        a_list = [(Animal.Fish, SquareGridCoordinate(x=1, y=1)),
                  (Animal.Fish, SquareGridCoordinate(x=2, y=1)),
                  (Animal.Fish, SquareGridCoordinate(x=3, y=1)),
                  (Animal.Fish, SquareGridCoordinate(x=1, y=3)),
                  (Animal.Fish, SquareGridCoordinate(x=3, y=2))]
        for t, c in a_list:
            client.init_animal(sim_id=sid,
                               current_turn=0,
                               animal_type=t,
                               coordinate=c)
        coord_list = client.has_fish_in_square(
            sim_id=sid, coordinates=[SquareGridCoordinate(1, 1)])
        assert len(coord_list) == 1, 'There should be a single fish'
        coord_list = client.has_fish_in_square(
            sim_id=sid, coordinates=[SquareGridCoordinate(1, 2)])
        assert len(coord_list) == 0, 'There should be no fish here'
        neigh = square_grid_neighbours(grid_size=10,
                                       coordinate=SquareGridCoordinate(2, 2))
        coord_list = client.has_fish_in_square(sim_id=sid, coordinates=neigh)
        assert len(coord_list) == 5, 'There should be 5 fishes here'

        # eating animals
        eaten = client.eat_animal_in_square(sim_id=sid,
                                            coordinate=SquareGridCoordinate(
                                                1, 1))
        assert eaten, 'Fish in 1, 1 should have been eaten'
        # can't eat dead Fish
        eaten = client.eat_animal_in_square(sim_id=sid,
                                            coordinate=SquareGridCoordinate(
                                                1, 1))
        assert not eaten, 'Should not be able to eat a dead Fish'
        client.init_animal(sim_id=sid,
                           current_turn=0,
                           animal_type=Animal.Shark,
                           coordinate=SquareGridCoordinate(5, 5))
        eaten = client.eat_animal_in_square(sim_id=sid,
                                            coordinate=SquareGridCoordinate(
                                                5, 5))
        assert not eaten, 'Should not be able to eat a Shark'
Пример #22
0
sim_config = {
    'grid_size': 10,
    'init_nb_fish': 50,
    'fish_breed_maturity': 3,
    'fish_breed_probability': 80,
    'fish_speed': 2,
    'init_nb_shark': 5,
    'shark_breed_maturity': 5,
    'shark_breed_probability': 100,
    'shark_speed': 4,
    'shark_starving': 4
}

animal_list = [
    (Animal.Fish, SquareGridCoordinate(x=1, y=3)),
    (Animal.Fish, SquareGridCoordinate(x=2, y=1)),
    (Animal.Fish, SquareGridCoordinate(x=3, y=2)),
    (Animal.Fish, SquareGridCoordinate(x=4, y=3)),
    (Animal.Fish, SquareGridCoordinate(x=5, y=4)),
    (Animal.Shark, SquareGridCoordinate(x=6, y=5)),
    (Animal.Shark, SquareGridCoordinate(x=6, y=6)),
    (Animal.Fish, SquareGridCoordinate(x=6, y=1)),
]


class TestPersistence:
    def test_database_init(self):
        client = SimulationClient('sqlite:///:memory:')
        # init DB
        sid = client.init_simulation(**sim_config)
Пример #23
0
 def _breed_and_move(
         self, fed_sharks: Dict[int, SquareGridCoordinate]) -> List[int]:
     """
     Sharks or Fish that can breed, do so in same square (and Move), others moves if free space
     - Shark Breed first
     - Then Fish
     :parameter fed_sharks: list of sharks that fed and moved (breed, if possible, on previous position)
     :return: return the list of animals that bred and moved
     """
     # perform breed for
     _debug = 'Turn: {:<3} - Breed - '.format(self._sim_turn)
     simulation_params = self.get_simulation_parameters(self._sid)
     moved = []
     to_update = {}
     # First for sharks
     sharks = self._persistence.get_animals_by_type(
         sim_id=self._sid, animal_type=Animal.Shark).sample(frac=1)
     for idx, shark in sharks.iterrows():
         # can shark breed?
         if (self._sim_turn - shark.spawn_turn
             ) >= simulation_params.shark_breed_maturity:
             # shark can breed
             if random.randint(
                     0, 100) <= simulation_params.shark_breed_probability:
                 # shark is possibly breeding...
                 breed_coord = None
                 if shark.oid in fed_sharks:
                     # ...if shark has eaten...
                     breed_coord = fed_sharks[shark.oid]
                     if self._persistence.coordinate_is_occupied(
                             self._sid, breed_coord):
                         # someone took that space before breeding
                         _logger.debug(
                             '{}This shark {} breeding has fed and moved,' +
                             ' cannot breed in {} because position is taken'
                             .format(_debug, shark.oid, breed_coord))
                         breed_coord = None
                     _logger.debug(
                         '{}This shark {} breeding has fed and moved, breeding in {}'
                         .format(_debug, shark.oid, breed_coord))
                     # shark has already moved to eating position
                     moved.append(shark.oid)
                 else:
                     # ... or if free space is available
                     neighbors = square_grid_neighbours(
                         simulation_params.grid_size,
                         SquareGridCoordinate(shark.coord_x, shark.coord_y))
                     for neigh in neighbors:
                         if not self._persistence.coordinate_is_occupied(
                                 self._sid, neigh):
                             breed_coord = SquareGridCoordinate(
                                 int(shark.coord_x), int(shark.coord_y))
                             # move shark to this slot
                             self._persistence.move_animal(
                                 sim_id=self._sid,
                                 animal_id=shark.oid,
                                 new_position=neigh)
                             moved.append(shark.oid)
                             _logger.debug(
                                 '{}Shark {} not fed breeding in {}, moving to {}'
                                 .format(_debug, shark.oid, breed_coord,
                                         neigh))
                             # break out of loop
                             break
                 if breed_coord is not None:
                     to_update[shark.oid] = {
                         'last_breed': self._sim_turn,
                         'breed_count': shark.breed_count + 1
                     }
                     # spawn new fish in breed_coord
                     new_oid = self._persistence.init_animal(
                         sim_id=self._sid,
                         current_turn=self._sim_turn,
                         animal_type=Animal.Shark,
                         coordinate=breed_coord)
                     _logger.debug('{}Spawning new shark {} {}'.format(
                         _debug, new_oid, breed_coord))
     # Last Fishes, randomize
     fishes = self._persistence.get_animals_by_type(
         sim_id=self._sid, animal_type=Animal.Fish).sample(frac=1)
     for idx, fish in fishes.iterrows():
         # can fish breed?
         if (self._sim_turn -
                 fish.spawn_turn) >= simulation_params.fish_breed_maturity:
             # fish can breed
             if random.randint(
                     0, 100) <= simulation_params.fish_breed_probability:
                 # fish is possibly breeding if free space is available
                 breed_coord = SquareGridCoordinate(int(fish.coord_x),
                                                    int(fish.coord_y))
                 _logger.debug(
                     '{}Fish breeding in {} if space is available'.format(
                         _debug, breed_coord))
                 neighbors = square_grid_neighbours(
                     simulation_params.grid_size,
                     SquareGridCoordinate(fish.coord_x, fish.coord_y))
                 for neigh in neighbors:
                     if not self._persistence.coordinate_is_occupied(
                             self._sid, neigh):
                         _logger.debug(
                             '{}Space found in {}, fish breed and move'.
                             format(_debug, neigh))
                         to_update[fish.oid] = {
                             'last_breed': self._sim_turn,
                             'breed_count': fish.breed_count + 1
                         }
                         # move fish to this slot
                         self._persistence.move_animal(sim_id=self._sid,
                                                       animal_id=fish.oid,
                                                       new_position=neigh)
                         moved.append(fish.oid)
                         # spawn new fish in breed_coord
                         self._persistence.init_animal(
                             sim_id=self._sid,
                             current_turn=self._sim_turn,
                             animal_type=Animal.Fish,
                             coordinate=breed_coord)
                         # break out of loop
                         break
     # now, update all animals
     if len(to_update) > 0:
         _logger.debug('{}{} animals updated after breeding'.format(
             _debug, len(to_update)))
         self._persistence.update_animals(sim_id=self._sid,
                                          update_dict=to_update)
     # add shark that ate and did not breed to the moved list
     for oid in fed_sharks.keys():
         if oid not in moved:
             _logger.debug('{}Shark {} did not breed after movin'.format(
                 _debug, oid))
             moved.append(oid)
     # return animal list that have already bred and moved
     return moved
Пример #24
0
from fish_bowl.dataio.persistence import SimulationClient, get_database_string
from fish_bowl.process.topology import SquareGridCoordinate
from fish_bowl.process.simple_display import display_simple_grid

client = SimulationClient(get_database_string())
print(display_simple_grid(client.get_animals_df(sim_id=1), 10))
coord_1 = SquareGridCoordinate(6, 8)
coord_2 = SquareGridCoordinate(7, 9)
print(
    client.get_animal_in_position(sim_id=1,
                                  coordinate=coord_1,
                                  live_only=False))
print(
    client.get_animal_in_position(sim_id=1,
                                  coordinate=coord_2,
                                  live_only=False))