Add crosspoll_state table to persist per-island generation counters across evolver restarts. Load state on startup and save after each cross-pollination check. Add persistence pattern and translation structure tests. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
64 lines
1.7 KiB
Python
64 lines
1.7 KiB
Python
"""Grid utility functions for AI Code Battle.
|
|
|
|
Provides toroidal distance calculations, neighbor enumeration,
|
|
and BFS pathfinding on a wrapping grid.
|
|
"""
|
|
|
|
from collections import deque
|
|
|
|
|
|
def toroidal_manhattan(r1, c1, r2, c2, cols, rows):
|
|
"""Manhattan distance with wrap-around on a toroidal grid."""
|
|
dr = abs(r1 - r2)
|
|
dc = abs(c1 - c2)
|
|
dr = min(dr, rows - dr)
|
|
dc = min(dc, cols - dc)
|
|
return dr + dc
|
|
|
|
|
|
def toroidal_chebyshev(r1, c1, r2, c2, cols, rows):
|
|
"""Chebyshev distance with wrap-around on a toroidal grid."""
|
|
dr = abs(r1 - r2)
|
|
dc = abs(c1 - c2)
|
|
dr = min(dr, rows - dr)
|
|
dc = min(dc, cols - dc)
|
|
return max(dr, dc)
|
|
|
|
|
|
def neighbors(row, col, rows, cols):
|
|
"""Return 8-directional neighbors with wrap-around."""
|
|
offsets = [(-1, -1), (-1, 0), (-1, 1),
|
|
(0, -1), (0, 1),
|
|
(1, -1), (1, 0), (1, 1)]
|
|
return [((row + dr) % rows, (col + dc) % cols) for dr, dc in offsets]
|
|
|
|
|
|
def bfs(start, goal, passable, rows, cols):
|
|
"""BFS pathfinding on a toroidal grid.
|
|
|
|
Args:
|
|
start: (row, col) tuple
|
|
goal: (row, col) tuple
|
|
passable: callable(row, col) -> bool
|
|
rows, cols: grid dimensions
|
|
|
|
Returns:
|
|
List of (row, col) from start to goal (exclusive of start),
|
|
or None if no path exists.
|
|
"""
|
|
if start == goal:
|
|
return []
|
|
|
|
queue = deque([(start, [])])
|
|
visited = {start}
|
|
|
|
while queue:
|
|
(r, c), path = queue.popleft()
|
|
for nr, nc in neighbors(r, c, rows, cols):
|
|
if (nr, nc) == goal:
|
|
return path + [(nr, nc)]
|
|
if (nr, nc) not in visited and passable(nr, nc):
|
|
visited.add((nr, nc))
|
|
queue.append(((nr, nc), path + [(nr, nc)]))
|
|
|
|
return None
|