|
1 | 1 | import mesa |
2 | 2 |
|
3 | | -from .random_walk import RandomWalker |
| 3 | +from mesa.experimental.cell_space import CellAgent, FixedAgent |
4 | 4 |
|
5 | 5 |
|
6 | | -class Sheep(RandomWalker): |
7 | | - """ |
8 | | - A sheep that walks around, reproduces (asexually) and gets eaten. |
9 | | -
|
10 | | - The init is the same as the RandomWalker. |
11 | | - """ |
| 6 | +class Animal(CellAgent): |
| 7 | + """The base animal class.""" |
12 | 8 |
|
13 | | - energy = None |
| 9 | + def __init__(self, model, energy, p_reproduce, energy_from_food, cell): |
| 10 | + """Initializes an animal. |
14 | 11 |
|
15 | | - def __init__(self, model, moore, energy=None): |
16 | | - super().__init__(model, moore=moore) |
| 12 | + Args: |
| 13 | + model: a model instance |
| 14 | + energy: starting amount of energy |
| 15 | + p_reproduce: probability of sexless reproduction |
| 16 | + energy_from_food: energy obtained from 1 unit of food |
| 17 | + cell: the cell in which the animal starts |
| 18 | + """ |
| 19 | + super().__init__(model) |
17 | 20 | self.energy = energy |
| 21 | + self.p_reproduce = p_reproduce |
| 22 | + self.energy_from_food = energy_from_food |
| 23 | + self.cell = cell |
| 24 | + |
| 25 | + def spawn_offspring(self): |
| 26 | + """Create offspring.""" |
| 27 | + self.energy /= 2 |
| 28 | + self.__class__( |
| 29 | + self.model, |
| 30 | + self.energy, |
| 31 | + self.p_reproduce, |
| 32 | + self.energy_from_food, |
| 33 | + self.cell, |
| 34 | + ) |
| 35 | + |
| 36 | + def feed(self): ... # noqa: D102 |
18 | 37 |
|
19 | 38 | def step(self): |
20 | | - """ |
21 | | - A model step. Move, then eat grass and reproduce. |
22 | | - """ |
23 | | - self.random_move() |
24 | | - living = True |
25 | | - |
26 | | - if self.model.grass: |
27 | | - # Reduce energy |
28 | | - self.energy -= 1 |
29 | | - |
30 | | - # If there is grass available, eat it |
31 | | - this_cell = self.model.grid.get_cell_list_contents([self.pos]) |
32 | | - grass_patch = next(obj for obj in this_cell if isinstance(obj, GrassPatch)) |
33 | | - if grass_patch.fully_grown: |
34 | | - self.energy += self.model.sheep_gain_from_food |
35 | | - grass_patch.fully_grown = False |
| 39 | + """One step of the agent.""" |
| 40 | + self.cell = self.cell.neighborhood.select_random_cell() |
| 41 | + self.energy -= 1 |
36 | 42 |
|
37 | | - # Death |
38 | | - if self.energy < 0: |
39 | | - self.model.grid.remove_agent(self) |
40 | | - self.remove() |
41 | | - living = False |
| 43 | + self.feed() |
42 | 44 |
|
43 | | - if living and self.random.random() < self.model.sheep_reproduce: |
44 | | - # Create a new sheep: |
45 | | - if self.model.grass: |
46 | | - self.energy /= 2 |
47 | | - lamb = Sheep(self.model, self.moore, self.energy) |
48 | | - self.model.grid.place_agent(lamb, self.pos) |
| 45 | + if self.energy < 0: |
| 46 | + self.remove() |
| 47 | + elif self.random.random() < self.p_reproduce: |
| 48 | + self.spawn_offspring() |
49 | 49 |
|
50 | 50 |
|
51 | | -class Wolf(RandomWalker): |
52 | | - """ |
53 | | - A wolf that walks around, reproduces (asexually) and eats sheep. |
54 | | - """ |
| 51 | +class Sheep(Animal): |
| 52 | + """A sheep that walks around, reproduces (asexually) and gets eaten.""" |
55 | 53 |
|
56 | | - energy = None |
| 54 | + def feed(self): |
| 55 | + """If possible eat the food in the current location.""" |
| 56 | + # If there is grass available, eat it |
| 57 | + if self.model.grass: |
| 58 | + grass_patch = next( |
| 59 | + obj for obj in self.cell.agents if isinstance(obj, GrassPatch) |
| 60 | + ) |
| 61 | + if grass_patch.fully_grown: |
| 62 | + self.energy += self.energy_from_food |
| 63 | + grass_patch.fully_grown = False |
57 | 64 |
|
58 | | - def __init__(self, model, moore, energy=None): |
59 | | - super().__init__(model, moore=moore) |
60 | | - self.energy = energy |
61 | 65 |
|
62 | | - def step(self): |
63 | | - self.random_move() |
64 | | - self.energy -= 1 |
| 66 | +class Wolf(Animal): |
| 67 | + """A wolf that walks around, reproduces (asexually) and eats sheep.""" |
65 | 68 |
|
66 | | - # If there are sheep present, eat one |
67 | | - x, y = self.pos |
68 | | - this_cell = self.model.grid.get_cell_list_contents([self.pos]) |
69 | | - sheep = [obj for obj in this_cell if isinstance(obj, Sheep)] |
| 69 | + def feed(self): |
| 70 | + """If possible eat the food in the current location.""" |
| 71 | + sheep = [obj for obj in self.cell.agents if isinstance(obj, Sheep)] |
70 | 72 | if len(sheep) > 0: |
71 | 73 | sheep_to_eat = self.random.choice(sheep) |
72 | | - self.energy += self.model.wolf_gain_from_food |
| 74 | + self.energy += self.energy_from_food |
73 | 75 |
|
74 | 76 | # Kill the sheep |
75 | | - self.model.grid.remove_agent(sheep_to_eat) |
76 | 77 | sheep_to_eat.remove() |
77 | 78 |
|
78 | | - # Death or reproduction |
79 | | - if self.energy < 0: |
80 | | - self.model.grid.remove_agent(self) |
81 | | - self.remove() |
82 | | - else: |
83 | | - if self.random.random() < self.model.wolf_reproduce: |
84 | | - # Create a new wolf cub |
85 | | - self.energy /= 2 |
86 | | - cub = Wolf(self.model, self.moore, self.energy) |
87 | | - self.model.grid.place_agent(cub, self.pos) |
88 | | - |
89 | 79 |
|
90 | | -class GrassPatch(mesa.Agent): |
| 80 | +class GrassPatch(FixedAgent): |
91 | 81 | """ |
92 | 82 | A patch of grass that grows at a fixed rate and it is eaten by sheep |
93 | 83 | """ |
|
0 commit comments