#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <chrono>
#include <queue>
#include <functional>
using namespace std;

#define INF 1e9

//????????????
class Timer {
	chrono::high_resolution_clock::time_point start, end;
	double limit;

public:
	Timer() {
		start = chrono::high_resolution_clock::now();
	}
	Timer(double l) {
		start = chrono::high_resolution_clock::now();
		limit = l;
	}

	double getTime() {
		end = chrono::high_resolution_clock::now();
		return chrono::duration<double>(end - start).count();
	}

	bool Over() {
		if (getTime() > limit) {
			return true;
		}
		return false;
	}

	void setLimit(double l) {
		limit = l;
	}
	void setStart() { start = chrono::high_resolution_clock::now(); }
};

struct POINT {
	int x, y;

	POINT() {}
	POINT(int x_, int y_) { x = x_, y = y_; }

	bool operator<(const POINT& r)const {
		return x + y < r.x + r.y;
	}

	POINT operator+(const POINT& r)const {
		return POINT(x + r.x, y + r.y);
	}
};

struct STATUS {
	int dist;

	int id;
	vector<bool>used;

	STATUS() {}
	STATUS(int dist_, int id_, vector<bool>used_) {
		dist = dist_;
		id = id_;
		used = used_;
	}

	bool operator>(const STATUS& r)const {
		return dist > r.dist;
	}
};

int W, H;
vector<vector<int>>MAP;
int status[20][20];
int cost[20][20];
void dijkstra(POINT p) {
	int v[] = { -1,0,1,0 };
	int h[] = { 0,1,0,-1 };

	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			status[i][j] = 0;
			cost[i][j] = INF;
		}
	}
	cost[p.x][p.y] = 0;
	status[p.x][p.y] = 1;

	priority_queue<pair<int, POINT>, vector<pair<int, POINT>>, greater<pair<int, POINT>>>U;
	U.push(make_pair(cost[p.x][p.y], p));
	while (!U.empty()) {
		//??¢?´¢???????????£??????????????§?????????????°???????
		POINT u = U.top().second; U.pop();

		if (status[u.x][u.y] == -1) continue;

		status[u.x][u.y] = -1;

		//?????????????°????????????¢???
		for (int i = 0; i < 4; i++) {
			POINT np = u + POINT(v[i], h[i]);
			if (np.x < 0 || np.x >= H || np.y < 0 || np.y >= W)continue;
			if (MAP[np.x][np.y] == 1)continue;
			if (status[np.x][np.y] != -1) {
				if (cost[np.x][np.y] > cost[u.x][u.y] + 1) {
					cost[np.x][np.y] = cost[u.x][u.y] + 1;
					status[np.x][np.y] = 1;
					U.push(make_pair(cost[np.x][np.y], np));
				}
			}
		}
	}
}

int main()
{
	while (1) {
		cin >> W >> H;

		if (W == 0 && H == 0)break;

		MAP.assign(H,vector<int>(W,0));

		vector<POINT>pos;
		int cnt = 0;

		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				char c; cin >> c;
				if (c == '*') {
					POINT p = POINT(i, j);
					pos.push_back(p);
					cnt++;
				}
				else if (c == 'x')MAP[i][j] = 1;
				else if (c == 'o') {
					POINT sp = POINT(i, j);
					pos.insert(pos.begin(), sp);
					cnt++;
				}
			}
		}

		bool fin = false;
		vector<vector<int>>dist(cnt);
		for (int i = 0; i < cnt; i++) {
			dist[i].resize(cnt);
			dijkstra(pos[i]);
			for (int j = 1; j < cnt; j++) {
				int distance = cost[pos[j].x][pos[j].y];
				if (distance == INF)fin = true;
				dist[i][j] = distance;
			}
		}

		if (fin) {
			cout << -1 << endl;
			continue;
		}

		Timer tmr(0.016);
		vector<priority_queue<STATUS, vector<STATUS>, greater<STATUS>>>STAT(cnt);
		STAT[0].push(STATUS(0,0,vector<bool>(cnt)));
		while (1) {
			if (tmr.Over())break;

			for (int i = 0; i < cnt - 1; i++) {
				if (STAT[i].empty())continue;

				STATUS st = STAT[i].top(); STAT[i].pop();

				for (int j = 1; j < cnt; j++) {
					if (st.used[j])continue;

					st.used[j] = true;
					STAT[i + 1].push(STATUS(st.dist + dist[st.id][j], j, st.used));
					st.used[j] = false;
				}
			}
		}

		STATUS last = STAT[cnt - 1].top();
		cout << last.dist << endl;
	}

    return 0;
}

Measured memory_bytes: 8988