Skip to content

Commit 6e93025

Browse files
committed
Move grass regrowth time to PropertyLayer
1 parent 0921b7c commit 6e93025

File tree

2 files changed

+38
-43
lines changed

2 files changed

+38
-43
lines changed

mesa/examples/advanced/wolf_sheep/agents.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,6 @@ def move(self):
7373
if len(cells_without_wolves) == 0:
7474
return
7575

76-
target_cells_not_walls = cells_without_wolves.select(
77-
lambda cell: not self.model.grid.wall.data[cell.coordinate[0]][
78-
cell.coordinate[1]
79-
]
80-
)
81-
82-
if len(target_cells_not_walls) == 0:
83-
return
84-
8576
# Among safe cells, prefer those with grown grass
8677
cells_with_grass = cells_without_wolves.select(
8778
lambda cell: any(
@@ -133,11 +124,15 @@ def fully_grown(self, value: bool) -> None:
133124
if not value: # If grass was just eaten
134125
self.model.simulator.schedule_event_relative(
135126
setattr,
136-
self.grass_regrowth_time,
127+
int(
128+
self.model.grid.grass_regrowth_time.data[self.cell.coordinate[0]][
129+
self.cell.coordinate[1]
130+
]
131+
),
137132
function_args=[self, "fully_grown", True],
138133
)
139134

140-
def __init__(self, model, countdown, grass_regrowth_time, cell):
135+
def __init__(self, model, countdown, cell):
141136
"""Create a new patch of grass.
142137
143138
Args:
@@ -148,7 +143,6 @@ def __init__(self, model, countdown, grass_regrowth_time, cell):
148143
"""
149144
super().__init__(model)
150145
self._fully_grown = countdown == 0
151-
self.grass_regrowth_time = grass_regrowth_time
152146
self.cell = cell
153147

154148
# Schedule initial growth if not fully grown

mesa/examples/advanced/wolf_sheep/model.py

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
"""
1111

1212
import math
13-
import random
1413

1514
import numpy as np
15+
from scipy.ndimage import gaussian_filter
1616

1717
from mesa import Model
1818
from mesa.datacollection import DataCollector
@@ -96,38 +96,32 @@ def __init__(
9696

9797
self.datacollector = DataCollector(model_reporters)
9898

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

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

108-
wall_arr = np.array(wall_arr)
105+
for _ in range(num_seeds):
106+
x, y = np.random.randint(0, rows), np.random.randint(0, cols)
107+
seeds[x, y] = np.random.randint(1, num_seeds)
109108

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

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

119-
def is_trapped_in_walls(row, col):
120-
return (
121-
is_wall(row + 1, col)
122-
and is_wall(row - 1, col)
123-
and is_wall(row, col + 1)
124-
and is_wall(row, col - 1)
125-
)
118+
return filtered_array
126119

127-
possible_cells = self.grid.all_cells.select(
128-
lambda cell: not wall_arr[cell.coordinate[0]][cell.coordinate[1]]
129-
and not is_trapped_in_walls(cell.coordinate[0], cell.coordinate[1])
130-
).cells # so we don't create an animal at wall cells. and make sure the animal is not trapped in walls
120+
grass_regrowth_time_array = generate_grass_regrowth_time_array()
121+
122+
self.grid.add_property_layer(
123+
PropertyLayer.from_data("grass_regrowth_time", grass_regrowth_time_array)
124+
)
131125

132126
# Create sheep:
133127
Sheep.create_agents(
@@ -136,7 +130,7 @@ def is_trapped_in_walls(row, col):
136130
energy=self.rng.random((initial_sheep,)) * 2 * sheep_gain_from_food,
137131
p_reproduce=sheep_reproduce,
138132
energy_from_food=sheep_gain_from_food,
139-
cell=self.random.choices(possible_cells, k=initial_sheep),
133+
cell=self.random.choices(self.grid.all_cells.cells, k=initial_sheep),
140134
)
141135
# Create Wolves:
142136
Wolf.create_agents(
@@ -145,7 +139,7 @@ def is_trapped_in_walls(row, col):
145139
energy=self.rng.random((initial_wolves,)) * 2 * wolf_gain_from_food,
146140
p_reproduce=wolf_reproduce,
147141
energy_from_food=wolf_gain_from_food,
148-
cell=self.random.choices(possible_cells, k=initial_wolves),
142+
cell=self.random.choices(self.grid.all_cells.cells, k=initial_wolves),
149143
)
150144

151145
# Create grass patches if enabled
@@ -154,9 +148,16 @@ def is_trapped_in_walls(row, col):
154148
for cell in self.grid:
155149
fully_grown = self.random.choice(possibly_fully_grown)
156150
countdown = (
157-
0 if fully_grown else self.random.randrange(0, grass_regrowth_time)
151+
0
152+
if fully_grown
153+
else self.random.randrange(
154+
0,
155+
grass_regrowth_time_array[cell.coordinate[0]][
156+
cell.coordinate[1]
157+
],
158+
)
158159
)
159-
GrassPatch(self, countdown, grass_regrowth_time, cell)
160+
GrassPatch(self, countdown, cell)
160161

161162
# Collect initial data
162163
self.running = True

0 commit comments

Comments
 (0)