Skip to content

Commit

Permalink
Move grass regrowth time to PropertyLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
mgemaakbar committed Jan 12, 2025
1 parent 0921b7c commit 6e93025
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 43 deletions.
18 changes: 6 additions & 12 deletions mesa/examples/advanced/wolf_sheep/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,6 @@ def move(self):
if len(cells_without_wolves) == 0:
return

target_cells_not_walls = cells_without_wolves.select(
lambda cell: not self.model.grid.wall.data[cell.coordinate[0]][
cell.coordinate[1]
]
)

if len(target_cells_not_walls) == 0:
return

# Among safe cells, prefer those with grown grass
cells_with_grass = cells_without_wolves.select(
lambda cell: any(
Expand Down Expand Up @@ -133,11 +124,15 @@ def fully_grown(self, value: bool) -> None:
if not value: # If grass was just eaten
self.model.simulator.schedule_event_relative(
setattr,
self.grass_regrowth_time,
int(
self.model.grid.grass_regrowth_time.data[self.cell.coordinate[0]][
self.cell.coordinate[1]
]
),
function_args=[self, "fully_grown", True],
)

def __init__(self, model, countdown, grass_regrowth_time, cell):
def __init__(self, model, countdown, cell):
"""Create a new patch of grass.
Args:
Expand All @@ -148,7 +143,6 @@ def __init__(self, model, countdown, grass_regrowth_time, cell):
"""
super().__init__(model)
self._fully_grown = countdown == 0
self.grass_regrowth_time = grass_regrowth_time
self.cell = cell

# Schedule initial growth if not fully grown
Expand Down
63 changes: 32 additions & 31 deletions mesa/examples/advanced/wolf_sheep/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"""

import math
import random

import numpy as np
from scipy.ndimage import gaussian_filter

from mesa import Model
from mesa.datacollection import DataCollector
Expand Down Expand Up @@ -96,38 +96,32 @@ def __init__(

self.datacollector = DataCollector(model_reporters)

wall_arr = [[False] * self.width for i in range(self.height)]
def generate_grass_regrowth_time_array(): # Using Gaussian filter to make it look like spatial distribution
rows, cols = height, width

wall_coord = {
(random.randrange(self.height), random.randrange(self.width))
for i in range((width * height) // 10)
} # set is used because the random number gen might return the same coordinate
for i, j in wall_coord:
wall_arr[i][j] = True
seeds = np.zeros((rows, cols))
num_seeds = grass_regrowth_time

wall_arr = np.array(wall_arr)
for _ in range(num_seeds):
x, y = np.random.randint(0, rows), np.random.randint(0, cols)
seeds[x, y] = np.random.randint(1, num_seeds)

self.grid.add_property_layer(PropertyLayer.from_data("wall", wall_arr))
# Smooth the array to create clustered patterns using SciPy's Gaussian filter
filtered_array = gaussian_filter(seeds, sigma=10)

def is_wall(row, col):
return (
True
if row < 0 or col < 0 or row >= height or col >= width # corner case
else wall_arr[row][col]
)
# Normalize the array to the range [1, num_seeds]
filtered_array = (filtered_array - np.min(filtered_array)) / (
np.max(filtered_array) - np.min(filtered_array)
) * (num_seeds - 1) + 1
filtered_array = filtered_array.astype(int)

def is_trapped_in_walls(row, col):
return (
is_wall(row + 1, col)
and is_wall(row - 1, col)
and is_wall(row, col + 1)
and is_wall(row, col - 1)
)
return filtered_array

possible_cells = self.grid.all_cells.select(
lambda cell: not wall_arr[cell.coordinate[0]][cell.coordinate[1]]
and not is_trapped_in_walls(cell.coordinate[0], cell.coordinate[1])
).cells # so we don't create an animal at wall cells. and make sure the animal is not trapped in walls
grass_regrowth_time_array = generate_grass_regrowth_time_array()

self.grid.add_property_layer(
PropertyLayer.from_data("grass_regrowth_time", grass_regrowth_time_array)
)

# Create sheep:
Sheep.create_agents(
Expand All @@ -136,7 +130,7 @@ def is_trapped_in_walls(row, col):
energy=self.rng.random((initial_sheep,)) * 2 * sheep_gain_from_food,
p_reproduce=sheep_reproduce,
energy_from_food=sheep_gain_from_food,
cell=self.random.choices(possible_cells, k=initial_sheep),
cell=self.random.choices(self.grid.all_cells.cells, k=initial_sheep),
)
# Create Wolves:
Wolf.create_agents(
Expand All @@ -145,7 +139,7 @@ def is_trapped_in_walls(row, col):
energy=self.rng.random((initial_wolves,)) * 2 * wolf_gain_from_food,
p_reproduce=wolf_reproduce,
energy_from_food=wolf_gain_from_food,
cell=self.random.choices(possible_cells, k=initial_wolves),
cell=self.random.choices(self.grid.all_cells.cells, k=initial_wolves),
)

# Create grass patches if enabled
Expand All @@ -154,9 +148,16 @@ def is_trapped_in_walls(row, col):
for cell in self.grid:
fully_grown = self.random.choice(possibly_fully_grown)
countdown = (
0 if fully_grown else self.random.randrange(0, grass_regrowth_time)
0
if fully_grown
else self.random.randrange(
0,
grass_regrowth_time_array[cell.coordinate[0]][
cell.coordinate[1]
],
)
)
GrassPatch(self, countdown, grass_regrowth_time, cell)
GrassPatch(self, countdown, cell)

# Collect initial data
self.running = True
Expand Down

0 comments on commit 6e93025

Please sign in to comment.