package main import ( "reflect" "testing" ) func TestWalkableTiles_coversAllRooms(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) if len(walk) != 54 { t.Fatalf("expected 54 walkable tiles, got %d", len(walk)) } // Spot-check one tile from each room checks := [][2]int{ {4, 10}, // Pilot center {7, 7}, // Weapons {7, 10}, // Shields {7, 13}, // MedBay {11, 10}, // Engines center } for _, tc := range checks { if !walk[tc] { t.Errorf("expected tile %v to be walkable", tc) } } // Off-ship tile must be absent if walk[[2]int{0, 0}] { t.Error("tile (0,0) must not be walkable") } } func TestWalkableTiles_ignoresOutside(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) if walk[[2]int{0, 0}] { t.Error("tile (0,0) must not be walkable") } if walk[[2]int{20, 20}] { t.Error("tile (20,20) must not be walkable") } } func TestCellSet_returnsAllCells(t *testing.T) { s := NewPlayerShip() cells := cellSet(s) if len(cells) != 10 { t.Fatalf("expected 10 cells (2 per room × 5 rooms), got %d", len(cells)) } expected := [][2]int{ {4, 10}, {5, 10}, {7, 7}, {8, 7}, {7, 10}, {8, 10}, {7, 13}, {8, 13}, {11, 10}, {12, 10}, } for _, c := range expected { if !cells[c] { t.Errorf("expected cell %v to be present", c) } } } func TestCellSet_allWalkable(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) cells := cellSet(s) for c := range cells { if !walk[c] { t.Errorf("cell %v is not walkable", c) } } } func TestCellSet_startingCrewOnCells(t *testing.T) { s := NewPlayerShip() cells := cellSet(s) crew := NewStartingCrew() for _, c := range crew { pos := [2]int{c.TileX, c.TileY} if !cells[pos] { t.Errorf("crew %s at %v is not on a cell", c.Name, pos) } } } func TestBFSPath_sameTile(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) path := bfsPath(walk, [2]int{4, 10}, [2]int{4, 10}) if len(path) != 0 { t.Errorf("expected empty path for same-tile, got %v", path) } } func TestBFSPath_adjacentTile(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) path := bfsPath(walk, [2]int{4, 10}, [2]int{5, 10}) if len(path) != 1 { t.Fatalf("expected path of length 1, got %d: %v", len(path), path) } if path[0] != ([2]int{5, 10}) { t.Errorf("expected path[0] == {5,10}, got %v", path[0]) } } func TestBFSPath_unreachable(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) path := bfsPath(walk, [2]int{4, 10}, [2]int{0, 0}) if len(path) != 0 { t.Errorf("expected empty path for unreachable target, got %v", path) } } func TestBFSPath_throughShields(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) from := [2]int{4, 10} to := [2]int{11, 10} path := bfsPath(walk, from, to) if len(path) != 7 { t.Fatalf("expected path length 7, got %d: %v", len(path), path) } if path[len(path)-1] != to { t.Errorf("expected last tile %v, got %v", to, path[len(path)-1]) } for _, tile := range path { if !walk[tile] { t.Errorf("path contains non-walkable tile %v", tile) } } } func TestBFSPath_deterministic(t *testing.T) { s := NewPlayerShip() walk := walkableTiles(s) from := [2]int{4, 10} to := [2]int{11, 10} p1 := bfsPath(walk, from, to) p2 := bfsPath(walk, from, to) if !reflect.DeepEqual(p1, p2) { t.Errorf("non-deterministic: first=%v second=%v", p1, p2) } }