1010"""
1111
1212import math
13- import random
1413
1514import numpy as np
15+ from scipy .ndimage import gaussian_filter
1616
1717from mesa import Model
1818from 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