amogus/tests/test_map.py

257 lines
9.2 KiB
Python

"""
Tests for the map/graph system.
"""
import unittest
import sys
import os
import tempfile
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.map.graph import GameMap, Room, Edge, Task, Vent
from src.engine.types import Position
class TestRoom(unittest.TestCase):
"""Tests for Room dataclass."""
def test_room_creation(self):
room = Room(id="test", name="Test Room")
self.assertEqual(room.id, "test")
self.assertEqual(room.name, "Test Room")
self.assertEqual(room.tasks, [])
self.assertIsNone(room.vent)
def test_room_with_tasks(self):
task = Task(id="task1", name="Do Thing", duration=5.0)
room = Room(id="test", name="Test Room", tasks=[task])
self.assertEqual(len(room.tasks), 1)
self.assertEqual(room.tasks[0].duration, 5.0)
def test_room_with_vent(self):
vent = Vent(id="vent1", connects_to=["vent2", "vent3"])
room = Room(id="test", name="Test Room", vent=vent)
self.assertIsNotNone(room.vent)
self.assertEqual(len(room.vent.connects_to), 2)
def test_room_with_center(self):
room = Room(id="test", name="Test Room", center=Position(x=100, y=200))
self.assertEqual(room.center.x, 100)
self.assertEqual(room.center.y, 200)
def test_room_contains_point(self):
room = Room(
id="test", name="Test Room",
center=Position(x=100, y=100),
bounds=(Position(x=0, y=0), Position(x=200, y=200))
)
self.assertTrue(room.contains_point(Position(x=100, y=100)))
self.assertTrue(room.contains_point(Position(x=50, y=50)))
self.assertFalse(room.contains_point(Position(x=300, y=100)))
class TestEdge(unittest.TestCase):
"""Tests for Edge dataclass."""
def test_edge_creation(self):
edge = Edge(id="e1", room_a="a", room_b="b")
self.assertEqual(edge.id, "e1")
self.assertEqual(edge.room_a, "a")
def test_edge_with_waypoints(self):
edge = Edge(
id="e1", room_a="a", room_b="b",
waypoints=[Position(x=0, y=0), Position(x=100, y=0)]
)
self.assertAlmostEqual(edge.distance, 100.0)
def test_edge_other_room(self):
edge = Edge(id="e1", room_a="a", room_b="b")
self.assertEqual(edge.other_room("a"), "b")
self.assertEqual(edge.other_room("b"), "a")
class TestGameMap(unittest.TestCase):
"""Tests for GameMap class."""
def setUp(self):
"""Create a simple test map."""
self.game_map = GameMap()
# Create rooms: A -- B -- C
# |
# D
self.game_map.add_room(Room(id="a", name="Room A", center=Position(x=0, y=0)))
self.game_map.add_room(Room(id="b", name="Room B", center=Position(x=100, y=0)))
self.game_map.add_room(Room(id="c", name="Room C", center=Position(x=200, y=0)))
self.game_map.add_room(Room(id="d", name="Room D", center=Position(x=100, y=100)))
# Create edges with waypoints
self.game_map.add_edge(Edge(
id="ab", room_a="a", room_b="b",
waypoints=[Position(x=0, y=0), Position(x=50, y=0), Position(x=100, y=0)]
))
self.game_map.add_edge(Edge(
id="bc", room_a="b", room_b="c",
waypoints=[Position(x=100, y=0), Position(x=200, y=0)]
))
self.game_map.add_edge(Edge(
id="bd", room_a="b", room_b="d",
waypoints=[Position(x=100, y=0), Position(x=100, y=100)]
))
def test_add_room(self):
self.assertEqual(len(self.game_map.rooms), 4)
self.assertIn("a", self.game_map.rooms)
def test_add_edge(self):
self.assertEqual(len(self.game_map.edges), 3)
self.assertIn("ab", self.game_map.edges)
def test_get_room(self):
room = self.game_map.get_room("a")
self.assertIsNotNone(room)
self.assertEqual(room.name, "Room A")
self.assertIsNone(self.game_map.get_room("nonexistent"))
def test_get_edge(self):
edge = self.game_map.get_edge("ab")
self.assertIsNotNone(edge)
self.assertAlmostEqual(edge.distance, 100.0)
def test_get_neighbors(self):
neighbors = self.game_map.get_neighbors("b")
self.assertEqual(len(neighbors), 3) # a, c, d
neighbor_rooms = [n[1] for n in neighbors]
self.assertIn("a", neighbor_rooms)
self.assertIn("c", neighbor_rooms)
self.assertIn("d", neighbor_rooms)
def test_find_edge(self):
edge = self.game_map.find_edge("a", "b")
self.assertIsNotNone(edge)
self.assertEqual(edge.id, "ab")
# Reverse direction
edge = self.game_map.find_edge("b", "a")
self.assertIsNotNone(edge)
# Non-adjacent
self.assertIsNone(self.game_map.find_edge("a", "c"))
def test_find_path_adjacent(self):
path = self.game_map.find_path("a", "b")
self.assertEqual(path, ["ab"])
def test_find_path_multi_hop(self):
path = self.game_map.find_path("a", "c")
self.assertEqual(path, ["ab", "bc"])
def test_find_path_same_room(self):
path = self.game_map.find_path("a", "a")
self.assertEqual(path, [])
def test_find_path_no_path(self):
# Add isolated room
self.game_map.add_room(Room(id="isolated", name="Isolated"))
path = self.game_map.find_path("a", "isolated")
self.assertIsNone(path)
class TestMapSerialization(unittest.TestCase):
"""Tests for map serialization."""
def test_to_dict(self):
game_map = GameMap()
game_map.add_room(Room(id="a", name="A", center=Position(x=0, y=0)))
game_map.add_room(Room(id="b", name="B", center=Position(x=100, y=0)))
game_map.add_edge(Edge(
id="ab", room_a="a", room_b="b",
waypoints=[Position(x=0, y=0), Position(x=100, y=0)]
))
data = game_map.to_dict()
self.assertEqual(len(data["rooms"]), 2)
self.assertEqual(len(data["edges"]), 1)
def test_save_and_load(self):
game_map = GameMap()
task = Task(id="t1", name="Task", duration=3.0, position=Position(x=50, y=50))
vent = Vent(id="v1", connects_to=["v2"], position=Position(x=60, y=60))
game_map.add_room(Room(
id="a", name="A",
center=Position(x=50, y=50),
bounds=(Position(x=0, y=0), Position(x=100, y=100)),
tasks=[task], vent=vent
))
game_map.add_room(Room(id="b", name="B", center=Position(x=200, y=50)))
game_map.add_edge(Edge(
id="ab", room_a="a", room_b="b",
waypoints=[Position(x=100, y=50), Position(x=200, y=50)]
))
with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f:
game_map.save(f.name)
loaded = GameMap.load(f.name)
self.assertEqual(len(loaded.rooms), 2)
self.assertEqual(len(loaded.edges), 1)
self.assertEqual(loaded.rooms["a"].tasks[0].duration, 3.0)
self.assertIsNotNone(loaded.rooms["a"].vent)
os.unlink(f.name)
class TestSkeldMap(unittest.TestCase):
"""Tests for the actual Skeld map."""
@classmethod
def setUpClass(cls):
map_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"data", "maps", "skeld.json"
)
cls.skeld = GameMap.load(map_path)
def test_skeld_has_all_rooms(self):
expected_rooms = [
"cafeteria", "weapons", "navigation", "o2", "admin",
"storage", "communications", "shields", "electrical",
"lower_engine", "security", "reactor", "upper_engine", "medbay"
]
for room_id in expected_rooms:
self.assertIn(room_id, self.skeld.rooms, f"Missing room: {room_id}")
def test_skeld_connectivity(self):
# Every room should be reachable from cafeteria
for room_id in self.skeld.rooms:
path = self.skeld.find_path("cafeteria", room_id)
self.assertIsNotNone(path, f"No path to {room_id}")
def test_skeld_has_vents(self):
vent_rooms = ["weapons", "navigation", "admin", "electrical",
"lower_engine", "security", "reactor", "upper_engine", "medbay", "shields"]
for room_id in vent_rooms:
room = self.skeld.get_room(room_id)
self.assertIsNotNone(room.vent, f"{room_id} should have a vent")
def test_vent_connectivity(self):
# Check medbay-security-electrical vent network
medbay = self.skeld.get_room("medbay")
self.assertIn("vent_security", medbay.vent.connects_to)
self.assertIn("vent_elec", medbay.vent.connects_to)
def test_skeld_has_walls(self):
"""Skeld should have wall geometry for raycasting."""
self.assertGreater(len(self.skeld.walls), 0)
def test_skeld_has_spawn_points(self):
"""Skeld should have spawn points."""
self.assertIn("cafeteria", self.skeld.spawn_points)
if __name__ == "__main__":
unittest.main()