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)
}
}