Repository: projectmesa/mesa

Issue:
Bug in visualization of hexgrids
**Describe the bug**
The visualization of hexgrids seems wrong. Below, you see a simple hex grid. The central agent is shown in blue, while its neighbors are shown in orange. This visual suggests three neighbors are in the third row and only one in the bottom row. 

![Image](https://github.com/user-attachments/assets/49ca079e-f4e1-4d14-b831-380e15ecbba4)

**Expected behavior**
The visualization should show the correct neighbors 

**cause and fix**
The cause of the bug is a misalignment between the visualization and how the hexgrid is wired up. `HexGrid. _connect_cells_2d ` used (row, column) notation for its neighbors, while the visualization code treats this as (x, y) coordinates, effectively transposing the grid. 

To fix this, we have to decide on which notation to use. If we want to stick with (row, col), we need to change the visualization (as well as a bunch of other things, such as the width and height properties). The simpler solution is thus to change `HexGrid. _connect_cells_2d` to use (x,y) notation for calculating the indices of neighbors.



for more background on this kind of problem, you can check https://www.redblobgames.com/grids/hexagons/ 




Discussion:

Patch:
diff --git a/mesa/experimental/cell_space/grid.py b/mesa/experimental/cell_space/grid.py
index 5e2b993e847..6078a038401 100644
--- a/mesa/experimental/cell_space/grid.py
+++ b/mesa/experimental/cell_space/grid.py
@@ -273,20 +273,20 @@ class HexGrid(Grid[T]):
     def _connect_cells_2d(self) -> None:
         # fmt: off
         even_offsets = [
-                        (-1, -1), (-1, 0),
-                    ( 0, -1),        ( 0, 1),
-                        ( 1, -1), ( 1, 0),
+                        (-1, -1), (0, -1),
+                    ( -1, 0),        ( 1, 0),
+                        ( -1, 1), (0, 1),
                 ]
         odd_offsets = [
-                        (-1, 0), (-1, 1),
-                    ( 0, -1),       ( 0, 1),
-                        ( 1, 0), ( 1, 1),
+                        (0, -1), (1, -1),
+                    ( -1, 0),       ( 1, 0),
+                        ( 0, 1), ( 1, 1),
                 ]
         # fmt: on
 
         for cell in self.all_cells:
-            i = cell.coordinate[0]
-            offsets = even_offsets if i % 2 == 0 else odd_offsets
+            i = cell.coordinate[1]
+            offsets = even_offsets if i % 2 else odd_offsets
             self._connect_single_cell_2d(cell, offsets=offsets)
 
     def _connect_cells_nd(self) -> None:


Test patch:
diff --git a/tests/test_cell_space.py b/tests/test_cell_space.py
index 53fb737d5a7..7f4dd820b65 100644
--- a/tests/test_cell_space.py
+++ b/tests/test_cell_space.py
@@ -354,7 +354,7 @@ def test_cell_neighborhood():
     grid = HexGrid(
         (width, height), torus=False, capacity=None, random=random.Random(42)
     )
-    for radius, n in zip(range(1, 4), [2, 6, 11]):
+    for radius, n in zip(range(1, 4), [3, 7, 13]):
         if radius == 1:
             neighborhood = grid._cells[(0, 0)].neighborhood
         else:
@@ -366,7 +366,7 @@ def test_cell_neighborhood():
     grid = HexGrid(
         (width, height), torus=False, capacity=None, random=random.Random(42)
     )
-    for radius, n in zip(range(1, 4), [5, 10, 17]):
+    for radius, n in zip(range(1, 4), [4, 10, 17]):
         if radius == 1:
             neighborhood = grid._cells[(1, 0)].neighborhood
         else:
@@ -385,25 +385,25 @@ def test_hexgrid():
     assert len(grid._cells) == width * height
 
     # first row
-    assert len(grid._cells[(0, 0)].connections.values()) == 2
+    assert len(grid._cells[(0, 0)].connections.values()) == 3
     for connection in grid._cells[(0, 0)].connections.values():
-        assert connection.coordinate in {(0, 1), (1, 0)}
+        assert connection.coordinate in {(0, 1), (1, 0), (1, 1)}
 
     # second row
-    assert len(grid._cells[(1, 0)].connections.values()) == 5
+    assert len(grid._cells[(1, 0)].connections.values()) == 4
     for connection in grid._cells[(1, 0)].connections.values():
         # fmt: off
-        assert connection.coordinate in {(0, 0), (0, 1),
-                                         (1, 1),
-                                         (2, 0), (2, 1)}
+        assert connection.coordinate in {   (1, 1), (2, 1),
+                                         (0, 0),    (2, 0),}
+        # fmt: on
 
     # middle odd row
     assert len(grid._cells[(5, 5)].connections.values()) == 6
     for connection in grid._cells[(5, 5)].connections.values():
         # fmt: off
-        assert connection.coordinate in {(4, 5), (4, 6),
-                                         (5, 4), (5, 6),
-                                         (6, 5), (6, 6)}
+        assert connection.coordinate in {  (4, 4), (5, 4),
+                                         (4, 5), (6, 5),
+                                         (4, 6), (5, 6)}
 
         # fmt: on
 
@@ -411,9 +411,9 @@ def test_hexgrid():
     assert len(grid._cells[(4, 4)].connections.values()) == 6
     for connection in grid._cells[(4, 4)].connections.values():
         # fmt: off
-        assert connection.coordinate in {(3, 3), (3, 4),
-                                         (4, 3), (4, 5),
-                                         (5, 3), (5, 4)}
+        assert connection.coordinate in {(4, 3), (5, 3),
+                                         (3, 4), (5, 4),
+                                         (4, 5), (5, 5)}
 
         # fmt: on
 
@@ -424,9 +424,9 @@ def test_hexgrid():
     assert len(grid._cells[(0, 0)].connections.values()) == 6
     for connection in grid._cells[(0, 0)].connections.values():
         # fmt: off
-        assert connection.coordinate in {(9, 9), (9, 0),
-                                         (0, 9), (0, 1),
-                                         (1, 9), (1, 0)}
+        assert connection.coordinate in {(0, 9), (1, 9),
+                                         (9, 0), (1, 0),
+                                         (0, 1), (1, 1)}
 
         # fmt: on