diff --git a/mesa/space.py b/mesa/space.py index d9aa7fb6ea4..e464b8d1842 100644 --- a/mesa/space.py +++ b/mesa/space.py @@ -459,15 +459,21 @@ def move_agent_to_one_of( elif selection == "closest": current_pos = agent.pos # Find the closest position without sorting all positions - closest_pos = None + # TODO: See if this method can be optimized further + closest_pos = [] min_distance = float("inf") agent.random.shuffle(pos) for p in pos: distance = self._distance_squared(p, current_pos) if distance < min_distance: min_distance = distance - closest_pos = p - chosen_pos = closest_pos + closest_pos.clear() + closest_pos.append(p) + elif distance == min_distance: + closest_pos.append(p) + + chosen_pos = agent.random.choice(closest_pos) + else: raise ValueError( f"Invalid selection method {selection}. Choose 'random' or 'closest'." diff --git a/tests/test_space.py b/tests/test_space.py index 23cf8c95450..2da9ee2acb7 100644 --- a/tests/test_space.py +++ b/tests/test_space.py @@ -509,6 +509,23 @@ def test_move_agent_closest_selection(self): self.space.move_agent_to_one_of(agent, possible_positions, selection="closest") assert agent.pos == (6, 6) + def test_move_agent_closest_selection_multiple(self): + random_locations = [] + agent = self.agents[0] + agent.pos = (5, 5) + repetititions = 10 + + for _ in range(repetititions): + possible_positions = [(4, 4), (6, 6), (10, 10), (20, 20)] + self.space.move_agent_to_one_of( + agent, possible_positions, selection="closest" + ) + random_locations.append(agent.pos) + assert agent.pos in possible_positions + self.space.move_agent_to_one_of(agent, [(5, 5)], selection="closest") + non_random_locations = [random_locations[0]] * repetititions + assert random_locations != non_random_locations + def test_move_agent_invalid_selection(self): agent = self.agents[0] possible_positions = [(10, 10), (20, 20), (30, 30)]