From dfbdb1a679b729f843af6693b3dac45ef757e0b1 Mon Sep 17 00:00:00 2001 From: Ewout ter Hoeven Date: Wed, 13 Nov 2024 17:16:34 +0100 Subject: [PATCH] examples/wolf_sheep: Don't allow dump moves Agents now move completely random in WolfSheep. That makes no sense whatsoever, so this PR makes them move a little bit less dump. - Wolf moves to random cell with sheep on them, if available (otherwise completely random) - Sheep move to a random cell without a wolf (if available), and preferably with grass. This enables sheep to actually "search" for grass, wolfs to search for sheep and sheep to not move to a cell with wolves. More importantly, it shows of some nice selection mechanics with the cell space. --- mesa/examples/advanced/wolf_sheep/agents.py | 34 ++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/mesa/examples/advanced/wolf_sheep/agents.py b/mesa/examples/advanced/wolf_sheep/agents.py index e3f308aa479..c3837da7f6d 100644 --- a/mesa/examples/advanced/wolf_sheep/agents.py +++ b/mesa/examples/advanced/wolf_sheep/agents.py @@ -37,7 +37,8 @@ def feed(self): def step(self): """Execute one step of the animal's behavior.""" # Move to random neighboring cell - self.cell = self.cell.neighborhood.select_random_cell() + self.move() + self.energy -= 1 # Try to feed @@ -62,6 +63,27 @@ def feed(self): self.energy += self.energy_from_food grass_patch.fully_grown = False + def move(self): + """Move towards a cell where there isn't a wolf, and preferably with grown grass.""" + cells_without_wolves = self.cell.neighborhood.select( + lambda cell: not any(isinstance(obj, Wolf) for obj in cell.agents) + ) + # If all surrounding cells have wolves, stay put + if len(cells_without_wolves) == 0: + return + + # Among safe cells, prefer those with grown grass + cells_with_grass = cells_without_wolves.select( + lambda cell: any( + isinstance(obj, GrassPatch) and obj.fully_grown for obj in cell.agents + ) + ) + # Move to a cell with grass if available, otherwise move to any safe cell + target_cells = ( + cells_with_grass if len(cells_with_grass) > 0 else cells_without_wolves + ) + self.cell = target_cells.select_random_cell() + class Wolf(Animal): """A wolf that walks around, reproduces (asexually) and eats sheep.""" @@ -74,6 +96,16 @@ def feed(self): self.energy += self.energy_from_food sheep_to_eat.remove() + def move(self): + """Move to a neighboring cell, preferably one with sheep.""" + cells_with_sheep = self.cell.neighborhood.select( + lambda cell: any(isinstance(obj, Sheep) for obj in cell.agents) + ) + target_cells = ( + cells_with_sheep if len(cells_with_sheep) > 0 else self.cell.neighborhood + ) + self.cell = target_cells.select_random_cell() + class GrassPatch(FixedAgent): """A patch of grass that grows at a fixed rate and can be eaten by sheep."""