Skip to content

Commit ff611c9

Browse files
committed
add some agents
1 parent eaf7457 commit ff611c9

File tree

6 files changed

+69
-40
lines changed

6 files changed

+69
-40
lines changed

mesa/experimental/cell_space/cell.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from mesa.experimental.cell_space.cell_collection import CellCollection
88

99
if TYPE_CHECKING:
10-
from mesa.experimental.cell_space.cell_agent import CellAgent
10+
from mesa.experimental.cell_space.cell_agent import CellHolder
1111

1212

1313
class Cell:
@@ -80,7 +80,7 @@ def disconnect(self, other: Cell) -> None:
8080
"""
8181
self._connections.remove(other)
8282

83-
def add_agent(self, agent: CellAgent) -> None:
83+
def add_agent(self, agent: CellHolder) -> None:
8484
"""Adds an agent to the cell.
8585
8686
Args:
@@ -96,7 +96,7 @@ def add_agent(self, agent: CellAgent) -> None:
9696

9797
self.agents.append(agent)
9898

99-
def remove_agent(self, agent: CellAgent) -> None:
99+
def remove_agent(self, agent: CellHolder) -> None:
100100
"""Removes an agent from the cell.
101101
102102
Args:
Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,59 @@
11
from __future__ import annotations
22

3-
from typing import TYPE_CHECKING
3+
from typing import TYPE_CHECKING, Protocol, runtime_checkable
44

5-
from mesa import Agent, Model
5+
from mesa.experimental.cell_space.discrete_space import DiscreteSpace
66

77
if TYPE_CHECKING:
8-
from mesa.experimental.cell_space.cell import Cell
8+
from mesa.experimental.cell_space import Cell, Grid
99

1010

11-
class CellAgent(Agent):
12-
"""Cell Agent is an extension of the Agent class and adds behavior for moving in discrete spaces
11+
@runtime_checkable
12+
class CellHolder(Protocol):
13+
cell: Cell | None
1314

1415

15-
Attributes:
16-
unique_id (int): A unique identifier for this agent.
17-
model (Model): The model instance to which the agent belongs
18-
pos: (Position | None): The position of the agent in the space
19-
cell: (Cell | None): the cell which the agent occupies
20-
"""
16+
class CellAgent:
17+
cell: Cell | None
18+
space: DiscreteSpace[Cell]
19+
"""Cell Agent is an extension of the Agent class and adds behavior for moving in discrete spaces"""
2120

22-
def __init__(self, model: Model) -> None:
23-
"""
24-
Create a new agent.
25-
26-
Args:
27-
unique_id (int): A unique identifier for this agent.
28-
model (Model): The model instance in which the agent exists.
29-
"""
30-
super().__init__(model)
31-
self.cell: Cell | None = None
32-
33-
def move_to(self, cell) -> None:
21+
def move_to(self: CellHolder, cell: Cell) -> None:
3422
if self.cell is not None:
3523
self.cell.remove_agent(self)
3624
self.cell = cell
3725
cell.add_agent(self)
26+
27+
def move_relative(self, directions: tuple[int, ...], distance: int = 1):
28+
new_position = tuple(
29+
self.cell.coordinate[i] + directions[i] * distance
30+
for i in range(len(directions))
31+
if self.cell
32+
)
33+
new_cell = self.space[new_position]
34+
self.move_to(new_cell)
35+
36+
37+
class Grid2DMovingAgent(CellAgent):
38+
grid: Grid[Cell]
39+
40+
def move(self, direction: str, distance: int = 1):
41+
match direction:
42+
case "N" | "North" | "Up":
43+
self.move_relative((-1, 0), distance)
44+
case "S" | "South" | "Down":
45+
self.move_relative((1, 0), distance)
46+
case "E" | "East" | "Right":
47+
self.move_relative((0, 1), distance)
48+
case "W" | "West" | "Left":
49+
self.move_relative((0, -1), distance)
50+
case "NE" | "NorthEast" | "UpRight":
51+
self.move_relative((-1, 1), distance)
52+
case "NW" | "NorthWest" | "UpLeft":
53+
self.move_relative((-1, -1), distance)
54+
case "SE" | "SouthEast" | "DownRight":
55+
self.move_relative((1, 1), distance)
56+
case "SW" | "SouthWest" | "DownLeft":
57+
self.move_relative((1, -1), distance)
58+
case _:
59+
raise ValueError(f"Invalid direction: {direction}")

mesa/experimental/cell_space/discrete_space.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def __init__(
4343
def cutoff_empties(self):
4444
return 7.953 * len(self._cells) ** 0.384
4545

46-
def _connect_single_cell(self, cell: T): ...
46+
def _connect_single_cell(self, cell: T):
47+
...
4748

4849
@cached_property
4950
def all_cells(self):
@@ -56,7 +57,7 @@ def __getitem__(self, key):
5657
return self._cells[key]
5758

5859
@property
59-
def empties(self) -> CellCollection:
60+
def empties(self) -> CellCollection[T]:
6061
return self.all_cells.select(lambda cell: cell.is_empty)
6162

6263
def select_random_empty_cell(self) -> T:

mesa/experimental/cell_space/grid.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
T = TypeVar("T", bound=Cell)
1111

1212

13-
class Grid(DiscreteSpace, Generic[T]):
13+
class Grid(DiscreteSpace[T], Generic[T]):
1414
"""Base class for all grid classes
1515
1616
Attributes:
@@ -51,9 +51,11 @@ def _connect_cells(self) -> None:
5151
else:
5252
self._connect_cells_nd()
5353

54-
def _connect_cells_2d(self) -> None: ...
54+
def _connect_cells_2d(self) -> None:
55+
...
5556

56-
def _connect_cells_nd(self) -> None: ...
57+
def _connect_cells_nd(self) -> None:
58+
...
5759

5860
def _validate_parameters(self):
5961
if not all(isinstance(dim, int) and dim > 0 for dim in self.dimensions):

mesa/visualization/__init__.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
from .components.altair import make_space_altair
22
from .components.matplotlib import make_plot_measure, make_space_matplotlib
3-
from .solara_viz import JupyterViz, SolaraViz, make_text
3+
from .solara_viz import JupyterViz, SolaraViz
44
from .UserParam import Slider
55

66
__all__ = [
77
"JupyterViz",
88
"SolaraViz",
9-
"make_text",
109
"Slider",
1110
"make_space_altair",
1211
"make_space_matplotlib",

tests/test_cell_space.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44

55
from mesa import Model
6+
from mesa.agent import Agent
67
from mesa.experimental.cell_space import (
78
Cell,
89
CellAgent,
@@ -15,6 +16,10 @@
1516
)
1617

1718

19+
class TestAgent(Agent, CellAgent):
20+
pass
21+
22+
1823
def test_orthogonal_grid_neumann():
1924
width = 10
2025
height = 10
@@ -408,7 +413,7 @@ def test_empties_space():
408413

409414
model = Model()
410415
for i in range(8):
411-
grid._cells[i].add_agent(CellAgent(model))
416+
grid._cells[i].add_agent(TestAgent(model))
412417

413418
cell = grid.select_random_empty_cell()
414419
assert cell.coordinate in {8, 9}
@@ -432,7 +437,7 @@ def test_cell():
432437

433438
# add_agent
434439
model = Model()
435-
agent = CellAgent(model)
440+
agent = TestAgent(model)
436441

437442
cell1.add_agent(agent)
438443
assert agent in cell1.agents
@@ -445,11 +450,11 @@ def test_cell():
445450
cell1.remove_agent(agent)
446451

447452
cell1 = Cell((1,), capacity=1, random=random.Random())
448-
cell1.add_agent(CellAgent(model))
453+
cell1.add_agent(TestAgent(model))
449454
assert cell1.is_full
450455

451456
with pytest.raises(Exception):
452-
cell1.add_agent(CellAgent(model))
457+
cell1.add_agent(TestAgent(model))
453458

454459

455460
def test_cell_collection():
@@ -475,9 +480,9 @@ def test_cell_collection():
475480

476481
cells = collection.cells
477482
model = Model()
478-
cells[0].add_agent(CellAgent(model))
479-
cells[3].add_agent(CellAgent(model))
480-
cells[7].add_agent(CellAgent(model))
483+
cells[0].add_agent(TestAgent(model))
484+
cells[3].add_agent(TestAgent(model))
485+
cells[7].add_agent(TestAgent(model))
481486
agents = collection.agents
482487
assert len(list(agents)) == 3
483488

0 commit comments

Comments
 (0)